diff --git a/.brazil.json b/.brazil.json index f5e231e1727f..39d2435c1011 100644 --- a/.brazil.json +++ b/.brazil.json @@ -246,7 +246,7 @@ "module-path-tests": { "skipImport": true }, - "old-client-version-compatibility-test": { + "service-client-backward-compat-test": { "skipImport": true }, "protocol-tests": { @@ -318,6 +318,9 @@ "s3-tests": { "skipImport": true }, + "warmup-tests": { + "skipImport": true + }, "dynamodb-mapper": { "skipImport": true } diff --git a/.changes/2.47.0.json b/.changes/2.47.x/2.47.0.json similarity index 100% rename from .changes/2.47.0.json rename to .changes/2.47.x/2.47.0.json diff --git a/.changes/2.47.1.json b/.changes/2.47.x/2.47.1.json similarity index 100% rename from .changes/2.47.1.json rename to .changes/2.47.x/2.47.1.json diff --git a/.changes/2.47.2.json b/.changes/2.47.x/2.47.2.json similarity index 100% rename from .changes/2.47.2.json rename to .changes/2.47.x/2.47.2.json diff --git a/.changes/2.47.3.json b/.changes/2.47.x/2.47.3.json similarity index 100% rename from .changes/2.47.3.json rename to .changes/2.47.x/2.47.3.json diff --git a/.changes/2.47.4.json b/.changes/2.47.x/2.47.4.json similarity index 100% rename from .changes/2.47.4.json rename to .changes/2.47.x/2.47.4.json diff --git a/.changes/2.47.x/2.47.5.json b/.changes/2.47.x/2.47.5.json new file mode 100644 index 000000000000..4755e78b28ce --- /dev/null +++ b/.changes/2.47.x/2.47.5.json @@ -0,0 +1,60 @@ +{ + "version": "2.47.5", + "date": "2026-07-10", + "entries": [ + { + "type": "feature", + "category": "AWS License Manager", + "contributor": "", + "description": "Added the ResetUsage field to the CreateLicenseVersion API. When set to true, the entitlement usage counts for the license are reset to 0. If it is false or not specified, entitlement usage is left unchanged." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Provides CreateKnowledgeBase and UpdateKnowledgeBase APIs" + }, + { + "type": "feature", + "category": "Amazon CloudWatch", + "contributor": "", + "description": "CloudWatch now assigns a unique identifier to each anomaly detector. PutAnomalyDetector and DescribeAnomalyDetectors return this AnomalyDetectorId, which you can use to describe or delete a specific anomaly detector directly." + }, + { + "type": "feature", + "category": "Apache HTTP Client 5", + "contributor": "", + "description": "Upgrade httpcomponents.client5 to 5.6.2 to address CVE-2026-54428" + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Release support for g4d, c6g, c7g, c8g instance types for SageMaker HyperPod" + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "New Amazon EC2 instances. M9g, M9gd, C9g, and C9gd on AWS Graviton5. C8in, M8in, and R8in add 600 Gbps network. C8ib, M8ib, and R8ib add 300 Gbps EBS. C8ine, M8ine, M8idn, R8idn, M8idb, and R8idb round out Intel Xeon 6. Mac-m3ultra with Apple M3 Ultra. G7 with NVIDIA RTX PRO 4500 Blackwell GPUs." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "Added TelemetryConfig support for Managed Instances Capacity Provider, enabling customers to configure system log level and custom log group for managed instance logging." + }, + { + "type": "feature", + "category": "Inspector2", + "contributor": "", + "description": "Support for 3 day and 7 day ECR re-scan durations" + }, + { + "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/2.47.x/2.47.6.json b/.changes/2.47.x/2.47.6.json new file mode 100644 index 000000000000..994fd21ae4c6 --- /dev/null +++ b/.changes/2.47.x/2.47.6.json @@ -0,0 +1,48 @@ +{ + "version": "2.47.6", + "date": "2026-07-13", + "entries": [ + { + "type": "feature", + "category": "Amazon Elasticsearch Service", + "contributor": "", + "description": "Adds support for the EngineMode and UseCase parameters on Amazon Elasticsearch Service domains, enabling GENERAL or OPTIMIZED engine modes and SEARCH, VECTOR, OBSERVABILITY, or MIXED usecases when creating and updating domain configurations." + }, + { + "type": "feature", + "category": "AWS Common Runtime HTTP Client", + "contributor": "", + "description": "Added tlsNegotiationTimeout(Duration) configuration to AwsCrtAsyncHttpClient and AwsCrtHttpClient builders, mirroring the option on the Netty client. Configures the maximum amount of time a TLS handshake may take, from CLIENT HELLO through key exchange. Defaults to 10 seconds, matching the underlying CRT runtime's native default." + }, + { + "type": "feature", + "category": "Redshift Serverless", + "contributor": "", + "description": "Add support for preserving datasharing, zero-ETL and S3 event integrations on snapshot restore to serverless namespace." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "Add Java 8, 11 and 17 on AL2023 (java8.al2023, java11.al2023, java17.al2023) support to AWS Lambda." + }, + { + "type": "feature", + "category": "Amazon GameLift", + "contributor": "", + "description": "Amazon GameLift Servers now includes fleet expiration for managed fleets. A managed fleet expires one year after creation, transitioning to EXPIRED status, emitting a FLEET EXPIRED event, and scaling to zero instances. Expired fleets cannot host new game sessions or increase capacity." + }, + { + "type": "feature", + "category": "Amazon GuardDuty", + "contributor": "", + "description": "GuardDuty AI Protection is now publicly available. Findings include Bedrock guardrail details, model details, observation numbers, and continuous scan details. GuardrailArn and GuardrailVersion are deprecated in favor of the guardrails list." + }, + { + "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/2.48.x/2.48.0.json b/.changes/2.48.x/2.48.0.json new file mode 100644 index 000000000000..8a8811fb941c --- /dev/null +++ b/.changes/2.48.x/2.48.0.json @@ -0,0 +1,66 @@ +{ + "version": "2.48.0", + "date": "2026-07-14", + "entries": [ + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "This release adds SearchRules API which can be used to search for rules within an Amazon Connect instance." + }, + { + "type": "feature", + "category": "AWS Cloud Map", + "contributor": "", + "description": "Fixed Cloud Map endpoint resolution to correctly route to the dualstack endpoint when dualstack is enabled." + }, + { + "type": "feature", + "category": "Amazon Simple Systems Manager (SSM)", + "contributor": "", + "description": "Update AWS Systems Manager Automation Targets to be correct max value." + }, + { + "type": "feature", + "category": "Amazon EMR Containers", + "contributor": "", + "description": "Introduced 5 new fields across 3 APIs as part of Spark Connect server launch for EMR on EKS. The fields added are sessionIdleTimeoutInMinutes, sessionEnabled, endpointToken, authProxyUrl and encryptionKeyArn." + }, + { + "type": "feature", + "category": "AmazonMQ", + "contributor": "", + "description": "This release adds storage size parameter for Amazon MQ for RabbitMQ cluster deployment broker on engine version RabbitMQ 4.2. You can now set a configurable storage size within a range of sizes dependent on broker instance size." + }, + { + "type": "feature", + "category": "Elastic Disaster Recovery Service", + "contributor": "", + "description": "Fast recovery of EC2 based drs workloads by skipping the conversion step" + }, + { + "type": "bugfix", + "category": "Amazon S3", + "contributor": "", + "description": "Fix bug where S3 PutObject would hang indefinitely when using AwsCrtAsyncHttpClient with chunkedEncodingEnabled(false)" + }, + { + "type": "feature", + "category": "AWS SecurityHub", + "contributor": "", + "description": "AWS Security Hub now provides an AI inventory, giving central security teams a continuously updated, organization-wide view of AI assets and their security posture" + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "AWS Lambda now returns a new DependencyError value in StateReasonCode and LastUpdateStatusReasonCode to provide more actionable information when a function reaches a failed state due to an error from an upstream dependency or service." + }, + { + "type": "feature", + "category": "Amazon S3", + "contributor": "", + "description": "Add presigned URL download support to S3AsyncClient and S3 Transfer Manager. Customers can now download S3 objects using pre-signed URLs through the SDK's async client pipeline without needing AWS credentials configured." + } + ] +} \ No newline at end of file diff --git a/.changes/2.48.x/2.48.1.json b/.changes/2.48.x/2.48.1.json new file mode 100644 index 000000000000..940ad6cc7b4a --- /dev/null +++ b/.changes/2.48.x/2.48.1.json @@ -0,0 +1,48 @@ +{ + "version": "2.48.1", + "date": "2026-07-15", + "entries": [ + { + "type": "feature", + "category": "Elastic Load Balancing", + "contributor": "", + "description": "This release adds support for the IpAddressType field on SourceIpConfig, enabling Network Load Balancer listener rules to match traffic based on whether the source IP is IPv4 or IPv6." + }, + { + "type": "feature", + "category": "S3 Event Notification", + "contributor": "", + "description": "Added `awsGeneratedTags` field to `S3Bucket` in the S3 Event Notifications module. Amazon S3 emits AWS-generated system tags on the `bucket` portion of event notifications when system tags are enabled on the source bucket. SDK consumers on the SNS/SQS/Lambda delivery paths can now access these tags via `S3Bucket#getAwsGeneratedTags()`." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "jtuglu1", + "description": "Fixed an issue where `ContainerCredentialsProvider` rejected the EKS Pod Identity IPv6 endpoint unless `AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE` was set to `IPv6`." + }, + { + "type": "feature", + "category": "Amazon HealthLake", + "contributor": "", + "description": "AWS HealthLake now offers data transformation in Preview to convert CSV and C-CDA data to FHIR R4. Customers can maintain reusable mapping profiles, run sync or async jobs with provenance tracking and drift detection, and use an AI agent to build and edit mapping logic from natural language." + }, + { + "type": "feature", + "category": "Amazon Relational Database Service", + "contributor": "", + "description": "Adds support for modifying EngineLifecycleSupport on DB instances and DB clusters through ModifyDBInstance and ModifyDBCluster." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Fix HarnessEndpointArn pattern to match the actual service-emitted ARN format ('harness-endpoint' instead of 'endpoint'). Add additionalParams to Gemini model configuration for passing provider-specific parameters through to the model unchanged." + }, + { + "type": "feature", + "category": "Payment Cryptography Data Plane", + "contributor": "", + "description": "Adds support for UnionPay session key derivation to the GenerateAuthRequestCryptogram, VerifyAuthRequestCryptogram, GenerateMac, and VerifyMac APIs." + } + ] +} \ No newline at end of file diff --git a/.changes/2.48.x/2.48.2.json b/.changes/2.48.x/2.48.2.json new file mode 100644 index 000000000000..67bbac9693e5 --- /dev/null +++ b/.changes/2.48.x/2.48.2.json @@ -0,0 +1,54 @@ +{ + "version": "2.48.2", + "date": "2026-07-16", + "entries": [ + { + "type": "feature", + "category": "AWS Sustainability", + "contributor": "", + "description": "Adds support for retrieving estimated water allocation data." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Release support for g7 instance type for SageMaker inference endpoints." + }, + { + "type": "feature", + "category": "Amazon Redshift", + "contributor": "", + "description": "Amazon Redshift - Added support for rg.large and rg.12xlarge node types in CreateCluster, ModifyCluster, and ResizeCluster API operations." + }, + { + "type": "feature", + "category": "Amazon Omics", + "contributor": "", + "description": "Adds support for returning the task UUID (universally unique identifier) in GetRunTask and ListRunTasks responses" + }, + { + "type": "feature", + "category": "Amazon Simple Storage Service", + "contributor": "", + "description": "Documentation update for removing the 30 day minimum restriction for transition to Standard-IA or OneZone-IA storage classes" + }, + { + "type": "feature", + "category": "Amazon EMR", + "contributor": "", + "description": "Amazon EMR updates the Session object returned by GetSession API" + }, + { + "type": "feature", + "category": "Amazon Chime SDK Voice", + "contributor": "", + "description": "Marked CreateProxySession, DeleteProxySession, GetProxySession, ListProxySessions, UpdateProxySession, PutVoiceConnectorProxy, DeleteVoiceConnectorProxy, and GetVoiceConnectorProxy as deprecated." + }, + { + "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/2.48.x/2.48.3.json b/.changes/2.48.x/2.48.3.json new file mode 100644 index 000000000000..293b43278c4b --- /dev/null +++ b/.changes/2.48.x/2.48.3.json @@ -0,0 +1,48 @@ +{ + "version": "2.48.3", + "date": "2026-07-17", + "entries": [ + { + "type": "feature", + "category": "Amazon Relational Database Service", + "contributor": "", + "description": "Adds the AssociatedRoles parameter to CreateDBCluster, RestoreDBClusterFromSnapshot, RestoreDBClusterToPointInTime, and RestoreDBClusterFromS3, letting customers associate IAM roles with an Aurora DB cluster at create or restore time instead of calling AddRoleToDBCluster afterward." + }, + { + "type": "feature", + "category": "Amazon Cognito Identity Provider", + "contributor": "", + "description": "Amazon Cognito user pools now support sending SMS via AWS End User Messaging. A new EumsSms object in SmsConfigurationType lets you deliver MFA and verification texts through AWS End User Messaging, alongside the existing Amazon SNS option." + }, + { + "type": "feature", + "category": "odb", + "contributor": "", + "description": "Adds support for sourcing Autonomous Database admin and wallet passwords from customer-managed AWS Secrets Manager secrets, including password source configuration and summaries, and enabling or disabling the OCI IAM service role for Secrets Manager integration via InitializeService." + }, + { + "type": "feature", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Add a minTlsVersion(TlsVersion) builder option on AwsCrtHttpClient and AwsCrtAsyncHttpClient that enforces a minimum TLS protocol version for outbound connections. Currently supports TlsVersion.TLS_1_3 and TlsVersion.SYSTEM_DEFAULT (the default). Fixes [#5619](https://github.com/aws/aws-sdk-java-v2/issues/5619)." + }, + { + "type": "feature", + "category": "Amazon Kinesis Analytics", + "contributor": "", + "description": "Support for Flink 2.3 in Managed Service for Apache Flink" + }, + { + "type": "feature", + "category": "Amazon GameLift Streams", + "contributor": "", + "description": "Amazon GameLift Streams now supports assigning an IAM role to a stream session, enabling your application to securely access resources in your AWS account, such as Amazon S3 buckets and DynamoDB tables." + }, + { + "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/2.48.x/2.48.4.json b/.changes/2.48.x/2.48.4.json new file mode 100644 index 000000000000..f436de4d5ff1 --- /dev/null +++ b/.changes/2.48.x/2.48.4.json @@ -0,0 +1,60 @@ +{ + "version": "2.48.4", + "date": "2026-07-20", + "entries": [ + { + "type": "feature", + "category": "AWS Organizations", + "contributor": "", + "description": "Updated InvalidInputException error documentation to clarify that the service validates free-text field values against common cross-site scripting (XSS) patterns." + }, + { + "type": "feature", + "category": "AWS MediaTailor", + "contributor": "", + "description": "This change adds api support for configuring ad decision server timeouts and concurrency fields on MediaTailor playback configurations" + }, + { + "type": "feature", + "category": "Inspector2", + "contributor": "", + "description": "Adds Windows path support for deep inspection. Fixes tag propagation for connector CloudFormation stack operations." + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "Amazon SES introduces three new Pricing Plans (Essentials, Pro, Enterprise), which bundle SES features under one pricing umbrella. The new PutAccountPricingAttributes API lets the user set the account's plan, while current plan retrievalif done through the new PricingAttributes field on GetAccount." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Adds support for custom permissions for Triggers, allowing administrators to control user access to Schedule, Inbound Email and Quick Event triggers." + }, + { + "type": "bugfix", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Preserve the underlying CRT HttpException (including the CRT error code) as the cause of the SSLHandshakeException and ConnectException surfaced for TLS negotiation failures and socket timeouts, so callers can differentiate transient failures from persistent ones by inspecting the exception cause chain." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "This release adds support for specifying a connector version on Gateway targets to pin the connector's tool schema. It also introduces web-search connector version 1.2.0, which adds agent-side domain filtering, published date range filtering, and admin-side domain allowlisting." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Add W3C trace context headers (traceparent, tracestate, baggage) and X-Amzn-Trace-Id to InvokeHarness request for end-to-end observability propagation. Add toolResultMetadata to the streaming content block delta for MCP tool result meta delivery without oversized SSE frames." + }, + { + "type": "feature", + "category": "AWSMarketplace Metering", + "contributor": "", + "description": "For new SaaS product integrations, CustomerIdentifier is not populated in ResolveCustomer responses and is not supported in BatchMeterUsage. Use CustomerAWSAccountId and LicenseArn instead." + } + ] +} \ No newline at end of file diff --git a/.changes/2.49.x/2.49.0.json b/.changes/2.49.x/2.49.0.json new file mode 100644 index 000000000000..b05d932b459b --- /dev/null +++ b/.changes/2.49.x/2.49.0.json @@ -0,0 +1,66 @@ +{ + "version": "2.49.0", + "date": "2026-07-21", + "entries": [ + { + "type": "feature", + "category": "Inspector2", + "contributor": "", + "description": "GA date - July 21st 2026, remove Tags field from ListCodeSecurityIntegration and ListCodeSecurityScanConfiguration." + }, + { + "type": "feature", + "category": "Amazon Simple Systems Manager (SSM)", + "contributor": "", + "description": "Added a WarningMessage field to Automation along with corresponding public documentation." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Update Netty to 4.1.136" + }, + { + "type": "feature", + "category": "Timestream InfluxDB", + "contributor": "", + "description": "This release adds support for custom plugins in Amazon Timestream for InfluxDB. InfluxDB 3 Core and Enterprise DB parameter groups now accept a plugin repository URL and optional AWS Secrets Manager secret ARN, so the Processing Engine loads your Python plugins from a public or private repository." + }, + { + "type": "feature", + "category": "Amazon EMR Containers", + "contributor": "", + "description": "Added support for the DeleteSecurityConfiguration API, which allows customers to delete security configurations in Amazon EMR on EKS. Also added authenticationConfiguration in securityConfigurationdata structure." + }, + { + "type": "feature", + "category": "AWS EntityResolution", + "contributor": "", + "description": "Add support for real time matching with AWS Entity Resolution matching workflows with advanced rule sets." + }, + { + "type": "feature", + "category": "AWS Invoicing", + "contributor": "", + "description": "Added the SendProcurementPortalValidation and VerifyProcurementPortalValidation APIs. You can use the AWS SDKs to self-service activate your Procurement Portal Preferences created on the Billing Preferences page with a one-time-passcode (OTP) delivered to your portal." + }, + { + "type": "feature", + "category": "Redshift Data API Service", + "contributor": "", + "description": "update the workgroupArn to include EUSC partition, tests in THF Gamma and Prod no issue" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Eliminate per-operation lambdas for endpoint and auth scheme resolution in generated clients, permanently fixing constant pool overflow for large services like EC2 Internal." + }, + { + "type": "feature", + "category": "Amazon Redshift", + "contributor": "", + "description": "Amazon Redshift - Added support for managing Query Editor V2 IAM Identity Center applications via new CreateQev2IdcApplication, DescribeQev2IdcApplications, ModifyQev2IdcApplication, and DeleteQev2IdcApplication API operations." + } + ] +} \ No newline at end of file diff --git a/.changes/2.49.x/2.49.1.json b/.changes/2.49.x/2.49.1.json new file mode 100644 index 000000000000..5eacb32049d2 --- /dev/null +++ b/.changes/2.49.x/2.49.1.json @@ -0,0 +1,78 @@ +{ + "version": "2.49.1", + "date": "2026-07-22", + "entries": [ + { + "type": "feature", + "category": "Elastic Load Balancing", + "contributor": "", + "description": "This adds CLI examples for the IpAddressType field on SourceIpConfig, enabling Network Load Balancer listener rules to match traffic based on whether the source IP is IPv4 or IPv6." + }, + { + "type": "feature", + "category": "AWS Parallel Computing Service", + "contributor": "", + "description": "AWS PCS Node Lifecycle Actions provides a structured way to run custom scripts at defined points in a compute node's lifecycle directly through the AWS PCS compute node group API." + }, + { + "type": "feature", + "category": "Amazon Prometheus Service", + "contributor": "", + "description": "Add CloudWatch dataset destinations for Amazon Managed Service for Prometheus collectors." + }, + { + "type": "feature", + "category": "Partner Central Account API", + "contributor": "", + "description": "Adds Qualifications Association APIs that enable partners to associate a subsidiary account's qualifications with a primary account. Once associated, qualifications are shared across all connected accounts and scorecards are consolidated. Partners can start and track association and disassociation." + }, + { + "type": "bugfix", + "category": "Amazon S3", + "contributor": "", + "description": "Fix a race condition in multipart upload with low maxInFlightParts where CompleteMultipartUpload could be initiated while the final part was still uploading." + }, + { + "type": "bugfix", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Do not set the Content-Length header on a request that already carries Transfer-Encoding. Emitting both violates RFC 7230 and was rejected by the underlying CRT layer; this aligns the CRT client with the Netty client's existing behavior for chunked requests." + }, + { + "type": "feature", + "category": "ARC - Region switch", + "contributor": "", + "description": "Adds support for a client token in StartPlanExecution to make plan execution requests idempotent for safe retries." + }, + { + "type": "feature", + "category": "Amazon CloudWatch", + "contributor": "", + "description": "Adds documented value constraints for CloudWatch Log Alarm scheduled query configuration fields, and makes LogGroupIdentifiers optional for log alarms." + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "Launching DEED and MREP in US GOV" + }, + { + "type": "feature", + "category": "Amazon GuardDuty", + "contributor": "", + "description": "Amazon GuardDuty now returns filter lifecycle metadata in GetFilter responses. The response includes createdAt and updatedAt timestamps and a version number that increments on each update, giving you visibility into when a filter was created and last modified." + }, + { + "type": "feature", + "category": "CloudWatch Observability Admin Service", + "contributor": "", + "description": "Enablement for ALB and Bedrock Knowledge Base logs via Observability Admin Telemetry Rule for account and organization level" + }, + { + "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/2.49.x/2.49.2.json b/.changes/2.49.x/2.49.2.json new file mode 100644 index 000000000000..4184ef2a5be1 --- /dev/null +++ b/.changes/2.49.x/2.49.2.json @@ -0,0 +1,96 @@ +{ + "version": "2.49.2", + "date": "2026-07-23", + "entries": [ + { + "type": "feature", + "category": "Amazon DataZone", + "contributor": "", + "description": "Adds support for notebook sync with S3 ipynb files" + }, + { + "type": "feature", + "category": "Amazon Workspaces Instances", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "AWS Elemental MediaPackage v2", + "contributor": "", + "description": "This release adds support for non-epoch-locked CMAF ingest in MediaPackageV2 channels." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adds support for the Bring Your Own Storage(BYOS) feature in AgentCore Browser and Code Interpreter. Enables mounting S3Files and EFS File Systems via Access points." + }, + { + "type": "feature", + "category": "Amazon GameLift Streams", + "contributor": "", + "description": "GameLift Streams now supports configuring a custom aspect ratio per stream session to accommodate different player devices. Supported aspect ratios include landscape, portrait, and square - delivering a full-screen experience without letterboxing or cropping." + }, + { + "type": "feature", + "category": "AWS Billing and Cost Management Recommended Actions", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "Redshift Data API Service", + "contributor": "", + "description": "This release include long polling provids a new parameter wait-time-seconds to 5 API operations, new API ListSessions, and a new parameter execution-mode to BatchExecuteStatement" + }, + { + "type": "feature", + "category": "Amazon AppStream", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.1. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Added new capabilities to custom permissions profiles to control access to Amazon Quick through the browser extension and Microsoft Word, Outlook, Excel, and PowerPoint add-ins." + }, + { + "type": "feature", + "category": "Amazon Kendra Intelligent Ranking", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Release support for c6a, m6a, m6g, m7g, m8g instance types for SageMaker HyperPod" + }, + { + "type": "feature", + "category": "AWS Backup Gateway", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Add `numEventLoopThreads(Integer)` to `AwsCrtAsyncHttpClient.Builder` and `AwsCrtHttpClient.Builder` to configure the number of CRT event-loop (IO) threads. When set, the client owns a private `EventLoopGroup` of that size (must be greater than 1); when unset, it shares the process-wide default group." + }, + { + "type": "feature", + "category": "AWS Billing and Cost Management Pricing Calculator", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Adds support for the Bring Your Own Storage(BYOS) feature in AgentCore Browser and Code Interpreter. Enables mounting S3Files and EFS File Systems via Access points." + } + ] +} \ No newline at end of file diff --git a/.changes/2.49.x/2.49.3.json b/.changes/2.49.x/2.49.3.json new file mode 100644 index 000000000000..849539b0112b --- /dev/null +++ b/.changes/2.49.x/2.49.3.json @@ -0,0 +1,66 @@ +{ + "version": "2.49.3", + "date": "2026-07-24", + "entries": [ + { + "type": "feature", + "category": "Amazon DynamoDB", + "contributor": "", + "description": "Endpoint test standardizations" + }, + { + "type": "feature", + "category": "odb", + "contributor": "", + "description": "Documentation-only update to clarify the operation-specific valid values for the externalIdType field." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fixed several delegating AsyncRequestBody implementations (including those used by S3 Transfer Manager uploads) that reported the request-body type as unknown in the user-agent business metric instead of the actual type (file, bytes, or stream)." + }, + { + "type": "feature", + "category": "Amazon Neptune Graph", + "contributor": "", + "description": "Update validations for Tag Keys and KMS Key ARNs." + }, + { + "type": "feature", + "category": "AWS Artifact", + "contributor": "", + "description": "Added the PutComplianceInquiryFeedback API, enabling customers to submit feedback on compliance inquiry responses. Customers can rate responses as helpful or not helpful and provide optional reason codes and comments." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Update `ResponseInputStream`, to only return `0` from `available()` if the stream is closed; in other cases, if the wrapped stream returns 0 from `available()`, `1` is returned instead. This is to avoid cases where other classes such as [`java.util.zip.GZIPInputStream`](https://docs.oracle.com/javase/8/docs/api/java/util/zip/GZIPInputStream.html) misinterpret this as meaning the stream is closed." + }, + { + "type": "feature", + "category": "Amazon CloudWatch Application Insights", + "contributor": "", + "description": "This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.1. The SDK will prioritize its most performant protocol." + }, + { + "type": "feature", + "category": "RTBFabric", + "contributor": "", + "description": "The deprecated inboundLinksCount field has been removed from the GetResponderGateway API response. Customers who previously relied on this field should use linksRequestedCount instead." + }, + { + "type": "feature", + "category": "Amazon Cognito Identity Provider", + "contributor": "", + "description": "Amazon Cognito user pools now support the AdminGetUserAuthFactors operation, which lets administrators retrieve the configured authentication factors (such as password, SMS, email, and TOTP) available for a specific user in a user pool." + }, + { + "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/2.49.x/2.49.4.json b/.changes/2.49.x/2.49.4.json new file mode 100644 index 000000000000..d952496963ea --- /dev/null +++ b/.changes/2.49.x/2.49.4.json @@ -0,0 +1,78 @@ +{ + "version": "2.49.4", + "date": "2026-07-27", + "entries": [ + { + "type": "bugfix", + "category": "S3 Transfer Manager", + "contributor": "", + "description": "Fix race condition when invoking pausing upload that can cause a `NullPointerException`." + }, + { + "type": "feature", + "category": "Amazon EMR Containers", + "contributor": "", + "description": "With this launch, you can now set concurrent job limits on a virtual cluster, giving you fine-grained control over how many job runs execute at once and how many can wait in queue." + }, + { + "type": "feature", + "category": "Partner Central Account API", + "contributor": "", + "description": "Adds optional headquarters location to StartProfileUpdateTask, letting partners record their headquarters as an ISO 3166 country and subdivision code on their profile. When headquarters is provided, both the country and subdivision codes are required." + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Adds BatchGetDataQualityRulesetEvaluationRun API to retrieve multiple runs in one call, ObservationScope and ObservationMode parameters for anomaly detection, writing evaluation results to Data Catalog tables, and custom log group paths for recommendation runs." + }, + { + "type": "feature", + "category": "AWS Account", + "contributor": "", + "description": "This release adds support for the GetPrimaryEmailUpdateStatus API operation, which allows customers to retrieve the current status of a primary email address update request for an AWS account. The operation returns status information including whether the update is pending, completed, or failed." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Added new Governance fields to Custom Permissions API to support Deny By Default functionality." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "This release adds LoRA adapters, training plans, and new instance types to SageMaker inference optimization. CreateAIRecommendationJob accepts optional AdapterSource and CreateOptimizationJob accepts optional TrainingPlanArns and the ml.g7e and ml.p6-b200 families." + }, + { + "type": "feature", + "category": "AWS Clean Rooms ML", + "contributor": "", + "description": "This release adds support for the CR.8X worker type for SQL (32 vCPU)" + }, + { + "type": "feature", + "category": "AWS Billing and Cost Management Data Exports", + "contributor": "", + "description": "With this release, customers can configure their data exports to deliver CSV reports in ZIP compressed format." + }, + { + "type": "feature", + "category": "AWS Security Agent", + "contributor": "", + "description": "AWS Security Agent adds a new task hours field that reflects the active work done for a task." + }, + { + "type": "feature", + "category": "AWS Clean Rooms Service", + "contributor": "", + "description": "This release adds support for the CR.8X worker type for SQL (32 vCPU)" + }, + { + "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/2.49.x/2.49.5.json b/.changes/2.49.x/2.49.5.json new file mode 100644 index 000000000000..31a76e29debb --- /dev/null +++ b/.changes/2.49.x/2.49.5.json @@ -0,0 +1,36 @@ +{ + "version": "2.49.5", + "date": "2026-07-28", + "entries": [ + { + "type": "feature", + "category": "TrustedAdvisor Public API", + "contributor": "", + "description": "Adds ListRecommendationsForResource API and four CheckSummary fields (resourceArnQueryable, awsResourceTypes, checkGranularity, recommendationId) to retrieve recommendations for a given resource ARN." + }, + { + "type": "feature", + "category": "IAM Roles Anywhere", + "contributor": "", + "description": "Increases certificate string length for trust anchor source data to support new adjustable trust anchor limits." + }, + { + "type": "feature", + "category": "AWS DataSync", + "contributor": "", + "description": "Adds Enhanced mode support for EFS and FSx Lustre locations without an agent, and for HDFS (TDE), Azure Blob, and object storage locations with an agent. HDFS Enhanced mode supports multiple NameNodes for High Availability. Enhanced mode agents can now be deployed on Microsoft Hyper-V." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "AgentCore Identity now supports Private Key JWT client authentication for OAuth 2.0 credential providers. Agents can authenticate to identity provider token endpoints with a JWT client assertion signed by a customer-managed AWS KMS asymmetric key, eliminating the need for client secrets." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Documentation updates for SearchRules, AssociateRoutingProfileQueues, CreateRoutingProfile, AssociateContactWithUser CreateTaskTemplate, and UpdateTaskTemplate" + } + ] +} \ No newline at end of file diff --git a/.changes/2.49.x/2.49.6.json b/.changes/2.49.x/2.49.6.json new file mode 100644 index 000000000000..8899cb33330b --- /dev/null +++ b/.changes/2.49.x/2.49.6.json @@ -0,0 +1,54 @@ +{ + "version": "2.49.6", + "date": "2026-07-29", + "entries": [ + { + "type": "feature", + "category": "AWS Database Migration Service", + "contributor": "", + "description": "Updated documentation for various DMS Schema Conversion operations" + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Adding filtering, partitioning, and VPC support to AWS Glue REST API connector" + }, + { + "type": "feature", + "category": "AWS WAFV2", + "contributor": "", + "description": "AWS WAF now supports pre-parse text transformations, letting you normalize raw query strings before parsing, available on rule statements that use SingleQueryArgument or AllQueryArguments as the FieldToMatch. AWS WAF also added 10 new text transformations, including ModSecurity v3 parity options." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "This release adds support for policy-based routing on AWS Transit Gateway, enabling you to route traffic based on 5-tuple matching (source IP, destination IP, source port, destination port, and protocol) using new policy table entry APIs that direct matching traffic to a target route table." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fixed an issue where duplicate signing-region endpoint keys in service metadata caused ServiceMetadata static initialization to fail with \"Duplicate keys are provided\". The generated SIGNING_REGIONS_BY_REGION map now tolerates duplicate keys." + }, + { + "type": "feature", + "category": "AWS IoT SiteWise", + "contributor": "", + "description": "We have released a new set of APIs in support of a major new feature within AWS IoT SiteWise called Scenario Discover. Please see user guide about the feature and the API guide in public documentation for new APIs." + }, + { + "type": "feature", + "category": "Amazon GameLift Streams", + "contributor": "", + "description": "Adds ListApplicationShaderCaches API to retrieve shader cache metadata for applications and adds stream URLs, which give end users temporary, unauthenticated access to a stream session in their browser. Includes CreateStreamUrl, GetStreamUrl, ListStreamUrls, and RevokeStreamUrl operations." + }, + { + "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/2.50.x/2.50.0.json b/.changes/2.50.x/2.50.0.json new file mode 100644 index 000000000000..1b452ba75a7b --- /dev/null +++ b/.changes/2.50.x/2.50.0.json @@ -0,0 +1,66 @@ +{ + "version": "2.50.0", + "date": "2026-07-30", + "entries": [ + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Improve endpoint resolution performance by replacing URI.create with a lightweight EndpointUrl." + }, + { + "type": "feature", + "category": "Managed Streaming for Kafka", + "contributor": "", + "description": "Amazon MSK Express brokers now support streaming tables for Apache Iceberg, continuously materializing Apache Kafka topics as Iceberg tables in Amazon S3 Tables. Express brokers also now support data delivery to Amazon S3 general purpose buckets." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adds support for configuring models through the OpenResponses API for custom evaluators. CreateEvaluator and UpdateEvaluator now accept an OpenResponses model configuration for LLM-as-a-Judge evaluations." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "Add Python3.15 (python3.15) and NodeJs 26 (nodejs26.x) support to AWS Lambda" + }, + { + "type": "feature", + "category": "AWS Network Firewall", + "contributor": "", + "description": "Adds UPDATING field to Container Association Status" + }, + { + "type": "feature", + "category": "AWS Identity and Access Management", + "contributor": "", + "description": "Improved IAM Policy Simulator accuracy. Simulator now evaluates SCP conditions and resource scoping, returns explicitDeny for explicit SCP denials, and reports accurate cross-account decisions." + }, + { + "type": "feature", + "category": "PricingPlanManager", + "contributor": "", + "description": "Adds support for Public PricingPlanManager SDK" + }, + { + "type": "bugfix", + "category": "Amazon S3", + "contributor": "", + "description": "Honor an explicit `S3Configuration.expectContinueEnabled(false)` when cross region access is enabled." + }, + { + "type": "feature", + "category": "AWS Security Agent", + "contributor": "", + "description": "Adds support for providing a branch override when configured integrated repositories" + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Adds support for g7 family instance types for SageMaker Studio JupyterLab and CodeEditor apps for IAD (us-east-1), PDX (us-west-2), CMH (us-east-2)." + } + ] +} \ No newline at end of file diff --git a/.changes/2.50.x/2.50.1.json b/.changes/2.50.x/2.50.1.json new file mode 100644 index 000000000000..8a805574254a --- /dev/null +++ b/.changes/2.50.x/2.50.1.json @@ -0,0 +1,30 @@ +{ + "version": "2.50.1", + "date": "2026-07-30", + "entries": [ + { + "type": "feature", + "category": "AWS Billing and Cost Management Pricing Calculator", + "contributor": "", + "description": "Removing Smithy RPC v2 CBOR support that was added in previous SDK release." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Add the `@SdkAdvancedApi` annotation, which marks APIs that are error-prone to implement, override, call, or configure so that using them incorrectly compiles cleanly but can fail or misbehave at runtime. The annotation records structured guidance (the risky usage kind, an explanation of the contract to uphold, a safer alternative, and a documentation link) and is applied to several streaming and interceptor extension points, including AsyncRequestBody, AsyncResponseTransformer, ContentStreamProvider, the mutating ExecutionInterceptor content hooks, and the FUTURE_COMPLETION_EXECUTOR advanced client option." + }, + { + "type": "feature", + "category": "AWS Billing and Cost Management Recommended Actions", + "contributor": "", + "description": "Removing Smithy RPC v2 CBOR support that was added in previous SDK release." + }, + { + "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/2.50.x/2.50.2.json b/.changes/2.50.x/2.50.2.json new file mode 100644 index 000000000000..788e830970cf --- /dev/null +++ b/.changes/2.50.x/2.50.2.json @@ -0,0 +1,96 @@ +{ + "version": "2.50.2", + "date": "2026-07-31", + "entries": [ + { + "type": "feature", + "category": "Amazon CloudWatch Logs", + "contributor": "", + "description": "Amazon CloudWatch Logs now lets you create and update lookup tables directly from CloudWatch Logs query results by passing a queryId, and configure a lookup table as a scheduled query destination so it refreshes automatically with the latest query results on each run." + }, + { + "type": "feature", + "category": "Amazon Prometheus Service", + "contributor": "", + "description": "Amazon Managed Service for Prometheus adds support for an Amazon OpenSearch Service exporter for managed collectors." + }, + { + "type": "feature", + "category": "AWS Network Firewall", + "contributor": "", + "description": "Doc Updates for Container Attributes" + }, + { + "type": "feature", + "category": "Amazon DataZone", + "contributor": "", + "description": "Adding support for enhanced Git experience in Sagemaker Unified Studio." + }, + { + "type": "feature", + "category": "AWS Billing", + "contributor": "", + "description": "Adds GetEnterpriseSupportChargeSummary, GetEnterpriseSupportContractDetails, and ListEnterpriseSupportLinkedAccountCharges. These APIs provide first-time programmatic access to billing data for Enterprise Support usage previously only available upon request through AWS Concierge or Support." + }, + { + "type": "feature", + "category": "AmazonConnectCampaignServiceV2", + "contributor": "", + "description": "Launching feature for abandonment rate pacing control for outbound campaigns." + }, + { + "type": "feature", + "category": "AWS Elemental Inference", + "contributor": "", + "description": "AWS Elemental Inference now supports graphic composition on cropped video outputs, enabling branded graphics and other visual elements to be overlaid as part of the inference workflow." + }, + { + "type": "feature", + "category": "AWS CloudFormation", + "contributor": "", + "description": "Adding enum for sensitive property to DriftIgnoredReason" + }, + { + "type": "feature", + "category": "AWS Marketplace Catalog Service", + "contributor": "", + "description": "This release enhances the ListEntities API to support TargetAgreementId, TargetAgreementIntent, and CreatedBySource filters for the Offer entity type." + }, + { + "type": "feature", + "category": "AWS Outposts", + "contributor": "", + "description": "Adds the \"EKS\" value to the AWSServiceName enum and marks the Address field as sensitive." + }, + { + "type": "feature", + "category": "Amazon Transcribe Streaming Service", + "contributor": "", + "description": "This release adds a new optional TranscriptFormat parameter to the Amazon Transcribe streaming API, letting customers select spoken or written form for numeric and formatted output." + }, + { + "type": "feature", + "category": "Amazon Bedrock Runtime", + "contributor": "", + "description": "Added support for mid-conversation tool changes in the Amazon Bedrock Converse and ConverseStream APIs" + }, + { + "type": "feature", + "category": "AWS Resilience Hub V2", + "contributor": "", + "description": "Adding support for new testing capability in AWS Resilience Hub." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Adding TopicV2 management APIs, adding possibility to use Topics in Analysis" + }, + { + "type": "feature", + "category": "Amazon Relational Database Service", + "contributor": "", + "description": "Adds StorageOperationStatus and StorageOperationPercentProgress to DescribeDBInstances, letting you monitor RDS storage initialization and optimization progress." + } + ] +} \ No newline at end of file diff --git a/.changes/2.50.x/2.50.3.json b/.changes/2.50.x/2.50.3.json new file mode 100644 index 000000000000..58ef12b1ede4 --- /dev/null +++ b/.changes/2.50.x/2.50.3.json @@ -0,0 +1,48 @@ +{ + "version": "2.50.3", + "date": "2026-08-03", + "entries": [ + { + "type": "feature", + "category": "CloudWatch Observability Admin Service", + "contributor": "", + "description": "Launch CMK support for Telemetry Enablement Organization and Account Rules." + }, + { + "type": "feature", + "category": "AWS Network Firewall", + "contributor": "", + "description": "This launch allows customers to use Network Firewall as an explicit Proxy and protect their workloads against threat of data exfiltration." + }, + { + "type": "feature", + "category": "AWS Elemental MediaConvert", + "contributor": "", + "description": "Updates Kantar server URL validation to accept Fifty5Blue domain. Adds support for output to S3 Glacier Instant Retrieval." + }, + { + "type": "feature", + "category": "Timestream InfluxDB", + "contributor": "", + "description": "This release adds support for customer-managed backup restore, and encryption of new DbInstances and DbClusters using customer-managed KMS keys." + }, + { + "type": "feature", + "category": "AWS Direct Connect", + "contributor": "", + "description": "Added route visibility support for AWS Direct Connect, allowing customers to call ListVirtualInterfaceRoutes to view the BGP routes including AS path and BGP communities advertised over their virtual interfaces." + }, + { + "type": "feature", + "category": "Amazon EKS Auth", + "contributor": "", + "description": "Added eksNodeName, instanceId, and zone optional parameters to the AssumeRoleForPodIdentity API." + }, + { + "type": "feature", + "category": "AWS WAFV2", + "contributor": "", + "description": "Updated descriptions for number of PreParseTextTransformations allowed per rule statement" + } + ] +} \ No newline at end of file diff --git a/.changes/2.51.x/2.51.0.json b/.changes/2.51.x/2.51.0.json new file mode 100644 index 000000000000..9fd40d024595 --- /dev/null +++ b/.changes/2.51.x/2.51.0.json @@ -0,0 +1,78 @@ +{ + "version": "2.51.0", + "date": "2026-08-04", + "entries": [ + { + "type": "feature", + "category": "Amazon DynamoDB", + "contributor": "", + "description": "Vector indexes are a type of index in Amazon DynamoDB that enable similarity search on vector embedding stored in your table items. Vector indexes use approximate nearest neighbor search to find items whose vectors are most similar to a query vector that you provide." + }, + { + "type": "feature", + "category": "Amazon DynamoDB Enhanced Client", + "contributor": "", + "description": "Adds SearchVectors and vector index support to the DynamoDB Enhanced Client, including vector index table operations, table.vectorIndex() search handles, and enhanced search request/response types." + }, + { + "type": "feature", + "category": "AWS Identity and Access Management", + "contributor": "", + "description": "Updating endpoint generation logic" + }, + { + "type": "feature", + "category": "Amazon DynamoDB Enhanced Client", + "contributor": "", + "description": "Adds annotation-driven vector index support to the DynamoDB Enhanced Client via @DynamoDbVectorAttribute, @DynamoDbSearchVectorsHashKey, and @DynamoDbSearchVectorsInlineFilterKey on bean and immutable schemas, enabling no-arg createTable() and vector search through annotation-derived table.vectorIndex() handles." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Amazon Connect Customer now supports up to 50 attachments per email, increased from the previous limit of 10. The individual maximum attachment size limit of 20 MB and the total email size limit of 25 MB still hold true." + }, + { + "type": "feature", + "category": "Inspector2", + "contributor": "", + "description": "Adding Azure SBOM export capability." + }, + { + "type": "feature", + "category": "Partner Central Selling API", + "contributor": "", + "description": "Partners can now create leads with only 5 required fields and free-text values for all other fields, reducing import friction. Engagement invitations now include enrichment data (propensity scores, lead readiness) directly in the response." + }, + { + "type": "feature", + "category": "AWS Organizations", + "contributor": "", + "description": "Improved accuracy of CloudTrail event documentation for AWS Organizations membership operations." + }, + { + "type": "feature", + "category": "AWS Single Sign-On Admin", + "contributor": "", + "description": "AWS IAM Identity Center now lets you create organization-level instances without enabling multi-account permissions. You can enable multi-account permissions during instance creation or later via console or API, which then provisions the necessary service-linked roles." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Amazon EC2 now supports Application Status Checks, a new status check that monitors your application's health through configurable HTTP(S) paths and ports, so you can detect and automatically respond to application-level impairments." + }, + { + "type": "feature", + "category": "Amazon Aurora DSQL", + "contributor": "", + "description": "UpdateCluster now checks the RemovePeerCluster permission on the specific cluster being removed, not a wildcard and docs now clarify how to set kmsEncryptionKey so the cluster uses the AWS-owned key." + }, + { + "type": "feature", + "category": "Amazon WorkSpaces", + "contributor": "", + "description": "Added ClientExperiencePolicy to ClientProperties object for ModifyClientProperties and DescribeClientProperties APIs." + } + ] +} \ No newline at end of file diff --git a/.changes/2.51.x/2.51.1.json b/.changes/2.51.x/2.51.1.json new file mode 100644 index 000000000000..d00da370996a --- /dev/null +++ b/.changes/2.51.x/2.51.1.json @@ -0,0 +1,48 @@ +{ + "version": "2.51.1", + "date": "2026-08-05", + "entries": [ + { + "type": "feature", + "category": "AWSDeadlineCloud", + "contributor": "", + "description": "AWS Deadline Cloud now reports persistent volume costs alongside compute and license costs. Customers can view per-fleet storage costs in Usage Explorer by selecting the Usage Type grouping, helping them better understand the costs of their infrastructure." + }, + { + "type": "feature", + "category": "Amazon EC2 Container Service", + "contributor": "", + "description": "New enum values added for Agent Connectivity issues" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Eliminate per-operation metric-publishing lambdas in generated clients by hoisting them into shared helper methods, reducing constant pool usage and class size for large service clients approaching the JVM per-class constant pool limit." + }, + { + "type": "feature", + "category": "AWS Certificate Manager Private Certificate Authority", + "contributor": "", + "description": "Private Certificate Authority service now supports RSASSA-PSS signing algorithm." + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Added the PutDataCatalogExportConfiguration to export Glue Data Catalog metadata to systems tables stored in S3 Tables." + }, + { + "type": "bugfix", + "category": "AWS Sign-In Service", + "contributor": "", + "description": "Fixed an issue where credentials loaded from a login_session profile resolved the Signin client's configuration, such as region and endpoint_url, from the default profile instead of the profile that requested the credentials." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adding support for fine-grained access control for AgentCore Memory through managed AgentCore Gateway HTTP Connectors." + } + ] +} \ No newline at end of file diff --git a/.changes/2.51.x/2.51.2.json b/.changes/2.51.x/2.51.2.json new file mode 100644 index 000000000000..a6e3054c189b --- /dev/null +++ b/.changes/2.51.x/2.51.2.json @@ -0,0 +1,120 @@ +{ + "version": "2.51.2", + "date": "2026-08-06", + "entries": [ + { + "type": "feature", + "category": "AWS Marketplace Discovery", + "contributor": "", + "description": "GetOfferTerms now returns netPaymentTerm in offerTerms, specifying payment due period after invoice date. The paymentDuePeriod field uses ISO 8601 duration format (e.g., \"P30D\" for net 30 days). This is a backward-compatible addition. See API documentation for full structure and examples." + }, + { + "type": "feature", + "category": "Amazon Simple Storage Service", + "contributor": "", + "description": "AWS Backup now lets you create read-only access points for Amazon S3 recovery points, enabling you to access backup data using S3 APIs without initiating a restore." + }, + { + "type": "feature", + "category": "AWS Backup", + "contributor": "", + "description": "AWS Backup now lets you create read-only access points for Amazon S3 recovery points, enabling you to access backup data using S3 APIs without initiating a restore." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Add support for capacity provider sessions in Amazon Bedrock AgentCore. Customers can now delete an active session running on a runtime instance launched through their capacity provider." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Adds a new optional IncludeLocalZones parameter to the Spot Placement Score API that defaults to false. When set to true, the Spot Placement Score API will consider the relevant Local Zones with Spot capacity when computing the Spot Placement Score." + }, + { + "type": "feature", + "category": "AWS Marketplace Agreement Service", + "contributor": "", + "description": "GetAgreementTerms now returns a new term variant in AcceptedTerm, netPaymentTerm, with a paymentDuePeriod field (example \"P30D\")." + }, + { + "type": "feature", + "category": "Managed Streaming for Kafka", + "contributor": "", + "description": "MSK Clusters can now deliver authorizer logs alongside broker logs to the destinations defined by you" + }, + { + "type": "feature", + "category": "AWS SecurityHub", + "contributor": "", + "description": "Security Hub is adding a new public API, ListFreeTrialStatusesV2 to describe the free trial statuses of the Security Hub service and its opt-in features." + }, + { + "type": "feature", + "category": "Auto Scaling", + "contributor": "", + "description": "EC2 Auto Scaling now supports being managed by other AWS services via the operator field." + }, + { + "type": "feature", + "category": "AWS MediaTailor", + "contributor": "", + "description": "AWS Elemental MediaTailor now supports concurrent function execution. The new Concurrent Executor function type runs multiple independent child functions in parallel within a single lifecycle hook, reducing pipeline latency to the duration of the slowest call instead of the sum of all calls." + }, + { + "type": "feature", + "category": "Agent Registry", + "contributor": "", + "description": "Agent Registry's Public Preview release" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Add support for Gateway rate limits and Runtime instances in Amazon Bedrock AgentCore. Customers can now configure rate limits scoped to control request rates, token consumption rates, and active connection rates. Customers can now create capacity providers to launch runtimes on their EC2 instances." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Releases new Model Customization SequenceLength parameter for Training and g7 instance types for Training and Processing." + }, + { + "type": "feature", + "category": "Amazon CloudWatch Logs", + "contributor": "", + "description": "This release adds index category support to the CloudWatch Logs DescribeFieldIndexes API. Customers can filter and identify DEFAULT, CUSTOM, AUTO, and INACTIVE field indexes." + }, + { + "type": "feature", + "category": "AWS End User Messaging Social", + "contributor": "", + "description": "Add support for WhatsApp Conversions APIs." + }, + { + "type": "feature", + "category": "AWS Device Farm", + "contributor": "", + "description": "Adds support for service generated insights across runs, jobs, and tests." + }, + { + "type": "feature", + "category": "Amazon GameLift", + "contributor": "", + "description": "Adds support for C8a, C8i, C9g, M8a, M8i, and M9g EC2 instance type families for managed EC2 and container fleets. Also adds explicit anchors on most string regexes." + }, + { + "type": "feature", + "category": "Agent Registry Control", + "contributor": "", + "description": "Agent Registry's Public Preview release" + }, + { + "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/2.51.x/2.51.3.json b/.changes/2.51.x/2.51.3.json new file mode 100644 index 000000000000..25ee47ff33e9 --- /dev/null +++ b/.changes/2.51.x/2.51.3.json @@ -0,0 +1,66 @@ +{ + "version": "2.51.3", + "date": "2026-08-07", + "entries": [ + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Correctly support endpoint expressions with multiple chained assigns." + }, + { + "type": "feature", + "category": "AWS Elemental MediaPackage v2", + "contributor": "", + "description": "StreamNameOutputMode - a new optional field on MediaPackageV2 OriginEndpoints that lets customers choose whether egress manifests use numeric stream indices (default) or encoder-assigned stream names from the input" + }, + { + "type": "feature", + "category": "AWS MediaTailor", + "contributor": "", + "description": "Added support for inserting ads via the VAST Ad Buffet standard. You can now configure MediaTailor to insert ads in sequence order using the AdSequencingMode setting in your playback configuration. Standalone ads are used as fallbacks when a sequenced ad is unavailable." + }, + { + "type": "feature", + "category": "AWS Security Agent", + "contributor": "", + "description": "Added enableEmailMfa input field on Actor to enable email-based MFA during penetration tests. When enabled, a server-generated mfaForwardingAddress is returned. Set up a forwarding rule in your email provider to forward MFA emails to this address so the agent can complete email-based MFA login flows" + }, + { + "type": "feature", + "category": "Amazon HealthLake", + "contributor": "", + "description": "Adds provenanceEnabled to StartFHIRImportJob" + }, + { + "type": "feature", + "category": "AWS Amplify", + "contributor": "", + "description": "Increased the maximum allowed length of the oauthToken parameter in the CreateApp and UpdateApp APIs to support longer OAuth tokens issued by third-party Git providers." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Supports updating the task template associated with in-progress task contacts using the new UpdateContactTaskTemplate API. This enables supervisors and developers to dynamically reassign task templates without creating a new task." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Amazon SageMaker adds maintenance lifecycle statuses for Notebook Instances" + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "This release adds support for BGP route protection in Amazon VPC IP Address Manager (IPAM), including route discovery, RPKI route protection findings, and delegated RPKI (Internet Registry Associations, routing policy registrations, and ROA management) for BYOIP prefixes." + }, + { + "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/2.51.x/2.51.4.json b/.changes/2.51.x/2.51.4.json new file mode 100644 index 000000000000..29e38155f3e9 --- /dev/null +++ b/.changes/2.51.x/2.51.4.json @@ -0,0 +1,42 @@ +{ + "version": "2.51.4", + "date": "2026-08-10", + "entries": [ + { + "type": "feature", + "category": "AWS Elemental MediaLive", + "contributor": "", + "description": "Added VirtualSourceAddress to multicast output destinations for MediaLive Anywhere channels. Specifies the source IP address for outbound multicast packets when downstream networks enforce source-IP filtering." + }, + { + "type": "feature", + "category": "AWS Elemental Inference", + "contributor": "", + "description": "Added support for the SearchFixtures API and DataSourceConfiguration, enabling customers to map fixture event data onto clipping outputs for improved feature accuracy." + }, + { + "type": "feature", + "category": "Amazon SageMaker Runtime", + "contributor": "", + "description": "Added the PrefixAwareId header to InvokeEndpoint and InvokeEndpointWithResponseStream. This optional parameter serves as a routing hint for endpoints configured with prefix-aware routing, differentiating routing decisions for requests that share the same prompt prefix." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Added Malay language option to use AI to automatically fill evaluation forms in Malay" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Reduce generated client source and bytecode size for JSON, CBOR, and Smithy RPC v2 protocol services by generating the error-metadata mapper once per client instead of once per operation." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Added PREFIX AWARE routing strategy and PrefixAwareRoutingConfig to CreateEndpointConfig. Configure PrefixLength and ConcurrencyThreshold to route requests that share the same prompt prefix to the same instance." + } + ] +} \ No newline at end of file diff --git a/.changes/2.52.x/2.52.0.json b/.changes/2.52.x/2.52.0.json new file mode 100644 index 000000000000..511c21c0227e --- /dev/null +++ b/.changes/2.52.x/2.52.0.json @@ -0,0 +1,90 @@ +{ + "version": "2.52.0", + "date": "2026-08-11", + "entries": [ + { + "type": "feature", + "category": "Amazon Elastic Kubernetes Service", + "contributor": "", + "description": "This feature would give customers the ability to selectively tune certain configurations of Kubernetes control plane components in an Amazon EKS cluster." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Added support for the AWS_IGNORE_CONFIGURED_ENDPOINT_URLS setting to skip endpoint URLs from environment variables and config files." + }, + { + "type": "feature", + "category": "Account Access", + "contributor": "", + "description": "Adds SDK support for AWS IAM account access manager, a feature that enables mapping of IAM roles to the users and groups in AWS IAM Identity Center." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Seven new APIs for managing custom metrics, including create, describe, update, and delete. Using Custom Metrics, customers of Amazon Connect Customer can tailor analytics dashboards to their needs by applying custom thresholds, filters, and calculations to one or more out of the box measurements." + }, + { + "type": "feature", + "category": "Amazon CloudDirectory", + "contributor": "", + "description": "Added an end-of-support notice to Amazon Cloud Directory public CLI reference documentation." + }, + { + "type": "feature", + "category": "Apache HTTP Client 5", + "contributor": "", + "description": "Upgrade httpcomponents.client5 to 5.6.3 to address CVE-2026-64607" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Make individual parts retryable when an in-memory `AsyncRequestBody` (for example one created with `AsyncRequestBody.fromBytes`, `fromByteBuffer`, or `fromString`) is split, such as during an S3 multipart upload. The body in these cases is entirely in memory already so no data is copied and callers no longer need to wrap the body in `BufferedSplittableAsyncRequestBody` to get retries." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fixed the client-side rate limiting behavior of `AdaptiveRetryStrategy` under throttling conditions. Previously, the computed rate limit was overly aggressive, potentially allowing a request rate much lower than what the service allows, and was unstable, varying over time even when the service's allowed throughput was constant." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Update Netty to 4.1.137" + }, + { + "type": "feature", + "category": "Amazon DataZone", + "contributor": "", + "description": "GetSubscriptionGrant now returns materialized asset scope name for mapping Lake Formation data cell filters or Redshift views to subscription grants." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Adding online eval arn as input for recommendation API" + }, + { + "type": "feature", + "category": "Amazon Textract", + "contributor": "", + "description": "Amazon A2I entered maintenance mode in July 2026 and now rejects StartHumanLoop requests from accounts that it does not recognize as existing customers. This update adds a corresponding note to the HumanLoopConfig parameter documentation so that the API Reference and SDK docs explain this behavior." + }, + { + "type": "feature", + "category": "AWS Organizations", + "contributor": "", + "description": "Documentation update for AWS Organizations that clarifies valid input values for the HandshakePartyType parameter in the InviteAccountToOrganization. API ORGANIZATION is valid in responses only. valid input values are ACCOUNT and EMAIL" + }, + { + "type": "feature", + "category": "AWS Clean Rooms Service", + "contributor": "", + "description": "Adds support for exporting redacted query execution logs in AWS Clean Rooms" + } + ] +} \ No newline at end of file diff --git a/.changes/2.52.x/2.52.1.json b/.changes/2.52.x/2.52.1.json new file mode 100644 index 000000000000..16dab9edf166 --- /dev/null +++ b/.changes/2.52.x/2.52.1.json @@ -0,0 +1,48 @@ +{ + "version": "2.52.1", + "date": "2026-08-12", + "entries": [ + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Added APIs for DLP with Microsoft Purview (manage configs with label enforcement across Spaces, Chat, Knowledge Bases), Approval Workflows (CRUD for policies on asset sharing for Agents, Knowledge Bases, Spaces), and Limits Management (limit profiles for index storage and agent hours per user)." + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Documentation updates for materialized views APIs." + }, + { + "type": "feature", + "category": "AWS MediaConnect", + "contributor": "", + "description": "AWS MediaConnect now supports tuning the internal recovery latency between Router Inputs and Outputs to prioritize stream quality versus end-to-end latency." + }, + { + "type": "feature", + "category": "Amazon Aurora DSQL", + "contributor": "", + "description": "Improved validation of Kinesis stream ARN format to ensure only valid ARN characters are accepted" + }, + { + "type": "feature", + "category": "AWS Well-Architected Tool", + "contributor": "", + "description": "This change releases the Well-Architected Agent, a generative AI service that analyzes a customer's AWS environment and delivers personalized, prioritized recommendations across cost, security, performance, and resilience." + }, + { + "type": "feature", + "category": "odb", + "contributor": "", + "description": "Adds support for Oracle Exadata on Exascale Infrastructure (ExaDB-XS) resources including storage vaults and VM clusters." + }, + { + "type": "feature", + "category": "AWS Identity and Access Management", + "contributor": "", + "description": "Introduced role manager, an IAM capability that automatically sets up the IAM roles your AWS services need. When you set up a supported service in the console, role manager creates a role for you or reuses an existing one from an AWS-managed template." + } + ] +} \ No newline at end of file diff --git a/.changes/2.53.x/2.53.0.json b/.changes/2.53.x/2.53.0.json new file mode 100644 index 000000000000..ae9b2ef6ad42 --- /dev/null +++ b/.changes/2.53.x/2.53.0.json @@ -0,0 +1,96 @@ +{ + "version": "2.53.0", + "date": "2026-08-13", + "entries": [ + { + "type": "feature", + "category": "Apache HTTP Client 5", + "contributor": "", + "description": "Upgrade httpcomponents.client5 to 5.6.4 to address CVE-2026-71290" + }, + { + "type": "feature", + "category": "Auto Scaling", + "contributor": "", + "description": "Amazon EC2 Auto Scaling now supports terminating multiple instances in a single TerminateInstanceInAutoScalingGroup call via the new InstanceIds parameter, returning an Activities list. LaunchInstances now returns IdempotentCallInProgressFault for duplicate client tokens." + }, + { + "type": "feature", + "category": "AWS Security Agent", + "contributor": "", + "description": "Add support for setting a maximum task-hour budget cap on penetration tests and code reviews, and for revalidating previously reported findings via a new REVALIDATION job type." + }, + { + "type": "bugfix", + "category": "Apache 5 HTTP Client", + "contributor": "", + "description": "Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it." + }, + { + "type": "bugfix", + "category": "Apache HTTP Client", + "contributor": "", + "description": "Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it." + }, + { + "type": "bugfix", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Honor wildcard `nonProxyHosts` entries in CRT-based HTTP clients (`AwsCrtHttpClient`, `AwsCrtAsyncHttpClient`, and the S3/CRT client). Previously a `*.suffix` wildcard or a bare `*` from `http.nonProxyHosts`/`no_proxy` was silently ignored, so matching hosts were routed through the proxy instead of bypassing it. Supported forms are an exact host, a `*.suffix` wildcard (matches the domain and its subdomains), a single `*` for all hosts, and CIDR ranges. Entries must not contain surrounding whitespace." + }, + { + "type": "feature", + "category": "AWS Clean Rooms Service", + "contributor": "", + "description": "This release adds support for minimum aggregation thresholds and comparison controls to the Custom analysis rule type." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Adds the StartAssistantContact API to start chat contacts handled by an AI agent. Adds SegmentAttributes to StartWebRTCContact, and corrects its error response to now receive AccessDeniedException (previously returned as an internal server error due to a missing error declaration)." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Removed ServiceMetadata usages from client creation and request processing code paths to improve cold start performance. Endpoint and signing region resolution now uses Endpoints 2.0 directly instead of triggering eager initialization of all service metadata classes. Service client artifacts must be version 2.28.1 or later to be compatible with this change." + }, + { + "type": "feature", + "category": "Amazon CloudFront", + "contributor": "", + "description": "Adds SHA256 support to CloudFrontUtilities" + }, + { + "type": "bugfix", + "category": "URL Connection HTTP Client", + "contributor": "", + "description": "Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it." + }, + { + "type": "feature", + "category": "AWS CodeCommit", + "contributor": "", + "description": "Added the GetBlobDifferences API operation, which returns line-level diffs between two blob versions without requiring a local clone. Returns structured hunks with context, additions, and deletions. Supports pagination for large diffs." + }, + { + "type": "bugfix", + "category": "Netty NIO HTTP Client", + "contributor": "", + "description": "Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it." + }, + { + "type": "bugfix", + "category": "Amazon DynamoDB Enhanced Client", + "contributor": "", + "description": "Fix AutoGeneratedTimestampRecordExtension failing when TableSchema.converterForAttribute throws UnsupportedOperationException for custom schemas; expand dynamodb-enhanced functional test coverage" + }, + { + "type": "feature", + "category": "AWS Certificate Manager", + "contributor": "", + "description": "This change allows customers to update their existing email-validated certificates to use the DNS validation method." + } + ] +} \ No newline at end of file diff --git a/.changes/2.53.x/2.53.1.json b/.changes/2.53.x/2.53.1.json new file mode 100644 index 000000000000..0d53a82304e4 --- /dev/null +++ b/.changes/2.53.x/2.53.1.json @@ -0,0 +1,66 @@ +{ + "version": "2.53.1", + "date": "2026-08-14", + "entries": [ + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Release support for g7.2xlarge, g7.4xlarge, g7.8xlarge, g7.12xlarge, g7.24xlarge, and g7.48xlarge instance types for SageMaker HyperPod" + }, + { + "type": "feature", + "category": "Amazon Redshift", + "contributor": "", + "description": "Amazon Redshift now unlocks a locked admin user account and resets the failed-login counter when you update the admin password using the ModifyCluster API. This option is available only when account lockout security is enabled." + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Added support for associating glossary terms with iterable form items, such as table columns." + }, + { + "type": "feature", + "category": "AmazonMWAAServerless", + "contributor": "", + "description": "Adds support for Consuming code for MWAA Serverless" + }, + { + "type": "feature", + "category": "CloudWatch Observability Admin Service", + "contributor": "", + "description": "CloudWatch Logs centralization rules now support tag propagation. You can configure a TagPropagationConfiguration on your centralization rule to automatically sync resource tags from source to destination log groups, with configurable conflict resolution strategies." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adds AgentCore Payments support for CMK, Marketplace Subscriptions and QuickCreate" + }, + { + "type": "feature", + "category": "Agents for Amazon Bedrock Runtime", + "contributor": "", + "description": "Adds CheckIngestedDocumentAcl and GetIngestedDocumentAcl APIs to Amazon Bedrock Knowledge Bases. Customers can verify user access to documents based on ingested ACLs and retrieve full ACL details including allow and deny entries, enabling validation of ACL ingestion without test retrievals." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Add support for the Machine Payments Protocol (MPP) and x402 upto scheme payments protocol in Amazon Bedrock AgentCore Payments. Customers can now pay for MPP-gated resources and also pay services which requires upto scheme in x402" + }, + { + "type": "feature", + "category": "Redshift Serverless", + "contributor": "", + "description": "Amazon Redshift now unlocks a locked admin user account and resets the failed-login counter when you update the admin password using the UpdateNamespace API. This option is available only when account lockout security is enabled." + }, + { + "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/2.53.x/2.53.2.json b/.changes/2.53.x/2.53.2.json new file mode 100644 index 000000000000..6be448c0c27d --- /dev/null +++ b/.changes/2.53.x/2.53.2.json @@ -0,0 +1,48 @@ +{ + "version": "2.53.2", + "date": "2026-08-17", + "entries": [ + { + "type": "feature", + "category": "Amazon Elastic Container Registry", + "contributor": "", + "description": "Documentation update for the ECR PutReplicationConfiguration API to increase the replication rule limit from 10 to 25" + }, + { + "type": "feature", + "category": "AWS Organizations", + "contributor": "", + "description": "Add new Transfer Responsibility error codes and document related CloudTrail events for accepting and terminating a Transfer Responsibility." + }, + { + "type": "feature", + "category": "Agents for Amazon Bedrock Runtime", + "contributor": "", + "description": "AgenticRetrieveStream API now supports Amazon Bedrock AgentCore Memory. Use the new memoryConfiguration parameter to continue a session from short-term memory and retrieve from long-term memory." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "This release adds new APIs to create, describe, update, delete, and list extraction definitions, enabling customers to manage lifecycle of extraction definition resources. Additionally, this release adds new event sources for Rules related to ACW and new action to Extract Information." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adds implementations of third-party evaluators, both managed-as-a-service and as templates within custom evaluators." + }, + { + "type": "feature", + "category": "Amazon Location Service Maps V2", + "contributor": "", + "description": "Amazon Location Service now supports POI density and category filtering on dynamic maps. The GetStyleDescriptor API adds two optional parameters. PoiDensity (Off to VeryDense) controls POI volume, and PoiCategories filters by up to nine categories. Available on HERE and Grab map styles." + }, + { + "type": "feature", + "category": "Elastic Disaster Recovery Service", + "contributor": "", + "description": "AWS Elastic Disaster Recovery (AWS DRS) now offers Recovery Plans to recover multi-server applications in the right order in one action. Define the launch sequence once, with ordered steps and wait times, and DRS runs it automatically. Validate with non-disruptive drills and monitor in real time." + } + ] +} \ No newline at end of file diff --git a/.changes/2.53.x/2.53.3.json b/.changes/2.53.x/2.53.3.json new file mode 100644 index 000000000000..45d049b589ab --- /dev/null +++ b/.changes/2.53.x/2.53.3.json @@ -0,0 +1,54 @@ +{ + "version": "2.53.3", + "date": "2026-08-18", + "entries": [ + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Doc release for CreateImage support for instances with local snapshots in Outpost" + }, + { + "type": "feature", + "category": "AWS Batch", + "contributor": "", + "description": "Update AWS Batch documentation with newer Fargate Supported configurations, notes, and fix broken Docker link re-directs." + }, + { + "type": "feature", + "category": "AWS Outposts", + "contributor": "", + "description": "AWS Outposts now supports VPC Endpoint configuration in CreatePrivateConnectivityConfig, enabling scoped private connectivity with provisioning role creation for secure outpost installations" + }, + { + "type": "feature", + "category": "AWS Elemental MediaLive", + "contributor": "", + "description": "AWS Elemental MediaLive now supports SCTE-35 marker passthrough without IDR frame insertion for CMAF Ingest, MediaPackage V2, and transport stream outputs." + }, + { + "type": "feature", + "category": "AWS Marketplace Catalog Service", + "contributor": "", + "description": "Introducing two new APIs, DescribeAssessment and ListAssessments. These APIs expose validation issues on Marketplace resources. The validation issues are exposed via a newly created resource called Assessment." + }, + { + "type": "feature", + "category": "AWS EntityResolution", + "contributor": "", + "description": "Added ResourceNotFoundException to DeleteSchemaMapping, DeleteMatchingWorkflow, DeleteIdMappingWorkflow, and DeleteIdNamespace. These operations now return a 404 ResourceNotFoundException (previously a 200 Success) when the target resource does not exist." + }, + { + "type": "feature", + "category": "Amazon WorkSpaces", + "contributor": "", + "description": "Amazon WorkSpaces now supports nested virtualization, allowing you to run hypervisors and virtualization-based workloads within your WorkSpaces. You can enable or disable nested virtualization when creating a WorkSpace or by modifying an existing WorkSpace's properties." + }, + { + "type": "feature", + "category": "S3 Transfer Manager", + "contributor": "", + "description": "Use CRT's response file when downloading to a file with the CRT-based S3TransferManager - CRT now writes the object to the destination file directly instead of streaming the body back through the SDK. Pausing such a download uses CRT's new asynchronous pause, so the resume token reflects a fully flushed file." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.0.json b/.changes/2.54.x/2.54.0.json new file mode 100644 index 000000000000..5a4c4ad7c539 --- /dev/null +++ b/.changes/2.54.x/2.54.0.json @@ -0,0 +1,84 @@ +{ + "version": "2.54.0", + "date": "2026-08-19", + "entries": [ + { + "type": "feature", + "category": "AWS Elemental MediaLive", + "contributor": "", + "description": "AWS Elemental MediaLive now supports video cropping and output positioning. Use cropRectangle and outputPositionRectangle to position the encoded video within the output frame, with the surrounding area filled with black." + }, + { + "type": "feature", + "category": "Redshift Serverless", + "contributor": "", + "description": "Amazon Redshift Enhanced System Table Retention that allows customers to store their system table data directly in S3 Tables in customer's account instead of Redshift Managed Storage" + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Cache auth scheme resolution results per operation" + }, + { + "type": "feature", + "category": "AWS Batch", + "contributor": "", + "description": "AWS Batch now supports managing CloudWatch Container Insights on compute environments via CreateComputeEnvironment and UpdateComputeEnvironment." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Add `SdkWarmUp` to warm up SDK request paths before a Coordinated Restore at Checkpoint (CRaC) checkpoint, including AWS Lambda SnapStart. `SdkWarmUp.warmUp()` warms every service client on the classpath. `SdkWarmUp.warmUp(Class...)` warms the service clients you name." + }, + { + "type": "feature", + "category": "Amazon Elastic Kubernetes Service", + "contributor": "", + "description": "Adds support for EKS cluster certificate authorities (CA)" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "AgentCore Memory now supports Flexible Namespaces" + }, + { + "type": "feature", + "category": "Amazon Redshift", + "contributor": "", + "description": "Amazon Redshift enhanced System Table retention that allows customers to store their system table data directly in S3 Tables in customer's account instead of Redshift Managed Storage" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "AgentCore Memory now supports Flexible Namespaces and Non-Conversational Payloads in CreateEvent API" + }, + { + "type": "feature", + "category": "Amazon VPC Lattice", + "contributor": "", + "description": "Amazon VPC Lattice now supports modification of private DNS options on Service Network VPC Associations" + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Enable compiled endpoint rules for all services by default, with a fix for region parameter handling in the generated endpoint providers." + }, + { + "type": "documentation", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Add the @SdkAdvancedApi annotation to generated, operation event stream response handlers." + }, + { + "type": "feature", + "category": "Account Access", + "contributor": "", + "description": "Adds throttling exceptions to operation outputs that were previously inconsistent with other operations." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.1.json b/.changes/2.54.x/2.54.1.json new file mode 100644 index 000000000000..9247e81d7ea7 --- /dev/null +++ b/.changes/2.54.x/2.54.1.json @@ -0,0 +1,66 @@ +{ + "version": "2.54.1", + "date": "2026-08-20", + "entries": [ + { + "type": "feature", + "category": "AWS Amplify", + "contributor": "", + "description": "Increased the maximum allowed length from 255 to 4,096 characters to support longer access tokens." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "EC2 marks UEFI instance metadata field as sensitive." + }, + { + "type": "feature", + "category": "AWS Batch", + "contributor": "", + "description": "AWS Batch now supports a new compute environment type that provides fully managed EC2 capacity with broader compute flexibility than Fargate, including GPU instances, bare metal, and specific instance type selection, without infrastructure management overhead." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Added IAM Identity Center (IdC) support to CreatePartnerApp and UpdatePartnerApp APIs. Added Customer Managed Key (CMK) support to CreateMlflowApp and DescribeMlflowApp." + }, + { + "type": "feature", + "category": "ARC - Region switch", + "contributor": "", + "description": "Adds support for Rds switchover read replica for Oracle databases in Region switch plans" + }, + { + "type": "feature", + "category": "PricingPlanManager", + "contributor": "", + "description": "Documentation update for the CreateSubscription API to correct the default value of the approval mode parameter. The default value for paid subscriptions is MANUAL, not IMMEDIATE as previously documented. The default value remains IMMEDIATE for FREE tier subscriptions." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "Adds support for full JSON resource-based policies, enabling customers to create, retrieve, update, and delete function resource policies as complete JSON documents." + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "Amazon SES now supports per-message tracking overrides. You can use the new ConfigurationOverrides parameter in SendEmail and SendBulkEmail to enable or disable open and click tracking for individual messages without changing your account-level or configuration set settings." + }, + { + "type": "feature", + "category": "Amazon CloudFront", + "contributor": "", + "description": "Added SigV4a as a supported signing protocol for Origin Access Control (OAC), enabling CloudFront to sign requests to Amazon S3 Multi-Region Access Point (S3-MRAP) origins." + }, + { + "type": "feature", + "category": "AWS Direct Connect", + "contributor": "", + "description": "This release adds custom route prefix pool allocations for Direct Connect. You can set IPv4 and IPv6 route prefix counts on private and transit virtual interfaces, and view pool size and unallocated counts on connections and LAGs, plus direct connect gateway attachment prefix allocation totals." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.10.json b/.changes/2.54.x/2.54.10.json new file mode 100644 index 000000000000..56e9d1bbc68e --- /dev/null +++ b/.changes/2.54.x/2.54.10.json @@ -0,0 +1,90 @@ +{ + "version": "2.54.10", + "date": "2026-09-01", + "entries": [ + { + "type": "feature", + "category": "Tax Settings", + "contributor": "", + "description": "France and Monaco Additional Info changes" + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Removed the legacy interpreted endpoint rules code generation path. Compiled endpoint rules are now the only supported path. This includes removing the `enableGenerateCompiledEndpointRules` customization flag from all services and deleting the old interpreted runtime resources." + }, + { + "type": "feature", + "category": "Amazon Kinesis", + "contributor": "", + "description": "Amazon Kinesis Data Streams now supports a dry run feature for data-plane APIs to validate the permissions and request parameters. If all checks complete successfully, the API returns a 'DryRunOperationException', confirming the request would have succeeded without the 'DryRun' parameter." + }, + { + "type": "feature", + "category": "AWS Marketplace Agreement Service", + "contributor": "", + "description": "This release adds renewal support for AWS Marketplace private offers. Agreements report whether they renew and, if not, why. Renewal terms add price increases, renewal limits, renewal decision deadlines, and payment schedule templates. SearchAgreements adds filters." + }, + { + "type": "feature", + "category": "Amazon GuardDuty", + "contributor": "", + "description": "Amazon GuardDuty now supports custom detection rules, including APIs to manage rule associations and organization-level configurations." + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "Added support for managing SMIME signing certificates for email identities, including associating, listing, and disassociating certificates. Added the UpdateConfigurationSet operation to configure message security options such as signing scheme." + }, + { + "type": "feature", + "category": "AWS Elemental MediaConvert", + "contributor": "", + "description": "Adds support for AAC passthrough. Adds ManifestCues option to support HLS manifest Cue marker passthrough. Adds playback device compatibility mode for DASH H.265 outputs. Adds TTML caption styling options. Adds interlace mode support for XAVC HD Intra CBG profile." + }, + { + "type": "feature", + "category": "Amazon Lightsail", + "contributor": "", + "description": "This release adds support for the Amazon Lightsail GetProfile API, which returns the profile for the specified account." + }, + { + "type": "feature", + "category": "AWS IoT SiteWise", + "contributor": "", + "description": "AWS IoT SiteWise Scenario Discovery now supports mounting Amazon S3 data directly into pipeline task containers via S3 Access Points, and configuring additional ephemeral storage per task. Mount configurations can be overridden at execution time. See the API guide for details." + }, + { + "type": "feature", + "category": "AWS Marketplace Discovery", + "contributor": "", + "description": "GetOfferTerms now returns renewalTerm for offers with pre-authorized renewals, exposing maxRenewals, lockoutPeriod, adjustmentDeadline, priceIncrease (fixed percentage or percentage range), and termTemplates (renewal payment schedules). Enables buyers to view renewal pricing and terms." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Update UserData and UploadPolicy shapes to use SecureBlob" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Online evaluation configurations now support up to 25 evaluators. CloudWatch Logs data sources for online evaluation now support up to 10 log groups." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "AWS Lambda now provides configurable control over S3 direct access, allowing you to explicitly enable or disable how functions stream file reads directly from S3 buckets. This gives you flexibility to tune data access behavior based on your workload requirements, independent of memory size." + }, + { + "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/2.54.x/2.54.11.json b/.changes/2.54.x/2.54.11.json new file mode 100644 index 000000000000..2faaef826a7a --- /dev/null +++ b/.changes/2.54.x/2.54.11.json @@ -0,0 +1,60 @@ +{ + "version": "2.54.11", + "date": "2026-09-02", + "entries": [ + { + "type": "feature", + "category": "Amazon SageMaker Feature Store Runtime", + "contributor": "", + "description": "Amazon SageMaker Feature Store now supports the UpdateRecord API, enabling partial updates to individual feature values in an existing Online Store record without rewriting the entire record. This reduces write payloads and latency for high-frequency feature-level writes ." + }, + { + "type": "feature", + "category": "AWS Elemental MediaLive", + "contributor": "", + "description": "AWS Elemental MediaLive now supports AB forensic video watermarking" + }, + { + "type": "feature", + "category": "Amazon AppIntegrations Service", + "contributor": "", + "description": "This release adds a force parameter to DeleteApplication and a ConflictException to UpdateApplication, letting customers delete applications with existing associations in one call and get a clear error when an update conflicts with the application's current state." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Batch evaluation now supports up to 10 CloudWatch log groups per CloudWatchLogsSource" + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "This release adds support to retain interruptible Capacity Reservations in an active state when all capacity is reclaimed." + }, + { + "type": "feature", + "category": "AmazonMWAA", + "contributor": "", + "description": "Enabled customers to clear optional S3 paths (plugins, requirements, and startup script) for their Amazon MWAA environments by accepting empty strings for the associated fields in UpdateEnvironment requests." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Amazon SageMaker Feature Store now supports the Standard V2 online store type, which enables feature-level writes to feature groups. You can select Standard V2 when creating a feature group, and update the storage type of an existing feature group via UpdateFeatureGroup." + }, + { + "type": "feature", + "category": "odb", + "contributor": "", + "description": "Adds the ListFlexComponents API for listing the flex components available for a given DB system shape." + }, + { + "type": "feature", + "category": "Application Migration Service", + "contributor": "", + "description": "AWS Transform for migrations adds a second network migration option - apply your source security posture to existing VPCs. Upload a source network file with firewall rules, tag the in-scope VPCs, and AWS Transform matches source subnets to them by CIDR and generates the security groups." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.12.json b/.changes/2.54.x/2.54.12.json new file mode 100644 index 000000000000..789426bac1e8 --- /dev/null +++ b/.changes/2.54.x/2.54.12.json @@ -0,0 +1,90 @@ +{ + "version": "2.54.12", + "date": "2026-09-03", + "entries": [ + { + "type": "feature", + "category": "Elastic Disaster Recovery Service", + "contributor": "", + "description": "AWS Elastic Disaster Recovery now includes source server architecture in SourceProperties to identify x86 and ARM64 systems." + }, + { + "type": "feature", + "category": "Elastic Load Balancing", + "contributor": "", + "description": "This release adds support for sending TCP resets for Gateway Load Balancer when a flow's idle timeout expires, or when a target becomes unhealthy or is deregistered. This adds updates the CLI documentation." + }, + { + "type": "feature", + "category": "Amazon EC2 Container Service", + "contributor": "", + "description": "Adds a critical parameter to the Amazon ECS managed daemon APIs that controls whether a daemon task failure drains the container instance. Non-critical daemon failures no longer drain the instance or block instance registration." + }, + { + "type": "feature", + "category": "AWS Transfer Family", + "contributor": "", + "description": "AWS Transfer Family SFTP Connectors now support specifying an ordered list of AWS Secrets Manager version stages for secret retrieval. This enables seamless credential rotation workflows where external partners may take time to update their systems with new credentials." + }, + { + "type": "feature", + "category": "AWS Step Functions", + "contributor": "", + "description": "Updates Step Functions API documentation around CloudTrail, Execution name reuse and sort order of ListExecutions API" + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "This release enables TagOnCreate for Rule resource on CreateRule API. It also introduces a new field called PreEvaluationFilters to Rule resource, thereby impacting all Create, Update, Describe and Search APIs for Rules" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "AgentCore Identity adds Consent Portal APIs to manage portals that let end users grant OAuth authorization for agents to access resources. AgentCore Evaluation adds trace source selection by log group prefix, custom or source log group result destinations, and metrics namespace customization." + }, + { + "type": "feature", + "category": "Amazon Elastic Kubernetes Service", + "contributor": "", + "description": "Deprecate EncryptionConfig resources field. Amazon EKS encrypts all Kubernetes API data with envelope encryption by default for clusters running Kubernetes version 1.28 or higher, so this field no longer affects which resources are encrypted." + }, + { + "type": "feature", + "category": "Amazon Transcribe Service", + "contributor": "", + "description": "Amazon Transcribe now supports specifying up to 29 PII entity types in the ContentRedaction configuration of a StartTranscriptionJob request, allowing all supported entity types to be redacted in a single batch transcription job." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fix `ApiCallDuration` so that it measures the whole API call. It previously started after marshalling had already completed, and on asynchronous clients it also started after endpoint resolution, auth scheme resolution, request compression and checksum computation, and so understated the reported duration. The metric is now measured identically for synchronous and asynchronous clients and matches the documented formula. Reported `ApiCallDuration` values will increase but do not reflect changes in actual round-trip latency." + }, + { + "type": "feature", + "category": "AWS End User Messaging Social", + "contributor": "", + "description": "Adding support for WhatsApp Flows with endpoints." + }, + { + "type": "feature", + "category": "Amazon GuardDuty", + "contributor": "", + "description": "Adding support for Sequence Activities in GuardDuty Findings" + }, + { + "type": "feature", + "category": "Amazon Elastic VMware Service", + "contributor": "", + "description": "Amazon EVS now allows users to set, update, and retrieve values for parameters that apply across all EVS Environments in their account at a regional level, such as the VCF License portability core count." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Adds log group name prefix trace source selection, custom or source log group result destinations, and metrics namespace customization" + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.13.json b/.changes/2.54.x/2.54.13.json new file mode 100644 index 000000000000..f562addb3ab4 --- /dev/null +++ b/.changes/2.54.x/2.54.13.json @@ -0,0 +1,36 @@ +{ + "version": "2.54.13", + "date": "2026-09-04", + "entries": [ + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Add support for code generating Endpoint Resolvers based on BDD rather than rules. Adds single element endpoint cache to generated BDD based resolvers. BDD based Endpoint Resolvers are generated only when the BDD model is present on a service." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Adds support for ValidateSecurityGroupQuotasForInterface, an API that specifically authorized AWS services use to validate security group rule quotas before creating an elastic network interface." + }, + { + "type": "feature", + "category": "AWS MediaTailor", + "contributor": "", + "description": "Elemental MediaTailor now supports two new Monetization Functions lifecycle hooks, Post Ads Response and Pre Manifest Insertion, and a VAST Request function type that calls a VAST or VMAP ad server. This release also adds Yield Optimization with demand from Amazon Publisher Services." + }, + { + "type": "feature", + "category": "Amazon Bedrock", + "contributor": "", + "description": "New AWS REVIEW mode as supported data retention mode for Bedrock models" + }, + { + "type": "feature", + "category": "Service Quotas", + "contributor": "", + "description": "Service Quotas adds the AdjustableAtLevel property to QuotaContext, indicating whether a quota is adjustable at the account or resource level." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.14.json b/.changes/2.54.x/2.54.14.json new file mode 100644 index 000000000000..7673f2af72db --- /dev/null +++ b/.changes/2.54.x/2.54.14.json @@ -0,0 +1,90 @@ +{ + "version": "2.54.14", + "date": "2026-09-08", + "entries": [ + { + "type": "bugfix", + "category": "URL Connection HTTP Client", + "contributor": "", + "description": "Allow retries when the URL Connection HTTP Client encounters an IOException or NullPointerException while accessing request or response body streams." + }, + { + "type": "feature", + "category": "S3 Event Notification", + "contributor": "", + "description": "Add support for ObjectRetention to S3EventNotifications." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Add support for InstancePreferences list for multiple instance type input support on SageMaker Training and Processing" + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Releasing workload types feature. A proper launch announcement or details will follow up." + }, + { + "type": "feature", + "category": "Amazon Pinpoint SMS Voice V2", + "contributor": "", + "description": "This feature will allow customers to specify an area-code when requesting a 10DLC number. Why it matters- Customers can now select a number that matches where their business is located." + }, + { + "type": "feature", + "category": "Application Migration Service", + "contributor": "", + "description": "This release adds support for configuring the EBS volume initialization rate and delete on termination behavior in launch configuration template" + }, + { + "type": "feature", + "category": "AWS S3 Control", + "contributor": "", + "description": "Adds support for Amazon S3 Object Lock variable retention. Existing S3 APIs that support S3 Object Lock parameters now support two new parameters EventHold and EventHoldDuration at the object level, and DefaultEventHoldDuration at the bucket level." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Prevent `AsyncResponseTransformer.toFile` from deleting a pre-existing destination when a request fails before the SDK opens the file. Calls using `CREATE_NEW` now preserve the existing file and surface `FileAlreadyExistsException` instead of allowing a retry to overwrite it." + }, + { + "type": "feature", + "category": "Amazon Simple Storage Service", + "contributor": "", + "description": "Adds support for Amazon S3 Object Lock variable retention. Existing S3 APIs that support S3 Object Lock parameters now support two new parameters EventHold and EventHoldDuration at the object level, and DefaultEventHoldDuration at the bucket level." + }, + { + "type": "feature", + "category": "Amazon Omics", + "contributor": "", + "description": "Added support for session policies in AWS HealthOmics Workflows, allowing customers to scope down IAM permissions for individual workflow runs without modifying the service role." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Adds the InterfaceTypes field to NetworkCardInfo in the DescribeInstanceTypes response. This field identifies the network interface types supported by each network card." + }, + { + "type": "feature", + "category": "Amazon Appflow", + "contributor": "", + "description": "Amazon AppFlow now supports key pair (RSA private key) authentication for the Snowflake connector. You can provide a privateKey in SnowflakeConnectorProfileCredentials, and password is no longer required. This is a non-breaking, additive change available via the AWS SDK and CLI." + }, + { + "type": "feature", + "category": "AWS CloudTrail", + "contributor": "", + "description": "Adds support for the RecursiveLogging trail setting, which suppresses recursive events generated when CloudTrail delivers logs to a trail's destinations." + }, + { + "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/2.54.x/2.54.15.json b/.changes/2.54.x/2.54.15.json new file mode 100644 index 000000000000..3a626b0c6c22 --- /dev/null +++ b/.changes/2.54.x/2.54.15.json @@ -0,0 +1,66 @@ +{ + "version": "2.54.15", + "date": "2026-09-09", + "entries": [ + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "cthiebault", + "description": "Fixed an intermittent NullPointerException when downloading a single-part object with a multipart-enabled async S3 client. A race between the emit loop and subscription cancellation could dereference a cleared subscriber reference; the reference is now stable and reads are null-safe." + }, + { + "type": "deprecation", + "category": "Apache HTTP Client", + "contributor": "", + "description": "`apache-client` is now deprecated in favor of `apache5-client`. [Apache HttpClient 4.x](https://hc.apache.org/status.html) is in maintenance mode, receiving fixes only for major defects and security issues." + }, + { + "type": "feature", + "category": "AWS Lambda", + "contributor": "", + "description": "Updates documentation for lambda function timeout." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "This release adds support for sharing Amazon EBS volumes across AWS accounts using AWS Resource Access Manager (RAM). Consuming accounts can view shared volume metadata and create copies of shared volumes within the same Availability Zone, with optional re-encryption using their own KMS key." + }, + { + "type": "feature", + "category": "AWS Elemental MediaPackage v2", + "contributor": "", + "description": "Dynamic Multiview enables viewers to watch multiple live video streams in a single combined output. Viewers can select from 6 preset tiled layouts. Create MediaPackage channels with Input Type MULTIVIEW and configure Available Layouts and Available Sources. See the API Documentation for details." + }, + { + "type": "feature", + "category": "AWS MediaTailor", + "contributor": "", + "description": "Added the AWS Service Request function type for MediaTailor Functions, enabling authenticated requests to AWS Elemental Inference for contextual ad targeting during ad insertion." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Add metric configuration field to evaluation forms and ListEvaluationFormAIVersions API for retrieving AI-generated evaluation form versions" + }, + { + "type": "feature", + "category": "AWS Elemental MediaLive", + "contributor": "", + "description": "MediaLive now supports Manual Style Control for vertical caption positioning in TTML, WebVTT, and Embedded captions, Contextual Metadata Enrichment via Elemental Inference, and an Output Usage field on MediaPackage v2 for Dynamic Multiview validation." + }, + { + "type": "feature", + "category": "AWS Parallel Computing Service", + "contributor": "", + "description": "This release adds support for custom Gres.conf configuration and Slurm version 26.05 in AWS PCS. Customers can now specify generic resource (GRES) settings to control how GPUs and other resources are configured and shared on their compute node groups." + }, + { + "type": "feature", + "category": "AWS Elemental Inference", + "contributor": "", + "description": "This release adds contextual metadata, a feed output type that generates a descriptive summary of your media content along with IAB taxonomy and GARM suitability classifications. It also adds feed resource policies for granting cross-account access to a feed." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.16.json b/.changes/2.54.x/2.54.16.json new file mode 100644 index 000000000000..a0669485888f --- /dev/null +++ b/.changes/2.54.x/2.54.16.json @@ -0,0 +1,54 @@ +{ + "version": "2.54.16", + "date": "2026-09-10", + "entries": [ + { + "type": "feature", + "category": "AWS Resilience Hub V2", + "contributor": "", + "description": "This release adds the ListTestRunSourceEvents and ListTestRunDependencies APIs, which return the alarm state changes during a test run and the dependencies the run blocked." + }, + { + "type": "feature", + "category": "Agents for Amazon Bedrock", + "contributor": "", + "description": "TwelveLabs Marengo 3.0 is now an embedding model option in Amazon Bedrock Managed Knowledge Base. Create multimodal embeddings for video, audio, and image content that capture visual scenes, speech, and video cues, not just transcribed text." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Enable BDD Endpoints for a small subset of services." + }, + { + "type": "feature", + "category": "AWS Outposts", + "contributor": "", + "description": "Added fields to identify Outpost generation and rack scaling configuration on Outpost and CatalogItem resources." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "The CreateImage API now supports a BootModeOverride parameter to explicitly set UEFI boot mode on a new AMI, overriding the source instance's inherited boot mode." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "This release adds the ability for customers to attach customer owned Elastic Network Interfaces (ENIs) to HyperPod cluster nodes." + }, + { + "type": "feature", + "category": "RTBFabric", + "contributor": "", + "description": "AWS RTB Fabric now lets you control how traffic is routed to your responder gateway across Availability Zones. Set the new clientRoutingPolicy parameter to keep traffic within the same Availability Zone or distribute traffic across all Availability Zones." + }, + { + "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/2.54.x/2.54.17.json b/.changes/2.54.x/2.54.17.json new file mode 100644 index 000000000000..744ff18a3a79 --- /dev/null +++ b/.changes/2.54.x/2.54.17.json @@ -0,0 +1,60 @@ +{ + "version": "2.54.17", + "date": "2026-09-11", + "entries": [ + { + "type": "bugfix", + "category": "Amazon S3", + "contributor": "", + "description": "Prevent the CRT-based S3 async client from replacing a pre-existing destination when using `getObject(request, Path)`. Failed or cancelled downloads now delete files they create. Existing destinations surface `FileAlreadyExistsException`; callers that require replacement can use `AsyncResponseTransformer.toFile` with `FileTransformerConfiguration.defaultCreateOrReplaceExisting()`. This fixes an inconsistency introduced in 2.32.11." + }, + { + "type": "feature", + "category": "Amazon EC2 Container Service", + "contributor": "", + "description": "This feature adds support for setting the cpu architecture type that should be used to launch tasks for an Express Gateway Service." + }, + { + "type": "feature", + "category": "Amazon Simple Storage Service", + "contributor": "", + "description": "Updated S3 Object Lock Default Retention documentation." + }, + { + "type": "feature", + "category": "AWS Batch", + "contributor": "", + "description": "Added new bulk job APIs (CancelJobs, TerminateJobs, TerminateServiceJobs) and new fields on ListJobs and ListServiceJobs responses. This allows customers to cancel or terminate multiple jobs in a single request. ListJobs and ListServiceJobs responses now include isCancelled and isTerminated fields." + }, + { + "type": "feature", + "category": "AWS Invoicing", + "contributor": "", + "description": "Add ListProcurementPortals and ListProcurementPortalSuppliers APIs to retrieve AWS-supported 3rd party procurement portals and their suppliers for e-invoice delivery and purchase order retrieval." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Upgrade Netty to 4.1.138" + }, + { + "type": "feature", + "category": "AWS Elemental MediaConvert", + "contributor": "", + "description": "Adds Dolby Vision metadata to Probe results, including profile, level, and presence of the RPU, base layer, and enhancement layer. Adds video sample and display aspect ratios. Adds the UnprocessableEntityException (HTTP 422) error to Probe for recognized but malformed or corrupt inputs." + }, + { + "type": "feature", + "category": "Amazon Lightsail", + "contributor": "", + "description": "Amazon Lightsail now lets you serve website content from a private Lightsail bucket through a Lightsail distribution. This release adds enablePrivateOriginAccess to the CreateDistribution and UpdateDistribution actions, plus new defaultRootObject and customErrorResponses options." + }, + { + "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/2.54.x/2.54.18.json b/.changes/2.54.x/2.54.18.json new file mode 100644 index 000000000000..0186e0c4a7e1 --- /dev/null +++ b/.changes/2.54.x/2.54.18.json @@ -0,0 +1,54 @@ +{ + "version": "2.54.18", + "date": "2026-09-14", + "entries": [ + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Amazon Glue releasing the new API ListIntegrationTableProperties and adding IntegrationArn to TargetTableConfig" + }, + { + "type": "feature", + "category": "AWS CodeDeploy", + "contributor": "", + "description": "AWS CodeDeploy now returns the deployment mode on GetDeployment and BatchGetDeployments. The new deploymentMode field on DeploymentInfo indicates whether a deployment used the standard deployment process or restarted the application using a previously installed revision (RESTART mode)." + }, + { + "type": "feature", + "category": "AWS Security Token Service", + "contributor": "", + "description": "Increases the maximum session token size to 4,096 bytes and removes the packed policy size limit. Adds SessionTokenSize and SessionTokenUtilization fields and a new MinimumSessionTokenSize parameter. PackedPolicySize is deprecated." + }, + { + "type": "perf-improvement", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fix request-side performance regression that scaled with payload size for `query` and `ec2` protocol services where the request endpoint was re-parsed as a URI. The internal `HTTP_REQUEST_URI_BEFORE_MODIFY` execution attribute is now deprecated and computed on demand from `HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY`; the value the SDK records carries the scheme, host, port and path but no query string." + }, + { + "type": "feature", + "category": "EC2 Image Builder", + "contributor": "", + "description": "This release adds a dryRun option to Image Builder create APIs (except CreateImage), structured failure context on failed images including component and distribution failure details, and step retry attempt tracking." + }, + { + "type": "feature", + "category": "AWSBillingConductor", + "contributor": "", + "description": "This release adds support for custom volume tiering. You can now define custom tiers on a pricing rule's tiering configuration, where each tier specifies a usage range and the rate applied to usage in that range." + }, + { + "type": "feature", + "category": "AWS Billing", + "contributor": "", + "description": "Increased the maximum number of services returned in the supportEligibleSpendByService field of ListEnterpriseSupportLinkedAccountCharges" + }, + { + "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/2.54.x/2.54.19.json b/.changes/2.54.x/2.54.19.json new file mode 100644 index 000000000000..026683039655 --- /dev/null +++ b/.changes/2.54.x/2.54.19.json @@ -0,0 +1,30 @@ +{ + "version": "2.54.19", + "date": "2026-09-15", + "entries": [ + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Amazon Bedrock AgentCore Runtime now supports specifying the platform version of an agent runtime through the new platformVersion field on CreateAgentRuntime, UpdateAgentRuntime, and GetAgentRuntime." + }, + { + "type": "feature", + "category": "AWS Transfer Family", + "contributor": "", + "description": "AWS Transfer Family now preserves the original source IP address using Proxy Protocol v2 when you place a Network Load Balancer in front of your server for SFTP connections." + }, + { + "type": "feature", + "category": "Amazon WorkSpaces", + "contributor": "", + "description": "Added support for 4 new graphics-optimized compute types - Graphics.g7 (2xlarge, 4xlarge, 8xlarge, 12xlarge)." + }, + { + "type": "feature", + "category": "AWS Direct Connect", + "contributor": "", + "description": "AWS Direct Connect is introducing flat-rate pricing, a simplified billing model that gives you a fixed monthly price for dedicated connectivity with no per-gigabyte data transfer out charges within the selected pricing tier." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.2.json b/.changes/2.54.x/2.54.2.json new file mode 100644 index 000000000000..bdff11d54147 --- /dev/null +++ b/.changes/2.54.x/2.54.2.json @@ -0,0 +1,66 @@ +{ + "version": "2.54.2", + "date": "2026-08-21", + "entries": [ + { + "type": "feature", + "category": "AWS WAFV2", + "contributor": "", + "description": "DataProtectionConfig field Key Documentation Update" + }, + { + "type": "bugfix", + "category": "Netty NIO HTTP Client", + "contributor": "", + "description": "Fix `NettyNioAsyncHttpClient` errors when making requests in GraalVM native images, which can lead to timeout exceptions." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Increase spans count from 1k to 20k" + }, + { + "type": "feature", + "category": "AWS Backup", + "contributor": "", + "description": "Updating CLI Docs for Backup Audit Manager List Job Summaries APIs." + }, + { + "type": "feature", + "category": "AWS Device Farm", + "contributor": "", + "description": "Added support to CreateRemoveAccessSession for selecting a server version on the mobile WebDriver endpoint." + }, + { + "type": "feature", + "category": "Amazon CloudWatch", + "contributor": "", + "description": "Allows customers to specify an initial warm up period to wait for metrics to arrive when creating metric or log alarms" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Update Dataset schema to THIRDPARTYEVALUATIONV1" + }, + { + "type": "bugfix", + "category": "Netty NIO HTTP Client", + "contributor": "", + "description": "Fixed a `NullPointerException` in `HandlerSubscriber` that could intermittently fail async requests (such as S3 `PutObject`/`UploadPart`) when a channel writability change occurred during the `Expect: 100-continue` window before the request body subscription was established. See [#7271](https://github.com/aws/aws-sdk-java-v2/issues/7271)." + }, + { + "type": "feature", + "category": "Amazon Kinesis", + "contributor": "", + "description": "Generate account endpoint for Kinesis Data Streams requests when the account ID is available" + }, + { + "type": "feature", + "category": "Netty NIO HTTP Client", + "contributor": "", + "description": "Add support for Kerberos (SPNEGO) proxy authentication via the new `proxyAuthScheme` option on the Netty client's `ProxyConfiguration`. Setting `ProxyAuthScheme.NEGOTIATE` authenticates proxy CONNECT tunnels using the Kerberos ticket cache in the environment; a valid ticket-granting ticket must already exist (for example via `kinit`), and no password or keytab is read. `ProxyAuthScheme.BASIC` may also be set to select Basic authentication explicitly. See [#7033](https://github.com/aws/aws-sdk-java-v2/issues/7033)." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.20.json b/.changes/2.54.x/2.54.20.json new file mode 100644 index 000000000000..81ca9ae7ceed --- /dev/null +++ b/.changes/2.54.x/2.54.20.json @@ -0,0 +1,84 @@ +{ + "version": "2.54.20", + "date": "2026-09-16", + "entries": [ + { + "type": "perf-improvement", + "category": "Amazon S3 Outposts", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "perf-improvement", + "category": "Amazon S3 Tables", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Adds support for a new DELETE FAILED status for Bedrock AgentCore Runtimes and Bedrock AgentCore Runtime Endpoints." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Adds support for ContactAnalysis via ListContactReferences." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Releasing new EC2 R9g and R9gd memory-optimized instances powered by AWS Graviton5 processors, with up to 25 percent better compute performance than R8g instances, faster DDR5 memory, and up to 100 Gbps network and 72 Gbps EBS bandwidth. R9gd instances additionally provide local NVMe SSD storage." + }, + { + "type": "feature", + "category": "AWS Resilience Hub V2", + "contributor": "", + "description": "Next Gen Resilience Hub now supports dependency insights (LLM-based insights about customer's service dependencies) and organization-level policy sharing (provision to share policy with member accounts for an organization)" + }, + { + "type": "feature", + "category": "AWS Marketplace Catalog Service", + "contributor": "", + "description": "This release enhances the ListEntities API to support issuerAccountId and SourceAuthorization filter for ResaleAuthorization entity." + }, + { + "type": "perf-improvement", + "category": "Amazon S3 Files", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "perf-improvement", + "category": "Amazon S3 Vectors", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "perf-improvement", + "category": "Amazon S3 Control", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "perf-improvement", + "category": "Amazon S3", + "contributor": "", + "description": "Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved" + }, + { + "type": "feature", + "category": "AWS Elastic Beanstalk", + "contributor": "", + "description": "Adds support to create and manage Elastic Beanstalk Cluster Environments." + }, + { + "type": "feature", + "category": "Amazon Connect Customer Profiles", + "contributor": "", + "description": "This release introduces the SearchRecommendations API, which retrieves recommendations for a profile identified by a search key." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.3.json b/.changes/2.54.x/2.54.3.json new file mode 100644 index 000000000000..e64c163215da --- /dev/null +++ b/.changes/2.54.x/2.54.3.json @@ -0,0 +1,66 @@ +{ + "version": "2.54.3", + "date": "2026-08-24", + "entries": [ + { + "type": "feature", + "category": "AWS Security Agent", + "contributor": "", + "description": "Adding private and self-signed certificate configuration support for penetration tests" + }, + { + "type": "feature", + "category": "Timestream InfluxDB", + "contributor": "", + "description": "Service-managed parameter groups now only apply optimized defaults to DB Clusters automatically. New field effectiveDbParameterGroupIdentifier surfaces the parameter group actually applied." + }, + { + "type": "feature", + "category": "Managed Streaming for Kafka", + "contributor": "", + "description": "Amazon MSK Replicator now supports OAuth authentication when connecting to external Apache Kafka clusters, enabling customers to replicate data from clusters that require OAuth for client authentication. This new capability is supported in all AWS Regions where MSK Express brokers are available." + }, + { + "type": "feature", + "category": "AWS Elemental Inference", + "contributor": "", + "description": "Added support for the GetFixture API, enabling customers to retrieve the details of a fixture from its fixture ID, and added the access role ARN to the CreateFeed, GetFeed, and UpdateFeed responses." + }, + { + "type": "feature", + "category": "AWS Launch Wizard", + "contributor": "", + "description": "Added accountConstraints and patternType to GetWorkload, ListWorkloads, GetWorkloadDeploymentPattern and ListWorkloadDeploymentPatterns for Launch Wizard" + }, + { + "type": "feature", + "category": "Amazon Aurora DSQL", + "contributor": "", + "description": "Corrected the validation pattern on the ServiceName response field in the GetVpcEndpointServiceName API to match the values Amazon Aurora DSQL actually returns." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "This release adds the ExtractedInformation segment to the ListRealtimeContactAnalysisSegmentsV2 API, enabling customers to retrieve information extracted from real-time contact analysis." + }, + { + "type": "feature", + "category": "Amazon Bedrock", + "contributor": "", + "description": "Adds support for specifying an inference profile ID or ARN, or an application inference profile ARN as the target model in CreateAdvancedPromptOptimizationJob." + }, + { + "type": "feature", + "category": "Amazon Connect Contact Lens", + "contributor": "", + "description": "This release adds the ExtractedInformation segment to the ListRealtimeContactAnalysisSegments API, enabling customers to retrieve information extracted from real-time contact analysis." + }, + { + "type": "feature", + "category": "AWS Batch", + "contributor": "", + "description": "Doc Update, Add note that UpdatePolicy applies only to EC2 managed compute environments" + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.4.json b/.changes/2.54.x/2.54.4.json new file mode 100644 index 000000000000..55ca763bfe19 --- /dev/null +++ b/.changes/2.54.x/2.54.4.json @@ -0,0 +1,72 @@ +{ + "version": "2.54.4", + "date": "2026-08-25", + "entries": [ + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "Se3do", + "description": "Extract the duplicated resolveMetricPublishers generator into ClientClassUtils, removing verbatim duplication across the sync and async client generators. No change to generated client code or SDK behavior." + }, + { + "type": "bugfix", + "category": "Amazon SQS", + "contributor": "", + "description": "Fixed `SqsAsyncBatchManager.close()` re-sending the same buffered batch in a busy loop. On close, each buffered batch (including partial batches) is now flushed exactly once, and close waits a bounded timeout (approximately 5 seconds) for in-flight batch sends to complete so their callers receive the real result instead of a cancellation." + }, + { + "type": "feature", + "category": "AWSMarketplace Metering", + "contributor": "", + "description": "Updated documentation to clarify duplicate-billing prevention and BatchMeterUsage retry guidance" + }, + { + "type": "feature", + "category": "Amazon Elastic VMware Service", + "contributor": "", + "description": "EVS now supports i7i.metal-48xl EC2 bare metal instance type, delivering high random IOPS performance with real-time latency, ideal for IO intensive and latency-sensitive workloads such as transactional databases, real-time analytics, and AI ML pre-processing." + }, + { + "type": "feature", + "category": "IAM Toolbox (Preview)", + "contributor": "", + "description": "AWS Identity and Access Management (IAM) announces access troubleshooter, helping you debug access denied errors faster. Supported error messages now include an identifier you can use to retrieve detailed evaluations of the policies considered and their results. Preview in US East (N. Virginia)." + }, + { + "type": "feature", + "category": "Amazon Elastic Kubernetes Service", + "contributor": "", + "description": "This feature would give customers the ability to tune TerminatedPodGcThreshold configuration in an Amazon EKS cluster." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fix an issue where futures from the async SDK clients don't complete with an exception when the client or its [scheduled executor service](https://docs.aws.amazon.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#scheduledExecutorService()) is closed. See [#7313](https://github.com/aws/aws-sdk-java-v2/issues/7313) for more details." + }, + { + "type": "feature", + "category": "Auto Scaling", + "contributor": "", + "description": "Adds support for Distribution Segments in mixed instances policies, providing ordered prioritization across On-Demand Capacity Reservations, Capacity Blocks, interruptible Capacity Reservations, and On-Demand capacity." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Fleet feature to support Capacity Reservation Resource Groups with Amazon EC2 Capacity Blocks and interruptible Capacity Reservations" + }, + { + "type": "feature", + "category": "AWS DevOps Agent Service", + "contributor": "", + "description": "Adds the UpdateApprovalAction API for resolving agent action approvals in AWS DevOps Agent agent spaces." + }, + { + "type": "feature", + "category": "AWS IoT", + "contributor": "", + "description": "As part of this release, we are extending capability of AWS IoT Rules Engine to support IoT InfluxDB Action. The IoT InfluxDB action lets customers send messages from IoT sensors and applications to InfluxDB." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.5.json b/.changes/2.54.x/2.54.5.json new file mode 100644 index 000000000000..ecc0bd295627 --- /dev/null +++ b/.changes/2.54.x/2.54.5.json @@ -0,0 +1,54 @@ +{ + "version": "2.54.5", + "date": "2026-08-26", + "entries": [ + { + "type": "bugfix", + "category": "AWS CRT Async HTTP Client", + "contributor": "", + "description": "Fixed an issue where an error signaled by a request body publisher was printed to stderr on a CRT event loop thread instead of failing the request with the original error." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Amazon SageMaker AI now supports ml.g7 instances for model optimization. You can now run model optimization jobs on ml.g7 instances, in supported AWS Regions." + }, + { + "type": "feature", + "category": "AWS License Manager User Subscriptions", + "contributor": "", + "description": "Released support for License Expiry field in ListProductSubscriptions API" + }, + { + "type": "bugfix", + "category": "AWS CRT-based S3 Client", + "contributor": "", + "description": "Fixed an issue where an error signaled by a request body publisher (for example via `AsyncRequestBody.fromPublisher`) was printed to stderr on a CRT event loop thread instead of failing the operation; the operation's future now completes with the original publisher error. See [#6715](https://github.com/aws/aws-sdk-java-v2/issues/6715)." + }, + { + "type": "feature", + "category": "AWS Network Firewall", + "contributor": "", + "description": "Adding new status enum for Firewalls." + }, + { + "type": "feature", + "category": "AWS DevOps Agent Service", + "contributor": "", + "description": "AWS DevOps Agent now supports trigger filter groups for Release Readiness Review, letting you control when the capability auto-triggers based on webhook events and target branches." + }, + { + "type": "bugfix", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Fixed an issue where an error thrown while reading the request body stream was printed to stderr on a CRT event loop thread instead of failing the request with the original error. See [#6715](https://github.com/aws/aws-sdk-java-v2/issues/6715)." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Adds deleting state to possible VPC States." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.6.json b/.changes/2.54.x/2.54.6.json new file mode 100644 index 000000000000..9037a1e0d6ca --- /dev/null +++ b/.changes/2.54.x/2.54.6.json @@ -0,0 +1,54 @@ +{ + "version": "2.54.6", + "date": "2026-08-27", + "entries": [ + { + "type": "feature", + "category": "Amazon Relational Database Service", + "contributor": "", + "description": "Adding support for the full snapshot size, in bytes, of DB instance snapshots." + }, + { + "type": "feature", + "category": "AWS CodeDeploy", + "contributor": "", + "description": "Added a deploymentMode parameter to CreateDeployment. Set it to RESTART to restart an EC2 and on-premises fleet, using the last successful revision, honoring Deployment Configuration." + }, + { + "type": "feature", + "category": "Amazon CloudWatch Logs", + "contributor": "", + "description": "Added resultCount to QueryStatistics in GetQueryResults. This field returns the total number of output rows in the final result set, helping customers programmatically determine whether a query produced results after all operations including post-aggregation filters." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "EC2 allows AMI owners to define compatible instance types on their AMIs, blocking RunInstances calls automatically for launches on non-permitted instance types." + }, + { + "type": "feature", + "category": "Amazon OpenSearch Service", + "contributor": "", + "description": "Updating SDK and CLI documentation for AttachDataSource API." + }, + { + "type": "feature", + "category": "Amazon DataZone", + "contributor": "", + "description": "Add cascadeDelete to DeleteDomain. When specified, DataZone recursively deletes all projects, environments, subscriptions, and their underlying AWS resources before removing the domain. Deletion progress is reported via deleteProgress and resource failures via failureReasons on GetDomain." + }, + { + "type": "feature", + "category": "Lambda MicroVMs", + "contributor": "", + "description": "Added InsufficientCapacityException to RunMicrovm for capacity-related failures. Added lifecycle status field (AVAILABLE, DEPRECATED) to ListManagedMicrovmImageVersions. Added ConflictException to CreateMicrovmAuthToken and CreateMicrovmShellAuthToken for unregistered MicroVMs." + }, + { + "type": "feature", + "category": "Amazon Cognito Identity Provider", + "contributor": "", + "description": "Adds the AdminDeleteSoftwareToken API operation, enabling administrators to remove a user's registered TOTP (software token) MFA configuration from a user pool." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.7.json b/.changes/2.54.x/2.54.7.json new file mode 100644 index 000000000000..c6d31283bc3e --- /dev/null +++ b/.changes/2.54.x/2.54.7.json @@ -0,0 +1,48 @@ +{ + "version": "2.54.7", + "date": "2026-08-28", + "entries": [ + { + "type": "feature", + "category": "Amazon Cognito Identity Provider", + "contributor": "", + "description": "Adds two new operations - GetClientToken which allows M2M auth through the SDK, and DescribeTermsByClient to find which Terms are associated with a user-pool client without knowing the Terms resource id." + }, + { + "type": "feature", + "category": "Agents for Amazon Bedrock", + "contributor": "", + "description": "Adds an optional syncSchedule field to CreateDataSource and UpdateDataSource for Managed Knowledge Bases data source connectors, so a data source can sync automatically on a daily, weekly, or monthly schedule." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "AgentCore Memory now supports direct ingestion into long-term memory via IngestData API" + }, + { + "type": "feature", + "category": "Partner Central Selling API", + "contributor": "", + "description": "Releasing PARC, new APN Program that lets sellers add solftware revenue details to aws opportunity summary" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Reduce memory allocations for non-streaming requests made with asycn clients." + }, + { + "type": "feature", + "category": "Amazon EC2 Container Service", + "contributor": "", + "description": "Amazon Elastic Container Service - This release adds support for early success criteria on ECS rolling deployments, letting deployment complete once a configurable percentage of tasks are healthy, with configurable BLOCKING (required) or DEFERRED (asynchronous) cleanup of previous service revisions." + }, + { + "type": "feature", + "category": "Amazon HealthLake", + "contributor": "", + "description": "New HealthLake API, RestoreFHIRDatastore, providing the capability to restore active datastores to a point in time within the last 30 days or recover a deleted datastore from the delete snapshot." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.8.json b/.changes/2.54.x/2.54.8.json new file mode 100644 index 000000000000..17d614874162 --- /dev/null +++ b/.changes/2.54.x/2.54.8.json @@ -0,0 +1,84 @@ +{ + "version": "2.54.8", + "date": "2026-08-31", + "entries": [ + { + "type": "feature", + "category": "Agent Registry", + "contributor": "", + "description": "AWS Agent Registry becomes Generally Available" + }, + { + "type": "feature", + "category": "AWS DevOps Agent Service", + "contributor": "", + "description": "Adds support for Slack bidirectional communication configuration in AWS DevOps Agent agent spaces." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "This release adds support for managing apps in Amazon QuickSight with ListApps, SearchApps, DescribeApp, DescribeAppPermissions, UpdateAppPermissions, and DeleteApp" + }, + { + "type": "feature", + "category": "Amazon Workspaces Instances", + "contributor": "", + "description": "Amazon WorkSpaces Core managed instances now support nested virtualization. Customers can enable nested virtualization with supported instance types at launch via CpuOptions.NestedVirtualization in CreateWorkspaceInstance to run hypervisors and virtual machines inside their WorkSpaces Instance." + }, + { + "type": "feature", + "category": "AWS Control Tower", + "contributor": "", + "description": "Updated the descriptions for the AWS Control Tower ListEnabledControls API parameters to make them more accurate and intuitive." + }, + { + "type": "feature", + "category": "Agent Registry Control", + "contributor": "", + "description": "AWS Agent Registry becomes Generally Available" + }, + { + "type": "feature", + "category": "Amazon Kinesis", + "contributor": "", + "description": "Adds support for data delivery to Amazon S3 Tables (Apache Iceberg) and general purpose Amazon S3 buckets with new CreateChannel, UpdateChannel, DeleteChannel, DescribeChannel, and ListChannels APIs for Amazon Kinesis Data Streams." + }, + { + "type": "feature", + "category": "Managed Streaming for Kafka Connect", + "contributor": "", + "description": "Amazon MSK Connect now supports restarting newly created connectors via the asynchronous RestartConnector API. Restart all tasks or only failed tasks, while preserving configuration and committed offsets. This returns a connector operation ARN that you can track with DescribeConnectorOperation." + }, + { + "type": "feature", + "category": "AWS Support", + "contributor": "", + "description": "AWS Support now allows up to 10 attachments (150 MB each) per case correspondence, up from 3 at 5 MB. Customers can share large diagnostic logs, heap dumps, and packet captures directly in cases to reduce back-and-forth and speed up resolution. Available in US East, US West, and Europe (Ireland)." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Amazon SageMaker Batch Transform now supports G6e instances, powered by NVIDIA L40S Tensor Core GPUs. G6e instances are the most cost-efficient GPU instances for deploying generative AI models and the highest-performance GPU instances for spatial computing workloads." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Added support for global routing on Amazon Connect Global Resiliency instances. New APIs GetCrossRegionRouting and UpdateCrossRegionRouting allow you to view and control cross-region contact routing between linked instances, so both Regions are active at all times." + }, + { + "type": "feature", + "category": "Amazon Pinpoint SMS Voice V2", + "contributor": "", + "description": "AWS End User Messaging SMS now returns ConditionalBehavior on DescribeRegistrationFieldDefinitions, allowing you to programmatically discover which registration fields are required, optional, or disallowed based on the values of other fields in the same form." + }, + { + "type": "feature", + "category": "Amazon Connect Customer Profiles", + "contributor": "", + "description": "This release introduces new APIs for segment membership events allowing segment definition membership events to be exported to a kinesis stream for downstream processing. Additionally, includes new calculated attribute statistic and 2 new segment dimension types." + } + ] +} \ No newline at end of file diff --git a/.changes/2.54.x/2.54.9.json b/.changes/2.54.x/2.54.9.json new file mode 100644 index 000000000000..a9108a02ce49 --- /dev/null +++ b/.changes/2.54.x/2.54.9.json @@ -0,0 +1,12 @@ +{ + "version": "2.54.9", + "date": "2026-08-31", + "entries": [ + { + "type": "feature", + "category": "Agent Registry", + "contributor": "", + "description": "Release HTTP and AGUI descriptors to the dataplane model" + } + ] +} \ No newline at end of file diff --git a/.changes/2.55.0.json b/.changes/2.55.0.json new file mode 100644 index 000000000000..4fc6d1843fa8 --- /dev/null +++ b/.changes/2.55.0.json @@ -0,0 +1,72 @@ +{ + "version": "2.55.0", + "date": "2026-09-17", + "entries": [ + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "Made the replicaAlias attribute optional in the ReplicateInstance API to support Global routing for Amazon Connect Global Resiliency (ACGR) instances. This change maintains backward compatibility. When onboarding to ACGR without Global routing, you must specify a custom replicaAlias in your API call" + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Batch evaluation now supports evaluating specific traces within a session. Each session can specify up to 100 trace IDs to evaluate." + }, + { + "type": "feature", + "category": "Amazon GuardDuty", + "contributor": "", + "description": "This change surfaces AI Protection resources on existing public IAM attack sequences. Customers will now see which model was accessed and whether a guardrail intervened as part of the credential-compromise sequence." + }, + { + "type": "feature", + "category": "Amazon VPC Lattice", + "contributor": "", + "description": "Adding support for CIDR Resource Configuration" + }, + { + "type": "feature", + "category": "AWS IoT Wireless", + "contributor": "", + "description": "Adds Multi-frame GNSS support to the AWS IoT Core Device Location GetPositionEstimate API. The new GnssMultiFrame measurement type improves location accuracy by combining multiple GNSS signal captures (2, 4, 8, 16, or 32) from the same device to estimate its position." + }, + { + "type": "feature", + "category": "Amazon Simple Notification Service", + "contributor": "", + "description": "SNS API reference documentation update" + }, + { + "type": "feature", + "category": "AWS End User Messaging Social", + "contributor": "", + "description": "Add support for WhatsApp Calling APIs." + }, + { + "type": "feature", + "category": "AWS User Notifications", + "contributor": "", + "description": "Added support for attachments on managed notification events. Added support to access and subscribe sensitive managed notification events." + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "Added support to query the tenant name for BatchGetMetricData and CreateExportJob APIs to filter metrics and messages at the tenant level." + }, + { + "type": "feature", + "category": "AWS CRT HTTP Client", + "contributor": "", + "description": "Added an opt-in read/write (socket) inactivity timeout for the CRT-based HTTP clients (`AwsCrtHttpClient` and `AwsCrtAsyncHttpClient`). It is not enabled unless you set the `AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026` environment variable or the `aws.enableDefaultSocketTimeout2026` system property. Once enabled, an SDK-managed CRT HTTP client that has no explicit `connectionHealthConfiguration` set receives a per-service read/write timeout; a connection that makes no read or write progress within that window is closed and the in-flight request fails with a retryable `IOException`. The timeout is not applied to an HTTP client you build and supply yourself via `httpClient(...)`." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Adding support for \"Tunnel\" VPC Endpoint" + } + ] +} \ No newline at end of file diff --git a/.changes/2.55.1.json b/.changes/2.55.1.json new file mode 100644 index 000000000000..524d20c8cffb --- /dev/null +++ b/.changes/2.55.1.json @@ -0,0 +1,66 @@ +{ + "version": "2.55.1", + "date": "2026-09-18", + "entries": [ + { + "type": "feature", + "category": "Amazon AppIntegrations Service", + "contributor": "", + "description": "This release adds support for A2A servers via the ApplicationType and AuthConfig fields, allowing customers to register their agent-to-agent servers with API key authentication." + }, + { + "type": "feature", + "category": "Amazon DataZone", + "contributor": "", + "description": "Adds support for specifying Notebook type" + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "This release adds documentation for the T8i instance family to the EC2 ModifyDefaultCreditSpecification and GetDefaultCreditSpecification APIs." + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2 Codegen", + "contributor": "", + "description": "Resolve endpoint parameters up front and ensure all parts of codegen reference them consistently." + }, + { + "type": "feature", + "category": "Amazon Connect Service", + "contributor": "", + "description": "This release adds the ListSecurityProfileAIAgents API and updates the CreateSecurityProfile and UpdateSecurityProfile APIs to support the AllowedAIAgents field on security profiles, allowing customers to manage the 3P AI agents associated with a security profile for Agent-to-Agent interactions." + }, + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Introducing AWS Glue Data Quality advanced rule recommendations for faster recommendations. This capability uses Amazon Athena to analyze a sample of table data and Amazon Bedrock to recommend DQDL rules." + }, + { + "type": "feature", + "category": "Amazon Transcribe Service", + "contributor": "", + "description": "Amazon Transcribe now lets you encrypt your custom vocabularies, custom vocabulary filters, and custom language models with a customer managed AWS KMS key instead of an AWS owned key, and adds a new UpdateLanguageModel operation to transition CLM encryption to a different KMS key." + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Adds support for the hub content resource in SageMaker Search." + }, + { + "type": "feature", + "category": "Amazon Interactive Video Service RealTime", + "contributor": "", + "description": "GetParticipant, ListParticipantEvents, ListParticipantReplicas, StartParticipantReplication, and StopParticipantReplication now accept participant IDs containing underscores." + }, + { + "type": "feature", + "category": "Amazon Q Connect", + "contributor": "", + "description": "Amazon Connect AI Agents now support multi-agent orchestration and structured JSON input and output messaging for orchestration agents." + } + ] +} \ No newline at end of file diff --git a/.changes/2.55.2.json b/.changes/2.55.2.json new file mode 100644 index 000000000000..75ecef90c421 --- /dev/null +++ b/.changes/2.55.2.json @@ -0,0 +1,36 @@ +{ + "version": "2.55.2", + "date": "2026-09-21", + "entries": [ + { + "type": "feature", + "category": "Amazon Bedrock AgentCore Control", + "contributor": "", + "description": "Amazon Bedrock AgentCore Harness now supports lifecycle hooks for invocations and tool calls, with Lambda, SNS, and EventBridge targets. This release also adds apiBase for custom OpenAI-compatible endpoints" + }, + { + "type": "feature", + "category": "Amazon SageMaker Service", + "contributor": "", + "description": "Add support for r6i, m8i, c8i, r8i instance types in Training and Processing" + }, + { + "type": "feature", + "category": "Amazon DocumentDB with MongoDB compatibility", + "contributor": "", + "description": "Add support for CopyTagsToSnapshot field in CreateDbCluster, ModifyDbCluster, RestoreDbClusterFromSnapshot and RestoreDbClusterToPointInTime for DocumentDB." + }, + { + "type": "feature", + "category": "Amazon Bedrock AgentCore", + "contributor": "", + "description": "Amazon Bedrock AgentCore Harness now supports lifecycle hooks for invocations and tool calls, with Lambda, SNS, and EventBridge targets. This release also adds apiBase for custom OpenAI-compatible endpoints." + }, + { + "type": "feature", + "category": "AWSBillingConductor", + "contributor": "", + "description": "Launching Auto Billing Transfer Billing Group Creation Preference feature" + } + ] +} \ No newline at end of file diff --git a/.changes/2.55.3.json b/.changes/2.55.3.json new file mode 100644 index 000000000000..25067b971cc1 --- /dev/null +++ b/.changes/2.55.3.json @@ -0,0 +1,60 @@ +{ + "version": "2.55.3", + "date": "2026-09-22", + "entries": [ + { + "type": "feature", + "category": "AWS Glue", + "contributor": "", + "description": "Adding two new fields for Glue Materialized Views feature - (1) SubObjectsStatistics and (2) SparkPipelineInfo." + }, + { + "type": "feature", + "category": "CloudWatch Omni", + "contributor": "", + "description": "Amazon CloudWatch Omni is now generally available, an AI-powered unified observability for AI agents, applications, and infrastructure. As part of it, organization centralization rules now support cross-account context graph centralization." + }, + { + "type": "bugfix", + "category": "Amazon S3", + "contributor": "", + "description": "`PresignedUrlDownloadRequest#toString()` and the presigned URL marshaller's exception messages render the presigned URL without its query string. `PresignedUrlDownloadRequest#presignedUrl()` still returns the full URL." + }, + { + "type": "perf-improvement", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Migrate all services to BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved." + }, + { + "type": "feature", + "category": "AWS Single Sign-On Admin", + "contributor": "", + "description": "AWS IAM Identity Center now returns PrimaryRegion and Regions in the DescribeInstance response, providing information about replicated instances, and returns IdentityStoreArn in both the ListInstances and DescribeInstance responses." + }, + { + "type": "feature", + "category": "Amazon QuickSight", + "contributor": "", + "description": "Adds support for granular custom permissions on 28 action connectors, including Gmail, Google Drive, Google Sheets, Airtable, and Dropbox. Administrators can now allow or deny individual connector operations instead of all action connectors at once." + }, + { + "type": "feature", + "category": "Amazon Elastic Compute Cloud", + "contributor": "", + "description": "Amazon EC2 now supports quote-based start date changes for future-dated Capacity Reservations" + }, + { + "type": "feature", + "category": "CloudWatch Observability Admin Service", + "contributor": "", + "description": "Amazon CloudWatch Omni is now generally available, an AI-powered unified observability for AI agents, applications, and infrastructure. Centralization now supports context graph for multi-account resource discovery, and dataset integrations makes logs available in CloudWatch datasets." + }, + { + "type": "feature", + "category": "Amazon API Gateway", + "contributor": "", + "description": "API Gateway now supports two new security policies for REST APIs and custom domain names, SecurityPolicy-TLS13-1-2-Ext2-PQ-2025-09 (TLS 1.3 1.2 with post-quantum cryptography) and SecurityPolicy-TLS13-1-2-Ext2-FIPS-PQ-2025-09 (adds FIPS). Both retain legacy algorithms for backward compatibility." + } + ] +} \ No newline at end of file diff --git a/.changes/2.55.4.json b/.changes/2.55.4.json new file mode 100644 index 000000000000..3566a040e637 --- /dev/null +++ b/.changes/2.55.4.json @@ -0,0 +1,72 @@ +{ + "version": "2.55.4", + "date": "2026-09-23", + "entries": [ + { + "type": "feature", + "category": "EC2 Image Builder", + "contributor": "", + "description": "Documentation update for EC2 Image Builder - adds API request and response examples for all operations, improves descriptions throughout, and corrects response field patterns for image versions and workflow ARNs." + }, + { + "type": "feature", + "category": "AWS Elemental MediaConvert", + "contributor": "", + "description": "This release adds support for SMPTE 337M audio passthrough, compositing up to five motion graphic overlays in a single output, and controlling how passthrough video is segmented in ABR outputs. It also adds 3GP, 3G2, AAC, AC-3, and E-AC-3 as supported input containers for the Probe operation." + }, + { + "type": "feature", + "category": "AWS Billing", + "contributor": "", + "description": "Added the ListBillingViewSegments API, which returns billing view segment information for a specified billing view ARN and time range. This API enables customers and integrated tools to programmatically determine the billing context of their accounts." + }, + { + "type": "feature", + "category": "AWS Network Security Manager Customer API", + "contributor": "", + "description": "AWS Network Security Manager is a new service that helps you centrally configure, deploy, and continuously enforce security policies on network security services across the accounts and resources in your AWS Organization." + }, + { + "type": "feature", + "category": "Payment Cryptography Data Plane", + "contributor": "", + "description": "Adds asymmetric key support to ReEncryptData for re-encrypting data between RSA and symmetric data encryption keys." + }, + { + "type": "feature", + "category": "Connect Health", + "contributor": "", + "description": "Multi language support with code switching, custom template sectionHeader now allows underscores." + }, + { + "type": "feature", + "category": "Amazon Kinesis", + "contributor": "", + "description": "Amazon Kinesis Data Streams now supports service managed record distribution for on demand streams. Set the record distribution strategy to AUTO to evenly distribute records across shards. Configure it at stream creation with CreateStream or update anytime with UpdateStreamRecordDistributionStrategy" + }, + { + "type": "feature", + "category": "Amazon Lex Model Building V2", + "contributor": "", + "description": "Adds support for speaker diarization on Amazon Lex V2 bot locales. Speaker diarization keeps your bot on the primary (loudest) speaker during a streaming voice conversation, so background voices do not start a turn or interrupt a prompt." + }, + { + "type": "feature", + "category": "AWS Elemental MediaPackage v2", + "contributor": "", + "description": "This release adds support for signalling start and end in the ContentKeyPeriod element in key request from MediaPackageV2" + }, + { + "type": "perf-improvement", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Fix unnecessary allocation and request latency during endpoint resolution for operations that derive endpoint parameters from request data, including DynamoDB batch and transaction operations and Amazon S3 DeleteObjects. These bindings now use generated typed getters and iterate request maps directly instead of using reflection and copying maps. The order of derived key lists may change, but current DynamoDB endpoint routing behavior is unchanged." + }, + { + "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-ApacheHTTPClient5-9937320.json b/.changes/next-release/feature-ApacheHTTPClient5-9937320.json deleted file mode 100644 index d61cb27e012f..000000000000 --- a/.changes/next-release/feature-ApacheHTTPClient5-9937320.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "type": "feature", - "category": "Apache HTTP Client 5", - "contributor": "", - "description": "Upgrade httpcomponents.client5 to 5.6.2 to address CVE-2026-54428" -} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fdb079b56364..a73203874127 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -56,7 +56,6 @@ updates: - dependency-name: "org.codehaus.mojo:build-helper-maven-plugin" - dependency-name: "org.codehaus.mojo:exec-maven-plugin" - dependency-name: "org.apache.maven.plugin-tools:maven-plugin-annotations" - - dependency-name: "org.graalvm.buildtools:*" - dependency-name: "org.jacoco:jacoco-maven-plugin" - dependency-name: "org.apache.commons:commons-lang3" - dependency-name: "org.codehaus.plexus:plexus-utils" diff --git a/.github/workflows/cve-monitor-list-check.yml b/.github/workflows/cve-monitor-list-check.yml new file mode 100644 index 000000000000..8a3ab03ed39f --- /dev/null +++ b/.github/workflows/cve-monitor-list-check.yml @@ -0,0 +1,54 @@ +# Ensures dependency-cve-monitor.yml stays in sync when modules are removed. +name: "Dependency CVE Monitor Verification" + +on: + pull_request: + merge_group: + +permissions: + contents: read + +jobs: + verify-exclusion-list: + name: Verify CVE monitor exclusion list + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - uses: actions/checkout@v6 + + - name: Validate -pl exclusion list against reactor modules + shell: bash + run: | + set -euo pipefail + + WORKFLOW_FILE=".github/workflows/dependency-cve-monitor.yml" + + # Extract the -pl argument from the workflow file + PL_LINE=$(grep -oP '(?<=-pl )\S+' "$WORKFLOW_FILE") + if [ -z "$PL_LINE" ]; then + echo "Could not find -pl argument in $WORKFLOW_FILE" + exit 1 + fi + + # Parse individual module exclusions (remove leading '!') + EXCLUDED_MODULES=$(echo "$PL_LINE" | tr ',' '\n' | sed 's/^!//') + + # Collect all reactor modules from root pom.xml (recursive through submodule poms) + REACTOR_MODULES=$(grep -ohP '(?<=)[^<]+' pom.xml) + + HAS_ERRORS=0 + while IFS= read -r MODULE; do + if ! echo "$REACTOR_MODULES" | grep -qx "$MODULE"; then + echo "::error::Module '$MODULE' is excluded in $WORKFLOW_FILE but does not exist in the Maven reactor (pom.xml)" + HAS_ERRORS=1 + fi + done <<< "$EXCLUDED_MODULES" + + if [ $HAS_ERRORS -eq 1 ]; then + echo "" + echo "The -pl exclusion list in $WORKFLOW_FILE references modules that are no longer in the reactor." + echo "Please remove the stale entries from the exclusion list." + exit 1 + fi + + echo "All excluded modules are valid reactor modules." diff --git a/.github/workflows/dependency-cve-monitor.yml b/.github/workflows/dependency-cve-monitor.yml index 22868167c539..a52cc6d25b86 100644 --- a/.github/workflows/dependency-cve-monitor.yml +++ b/.github/workflows/dependency-cve-monitor.yml @@ -16,12 +16,12 @@ jobs: contents: write steps: - uses: actions/checkout@v6 - - uses: advanced-security/maven-dependency-submission-action@v5 + - uses: advanced-security/maven-dependency-submission-action@b275d12641ac2d2108b2cbb7598b154ad2f2cee8 # v5 with: maven-args: >- -DtransitiveExcludes=*:* -DclasspathScope=runtime - -pl !build-tools,!release-scripts,!archetypes,!test/test-utils,!test/sdk-benchmarks,!test/http-client-tests,!test/http-client-benchmarks,!test/s3-benchmarks,!test/protocol-tests-core,!test/ruleset-testing-core,!test/protocol-tests,!test/service-test-utils,!test/codegen-generated-classes-test,!test/sdk-standard-benchmarks,!test/module-path-tests,!test/tests-coverage-reporting,!test/stability-tests,!test/sdk-native-image-test,!test/auth-tests,!test/region-testing,!test/old-client-version-compatibility-test,!test/bundle-logging-bridge-binding-test,!test/v2-migration-tests,!test/bundle-shading-tests,!test/crt-unavailable-tests,!test/architecture-tests,!test/s3-tests + -pl !build-tools,!release-scripts,!archetypes,!test/test-utils,!test/sdk-benchmarks,!test/http-client-tests,!test/http-client-benchmarks,!test/s3-benchmarks,!test/protocol-tests-core,!test/ruleset-testing-core,!test/protocol-tests,!test/service-test-utils,!test/codegen-generated-classes-test,!test/sdk-standard-benchmarks,!test/module-path-tests,!test/tests-coverage-reporting,!test/stability-tests,!test/sdk-native-image-test,!test/auth-tests,!test/service-client-backward-compat-test,!test/bundle-logging-bridge-binding-test,!test/v2-migration-tests,!test/bundle-shading-tests,!test/crt-unavailable-tests,!test/architecture-tests,!test/s3-tests notify-alerts: if: github.repository == 'aws/aws-sdk-java-v2' @@ -36,7 +36,7 @@ jobs: env: SLACK_WEBHOOK_URL: ${{ secrets.CI_SLACK_WEBHOOK_URL }} GH_TOKEN: ${{ secrets.DEPENDABOT_ALERTS_TOKEN }} - JQ_FILTER_B64: "Wy5bXSB8IHNlbGVjdCguY3JlYXRlZF9hdCA+ICRjdXRvZmYgYW5kIC5zZWN1cml0eV92dWxuZXJhYmlsaXR5LmZpcnN0X3BhdGNoZWRfdmVyc2lvbiAhPSBudWxsKV0KfCBncm91cF9ieSguc2VjdXJpdHlfdnVsbmVyYWJpbGl0eS5wYWNrYWdlLm5hbWUpCnwgbWFwKHsKICAgIHBrZzogLlswXS5zZWN1cml0eV92dWxuZXJhYmlsaXR5LnBhY2thZ2UubmFtZSwKICAgIGZpeDogLlswXS5zZWN1cml0eV92dWxuZXJhYmlsaXR5LmZpcnN0X3BhdGNoZWRfdmVyc2lvbi5pZGVudGlmaWVyLAogICAgbWFuaWZlc3RzOiAoWy5bXS5kZXBlbmRlbmN5Lm1hbmlmZXN0X3BhdGhdIHwgdW5pcXVlIHwgbWFwKGdzdWIoIi9wb20ueG1sJCI7ICIiKSB8IGdzdWIoIi4qLyI7ICIiKSkpLAogICAgY3ZlczogKGdyb3VwX2J5KC5zZWN1cml0eV9hZHZpc29yeS5jdmVfaWQgLy8gLnNlY3VyaXR5X2Fkdmlzb3J5Lmdoc2FfaWQpIHwgbWFwKHsKICAgICAgY3ZlOiAoLlswXS5zZWN1cml0eV9hZHZpc29yeS5jdmVfaWQgLy8gLlswXS5zZWN1cml0eV9hZHZpc29yeS5naHNhX2lkKSwKICAgICAgZ2hzYTogLlswXS5zZWN1cml0eV9hZHZpc29yeS5naHNhX2lkLAogICAgICBzZXZlcml0eTogKC5bMF0uc2VjdXJpdHlfYWR2aXNvcnkuc2V2ZXJpdHkgfCBhc2NpaV91cGNhc2UpCiAgICB9KSkKICB9KQp8IGlmIGxlbmd0aCA9PSAwIHRoZW4gZW1wdHkKICBlbHNlCiAgICAiOndhcm5pbmc6ICpcKG1hcCguY3ZlcyB8IGxlbmd0aCkgfCBhZGQpIG5ldyBDVkUocykgZGV0ZWN0ZWQgaW4gU0RLIGRlcGVuZGVuY2llcyB3aXRoIGZpeGVzIGF2YWlsYWJsZSpcblxuIiArCiAgICAobWFwKAogICAgICAiYFwoLnBrZylgIChcKC5tYW5pZmVzdHMgfCBqb2luKCIsICIpKSkgXHUyMTkyIFVwZ3JhZGUgdG8gYFwoLmZpeClgXG4iICsKICAgICAgKC5jdmVzIHwgbWFwKCIgIFx1MjAyMiA8aHR0cHM6Ly9naXRodWIuY29tL2Fkdmlzb3JpZXMvXCguZ2hzYSl8XCguY3ZlKT4gKFwoLnNldmVyaXR5KSkiKSB8IGpvaW4oIlxuIikpCiAgICApIHwgam9pbigiXG5cbiIpKSArCiAgICAiXG5cbipBY3Rpb24gbmVlZGVkKjogVXBncmFkZSB0aGUgYWZmZWN0ZWQgZGVwZW5kZW5jeSB2ZXJzaW9ucyB0byB0aGUgZml4IHZlcnNpb25zIGxpc3RlZCBhYm92ZS4iCiAgZW5kCg==" + JQ_FILTER_B64: "Wy5bXSB8IHNlbGVjdCguY3JlYXRlZF9hdCA+ICRjdXRvZmYgYW5kIC5zZWN1cml0eV92dWxuZXJhYmlsaXR5LmZpcnN0X3BhdGNoZWRfdmVyc2lvbiAhPSBudWxsKV0KfCBncm91cF9ieSguc2VjdXJpdHlfdnVsbmVyYWJpbGl0eS5wYWNrYWdlLm5hbWUpCnwgbWFwKHsKICAgIHBrZzogLlswXS5zZWN1cml0eV92dWxuZXJhYmlsaXR5LnBhY2thZ2UubmFtZSwKICAgIGZpeDogLlswXS5zZWN1cml0eV92dWxuZXJhYmlsaXR5LmZpcnN0X3BhdGNoZWRfdmVyc2lvbi5pZGVudGlmaWVyLAogICAgbWFuaWZlc3RzOiAoWy5bXS5kZXBlbmRlbmN5Lm1hbmlmZXN0X3BhdGhdIHwgdW5pcXVlIHwgbWFwKGdzdWIoIi9wb20ueG1sJCI7ICIiKSB8IGdzdWIoIi4qLyI7ICIiKSkpLAogICAgY3ZlczogKGdyb3VwX2J5KC5zZWN1cml0eV9hZHZpc29yeS5jdmVfaWQgLy8gLnNlY3VyaXR5X2Fkdmlzb3J5Lmdoc2FfaWQpIHwgbWFwKHsKICAgICAgY3ZlOiAoLlswXS5zZWN1cml0eV9hZHZpc29yeS5jdmVfaWQgLy8gLlswXS5zZWN1cml0eV9hZHZpc29yeS5naHNhX2lkKSwKICAgICAgZ2hzYTogLlswXS5zZWN1cml0eV9hZHZpc29yeS5naHNhX2lkLAogICAgICBzZXZlcml0eTogKC5bMF0uc2VjdXJpdHlfYWR2aXNvcnkuc2V2ZXJpdHkgfCBhc2NpaV91cGNhc2UpLAogICAgICBzdW1tYXJ5OiAoLlswXS5zZWN1cml0eV9hZHZpc29yeS5zdW1tYXJ5IHwgc3BsaXQoIi4gIikgfCBmaXJzdCB8IGlmIGxlbmd0aCA+IDE1MCB0aGVuIC5bOjE0N10gKyAiLi4uIiBlbHNlIC4gZW5kKQogICAgfSkpCiAgfSkKfCBpZiBsZW5ndGggPT0gMCB0aGVuIGVtcHR5CiAgZWxzZQogICAgIjp3YXJuaW5nOiAqXChtYXAoLmN2ZXMgfCBsZW5ndGgpIHwgYWRkKSBDVkUocykgZGV0ZWN0ZWQgdmlhIDxodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1zZGstamF2YS12Mi9zZWN1cml0eS9kZXBlbmRhYm90fERlcGVuZGFib3QgYWxlcnRzPipcblxuIiArCiAgICAobWFwKAogICAgICAiYFwoLnBrZylgIChcKC5tYW5pZmVzdHMgfCBqb2luKCIsICIpKSkgXHUyMTkyIFVwZ3JhZGUgdG8gYFwoLmZpeClgXG4iICsKICAgICAgKC5jdmVzIHwgbWFwKCIgIFx1MjAyMiA8aHR0cHM6Ly9naXRodWIuY29tL2Fkdmlzb3JpZXMvXCguZ2hzYSl8XCguY3ZlKT4gKFwoLnNldmVyaXR5KSlcbiAgICBcKC5zdW1tYXJ5KSIpIHwgam9pbigiXG4iKSkKICAgICkgfCBqb2luKCJcblxuIikpICsKICAgICJcblxuKkFjdGlvbiBuZWVkZWQqOiBVcGdyYWRlIHRoZSBhZmZlY3RlZCBkZXBlbmRlbmN5IHZlcnNpb25zIHRvIHRoZSBmaXggdmVyc2lvbnMgbGlzdGVkIGFib3ZlLiIKICBlbmQK" shell: bash run: | ONE_DAY_AGO=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ) @@ -66,3 +66,281 @@ jobs: echo "" echo "Slack notification sent." + + check-upstream-advisories: + if: github.repository == 'aws/aws-sdk-java-v2' + runs-on: ubuntu-latest + timeout-minutes: 3 + permissions: + contents: read + steps: + - uses: actions/checkout@v6 + with: + sparse-checkout: pom.xml + sparse-checkout-cone-mode: false + + - name: Check for new CVEs in upstream dependencies + env: + GH_TOKEN: ${{ secrets.DEPENDABOT_ALERTS_TOKEN }} + SLACK_WEBHOOK_URL: ${{ secrets.CI_SLACK_WEBHOOK_URL }} + shell: bash + run: | + set -euo pipefail + + ALERTS="" + NOW=$(date -u +%s) + # Check for CVEs published in the last 24 hours + ONE_DAY_AGO=$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ) + + # ============================================================ + # SDK versions from pom.xml + # ============================================================ + NETTY_VERSION=$(grep -oP '(?<=)[^<]+' pom.xml | sed 's/.Final//') + NETTY_PATCH=$(echo "$NETTY_VERSION" | grep -oP '\d+$') + NETTY_MAJOR_MINOR=$(echo "$NETTY_VERSION" | grep -oP '^\d+\.\d+') + + JACKSON_VERSION=$(grep -oP '(?<=)[^<]+' pom.xml) + JACKSON_DATABIND_VERSION=$(grep -oP '(?<=)[^<]+' pom.xml) + + HTTPCLIENT5_VERSION=$(grep -oP '(?<=)[^<]+' pom.xml) + HTTPCORE5_VERSION=$(grep -oP '(?<=)[^<]+' pom.xml) + + echo "SDK versions:" + echo " Netty: $NETTY_VERSION" + echo " Jackson: $JACKSON_VERSION (databind: $JACKSON_DATABIND_VERSION)" + echo " httpclient5: $HTTPCLIENT5_VERSION" + echo " httpcore5: $HTTPCORE5_VERSION" + + # ============================================================ + # NETTY: Check repo-level security advisories + # ============================================================ + echo "" + echo "=== Checking Netty repo advisories ===" + + SDK_NETTY_PACKAGES=( + "io.netty:netty-codec-http" + "io.netty:netty-codec-http2" + "io.netty:netty-codec" + "io.netty:netty-transport" + "io.netty:netty-transport-native-epoll" + "io.netty:netty-transport-classes-epoll" + "io.netty:netty-common" + "io.netty:netty-buffer" + "io.netty:netty-handler" + "io.netty:netty-resolver" + "io.netty:netty-resolver-dns" + ) + + NETTY_ADVISORIES=$(gh api "repos/netty/netty/security-advisories?sort=published&direction=desc&per_page=30") + + NETTY_NEW=$(echo "$NETTY_ADVISORIES" | jq --arg cutoff "$ONE_DAY_AGO" --arg major_minor "$NETTY_MAJOR_MINOR" --arg sdk_patch "$NETTY_PATCH" \ + --argjson sdk_packages "$(printf '%s\n' "${SDK_NETTY_PACKAGES[@]}" | jq -R . | jq -s .)" \ + '[.[] | + select(.published_at > $cutoff) | + select([.vulnerabilities[].package.name] | any(. as $pkg | $sdk_packages | index($pkg))) | + select(.vulnerabilities[] | + select(.package.name as $pkg | $sdk_packages | index($pkg)) | + (.patched_versions | capture("(?" + $major_minor + "\\.(?

[0-9]+))") | (.p | tonumber) > ($sdk_patch | tonumber)) + ) | + {ghsa_id, severity, summary, + patched: ([.vulnerabilities[] | select(.package.name as $pkg | $sdk_packages | index($pkg)) | .patched_versions | capture("(?" + $major_minor + "\\.(?

[0-9]+))").v] | max), + packages: [.vulnerabilities[] | select(.package.name as $pkg | $sdk_packages | index($pkg)) | .package.name] | unique} + ]') + + NETTY_COUNT=$(echo "$NETTY_NEW" | jq 'length') + echo "Found $NETTY_COUNT new Netty advisories affecting SDK (published in last 24h)" + + if [ "$NETTY_COUNT" -gt 0 ]; then + NETTY_MSG=$(echo "$NETTY_NEW" | jq -r ' + (map(.patched) | max) as $max_patched | + "⚠️ *" + (length | tostring) + " Netty CVE(s) detected via *\n\n" + + (map(" • (\(.severity | ascii_upcase)) — \(.packages | join(", "))\n \(.summary | split(". ") | first | if length > 150 then .[:147] + "..." else . end)") | join("\n")) + + "\n\n*Action needed*: Upgrade Netty from `'"$NETTY_VERSION"'.Final` → `" + $max_patched + ".Final`" + ') + ALERTS="${ALERTS}${NETTY_MSG}\n\n" + fi + + # ============================================================ + # JACKSON: Check repo-level security advisories + # ============================================================ + echo "" + echo "=== Checking Jackson repo advisories ===" + + JACKSON_ALERTS="" + for REPO in "FasterXML/jackson-databind" "FasterXML/jackson-core" "FasterXML/jackson-dataformats-binary"; do + PKG_NAME=$(echo "$REPO" | sed 's|FasterXML/||') + + if [ "$PKG_NAME" = "jackson-databind" ]; then + SDK_VER="$JACKSON_DATABIND_VERSION" + else + SDK_VER="$JACKSON_VERSION" + fi + + SDK_MINOR=$(echo "$SDK_VER" | grep -oP '^\d+\.\d+') + SDK_PATCH=$(echo "$SDK_VER" | grep -oP '\d+$') + + ADVISORIES=$(gh api "repos/$REPO/security-advisories?sort=published&direction=desc&per_page=10") + + NEW_ADVISORIES=$(echo "$ADVISORIES" | jq --arg cutoff "$ONE_DAY_AGO" --arg sdk_minor "$SDK_MINOR" --arg sdk_patch "$SDK_PATCH" --arg sdk_ver "$SDK_VER" \ + '[.[] | + select(.published_at > $cutoff) | + # Find vulnerabilities that match our version line AND where SDK is in the affected range + select([.vulnerabilities[] | + select(.package.name | startswith("com.fasterxml.jackson")) | + select(.patched_versions != null and .patched_versions != "") | + select(.vulnerable_version_range | test($sdk_minor)) | + select( + (.patched_versions // "") | + if . == "" then + false + else + capture("(?" + $sdk_minor + "\\.(?

[0-9]+))") | + (.p | tonumber) > ($sdk_patch | tonumber) + end + ) + ] | length > 0) | + { + ghsa_id, + severity, + summary, + patched: ([.vulnerabilities[] | + select(.package.name | startswith("com.fasterxml.jackson")) | + select(.patched_versions != null and .patched_versions != "") | + select(.vulnerable_version_range | test($sdk_minor)) | + .patched_versions // "" | + capture("(?" + $sdk_minor + "\\.(?

[0-9]+))").v // null + ] | map(select(. != null)) | max // "unknown") + } + ]') + + COUNT=$(echo "$NEW_ADVISORIES" | jq 'length') + echo " $REPO: $COUNT new advisories (last 24h, affecting SDK)" + + if [ "$COUNT" -gt 0 ]; then + MAX_PATCHED=$(echo "$NEW_ADVISORIES" | jq -r '[.[].patched] | map(select(. != "unknown")) | max // "latest"') + JACKSON_MSG=$(echo "$NEW_ADVISORIES" | jq -r --arg repo "$REPO" --arg max_patched "$MAX_PATCHED" ' + "⚠️ *" + (length | tostring) + " '"$PKG_NAME"' CVE(s) detected via *\n\n" + + (map(" • (\(.severity | ascii_upcase)) — \(.summary | split(". ") | first | if length > 150 then .[:147] + "..." else . end)") | join("\n")) + + "\n\n*Action needed*: Upgrade '"$PKG_NAME"' from `'"$SDK_VER"'` → `" + $max_patched + "`" + ') + ALERTS="${ALERTS}${JACKSON_MSG}\n\n" + fi + done + + # ============================================================ + # APACHE: Check NVD for new CVEs, get details from cve.org + # ============================================================ + echo "" + echo "=== Checking Apache httpcomponents via NVD ===" + + NVD_RESULTS=$(curl -s "https://services.nvd.nist.gov/rest/json/cves/2.0?keywordSearch=httpcomponents&pubStartDate=${ONE_DAY_AGO}&pubEndDate=$(date -u +%Y-%m-%dT%H:%M:%S.000)&resultsPerPage=10") + + APACHE_CVES=$(echo "$NVD_RESULTS" | jq -r '.vulnerabilities[]?.cve.id // empty') + + if [ -z "$APACHE_CVES" ]; then + echo " No new Apache httpcomponents CVEs in last 24h" + else + APACHE_ALERTS="" + APACHE_ACTION="" + while IFS= read -r CVE_ID; do + echo " Checking $CVE_ID..." + + # Get structured data from cve.org + CVE_DATA=$(curl -s "https://cveawg.mitre.org/api/cve/$CVE_ID") + + # Extract affected package and version + PACKAGE=$(echo "$CVE_DATA" | jq -r '.containers.cna.affected[0].packageName // .containers.cna.affected[0].product // "unknown"') + + # Check if this affects SDK's versions + AFFECTS_SDK=false + FIX_VERSION="" + DESCRIPTION_FULL=$(echo "$CVE_DATA" | jq -r '.containers.cna.descriptions[0].value // ""') + DESCRIPTION=$(echo "$DESCRIPTION_FULL" | tr '\n' ' ' | sed 's/ */ /g' | sed 's/\. /.\n/' | head -1) + if [ ${#DESCRIPTION} -gt 150 ]; then + DESCRIPTION="${DESCRIPTION:0:147}..." + fi + + # Try to extract fix version from description + FIX_FROM_DESC=$(echo "$DESCRIPTION_FULL" | grep -oP 'upgrade to (?:at least )?version \K[0-9.]+' || echo "") + + # Determine SDK current version based on package + SDK_CURRENT="" + if echo "$PACKAGE" | grep -q "httpclient5"; then + SDK_CURRENT="$HTTPCLIENT5_VERSION" + elif echo "$PACKAGE" | grep -q "httpcore5"; then + SDK_CURRENT="$HTTPCORE5_VERSION" + else + continue + fi + + # Check ALL version entries — SDK is affected if its version <= lessThanOrEqual or < lessThan + VERSIONS_COUNT=$(echo "$CVE_DATA" | jq '.containers.cna.affected[0].versions | length') + SDK_MAJOR_MINOR_APACHE=$(echo "$SDK_CURRENT" | sed 's/\.[0-9]*$//') + for i in $(seq 0 $((VERSIONS_COUNT - 1))); do + LESS_THAN=$(echo "$CVE_DATA" | jq -r ".containers.cna.affected[0].versions[$i].lessThan // \"\"") + LESS_THAN_EQ=$(echo "$CVE_DATA" | jq -r ".containers.cna.affected[0].versions[$i].lessThanOrEqual // \"\"") + VER_BOUND="${LESS_THAN_EQ:-$LESS_THAN}" + + # Skip entries for different version lines (alpha/beta entries that don't match our major.minor) + if echo "$VER_BOUND" | grep -q "alpha\|beta"; then + continue + fi + + # Skip if the bound doesn't start with our major.minor + if ! echo "$VER_BOUND" | grep -q "^${SDK_MAJOR_MINOR_APACHE}\."; then + continue + fi + + if [ -n "$LESS_THAN" ]; then + # Affected if SDK_CURRENT < LESS_THAN + if [ "$(printf '%s\n' "$SDK_CURRENT" "$LESS_THAN" | sort -V | head -1)" = "$SDK_CURRENT" ] && [ "$SDK_CURRENT" != "$LESS_THAN" ]; then + AFFECTS_SDK=true + FIX_VERSION="${FIX_FROM_DESC:-$LESS_THAN}" + break + fi + elif [ -n "$LESS_THAN_EQ" ]; then + # Affected if SDK_CURRENT <= LESS_THAN_EQ + if [ "$(printf '%s\n' "$SDK_CURRENT" "$LESS_THAN_EQ" | sort -V | head -1)" = "$SDK_CURRENT" ]; then + AFFECTS_SDK=true + FIX_VERSION="${FIX_FROM_DESC:-"> $LESS_THAN_EQ"}" + break + fi + fi + done + + if [ "$AFFECTS_SDK" = true ]; then + APACHE_ALERTS="${APACHE_ALERTS} • — $PACKAGE\n $DESCRIPTION\n" + APACHE_ACTION="*Action needed*: Upgrade \`$PACKAGE\` from \`$SDK_CURRENT\` → \`$FIX_VERSION\`" + fi + done <<< "$APACHE_CVES" + + if [ -n "$APACHE_ALERTS" ]; then + APACHE_COUNT=$(echo -e "$APACHE_ALERTS" | grep -c "•") + APACHE_MSG="⚠️ *${APACHE_COUNT} Apache HttpComponents CVE(s) detected via *\n\n${APACHE_ALERTS}\n${APACHE_ACTION}" + ALERTS="${ALERTS}${APACHE_MSG}\n\n" + fi + fi + + # ============================================================ + # Send Slack notification if any alerts found + # ============================================================ + echo "" + if [ -z "$ALERTS" ]; then + echo "No new CVEs found across all upstream sources." + exit 0 + fi + + echo "Sending Slack notification..." + FINAL_MESSAGE=$(echo -e "$ALERTS") + echo "$FINAL_MESSAGE" + + if [ -n "$SLACK_WEBHOOK_URL" ]; then + PAYLOAD=$(jq -n --arg text "$FINAL_MESSAGE" '{text: $text}') + curl -s -X POST "$SLACK_WEBHOOK_URL" \ + -H 'Content-Type: application/json' \ + -d "$PAYLOAD" + echo "" + echo "Slack notification sent." + else + echo "No SLACK_WEBHOOK_URL configured. Skipping notification." + fi diff --git a/.github/workflows/pull-request-build.yml b/.github/workflows/pull-request-build.yml index 96edcd3b1292..55066cb4bdb6 100644 --- a/.github/workflows/pull-request-build.yml +++ b/.github/workflows/pull-request-build.yml @@ -2,10 +2,6 @@ name: Build SDK on: merge_group: pull_request: - paths-ignore: - - '**.md' - - '.all-contributorsrc' - - 'docs/**' concurrency: group: start-pull-request-build-${{ github.ref }} diff --git a/CHANGELOG.md b/CHANGELOG.md index d5ae8d9acc81..9723e16de8b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,162 +1,189 @@ #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ -# __2.47.4__ __2026-07-09__ -## __Apache 5 HTTP Client__ - - ### Bugfixes - - Fix GraalVM native-image metadata for Apache 5. - - Contributed by: [@luneo7](https://github.com/luneo7) +# __2.55.4__ __2026-09-23__ +## __AWS Billing__ + - ### Features + - Added the ListBillingViewSegments API, which returns billing view segment information for a specified billing view ARN and time range. This API enables customers and integrated tools to programmatically determine the billing context of their accounts. -## __Amazon Connect Service__ +## __AWS Elemental MediaConvert__ - ### Features - - Amazon Connect - Added DeleteContactData API to support PII deletion of customer endpoint, additional email recipients and email subject. + - This release adds support for SMPTE 337M audio passthrough, compositing up to five motion graphic overlays in a single output, and controlling how passthrough video is segmented in ABR outputs. It also adds 3GP, 3G2, AAC, AC-3, and E-AC-3 as supported input containers for the Probe operation. -## __Amazon Elastic Compute Cloud__ +## __AWS Elemental MediaPackage v2__ - ### Features - - Added support for additional override parameters in CreateFleet, including LaunchTemplateSpecificationUserData, KeyName, IamInstanceProfile, and MetadataOptions. The CreateFleet response now also includes SubnetId, AvailabilityZone, and AvailabilityZoneId for launched instances. + - This release adds support for signalling start and end in the ContentKeyPeriod element in key request from MediaPackageV2 -## __Amazon GuardDuty__ +## __AWS Network Security Manager Customer API__ + - ### Features + - AWS Network Security Manager is a new service that helps you centrally configure, deploy, and continuously enforce security policies on network security services across the accounts and resources in your AWS Organization. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Performance Improvements + - Fix unnecessary allocation and request latency during endpoint resolution for operations that derive endpoint parameters from request data, including DynamoDB batch and transaction operations and Amazon S3 DeleteObjects. These bindings now use generated typed getters and iterate request maps directly instead of using reflection and copying maps. The order of derived key lists may change, but current DynamoDB endpoint routing behavior is unchanged. + +## __Amazon Kinesis__ - ### Features - - Adding "AI Analyst" enum value for detector + - Amazon Kinesis Data Streams now supports service managed record distribution for on demand streams. Set the record distribution strategy to AUTO to evenly distribute records across shards. Configure it at stream creation with CreateStream or update anytime with UpdateStreamRecordDistributionStrategy -## __Amazon Interactive Video Service__ +## __Amazon Lex Model Building V2__ - ### Features - - adds support for AWS IVS ad configuration APIs to allow for a postRollConfiguration object on the ad configuration resource + - Adds support for speaker diarization on Amazon Lex V2 bot locales. Speaker diarization keeps your bot on the primary (loudest) speaker during a streaming voice conversation, so background voices do not start a turn or interrupt a prompt. -## __Synthetics__ +## __Connect Health__ - ### Features - - CloudWatch Synthetics adds support for customer managed KMS keys for canary environment variables. Customers can now encrypt their canary's Lambda function environment variables at rest using their own AWS KMS key, providing additional control over data protection. + - Multi language support with code switching, custom template sectionHeader now allows underscores. + +## __EC2 Image Builder__ + - ### Features + - Documentation update for EC2 Image Builder - adds API request and response examples for all operations, improves descriptions throughout, and corrects response field patterns for image versions and workflow ARNs. + +## __Payment Cryptography Data Plane__ + - ### Features + - Adds asymmetric key support to ReEncryptData for re-encrypting data between RSA and symmetric data encryption keys. + +# __2.55.3__ __2026-09-22__ +## __AWS Glue__ + - ### Features + - Adding two new fields for Glue Materialized Views feature - (1) SubObjectsStatistics and (2) SparkPipelineInfo. -# __2.47.3__ __2026-07-08__ ## __AWS SDK for Java v2__ - - ### Bugfixes - - Refactor per-operation inline lambdas to factory methods in generated clients - - Updating Lake Formation Access Grants Plugin version to 1.4.3 - - Contributed by: [@rajasbh-aws](https://github.com/rajasbh-aws) + - ### Performance Improvements + - Migrate all services to BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. -## __AWS Sign-In Service__ +## __AWS Single Sign-On Admin__ - ### Features - - Adds support for OAuth 2.0 token operations in AWS Sign-In, CreateOAuth2TokenWithIAM (client credentials flow), IntrospectOAuth2TokenWithIAM (token inspection), and RevokeOAuth2TokenWithIAM (token revocation). + - AWS IAM Identity Center now returns PrimaryRegion and Regions in the DescribeInstance response, providing information about replicated instances, and returns IdentityStoreArn in both the ListInstances and DescribeInstance responses. -## __Amazon DynamoDB__ +## __Amazon API Gateway__ - ### Features - - Adding alternative factory methods to construct AttributeValue that circumvent the use of the builder pattern, and wiring those new factory methods into the DDB enhanced client usages to improve performance. + - API Gateway now supports two new security policies for REST APIs and custom domain names, SecurityPolicy-TLS13-1-2-Ext2-PQ-2025-09 (TLS 1.3 1.2 with post-quantum cryptography) and SecurityPolicy-TLS13-1-2-Ext2-FIPS-PQ-2025-09 (adds FIPS). Both retain legacy algorithms for backward compatibility. -## __Amazon S3__ - - ### Bugfixes - - Fix regression where the SDK automatically attached the source object's versionId to UploadPartCopy requests during multipart copy, causing S3 to require `s3:GetObjectVersion` permission. Updated to only add versionId when explicitly provided by the caller. +## __Amazon Elastic Compute Cloud__ + - ### Features + - Amazon EC2 now supports quote-based start date changes for future-dated Capacity Reservations -## __Contributors__ -Special thanks to the following contributors to this release: +## __Amazon QuickSight__ + - ### Features + - Adds support for granular custom permissions on 28 action connectors, including Gmail, Google Drive, Google Sheets, Airtable, and Dropbox. Administrators can now allow or deny individual connector operations instead of all action connectors at once. -[@rajasbh-aws](https://github.com/rajasbh-aws) -# __2.47.2__ __2026-07-08__ -## __AWS Common Runtime HTTP Client__ +## __Amazon S3__ - ### Bugfixes - - Fix CRT connection pool exhaustion/leak when streams are cancelled due to API call timeouts. Ensure concurrency/HTTP metrics are always published. + - `PresignedUrlDownloadRequest#toString()` and the presigned URL marshaller's exception messages render the presigned URL without its query string. `PresignedUrlDownloadRequest#presignedUrl()` still returns the full URL. -## __AWS IoT Wireless__ +## __CloudWatch Observability Admin Service__ + - ### Features + - Amazon CloudWatch Omni is now generally available, an AI-powered unified observability for AI agents, applications, and infrastructure. Centralization now supports context graph for multi-account resource discovery, and dataset integrations makes logs available in CloudWatch datasets. + +## __CloudWatch Omni__ - ### Features - - Default session downlink transmission parameters have been added to the existing Multicast Group APIs. Explicit transmission parameters are no longer required when starting a multicast session during the FUOTA procedure. + - Amazon CloudWatch Omni is now generally available, an AI-powered unified observability for AI agents, applications, and infrastructure. As part of it, organization centralization rules now support cross-account context graph centralization. -## __AWS Resilience Hub V2__ +# __2.55.2__ __2026-09-21__ +## __AWSBillingConductor__ - ### Features - - Next Generation Resilience Hub now supports filtering and sorting failure mode assessments, resource type filtering in ListResources, cross-region and cross-account topology edges, data recovery achievability status, and more granular dependency discovery progress tracking. + - Launching Auto Billing Transfer Billing Group Creation Preference feature -## __Amazon AppConfig__ +## __Amazon Bedrock AgentCore__ - ### Features - - Update ExperimentRun APIs to support ConflictExceptions. + - Amazon Bedrock AgentCore Harness now supports lifecycle hooks for invocations and tool calls, with Lambda, SNS, and EventBridge targets. This release also adds apiBase for custom OpenAI-compatible endpoints. ## __Amazon Bedrock AgentCore Control__ - ### Features - - AgentCore Gateway now supports mapping allowed scopes to separate advertised scopes on the inbound authorizer. + - Amazon Bedrock AgentCore Harness now supports lifecycle hooks for invocations and tool calls, with Lambda, SNS, and EventBridge targets. This release also adds apiBase for custom OpenAI-compatible endpoints -## __Amazon EC2 Container Service__ +## __Amazon DocumentDB with MongoDB compatibility__ - ### Features - - Amazon ECS now automatically detects the correct CPU architecture for Express Mode services. + - Add support for CopyTagsToSnapshot field in CreateDbCluster, ModifyDbCluster, RestoreDbClusterFromSnapshot and RestoreDbClusterToPointInTime for DocumentDB. -## __Amazon Elastic Compute Cloud__ +## __Amazon SageMaker Service__ - ### Features - - Replace Root Volume now supports a VolumeId parameter. This allows the customer to pass in a pre-prepared volume as the target root volume for an RRV workflow. + - Add support for r6i, m8i, c8i, r8i instance types in Training and Processing -## __Amazon Location Service Places V2__ +# __2.55.1__ __2026-09-18__ +## __AWS Glue__ - ### Features - - Added AddressNamesMode, AddressNameTranslations, MobilityMode, PostalCodeMode, SecondaryAddresses, and DriveThrough features across Places V2 APIs to support address name formatting, multilingual translations, travel-aware search, multi-city postal codes, and unit-level address resolution. + - Introducing AWS Glue Data Quality advanced rule recommendations for faster recommendations. This capability uses Amazon Athena to analyze a sample of table data and Amazon Bedrock to recommend DQDL rules. + +## __AWS SDK for Java v2 Codegen__ + - ### Bugfixes + - Resolve endpoint parameters up front and ensure all parts of codegen reference them consistently. -# __2.47.1__ __2026-07-07__ -## __AWS Config__ +## __Amazon AppIntegrations Service__ - ### Features - - Added support for connecting AWS Config to third-party cloud service providers. New APIs include PutConnector, GetConnector, DeleteConnector, and ListConnectors for managing connectors, and PutThirdPartyServiceLinkedConfigurationRecorder for creating third-party service-linked recorders. + - This release adds support for A2A servers via the ApplicationType and AuthConfig fields, allowing customers to register their agent-to-agent servers with API key authentication. -## __AWS Lambda__ +## __Amazon Connect Service__ - ### Features - - AWS Lambda Durable Functions now supports customer managed KMS keys. This allows customers to configure a KMS key in Durable Config to have all their durable execution data encrypted. + - This release adds the ListSecurityProfileAIAgents API and updates the CreateSecurityProfile and UpdateSecurityProfile APIs to support the AllowedAIAgents field on security profiles, allowing customers to manage the 3P AI agents associated with a security profile for Agent-to-Agent interactions. -## __AWS Marketplace Catalog Service__ +## __Amazon DataZone__ - ### Features - - This release enhances the ListEntities API to support ResellerRole filter for ResaleAuthorization entity. + - Adds support for specifying Notebook type -## __AWS SDK for Java v2__ - - ### Bugfixes - - Re-resolve SSO access token on each credential refresh in the SSOCredentialsProvider instead of caching it at construction time ensuring that refreshed tokens (for example from running `aws sso login`) are always used. +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds documentation for the T8i instance family to the EC2 ModifyDefaultCreditSpecification and GetDefaultCreditSpecification APIs. -## __AWS SecurityHub__ +## __Amazon Interactive Video Service RealTime__ - ### Features - - release SecurityHub MultiCloud integration with Azure + - GetParticipant, ListParticipantEvents, ListParticipantReplicas, StartParticipantReplication, and StopParticipantReplication now accept participant IDs containing underscores. -## __AWSMarketplace Metering__ +## __Amazon Q Connect__ - ### Features - - The usage reporting window for the BatchMeterUsage API has been extended from 6 hours to 24 hours. Sellers can now submit usage records for up to 24 hours after a metered event occurs. The existing 6-hour grace period at the end of a billing cycle still applies. + - Amazon Connect AI Agents now support multi-agent orchestration and structured JSON input and output messaging for orchestration agents. -## __Amazon Connect Service__ +## __Amazon SageMaker Service__ - ### Features - - Adds support for CreateAuthCode and DeleteSession APIs. + - Adds support for the hub content resource in SageMaker Search. -## __Amazon Elastic Compute Cloud__ +## __Amazon Transcribe Service__ - ### Features - - This launch surfaces the public SSM parameter associated with public AMIs in the AMI metadata. + - Amazon Transcribe now lets you encrypt your custom vocabularies, custom vocabulary filters, and custom language models with a customer managed AWS KMS key instead of an AWS owned key, and adds a new UpdateLanguageModel operation to transition CLM encryption to a different KMS key. -## __Amazon Route 53 Global Resolver__ +# __2.55.0__ __2026-09-17__ +## __AWS CRT HTTP Client__ - ### Features - - Adds ListSharedDNSViews operation to list all DNS Views shared with caller using AWS Resource Access Manager. Also updates ListHostedZoneAssociations operation so that resource ARN param is optional, allowing caller to list all HostedZoneAssociations in account. + - Added an opt-in read/write (socket) inactivity timeout for the CRT-based HTTP clients (`AwsCrtHttpClient` and `AwsCrtAsyncHttpClient`). It is not enabled unless you set the `AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026` environment variable or the `aws.enableDefaultSocketTimeout2026` system property. Once enabled, an SDK-managed CRT HTTP client that has no explicit `connectionHealthConfiguration` set receives a per-service read/write timeout; a connection that makes no read or write progress within that window is closed and the in-flight request fails with a retryable `IOException`. The timeout is not applied to an HTTP client you build and supply yourself via `httpClient(...)`. -## __Amazon Simple Systems Manager (SSM)__ +## __AWS End User Messaging Social__ - ### Features - - Adding SSM Cloud Connector to support Azure Virtual Machines onboarding to AWS Systems Manager + - Add support for WhatsApp Calling APIs. -## __Inspector2__ +## __AWS IoT Wireless__ - ### Features - - This release extends vulnerability management to Azure VM, container registries and function apps. Adds support for per-member-account scan configuration settings. + - Adds Multi-frame GNSS support to the AWS IoT Core Device Location GetPositionEstimate API. The new GnssMultiFrame measurement type improves location accuracy by combining multiple GNSS signal captures (2, 4, 8, 16, or 32) from the same device to estimate its position. -## __Partner Central Revenue Measurement API__ +## __AWS User Notifications__ - ### Features - - Add support for AWS Partner Central Revenue Measurement API for creating, managing, and tracking revenue attributions and marketplace revenue share allocations. + - Added support for attachments on managed notification events. Added support to access and subscribe sensitive managed notification events. -# __2.47.0__ __2026-07-06__ -## __AWS Billing__ +## __Amazon Bedrock AgentCore__ - ### Features - - Adds support for managing AWS account credits and billing preferences, including retrieving credit details, viewing per-month credit allocation history, redeeming promotional codes, and configuring credit sharing and billing preferences. + - Batch evaluation now supports evaluating specific traces within a session. Each session can specify up to 100 trace IDs to evaluate. -## __AWS SDK for Java v2__ +## __Amazon Connect Service__ - ### Features - - Moved auth scheme and endpoint resolution from per-service generated interceptors to shared pipeline stages, establishing clear separation between customer extension points and SDK internals. This also fixes a bug where credentials injected via `ExecutionInterceptor.modifyRequest()` were not being used for signing ([#6486](https://github.com/aws/aws-sdk-java-v2/issues/6486)) - - Updated endpoint and partition metadata. + - Made the replicaAlias attribute optional in the ReplicateInstance API to support Global routing for Amazon Connect Global Resiliency (ACGR) instances. This change maintains backward compatibility. When onboarding to ACGR without Global routing, you must specify a custom replicaAlias in your API call - - ### Bugfixes - - Updating Lake Formation Access Grants Plugin version to 1.4.2 - - Contributed by: [@rajasbh-aws](https://github.com/rajasbh-aws) +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adding support for "Tunnel" VPC Endpoint -## __Amazon CloudWatch Logs__ +## __Amazon GuardDuty__ - ### Features - - Added PutStorageTierPolicy and GetStorageTierPolicy APIs to Amazon CloudWatch Logs. Customers can now configure account-level Intelligent Tiering to automatically optimize log storage costs by moving infrequently accessed data to lower-cost storage tiers. + - This change surfaces AI Protection resources on existing public IAM attack sequences. Customers will now see which model was accessed and whether a guardrail intervened as part of the credential-compromise sequence. -## __Amazon OpenSearch Service__ +## __Amazon Simple Email Service__ - ### Features - - This release introduces Saved Object Migration APIs, enabling users to migrate dashboards, visualizations, index patterns, and other saved objects from a data source into an Amazon OpenSearch Service application workspace with configurable export filters and conflict resolution strategies. + - Added support to query the tenant name for BatchGetMetricData and CreateExportJob APIs to filter metrics and messages at the tenant level. -## __MailManager__ +## __Amazon Simple Notification Service__ - ### Features - - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + - SNS API reference documentation update -## __Contributors__ -Special thanks to the following contributors to this release: +## __Amazon VPC Lattice__ + - ### Features + - Adding support for CIDR Resource Configuration -[@rajasbh-aws](https://github.com/rajasbh-aws) diff --git a/README.md b/README.md index 16ff34bda546..9870b517f44e 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.47.4 + 2.55.4 pom import @@ -85,12 +85,12 @@ Alternatively you can add dependencies for the specific services you use only: software.amazon.awssdk ec2 - 2.47.4 + 2.55.4 software.amazon.awssdk s3 - 2.47.4 + 2.55.4 ``` @@ -102,7 +102,7 @@ You can import the whole SDK into your project (includes *ALL* services). Please software.amazon.awssdk aws-sdk-java - 2.47.4 + 2.55.4 ``` diff --git a/archetypes/archetype-app-quickstart/pom.xml b/archetypes/archetype-app-quickstart/pom.xml index 23c3afbf7e6e..d0005b7731b2 100644 --- a/archetypes/archetype-app-quickstart/pom.xml +++ b/archetypes/archetype-app-quickstart/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/archetypes/archetype-lambda/pom.xml b/archetypes/archetype-lambda/pom.xml index d5ce042e3ce7..7341263099ce 100644 --- a/archetypes/archetype-lambda/pom.xml +++ b/archetypes/archetype-lambda/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 archetype-lambda diff --git a/archetypes/archetype-tools/pom.xml b/archetypes/archetype-tools/pom.xml index cf6c84c1ee08..f8638555d88e 100644 --- a/archetypes/archetype-tools/pom.xml +++ b/archetypes/archetype-tools/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/archetypes/pom.xml b/archetypes/pom.xml index 8fc0af879a70..a2a2206a82c3 100644 --- a/archetypes/pom.xml +++ b/archetypes/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 archetypes diff --git a/aws-sdk-java/pom.xml b/aws-sdk-java/pom.xml index 9bb8bc1bdf13..c2c8bdefef99 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml aws-sdk-java @@ -2203,6 +2203,41 @@ Amazon AutoScaling, etc). partnercentralrevenuemeasurement ${awsjavasdk.version} + + software.amazon.awssdk + pricingplanmanager + ${awsjavasdk.version} + + + software.amazon.awssdk + agentregistry + ${awsjavasdk.version} + + + software.amazon.awssdk + agentregistrycontrol + ${awsjavasdk.version} + + + software.amazon.awssdk + accountaccess + ${awsjavasdk.version} + + + software.amazon.awssdk + iamtoolbox + ${awsjavasdk.version} + + + software.amazon.awssdk + cloudwatchomni + ${awsjavasdk.version} + + + software.amazon.awssdk + networksecuritymanager + ${awsjavasdk.version} + ${project.artifactId}-${project.version} diff --git a/bom-internal/pom.xml b/bom-internal/pom.xml index 6001658a28db..1917afe4781b 100644 --- a/bom-internal/pom.xml +++ b/bom-internal/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -519,6 +519,24 @@ pom import + + org.apache.kerby + kerb-simplekdc + ${kerby.version} + test + + + org.apache.kerby + kerb-client + ${kerby.version} + test + + + org.apache.kerby + kerb-core + ${kerby.version} + test + diff --git a/bom/pom.xml b/bom/pom.xml index 89ee6b302daa..a499d9ec1219 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml bom @@ -2402,6 +2402,41 @@ partnercentralrevenuemeasurement ${awsjavasdk.version} + + software.amazon.awssdk + pricingplanmanager + ${awsjavasdk.version} + + + software.amazon.awssdk + agentregistry + ${awsjavasdk.version} + + + software.amazon.awssdk + agentregistrycontrol + ${awsjavasdk.version} + + + software.amazon.awssdk + accountaccess + ${awsjavasdk.version} + + + software.amazon.awssdk + iamtoolbox + ${awsjavasdk.version} + + + software.amazon.awssdk + cloudwatchomni + ${awsjavasdk.version} + + + software.amazon.awssdk + networksecuritymanager + ${awsjavasdk.version} + diff --git a/build-tools/pom.xml b/build-tools/pom.xml index b48807ad8caf..9d55cdf9379c 100644 --- a/build-tools/pom.xml +++ b/build-tools/pom.xml @@ -59,6 +59,12 @@ true + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + @@ -74,6 +80,12 @@ spotbugs 4.8.6 + + org.junit.jupiter + junit-jupiter + 5.10.3 + test + diff --git a/build-tools/src/main/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheck.java b/build-tools/src/main/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheck.java new file mode 100644 index 000000000000..3db26f317689 --- /dev/null +++ b/build-tools/src/main/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheck.java @@ -0,0 +1,146 @@ +/* + * 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.buildtools.checkstyle; + +import com.puppycrawl.tools.checkstyle.api.AbstractCheck; +import com.puppycrawl.tools.checkstyle.api.DetailAST; +import com.puppycrawl.tools.checkstyle.api.FullIdent; +import com.puppycrawl.tools.checkstyle.api.TokenTypes; +import java.util.Arrays; +import java.util.List; + +/** + * Caps the length of the {@code guidance} and {@code saferAlternative} member values on any + * {@code @SdkAdvancedApi} usage. The values are written as multi-line string-literal concatenations, so this operates + * on the source AST and sums the decoded content of every concatenated string literal in the member's expression before + * comparing to {@code max}. + */ +public class SdkAdvancedApiMemberLengthCheck extends AbstractCheck { + + private static final String ANNOTATION_NAME = "SdkAdvancedApi"; + private static final List CHECKED_MEMBERS = Arrays.asList("guidance", "saferAlternative"); + + private int max = 1000; + + public void setMax(int max) { + this.max = max; + } + + @Override + public int[] getDefaultTokens() { + return getRequiredTokens(); + } + + @Override + public int[] getAcceptableTokens() { + return getRequiredTokens(); + } + + @Override + public int[] getRequiredTokens() { + return new int[] {TokenTypes.ANNOTATION}; + } + + @Override + public void visitToken(DetailAST annotation) { + if (!isSdkAdvancedApi(annotation)) { + return; + } + + for (DetailAST child = annotation.getFirstChild(); child != null; child = child.getNextSibling()) { + if (child.getType() != TokenTypes.ANNOTATION_MEMBER_VALUE_PAIR) { + continue; + } + + DetailAST memberName = child.findFirstToken(TokenTypes.IDENT); + if (memberName == null || !CHECKED_MEMBERS.contains(memberName.getText())) { + continue; + } + + DetailAST expr = child.findFirstToken(TokenTypes.EXPR); + if (expr == null) { + continue; + } + + int length = concatenatedStringLength(expr); + if (length > max) { + log(memberName, String.format( + "@%s member '%s' is %d characters, which exceeds the maximum of %d. Tighten the wording.", + ANNOTATION_NAME, memberName.getText(), length, max)); + } + } + } + + private boolean isSdkAdvancedApi(DetailAST annotation) { + DetailAST nameNode = annotation.findFirstToken(TokenTypes.IDENT); + if (nameNode == null) { + nameNode = annotation.findFirstToken(TokenTypes.DOT); + } + if (nameNode == null) { + return false; + } + String name = FullIdent.createFullIdent(nameNode).getText(); + return name.equals(ANNOTATION_NAME) || name.endsWith("." + ANNOTATION_NAME); + } + + private int concatenatedStringLength(DetailAST node) { + int total = 0; + for (DetailAST child = node.getFirstChild(); child != null; child = child.getNextSibling()) { + if (child.getType() == TokenTypes.STRING_LITERAL) { + total += decodedLength(child.getText()); + } else { + total += concatenatedStringLength(child); + } + } + return total; + } + + /** + * Counts the logical characters in a string literal token (its text includes the surrounding quotes), treating each + * escape sequence as a single character so the count matches the text a consumer of the annotation would see. + */ + private int decodedLength(String literalWithQuotes) { + String body = literalWithQuotes; + if (body.length() >= 2 && body.charAt(0) == '"' && body.charAt(body.length() - 1) == '"') { + body = body.substring(1, body.length() - 1); + } + + int count = 0; + int i = 0; + while (i < body.length()) { + if (body.charAt(i) == '\\' && i + 1 < body.length()) { + char next = body.charAt(i + 1); + if (next == 'u') { + i += 6; + } else if (next >= '0' && next <= '7') { + int j = i + 1; + int digits = 0; + while (j < body.length() && digits < 3 && body.charAt(j) >= '0' && body.charAt(j) <= '7') { + j++; + digits++; + } + i = j; + } else { + i += 2; + } + } else { + i++; + } + count++; + } + return count; + } +} diff --git a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml index bcccae6e04a5..60c504c691cd 100644 --- a/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml +++ b/build-tools/src/main/resources/software/amazon/awssdk/checkstyle-suppressions.xml @@ -72,6 +72,11 @@ + + + + + + + + diff --git a/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml b/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml index abd579363262..8168db1203b4 100644 --- a/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml +++ b/build-tools/src/main/resources/software/amazon/awssdk/spotbugs-suppressions.xml @@ -333,6 +333,7 @@ + @@ -348,6 +349,9 @@ + + + @@ -548,6 +552,16 @@ + + + + + + + + + + diff --git a/build-tools/src/test/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheckTest.java b/build-tools/src/test/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheckTest.java new file mode 100644 index 000000000000..450959528325 --- /dev/null +++ b/build-tools/src/test/java/software/amazon/awssdk/buildtools/checkstyle/SdkAdvancedApiMemberLengthCheckTest.java @@ -0,0 +1,165 @@ +/* + * 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.buildtools.checkstyle; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.puppycrawl.tools.checkstyle.Checker; +import com.puppycrawl.tools.checkstyle.DefaultConfiguration; +import com.puppycrawl.tools.checkstyle.api.AuditEvent; +import com.puppycrawl.tools.checkstyle.api.AuditListener; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +class SdkAdvancedApiMemberLengthCheckTest { + + @TempDir + Path tempDir; + + @Test + void guidanceWithinLimit_passes() throws Exception { + String source = classWithMembers(repeat("a", 50), repeat("b", 50)); + assertEquals(Collections.emptyList(), runCheck(source, 1000)); + } + + @Test + void guidanceOverLimit_fails() throws Exception { + String source = classWithMembers(repeat("a", 1001), repeat("b", 50)); + List violations = runCheck(source, 1000); + assertEquals(1, violations.size()); + assertTrue(violations.get(0).contains("guidance"), violations.get(0)); + assertTrue(violations.get(0).contains("1001"), violations.get(0)); + } + + @Test + void saferAlternativeOverLimit_fails() throws Exception { + String source = classWithMembers(repeat("a", 50), repeat("b", 1001)); + List violations = runCheck(source, 1000); + assertEquals(1, violations.size()); + assertTrue(violations.get(0).contains("saferAlternative"), violations.get(0)); + } + + @Test + void multiLineConcatenation_sumsAllFragments() throws Exception { + String guidance = "\"" + repeat("a", 400) + "\"\n" + + " + \"" + repeat("b", 400) + "\"\n" + + " + \"" + repeat("c", 300) + "\""; + String source = classWithRawGuidance(guidance); + List violations = runCheck(source, 1000); + assertEquals(1, violations.size()); + assertTrue(violations.get(0).contains("1100"), violations.get(0)); + } + + @Test + void valueAtExactLimit_passes() throws Exception { + String source = classWithMembers(repeat("a", 1000), repeat("b", 1000)); + assertEquals(Collections.emptyList(), runCheck(source, 1000)); + } + + private static String repeat(String s, int n) { + return IntStream.range(0, n).mapToObj(i -> s).collect(Collectors.joining()); + } + + private static String classWithMembers(String guidance, String saferAlternative) { + return classWithRawGuidanceAndSafer("\"" + guidance + "\"", "\"" + saferAlternative + "\""); + } + + private static String classWithRawGuidance(String rawGuidanceExpr) { + return classWithRawGuidanceAndSafer(rawGuidanceExpr, "\"safe\""); + } + + private static String classWithRawGuidanceAndSafer(String rawGuidanceExpr, String rawSaferExpr) { + return "package p;\n" + + "@SdkAdvancedApi(\n" + + " cautionWhen = Usage.IMPLEMENTED,\n" + + " guidance = " + rawGuidanceExpr + ",\n" + + " saferAlternative = " + rawSaferExpr + ")\n" + + "public interface Foo {\n" + + "}\n"; + } + + private List runCheck(String source, int max) throws IOException, CheckstyleException { + File file = tempDir.resolve("Foo.java").toFile(); + Files.write(file.toPath(), source.getBytes(StandardCharsets.UTF_8)); + + DefaultConfiguration checkConfig = new DefaultConfiguration(SdkAdvancedApiMemberLengthCheck.class.getName()); + checkConfig.addAttribute("max", Integer.toString(max)); + + DefaultConfiguration treeWalker = new DefaultConfiguration("TreeWalker"); + treeWalker.addChild(checkConfig); + + DefaultConfiguration checker = new DefaultConfiguration("Checker"); + checker.addAttribute("charset", "UTF-8"); + checker.addChild(treeWalker); + + Checker c = new Checker(); + c.setModuleClassLoader(Thread.currentThread().getContextClassLoader()); + c.configure(checker); + + List messages = new ArrayList<>(); + c.addListener(new CollectingListener(messages)); + + c.process(Collections.singletonList(file)); + c.destroy(); + return messages; + } + + private static final class CollectingListener implements AuditListener { + private final List messages; + + private CollectingListener(List messages) { + this.messages = messages; + } + + @Override + public void addError(AuditEvent event) { + messages.add(event.getMessage()); + } + + @Override + public void addException(AuditEvent event, Throwable throwable) { + messages.add("EXCEPTION: " + throwable.getMessage()); + } + + @Override + public void auditStarted(AuditEvent event) { + } + + @Override + public void auditFinished(AuditEvent event) { + } + + @Override + public void fileStarted(AuditEvent event) { + } + + @Override + public void fileFinished(AuditEvent event) { + } + } +} diff --git a/bundle-logging-bridge/pom.xml b/bundle-logging-bridge/pom.xml index c95b48c404f6..df02a317a10f 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bundle-logging-bridge jar diff --git a/bundle-sdk/pom.xml b/bundle-sdk/pom.xml index 818805159508..e1574cff6cde 100644 --- a/bundle-sdk/pom.xml +++ b/bundle-sdk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bundle-sdk jar diff --git a/bundle/pom.xml b/bundle/pom.xml index c87b91b39fe3..64a593352290 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bundle jar diff --git a/changelogs/2.47.x-CHANGELOG.md b/changelogs/2.47.x-CHANGELOG.md new file mode 100644 index 000000000000..3c526bb747f6 --- /dev/null +++ b/changelogs/2.47.x-CHANGELOG.md @@ -0,0 +1,232 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.47.6__ __2026-07-13__ +## __AWS Common Runtime HTTP Client__ + - ### Features + - Added tlsNegotiationTimeout(Duration) configuration to AwsCrtAsyncHttpClient and AwsCrtHttpClient builders, mirroring the option on the Netty client. Configures the maximum amount of time a TLS handshake may take, from CLIENT HELLO through key exchange. Defaults to 10 seconds, matching the underlying CRT runtime's native default. + +## __AWS Lambda__ + - ### Features + - Add Java 8, 11 and 17 on AL2023 (java8.al2023, java11.al2023, java17.al2023) support to AWS Lambda. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Elasticsearch Service__ + - ### Features + - Adds support for the EngineMode and UseCase parameters on Amazon Elasticsearch Service domains, enabling GENERAL or OPTIMIZED engine modes and SEARCH, VECTOR, OBSERVABILITY, or MIXED usecases when creating and updating domain configurations. + +## __Amazon GameLift__ + - ### Features + - Amazon GameLift Servers now includes fleet expiration for managed fleets. A managed fleet expires one year after creation, transitioning to EXPIRED status, emitting a FLEET EXPIRED event, and scaling to zero instances. Expired fleets cannot host new game sessions or increase capacity. + +## __Amazon GuardDuty__ + - ### Features + - GuardDuty AI Protection is now publicly available. Findings include Bedrock guardrail details, model details, observation numbers, and continuous scan details. GuardrailArn and GuardrailVersion are deprecated in favor of the guardrails list. + +## __Redshift Serverless__ + - ### Features + - Add support for preserving datasharing, zero-ETL and S3 event integrations on snapshot restore to serverless namespace. + +# __2.47.5__ __2026-07-10__ +## __AWS Lambda__ + - ### Features + - Added TelemetryConfig support for Managed Instances Capacity Provider, enabling customers to configure system log level and custom log group for managed instance logging. + +## __AWS License Manager__ + - ### Features + - Added the ResetUsage field to the CreateLicenseVersion API. When set to true, the entitlement usage counts for the license are reset to 0. If it is false or not specified, entitlement usage is left unchanged. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon CloudWatch__ + - ### Features + - CloudWatch now assigns a unique identifier to each anomaly detector. PutAnomalyDetector and DescribeAnomalyDetectors return this AnomalyDetectorId, which you can use to describe or delete a specific anomaly detector directly. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - New Amazon EC2 instances. M9g, M9gd, C9g, and C9gd on AWS Graviton5. C8in, M8in, and R8in add 600 Gbps network. C8ib, M8ib, and R8ib add 300 Gbps EBS. C8ine, M8ine, M8idn, R8idn, M8idb, and R8idb round out Intel Xeon 6. Mac-m3ultra with Apple M3 Ultra. G7 with NVIDIA RTX PRO 4500 Blackwell GPUs. + +## __Amazon QuickSight__ + - ### Features + - Provides CreateKnowledgeBase and UpdateKnowledgeBase APIs + +## __Amazon SageMaker Service__ + - ### Features + - Release support for g4d, c6g, c7g, c8g instance types for SageMaker HyperPod + +## __Apache HTTP Client 5__ + - ### Features + - Upgrade httpcomponents.client5 to 5.6.2 to address CVE-2026-54428 + +## __Inspector2__ + - ### Features + - Support for 3 day and 7 day ECR re-scan durations + +# __2.47.4__ __2026-07-09__ +## __Amazon Connect Service__ + - ### Features + - Amazon Connect - Added DeleteContactData API to support PII deletion of customer endpoint, additional email recipients and email subject. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Added support for additional override parameters in CreateFleet, including LaunchTemplateSpecificationUserData, KeyName, IamInstanceProfile, and MetadataOptions. The CreateFleet response now also includes SubnetId, AvailabilityZone, and AvailabilityZoneId for launched instances. + +## __Amazon GuardDuty__ + - ### Features + - Adding "AI Analyst" enum value for detector + +## __Amazon Interactive Video Service__ + - ### Features + - adds support for AWS IVS ad configuration APIs to allow for a postRollConfiguration object on the ad configuration resource + +## __Apache 5 HTTP Client__ + - ### Bugfixes + - Fix GraalVM native-image metadata for Apache 5. + - Contributed by: [@luneo7](https://github.com/luneo7) + +## __Synthetics__ + - ### Features + - CloudWatch Synthetics adds support for customer managed KMS keys for canary environment variables. Customers can now encrypt their canary's Lambda function environment variables at rest using their own AWS KMS key, providing additional control over data protection. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@luneo7](https://github.com/luneo7) +# __2.47.3__ __2026-07-08__ +## __AWS SDK for Java v2__ + - ### Bugfixes + - Refactor per-operation inline lambdas to factory methods in generated clients + - Updating Lake Formation Access Grants Plugin version to 1.4.3 + - Contributed by: [@rajasbh-aws](https://github.com/rajasbh-aws) + +## __AWS Sign-In Service__ + - ### Features + - Adds support for OAuth 2.0 token operations in AWS Sign-In, CreateOAuth2TokenWithIAM (client credentials flow), IntrospectOAuth2TokenWithIAM (token inspection), and RevokeOAuth2TokenWithIAM (token revocation). + +## __Amazon DynamoDB__ + - ### Features + - Adding alternative factory methods to construct AttributeValue that circumvent the use of the builder pattern, and wiring those new factory methods into the DDB enhanced client usages to improve performance. + +## __Amazon S3__ + - ### Bugfixes + - Fix regression where the SDK automatically attached the source object's versionId to UploadPartCopy requests during multipart copy, causing S3 to require `s3:GetObjectVersion` permission. Updated to only add versionId when explicitly provided by the caller. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@rajasbh-aws](https://github.com/rajasbh-aws) +# __2.47.2__ __2026-07-08__ +## __AWS Common Runtime HTTP Client__ + - ### Bugfixes + - Fix CRT connection pool exhaustion/leak when streams are cancelled due to API call timeouts. Ensure concurrency/HTTP metrics are always published. + +## __AWS IoT Wireless__ + - ### Features + - Default session downlink transmission parameters have been added to the existing Multicast Group APIs. Explicit transmission parameters are no longer required when starting a multicast session during the FUOTA procedure. + +## __AWS Resilience Hub V2__ + - ### Features + - Next Generation Resilience Hub now supports filtering and sorting failure mode assessments, resource type filtering in ListResources, cross-region and cross-account topology edges, data recovery achievability status, and more granular dependency discovery progress tracking. + +## __Amazon AppConfig__ + - ### Features + - Update ExperimentRun APIs to support ConflictExceptions. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - AgentCore Gateway now supports mapping allowed scopes to separate advertised scopes on the inbound authorizer. + +## __Amazon EC2 Container Service__ + - ### Features + - Amazon ECS now automatically detects the correct CPU architecture for Express Mode services. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Replace Root Volume now supports a VolumeId parameter. This allows the customer to pass in a pre-prepared volume as the target root volume for an RRV workflow. + +## __Amazon Location Service Places V2__ + - ### Features + - Added AddressNamesMode, AddressNameTranslations, MobilityMode, PostalCodeMode, SecondaryAddresses, and DriveThrough features across Places V2 APIs to support address name formatting, multilingual translations, travel-aware search, multi-city postal codes, and unit-level address resolution. + +# __2.47.1__ __2026-07-07__ +## __AWS Config__ + - ### Features + - Added support for connecting AWS Config to third-party cloud service providers. New APIs include PutConnector, GetConnector, DeleteConnector, and ListConnectors for managing connectors, and PutThirdPartyServiceLinkedConfigurationRecorder for creating third-party service-linked recorders. + +## __AWS Lambda__ + - ### Features + - AWS Lambda Durable Functions now supports customer managed KMS keys. This allows customers to configure a KMS key in Durable Config to have all their durable execution data encrypted. + +## __AWS Marketplace Catalog Service__ + - ### Features + - This release enhances the ListEntities API to support ResellerRole filter for ResaleAuthorization entity. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Re-resolve SSO access token on each credential refresh in the SSOCredentialsProvider instead of caching it at construction time ensuring that refreshed tokens (for example from running `aws sso login`) are always used. + +## __AWS SecurityHub__ + - ### Features + - release SecurityHub MultiCloud integration with Azure + +## __AWSMarketplace Metering__ + - ### Features + - The usage reporting window for the BatchMeterUsage API has been extended from 6 hours to 24 hours. Sellers can now submit usage records for up to 24 hours after a metered event occurs. The existing 6-hour grace period at the end of a billing cycle still applies. + +## __Amazon Connect Service__ + - ### Features + - Adds support for CreateAuthCode and DeleteSession APIs. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This launch surfaces the public SSM parameter associated with public AMIs in the AMI metadata. + +## __Amazon Route 53 Global Resolver__ + - ### Features + - Adds ListSharedDNSViews operation to list all DNS Views shared with caller using AWS Resource Access Manager. Also updates ListHostedZoneAssociations operation so that resource ARN param is optional, allowing caller to list all HostedZoneAssociations in account. + +## __Amazon Simple Systems Manager (SSM)__ + - ### Features + - Adding SSM Cloud Connector to support Azure Virtual Machines onboarding to AWS Systems Manager + +## __Inspector2__ + - ### Features + - This release extends vulnerability management to Azure VM, container registries and function apps. Adds support for per-member-account scan configuration settings. + +## __Partner Central Revenue Measurement API__ + - ### Features + - Add support for AWS Partner Central Revenue Measurement API for creating, managing, and tracking revenue attributions and marketplace revenue share allocations. + +# __2.47.0__ __2026-07-06__ +## __AWS Billing__ + - ### Features + - Adds support for managing AWS account credits and billing preferences, including retrieving credit details, viewing per-month credit allocation history, redeeming promotional codes, and configuring credit sharing and billing preferences. + +## __AWS SDK for Java v2__ + - ### Features + - Moved auth scheme and endpoint resolution from per-service generated interceptors to shared pipeline stages, establishing clear separation between customer extension points and SDK internals. This also fixes a bug where credentials injected via `ExecutionInterceptor.modifyRequest()` were not being used for signing ([#6486](https://github.com/aws/aws-sdk-java-v2/issues/6486)) + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Updating Lake Formation Access Grants Plugin version to 1.4.2 + - Contributed by: [@rajasbh-aws](https://github.com/rajasbh-aws) + +## __Amazon CloudWatch Logs__ + - ### Features + - Added PutStorageTierPolicy and GetStorageTierPolicy APIs to Amazon CloudWatch Logs. Customers can now configure account-level Intelligent Tiering to automatically optimize log storage costs by moving infrequently accessed data to lower-cost storage tiers. + +## __Amazon OpenSearch Service__ + - ### Features + - This release introduces Saved Object Migration APIs, enabling users to migrate dashboards, visualizations, index patterns, and other saved objects from a data source into an Amazon OpenSearch Service application workspace with configurable export filters and conflict resolution strategies. + +## __MailManager__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@rajasbh-aws](https://github.com/rajasbh-aws) diff --git a/changelogs/2.48.x-CHANGELOG.md b/changelogs/2.48.x-CHANGELOG.md new file mode 100644 index 000000000000..60785ca8e588 --- /dev/null +++ b/changelogs/2.48.x-CHANGELOG.md @@ -0,0 +1,174 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.48.4__ __2026-07-20__ +## __AWS CRT HTTP Client__ + - ### Bugfixes + - Preserve the underlying CRT HttpException (including the CRT error code) as the cause of the SSLHandshakeException and ConnectException surfaced for TLS negotiation failures and socket timeouts, so callers can differentiate transient failures from persistent ones by inspecting the exception cause chain. + +## __AWS MediaTailor__ + - ### Features + - This change adds api support for configuring ad decision server timeouts and concurrency fields on MediaTailor playback configurations + +## __AWS Organizations__ + - ### Features + - Updated InvalidInputException error documentation to clarify that the service validates free-text field values against common cross-site scripting (XSS) patterns. + +## __AWSMarketplace Metering__ + - ### Features + - For new SaaS product integrations, CustomerIdentifier is not populated in ResolveCustomer responses and is not supported in BatchMeterUsage. Use CustomerAWSAccountId and LicenseArn instead. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Add W3C trace context headers (traceparent, tracestate, baggage) and X-Amzn-Trace-Id to InvokeHarness request for end-to-end observability propagation. Add toolResultMetadata to the streaming content block delta for MCP tool result meta delivery without oversized SSE frames. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - This release adds support for specifying a connector version on Gateway targets to pin the connector's tool schema. It also introduces web-search connector version 1.2.0, which adds agent-side domain filtering, published date range filtering, and admin-side domain allowlisting. + +## __Amazon QuickSight__ + - ### Features + - Adds support for custom permissions for Triggers, allowing administrators to control user access to Schedule, Inbound Email and Quick Event triggers. + +## __Amazon Simple Email Service__ + - ### Features + - Amazon SES introduces three new Pricing Plans (Essentials, Pro, Enterprise), which bundle SES features under one pricing umbrella. The new PutAccountPricingAttributes API lets the user set the account's plan, while current plan retrievalif done through the new PricingAttributes field on GetAccount. + +## __Inspector2__ + - ### Features + - Adds Windows path support for deep inspection. Fixes tag propagation for connector CloudFormation stack operations. + +# __2.48.3__ __2026-07-17__ +## __AWS CRT HTTP Client__ + - ### Features + - Add a minTlsVersion(TlsVersion) builder option on AwsCrtHttpClient and AwsCrtAsyncHttpClient that enforces a minimum TLS protocol version for outbound connections. Currently supports TlsVersion.TLS_1_3 and TlsVersion.SYSTEM_DEFAULT (the default). Fixes [#5619](https://github.com/aws/aws-sdk-java-v2/issues/5619). + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Amazon Cognito user pools now support sending SMS via AWS End User Messaging. A new EumsSms object in SmsConfigurationType lets you deliver MFA and verification texts through AWS End User Messaging, alongside the existing Amazon SNS option. + +## __Amazon GameLift Streams__ + - ### Features + - Amazon GameLift Streams now supports assigning an IAM role to a stream session, enabling your application to securely access resources in your AWS account, such as Amazon S3 buckets and DynamoDB tables. + +## __Amazon Kinesis Analytics__ + - ### Features + - Support for Flink 2.3 in Managed Service for Apache Flink + +## __Amazon Relational Database Service__ + - ### Features + - Adds the AssociatedRoles parameter to CreateDBCluster, RestoreDBClusterFromSnapshot, RestoreDBClusterToPointInTime, and RestoreDBClusterFromS3, letting customers associate IAM roles with an Aurora DB cluster at create or restore time instead of calling AddRoleToDBCluster afterward. + +## __odb__ + - ### Features + - Adds support for sourcing Autonomous Database admin and wallet passwords from customer-managed AWS Secrets Manager secrets, including password source configuration and summaries, and enabling or disabling the OCI IAM service role for Secrets Manager integration via InitializeService. + +# __2.48.2__ __2026-07-16__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Sustainability__ + - ### Features + - Adds support for retrieving estimated water allocation data. + +## __Amazon Chime SDK Voice__ + - ### Features + - Marked CreateProxySession, DeleteProxySession, GetProxySession, ListProxySessions, UpdateProxySession, PutVoiceConnectorProxy, DeleteVoiceConnectorProxy, and GetVoiceConnectorProxy as deprecated. + +## __Amazon EMR__ + - ### Features + - Amazon EMR updates the Session object returned by GetSession API + +## __Amazon Omics__ + - ### Features + - Adds support for returning the task UUID (universally unique identifier) in GetRunTask and ListRunTasks responses + +## __Amazon Redshift__ + - ### Features + - Amazon Redshift - Added support for rg.large and rg.12xlarge node types in CreateCluster, ModifyCluster, and ResizeCluster API operations. + +## __Amazon SageMaker Service__ + - ### Features + - Release support for g7 instance type for SageMaker inference endpoints. + +## __Amazon Simple Storage Service__ + - ### Features + - Documentation update for removing the 30 day minimum restriction for transition to Standard-IA or OneZone-IA storage classes + +# __2.48.1__ __2026-07-15__ +## __AWS SDK for Java v2__ + - ### Bugfixes + - Fixed an issue where `ContainerCredentialsProvider` rejected the EKS Pod Identity IPv6 endpoint unless `AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE` was set to `IPv6`. + - Contributed by: [@jtuglu1](https://github.com/jtuglu1) + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Fix HarnessEndpointArn pattern to match the actual service-emitted ARN format ('harness-endpoint' instead of 'endpoint'). Add additionalParams to Gemini model configuration for passing provider-specific parameters through to the model unchanged. + +## __Amazon HealthLake__ + - ### Features + - AWS HealthLake now offers data transformation in Preview to convert CSV and C-CDA data to FHIR R4. Customers can maintain reusable mapping profiles, run sync or async jobs with provenance tracking and drift detection, and use an AI agent to build and edit mapping logic from natural language. + +## __Amazon Relational Database Service__ + - ### Features + - Adds support for modifying EngineLifecycleSupport on DB instances and DB clusters through ModifyDBInstance and ModifyDBCluster. + +## __Elastic Load Balancing__ + - ### Features + - This release adds support for the IpAddressType field on SourceIpConfig, enabling Network Load Balancer listener rules to match traffic based on whether the source IP is IPv4 or IPv6. + +## __Payment Cryptography Data Plane__ + - ### Features + - Adds support for UnionPay session key derivation to the GenerateAuthRequestCryptogram, VerifyAuthRequestCryptogram, GenerateMac, and VerifyMac APIs. + +## __S3 Event Notification__ + - ### Features + - Added `awsGeneratedTags` field to `S3Bucket` in the S3 Event Notifications module. Amazon S3 emits AWS-generated system tags on the `bucket` portion of event notifications when system tags are enabled on the source bucket. SDK consumers on the SNS/SQS/Lambda delivery paths can now access these tags via `S3Bucket#getAwsGeneratedTags()`. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@jtuglu1](https://github.com/jtuglu1) +# __2.48.0__ __2026-07-14__ +## __AWS Cloud Map__ + - ### Features + - Fixed Cloud Map endpoint resolution to correctly route to the dualstack endpoint when dualstack is enabled. + +## __AWS Lambda__ + - ### Features + - AWS Lambda now returns a new DependencyError value in StateReasonCode and LastUpdateStatusReasonCode to provide more actionable information when a function reaches a failed state due to an error from an upstream dependency or service. + +## __AWS SecurityHub__ + - ### Features + - AWS Security Hub now provides an AI inventory, giving central security teams a continuously updated, organization-wide view of AI assets and their security posture + +## __Amazon Connect Service__ + - ### Features + - This release adds SearchRules API which can be used to search for rules within an Amazon Connect instance. + +## __Amazon EMR Containers__ + - ### Features + - Introduced 5 new fields across 3 APIs as part of Spark Connect server launch for EMR on EKS. The fields added are sessionIdleTimeoutInMinutes, sessionEnabled, endpointToken, authProxyUrl and encryptionKeyArn. + +## __Amazon S3__ + - ### Features + - Add presigned URL download support to S3AsyncClient and S3 Transfer Manager. Customers can now download S3 objects using pre-signed URLs through the SDK's async client pipeline without needing AWS credentials configured. + + - ### Bugfixes + - Fix bug where S3 PutObject would hang indefinitely when using AwsCrtAsyncHttpClient with chunkedEncodingEnabled(false) + +## __Amazon Simple Systems Manager (SSM)__ + - ### Features + - Update AWS Systems Manager Automation Targets to be correct max value. + +## __AmazonMQ__ + - ### Features + - This release adds storage size parameter for Amazon MQ for RabbitMQ cluster deployment broker on engine version RabbitMQ 4.2. You can now set a configurable storage size within a range of sizes dependent on broker instance size. + +## __Elastic Disaster Recovery Service__ + - ### Features + - Fast recovery of EC2 based drs workloads by skipping the conversion step + diff --git a/changelogs/2.49.x-CHANGELOG.md b/changelogs/2.49.x-CHANGELOG.md new file mode 100644 index 000000000000..f609c7b191f1 --- /dev/null +++ b/changelogs/2.49.x-CHANGELOG.md @@ -0,0 +1,290 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.49.6__ __2026-07-29__ +## __AWS Database Migration Service__ + - ### Features + - Updated documentation for various DMS Schema Conversion operations + +## __AWS Glue__ + - ### Features + - Adding filtering, partitioning, and VPC support to AWS Glue REST API connector + +## __AWS IoT SiteWise__ + - ### Features + - We have released a new set of APIs in support of a major new feature within AWS IoT SiteWise called Scenario Discover. Please see user guide about the feature and the API guide in public documentation for new APIs. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Fixed an issue where duplicate signing-region endpoint keys in service metadata caused ServiceMetadata static initialization to fail with "Duplicate keys are provided". The generated SIGNING_REGIONS_BY_REGION map now tolerates duplicate keys. + +## __AWS WAFV2__ + - ### Features + - AWS WAF now supports pre-parse text transformations, letting you normalize raw query strings before parsing, available on rule statements that use SingleQueryArgument or AllQueryArguments as the FieldToMatch. AWS WAF also added 10 new text transformations, including ModSecurity v3 parity options. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds support for policy-based routing on AWS Transit Gateway, enabling you to route traffic based on 5-tuple matching (source IP, destination IP, source port, destination port, and protocol) using new policy table entry APIs that direct matching traffic to a target route table. + +## __Amazon GameLift Streams__ + - ### Features + - Adds ListApplicationShaderCaches API to retrieve shader cache metadata for applications and adds stream URLs, which give end users temporary, unauthenticated access to a stream session in their browser. Includes CreateStreamUrl, GetStreamUrl, ListStreamUrls, and RevokeStreamUrl operations. + +# __2.49.5__ __2026-07-28__ +## __AWS DataSync__ + - ### Features + - Adds Enhanced mode support for EFS and FSx Lustre locations without an agent, and for HDFS (TDE), Azure Blob, and object storage locations with an agent. HDFS Enhanced mode supports multiple NameNodes for High Availability. Enhanced mode agents can now be deployed on Microsoft Hyper-V. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - AgentCore Identity now supports Private Key JWT client authentication for OAuth 2.0 credential providers. Agents can authenticate to identity provider token endpoints with a JWT client assertion signed by a customer-managed AWS KMS asymmetric key, eliminating the need for client secrets. + +## __Amazon Connect Service__ + - ### Features + - Documentation updates for SearchRules, AssociateRoutingProfileQueues, CreateRoutingProfile, AssociateContactWithUser CreateTaskTemplate, and UpdateTaskTemplate + +## __IAM Roles Anywhere__ + - ### Features + - Increases certificate string length for trust anchor source data to support new adjustable trust anchor limits. + +## __TrustedAdvisor Public API__ + - ### Features + - Adds ListRecommendationsForResource API and four CheckSummary fields (resourceArnQueryable, awsResourceTypes, checkGranularity, recommendationId) to retrieve recommendations for a given resource ARN. + +# __2.49.4__ __2026-07-27__ +## __AWS Account__ + - ### Features + - This release adds support for the GetPrimaryEmailUpdateStatus API operation, which allows customers to retrieve the current status of a primary email address update request for an AWS account. The operation returns status information including whether the update is pending, completed, or failed. + +## __AWS Billing and Cost Management Data Exports__ + - ### Features + - With this release, customers can configure their data exports to deliver CSV reports in ZIP compressed format. + +## __AWS Clean Rooms ML__ + - ### Features + - This release adds support for the CR.8X worker type for SQL (32 vCPU) + +## __AWS Clean Rooms Service__ + - ### Features + - This release adds support for the CR.8X worker type for SQL (32 vCPU) + +## __AWS Glue__ + - ### Features + - Adds BatchGetDataQualityRulesetEvaluationRun API to retrieve multiple runs in one call, ObservationScope and ObservationMode parameters for anomaly detection, writing evaluation results to Data Catalog tables, and custom log group paths for recommendation runs. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Security Agent__ + - ### Features + - AWS Security Agent adds a new task hours field that reflects the active work done for a task. + +## __Amazon EMR Containers__ + - ### Features + - With this launch, you can now set concurrent job limits on a virtual cluster, giving you fine-grained control over how many job runs execute at once and how many can wait in queue. + +## __Amazon QuickSight__ + - ### Features + - Added new Governance fields to Custom Permissions API to support Deny By Default functionality. + +## __Amazon SageMaker Service__ + - ### Features + - This release adds LoRA adapters, training plans, and new instance types to SageMaker inference optimization. CreateAIRecommendationJob accepts optional AdapterSource and CreateOptimizationJob accepts optional TrainingPlanArns and the ml.g7e and ml.p6-b200 families. + +## __Partner Central Account API__ + - ### Features + - Adds optional headquarters location to StartProfileUpdateTask, letting partners record their headquarters as an ISO 3166 country and subdivision code on their profile. When headquarters is provided, both the country and subdivision codes are required. + +## __S3 Transfer Manager__ + - ### Bugfixes + - Fix race condition when invoking pausing upload that can cause a `NullPointerException`. + +# __2.49.3__ __2026-07-24__ +## __AWS Artifact__ + - ### Features + - Added the PutComplianceInquiryFeedback API, enabling customers to submit feedback on compliance inquiry responses. Customers can rate responses as helpful or not helpful and provide optional reason codes and comments. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Fixed several delegating AsyncRequestBody implementations (including those used by S3 Transfer Manager uploads) that reported the request-body type as unknown in the user-agent business metric instead of the actual type (file, bytes, or stream). + - Update `ResponseInputStream`, to only return `0` from `available()` if the stream is closed; in other cases, if the wrapped stream returns 0 from `available()`, `1` is returned instead. This is to avoid cases where other classes such as [`java.util.zip.GZIPInputStream`](https://docs.oracle.com/javase/8/docs/api/java/util/zip/GZIPInputStream.html) misinterpret this as meaning the stream is closed. + +## __Amazon CloudWatch Application Insights__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.1. The SDK will prioritize its most performant protocol. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Amazon Cognito user pools now support the AdminGetUserAuthFactors operation, which lets administrators retrieve the configured authentication factors (such as password, SMS, email, and TOTP) available for a specific user in a user pool. + +## __Amazon DynamoDB__ + - ### Features + - Endpoint test standardizations + +## __Amazon Neptune Graph__ + - ### Features + - Update validations for Tag Keys and KMS Key ARNs. + +## __RTBFabric__ + - ### Features + - The deprecated inboundLinksCount field has been removed from the GetResponderGateway API response. Customers who previously relied on this field should use linksRequestedCount instead. + +## __odb__ + - ### Features + - Documentation-only update to clarify the operation-specific valid values for the externalIdType field. + +# __2.49.2__ __2026-07-23__ +## __AWS Backup Gateway__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __AWS Billing and Cost Management Pricing Calculator__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __AWS Billing and Cost Management Recommended Actions__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __AWS CRT HTTP Client__ + - ### Features + - Add `numEventLoopThreads(Integer)` to `AwsCrtAsyncHttpClient.Builder` and `AwsCrtHttpClient.Builder` to configure the number of CRT event-loop (IO) threads. When set, the client owns a private `EventLoopGroup` of that size (must be greater than 1); when unset, it shares the process-wide default group. + +## __AWS Elemental MediaPackage v2__ + - ### Features + - This release adds support for non-epoch-locked CMAF ingest in MediaPackageV2 channels. + +## __Amazon AppStream__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.1. The SDK will prioritize its most performant protocol. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Adds support for the Bring Your Own Storage(BYOS) feature in AgentCore Browser and Code Interpreter. Enables mounting S3Files and EFS File Systems via Access points. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adds support for the Bring Your Own Storage(BYOS) feature in AgentCore Browser and Code Interpreter. Enables mounting S3Files and EFS File Systems via Access points. + +## __Amazon DataZone__ + - ### Features + - Adds support for notebook sync with S3 ipynb files + +## __Amazon GameLift Streams__ + - ### Features + - GameLift Streams now supports configuring a custom aspect ratio per stream session to accommodate different player devices. Supported aspect ratios include landscape, portrait, and square - delivering a full-screen experience without letterboxing or cropping. + +## __Amazon Kendra Intelligent Ranking__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __Amazon QuickSight__ + - ### Features + - Added new capabilities to custom permissions profiles to control access to Amazon Quick through the browser extension and Microsoft Word, Outlook, Excel, and PowerPoint add-ins. + +## __Amazon SageMaker Service__ + - ### Features + - Release support for c6a, m6a, m6g, m7g, m8g instance types for SageMaker HyperPod + +## __Amazon Workspaces Instances__ + - ### Features + - This release adds Smithy RPC v2 CBOR as an additional protocol alongside the existing AWS JSON 1.0. The SDK will prioritize its most performant protocol. + +## __Redshift Data API Service__ + - ### Features + - This release include long polling provids a new parameter wait-time-seconds to 5 API operations, new API ListSessions, and a new parameter execution-mode to BatchExecuteStatement + +# __2.49.1__ __2026-07-22__ +## __ARC - Region switch__ + - ### Features + - Adds support for a client token in StartPlanExecution to make plan execution requests idempotent for safe retries. + +## __AWS CRT HTTP Client__ + - ### Bugfixes + - Do not set the Content-Length header on a request that already carries Transfer-Encoding. Emitting both violates RFC 7230 and was rejected by the underlying CRT layer; this aligns the CRT client with the Netty client's existing behavior for chunked requests. + +## __AWS Parallel Computing Service__ + - ### Features + - AWS PCS Node Lifecycle Actions provides a structured way to run custom scripts at defined points in a compute node's lifecycle directly through the AWS PCS compute node group API. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon CloudWatch__ + - ### Features + - Adds documented value constraints for CloudWatch Log Alarm scheduled query configuration fields, and makes LogGroupIdentifiers optional for log alarms. + +## __Amazon GuardDuty__ + - ### Features + - Amazon GuardDuty now returns filter lifecycle metadata in GetFilter responses. The response includes createdAt and updatedAt timestamps and a version number that increments on each update, giving you visibility into when a filter was created and last modified. + +## __Amazon Prometheus Service__ + - ### Features + - Add CloudWatch dataset destinations for Amazon Managed Service for Prometheus collectors. + +## __Amazon S3__ + - ### Bugfixes + - Fix a race condition in multipart upload with low maxInFlightParts where CompleteMultipartUpload could be initiated while the final part was still uploading. + +## __Amazon Simple Email Service__ + - ### Features + - Launching DEED and MREP in US GOV + +## __CloudWatch Observability Admin Service__ + - ### Features + - Enablement for ALB and Bedrock Knowledge Base logs via Observability Admin Telemetry Rule for account and organization level + +## __Elastic Load Balancing__ + - ### Features + - This adds CLI examples for the IpAddressType field on SourceIpConfig, enabling Network Load Balancer listener rules to match traffic based on whether the source IP is IPv4 or IPv6. + +## __Partner Central Account API__ + - ### Features + - Adds Qualifications Association APIs that enable partners to associate a subsidiary account's qualifications with a primary account. Once associated, qualifications are shared across all connected accounts and scorecards are consolidated. Partners can start and track association and disassociation. + +# __2.49.0__ __2026-07-21__ +## __AWS EntityResolution__ + - ### Features + - Add support for real time matching with AWS Entity Resolution matching workflows with advanced rule sets. + +## __AWS Invoicing__ + - ### Features + - Added the SendProcurementPortalValidation and VerifyProcurementPortalValidation APIs. You can use the AWS SDKs to self-service activate your Procurement Portal Preferences created on the Billing Preferences page with a one-time-passcode (OTP) delivered to your portal. + +## __AWS SDK for Java v2__ + - ### Features + - Update Netty to 4.1.136 + + - ### Bugfixes + - Eliminate per-operation lambdas for endpoint and auth scheme resolution in generated clients, permanently fixing constant pool overflow for large services like EC2 Internal. + +## __Amazon EMR Containers__ + - ### Features + - Added support for the DeleteSecurityConfiguration API, which allows customers to delete security configurations in Amazon EMR on EKS. Also added authenticationConfiguration in securityConfigurationdata structure. + +## __Amazon Redshift__ + - ### Features + - Amazon Redshift - Added support for managing Query Editor V2 IAM Identity Center applications via new CreateQev2IdcApplication, DescribeQev2IdcApplications, ModifyQev2IdcApplication, and DeleteQev2IdcApplication API operations. + +## __Amazon Simple Systems Manager (SSM)__ + - ### Features + - Added a WarningMessage field to Automation along with corresponding public documentation. + +## __Inspector2__ + - ### Features + - GA date - July 21st 2026, remove Tags field from ListCodeSecurityIntegration and ListCodeSecurityScanConfiguration. + +## __Redshift Data API Service__ + - ### Features + - update the workgroupArn to include EUSC partition, tests in THF Gamma and Prod no issue + +## __Timestream InfluxDB__ + - ### Features + - This release adds support for custom plugins in Amazon Timestream for InfluxDB. InfluxDB 3 Core and Enterprise DB parameter groups now accept a plugin repository URL and optional AWS Secrets Manager secret ARN, so the Processing Engine loads your Python plugins from a public or private repository. + diff --git a/changelogs/2.50.x-CHANGELOG.md b/changelogs/2.50.x-CHANGELOG.md new file mode 100644 index 000000000000..d579e3fb1eb2 --- /dev/null +++ b/changelogs/2.50.x-CHANGELOG.md @@ -0,0 +1,146 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.50.3__ __2026-08-03__ +## __AWS Direct Connect__ + - ### Features + - Added route visibility support for AWS Direct Connect, allowing customers to call ListVirtualInterfaceRoutes to view the BGP routes including AS path and BGP communities advertised over their virtual interfaces. + +## __AWS Elemental MediaConvert__ + - ### Features + - Updates Kantar server URL validation to accept Fifty5Blue domain. Adds support for output to S3 Glacier Instant Retrieval. + +## __AWS Network Firewall__ + - ### Features + - This launch allows customers to use Network Firewall as an explicit Proxy and protect their workloads against threat of data exfiltration. + +## __AWS WAFV2__ + - ### Features + - Updated descriptions for number of PreParseTextTransformations allowed per rule statement + +## __Amazon EKS Auth__ + - ### Features + - Added eksNodeName, instanceId, and zone optional parameters to the AssumeRoleForPodIdentity API. + +## __CloudWatch Observability Admin Service__ + - ### Features + - Launch CMK support for Telemetry Enablement Organization and Account Rules. + +## __Timestream InfluxDB__ + - ### Features + - This release adds support for customer-managed backup restore, and encryption of new DbInstances and DbClusters using customer-managed KMS keys. + +# __2.50.2__ __2026-07-31__ +## __AWS Billing__ + - ### Features + - Adds GetEnterpriseSupportChargeSummary, GetEnterpriseSupportContractDetails, and ListEnterpriseSupportLinkedAccountCharges. These APIs provide first-time programmatic access to billing data for Enterprise Support usage previously only available upon request through AWS Concierge or Support. + +## __AWS CloudFormation__ + - ### Features + - Adding enum for sensitive property to DriftIgnoredReason + +## __AWS Elemental Inference__ + - ### Features + - AWS Elemental Inference now supports graphic composition on cropped video outputs, enabling branded graphics and other visual elements to be overlaid as part of the inference workflow. + +## __AWS Marketplace Catalog Service__ + - ### Features + - This release enhances the ListEntities API to support TargetAgreementId, TargetAgreementIntent, and CreatedBySource filters for the Offer entity type. + +## __AWS Network Firewall__ + - ### Features + - Doc Updates for Container Attributes + +## __AWS Outposts__ + - ### Features + - Adds the "EKS" value to the AWSServiceName enum and marks the Address field as sensitive. + +## __AWS Resilience Hub V2__ + - ### Features + - Adding support for new testing capability in AWS Resilience Hub. + +## __Amazon Bedrock Runtime__ + - ### Features + - Added support for mid-conversation tool changes in the Amazon Bedrock Converse and ConverseStream APIs + +## __Amazon CloudWatch Logs__ + - ### Features + - Amazon CloudWatch Logs now lets you create and update lookup tables directly from CloudWatch Logs query results by passing a queryId, and configure a lookup table as a scheduled query destination so it refreshes automatically with the latest query results on each run. + +## __Amazon DataZone__ + - ### Features + - Adding support for enhanced Git experience in Sagemaker Unified Studio. + +## __Amazon Prometheus Service__ + - ### Features + - Amazon Managed Service for Prometheus adds support for an Amazon OpenSearch Service exporter for managed collectors. + +## __Amazon QuickSight__ + - ### Features + - Adding TopicV2 management APIs, adding possibility to use Topics in Analysis + +## __Amazon Relational Database Service__ + - ### Features + - Adds StorageOperationStatus and StorageOperationPercentProgress to DescribeDBInstances, letting you monitor RDS storage initialization and optimization progress. + +## __Amazon Transcribe Streaming Service__ + - ### Features + - This release adds a new optional TranscriptFormat parameter to the Amazon Transcribe streaming API, letting customers select spoken or written form for numeric and formatted output. + +## __AmazonConnectCampaignServiceV2__ + - ### Features + - Launching feature for abandonment rate pacing control for outbound campaigns. + +# __2.50.1__ __2026-07-30__ +## __AWS Billing and Cost Management Pricing Calculator__ + - ### Features + - Removing Smithy RPC v2 CBOR support that was added in previous SDK release. + +## __AWS Billing and Cost Management Recommended Actions__ + - ### Features + - Removing Smithy RPC v2 CBOR support that was added in previous SDK release. + +## __AWS SDK for Java v2__ + - ### Features + - Add the `@SdkAdvancedApi` annotation, which marks APIs that are error-prone to implement, override, call, or configure so that using them incorrectly compiles cleanly but can fail or misbehave at runtime. The annotation records structured guidance (the risky usage kind, an explanation of the contract to uphold, a safer alternative, and a documentation link) and is applied to several streaming and interceptor extension points, including AsyncRequestBody, AsyncResponseTransformer, ContentStreamProvider, the mutating ExecutionInterceptor content hooks, and the FUTURE_COMPLETION_EXECUTOR advanced client option. + - Updated endpoint and partition metadata. + +# __2.50.0__ __2026-07-30__ +## __AWS Identity and Access Management__ + - ### Features + - Improved IAM Policy Simulator accuracy. Simulator now evaluates SCP conditions and resource scoping, returns explicitDeny for explicit SCP denials, and reports accurate cross-account decisions. + +## __AWS Lambda__ + - ### Features + - Add Python3.15 (python3.15) and NodeJs 26 (nodejs26.x) support to AWS Lambda + +## __AWS Network Firewall__ + - ### Features + - Adds UPDATING field to Container Association Status + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Improve endpoint resolution performance by replacing URI.create with a lightweight EndpointUrl. + +## __AWS Security Agent__ + - ### Features + - Adds support for providing a branch override when configured integrated repositories + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adds support for configuring models through the OpenResponses API for custom evaluators. CreateEvaluator and UpdateEvaluator now accept an OpenResponses model configuration for LLM-as-a-Judge evaluations. + +## __Amazon S3__ + - ### Bugfixes + - Honor an explicit `S3Configuration.expectContinueEnabled(false)` when cross region access is enabled. + +## __Amazon SageMaker Service__ + - ### Features + - Adds support for g7 family instance types for SageMaker Studio JupyterLab and CodeEditor apps for IAD (us-east-1), PDX (us-west-2), CMH (us-east-2). + +## __Managed Streaming for Kafka__ + - ### Features + - Amazon MSK Express brokers now support streaming tables for Apache Iceberg, continuously materializing Apache Kafka topics as Iceberg tables in Amazon S3 Tables. Express brokers also now support data delivery to Amazon S3 general purpose buckets. + +## __PricingPlanManager__ + - ### Features + - Adds support for Public PricingPlanManager SDK + diff --git a/changelogs/2.51.x-CHANGELOG.md b/changelogs/2.51.x-CHANGELOG.md new file mode 100644 index 000000000000..aa64faf12235 --- /dev/null +++ b/changelogs/2.51.x-CHANGELOG.md @@ -0,0 +1,218 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.51.4__ __2026-08-10__ +## __AWS Elemental Inference__ + - ### Features + - Added support for the SearchFixtures API and DataSourceConfiguration, enabling customers to map fixture event data onto clipping outputs for improved feature accuracy. + +## __AWS Elemental MediaLive__ + - ### Features + - Added VirtualSourceAddress to multicast output destinations for MediaLive Anywhere channels. Specifies the source IP address for outbound multicast packets when downstream networks enforce source-IP filtering. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Reduce generated client source and bytecode size for JSON, CBOR, and Smithy RPC v2 protocol services by generating the error-metadata mapper once per client instead of once per operation. + +## __Amazon Connect Service__ + - ### Features + - Added Malay language option to use AI to automatically fill evaluation forms in Malay + +## __Amazon SageMaker Runtime__ + - ### Features + - Added the PrefixAwareId header to InvokeEndpoint and InvokeEndpointWithResponseStream. This optional parameter serves as a routing hint for endpoints configured with prefix-aware routing, differentiating routing decisions for requests that share the same prompt prefix. + +## __Amazon SageMaker Service__ + - ### Features + - Added PREFIX AWARE routing strategy and PrefixAwareRoutingConfig to CreateEndpointConfig. Configure PrefixLength and ConcurrencyThreshold to route requests that share the same prompt prefix to the same instance. + +# __2.51.3__ __2026-08-07__ +## __AWS Amplify__ + - ### Features + - Increased the maximum allowed length of the oauthToken parameter in the CreateApp and UpdateApp APIs to support longer OAuth tokens issued by third-party Git providers. + +## __AWS Elemental MediaPackage v2__ + - ### Features + - StreamNameOutputMode - a new optional field on MediaPackageV2 OriginEndpoints that lets customers choose whether egress manifests use numeric stream indices (default) or encoder-assigned stream names from the input + +## __AWS MediaTailor__ + - ### Features + - Added support for inserting ads via the VAST Ad Buffet standard. You can now configure MediaTailor to insert ads in sequence order using the AdSequencingMode setting in your playback configuration. Standalone ads are used as fallbacks when a sequenced ad is unavailable. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Correctly support endpoint expressions with multiple chained assigns. + +## __AWS Security Agent__ + - ### Features + - Added enableEmailMfa input field on Actor to enable email-based MFA during penetration tests. When enabled, a server-generated mfaForwardingAddress is returned. Set up a forwarding rule in your email provider to forward MFA emails to this address so the agent can complete email-based MFA login flows + +## __Amazon Connect Service__ + - ### Features + - Supports updating the task template associated with in-progress task contacts using the new UpdateContactTaskTemplate API. This enables supervisors and developers to dynamically reassign task templates without creating a new task. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds support for BGP route protection in Amazon VPC IP Address Manager (IPAM), including route discovery, RPKI route protection findings, and delegated RPKI (Internet Registry Associations, routing policy registrations, and ROA management) for BYOIP prefixes. + +## __Amazon HealthLake__ + - ### Features + - Adds provenanceEnabled to StartFHIRImportJob + +## __Amazon SageMaker Service__ + - ### Features + - Amazon SageMaker adds maintenance lifecycle statuses for Notebook Instances + +# __2.51.2__ __2026-08-06__ +## __AWS Backup__ + - ### Features + - AWS Backup now lets you create read-only access points for Amazon S3 recovery points, enabling you to access backup data using S3 APIs without initiating a restore. + +## __AWS Device Farm__ + - ### Features + - Adds support for service generated insights across runs, jobs, and tests. + +## __AWS End User Messaging Social__ + - ### Features + - Add support for WhatsApp Conversions APIs. + +## __AWS Marketplace Agreement Service__ + - ### Features + - GetAgreementTerms now returns a new term variant in AcceptedTerm, netPaymentTerm, with a paymentDuePeriod field (example "P30D"). + +## __AWS Marketplace Discovery__ + - ### Features + - GetOfferTerms now returns netPaymentTerm in offerTerms, specifying payment due period after invoice date. The paymentDuePeriod field uses ISO 8601 duration format (e.g., "P30D" for net 30 days). This is a backward-compatible addition. See API documentation for full structure and examples. + +## __AWS MediaTailor__ + - ### Features + - AWS Elemental MediaTailor now supports concurrent function execution. The new Concurrent Executor function type runs multiple independent child functions in parallel within a single lifecycle hook, reducing pipeline latency to the duration of the slowest call instead of the sum of all calls. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS SecurityHub__ + - ### Features + - Security Hub is adding a new public API, ListFreeTrialStatusesV2 to describe the free trial statuses of the Security Hub service and its opt-in features. + +## __Agent Registry__ + - ### Features + - Agent Registry's Public Preview release + +## __Agent Registry Control__ + - ### Features + - Agent Registry's Public Preview release + +## __Amazon Bedrock AgentCore__ + - ### Features + - Add support for capacity provider sessions in Amazon Bedrock AgentCore. Customers can now delete an active session running on a runtime instance launched through their capacity provider. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Add support for Gateway rate limits and Runtime instances in Amazon Bedrock AgentCore. Customers can now configure rate limits scoped to control request rates, token consumption rates, and active connection rates. Customers can now create capacity providers to launch runtimes on their EC2 instances. + +## __Amazon CloudWatch Logs__ + - ### Features + - This release adds index category support to the CloudWatch Logs DescribeFieldIndexes API. Customers can filter and identify DEFAULT, CUSTOM, AUTO, and INACTIVE field indexes. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds a new optional IncludeLocalZones parameter to the Spot Placement Score API that defaults to false. When set to true, the Spot Placement Score API will consider the relevant Local Zones with Spot capacity when computing the Spot Placement Score. + +## __Amazon GameLift__ + - ### Features + - Adds support for C8a, C8i, C9g, M8a, M8i, and M9g EC2 instance type families for managed EC2 and container fleets. Also adds explicit anchors on most string regexes. + +## __Amazon SageMaker Service__ + - ### Features + - Releases new Model Customization SequenceLength parameter for Training and g7 instance types for Training and Processing. + +## __Amazon Simple Storage Service__ + - ### Features + - AWS Backup now lets you create read-only access points for Amazon S3 recovery points, enabling you to access backup data using S3 APIs without initiating a restore. + +## __Auto Scaling__ + - ### Features + - EC2 Auto Scaling now supports being managed by other AWS services via the operator field. + +## __Managed Streaming for Kafka__ + - ### Features + - MSK Clusters can now deliver authorizer logs alongside broker logs to the destinations defined by you + +# __2.51.1__ __2026-08-05__ +## __AWS Certificate Manager Private Certificate Authority__ + - ### Features + - Private Certificate Authority service now supports RSASSA-PSS signing algorithm. + +## __AWS Glue__ + - ### Features + - Added the PutDataCatalogExportConfiguration to export Glue Data Catalog metadata to systems tables stored in S3 Tables. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Eliminate per-operation metric-publishing lambdas in generated clients by hoisting them into shared helper methods, reducing constant pool usage and class size for large service clients approaching the JVM per-class constant pool limit. + +## __AWS Sign-In Service__ + - ### Bugfixes + - Fixed an issue where credentials loaded from a login_session profile resolved the Signin client's configuration, such as region and endpoint_url, from the default profile instead of the profile that requested the credentials. + +## __AWSDeadlineCloud__ + - ### Features + - AWS Deadline Cloud now reports persistent volume costs alongside compute and license costs. Customers can view per-fleet storage costs in Usage Explorer by selecting the Usage Type grouping, helping them better understand the costs of their infrastructure. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adding support for fine-grained access control for AgentCore Memory through managed AgentCore Gateway HTTP Connectors. + +## __Amazon EC2 Container Service__ + - ### Features + - New enum values added for Agent Connectivity issues + +# __2.51.0__ __2026-08-04__ +## __AWS Identity and Access Management__ + - ### Features + - Updating endpoint generation logic + +## __AWS Organizations__ + - ### Features + - Improved accuracy of CloudTrail event documentation for AWS Organizations membership operations. + +## __AWS Single Sign-On Admin__ + - ### Features + - AWS IAM Identity Center now lets you create organization-level instances without enabling multi-account permissions. You can enable multi-account permissions during instance creation or later via console or API, which then provisions the necessary service-linked roles. + +## __Amazon Aurora DSQL__ + - ### Features + - UpdateCluster now checks the RemovePeerCluster permission on the specific cluster being removed, not a wildcard and docs now clarify how to set kmsEncryptionKey so the cluster uses the AWS-owned key. + +## __Amazon Connect Service__ + - ### Features + - Amazon Connect Customer now supports up to 50 attachments per email, increased from the previous limit of 10. The individual maximum attachment size limit of 20 MB and the total email size limit of 25 MB still hold true. + +## __Amazon DynamoDB__ + - ### Features + - Vector indexes are a type of index in Amazon DynamoDB that enable similarity search on vector embedding stored in your table items. Vector indexes use approximate nearest neighbor search to find items whose vectors are most similar to a query vector that you provide. + +## __Amazon DynamoDB Enhanced Client__ + - ### Features + - Adds SearchVectors and vector index support to the DynamoDB Enhanced Client, including vector index table operations, table.vectorIndex() search handles, and enhanced search request/response types. + - Adds annotation-driven vector index support to the DynamoDB Enhanced Client via @DynamoDbVectorAttribute, @DynamoDbSearchVectorsHashKey, and @DynamoDbSearchVectorsInlineFilterKey on bean and immutable schemas, enabling no-arg createTable() and vector search through annotation-derived table.vectorIndex() handles. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Amazon EC2 now supports Application Status Checks, a new status check that monitors your application's health through configurable HTTP(S) paths and ports, so you can detect and automatically respond to application-level impairments. + +## __Amazon WorkSpaces__ + - ### Features + - Added ClientExperiencePolicy to ClientProperties object for ModifyClientProperties and DescribeClientProperties APIs. + +## __Inspector2__ + - ### Features + - Adding Azure SBOM export capability. + +## __Partner Central Selling API__ + - ### Features + - Partners can now create leads with only 5 required fields and free-text values for all other fields, reducing import friction. Engagement invitations now include enrichment data (propensity scores, lead readiness) directly in the response. + diff --git a/changelogs/2.52.x-CHANGELOG.md b/changelogs/2.52.x-CHANGELOG.md new file mode 100644 index 000000000000..df8d49f1767c --- /dev/null +++ b/changelogs/2.52.x-CHANGELOG.md @@ -0,0 +1,80 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.52.1__ __2026-08-12__ +## __AWS Glue__ + - ### Features + - Documentation updates for materialized views APIs. + +## __AWS Identity and Access Management__ + - ### Features + - Introduced role manager, an IAM capability that automatically sets up the IAM roles your AWS services need. When you set up a supported service in the console, role manager creates a role for you or reuses an existing one from an AWS-managed template. + +## __AWS MediaConnect__ + - ### Features + - AWS MediaConnect now supports tuning the internal recovery latency between Router Inputs and Outputs to prioritize stream quality versus end-to-end latency. + +## __AWS Well-Architected Tool__ + - ### Features + - This change releases the Well-Architected Agent, a generative AI service that analyzes a customer's AWS environment and delivers personalized, prioritized recommendations across cost, security, performance, and resilience. + +## __Amazon Aurora DSQL__ + - ### Features + - Improved validation of Kinesis stream ARN format to ensure only valid ARN characters are accepted + +## __Amazon QuickSight__ + - ### Features + - Added APIs for DLP with Microsoft Purview (manage configs with label enforcement across Spaces, Chat, Knowledge Bases), Approval Workflows (CRUD for policies on asset sharing for Agents, Knowledge Bases, Spaces), and Limits Management (limit profiles for index storage and agent hours per user). + +## __odb__ + - ### Features + - Adds support for Oracle Exadata on Exascale Infrastructure (ExaDB-XS) resources including storage vaults and VM clusters. + +# __2.52.0__ __2026-08-11__ +## __AWS Clean Rooms Service__ + - ### Features + - Adds support for exporting redacted query execution logs in AWS Clean Rooms + +## __AWS Organizations__ + - ### Features + - Documentation update for AWS Organizations that clarifies valid input values for the HandshakePartyType parameter in the InviteAccountToOrganization. API ORGANIZATION is valid in responses only. valid input values are ACCOUNT and EMAIL + +## __AWS SDK for Java v2__ + - ### Features + - Added support for the AWS_IGNORE_CONFIGURED_ENDPOINT_URLS setting to skip endpoint URLs from environment variables and config files. + - Update Netty to 4.1.137 + + - ### Bugfixes + - Fixed the client-side rate limiting behavior of `AdaptiveRetryStrategy` under throttling conditions. Previously, the computed rate limit was overly aggressive, potentially allowing a request rate much lower than what the service allows, and was unstable, varying over time even when the service's allowed throughput was constant. + - Make individual parts retryable when an in-memory `AsyncRequestBody` (for example one created with `AsyncRequestBody.fromBytes`, `fromByteBuffer`, or `fromString`) is split, such as during an S3 multipart upload. The body in these cases is entirely in memory already so no data is copied and callers no longer need to wrap the body in `BufferedSplittableAsyncRequestBody` to get retries. + +## __Account Access__ + - ### Features + - Adds SDK support for AWS IAM account access manager, a feature that enables mapping of IAM roles to the users and groups in AWS IAM Identity Center. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Adding online eval arn as input for recommendation API + +## __Amazon CloudDirectory__ + - ### Features + - Added an end-of-support notice to Amazon Cloud Directory public CLI reference documentation. + +## __Amazon Connect Service__ + - ### Features + - Seven new APIs for managing custom metrics, including create, describe, update, and delete. Using Custom Metrics, customers of Amazon Connect Customer can tailor analytics dashboards to their needs by applying custom thresholds, filters, and calculations to one or more out of the box measurements. + +## __Amazon DataZone__ + - ### Features + - GetSubscriptionGrant now returns materialized asset scope name for mapping Lake Formation data cell filters or Redshift views to subscription grants. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - This feature would give customers the ability to selectively tune certain configurations of Kubernetes control plane components in an Amazon EKS cluster. + +## __Amazon Textract__ + - ### Features + - Amazon A2I entered maintenance mode in July 2026 and now rejects StartHumanLoop requests from accounts that it does not recognize as existing customers. This update adds a corresponding note to the HumanLoopConfig parameter documentation so that the API Reference and SDK docs explain this behavior. + +## __Apache HTTP Client 5__ + - ### Features + - Upgrade httpcomponents.client5 to 5.6.3 to address CVE-2026-64607 + diff --git a/changelogs/2.53.x-CHANGELOG.md b/changelogs/2.53.x-CHANGELOG.md new file mode 100644 index 000000000000..0b7527b3a3ff --- /dev/null +++ b/changelogs/2.53.x-CHANGELOG.md @@ -0,0 +1,165 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.53.3__ __2026-08-18__ +## __AWS Batch__ + - ### Features + - Update AWS Batch documentation with newer Fargate Supported configurations, notes, and fix broken Docker link re-directs. + +## __AWS Elemental MediaLive__ + - ### Features + - AWS Elemental MediaLive now supports SCTE-35 marker passthrough without IDR frame insertion for CMAF Ingest, MediaPackage V2, and transport stream outputs. + +## __AWS EntityResolution__ + - ### Features + - Added ResourceNotFoundException to DeleteSchemaMapping, DeleteMatchingWorkflow, DeleteIdMappingWorkflow, and DeleteIdNamespace. These operations now return a 404 ResourceNotFoundException (previously a 200 Success) when the target resource does not exist. + +## __AWS Marketplace Catalog Service__ + - ### Features + - Introducing two new APIs, DescribeAssessment and ListAssessments. These APIs expose validation issues on Marketplace resources. The validation issues are exposed via a newly created resource called Assessment. + +## __AWS Outposts__ + - ### Features + - AWS Outposts now supports VPC Endpoint configuration in CreatePrivateConnectivityConfig, enabling scoped private connectivity with provisioning role creation for secure outpost installations + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Doc release for CreateImage support for instances with local snapshots in Outpost + +## __Amazon WorkSpaces__ + - ### Features + - Amazon WorkSpaces now supports nested virtualization, allowing you to run hypervisors and virtualization-based workloads within your WorkSpaces. You can enable or disable nested virtualization when creating a WorkSpace or by modifying an existing WorkSpace's properties. + +## __S3 Transfer Manager__ + - ### Features + - Use CRT's response file when downloading to a file with the CRT-based S3TransferManager - CRT now writes the object to the destination file directly instead of streaming the body back through the SDK. Pausing such a download uses CRT's new asynchronous pause, so the resume token reflects a fully flushed file. + +# __2.53.2__ __2026-08-17__ +## __AWS Organizations__ + - ### Features + - Add new Transfer Responsibility error codes and document related CloudTrail events for accepting and terminating a Transfer Responsibility. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - AgenticRetrieveStream API now supports Amazon Bedrock AgentCore Memory. Use the new memoryConfiguration parameter to continue a session from short-term memory and retrieve from long-term memory. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adds implementations of third-party evaluators, both managed-as-a-service and as templates within custom evaluators. + +## __Amazon Connect Service__ + - ### Features + - This release adds new APIs to create, describe, update, delete, and list extraction definitions, enabling customers to manage lifecycle of extraction definition resources. Additionally, this release adds new event sources for Rules related to ACW and new action to Extract Information. + +## __Amazon Elastic Container Registry__ + - ### Features + - Documentation update for the ECR PutReplicationConfiguration API to increase the replication rule limit from 10 to 25 + +## __Amazon Location Service Maps V2__ + - ### Features + - Amazon Location Service now supports POI density and category filtering on dynamic maps. The GetStyleDescriptor API adds two optional parameters. PoiDensity (Off to VeryDense) controls POI volume, and PoiCategories filters by up to nine categories. Available on HERE and Grab map styles. + +## __Elastic Disaster Recovery Service__ + - ### Features + - AWS Elastic Disaster Recovery (AWS DRS) now offers Recovery Plans to recover multi-server applications in the right order in one action. Define the launch sequence once, with ordered steps and wait times, and DRS runs it automatically. Validate with non-disruptive drills and monitor in real time. + +# __2.53.1__ __2026-08-14__ +## __AWS Glue__ + - ### Features + - Added support for associating glossary terms with iterable form items, such as table columns. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - Adds CheckIngestedDocumentAcl and GetIngestedDocumentAcl APIs to Amazon Bedrock Knowledge Bases. Customers can verify user access to documents based on ingested ACLs and retrieve full ACL details including allow and deny entries, enabling validation of ACL ingestion without test retrievals. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Add support for the Machine Payments Protocol (MPP) and x402 upto scheme payments protocol in Amazon Bedrock AgentCore Payments. Customers can now pay for MPP-gated resources and also pay services which requires upto scheme in x402 + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adds AgentCore Payments support for CMK, Marketplace Subscriptions and QuickCreate + +## __Amazon Redshift__ + - ### Features + - Amazon Redshift now unlocks a locked admin user account and resets the failed-login counter when you update the admin password using the ModifyCluster API. This option is available only when account lockout security is enabled. + +## __Amazon SageMaker Service__ + - ### Features + - Release support for g7.2xlarge, g7.4xlarge, g7.8xlarge, g7.12xlarge, g7.24xlarge, and g7.48xlarge instance types for SageMaker HyperPod + +## __AmazonMWAAServerless__ + - ### Features + - Adds support for Consuming code for MWAA Serverless + +## __CloudWatch Observability Admin Service__ + - ### Features + - CloudWatch Logs centralization rules now support tag propagation. You can configure a TagPropagationConfiguration on your centralization rule to automatically sync resource tags from source to destination log groups, with configurable conflict resolution strategies. + +## __Redshift Serverless__ + - ### Features + - Amazon Redshift now unlocks a locked admin user account and resets the failed-login counter when you update the admin password using the UpdateNamespace API. This option is available only when account lockout security is enabled. + +# __2.53.0__ __2026-08-13__ +## __AWS CRT HTTP Client__ + - ### Bugfixes + - Honor wildcard `nonProxyHosts` entries in CRT-based HTTP clients (`AwsCrtHttpClient`, `AwsCrtAsyncHttpClient`, and the S3/CRT client). Previously a `*.suffix` wildcard or a bare `*` from `http.nonProxyHosts`/`no_proxy` was silently ignored, so matching hosts were routed through the proxy instead of bypassing it. Supported forms are an exact host, a `*.suffix` wildcard (matches the domain and its subdomains), a single `*` for all hosts, and CIDR ranges. Entries must not contain surrounding whitespace. + +## __AWS Certificate Manager__ + - ### Features + - This change allows customers to update their existing email-validated certificates to use the DNS validation method. + +## __AWS Clean Rooms Service__ + - ### Features + - This release adds support for minimum aggregation thresholds and comparison controls to the Custom analysis rule type. + +## __AWS CodeCommit__ + - ### Features + - Added the GetBlobDifferences API operation, which returns line-level diffs between two blob versions without requiring a local clone. Returns structured hunks with context, additions, and deletions. Supports pagination for large diffs. + +## __AWS SDK for Java v2__ + - ### Features + - Removed ServiceMetadata usages from client creation and request processing code paths to improve cold start performance. Endpoint and signing region resolution now uses Endpoints 2.0 directly instead of triggering eager initialization of all service metadata classes. Service client artifacts must be version 2.28.1 or later to be compatible with this change. + +## __AWS Security Agent__ + - ### Features + - Add support for setting a maximum task-hour budget cap on penetration tests and code reviews, and for revalidating previously reported findings via a new REVALIDATION job type. + +## __Amazon CloudFront__ + - ### Features + - Adds SHA256 support to CloudFrontUtilities + +## __Amazon Connect Service__ + - ### Features + - Adds the StartAssistantContact API to start chat contacts handled by an AI agent. Adds SegmentAttributes to StartWebRTCContact, and corrects its error response to now receive AccessDeniedException (previously returned as an internal server error due to a missing error declaration). + +## __Amazon DynamoDB Enhanced Client__ + - ### Bugfixes + - Fix AutoGeneratedTimestampRecordExtension failing when TableSchema.converterForAttribute throws UnsupportedOperationException for custom schemas; expand dynamodb-enhanced functional test coverage + +## __Apache 5 HTTP Client__ + - ### Bugfixes + - Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it. + +## __Apache HTTP Client__ + - ### Bugfixes + - Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it. + +## __Apache HTTP Client 5__ + - ### Features + - Upgrade httpcomponents.client5 to 5.6.4 to address CVE-2026-71290 + +## __Auto Scaling__ + - ### Features + - Amazon EC2 Auto Scaling now supports terminating multiple instances in a single TerminateInstanceInAutoScalingGroup call via the new InstanceIds parameter, returning an Activities list. LaunchInstances now returns IdempotentCallInProgressFault for duplicate client tokens. + +## __Netty NIO HTTP Client__ + - ### Bugfixes + - Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it. + +## __URL Connection HTTP Client__ + - ### Bugfixes + - Trimmed surrounding whitespace from `nonProxyHosts` / `no_proxy` entries so comma- or pipe-separated values with spaces (e.g. `no_proxy=a.com, *.foo.com`) are honored. Previously an entry with a leading or trailing space was treated as part of the host name and never matched, so the host was routed through the proxy instead of bypassing it. + diff --git a/changelogs/2.54.x-CHANGELOG.md b/changelogs/2.54.x-CHANGELOG.md new file mode 100644 index 000000000000..36c5f2a88886 --- /dev/null +++ b/changelogs/2.54.x-CHANGELOG.md @@ -0,0 +1,805 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.54.20__ __2026-09-16__ +## __AWS Elastic Beanstalk__ + - ### Features + - Adds support to create and manage Elastic Beanstalk Cluster Environments. + +## __AWS Marketplace Catalog Service__ + - ### Features + - This release enhances the ListEntities API to support issuerAccountId and SourceAuthorization filter for ResaleAuthorization entity. + +## __AWS Resilience Hub V2__ + - ### Features + - Next Gen Resilience Hub now supports dependency insights (LLM-based insights about customer's service dependencies) and organization-level policy sharing (provision to share policy with member accounts for an organization) + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Adds support for a new DELETE FAILED status for Bedrock AgentCore Runtimes and Bedrock AgentCore Runtime Endpoints. + +## __Amazon Connect Customer Profiles__ + - ### Features + - This release introduces the SearchRecommendations API, which retrieves recommendations for a profile identified by a search key. + +## __Amazon Connect Service__ + - ### Features + - Adds support for ContactAnalysis via ListContactReferences. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Releasing new EC2 R9g and R9gd memory-optimized instances powered by AWS Graviton5 processors, with up to 25 percent better compute performance than R8g instances, faster DDR5 memory, and up to 100 Gbps network and 72 Gbps EBS bandwidth. R9gd instances additionally provide local NVMe SSD storage. + +## __Amazon S3__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved + +## __Amazon S3 Control__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. + +## __Amazon S3 Files__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. + +## __Amazon S3 Outposts__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. + +## __Amazon S3 Tables__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. + +## __Amazon S3 Vectors__ + - ### Performance Improvements + - Enable BDD based endpoints. Endpoint resolution behavior is unchanged but performance is improved. + +# __2.54.19__ __2026-09-15__ +## __AWS Direct Connect__ + - ### Features + - AWS Direct Connect is introducing flat-rate pricing, a simplified billing model that gives you a fixed monthly price for dedicated connectivity with no per-gigabyte data transfer out charges within the selected pricing tier. + +## __AWS Transfer Family__ + - ### Features + - AWS Transfer Family now preserves the original source IP address using Proxy Protocol v2 when you place a Network Load Balancer in front of your server for SFTP connections. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Amazon Bedrock AgentCore Runtime now supports specifying the platform version of an agent runtime through the new platformVersion field on CreateAgentRuntime, UpdateAgentRuntime, and GetAgentRuntime. + +## __Amazon WorkSpaces__ + - ### Features + - Added support for 4 new graphics-optimized compute types - Graphics.g7 (2xlarge, 4xlarge, 8xlarge, 12xlarge). + +# __2.54.18__ __2026-09-14__ +## __AWS Billing__ + - ### Features + - Increased the maximum number of services returned in the supportEligibleSpendByService field of ListEnterpriseSupportLinkedAccountCharges + +## __AWS CodeDeploy__ + - ### Features + - AWS CodeDeploy now returns the deployment mode on GetDeployment and BatchGetDeployments. The new deploymentMode field on DeploymentInfo indicates whether a deployment used the standard deployment process or restarted the application using a previously installed revision (RESTART mode). + +## __AWS Glue__ + - ### Features + - Amazon Glue releasing the new API ListIntegrationTableProperties and adding IntegrationArn to TargetTableConfig + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Performance Improvements + - Fix request-side performance regression that scaled with payload size for `query` and `ec2` protocol services where the request endpoint was re-parsed as a URI. The internal `HTTP_REQUEST_URI_BEFORE_MODIFY` execution attribute is now deprecated and computed on demand from `HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY`; the value the SDK records carries the scheme, host, port and path but no query string. + +## __AWS Security Token Service__ + - ### Features + - Increases the maximum session token size to 4,096 bytes and removes the packed policy size limit. Adds SessionTokenSize and SessionTokenUtilization fields and a new MinimumSessionTokenSize parameter. PackedPolicySize is deprecated. + +## __AWSBillingConductor__ + - ### Features + - This release adds support for custom volume tiering. You can now define custom tiers on a pricing rule's tiering configuration, where each tier specifies a usage range and the rate applied to usage in that range. + +## __EC2 Image Builder__ + - ### Features + - This release adds a dryRun option to Image Builder create APIs (except CreateImage), structured failure context on failed images including component and distribution failure details, and step retry attempt tracking. + +# __2.54.17__ __2026-09-11__ +## __AWS Batch__ + - ### Features + - Added new bulk job APIs (CancelJobs, TerminateJobs, TerminateServiceJobs) and new fields on ListJobs and ListServiceJobs responses. This allows customers to cancel or terminate multiple jobs in a single request. ListJobs and ListServiceJobs responses now include isCancelled and isTerminated fields. + +## __AWS Elemental MediaConvert__ + - ### Features + - Adds Dolby Vision metadata to Probe results, including profile, level, and presence of the RPU, base layer, and enhancement layer. Adds video sample and display aspect ratios. Adds the UnprocessableEntityException (HTTP 422) error to Probe for recognized but malformed or corrupt inputs. + +## __AWS Invoicing__ + - ### Features + - Add ListProcurementPortals and ListProcurementPortalSuppliers APIs to retrieve AWS-supported 3rd party procurement portals and their suppliers for e-invoice delivery and purchase order retrieval. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + - Upgrade Netty to 4.1.138 + +## __Amazon EC2 Container Service__ + - ### Features + - This feature adds support for setting the cpu architecture type that should be used to launch tasks for an Express Gateway Service. + +## __Amazon Lightsail__ + - ### Features + - Amazon Lightsail now lets you serve website content from a private Lightsail bucket through a Lightsail distribution. This release adds enablePrivateOriginAccess to the CreateDistribution and UpdateDistribution actions, plus new defaultRootObject and customErrorResponses options. + +## __Amazon S3__ + - ### Bugfixes + - Prevent the CRT-based S3 async client from replacing a pre-existing destination when using `getObject(request, Path)`. Failed or cancelled downloads now delete files they create. Existing destinations surface `FileAlreadyExistsException`; callers that require replacement can use `AsyncResponseTransformer.toFile` with `FileTransformerConfiguration.defaultCreateOrReplaceExisting()`. This fixes an inconsistency introduced in 2.32.11. + +## __Amazon Simple Storage Service__ + - ### Features + - Updated S3 Object Lock Default Retention documentation. + +# __2.54.16__ __2026-09-10__ +## __AWS Outposts__ + - ### Features + - Added fields to identify Outpost generation and rack scaling configuration on Outpost and CatalogItem resources. + +## __AWS Resilience Hub V2__ + - ### Features + - This release adds the ListTestRunSourceEvents and ListTestRunDependencies APIs, which return the alarm state changes during a test run and the dependencies the run blocked. + +## __AWS SDK for Java v2__ + - ### Features + - Enable BDD Endpoints for a small subset of services. + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock__ + - ### Features + - TwelveLabs Marengo 3.0 is now an embedding model option in Amazon Bedrock Managed Knowledge Base. Create multimodal embeddings for video, audio, and image content that capture visual scenes, speech, and video cues, not just transcribed text. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - The CreateImage API now supports a BootModeOverride parameter to explicitly set UEFI boot mode on a new AMI, overriding the source instance's inherited boot mode. + +## __Amazon SageMaker Service__ + - ### Features + - This release adds the ability for customers to attach customer owned Elastic Network Interfaces (ENIs) to HyperPod cluster nodes. + +## __RTBFabric__ + - ### Features + - AWS RTB Fabric now lets you control how traffic is routed to your responder gateway across Availability Zones. Set the new clientRoutingPolicy parameter to keep traffic within the same Availability Zone or distribute traffic across all Availability Zones. + +# __2.54.15__ __2026-09-09__ +## __AWS Elemental Inference__ + - ### Features + - This release adds contextual metadata, a feed output type that generates a descriptive summary of your media content along with IAB taxonomy and GARM suitability classifications. It also adds feed resource policies for granting cross-account access to a feed. + +## __AWS Elemental MediaLive__ + - ### Features + - MediaLive now supports Manual Style Control for vertical caption positioning in TTML, WebVTT, and Embedded captions, Contextual Metadata Enrichment via Elemental Inference, and an Output Usage field on MediaPackage v2 for Dynamic Multiview validation. + +## __AWS Elemental MediaPackage v2__ + - ### Features + - Dynamic Multiview enables viewers to watch multiple live video streams in a single combined output. Viewers can select from 6 preset tiled layouts. Create MediaPackage channels with Input Type MULTIVIEW and configure Available Layouts and Available Sources. See the API Documentation for details. + +## __AWS Lambda__ + - ### Features + - Updates documentation for lambda function timeout. + +## __AWS MediaTailor__ + - ### Features + - Added the AWS Service Request function type for MediaTailor Functions, enabling authenticated requests to AWS Elemental Inference for contextual ad targeting during ad insertion. + +## __AWS Parallel Computing Service__ + - ### Features + - This release adds support for custom Gres.conf configuration and Slurm version 26.05 in AWS PCS. Customers can now specify generic resource (GRES) settings to control how GPUs and other resources are configured and shared on their compute node groups. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Fixed an intermittent NullPointerException when downloading a single-part object with a multipart-enabled async S3 client. A race between the emit loop and subscription cancellation could dereference a cleared subscriber reference; the reference is now stable and reads are null-safe. + - Contributed by: [@cthiebault](https://github.com/cthiebault) + +## __Amazon Connect Service__ + - ### Features + - Add metric configuration field to evaluation forms and ListEvaluationFormAIVersions API for retrieving AI-generated evaluation form versions + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds support for sharing Amazon EBS volumes across AWS accounts using AWS Resource Access Manager (RAM). Consuming accounts can view shared volume metadata and create copies of shared volumes within the same Availability Zone, with optional re-encryption using their own KMS key. + +## __Apache HTTP Client__ + - ### Deprecations + - `apache-client` is now deprecated in favor of `apache5-client`. [Apache HttpClient 4.x](https://hc.apache.org/status.html) is in maintenance mode, receiving fixes only for major defects and security issues. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@cthiebault](https://github.com/cthiebault) +# __2.54.14__ __2026-09-08__ +## __AWS CloudTrail__ + - ### Features + - Adds support for the RecursiveLogging trail setting, which suppresses recursive events generated when CloudTrail delivers logs to a trail's destinations. + +## __AWS S3 Control__ + - ### Features + - Adds support for Amazon S3 Object Lock variable retention. Existing S3 APIs that support S3 Object Lock parameters now support two new parameters EventHold and EventHoldDuration at the object level, and DefaultEventHoldDuration at the bucket level. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Prevent `AsyncResponseTransformer.toFile` from deleting a pre-existing destination when a request fails before the SDK opens the file. Calls using `CREATE_NEW` now preserve the existing file and surface `FileAlreadyExistsException` instead of allowing a retry to overwrite it. + +## __Amazon Appflow__ + - ### Features + - Amazon AppFlow now supports key pair (RSA private key) authentication for the Snowflake connector. You can provide a privateKey in SnowflakeConnectorProfileCredentials, and password is no longer required. This is a non-breaking, additive change available via the AWS SDK and CLI. + +## __Amazon Connect Service__ + - ### Features + - Releasing workload types feature. A proper launch announcement or details will follow up. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds the InterfaceTypes field to NetworkCardInfo in the DescribeInstanceTypes response. This field identifies the network interface types supported by each network card. + +## __Amazon Omics__ + - ### Features + - Added support for session policies in AWS HealthOmics Workflows, allowing customers to scope down IAM permissions for individual workflow runs without modifying the service role. + +## __Amazon Pinpoint SMS Voice V2__ + - ### Features + - This feature will allow customers to specify an area-code when requesting a 10DLC number. Why it matters- Customers can now select a number that matches where their business is located. + +## __Amazon SageMaker Service__ + - ### Features + - Add support for InstancePreferences list for multiple instance type input support on SageMaker Training and Processing + +## __Amazon Simple Storage Service__ + - ### Features + - Adds support for Amazon S3 Object Lock variable retention. Existing S3 APIs that support S3 Object Lock parameters now support two new parameters EventHold and EventHoldDuration at the object level, and DefaultEventHoldDuration at the bucket level. + +## __Application Migration Service__ + - ### Features + - This release adds support for configuring the EBS volume initialization rate and delete on termination behavior in launch configuration template + +## __S3 Event Notification__ + - ### Features + - Add support for ObjectRetention to S3EventNotifications. + +## __URL Connection HTTP Client__ + - ### Bugfixes + - Allow retries when the URL Connection HTTP Client encounters an IOException or NullPointerException while accessing request or response body streams. + +# __2.54.13__ __2026-09-04__ +## __AWS MediaTailor__ + - ### Features + - Elemental MediaTailor now supports two new Monetization Functions lifecycle hooks, Post Ads Response and Pre Manifest Insertion, and a VAST Request function type that calls a VAST or VMAP ad server. This release also adds Yield Optimization with demand from Amazon Publisher Services. + +## __AWS SDK for Java v2__ + - ### Features + - Add support for code generating Endpoint Resolvers based on BDD rather than rules. Adds single element endpoint cache to generated BDD based resolvers. BDD based Endpoint Resolvers are generated only when the BDD model is present on a service. + +## __Amazon Bedrock__ + - ### Features + - New AWS REVIEW mode as supported data retention mode for Bedrock models + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds support for ValidateSecurityGroupQuotasForInterface, an API that specifically authorized AWS services use to validate security group rule quotas before creating an elastic network interface. + +## __Service Quotas__ + - ### Features + - Service Quotas adds the AdjustableAtLevel property to QuotaContext, indicating whether a quota is adjustable at the account or resource level. + +# __2.54.12__ __2026-09-03__ +## __AWS End User Messaging Social__ + - ### Features + - Adding support for WhatsApp Flows with endpoints. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Fix `ApiCallDuration` so that it measures the whole API call. It previously started after marshalling had already completed, and on asynchronous clients it also started after endpoint resolution, auth scheme resolution, request compression and checksum computation, and so understated the reported duration. The metric is now measured identically for synchronous and asynchronous clients and matches the documented formula. Reported `ApiCallDuration` values will increase but do not reflect changes in actual round-trip latency. + +## __AWS Step Functions__ + - ### Features + - Updates Step Functions API documentation around CloudTrail, Execution name reuse and sort order of ListExecutions API + +## __AWS Transfer Family__ + - ### Features + - AWS Transfer Family SFTP Connectors now support specifying an ordered list of AWS Secrets Manager version stages for secret retrieval. This enables seamless credential rotation workflows where external partners may take time to update their systems with new credentials. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Adds log group name prefix trace source selection, custom or source log group result destinations, and metrics namespace customization + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - AgentCore Identity adds Consent Portal APIs to manage portals that let end users grant OAuth authorization for agents to access resources. AgentCore Evaluation adds trace source selection by log group prefix, custom or source log group result destinations, and metrics namespace customization. + +## __Amazon Connect Service__ + - ### Features + - This release enables TagOnCreate for Rule resource on CreateRule API. It also introduces a new field called PreEvaluationFilters to Rule resource, thereby impacting all Create, Update, Describe and Search APIs for Rules + +## __Amazon EC2 Container Service__ + - ### Features + - Adds a critical parameter to the Amazon ECS managed daemon APIs that controls whether a daemon task failure drains the container instance. Non-critical daemon failures no longer drain the instance or block instance registration. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - Deprecate EncryptionConfig resources field. Amazon EKS encrypts all Kubernetes API data with envelope encryption by default for clusters running Kubernetes version 1.28 or higher, so this field no longer affects which resources are encrypted. + +## __Amazon Elastic VMware Service__ + - ### Features + - Amazon EVS now allows users to set, update, and retrieve values for parameters that apply across all EVS Environments in their account at a regional level, such as the VCF License portability core count. + +## __Amazon GuardDuty__ + - ### Features + - Adding support for Sequence Activities in GuardDuty Findings + +## __Amazon Transcribe Service__ + - ### Features + - Amazon Transcribe now supports specifying up to 29 PII entity types in the ContentRedaction configuration of a StartTranscriptionJob request, allowing all supported entity types to be redacted in a single batch transcription job. + +## __Elastic Disaster Recovery Service__ + - ### Features + - AWS Elastic Disaster Recovery now includes source server architecture in SourceProperties to identify x86 and ARM64 systems. + +## __Elastic Load Balancing__ + - ### Features + - This release adds support for sending TCP resets for Gateway Load Balancer when a flow's idle timeout expires, or when a target becomes unhealthy or is deregistered. This adds updates the CLI documentation. + +# __2.54.11__ __2026-09-02__ +## __AWS Elemental MediaLive__ + - ### Features + - AWS Elemental MediaLive now supports AB forensic video watermarking + +## __Amazon AppIntegrations Service__ + - ### Features + - This release adds a force parameter to DeleteApplication and a ConflictException to UpdateApplication, letting customers delete applications with existing associations in one call and get a clear error when an update conflicts with the application's current state. + +## __Amazon Bedrock AgentCore__ + - ### Features + - Batch evaluation now supports up to 10 CloudWatch log groups per CloudWatchLogsSource + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds support to retain interruptible Capacity Reservations in an active state when all capacity is reclaimed. + +## __Amazon SageMaker Feature Store Runtime__ + - ### Features + - Amazon SageMaker Feature Store now supports the UpdateRecord API, enabling partial updates to individual feature values in an existing Online Store record without rewriting the entire record. This reduces write payloads and latency for high-frequency feature-level writes . + +## __Amazon SageMaker Service__ + - ### Features + - Amazon SageMaker Feature Store now supports the Standard V2 online store type, which enables feature-level writes to feature groups. You can select Standard V2 when creating a feature group, and update the storage type of an existing feature group via UpdateFeatureGroup. + +## __AmazonMWAA__ + - ### Features + - Enabled customers to clear optional S3 paths (plugins, requirements, and startup script) for their Amazon MWAA environments by accepting empty strings for the associated fields in UpdateEnvironment requests. + +## __Application Migration Service__ + - ### Features + - AWS Transform for migrations adds a second network migration option - apply your source security posture to existing VPCs. Upload a source network file with firewall rules, tag the in-scope VPCs, and AWS Transform matches source subnets to them by CIDR and generates the security groups. + +## __odb__ + - ### Features + - Adds the ListFlexComponents API for listing the flex components available for a given DB system shape. + +# __2.54.10__ __2026-09-01__ +## __AWS Elemental MediaConvert__ + - ### Features + - Adds support for AAC passthrough. Adds ManifestCues option to support HLS manifest Cue marker passthrough. Adds playback device compatibility mode for DASH H.265 outputs. Adds TTML caption styling options. Adds interlace mode support for XAVC HD Intra CBG profile. + +## __AWS IoT SiteWise__ + - ### Features + - AWS IoT SiteWise Scenario Discovery now supports mounting Amazon S3 data directly into pipeline task containers via S3 Access Points, and configuring additional ephemeral storage per task. Mount configurations can be overridden at execution time. See the API guide for details. + +## __AWS Lambda__ + - ### Features + - AWS Lambda now provides configurable control over S3 direct access, allowing you to explicitly enable or disable how functions stream file reads directly from S3 buckets. This gives you flexibility to tune data access behavior based on your workload requirements, independent of memory size. + +## __AWS Marketplace Agreement Service__ + - ### Features + - This release adds renewal support for AWS Marketplace private offers. Agreements report whether they renew and, if not, why. Renewal terms add price increases, renewal limits, renewal decision deadlines, and payment schedule templates. SearchAgreements adds filters. + +## __AWS Marketplace Discovery__ + - ### Features + - GetOfferTerms now returns renewalTerm for offers with pre-authorized renewals, exposing maxRenewals, lockoutPeriod, adjustmentDeadline, priceIncrease (fixed percentage or percentage range), and termTemplates (renewal payment schedules). Enables buyers to view renewal pricing and terms. + +## __AWS SDK for Java v2__ + - ### Features + - Removed the legacy interpreted endpoint rules code generation path. Compiled endpoint rules are now the only supported path. This includes removing the `enableGenerateCompiledEndpointRules` customization flag from all services and deleting the old interpreted runtime resources. + - Updated endpoint and partition metadata. + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Online evaluation configurations now support up to 25 evaluators. CloudWatch Logs data sources for online evaluation now support up to 10 log groups. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Update UserData and UploadPolicy shapes to use SecureBlob + +## __Amazon GuardDuty__ + - ### Features + - Amazon GuardDuty now supports custom detection rules, including APIs to manage rule associations and organization-level configurations. + +## __Amazon Kinesis__ + - ### Features + - Amazon Kinesis Data Streams now supports a dry run feature for data-plane APIs to validate the permissions and request parameters. If all checks complete successfully, the API returns a 'DryRunOperationException', confirming the request would have succeeded without the 'DryRun' parameter. + +## __Amazon Lightsail__ + - ### Features + - This release adds support for the Amazon Lightsail GetProfile API, which returns the profile for the specified account. + +## __Amazon Simple Email Service__ + - ### Features + - Added support for managing SMIME signing certificates for email identities, including associating, listing, and disassociating certificates. Added the UpdateConfigurationSet operation to configure message security options such as signing scheme. + +## __Tax Settings__ + - ### Features + - France and Monaco Additional Info changes + +# __2.54.9__ __2026-08-31__ +## __Agent Registry__ + - ### Features + - Release HTTP and AGUI descriptors to the dataplane model + +# __2.54.8__ __2026-08-31__ +## __AWS Control Tower__ + - ### Features + - Updated the descriptions for the AWS Control Tower ListEnabledControls API parameters to make them more accurate and intuitive. + +## __AWS DevOps Agent Service__ + - ### Features + - Adds support for Slack bidirectional communication configuration in AWS DevOps Agent agent spaces. + +## __AWS Support__ + - ### Features + - AWS Support now allows up to 10 attachments (150 MB each) per case correspondence, up from 3 at 5 MB. Customers can share large diagnostic logs, heap dumps, and packet captures directly in cases to reduce back-and-forth and speed up resolution. Available in US East, US West, and Europe (Ireland). + +## __Agent Registry__ + - ### Features + - AWS Agent Registry becomes Generally Available + +## __Agent Registry Control__ + - ### Features + - AWS Agent Registry becomes Generally Available + +## __Amazon Connect Customer Profiles__ + - ### Features + - This release introduces new APIs for segment membership events allowing segment definition membership events to be exported to a kinesis stream for downstream processing. Additionally, includes new calculated attribute statistic and 2 new segment dimension types. + +## __Amazon Connect Service__ + - ### Features + - Added support for global routing on Amazon Connect Global Resiliency instances. New APIs GetCrossRegionRouting and UpdateCrossRegionRouting allow you to view and control cross-region contact routing between linked instances, so both Regions are active at all times. + +## __Amazon Kinesis__ + - ### Features + - Adds support for data delivery to Amazon S3 Tables (Apache Iceberg) and general purpose Amazon S3 buckets with new CreateChannel, UpdateChannel, DeleteChannel, DescribeChannel, and ListChannels APIs for Amazon Kinesis Data Streams. + +## __Amazon Pinpoint SMS Voice V2__ + - ### Features + - AWS End User Messaging SMS now returns ConditionalBehavior on DescribeRegistrationFieldDefinitions, allowing you to programmatically discover which registration fields are required, optional, or disallowed based on the values of other fields in the same form. + +## __Amazon QuickSight__ + - ### Features + - This release adds support for managing apps in Amazon QuickSight with ListApps, SearchApps, DescribeApp, DescribeAppPermissions, UpdateAppPermissions, and DeleteApp + +## __Amazon SageMaker Service__ + - ### Features + - Amazon SageMaker Batch Transform now supports G6e instances, powered by NVIDIA L40S Tensor Core GPUs. G6e instances are the most cost-efficient GPU instances for deploying generative AI models and the highest-performance GPU instances for spatial computing workloads. + +## __Amazon Workspaces Instances__ + - ### Features + - Amazon WorkSpaces Core managed instances now support nested virtualization. Customers can enable nested virtualization with supported instance types at launch via CpuOptions.NestedVirtualization in CreateWorkspaceInstance to run hypervisors and virtual machines inside their WorkSpaces Instance. + +## __Managed Streaming for Kafka Connect__ + - ### Features + - Amazon MSK Connect now supports restarting newly created connectors via the asynchronous RestartConnector API. Restart all tasks or only failed tasks, while preserving configuration and committed offsets. This returns a connector operation ARN that you can track with DescribeConnectorOperation. + +# __2.54.7__ __2026-08-28__ +## __AWS SDK for Java v2__ + - ### Bugfixes + - Reduce memory allocations for non-streaming requests made with asycn clients. + +## __Agents for Amazon Bedrock__ + - ### Features + - Adds an optional syncSchedule field to CreateDataSource and UpdateDataSource for Managed Knowledge Bases data source connectors, so a data source can sync automatically on a daily, weekly, or monthly schedule. + +## __Amazon Bedrock AgentCore__ + - ### Features + - AgentCore Memory now supports direct ingestion into long-term memory via IngestData API + +## __Amazon Cognito Identity Provider__ + - ### Features + - Adds two new operations - GetClientToken which allows M2M auth through the SDK, and DescribeTermsByClient to find which Terms are associated with a user-pool client without knowing the Terms resource id. + +## __Amazon EC2 Container Service__ + - ### Features + - Amazon Elastic Container Service - This release adds support for early success criteria on ECS rolling deployments, letting deployment complete once a configurable percentage of tasks are healthy, with configurable BLOCKING (required) or DEFERRED (asynchronous) cleanup of previous service revisions. + +## __Amazon HealthLake__ + - ### Features + - New HealthLake API, RestoreFHIRDatastore, providing the capability to restore active datastores to a point in time within the last 30 days or recover a deleted datastore from the delete snapshot. + +## __Partner Central Selling API__ + - ### Features + - Releasing PARC, new APN Program that lets sellers add solftware revenue details to aws opportunity summary + +# __2.54.6__ __2026-08-27__ +## __AWS CodeDeploy__ + - ### Features + - Added a deploymentMode parameter to CreateDeployment. Set it to RESTART to restart an EC2 and on-premises fleet, using the last successful revision, honoring Deployment Configuration. + +## __Amazon CloudWatch Logs__ + - ### Features + - Added resultCount to QueryStatistics in GetQueryResults. This field returns the total number of output rows in the final result set, helping customers programmatically determine whether a query produced results after all operations including post-aggregation filters. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Adds the AdminDeleteSoftwareToken API operation, enabling administrators to remove a user's registered TOTP (software token) MFA configuration from a user pool. + +## __Amazon DataZone__ + - ### Features + - Add cascadeDelete to DeleteDomain. When specified, DataZone recursively deletes all projects, environments, subscriptions, and their underlying AWS resources before removing the domain. Deletion progress is reported via deleteProgress and resource failures via failureReasons on GetDomain. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - EC2 allows AMI owners to define compatible instance types on their AMIs, blocking RunInstances calls automatically for launches on non-permitted instance types. + +## __Amazon OpenSearch Service__ + - ### Features + - Updating SDK and CLI documentation for AttachDataSource API. + +## __Amazon Relational Database Service__ + - ### Features + - Adding support for the full snapshot size, in bytes, of DB instance snapshots. + +## __Lambda MicroVMs__ + - ### Features + - Added InsufficientCapacityException to RunMicrovm for capacity-related failures. Added lifecycle status field (AVAILABLE, DEPRECATED) to ListManagedMicrovmImageVersions. Added ConflictException to CreateMicrovmAuthToken and CreateMicrovmShellAuthToken for unregistered MicroVMs. + +# __2.54.5__ __2026-08-26__ +## __AWS CRT Async HTTP Client__ + - ### Bugfixes + - Fixed an issue where an error signaled by a request body publisher was printed to stderr on a CRT event loop thread instead of failing the request with the original error. + +## __AWS CRT HTTP Client__ + - ### Bugfixes + - Fixed an issue where an error thrown while reading the request body stream was printed to stderr on a CRT event loop thread instead of failing the request with the original error. See [#6715](https://github.com/aws/aws-sdk-java-v2/issues/6715). + +## __AWS CRT-based S3 Client__ + - ### Bugfixes + - Fixed an issue where an error signaled by a request body publisher (for example via `AsyncRequestBody.fromPublisher`) was printed to stderr on a CRT event loop thread instead of failing the operation; the operation's future now completes with the original publisher error. See [#6715](https://github.com/aws/aws-sdk-java-v2/issues/6715). + +## __AWS DevOps Agent Service__ + - ### Features + - AWS DevOps Agent now supports trigger filter groups for Release Readiness Review, letting you control when the capability auto-triggers based on webhook events and target branches. + +## __AWS License Manager User Subscriptions__ + - ### Features + - Released support for License Expiry field in ListProductSubscriptions API + +## __AWS Network Firewall__ + - ### Features + - Adding new status enum for Firewalls. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds deleting state to possible VPC States. + +## __Amazon SageMaker Service__ + - ### Features + - Amazon SageMaker AI now supports ml.g7 instances for model optimization. You can now run model optimization jobs on ml.g7 instances, in supported AWS Regions. + +# __2.54.4__ __2026-08-25__ +## __AWS DevOps Agent Service__ + - ### Features + - Adds the UpdateApprovalAction API for resolving agent action approvals in AWS DevOps Agent agent spaces. + +## __AWS IoT__ + - ### Features + - As part of this release, we are extending capability of AWS IoT Rules Engine to support IoT InfluxDB Action. The IoT InfluxDB action lets customers send messages from IoT sensors and applications to InfluxDB. + +## __AWS SDK for Java v2__ + - ### Features + - Extract the duplicated resolveMetricPublishers generator into ClientClassUtils, removing verbatim duplication across the sync and async client generators. No change to generated client code or SDK behavior. + - Contributed by: [@Se3do](https://github.com/Se3do) + + - ### Bugfixes + - Fix an issue where futures from the async SDK clients don't complete with an exception when the client or its [scheduled executor service](https://docs.aws.amazon.com/java/api/latest/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.html#scheduledExecutorService()) is closed. See [#7313](https://github.com/aws/aws-sdk-java-v2/issues/7313) for more details. + +## __AWSMarketplace Metering__ + - ### Features + - Updated documentation to clarify duplicate-billing prevention and BatchMeterUsage retry guidance + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Fleet feature to support Capacity Reservation Resource Groups with Amazon EC2 Capacity Blocks and interruptible Capacity Reservations + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - This feature would give customers the ability to tune TerminatedPodGcThreshold configuration in an Amazon EKS cluster. + +## __Amazon Elastic VMware Service__ + - ### Features + - EVS now supports i7i.metal-48xl EC2 bare metal instance type, delivering high random IOPS performance with real-time latency, ideal for IO intensive and latency-sensitive workloads such as transactional databases, real-time analytics, and AI ML pre-processing. + +## __Amazon SQS__ + - ### Bugfixes + - Fixed `SqsAsyncBatchManager.close()` re-sending the same buffered batch in a busy loop. On close, each buffered batch (including partial batches) is now flushed exactly once, and close waits a bounded timeout (approximately 5 seconds) for in-flight batch sends to complete so their callers receive the real result instead of a cancellation. + +## __Auto Scaling__ + - ### Features + - Adds support for Distribution Segments in mixed instances policies, providing ordered prioritization across On-Demand Capacity Reservations, Capacity Blocks, interruptible Capacity Reservations, and On-Demand capacity. + +## __IAM Toolbox (Preview)__ + - ### Features + - AWS Identity and Access Management (IAM) announces access troubleshooter, helping you debug access denied errors faster. Supported error messages now include an identifier you can use to retrieve detailed evaluations of the policies considered and their results. Preview in US East (N. Virginia). + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@Se3do](https://github.com/Se3do) +# __2.54.3__ __2026-08-24__ +## __AWS Batch__ + - ### Features + - Doc Update, Add note that UpdatePolicy applies only to EC2 managed compute environments + +## __AWS Elemental Inference__ + - ### Features + - Added support for the GetFixture API, enabling customers to retrieve the details of a fixture from its fixture ID, and added the access role ARN to the CreateFeed, GetFeed, and UpdateFeed responses. + +## __AWS Launch Wizard__ + - ### Features + - Added accountConstraints and patternType to GetWorkload, ListWorkloads, GetWorkloadDeploymentPattern and ListWorkloadDeploymentPatterns for Launch Wizard + +## __AWS Security Agent__ + - ### Features + - Adding private and self-signed certificate configuration support for penetration tests + +## __Amazon Aurora DSQL__ + - ### Features + - Corrected the validation pattern on the ServiceName response field in the GetVpcEndpointServiceName API to match the values Amazon Aurora DSQL actually returns. + +## __Amazon Bedrock__ + - ### Features + - Adds support for specifying an inference profile ID or ARN, or an application inference profile ARN as the target model in CreateAdvancedPromptOptimizationJob. + +## __Amazon Connect Contact Lens__ + - ### Features + - This release adds the ExtractedInformation segment to the ListRealtimeContactAnalysisSegments API, enabling customers to retrieve information extracted from real-time contact analysis. + +## __Amazon Connect Service__ + - ### Features + - This release adds the ExtractedInformation segment to the ListRealtimeContactAnalysisSegmentsV2 API, enabling customers to retrieve information extracted from real-time contact analysis. + +## __Managed Streaming for Kafka__ + - ### Features + - Amazon MSK Replicator now supports OAuth authentication when connecting to external Apache Kafka clusters, enabling customers to replicate data from clusters that require OAuth for client authentication. This new capability is supported in all AWS Regions where MSK Express brokers are available. + +## __Timestream InfluxDB__ + - ### Features + - Service-managed parameter groups now only apply optimized defaults to DB Clusters automatically. New field effectiveDbParameterGroupIdentifier surfaces the parameter group actually applied. + +# __2.54.2__ __2026-08-21__ +## __AWS Backup__ + - ### Features + - Updating CLI Docs for Backup Audit Manager List Job Summaries APIs. + +## __AWS Device Farm__ + - ### Features + - Added support to CreateRemoveAccessSession for selecting a server version on the mobile WebDriver endpoint. + +## __AWS WAFV2__ + - ### Features + - DataProtectionConfig field Key Documentation Update + +## __Amazon Bedrock AgentCore__ + - ### Features + - Increase spans count from 1k to 20k + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - Update Dataset schema to THIRDPARTYEVALUATIONV1 + +## __Amazon CloudWatch__ + - ### Features + - Allows customers to specify an initial warm up period to wait for metrics to arrive when creating metric or log alarms + +## __Amazon Kinesis__ + - ### Features + - Generate account endpoint for Kinesis Data Streams requests when the account ID is available + +## __Netty NIO HTTP Client__ + - ### Features + - Add support for Kerberos (SPNEGO) proxy authentication via the new `proxyAuthScheme` option on the Netty client's `ProxyConfiguration`. Setting `ProxyAuthScheme.NEGOTIATE` authenticates proxy CONNECT tunnels using the Kerberos ticket cache in the environment; a valid ticket-granting ticket must already exist (for example via `kinit`), and no password or keytab is read. `ProxyAuthScheme.BASIC` may also be set to select Basic authentication explicitly. See [#7033](https://github.com/aws/aws-sdk-java-v2/issues/7033). + + - ### Bugfixes + - Fix `NettyNioAsyncHttpClient` errors when making requests in GraalVM native images, which can lead to timeout exceptions. + - Fixed a `NullPointerException` in `HandlerSubscriber` that could intermittently fail async requests (such as S3 `PutObject`/`UploadPart`) when a channel writability change occurred during the `Expect: 100-continue` window before the request body subscription was established. See [#7271](https://github.com/aws/aws-sdk-java-v2/issues/7271). + +# __2.54.1__ __2026-08-20__ +## __ARC - Region switch__ + - ### Features + - Adds support for Rds switchover read replica for Oracle databases in Region switch plans + +## __AWS Amplify__ + - ### Features + - Increased the maximum allowed length from 255 to 4,096 characters to support longer access tokens. + +## __AWS Batch__ + - ### Features + - AWS Batch now supports a new compute environment type that provides fully managed EC2 capacity with broader compute flexibility than Fargate, including GPU instances, bare metal, and specific instance type selection, without infrastructure management overhead. + +## __AWS Direct Connect__ + - ### Features + - This release adds custom route prefix pool allocations for Direct Connect. You can set IPv4 and IPv6 route prefix counts on private and transit virtual interfaces, and view pool size and unallocated counts on connections and LAGs, plus direct connect gateway attachment prefix allocation totals. + +## __AWS Lambda__ + - ### Features + - Adds support for full JSON resource-based policies, enabling customers to create, retrieve, update, and delete function resource policies as complete JSON documents. + +## __Amazon CloudFront__ + - ### Features + - Added SigV4a as a supported signing protocol for Origin Access Control (OAC), enabling CloudFront to sign requests to Amazon S3 Multi-Region Access Point (S3-MRAP) origins. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - EC2 marks UEFI instance metadata field as sensitive. + +## __Amazon SageMaker Service__ + - ### Features + - Added IAM Identity Center (IdC) support to CreatePartnerApp and UpdatePartnerApp APIs. Added Customer Managed Key (CMK) support to CreateMlflowApp and DescribeMlflowApp. + +## __Amazon Simple Email Service__ + - ### Features + - Amazon SES now supports per-message tracking overrides. You can use the new ConfigurationOverrides parameter in SendEmail and SendBulkEmail to enable or disable open and click tracking for individual messages without changing your account-level or configuration set settings. + +## __PricingPlanManager__ + - ### Features + - Documentation update for the CreateSubscription API to correct the default value of the approval mode parameter. The default value for paid subscriptions is MANUAL, not IMMEDIATE as previously documented. The default value remains IMMEDIATE for FREE tier subscriptions. + +# __2.54.0__ __2026-08-19__ +## __AWS Batch__ + - ### Features + - AWS Batch now supports managing CloudWatch Container Insights on compute environments via CreateComputeEnvironment and UpdateComputeEnvironment. + +## __AWS Elemental MediaLive__ + - ### Features + - AWS Elemental MediaLive now supports video cropping and output positioning. Use cropRectangle and outputPositionRectangle to position the encoded video within the output frame, with the surrounding area filled with black. + +## __AWS SDK for Java v2__ + - ### Features + - Add `SdkWarmUp` to warm up SDK request paths before a Coordinated Restore at Checkpoint (CRaC) checkpoint, including AWS Lambda SnapStart. `SdkWarmUp.warmUp()` warms every service client on the classpath. `SdkWarmUp.warmUp(Class...)` warms the service clients you name. + - Cache auth scheme resolution results per operation + - Enable compiled endpoint rules for all services by default, with a fix for region parameter handling in the generated endpoint providers. + + - ### Documentations + - Add the @SdkAdvancedApi annotation to generated, operation event stream response handlers. + +## __Account Access__ + - ### Features + - Adds throttling exceptions to operation outputs that were previously inconsistent with other operations. + +## __Amazon Bedrock AgentCore__ + - ### Features + - AgentCore Memory now supports Flexible Namespaces and Non-Conversational Payloads in CreateEvent API + +## __Amazon Bedrock AgentCore Control__ + - ### Features + - AgentCore Memory now supports Flexible Namespaces + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - Adds support for EKS cluster certificate authorities (CA) + +## __Amazon Redshift__ + - ### Features + - Amazon Redshift enhanced System Table retention that allows customers to store their system table data directly in S3 Tables in customer's account instead of Redshift Managed Storage + +## __Amazon VPC Lattice__ + - ### Features + - Amazon VPC Lattice now supports modification of private DNS options on Service Network VPC Associations + +## __Redshift Serverless__ + - ### Features + - Amazon Redshift Enhanced System Table Retention that allows customers to store their system table data directly in S3 Tables in customer's account instead of Redshift Managed Storage + diff --git a/codegen-lite-maven-plugin/pom.xml b/codegen-lite-maven-plugin/pom.xml index cb32b7fb575a..2d4efd35dc63 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml codegen-lite-maven-plugin diff --git a/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java b/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java index ebd60e55afa9..0de2293aa79f 100644 --- a/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java +++ b/codegen-lite-maven-plugin/src/main/java/software/amazon/awssdk/codegen/lite/maven/plugin/RegionGenerationMojo.java @@ -15,11 +15,16 @@ package software.amazon.awssdk.codegen.lite.maven.plugin; +import java.io.BufferedReader; import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashSet; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Mojo; @@ -50,6 +55,8 @@ public class RegionGenerationMojo extends AbstractMojo { private static final String SERVICE_METADATA_BASE = "software.amazon.awssdk.regions.servicemetadata"; private static final String REGION_METADATA_BASE = "software.amazon.awssdk.regions.regionmetadata"; private static final String REGION_BASE = "software.amazon.awssdk.regions"; + private static final String SERVICE_METADATA_ALLOWLIST_PATH = + "/software/amazon/awssdk/codegen/lite/service-metadata-allowlist.txt"; @Parameter(property = "outputDirectory", defaultValue = "${project.build.directory}") private String outputDirectory; @@ -68,21 +75,28 @@ public class RegionGenerationMojo extends AbstractMojo { @Override public void execute() throws MojoExecutionException { Path baseSourcesDirectory = Paths.get(outputDirectory).resolve("generated-sources").resolve("sdk"); - Path testsDirectory = Paths.get(outputDirectory).resolve("generated-test-sources").resolve("sdk-tests"); Partitions partitions = RegionMetadataLoader.build(endpoints); PartitionsRegionsMetadata regionPartitions = PartitionsRegionsMetadataLoader.build(partitionsJson); + Set allEndpointServices = new HashSet<>(); + partitions.getPartitions().forEach(p -> allEndpointServices.addAll(p.getServices().keySet())); + Set allowedServices = loadServiceMetadataAllowlist(); + Set effectiveServices = allowedServices.stream() + .filter(allEndpointServices::contains) + .collect(Collectors.toSet()); + generatePartitionMetadataClass(baseSourcesDirectory, regionPartitions); generateRegionClass(baseSourcesDirectory, regionPartitions); - generateServiceMetadata(baseSourcesDirectory, partitions); + generateServiceMetadata(baseSourcesDirectory, partitions, effectiveServices); generateRegions(baseSourcesDirectory, regionPartitions); generatePartitionProvider(baseSourcesDirectory, regionPartitions); generateRegionProvider(baseSourcesDirectory, regionPartitions); - generateServiceProvider(baseSourcesDirectory, partitions); + generateServiceProvider(baseSourcesDirectory, effectiveServices); generateEndpointTags(baseSourcesDirectory, partitions); project.addCompileSourceRoot(baseSourcesDirectory.toFile().getAbsolutePath()); + Path testsDirectory = Paths.get(outputDirectory).resolve("generated-test-sources").resolve("sdk-tests"); project.addTestCompileSourceRoot(testsDirectory.toFile().getAbsolutePath()); } @@ -100,15 +114,13 @@ public void generateRegionClass(Path baseSourcesDirectory, PartitionsRegionsMeta new CodeGenerator(sourcesDirectory.toString(), new RegionGenerator(partitions, REGION_BASE)).generate(); } - public void generateServiceMetadata(Path baseSourcesDirectory, Partitions partitions) { + public void generateServiceMetadata(Path baseSourcesDirectory, Partitions partitions, Set effectiveServices) { Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(SERVICE_METADATA_BASE, ".", "/")); - Set services = new HashSet<>(); - partitions.getPartitions().forEach(p -> services.addAll(p.getServices().keySet())); - - services.forEach(s -> new CodeGenerator(sourcesDirectory.toString(), new ServiceMetadataGenerator(partitions, - s, - SERVICE_METADATA_BASE, - REGION_BASE)) + effectiveServices.forEach(s -> new CodeGenerator(sourcesDirectory.toString(), + new ServiceMetadataGenerator(partitions, + s, + SERVICE_METADATA_BASE, + REGION_BASE)) .generate()); } @@ -141,11 +153,11 @@ public void generateRegionProvider(Path baseSourcesDirectory, PartitionsRegionsM .generate(); } - public void generateServiceProvider(Path baseSourcesDirectory, Partitions partitions) { + public void generateServiceProvider(Path baseSourcesDirectory, Set effectiveServices) { Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(REGION_BASE, ".", "/")); - new CodeGenerator(sourcesDirectory.toString(), new ServiceMetadataProviderGenerator(partitions, - SERVICE_METADATA_BASE, - REGION_BASE)) + new CodeGenerator(sourcesDirectory.toString(), new ServiceMetadataProviderGenerator(SERVICE_METADATA_BASE, + REGION_BASE, + effectiveServices)) .generate(); } @@ -153,4 +165,18 @@ public void generateEndpointTags(Path baseSourcesDirectory, Partitions partition Path sourcesDirectory = baseSourcesDirectory.resolve(StringUtils.replace(REGION_BASE, ".", "/")); new CodeGenerator(sourcesDirectory.toString(), new EndpointTagGenerator(partitions, REGION_BASE)).generate(); } + + private Set loadServiceMetadataAllowlist() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader( + Objects.requireNonNull(RegionGenerationMojo.class.getResourceAsStream(SERVICE_METADATA_ALLOWLIST_PATH), + "Failed to load service-metadata-allowlist.txt"), + StandardCharsets.UTF_8))) { + return reader.lines() + .map(String::trim) + .filter(line -> !line.isEmpty() && !line.startsWith("#")) + .collect(Collectors.toSet()); + } catch (Exception e) { + throw new RuntimeException("Failed to load service-metadata-allowlist.txt", e); + } + } } diff --git a/codegen-lite-maven-plugin/src/main/resources/software/amazon/awssdk/codegen/lite/service-metadata-allowlist.txt b/codegen-lite-maven-plugin/src/main/resources/software/amazon/awssdk/codegen/lite/service-metadata-allowlist.txt new file mode 100644 index 000000000000..fb9c41e243f4 --- /dev/null +++ b/codegen-lite-maven-plugin/src/main/resources/software/amazon/awssdk/codegen/lite/service-metadata-allowlist.txt @@ -0,0 +1,310 @@ +# Frozen list of service endpoint prefixes for which ServiceMetadata classes are generated. +# New services should NOT be added to this list. ServiceMetadata is a legacy endpoint resolution +# system that has been superseded by Endpoints 2.0. +access-analyzer +account +acm +acm-pca +agreement-marketplace +airflow +amplify +amplifybackend +amplifyuibuilder +aoss +api.detective +api.ecr +api.ecr-public +api.iotdeviceadvisor +api.iotwireless +api.mediatailor +api.pricing +api.sagemaker +api.tunneling.iot +apigateway +app-integrations +appconfig +appconfigdata +appflow +application-autoscaling +applicationinsights +appmesh +apprunner +appstream2 +appsync +aps +arc-zonal-shift +athena +auditmanager +autoscaling +autoscaling-plans +backup +backup-gateway +batch +bedrock +billingconductor +braket +budgets +cases +cassandra +catalog.marketplace +ce +chime +cleanrooms +cloud9 +cloudcontrolapi +clouddirectory +cloudformation +cloudfront +cloudhsm +cloudhsmv2 +cloudsearch +cloudtrail +cloudtrail-data +codeartifact +codebuild +codecatalyst +codecommit +codedeploy +codeguru-profiler +codeguru-reviewer +codepipeline +codestar-connections +codestar-notifications +cognito-identity +cognito-idp +cognito-sync +comprehend +comprehendmedical +compute-optimizer +config +connect +connect-campaigns +contact-lens +controltower +cost-optimization-hub +cur +data-ats.iot +data.iot +data.jobs.iot +data.mediastore +databrew +dataexchange +datapipeline +datasync +datazone +dax +devicefarm +devops-guru +directconnect +discovery +dlm +dms +docdb +drs +ds +dynamodb +ebs +ec2 +ecs +edge.sagemaker +eks +eks-auth +elasticache +elasticbeanstalk +elasticfilesystem +elasticloadbalancing +elasticmapreduce +email +emr-containers +emr-serverless +entitlement.marketplace +es +events +finspace +finspace-api +firehose +fms +forecast +forecastquery +frauddetector +fsx +gamelift +gameliftstreams +geo +glacier +globalaccelerator +glue +grafana +greengrass +groundstation +guardduty +health +healthlake +iam +identity-chime +identitystore +importexport +ingest.timestream +inspector +inspector2 +internetmonitor +iot +iotfleetwise +iotsecuredtunneling +iotsitewise +iotthingsgraph +iottwinmaker +iotwireless +ivs +ivschat +ivsrealtime +kafka +kafkaconnect +kendra +kendra-ranking +kinesis +kinesisanalytics +kinesisvideo +kms +lakeformation +lambda +license-manager +license-manager-linux-subscriptions +license-manager-user-subscriptions +lightsail +logs +lookoutequipment +m2 +machinelearning +macie2 +managedblockchain +managedblockchain-query +marketplacecommerceanalytics +media-pipelines-chime +mediaconnect +mediaconvert +medialive +mediapackage +mediapackage-vod +mediapackagev2 +mediastore +meetings-chime +memory-db +messaging-chime +metering.marketplace +metrics.sagemaker +mgh +mgn +migrationhub-orchestrator +migrationhub-strategy +mobileanalytics +models-v2-lex +models.lex +monitoring +mq +mturk-requester +neptune +network-firewall +networkmanager +notifications +notifications-contacts +nova-act +oam +oidc +omics +organizations +osis +outposts +participant.connect +partnercentral-channel +personalize +pi +pinpoint +pipes +polly +portal.sso +profile +proton +qbusiness +query.timestream +quicksight +ram +rbin +rds +rds-data +redshift +redshift-serverless +rekognition +resiliencehub +resource-explorer-2 +resource-groups +rolesanywhere +route53 +route53-recovery-control-config +route53domains +route53profiles +route53resolver +rum +runtime-v2-lex +runtime.lex +runtime.sagemaker +s3 +s3-control +s3-outposts +sagemaker-geospatial +savingsplans +scheduler +schemas +sdb +secretsmanager +securityhub +securitylake +serverlessrepo +servicecatalog +servicecatalog-appregistry +servicediscovery +servicequotas +shield +signer +sms-voice +snowball +sns +sqs +ssm +ssm-contacts +ssm-incidents +ssm-quicksetup +ssm-sap +sso +states +storagegateway +streams.dynamodb +sts +support +supportapp +swf +synthetics +tagging +tax +textract +thinclient +tnb +transcribe +transcribestreaming +transfer +translate +trustedadvisor +verifiedpermissions +voice-chime +voiceid +vpc-lattice +waf +waf-regional +wafv2 +wellarchitected +wisdom +workdocs +workmail +workspaces +workspaces-web +xray diff --git a/codegen-lite/pom.xml b/codegen-lite/pom.xml index 95f7de961ccb..45cdaf2bd129 100644 --- a/codegen-lite/pom.xml +++ b/codegen-lite/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codegen-lite AWS Java SDK :: Code Generator Lite diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataGenerator.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataGenerator.java index 2cca47593d09..e5ac176f19cc 100644 --- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataGenerator.java +++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataGenerator.java @@ -164,7 +164,7 @@ public ClassName className() { private CodeBlock signingRegionsByRegion(Partitions partitions) { Map services = getServiceData(partitions); - CodeBlock.Builder builder = CodeBlock.builder().add("$T.<$T, $T>builder()", + CodeBlock.Builder builder = CodeBlock.builder().add("$T.<$T, $T>builder().allowDuplicateKeys(true)", ImmutableMap.class, serviceEndpointKeyClass(), String.class); services.forEach((partition, service) -> { diff --git a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataProviderGenerator.java b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataProviderGenerator.java index f169fac71f7a..ce422d3d8022 100644 --- a/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataProviderGenerator.java +++ b/codegen-lite/src/main/java/software/amazon/awssdk/codegen/lite/regions/ServiceMetadataProviderGenerator.java @@ -37,21 +37,20 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.codegen.lite.PoetClass; import software.amazon.awssdk.codegen.lite.Utils; -import software.amazon.awssdk.codegen.lite.regions.model.Partitions; import software.amazon.awssdk.utils.ImmutableMap; public class ServiceMetadataProviderGenerator implements PoetClass { - private final Partitions partitions; private final String basePackage; private final String regionBasePackage; + private final Set allowedServices; - public ServiceMetadataProviderGenerator(Partitions partitions, - String basePackage, - String regionBasePackage) { - this.partitions = partitions; + public ServiceMetadataProviderGenerator(String basePackage, + String regionBasePackage, + Set allowedServices) { this.basePackage = basePackage; this.regionBasePackage = regionBasePackage; + this.allowedServices = new HashSet<>(allowedServices); } @Override @@ -69,7 +68,7 @@ public TypeSpec poetClass() { .addModifiers(FINAL) .addField(FieldSpec.builder(mapOfServiceMetadata, "SERVICE_METADATA") .addModifiers(PRIVATE, FINAL, STATIC) - .initializer(regions(partitions)) + .initializer(regions()) .build()) .addMethod(getter()) .build(); @@ -80,20 +79,11 @@ public ClassName className() { return ClassName.get(regionBasePackage, "GeneratedServiceMetadataProvider"); } - private CodeBlock regions(Partitions partitions) { + private CodeBlock regions() { CodeBlock.Builder builder = CodeBlock.builder().add("$T.builder()", ImmutableMap.class); - Set seenServices = new HashSet<>(); - - partitions.getPartitions() - .forEach(p -> p.getServices() - .keySet() - .forEach(s -> { - if (!seenServices.contains(s)) { - builder.add(".put($S, new $T())", s, serviceMetadataClass(s)); - seenServices.add(s); - } - })); + allowedServices.stream().sorted().forEach(s -> + builder.add(".put($S, new $T())", s, serviceMetadataClass(s))); return builder.add(".build()").build(); } diff --git a/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java index 02376fbc5861..7d434d9802a4 100644 --- a/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java +++ b/codegen-lite/src/test/java/software/amazon/awssdk/codegen/lite/regions/RegionGenerationTest.java @@ -17,8 +17,14 @@ import static org.hamcrest.MatcherAssert.assertThat; import static software.amazon.awssdk.codegen.lite.PoetMatchers.generatesTo; +import java.io.BufferedReader; import java.io.File; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Paths; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import software.amazon.awssdk.codegen.lite.regions.model.Partitions; @@ -96,9 +102,10 @@ public void serviceWithOverriddenPartitionsMetadataClass() { @Test public void serviceMetadataProviderClass() { - ServiceMetadataProviderGenerator serviceMetadataProviderGenerator = new ServiceMetadataProviderGenerator(partitions, - SERVICE_METADATA_BASE, - REGION_BASE); + Set allowedServices = loadTestAllowlist(); + ServiceMetadataProviderGenerator serviceMetadataProviderGenerator = new ServiceMetadataProviderGenerator(SERVICE_METADATA_BASE, + REGION_BASE, + allowedServices); assertThat(serviceMetadataProviderGenerator, generatesTo("service-metadata-provider.java")); } @@ -126,4 +133,17 @@ public void partitionMetadataProviderClass() { assertThat(partitionMetadataProviderGenerator, generatesTo("partition-metadata-provider.java")); } + + private Set loadTestAllowlist() { + try (BufferedReader reader = new BufferedReader(new InputStreamReader( + Objects.requireNonNull(getClass().getResourceAsStream("/software/amazon/awssdk/codegen/lite/regions/test-service-metadata-allowlist.txt")), + StandardCharsets.UTF_8))) { + return reader.lines() + .map(String::trim) + .filter(line -> !line.isEmpty() && !line.startsWith("#")) + .collect(Collectors.toSet()); + } catch (Exception e) { + throw new RuntimeException("Failed to load test allowlist", e); + } + } } diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/s3-service-metadata.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/s3-service-metadata.java index 3e5f143ed8ca..f4052e507d3d 100644 --- a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/s3-service-metadata.java +++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/s3-service-metadata.java @@ -41,6 +41,7 @@ public final class S3ServiceMetadata implements ServiceMetadata { private static final Map SIGNING_REGIONS_BY_REGION = ImmutableMap . builder() + .allowDuplicateKeys(true) .put(ServiceEndpointKey.builder().region(Region.of("aws-global")).build(), "us-east-1") .put(ServiceEndpointKey.builder().region(Region.of("fips-ca-central-1")).build(), "ca-central-1") .put(ServiceEndpointKey.builder().region(Region.of("fips-us-east-1")).build(), "us-east-1") diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/service-metadata-provider.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/service-metadata-provider.java index c5231d0ab17e..91441a29172f 100644 --- a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/service-metadata-provider.java +++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/service-metadata-provider.java @@ -3,407 +3,30 @@ import java.util.Map; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkPublicApi; -import software.amazon.awssdk.regions.servicemetadata.A4bServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.AccessAnalyzerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AccountServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AcmPcaServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AcmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AirflowServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AmplifyServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AmplifybackendServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiDetectiveServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.ApiEcrPublicServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.ApiEcrServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiElasticInferenceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiFleethubIotServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiMediatailorServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiPricingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApiSagemakerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApigatewayServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AppIntegrationsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AppflowServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApplicationAutoscalingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApplicationinsightsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AppmeshServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApprunnerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Appstream2ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AppsyncServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ApsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AthenaServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AuditmanagerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AutoscalingPlansServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.AutoscalingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.BackupServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.BatchServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.BraketServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.BudgetsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ChimeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Cloud9ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudcontrolapiServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ClouddirectoryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudformationServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudfrontServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudhsmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Cloudhsmv2ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudsearchServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CloudtrailServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodeartifactServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodebuildServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodecommitServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodedeployServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodeguruProfilerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodeguruReviewerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodepipelineServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodestarConnectionsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodestarNotificationsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CodestarServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CognitoIdentityServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CognitoIdpServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CognitoSyncServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ComprehendServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ComprehendmedicalServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ComputeOptimizerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ConfigServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ConnectServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ConnectparticipantServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ContactLensServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.CurServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DataIotServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DataJobsIotServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DataMediastoreServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DatabrewServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DataexchangeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DatapipelineServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DatasyncServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DaxServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DeeplensServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DevicefarmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DevicesIot1clickServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DirectconnectServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DiscoveryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DlmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DmsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DocdbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.DsServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.DynamodbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EbsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Ec2ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EcsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EdgeSagemakerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EksServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ElasticacheServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ElasticbeanstalkServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ElasticfilesystemServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.ElasticloadbalancingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ElasticmapreduceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ElastictranscoderServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EmailServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EmrContainersServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.EnhancedS3ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EntitlementMarketplaceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.EventsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ExecuteApiServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FinspaceApiServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FinspaceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FirehoseServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FmsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ForecastServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ForecastqueryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FrauddetectorServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.FsxServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GameliftServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GlacierServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GlueServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GrafanaServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GreengrassServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GroundstationServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.GuarddutyServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.HealthServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.HealthlakeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.HoneycodeServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.IamServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IdentityChimeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IdentitystoreServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ImportexportServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.InspectorServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotanalyticsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotdeviceadvisorServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IoteventsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IoteventsdataServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotsecuredtunnelingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotsitewiseServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotthingsgraphServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IotwirelessServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.IvsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KafkaServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KafkaconnectServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KendraServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KinesisServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KinesisanalyticsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KinesisvideoServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.KmsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LakeformationServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.LambdaServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LicenseManagerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LightsailServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LogsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LookoutequipmentServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LookoutmetricsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.LookoutvisionServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MachinelearningServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Macie2ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MacieServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ManagedblockchainServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MarketplacecommerceanalyticsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MediaconnectServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MediaconvertServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MedialiveServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MediapackageServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MediapackageVodServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MediastoreServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MemorydbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MessagingChimeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MeteringMarketplaceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MghServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MgnServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MigrationhubStrategyServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MobileanalyticsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ModelsLexServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ModelsV2LexServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MonitoringServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MqServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.MturkRequesterServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.NeptuneServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.NetworkFirewallServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.NetworkmanagerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.NimbleServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OidcServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OperatorServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OpsworksCmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OpsworksServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OrganizationsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.OutpostsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PersonalizeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PiServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PinpointServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PinpointSmsVoiceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PollyServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.PortalSsoServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ProfileServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ProjectsIot1clickServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.QldbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.QuicksightServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RamServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RdsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RdsdataserviceServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RedshiftServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RekognitionServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ResourceGroupsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RobomakerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Route53RecoveryControlConfigServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.Route53ServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Route53domainsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.Route53resolverServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RuntimeLexServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.RuntimeSagemakerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.RuntimeV2LexServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.S3ControlServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.S3OutpostsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SavingsplansServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SchemasServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SdbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SecretsmanagerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SecurityhubServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ServerlessrepoServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ServicecatalogAppregistryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ServicecatalogServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ServicediscoveryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ServicequotasServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SessionQldbServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ShieldServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SignerServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SmsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SmsVoicePinpointServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SnowDeviceManagementServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SnowballServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SnsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SqsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SsmIncidentsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SsmServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.StatesServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.StoragegatewayServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.StreamsDynamodbServiceMetadata; import software.amazon.awssdk.regions.servicemetadata.StsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SupportServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SwfServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.SyntheticsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TaggingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TextractServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TimestreamQueryServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TimestreamWriteServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TranscribeServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TranscribestreamingServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TransferServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.TranslateServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.ValkyrieServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.VoiceidServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WafRegionalServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WafServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WisdomServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WorkdocsServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WorkmailServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.WorkspacesServiceMetadata; -import software.amazon.awssdk.regions.servicemetadata.XrayServiceMetadata; import software.amazon.awssdk.utils.ImmutableMap; @Generated("software.amazon.awssdk:codegen") @SdkPublicApi public final class GeneratedServiceMetadataProvider implements ServiceMetadataProvider { - private static final Map SERVICE_METADATA = ImmutableMap. builder() - .put("a4b", new A4bServiceMetadata()).put("access-analyzer", new AccessAnalyzerServiceMetadata()) - .put("account", new AccountServiceMetadata()).put("acm", new AcmServiceMetadata()) - .put("acm-pca", new AcmPcaServiceMetadata()).put("airflow", new AirflowServiceMetadata()) - .put("amplify", new AmplifyServiceMetadata()).put("amplifybackend", new AmplifybackendServiceMetadata()) - .put("api.detective", new ApiDetectiveServiceMetadata()).put("api.ecr", new ApiEcrServiceMetadata()) - .put("api.ecr-public", new ApiEcrPublicServiceMetadata()) - .put("api.elastic-inference", new ApiElasticInferenceServiceMetadata()) - .put("api.fleethub.iot", new ApiFleethubIotServiceMetadata()) - .put("api.mediatailor", new ApiMediatailorServiceMetadata()).put("api.pricing", new ApiPricingServiceMetadata()) - .put("api.sagemaker", new ApiSagemakerServiceMetadata()).put("apigateway", new ApigatewayServiceMetadata()) - .put("app-integrations", new AppIntegrationsServiceMetadata()).put("appflow", new AppflowServiceMetadata()) - .put("application-autoscaling", new ApplicationAutoscalingServiceMetadata()) - .put("applicationinsights", new ApplicationinsightsServiceMetadata()).put("appmesh", new AppmeshServiceMetadata()) - .put("apprunner", new ApprunnerServiceMetadata()).put("appstream2", new Appstream2ServiceMetadata()) - .put("appsync", new AppsyncServiceMetadata()).put("aps", new ApsServiceMetadata()) - .put("athena", new AthenaServiceMetadata()).put("auditmanager", new AuditmanagerServiceMetadata()) - .put("autoscaling", new AutoscalingServiceMetadata()).put("autoscaling-plans", new AutoscalingPlansServiceMetadata()) - .put("backup", new BackupServiceMetadata()).put("batch", new BatchServiceMetadata()) - .put("braket", new BraketServiceMetadata()).put("budgets", new BudgetsServiceMetadata()) - .put("ce", new CeServiceMetadata()).put("chime", new ChimeServiceMetadata()) - .put("cloud9", new Cloud9ServiceMetadata()).put("cloudcontrolapi", new CloudcontrolapiServiceMetadata()) - .put("clouddirectory", new ClouddirectoryServiceMetadata()) - .put("cloudformation", new CloudformationServiceMetadata()).put("cloudfront", new CloudfrontServiceMetadata()) - .put("cloudhsm", new CloudhsmServiceMetadata()).put("cloudhsmv2", new Cloudhsmv2ServiceMetadata()) - .put("cloudsearch", new CloudsearchServiceMetadata()).put("cloudtrail", new CloudtrailServiceMetadata()) - .put("codeartifact", new CodeartifactServiceMetadata()).put("codebuild", new CodebuildServiceMetadata()) - .put("codecommit", new CodecommitServiceMetadata()).put("codedeploy", new CodedeployServiceMetadata()) - .put("codeguru-profiler", new CodeguruProfilerServiceMetadata()) - .put("codeguru-reviewer", new CodeguruReviewerServiceMetadata()) - .put("codepipeline", new CodepipelineServiceMetadata()).put("codestar", new CodestarServiceMetadata()) - .put("codestar-connections", new CodestarConnectionsServiceMetadata()) - .put("codestar-notifications", new CodestarNotificationsServiceMetadata()) - .put("cognito-identity", new CognitoIdentityServiceMetadata()).put("cognito-idp", new CognitoIdpServiceMetadata()) - .put("cognito-sync", new CognitoSyncServiceMetadata()).put("comprehend", new ComprehendServiceMetadata()) - .put("comprehendmedical", new ComprehendmedicalServiceMetadata()) - .put("compute-optimizer", new ComputeOptimizerServiceMetadata()).put("config", new ConfigServiceMetadata()) - .put("connect", new ConnectServiceMetadata()).put("connectparticipant", new ConnectparticipantServiceMetadata()) - .put("contact-lens", new ContactLensServiceMetadata()).put("cur", new CurServiceMetadata()) - .put("data.iot", new DataIotServiceMetadata()).put("data.jobs.iot", new DataJobsIotServiceMetadata()) - .put("data.mediastore", new DataMediastoreServiceMetadata()).put("databrew", new DatabrewServiceMetadata()) - .put("dataexchange", new DataexchangeServiceMetadata()).put("datapipeline", new DatapipelineServiceMetadata()) - .put("datasync", new DatasyncServiceMetadata()).put("dax", new DaxServiceMetadata()) - .put("deeplens", new DeeplensServiceMetadata()).put("devicefarm", new DevicefarmServiceMetadata()) - .put("devices.iot1click", new DevicesIot1clickServiceMetadata()) - .put("directconnect", new DirectconnectServiceMetadata()).put("discovery", new DiscoveryServiceMetadata()) - .put("dlm", new DlmServiceMetadata()).put("dms", new DmsServiceMetadata()).put("docdb", new DocdbServiceMetadata()) - .put("ds", new DsServiceMetadata()).put("dynamodb", new DynamodbServiceMetadata()) - .put("ebs", new EbsServiceMetadata()).put("ec2", new Ec2ServiceMetadata()).put("ecs", new EcsServiceMetadata()) - .put("edge.sagemaker", new EdgeSagemakerServiceMetadata()).put("eks", new EksServiceMetadata()) - .put("elasticache", new ElasticacheServiceMetadata()).put("elasticbeanstalk", new ElasticbeanstalkServiceMetadata()) - .put("elasticfilesystem", new ElasticfilesystemServiceMetadata()) - .put("elasticloadbalancing", new ElasticloadbalancingServiceMetadata()) - .put("elasticmapreduce", new ElasticmapreduceServiceMetadata()) - .put("elastictranscoder", new ElastictranscoderServiceMetadata()).put("email", new EmailServiceMetadata()) - .put("emr-containers", new EmrContainersServiceMetadata()) - .put("entitlement.marketplace", new EntitlementMarketplaceServiceMetadata()).put("es", new EsServiceMetadata()) - .put("events", new EventsServiceMetadata()).put("execute-api", new ExecuteApiServiceMetadata()) - .put("finspace", new FinspaceServiceMetadata()).put("finspace-api", new FinspaceApiServiceMetadata()) - .put("firehose", new FirehoseServiceMetadata()).put("fms", new FmsServiceMetadata()) - .put("forecast", new ForecastServiceMetadata()).put("forecastquery", new ForecastqueryServiceMetadata()) - .put("frauddetector", new FrauddetectorServiceMetadata()).put("fsx", new FsxServiceMetadata()) - .put("gamelift", new GameliftServiceMetadata()).put("glacier", new GlacierServiceMetadata()) - .put("glue", new GlueServiceMetadata()).put("grafana", new GrafanaServiceMetadata()) - .put("greengrass", new GreengrassServiceMetadata()).put("groundstation", new GroundstationServiceMetadata()) - .put("guardduty", new GuarddutyServiceMetadata()).put("health", new HealthServiceMetadata()) - .put("healthlake", new HealthlakeServiceMetadata()).put("honeycode", new HoneycodeServiceMetadata()) - .put("iam", new IamServiceMetadata()).put("identity-chime", new IdentityChimeServiceMetadata()) - .put("identitystore", new IdentitystoreServiceMetadata()).put("importexport", new ImportexportServiceMetadata()) - .put("inspector", new InspectorServiceMetadata()).put("iot", new IotServiceMetadata()) - .put("iotanalytics", new IotanalyticsServiceMetadata()) - .put("iotdeviceadvisor", new IotdeviceadvisorServiceMetadata()).put("iotevents", new IoteventsServiceMetadata()) - .put("ioteventsdata", new IoteventsdataServiceMetadata()) - .put("iotsecuredtunneling", new IotsecuredtunnelingServiceMetadata()) - .put("iotsitewise", new IotsitewiseServiceMetadata()).put("iotthingsgraph", new IotthingsgraphServiceMetadata()) - .put("iotwireless", new IotwirelessServiceMetadata()).put("ivs", new IvsServiceMetadata()) - .put("kafka", new KafkaServiceMetadata()).put("kafkaconnect", new KafkaconnectServiceMetadata()) - .put("kendra", new KendraServiceMetadata()).put("kinesis", new KinesisServiceMetadata()) - .put("kinesisanalytics", new KinesisanalyticsServiceMetadata()) - .put("kinesisvideo", new KinesisvideoServiceMetadata()).put("kms", new KmsServiceMetadata()) - .put("lakeformation", new LakeformationServiceMetadata()).put("lambda", new LambdaServiceMetadata()) - .put("license-manager", new LicenseManagerServiceMetadata()).put("lightsail", new LightsailServiceMetadata()) - .put("logs", new LogsServiceMetadata()).put("lookoutequipment", new LookoutequipmentServiceMetadata()) - .put("lookoutmetrics", new LookoutmetricsServiceMetadata()).put("lookoutvision", new LookoutvisionServiceMetadata()) - .put("machinelearning", new MachinelearningServiceMetadata()).put("macie", new MacieServiceMetadata()) - .put("macie2", new Macie2ServiceMetadata()).put("managedblockchain", new ManagedblockchainServiceMetadata()) - .put("marketplacecommerceanalytics", new MarketplacecommerceanalyticsServiceMetadata()) - .put("mediaconnect", new MediaconnectServiceMetadata()).put("mediaconvert", new MediaconvertServiceMetadata()) - .put("medialive", new MedialiveServiceMetadata()).put("mediapackage", new MediapackageServiceMetadata()) - .put("mediapackage-vod", new MediapackageVodServiceMetadata()).put("mediastore", new MediastoreServiceMetadata()) - .put("memorydb", new MemorydbServiceMetadata()).put("messaging-chime", new MessagingChimeServiceMetadata()) - .put("metering.marketplace", new MeteringMarketplaceServiceMetadata()).put("mgh", new MghServiceMetadata()) - .put("mgn", new MgnServiceMetadata()).put("migrationhub-strategy", new MigrationhubStrategyServiceMetadata()) - .put("mobileanalytics", new MobileanalyticsServiceMetadata()).put("models-v2-lex", new ModelsV2LexServiceMetadata()) - .put("models.lex", new ModelsLexServiceMetadata()).put("monitoring", new MonitoringServiceMetadata()) - .put("mq", new MqServiceMetadata()).put("mturk-requester", new MturkRequesterServiceMetadata()) - .put("neptune", new NeptuneServiceMetadata()).put("network-firewall", new NetworkFirewallServiceMetadata()) - .put("networkmanager", new NetworkmanagerServiceMetadata()).put("nimble", new NimbleServiceMetadata()) - .put("oidc", new OidcServiceMetadata()).put("opsworks", new OpsworksServiceMetadata()) - .put("opsworks-cm", new OpsworksCmServiceMetadata()).put("organizations", new OrganizationsServiceMetadata()) - .put("outposts", new OutpostsServiceMetadata()).put("personalize", new PersonalizeServiceMetadata()) - .put("pi", new PiServiceMetadata()).put("pinpoint", new PinpointServiceMetadata()) - .put("pinpoint-sms-voice", new PinpointSmsVoiceServiceMetadata()).put("polly", new PollyServiceMetadata()) - .put("portal.sso", new PortalSsoServiceMetadata()).put("profile", new ProfileServiceMetadata()) - .put("projects.iot1click", new ProjectsIot1clickServiceMetadata()).put("qldb", new QldbServiceMetadata()) - .put("quicksight", new QuicksightServiceMetadata()).put("ram", new RamServiceMetadata()) - .put("rds", new RdsServiceMetadata()).put("rdsdataservice", new RdsdataserviceServiceMetadata()) - .put("redshift", new RedshiftServiceMetadata()).put("rekognition", new RekognitionServiceMetadata()) - .put("resource-groups", new ResourceGroupsServiceMetadata()).put("robomaker", new RobomakerServiceMetadata()) - .put("route53", new Route53ServiceMetadata()) - .put("route53-recovery-control-config", new Route53RecoveryControlConfigServiceMetadata()) - .put("route53domains", new Route53domainsServiceMetadata()) - .put("route53resolver", new Route53resolverServiceMetadata()) - .put("runtime-v2-lex", new RuntimeV2LexServiceMetadata()).put("runtime.lex", new RuntimeLexServiceMetadata()) - .put("runtime.sagemaker", new RuntimeSagemakerServiceMetadata()).put("s3", new EnhancedS3ServiceMetadata()) - .put("s3-control", new S3ControlServiceMetadata()).put("s3-outposts", new S3OutpostsServiceMetadata()) - .put("savingsplans", new SavingsplansServiceMetadata()).put("schemas", new SchemasServiceMetadata()) - .put("sdb", new SdbServiceMetadata()).put("secretsmanager", new SecretsmanagerServiceMetadata()) - .put("securityhub", new SecurityhubServiceMetadata()).put("serverlessrepo", new ServerlessrepoServiceMetadata()) - .put("servicecatalog", new ServicecatalogServiceMetadata()) - .put("servicecatalog-appregistry", new ServicecatalogAppregistryServiceMetadata()) - .put("servicediscovery", new ServicediscoveryServiceMetadata()) - .put("servicequotas", new ServicequotasServiceMetadata()).put("session.qldb", new SessionQldbServiceMetadata()) - .put("shield", new ShieldServiceMetadata()).put("signer", new SignerServiceMetadata()) - .put("sms", new SmsServiceMetadata()).put("sms-voice.pinpoint", new SmsVoicePinpointServiceMetadata()) - .put("snow-device-management", new SnowDeviceManagementServiceMetadata()) - .put("snowball", new SnowballServiceMetadata()).put("sns", new SnsServiceMetadata()) - .put("sqs", new SqsServiceMetadata()).put("ssm", new SsmServiceMetadata()) - .put("ssm-incidents", new SsmIncidentsServiceMetadata()).put("states", new StatesServiceMetadata()) - .put("storagegateway", new StoragegatewayServiceMetadata()) - .put("streams.dynamodb", new StreamsDynamodbServiceMetadata()).put("sts", new StsServiceMetadata()) - .put("support", new SupportServiceMetadata()).put("swf", new SwfServiceMetadata()) - .put("synthetics", new SyntheticsServiceMetadata()).put("tagging", new TaggingServiceMetadata()) - .put("textract", new TextractServiceMetadata()).put("timestream.query", new TimestreamQueryServiceMetadata()) - .put("timestream.write", new TimestreamWriteServiceMetadata()).put("transcribe", new TranscribeServiceMetadata()) - .put("transcribestreaming", new TranscribestreamingServiceMetadata()).put("transfer", new TransferServiceMetadata()) - .put("translate", new TranslateServiceMetadata()).put("valkyrie", new ValkyrieServiceMetadata()) - .put("voiceid", new VoiceidServiceMetadata()).put("waf", new WafServiceMetadata()) - .put("waf-regional", new WafRegionalServiceMetadata()).put("wisdom", new WisdomServiceMetadata()) - .put("workdocs", new WorkdocsServiceMetadata()).put("workmail", new WorkmailServiceMetadata()) - .put("workspaces", new WorkspacesServiceMetadata()).put("xray", new XrayServiceMetadata()) - .put("operator", new OperatorServiceMetadata()).build(); + private static final Map SERVICE_METADATA = ImmutableMap.builder() + .put("access-analyzer", new AccessAnalyzerServiceMetadata()).put("api.ecr", new ApiEcrServiceMetadata()) + .put("api.ecr-public", new ApiEcrPublicServiceMetadata()).put("dynamodb", new DynamodbServiceMetadata()) + .put("elasticloadbalancing", new ElasticloadbalancingServiceMetadata()).put("iam", new IamServiceMetadata()) + .put("lambda", new LambdaServiceMetadata()).put("route53", new Route53ServiceMetadata()) + .put("runtime.sagemaker", new RuntimeSagemakerServiceMetadata()).put("s3", new EnhancedS3ServiceMetadata()) + .put("s3-outposts", new S3OutpostsServiceMetadata()).put("sts", new StsServiceMetadata()).build(); public ServiceMetadata serviceMetadata(String endpointPrefix) { return SERVICE_METADATA.get(endpointPrefix); diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/sts-service-metadata.java b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/sts-service-metadata.java index 0a814ccc1794..0023a19f4ec2 100644 --- a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/sts-service-metadata.java +++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/sts-service-metadata.java @@ -41,6 +41,7 @@ public final class StsServiceMetadata implements ServiceMetadata { private static final Map SIGNING_REGIONS_BY_REGION = ImmutableMap . builder() + .allowDuplicateKeys(true) .put(ServiceEndpointKey.builder().region(Region.of("aws-global")).build(), "us-east-1") .put(ServiceEndpointKey.builder().region(Region.of("us-east-1-fips")).build(), "us-east-1") .put(ServiceEndpointKey.builder().region(Region.of("us-east-2-fips")).build(), "us-east-2") diff --git a/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/test-service-metadata-allowlist.txt b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/test-service-metadata-allowlist.txt new file mode 100644 index 000000000000..aafe0b58d2e8 --- /dev/null +++ b/codegen-lite/src/test/resources/software/amazon/awssdk/codegen/lite/regions/test-service-metadata-allowlist.txt @@ -0,0 +1,13 @@ +# Test allowlist for ServiceMetadataProviderGenerator +access-analyzer +api.ecr +api.ecr-public +dynamodb +elasticloadbalancing +iam +lambda +route53 +runtime.sagemaker +s3 +s3-outposts +sts diff --git a/codegen-maven-plugin/pom.xml b/codegen-maven-plugin/pom.xml index 2dbc15ddcc7d..5aa54036672b 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml codegen-maven-plugin diff --git a/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java b/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java index 9e59e82abdb1..ce8d2d524628 100644 --- a/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java +++ b/codegen-maven-plugin/src/main/java/software/amazon/awssdk/codegen/maven/plugin/GenerationMojo.java @@ -42,6 +42,7 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.Paginators; import software.amazon.awssdk.codegen.model.service.ServiceModel; @@ -62,6 +63,7 @@ public class GenerationMojo extends AbstractMojo { private static final String PAGINATORS_FILE = "paginators-1.json"; private static final String ENDPOINT_RULE_SET_FILE = "endpoint-rule-set.json"; private static final String ENDPOINT_TESTS_FILE = "endpoint-tests.json"; + private static final String ENDPOINT_BDD_FILE = "endpoint-bdd-1.json"; @Parameter(property = "codeGenResources", defaultValue = "${basedir}/src/main/resources/codegen-resources/") @@ -144,6 +146,7 @@ private List initGenerationParams() throws MojoExecutionExcept .waitersModel(loadWaiterModel(modelRootPath)) .paginatorsModel(loadPaginatorModel(modelRootPath)) .endpointRuleSetModel(loadEndpointRuleSetModel(modelRootPath)) + .endpointBddModel(loadEndpointBddModel(modelRootPath)) .endpointTestSuiteModel(loadEndpointTestSuiteModel(modelRootPath)) .build(); String intermediateModelFileNamePrefix = intermediateModelFileNamePrefix(c2jModels); @@ -218,6 +221,10 @@ private EndpointTestSuiteModel loadEndpointTestSuiteModel(Path root) { return loadOptionalModel(EndpointTestSuiteModel.class, root.resolve(ENDPOINT_TESTS_FILE)).orElse(null); } + private EndpointBddModel loadEndpointBddModel(Path root) { + return loadOptionalModel(EndpointBddModel.class, root.resolve(ENDPOINT_BDD_FILE)).orElse(null); + } + /** * Load required model from the project resources. */ diff --git a/codegen/pom.xml b/codegen/pom.xml index 2557e05dbcbe..a5b07e36d255 100644 --- a/codegen/pom.xml +++ b/codegen/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codegen AWS Java SDK :: Code Generator diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java index 41d1f32693f8..f5764111371c 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/AddMetadata.java @@ -62,6 +62,7 @@ public static Metadata constructMetadata(ServiceModel serviceModel, .withDocumentation(serviceModel.getDocumentation()) .withServiceAbbreviation(serviceMetadata.getServiceAbbreviation()) .withBatchmanagerPackageName(namingStrategy.getBatchManagerPackageName(serviceName)) + .withPresignedUrlPackageName(namingStrategy.getPresignedUrlPackageName(serviceName)) .withServiceFullName(serviceMetadata.getServiceFullName()) .withServiceName(serviceName) .withSyncClient(String.format(Constant.SYNC_CLIENT_CLASS_NAME_PATTERN, serviceName)) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/C2jModels.java b/codegen/src/main/java/software/amazon/awssdk/codegen/C2jModels.java index 84d136782434..ecfccd1fd020 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/C2jModels.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/C2jModels.java @@ -17,6 +17,7 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.Paginators; import software.amazon.awssdk.codegen.model.service.ServiceModel; @@ -32,6 +33,7 @@ public class C2jModels { private final Waiters waitersModel; private final EndpointRuleSetModel endpointRuleSetModel; private final EndpointTestSuiteModel endpointTestSuiteModel; + private final EndpointBddModel endpointBddModel; private final CustomizationConfig customizationConfig; private final Paginators paginatorsModel; @@ -39,12 +41,14 @@ private C2jModels(ServiceModel serviceModel, Waiters waitersModel, EndpointRuleSetModel endpointRuleSetModel, EndpointTestSuiteModel endpointTestSuiteModel, + EndpointBddModel endpointBddModel, CustomizationConfig customizationConfig, Paginators paginatorsModel) { this.serviceModel = serviceModel; this.waitersModel = waitersModel; this.endpointRuleSetModel = endpointRuleSetModel; this.endpointTestSuiteModel = endpointTestSuiteModel; + this.endpointBddModel = endpointBddModel; this.customizationConfig = customizationConfig; this.paginatorsModel = paginatorsModel; } @@ -77,12 +81,17 @@ public EndpointTestSuiteModel endpointTestSuiteModel() { return endpointTestSuiteModel; } + public EndpointBddModel endpointBddModel() { + return endpointBddModel; + } + public static class Builder implements SdkBuilder { private ServiceModel serviceModel; private Waiters waitersModel; private EndpointRuleSetModel endpointRuleSetModel; private EndpointTestSuiteModel endpointTestSuiteModel; + private EndpointBddModel endpointBddModel; private CustomizationConfig customizationConfig; private Paginators paginatorsModel; @@ -119,12 +128,17 @@ public Builder endpointTestSuiteModel(EndpointTestSuiteModel endpointTestSuiteMo return this; } + public Builder endpointBddModel(EndpointBddModel endpointBddModel) { + this.endpointBddModel = endpointBddModel; + return this; + } + @Override public C2jModels build() { Waiters waiters = waitersModel != null ? waitersModel : Waiters.none(); Paginators paginators = paginatorsModel != null ? paginatorsModel : Paginators.none(); - return new C2jModels(serviceModel, waiters, endpointRuleSetModel, endpointTestSuiteModel, customizationConfig, - paginators); + return new C2jModels(serviceModel, waiters, endpointRuleSetModel, endpointTestSuiteModel, endpointBddModel, + customizationConfig, paginators); } } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/IntermediateModelBuilder.java b/codegen/src/main/java/software/amazon/awssdk/codegen/IntermediateModelBuilder.java index 8848973412d9..d2917e206288 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/IntermediateModelBuilder.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/IntermediateModelBuilder.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -37,8 +38,10 @@ import software.amazon.awssdk.codegen.model.intermediate.OperationModel; import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; import software.amazon.awssdk.codegen.model.service.AuthType; import software.amazon.awssdk.codegen.model.service.CustomOperationContextParam; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.Operation; import software.amazon.awssdk.codegen.model.service.Paginators; @@ -65,6 +68,7 @@ public class IntermediateModelBuilder { private final Waiters waiters; private final EndpointRuleSetModel endpointRuleSet; private final EndpointTestSuiteModel endpointTestSuiteModel; + private final EndpointBddModel endpointBddModel; public IntermediateModelBuilder(C2jModels models) { this.customConfig = models.customizationConfig(); @@ -76,6 +80,7 @@ public IntermediateModelBuilder(C2jModels models) { this.waiters = models.waitersModel(); this.endpointRuleSet = models.endpointRuleSetModel(); this.endpointTestSuiteModel = models.endpointTestSuiteModel(); + this.endpointBddModel = models.endpointBddModel(); } @@ -138,7 +143,8 @@ public IntermediateModel build() { IntermediateModel fullModel = new IntermediateModel( constructMetadata(service, customConfig), operations, shapes, customConfig, endpointOperation, paginators.getPagination(), namingStrategy, - waiters.getWaiters(), endpointRuleSet, endpointTestSuiteModel, service.getClientContextParams()); + waiters.getWaiters(), endpointRuleSet, endpointTestSuiteModel, endpointBddModel, + service.getClientContextParams()); customization.postprocess(fullModel); @@ -158,8 +164,9 @@ public IntermediateModel build() { fullModel.getPaginators(), namingStrategy, fullModel.getWaiters(), - fullModel.getEndpointRuleSetModel(), + endpointRuleSet, endpointTestSuiteModel, + fullModel.getEndpointBddModel(), service.getClientContextParams()); linkMembersToShapes(trimmedModel); @@ -170,7 +177,7 @@ public IntermediateModel build() { setSimpleMethods(trimmedModel); namingStrategy.validateCustomerVisibleNaming(trimmedModel); - customizeEndpointParameters(fullModel, endpointRuleSet); + customizeEndpointParameters(trimmedModel); customizeOperationContextParams(trimmedModel, fullModel.getCustomizationConfig().getCustomOperationContextParams()); return trimmedModel; } @@ -196,15 +203,25 @@ private static void customizeOperationContextParams(IntermediateModel trimmedMod }); } - private void customizeEndpointParameters(IntermediateModel fullModel, EndpointRuleSetModel endpointRuleSet) { - if (fullModel.getCustomizationConfig().getEndpointParameters() != null) { - fullModel.getCustomizationConfig().getEndpointParameters().keySet().forEach(key -> { - if (endpointRuleSet.getParameters().containsKey(key)) { - throw new IllegalStateException("Duplicate parameters found in customizationConfig"); - } - }); - fullModel.getCustomizationConfig().getEndpointParameters().forEach(endpointRuleSet.getParameters()::put); + /** + * Merges the parameters declared by {@code customizationConfig} into the ones the service's endpoint model + * declares. This is the only writer of {@link IntermediateModel#setEndpointParameters(Map)}, so the merged set is + * what every generated class sees. + */ + private void customizeEndpointParameters(IntermediateModel model) { + Map customParameters = model.getCustomizationConfig().getEndpointParameters(); + if (CollectionUtils.isNullOrEmpty(customParameters)) { + return; } + + Map parameters = new LinkedHashMap<>(model.getEndpointParameters()); + customParameters.forEach((name, parameter) -> { + if (parameters.containsKey(name)) { + throw new IllegalStateException("Duplicate parameters found in customizationConfig"); + } + parameters.put(name, parameter); + }); + model.setEndpointParameters(parameters); } /** diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultCustomizationProcessor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultCustomizationProcessor.java index 1511bf6be282..d0fbd360dbf3 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultCustomizationProcessor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultCustomizationProcessor.java @@ -43,7 +43,8 @@ public static CodegenCustomizationProcessor getProcessorFor( new S3ControlRemoveAccountIdHostPrefixProcessor(), new ExplicitStringPayloadQueryProtocolProcessor(), new LowercaseShapeValidatorProcessor(), - new LongPollingOperationProcessor() + new LongPollingOperationProcessor(), + new DefaultReadWriteTimeoutExemptionProcessor() ); } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessor.java new file mode 100644 index 000000000000..87766c3cfb85 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessor.java @@ -0,0 +1,117 @@ +/* + * 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.codegen.customization.processors; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.codegen.customization.CodegenCustomizationProcessor; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.service.ServiceModel; +import software.amazon.awssdk.protocols.jsoncore.JsonNode; +import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser; +import software.amazon.awssdk.utils.Validate; + +/** + * Bakes the per-service default read/write inactivity timeout tier into the generated service HTTP config. The tiers come from a + * checked-in copy of the shared exemption artifact ({@code default-read-write-timeout-exemptions.json}), keyed by the service's + * sdkId ({@link software.amazon.awssdk.codegen.model.intermediate.Metadata#getServiceId()}). + * + *

An artifact value of {@code -1} marks a fully-exempt service (no default timeout applies); a positive value is the applied + * timeout in milliseconds. A service absent from the artifact has nothing baked, and {@code aws-core} supplies the flat default + * when the rollout gate is on. The rollout gate itself is applied later, in {@code aws-core}; this processor only bakes the + * per-service tier, which is the same regardless of whether the gate is on. + */ +public class DefaultReadWriteTimeoutExemptionProcessor implements CodegenCustomizationProcessor { + + private static final String EXEMPTIONS_RESOURCE = "software/amazon/awssdk/codegen/default-read-write-timeout-exemptions.json"; + + private static final Map SERVICE_ID_TO_TIMEOUT_MILLIS = loadExemptions(); + + private final Map serviceIdToTimeoutMillis; + + public DefaultReadWriteTimeoutExemptionProcessor() { + this(SERVICE_ID_TO_TIMEOUT_MILLIS); + } + + @SdkTestInternalApi + DefaultReadWriteTimeoutExemptionProcessor(Map serviceIdToTimeoutMillis) { + this.serviceIdToTimeoutMillis = serviceIdToTimeoutMillis; + } + + @Override + public void preprocess(ServiceModel serviceModel) { + // no-op + } + + @Override + public void postprocess(IntermediateModel intermediateModel) { + String serviceId = intermediateModel.getMetadata().getServiceId(); + Long timeoutMillis = serviceIdToTimeoutMillis.get(serviceId); + if (timeoutMillis != null) { + intermediateModel.getMetadata().setDefaultReadWriteTimeoutMillis(timeoutMillis); + } + } + + /** + * Fails if any artifact key does not match one of {@code knownServiceIds}. Matching is exact (case-sensitive), so a stale + * key (no such service) or a mis-cased key both surface here: either would otherwise silently leave the intended service + * unlisted and wrongly apply the flat default instead of its exempt/partial tier. + * + *

Codegen processes one service per run, so this whole-artifact cross-check cannot run inside {@link #postprocess} (a + * single run never sees every serviceId). It is invoked at build time by the coverage test against the full set of service + * sdkIds. + */ + void validateArtifactKeys(Set knownServiceIds) { + List unknownKeys = serviceIdToTimeoutMillis.keySet().stream() + .filter(key -> !knownServiceIds.contains(key)) + .sorted() + .collect(Collectors.toList()); + if (!unknownKeys.isEmpty()) { + throw new IllegalStateException( + "Read/write timeout exemption artifact " + EXEMPTIONS_RESOURCE + " contains key(s) matching no service sdkId " + + "(a stale or mis-cased key silently leaves that service unlisted): " + unknownKeys); + } + } + + private static Map loadExemptions() { + Map exemptions = new HashMap<>(); + try (InputStream stream = DefaultReadWriteTimeoutExemptionProcessor.class.getClassLoader() + .getResourceAsStream(EXEMPTIONS_RESOURCE)) { + Validate.notNull(stream, "Failed to load read/write timeout exemption artifact: %s", EXEMPTIONS_RESOURCE); + JsonNode root = JsonNodeParser.create().parse(stream); + root.asObject().forEach((serviceId, value) -> exemptions.put(serviceId, parseTimeoutMillis(serviceId, value))); + } catch (IOException e) { + throw new RuntimeException("Failed to read read/write timeout exemption artifact: " + EXEMPTIONS_RESOURCE, e); + } + return Collections.unmodifiableMap(exemptions); + } + + private static long parseTimeoutMillis(String serviceId, JsonNode value) { + try { + return Long.parseLong(value.asNumber()); + } catch (RuntimeException e) { + throw new IllegalArgumentException( + "Invalid numeric value for key '" + serviceId + "' in " + EXEMPTIONS_RESOURCE + ": " + value, e); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java index 900205933515..aded0d30ebb0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProvider.java @@ -107,4 +107,8 @@ public String getAuthSchemeInternalDirectory() { public String getJmesPathInternalDirectory() { return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullInternalJmesPathPackageName()); } + + public String getWarmUpProviderDirectory() { + return sourceDirectory + "/" + Utils.packageToDirectory(model.getMetadata().getFullWarmUpInternalPackageName()); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTask.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTask.java new file mode 100644 index 000000000000..9e7e28a1774f --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTask.java @@ -0,0 +1,72 @@ +/* + * 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.codegen.emitters; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.List; + +/** + * Appends a generated {@code SdkWarmUpProvider} implementation's fully-qualified class name to the shared + * {@code META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider} resource file. + * + *

This task writes a plain resource file rather than a {@code .java} file, so it does not use + * {@link SimpleGeneratorTask}. It creates the file once and appends to it for each subsequent service, and + * re-registering the same class name is a no-op. + */ +public final class WarmUpProviderRegistrationTask extends GeneratorTask { + + private static final String SPI_RESOURCE_PATH = + "META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider"; + + private final String resourcesDirectory; + private final String providerClassName; + + public WarmUpProviderRegistrationTask(String resourcesDirectory, String providerClassName) { + this.resourcesDirectory = resourcesDirectory; + this.providerClassName = providerClassName; + } + + @Override + public void compute() { + try { + Path file = Paths.get(resourcesDirectory, SPI_RESOURCE_PATH); + Path parent = file.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + + if (Files.exists(file)) { + List lines = Files.readAllLines(file, StandardCharsets.UTF_8); + if (lines.contains(providerClassName)) { + return; + } + } + + Files.write(file, + (providerClassName + "\n").getBytes(StandardCharsets.UTF_8), + StandardOpenOption.CREATE, + StandardOpenOption.APPEND); + } catch (IOException e) { + throw new UncheckedIOException("Failed to register warm up provider " + providerClassName, e); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java index a6b3b75e4fcc..888a7cbce01b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/AwsGeneratorTasks.java @@ -28,6 +28,7 @@ public AwsGeneratorTasks(GeneratorTaskParams params) { new EventStreamGeneratorTasks(params), new WaitersGeneratorTasks(params), new EndpointProviderTasks(params), - new AuthSchemeGeneratorTasks(params)); + new AuthSchemeGeneratorTasks(params), + new WarmUpProviderTasks(params)); } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/EndpointProviderTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/EndpointProviderTasks.java index b72a33263c5b..6c5721941d73 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/EndpointProviderTasks.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/EndpointProviderTasks.java @@ -24,7 +24,6 @@ import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask; import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; -import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; import software.amazon.awssdk.codegen.model.service.ClientContextParam; import software.amazon.awssdk.codegen.poet.rules.ClientContextParamsClassSpec; import software.amazon.awssdk.codegen.poet.rules.DefaultPartitionDataProviderSpec; @@ -34,7 +33,7 @@ import software.amazon.awssdk.codegen.poet.rules.EndpointProviderTestSpec; import software.amazon.awssdk.codegen.poet.rules.EndpointResolverUtilsSpec; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesClientTestSpec; -import software.amazon.awssdk.codegen.poet.rules2.EndpointProviderSpec2; +import software.amazon.awssdk.codegen.poet.rules.bdd.BddEndpointProviderSpec; public final class EndpointProviderTasks extends BaseGeneratorTasks { private final GeneratorTaskParams generatorTaskParams; @@ -49,14 +48,12 @@ protected List createTasks() throws Exception { List tasks = new ArrayList<>(); tasks.add(generateInterface()); tasks.add(generateParams()); - if (shouldGenerateCompiledEndpointRules()) { - tasks.add(generateDefaultProvider2()); - tasks.add(new RulesEngineRuntimeLiteGeneratorTask(generatorTaskParams)); - tasks.add(new RulesEngineRuntimeGeneratorTask2(generatorTaskParams)); + if (generatorTaskParams.getModel().getEndpointBddModel() != null) { + tasks.add(generateDefaultProviderBdd()); } else { - tasks.add(generateDefaultProvider()); - tasks.add(new RulesEngineRuntimeGeneratorTask(generatorTaskParams)); + tasks.add(generateDefaultProvider2()); } + tasks.add(new RulesEngineRuntimeGeneratorTask(generatorTaskParams)); if (shouldGenerateJmesPathRuntime()) { tasks.add(new JmesPathRuntimeGeneratorTask(generatorTaskParams)); } @@ -82,12 +79,16 @@ private GeneratorTask generateParams() { return new PoetGeneratorTask(endpointRulesDir(), model.getFileHeader(), new EndpointParametersClassSpec(model)); } - private GeneratorTask generateDefaultProvider() { + private GeneratorTask generateDefaultProvider2() { return new PoetGeneratorTask(endpointRulesInternalDir(), model.getFileHeader(), new EndpointProviderSpec(model)); } - private GeneratorTask generateDefaultProvider2() { - return new PoetGeneratorTask(endpointRulesInternalDir(), model.getFileHeader(), new EndpointProviderSpec2(model)); + private GeneratorTask generateDefaultProviderBdd() { + return new PoetGeneratorTask( + endpointRulesInternalDir(), + model.getFileHeader(), + new BddEndpointProviderSpec(model) + ); } private GeneratorTask generateDefaultPartitionsProvider() { @@ -95,10 +96,6 @@ private GeneratorTask generateDefaultPartitionsProvider() { new DefaultPartitionDataProviderSpec(model)); } - private boolean shouldGenerateCompiledEndpointRules() { - CustomizationConfig customizationConfig = generatorTaskParams.getModel().getCustomizationConfig(); - return customizationConfig.isEnableGenerateCompiledEndpointRules(); - } private Collection generateInterceptors() { return Arrays.asList( @@ -157,8 +154,9 @@ private boolean shouldGenerateJmesPathRuntime() { return true; } - Map endpointParameters = model.getEndpointRuleSetModel().getParameters(); - if (endpointParameters == null) { + // Operation context params are JMESPath expressions over the request that feed endpoint parameters, so a + // service declaring no endpoint parameters has nothing for them to bind to. + if (model.getEndpointParameters().isEmpty()) { return false; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeGeneratorTask2.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeGeneratorTask2.java deleted file mode 100644 index 744177e9e50c..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeGeneratorTask2.java +++ /dev/null @@ -1,92 +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.codegen.emitters.tasks; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import software.amazon.awssdk.codegen.emitters.GeneratorTask; -import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; -import software.amazon.awssdk.codegen.emitters.SimpleGeneratorTask; -import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; -import software.amazon.awssdk.utils.IoUtils; -import software.amazon.awssdk.utils.StringUtils; -import software.amazon.awssdk.utils.Validate; - -public final class RulesEngineRuntimeGeneratorTask2 extends BaseGeneratorTasks { - private final String engineInternalClassDir; - private final String engineInternalPackageName; - private final String fileHeader; - private final EndpointRulesSpecUtils endpointRulesSpecUtils; - - public RulesEngineRuntimeGeneratorTask2(GeneratorTaskParams generatorTaskParams) { - super(generatorTaskParams); - this.engineInternalClassDir = generatorTaskParams.getPathProvider().getEndpointRulesInternalDirectory(); - this.engineInternalPackageName = generatorTaskParams.getModel().getMetadata().getFullInternalEndpointRulesPackageName(); - this.fileHeader = generatorTaskParams.getModel().getFileHeader(); - this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(generatorTaskParams.getModel()); - } - - @Override - protected List createTasks() throws Exception { - List copyTasks = new ArrayList<>(); - List rulesEngineFiles = endpointRulesSpecUtils.rulesEngineResourceFiles2(); - for (String path : rulesEngineJavaFilePaths(rulesEngineFiles)) { - String newFileName = computeNewName(path); - copyTasks.add(new SimpleGeneratorTask(engineInternalClassDir, - newFileName, - fileHeader, - () -> rulesEngineFileContent("/" + path))); - } - - return copyTasks; - } - - private List rulesEngineJavaFilePaths(Collection runtimeEngineFiles) { - return runtimeEngineFiles.stream() - .filter(e -> e.endsWith(".java.resource")) - .collect(Collectors.toList()); - } - - private String rulesEngineFileContent(String path) { - return "package " + engineInternalPackageName + ";\n" + - "\n" - + loadResourceAsString(path); - } - - private String loadResourceAsString(String path) { - try { - return IoUtils.toUtf8String(loadResource(path)); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private InputStream loadResource(String name) { - InputStream resourceAsStream = RulesEngineRuntimeGeneratorTask2.class.getResourceAsStream(name); - Validate.notNull(resourceAsStream, "Failed to load resource from %s", name); - return resourceAsStream; - } - - private String computeNewName(String path) { - String[] pathComponents = path.split("/"); - return StringUtils.replace(pathComponents[pathComponents.length - 1], ".resource", ""); - } -} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeLiteGeneratorTask.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeLiteGeneratorTask.java deleted file mode 100644 index d223f2d6ace9..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/RulesEngineRuntimeLiteGeneratorTask.java +++ /dev/null @@ -1,57 +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.codegen.emitters.tasks; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; -import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; - -/** A version of {@link software.amazon.awssdk.codegen.emitters.tasks.RulesEngineRuntimeGeneratorTask} that copies a minimal - * set of the interpreter related classes. This set represents the only classes that need to be copied when compiled rules are - * enabled. - * - * @see CustomizationConfig#isEnableGenerateCompiledEndpointRules() - */ -public final class RulesEngineRuntimeLiteGeneratorTask extends RulesEngineRuntimeGeneratorTask { - // Note: leading slashes are important to disambiguate between files that share the same suffix - private static final List FILES_TO_COPY = Stream.of("/Outputs.java.resource", - "/RegionOverride.java.resource", - "/Partition.java.resource", - "/PartitionDataProvider.java.resource", - "/AwsEndpointProviderUtils.java.resource", - "/Arn.java.resource", - "/Value.java.resource", - "/Identifier.java.resource", - "/EndpointAuthSchemeStrategy.java.resource", - "/EndpointAttributeProvider.java.resource", - "/EndpointAuthSchemeStrategyFactory.java.resource", - "/DefaultEndpointAuthSchemeStrategy.java.resource") - .collect(Collectors.toList()); - - public RulesEngineRuntimeLiteGeneratorTask(GeneratorTaskParams generatorTaskParams) { - super(generatorTaskParams); - } - - protected List rulesEngineJavaFilePaths(Collection runtimeEngineFiles) { - return super.rulesEngineJavaFilePaths(runtimeEngineFiles) - .stream() - .filter(e -> FILES_TO_COPY.stream().anyMatch(e::endsWith)) - .collect(Collectors.toList()); - } -} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/WarmUpProviderTasks.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/WarmUpProviderTasks.java new file mode 100644 index 000000000000..9d22ec0aebf1 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/tasks/WarmUpProviderTasks.java @@ -0,0 +1,53 @@ +/* + * 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.codegen.emitters.tasks; + +import java.util.ArrayList; +import java.util.List; +import software.amazon.awssdk.codegen.emitters.GeneratorTask; +import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; +import software.amazon.awssdk.codegen.emitters.PoetGeneratorTask; +import software.amazon.awssdk.codegen.emitters.WarmUpProviderRegistrationTask; +import software.amazon.awssdk.codegen.poet.warmup.WarmUpProviderSpec; + +/** + * Emits the per-service {@code SdkWarmUpProvider} implementation and its {@code META-INF/services} registration. + */ +public final class WarmUpProviderTasks extends BaseGeneratorTasks { + + private final GeneratorTaskParams params; + + public WarmUpProviderTasks(GeneratorTaskParams params) { + super(params); + this.params = params; + } + + @Override + protected List createTasks() throws Exception { + List tasks = new ArrayList<>(); + + WarmUpProviderSpec spec = new WarmUpProviderSpec(model); + + tasks.add(new PoetGeneratorTask(warmUpProviderDir(), model.getFileHeader(), spec)); + tasks.add(new WarmUpProviderRegistrationTask(params.getPathProvider().getResourcesDirectory(), + spec.className().toString())); + return tasks; + } + + private String warmUpProviderDir() { + return params.getPathProvider().getWarmUpProviderDirectory(); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java index 5384975f49fb..a0bf024211b7 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/internal/Constant.java @@ -78,6 +78,8 @@ public final class Constant { public static final String PACKAGE_NAME_BATCHMANAGER_PATTERN = "%s.batchmanager"; + public static final String PACKAGE_NAME_PRESIGNEDURL_PATTERN = "%s.presignedurl"; + public static final String PACKAGE_NAME_CUSTOM_AUTH_PATTERN = "%s.auth"; public static final String AUTH_POLICY_ENUM_CLASS_DIR = "software/amazon/awssdk/auth/policy/actions"; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java index fe5bc8703920..069f738c64f6 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/CustomizationConfig.java @@ -230,6 +230,11 @@ public class CustomizationConfig { */ private Boolean defaultNewRetries2026; + /** + * Whether the client will apply a default read/write timeout by default. + */ + private Boolean defaultEnableSocketTimeout2026; + /** * Whether to generate an abstract decorator class that delegates to the async service client */ @@ -314,11 +319,6 @@ public class CustomizationConfig { private boolean s3ExpressAuthSupport; - /** - * Set to true to enable compiled endpoint rules. Currently defaults to false. - */ - private boolean enableGenerateCompiledEndpointRules = false; - /** * Customization related to auth scheme derived from endpoints. */ @@ -351,6 +351,11 @@ public class CustomizationConfig { */ private boolean batchManagerSupported; + /** + * A boolean flag to indicate if Presigned URL Extension is supported. + */ + private boolean presignedUrlExtensionSupported; + /** * A boolean flag to indicate if the fast unmarshaller code path is enabled. */ @@ -732,6 +737,14 @@ public void setDefaultNewRetries2026(Boolean defaultNewRetries2026) { this.defaultNewRetries2026 = defaultNewRetries2026; } + public Boolean getDefaultEnableSocketTimeout2026() { + return defaultEnableSocketTimeout2026; + } + + public void setDefaultEnableSocketTimeout2026(Boolean defaultEnableSocketTimeout2026) { + this.defaultEnableSocketTimeout2026 = defaultEnableSocketTimeout2026; + } + public ServiceConfig getServiceConfig() { return serviceConfig; } @@ -812,14 +825,6 @@ public void setUseS3ExpressSessionAuth(boolean useS3ExpressSessionAuth) { this.useS3ExpressSessionAuth = useS3ExpressSessionAuth; } - public boolean isEnableGenerateCompiledEndpointRules() { - return enableGenerateCompiledEndpointRules; - } - - public void setEnableGenerateCompiledEndpointRules(boolean enableGenerateCompiledEndpointRules) { - this.enableGenerateCompiledEndpointRules = enableGenerateCompiledEndpointRules; - } - public Map getSkipEndpointTests() { return skipEndpointTests; } @@ -951,6 +956,14 @@ public void setBatchManagerSupported(boolean batchManagerSupported) { this.batchManagerSupported = batchManagerSupported; } + public boolean getPresignedUrlExtensionSupported() { + return presignedUrlExtensionSupported; + } + + public void setPresignedUrlExtensionSupported(boolean presignedUrlExtensionSupported) { + this.presignedUrlExtensionSupported = presignedUrlExtensionSupported; + } + public boolean getEnableFastUnmarshaller() { return enableFastUnmarshaller; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/IntermediateModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/IntermediateModel.java index 892245e0cffa..dec5791be853 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/IntermediateModel.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/IntermediateModel.java @@ -21,13 +21,18 @@ import java.io.UncheckedIOException; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import software.amazon.awssdk.awscore.AwsResponse; import software.amazon.awssdk.awscore.AwsResponseMetadata; import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; import software.amazon.awssdk.codegen.model.service.ClientContextParam; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.PaginatorDefinition; import software.amazon.awssdk.codegen.model.service.WaiterDefinition; @@ -60,6 +65,12 @@ public final class IntermediateModel { @JsonIgnore private NamingStrategy namingStrategy; + @JsonIgnore + private EndpointBddModel endpointBddModel; + + @JsonIgnore + private Map endpointParameters; + private Map clientContextParams; static { @@ -80,7 +91,7 @@ public IntermediateModel(Metadata metadata, Map shapes, CustomizationConfig customizationConfig) { this(metadata, operations, shapes, customizationConfig, null, - Collections.emptyMap(), null, Collections.emptyMap(), null, null, null); + Collections.emptyMap(), null, Collections.emptyMap(), null, null, null, null); } public IntermediateModel( @@ -94,6 +105,7 @@ public IntermediateModel( Map waiters, EndpointRuleSetModel endpointRuleSetModel, EndpointTestSuiteModel endpointTestSuiteModel, + EndpointBddModel endpointBddModel, Map clientContextParams) { this.metadata = metadata; this.operations = operations; @@ -105,6 +117,7 @@ public IntermediateModel( this.waiters = waiters; this.endpointRuleSetModel = endpointRuleSetModel; this.endpointTestSuiteModel = endpointTestSuiteModel; + this.endpointBddModel = endpointBddModel; this.clientContextParams = clientContextParams; } @@ -169,7 +182,53 @@ public Map getWaiters() { return waiters; } - public EndpointRuleSetModel getEndpointRuleSetModel() { + /** + * The endpoint parameters this service declares. + * + *

Unmodifiable, because parameters are assembled once: {@link + * software.amazon.awssdk.codegen.IntermediateModelBuilder} merges in any that {@code customizationConfig} + * declares, and nothing else may add to the set. + * + * @see #setEndpointParameters(Map) + */ + @JsonIgnore + public Map getEndpointParameters() { + if (endpointParameters == null) { + endpointParameters = declaredEndpointParameters(); + } + return Collections.unmodifiableMap(endpointParameters); + } + + /** + * Replaces the endpoint parameters with {@code endpointParameters}, which must be the declared parameters plus any + * the customization config adds. Only {@link software.amazon.awssdk.codegen.IntermediateModelBuilder} should call + * this. + */ + @JsonIgnore + public void setEndpointParameters(Map endpointParameters) { + this.endpointParameters = new LinkedHashMap<>(endpointParameters); + } + + /** + * The rules tree of this service's rule set, for the rules-based endpoint provider. A service on the BDD model + * resolves endpoints from {@link #getEndpointBddModel()} instead and never reads this. + */ + @JsonIgnore + public List getEndpointRules() { + return endpointRuleSetOrDefault().getRules(); + } + + private Map declaredEndpointParameters() { + Map declared = endpointBddModel != null ? endpointBddModel.getParameters() + : endpointRuleSetOrDefault().getParameters(); + // A model may omit `parameters` entirely, which reads back as null rather than as an empty map. + return declared == null ? new LinkedHashMap<>() : new LinkedHashMap<>(declared); + } + + /** + * Falls back to a generic regional rule set for a service that ships neither endpoint model. + */ + private EndpointRuleSetModel endpointRuleSetOrDefault() { if (endpointRuleSetModel == null) { endpointRuleSetModel = EndpointRuleSetModel.defaultRules(metadata.getEndpointPrefix()); } @@ -183,6 +242,10 @@ public EndpointTestSuiteModel getEndpointTestSuiteModel() { return endpointTestSuiteModel; } + public EndpointBddModel getEndpointBddModel() { + return endpointBddModel; + } + public Map getClientContextParams() { return clientContextParams; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java index 4eb10f6bf105..5916fb1ee4de 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/intermediate/Metadata.java @@ -73,6 +73,8 @@ public class Metadata { private String batchManagerPackageName; + private String presignedUrlPackageName; + private String endpointRulesPackageName; private String authSchemePackageName; @@ -113,6 +115,8 @@ public class Metadata { private String serviceId; + private Long defaultReadWriteTimeoutMillis; + private List auth; public List getAuth() { @@ -708,6 +712,24 @@ public Metadata withServiceId(String serviceId) { return this; } + /** + * The default read/write inactivity timeout baked for this service by the exemption processor, in milliseconds, or + * {@code null} when the service is not listed in the exemption artifact. A value of {@code -1} marks a fully-exempt service + * (no default timeout); a positive value is the applied timeout in milliseconds. + */ + public Long getDefaultReadWriteTimeoutMillis() { + return defaultReadWriteTimeoutMillis; + } + + public void setDefaultReadWriteTimeoutMillis(Long defaultReadWriteTimeoutMillis) { + this.defaultReadWriteTimeoutMillis = defaultReadWriteTimeoutMillis; + } + + public Metadata withDefaultReadWriteTimeoutMillis(Long defaultReadWriteTimeoutMillis) { + setDefaultReadWriteTimeoutMillis(defaultReadWriteTimeoutMillis); + return this; + } + public String getWaitersPackageName() { return waitersPackageName; } @@ -775,6 +797,10 @@ public String getFullInternalPackageName() { return joinPackageNames(getFullClientPackageName(), "internal"); } + public String getFullWarmUpInternalPackageName() { + return joinPackageNames(getFullInternalPackageName(), "warmup"); + } + public Metadata setJmesPathPackageName(String jmesPathPackageName) { this.jmesPathPackageName = jmesPathPackageName; return this; @@ -815,4 +841,20 @@ public String getFullBatchManagerPackageName() { return joinPackageNames(rootPackageName, getBatchManagerPackageName()); } + public Metadata withPresignedUrlPackageName(String presignedUrlPackageName) { + setPresignedUrlPackageName(presignedUrlPackageName); + return this; + } + + public String getPresignedUrlPackageName() { + return presignedUrlPackageName; + } + + public void setPresignedUrlPackageName(String presignedUrlPackageName) { + this.presignedUrlPackageName = presignedUrlPackageName; + } + + public String getFullPresignedUrlPackageName() { + return joinPackageNames(rootPackageName, getPresignedUrlPackageName()); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/EndpointBddModel.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/EndpointBddModel.java new file mode 100644 index 000000000000..7173a9935ccd --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/service/EndpointBddModel.java @@ -0,0 +1,142 @@ +/* + * 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.codegen.model.service; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import software.amazon.awssdk.codegen.model.rules.endpoints.ConditionModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; + +public class EndpointBddModel { + private String serviceId; + private String version; + private Map parameters; + private List conditions; + private List results; + private int root; + private int nodeCount; + private String nodes; // Base64-encoded binary representation of BDD nodes. + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public List getConditions() { + return conditions; + } + + public void setConditions(List conditions) { + this.conditions = conditions; + } + + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } + + public String getNodes() { + return nodes; + } + + public int getRoot() { + return root; + } + + public void setRoot(int root) { + this.root = root; + } + + public int getNodeCount() { + return nodeCount; + } + + public void setNodeCount(int nodeCount) { + this.nodeCount = nodeCount; + } + + public void setNodes(String nodes) { + this.nodes = nodes; + } + + public List getDecodedNodes() { + List out = new ArrayList<>(nodeCount); + byte[] data = Base64.getDecoder().decode(nodes); + ByteBuffer buf = ByteBuffer.wrap(data); // big-endian by default + while (buf.remaining() >= 12) { + int conditionIndex = buf.getInt(); + int highRef = buf.getInt(); + int lowRef = buf.getInt(); + out.add(new BddNode(conditionIndex, highRef, lowRef)); + } + return out; + } + + public static class BddNode { + int conditionIndex; + int highRef; + int lowRef; + + public BddNode(int conditionIndex, int highRef, int lowRef) { + this.conditionIndex = conditionIndex; + this.highRef = highRef; + this.lowRef = lowRef; + } + + public int getConditionIndex() { + return conditionIndex; + } + + public int getHighRef() { + return highRef; + } + + public int getLowRef() { + return lowRef; + } + + @Override + public String toString() { + return "[C" + conditionIndex + ", " + highRef + ", " + lowRef + "]"; + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java index b9fcf41e6e0f..dc5257d9c9aa 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/DefaultNamingStrategy.java @@ -220,6 +220,11 @@ public String getJmesPathPackageName(String serviceName) { public String getBatchManagerPackageName(String serviceName) { return getCustomizedPackageName(concatServiceNameIfShareModel(serviceName), Constant.PACKAGE_NAME_BATCHMANAGER_PATTERN); } + + @Override + public String getPresignedUrlPackageName(String serviceName) { + return getCustomizedPackageName(concatServiceNameIfShareModel(serviceName), Constant.PACKAGE_NAME_PRESIGNEDURL_PATTERN); + } @Override public String getSmokeTestPackageName(String serviceName) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java index 5b22363970f0..1047a3a1904b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/naming/NamingStrategy.java @@ -93,6 +93,11 @@ public interface NamingStrategy { * Retrieve the batchManager package name that should be used based on the service name. */ String getBatchManagerPackageName(String serviceName); + + /** + * Retrieve the presignedUrl package name that should be used based on the service name. + */ + String getPresignedUrlPackageName(String serviceName); /** * Retrieve the smote test package name that should be used based on the service name. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java index f119507809c2..9e4fea7f6b31 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetExtension.java @@ -209,4 +209,8 @@ public ClassName getBatchManagerAsyncInterface() { return ClassName.get(model.getMetadata().getFullBatchManagerPackageName(), model.getMetadata().getServiceName() + "AsyncBatchManager"); } + + public ClassName getPresignedUrlExtensionAsyncInterface() { + return ClassName.get(model.getMetadata().getFullPresignedUrlPackageName(), "AsyncPresignedUrlExtension"); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java index 86af5542e886..a2fe74803942 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeParamsSpec.java @@ -147,6 +147,13 @@ private void addAccessorMethods(TypeSpec.Builder b) { .addJavadoc("Returns the region. The region parameter may be used with the $S auth scheme.", AwsV4AuthScheme.SCHEME_ID) .build()); + b.addMethod(MethodSpec.methodBuilder("regionId") + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .returns(String.class) + .addJavadoc("Returns the region ID as a string. Returns null if region is not set.") + .addStatement("$T region = region()", Region.class) + .addStatement("return region == null ? null : region.id()") + .build()); } if (authSchemeSpecUtils.hasSigV4aSupport()) { @@ -228,7 +235,7 @@ private void addBuilderSetterMethods(TypeSpec.Builder b) { } private Map parameters() { - return intermediateModel.getEndpointRuleSetModel().getParameters(); + return intermediateModel.getEndpointParameters(); } private TypeName toCopyableBuilderInterface() { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java index 379366b4182a..e82e3726e608 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/AuthSchemeSpecUtils.java @@ -162,6 +162,10 @@ public boolean hasSigV4aSupport() { return usesSigV4a() || generateEndpointBasedParams(); } + public boolean hasPerOperationAuthOverrides() { + return AuthSchemeCodegenKnowledgeIndex.of(intermediateModel).hasPerOperationAuthSchemesOverrides(); + } + private static Set setOf(String val1, String val2) { Set result = new HashSet<>(); result.add(val1); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java index 28b62024a00d..efcefad7ad9a 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/auth/scheme/DefaultAuthSchemeParamsSpec.java @@ -187,6 +187,13 @@ private void addFieldsAndAccessors(TypeSpec.Builder b) { .returns(Region.class) .addStatement("return region") .build()); + + b.addMethod(MethodSpec.methodBuilder("regionId") + .addModifiers(Modifier.PUBLIC) + .addAnnotation(Override.class) + .returns(String.class) + .addStatement("return region == null ? null : region.id()") + .build()); } if (authSchemeSpecUtils.hasSigV4aSupport()) { @@ -285,6 +292,6 @@ private ClassName builderClassName() { } private Map parameters() { - return intermediateModel.getEndpointRuleSetModel().getParameters(); + return intermediateModel.getEndpointParameters(); } } 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 cb0d9b103f1d..972a12325235 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 @@ -30,6 +30,8 @@ import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; import com.squareup.javapoet.WildcardTypeName; +import java.net.URI; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -47,8 +49,10 @@ import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.codegen.internal.Utils; +import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.OperationModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; import software.amazon.awssdk.codegen.model.service.ClientContextParam; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetExtension; @@ -86,7 +90,6 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; import software.amazon.awssdk.utils.StringUtils; @@ -329,9 +332,10 @@ private Optional mergeInternalDefaultsMethod() { String userAgent = model.getCustomizationConfig().getUserAgent(); RetryMode defaultRetryMode = model.getCustomizationConfig().getDefaultRetryMode(); Boolean defaultNewRetries2026 = model.getCustomizationConfig().getDefaultNewRetries2026(); + Boolean defaultEnableSocketTimeout2026 = model.getCustomizationConfig().getDefaultEnableSocketTimeout2026(); // If none of the options are customized, then we do not need to bother overriding the method - if (userAgent == null && defaultRetryMode == null && defaultNewRetries2026 == null) { + if (!hasInternalDefaults()) { return Optional.empty(); } @@ -353,10 +357,22 @@ private Optional mergeInternalDefaultsMethod() { builder.addCode("c.option($T.DEFAULT_NEW_RETRIES_2026, $L);\n", SdkClientOption.class, defaultNewRetries2026); } + if (defaultEnableSocketTimeout2026 != null) { + builder.addCode("c.option($T.DEFAULT_ENABLE_SOCKET_TIMEOUT_2026, $L);\n", + SdkClientOption.class, defaultEnableSocketTimeout2026); + } builder.addCode("});\n"); return Optional.of(builder.build()); } + private boolean hasInternalDefaults() { + CustomizationConfig customizationConfig = model.getCustomizationConfig(); + return customizationConfig.getUserAgent() != null + || customizationConfig.getDefaultRetryMode() != null + || customizationConfig.getDefaultNewRetries2026() != null + || customizationConfig.getDefaultEnableSocketTimeout2026() != null; + } + private MethodSpec finalizeServiceConfigurationMethod() { String requestHandlerDirectory = Utils.packageToDirectory(model.getMetadata().getFullClientPackageName()); String requestHandlerPath = String.format("%s/execution.interceptors", requestHandlerDirectory); @@ -510,21 +526,107 @@ private MethodSpec finalizeServiceConfigurationMethod() { String serviceNameForSystemProperty = model.getNamingStrategy().getServiceNameForSystemProperties(); String serviceNameForProfileFile = model.getNamingStrategy().getServiceNameForProfileFile(); - builder.addCode("builder.lazyOptionIfAbsent($T.CLIENT_ENDPOINT_PROVIDER, c ->", SdkClientOption.class) - .addCode(" $T.builder()", AwsClientEndpointProvider.class) - .addCode(" .serviceEndpointOverrideEnvironmentVariable($S)", "AWS_ENDPOINT_URL_" + serviceNameForEnvVar) - .addCode(" .serviceEndpointOverrideSystemProperty($S)", "aws.endpointUrl" + serviceNameForSystemProperty) - .addCode(" .serviceProfileProperty($S)", serviceNameForProfileFile) - .addCode(" .serviceEndpointPrefix(serviceEndpointPrefix())") - .addCode(" .defaultProtocol($S)", "https") - .addCode(" .region(c.get($T.AWS_REGION))", AwsClientOption.class) - .addCode(" .profileFile(c.get($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class) - .addCode(" .profileName(c.get($T.PROFILE_NAME))", SdkClientOption.class) - .addCode(" .putAdvancedOption($T.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT,", ServiceMetadataAdvancedOption.class) - .addCode(" c.get($T.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT))", ServiceMetadataAdvancedOption.class) - .addCode(" .dualstackEnabled(c.get($T.DUALSTACK_ENDPOINT_ENABLED))", AwsClientOption.class) - .addCode(" .fipsEnabled(c.get($T.FIPS_ENDPOINT_ENABLED))", AwsClientOption.class) - .addCode(" .build());"); + builder.addCode("builder.lazyOptionIfAbsent($T.CLIENT_ENDPOINT_PROVIDER, c -> {\n", SdkClientOption.class) + .addCode(" $T<$T> overrideEndpoint = $T.builder()\n", + Optional.class, URI.class, + AwsClientEndpointProvider.class) + .addCode(" .serviceEndpointOverrideEnvironmentVariable($S)\n", "AWS_ENDPOINT_URL_" + serviceNameForEnvVar) + .addCode(" .serviceEndpointOverrideSystemProperty($S)\n", "aws.endpointUrl" + serviceNameForSystemProperty) + .addCode(" .serviceProfileProperty($S)\n", serviceNameForProfileFile) + .addCode(" .profileFile(c.get($T.PROFILE_FILE_SUPPLIER))\n", SdkClientOption.class) + .addCode(" .profileName(c.get($T.PROFILE_NAME))\n", SdkClientOption.class) + .addCode(" .resolveFromOverrides();\n") + .addCode(" if (overrideEndpoint.isPresent()) {\n") + .addCode(" return $T.create(overrideEndpoint.get(), true);\n", + ClassName.get("software.amazon.awssdk.core", "ClientEndpointProvider")) + .addCode(" }\n") + .addCode(" $T clientEndpointUri = null;\n", URI.class) + .addCode(" $T region = c.get($T.AWS_REGION);\n", + ClassName.get("software.amazon.awssdk.regions", "Region"), + AwsClientOption.class) + .addCode(" try {\n") + .addCode(" $T endpointParams = $T.builder()\n", + endpointRulesSpecUtils.parametersClassName(), endpointRulesSpecUtils.parametersClassName()); + + if (hasBuiltIn(BuiltInParameter.AWS_REGION)) { + builder.addCode(" .region(region)\n"); + } + + if (hasBuiltIn(BuiltInParameter.AWS_USE_DUAL_STACK)) { + builder.addCode(" .useDualStack(c.get($T.DUALSTACK_ENDPOINT_ENABLED))\n", AwsClientOption.class); + } + if (hasBuiltIn(BuiltInParameter.AWS_USE_FIPS)) { + builder.addCode(" .useFips(c.get($T.FIPS_ENDPOINT_ENABLED))\n", AwsClientOption.class); + } + + builder.addCode(" .build();\n") + .addCode(" $T endpoint = $T.joinLikeSync(defaultEndpointProvider().resolveEndpoint(endpointParams));\n", + ClassName.get("software.amazon.awssdk.endpoints", "Endpoint"), + ClassName.get("software.amazon.awssdk.utils", "CompletableFutureUtils")) + .addCode(" clientEndpointUri = endpoint.url();\n") + .addCode(" } catch (Exception e) {\n") + .addCode(" // Endpoint resolution failed. This is expected for services with required parameters\n") + .addCode(" // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time.\n") + .addCode(" return $T.create($T.create($S), false);\n", + ClassName.get("software.amazon.awssdk.core", "ClientEndpointProvider"), + URI.class, "https://localhost") + .addCode(" }\n") + .addCode(" if (clientEndpointUri.getHost() == null) {\n") + .addCode(" throw $T.create(\"Configured region (\" + region\n", + ClassName.get("software.amazon.awssdk.core.exception", "SdkClientException")) + .addCode(" + \") resulted in an invalid URI: \" + clientEndpointUri\n") + .addCode(" + \". This is usually caused by an invalid region configuration.\");\n") + .addCode(" }\n") + .addCode(" return $T.create(clientEndpointUri, false);\n", + ClassName.get("software.amazon.awssdk.core", "ClientEndpointProvider")) + .addCode("});\n"); + + builder.addCode("builder.lazyOptionIfAbsent($T.SIGNING_REGION, c -> {\n", AwsClientOption.class) + .addCode(" $T region = c.get($T.AWS_REGION);\n", + ClassName.get("software.amazon.awssdk.regions", "Region"), + AwsClientOption.class); + + if (hasBuiltIn(BuiltInParameter.AWS_REGION)) { + builder.addCode(" try {\n") + .addCode(" $T endpointParams = $T.builder()\n", + endpointRulesSpecUtils.parametersClassName(), endpointRulesSpecUtils.parametersClassName()) + .addCode(" .region(region)\n"); + + if (hasBuiltIn(BuiltInParameter.AWS_USE_DUAL_STACK)) { + builder.addCode(" .useDualStack(c.get($T.DUALSTACK_ENDPOINT_ENABLED))\n", AwsClientOption.class); + } + if (hasBuiltIn(BuiltInParameter.AWS_USE_FIPS)) { + builder.addCode(" .useFips(c.get($T.FIPS_ENDPOINT_ENABLED))\n", AwsClientOption.class); + } + + builder.addCode(" .build();\n") + .addCode(" $T endpoint = $T.joinLikeSync(defaultEndpointProvider().resolveEndpoint(endpointParams));\n", + ClassName.get("software.amazon.awssdk.endpoints", "Endpoint"), + ClassName.get("software.amazon.awssdk.utils", "CompletableFutureUtils")) + .addCode(" $T<$T> authSchemes = endpoint.attribute($T.AUTH_SCHEMES);\n", + List.class, + ClassName.get("software.amazon.awssdk.awscore.endpoints.authscheme", "EndpointAuthScheme"), + ClassName.get("software.amazon.awssdk.awscore.endpoints", "AwsEndpointAttribute")) + .addCode(" if (authSchemes != null && !authSchemes.isEmpty()) {\n") + .addCode(" $T firstScheme = authSchemes.get(0);\n", + ClassName.get("software.amazon.awssdk.awscore.endpoints.authscheme", "EndpointAuthScheme")) + .addCode(" if (firstScheme instanceof $T) {\n", + ClassName.get("software.amazon.awssdk.awscore.endpoints.authscheme", "SigV4AuthScheme")) + .addCode(" String signingRegion = (($T) firstScheme).signingRegion();\n", + ClassName.get("software.amazon.awssdk.awscore.endpoints.authscheme", "SigV4AuthScheme")) + .addCode(" if (signingRegion != null) {\n") + .addCode(" return $T.of(signingRegion);\n", + ClassName.get("software.amazon.awssdk.regions", "Region")) + .addCode(" }\n") + .addCode(" }\n") + .addCode(" }\n") + .addCode(" } catch (Exception e) {\n") + .addCode(" // Endpoint resolution failed. Fall back to using the client region as signing region.\n") + .addCode(" }\n"); + } + + builder.addCode(" return region;\n") + .addCode("});\n"); if (model.getMetadata().isJsonProtocol()) { builder.addStatement("builder.option($1T.ENABLE_FAST_UNMARSHALLER, true)", @@ -741,24 +843,27 @@ private void addServiceHttpConfigIfNeeded(TypeSpec.Builder builder, Intermediate String serviceDefaultFqcn = model.getCustomizationConfig().getServiceSpecificHttpConfig(); boolean supportsH2 = model.getMetadata().supportsH2(); boolean usePriorKnowledgeForH2 = model.getCustomizationConfig().isUsePriorKnowledgeForH2(); + Long readWriteTimeoutMillis = model.getMetadata().getDefaultReadWriteTimeoutMillis(); - if (serviceDefaultFqcn != null || supportsH2) { - builder.addMethod(serviceSpecificHttpConfigMethod(serviceDefaultFqcn, supportsH2, usePriorKnowledgeForH2)); + if (serviceDefaultFqcn != null || supportsH2 || readWriteTimeoutMillis != null) { + builder.addMethod(serviceSpecificHttpConfigMethod(serviceDefaultFqcn, supportsH2, usePriorKnowledgeForH2, + readWriteTimeoutMillis)); } } private MethodSpec serviceSpecificHttpConfigMethod(String serviceDefaultFqcn, boolean supportsH2, - boolean usePriorKnowledgeForH2) { + boolean usePriorKnowledgeForH2, Long readWriteTimeoutMillis) { return MethodSpec.methodBuilder("serviceHttpConfig") .addAnnotation(Override.class) .addModifiers(PROTECTED, FINAL) .returns(AttributeMap.class) - .addCode(serviceSpecificHttpConfigMethodBody(serviceDefaultFqcn, supportsH2, usePriorKnowledgeForH2)) + .addCode(serviceSpecificHttpConfigMethodBody(serviceDefaultFqcn, supportsH2, usePriorKnowledgeForH2, + readWriteTimeoutMillis)) .build(); } private CodeBlock serviceSpecificHttpConfigMethodBody(String serviceDefaultFqcn, boolean supportsH2, - boolean usePriorKnowledgeForH2) { + boolean usePriorKnowledgeForH2, Long readWriteTimeoutMillis) { CodeBlock.Builder builder = CodeBlock.builder(); if (serviceDefaultFqcn != null) { @@ -769,14 +874,28 @@ private CodeBlock serviceSpecificHttpConfigMethodBody(String serviceDefaultFqcn, builder.addStatement("$1T result = $1T.empty()", AttributeMap.class); } - if (supportsH2) { - builder.add("return result.merge(AttributeMap.builder()" - + ".put($T.PROTOCOL, $T.HTTP2)", - SdkHttpConfigurationOption.class, Protocol.class); + if (supportsH2 || readWriteTimeoutMillis != null) { + builder.add("return result.merge(AttributeMap.builder()"); + + if (supportsH2) { + builder.add(".put($T.PROTOCOL, $T.HTTP2)", SdkHttpConfigurationOption.class, Protocol.class); - if (!usePriorKnowledgeForH2) { - builder.add(".put($T.PROTOCOL_NEGOTIATION, $T.ALPN)", - SdkHttpConfigurationOption.class, ProtocolNegotiation.class); + if (!usePriorKnowledgeForH2) { + builder.add(".put($T.PROTOCOL_NEGOTIATION, $T.ALPN)", + SdkHttpConfigurationOption.class, ProtocolNegotiation.class); + } + } + + if (readWriteTimeoutMillis != null) { + // A negative artifact value marks a fully-exempt service: bake Duration.ZERO, which means apply no + // read/write timeout. A positive value is the timeout in milliseconds. + if (readWriteTimeoutMillis < 0) { + builder.add(".put($T.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, $T.ZERO)", + SdkHttpConfigurationOption.class, Duration.class); + } else { + builder.add(".put($T.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, $T.ofMillis($L))", + SdkHttpConfigurationOption.class, Duration.class, readWriteTimeoutMillis + "L"); + } } builder.addStatement(".build())"); @@ -1047,6 +1166,11 @@ private boolean hasClientContextParams() { return clientContextParams != null && !clientContextParams.isEmpty(); } + private boolean hasBuiltIn(BuiltInParameter builtIn) { + return model.getEndpointParameters().values().stream() + .anyMatch(p -> builtIn.equals(p.getBuiltInEnum())); + } + private boolean hasSdkClientContextParams() { return model.getCustomizationConfig() != null && model.getCustomizationConfig().getCustomClientContextParams() != null diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java index 95ed15f3c6f9..c3ccd4e2cf2f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java @@ -25,6 +25,7 @@ import static javax.lang.model.element.Modifier.STATIC; import static software.amazon.awssdk.codegen.internal.Constant.EVENT_PUBLISHER_PARAM_NAME; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.addS3ArnableFieldCode; +import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.resolveMetricPublishersMethod; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.transformServiceId; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.updateSdkClientConfigurationMethod; import static software.amazon.awssdk.codegen.poet.client.SyncClientClass.addRequestModifierCode; @@ -41,7 +42,6 @@ import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.CompletableFuture; @@ -75,7 +75,6 @@ import software.amazon.awssdk.codegen.poet.model.EventStreamSpecHelper; import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; -import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.AsyncResponseTransformerUtils; import software.amazon.awssdk.core.async.SdkPublisher; @@ -119,24 +118,24 @@ public AsyncClientClass(GeneratorTaskParams dependencies) { } @Override - protected TypeSpec.Builder createTypeSpec() { + protected Builder createTypeSpec() { return PoetUtils.createClassBuilder(className); } @Override - protected void addInterfaceClass(TypeSpec.Builder type) { + protected void addInterfaceClass(Builder type) { ClassName interfaceClass = poetExtensions.getClientClass(model.getMetadata().getAsyncInterface()); type.addSuperinterface(interfaceClass) .addJavadoc("Internal implementation of {@link $1T}.\n\n@see $1T#builder()", interfaceClass); } @Override - protected void addAnnotations(TypeSpec.Builder type) { + protected void addAnnotations(Builder type) { type.addAnnotation(SdkInternalApi.class); } @Override - protected void addModifiers(TypeSpec.Builder type) { + protected void addModifiers(Builder type) { type.addModifiers(FINAL); } @@ -152,6 +151,8 @@ protected void addFields(Builder type) { .addField(protocolSpec.protocolFactory(model)) .addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL); + protocolSpec.errorResponseMapperField().ifPresent(type::addField); + // Kinesis doesn't support CBOR for STS yet so need another protocol factory for JSON if (model.getMetadata().isCborProtocol()) { type.addField(AwsJsonProtocolFactory.class, "jsonProtocolFactory", PRIVATE, FINAL); @@ -163,6 +164,8 @@ protected void addFields(Builder type) { model.getEndpointOperation().ifPresent( o -> type.addField(EndpointDiscoveryRefreshCache.class, "endpointDiscoveryCache", PRIVATE)); + + ClientClassUtils.authSchemeCacheField(authSchemeSpecUtils).ifPresent(type::addField); } @Override @@ -172,10 +175,10 @@ protected void addAdditionalMethods(TypeSpec.Builder type) { .addMethods(protocolSpec.additionalMethods()) .addMethod(protocolSpec.initProtocolFactory(model)) .addMethod(resolveMetricPublishersMethod()) + .addMethod(ClientClassUtils.publishMetricsMethod()) + .addMethod(ClientClassUtils.publishMetricsWhenCompleteMethod()) .addMethod(ClientClassUtils.resolveAuthSchemeOptionsMethod(authSchemeSpecUtils, endpointRulesSpecUtils)) - .addMethod(ClientClassUtils.resolveEndpointMethod(authSchemeSpecUtils, endpointRulesSpecUtils)) - .addMethod(ClientClassUtils.authSchemeResolverFactoryMethod()) - .addMethod(ClientClassUtils.endpointResolverFactoryMethod()); + .addMethod(ClientClassUtils.resolveEndpointMethod(authSchemeSpecUtils, endpointRulesSpecUtils)); type.addMethod(ClientClassUtils.updateRetryStrategyClientConfigurationMethod()); type.addMethod(updateSdkClientConfigurationMethod(configurationUtils.serviceClientConfigurationBuilderClassName(), @@ -448,7 +451,7 @@ protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, Operation "() -> $N.exceptionOccurred(t))", paramName); } - builder.addStatement("metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()))") + builder.addStatement("publishMetrics(metricPublishers, apiCallMetricCollector)") .addStatement("return $T.failedFuture(t)", CompletableFutureUtils.class) .endControlFlow(); @@ -548,40 +551,25 @@ protected void addBatchManagerMethod(Builder type) { type.addMethod(batchManager); } - - private MethodSpec resolveMetricPublishersMethod() { - String clientConfigName = "clientConfiguration"; - String requestOverrideConfigName = "requestOverrideConfiguration"; - - MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("resolveMetricPublishers") - .addModifiers(PRIVATE, STATIC) - .returns(ParameterizedTypeName.get(List.class, MetricPublisher.class)) - .addParameter(SdkClientConfiguration.class, clientConfigName) - .addParameter(RequestOverrideConfiguration.class, requestOverrideConfigName); - - String publishersName = "publishers"; - - methodBuilder.addStatement("$T $N = null", ParameterizedTypeName.get(List.class, MetricPublisher.class), publishersName); - - methodBuilder.beginControlFlow("if ($N != null)", requestOverrideConfigName) - .addStatement("$N = $N.metricPublishers()", publishersName, requestOverrideConfigName) - .endControlFlow(); - - methodBuilder.beginControlFlow("if ($1N == null || $1N.isEmpty())", publishersName) - .addStatement("$N = $N.option($T.$N)", - publishersName, - clientConfigName, - SdkClientOption.class, - "METRIC_PUBLISHERS") - .endControlFlow(); - - methodBuilder.beginControlFlow("if ($1N == null)", publishersName) - .addStatement("$N = $T.emptyList()", publishersName, Collections.class) - .endControlFlow(); - - methodBuilder.addStatement("return $N", publishersName); - - return methodBuilder.build(); + + @Override + protected void addPresignedUrlExtensionMethod(Builder type) { + ClassName returnType = poetExtensions.getPresignedUrlExtensionAsyncInterface(); + String internalPresignedUrlPackage = model.getMetadata().getFullInternalPackageName() + ".presignedurl"; + ClassName implClass = ClassName.get(internalPresignedUrlPackage, "DefaultAsyncPresignedUrlExtension"); + + MethodSpec presignedUrlExtension = MethodSpec.methodBuilder("presignedUrlExtension") + .addModifiers(PUBLIC) + .addAnnotation(Override.class) + .returns(returnType) + .addStatement("return new $T(clientHandler," + + " protocolFactory, " + + "clientConfiguration," + + " protocolMetadata)", + implClass) + .build(); + + type.addMethod(presignedUrlExtension); } private void addScheduledExecutorIfNeeded(Builder classBuilder) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java index cbd5f3cb3e9a..fe6d40015703 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java @@ -99,6 +99,9 @@ public TypeSpec poetSpec() { if (model.getCustomizationConfig().getBatchManagerSupported()) { addBatchManagerMethod(result); } + if (model.getCustomizationConfig().getPresignedUrlExtensionSupported()) { + addPresignedUrlExtensionMethod(result); + } result.addMethod(serviceClientConfigMethod()); addAdditionalMethods(result); addCloseMethod(result); @@ -174,6 +177,16 @@ protected void addBatchManagerMethod(TypeSpec.Builder type) { + "configuration set on this client.", returnType); type.addMethod(batchManagerOperationBody(builder).build()); } + + protected void addPresignedUrlExtensionMethod(TypeSpec.Builder type) { + ClassName returnType = poetExtensions.getPresignedUrlExtensionAsyncInterface(); + MethodSpec.Builder builder = MethodSpec.methodBuilder("presignedUrlExtension") + .addModifiers(PUBLIC) + .returns(returnType) + .addJavadoc("Creates an instance of {@link $T} object with the " + + "configuration set on this client.", returnType); + type.addMethod(presignedUrlExtensionOperationBody(builder).build()); + } @Override public ClassName className() { @@ -550,5 +563,10 @@ protected MethodSpec.Builder batchManagerOperationBody(MethodSpec.Builder builde return builder.addModifiers(DEFAULT, PUBLIC) .addStatement("throw new $T()", UnsupportedOperationException.class); } + + protected MethodSpec.Builder presignedUrlExtensionOperationBody(MethodSpec.Builder builder) { + return builder.addModifiers(DEFAULT, PUBLIC) + .addStatement("throw new $T()", UnsupportedOperationException.class); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java index 5b0f5ab6ae98..1a02dc119a51 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/ClientClassUtils.java @@ -16,21 +16,26 @@ package software.amazon.awssdk.codegen.poet.client; import static javax.lang.model.element.Modifier.PRIVATE; +import static javax.lang.model.element.Modifier.STATIC; import static software.amazon.awssdk.codegen.poet.PoetUtils.classNameFromFqcn; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeVariableName; import com.squareup.javapoet.WildcardTypeName; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -52,6 +57,7 @@ import software.amazon.awssdk.codegen.poet.PoetUtils; import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; +import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkClient; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.SdkRequest; @@ -59,15 +65,16 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; 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.retry.RetryMode; import software.amazon.awssdk.core.signer.Signer; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; @@ -368,11 +375,13 @@ static MethodSpec resolveAuthSchemeOptionsMethod(AuthSchemeSpecUtils authSchemeS .addModifiers(PRIVATE) .returns(ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(AuthSchemeOption.class))) .addParameter(SdkRequest.class, "request") - .addParameter(String.class, "operationName") - .addParameter(SdkClientConfiguration.class, "clientConfiguration"); + .addParameter(ExecutionAttributes.class, "executionAttributes"); ClassName providerInterface = authSchemeSpecUtils.providerInterfaceName(); + builder.addStatement("String operationName = executionAttributes.getAttribute($T.OPERATION_NAME)", + SdkExecutionAttribute.class); + // Check for request-level authSchemeProvider override builder.addStatement("$T requestAuthSchemeProvider = request.overrideConfiguration()" + ".flatMap(c -> c.authSchemeProvider())" @@ -380,23 +389,36 @@ static MethodSpec resolveAuthSchemeOptionsMethod(AuthSchemeSpecUtils authSchemeS + ".orElse(null)", providerInterface, Validate.class, providerInterface, "Expected an instance of " + authSchemeSpecUtils.providerInterfaceName().simpleName()); + builder.addStatement("$T authSchemeProvider = requestAuthSchemeProvider != null " + "? requestAuthSchemeProvider " + ": $T.isInstanceOf($T.class, " - + "clientConfiguration.option($T.AUTH_SCHEME_PROVIDER), $S)", - providerInterface, Validate.class, providerInterface, SdkClientOption.class, + + "executionAttributes.getAttribute($T.AUTH_SCHEME_RESOLVER), $S)", + providerInterface, Validate.class, providerInterface, + SdkInternalExecutionAttribute.class, "Expected an instance of " + authSchemeSpecUtils.providerInterfaceName().simpleName()); + boolean canCache = !authSchemeSpecUtils.useEndpointBasedAuthProvider(); + if (canCache) { + addAuthSchemeCacheLookup(builder, authSchemeSpecUtils); + } + if (authSchemeSpecUtils.useEndpointBasedAuthProvider()) { addEndpointBasedAuthSchemeResolution(builder, authSchemeSpecUtils, endpointRulesSpecUtils); } else { addSimpleAuthSchemeResolution(builder, authSchemeSpecUtils); } - if (endpointRulesSpecUtils.isS3()) { + if (canCache) { + builder.beginControlFlow("if (useCache)"); + builder.addStatement("options = $T.unmodifiableList(options)", Collections.class); + builder.addStatement("authSchemeCache.put(cacheKey, options)"); + builder.endControlFlow(); + builder.addStatement("return options"); + } else if (endpointRulesSpecUtils.isS3()) { ClassName sdkIdentityProperty = ClassName.get("software.amazon.awssdk.core.identity", "SdkIdentityProperty"); - builder.addStatement("$T sdkClient = clientConfiguration.option($T.SDK_CLIENT)", - SdkClient.class, SdkClientOption.class); + builder.addStatement("$T sdkClient = executionAttributes.getAttribute($T.SDK_CLIENT)", + SdkClient.class, SdkInternalExecutionAttribute.class); builder.addStatement("return options.stream().map(o -> o.toBuilder()" + ".putIdentityProperty($T.SDK_CLIENT, sdkClient).build())" + ".collect($T.toList())", @@ -408,22 +430,76 @@ static MethodSpec resolveAuthSchemeOptionsMethod(AuthSchemeSpecUtils authSchemeS return builder.build(); } + /** + * Returns a field spec for the auth scheme options cache, used when simple (non-endpoint-based) auth is in effect. + */ + static Optional authSchemeCacheField(AuthSchemeSpecUtils authSchemeSpecUtils) { + if (authSchemeSpecUtils.useEndpointBasedAuthProvider()) { + return Optional.empty(); + } + ClassName concurrentHashMap = ClassName.get("java.util.concurrent", "ConcurrentHashMap"); + ParameterizedTypeName mapType = ParameterizedTypeName.get( + concurrentHashMap, + ClassName.get(String.class), + ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(AuthSchemeOption.class))); + return Optional.of(FieldSpec.builder(mapType, "authSchemeCache", PRIVATE, Modifier.FINAL) + .initializer("new $T<>()", concurrentHashMap) + .build()); + } + + private static void addAuthSchemeCacheLookup(MethodSpec.Builder builder, AuthSchemeSpecUtils authSchemeSpecUtils) { + ClassName defaultProviderClass = authSchemeSpecUtils.defaultAuthSchemeProviderName(); + builder.addStatement("boolean useCache = requestAuthSchemeProvider == null " + + "&& authSchemeProvider instanceof $T", defaultProviderClass); + + ClassName awsExecAttr = ClassName.get("software.amazon.awssdk.awscore", "AwsExecutionAttribute"); + List parts = new ArrayList<>(); + if (authSchemeSpecUtils.hasPerOperationAuthOverrides()) { + parts.add(CodeBlock.of("operationName")); + } + if (authSchemeSpecUtils.usesSigV4()) { + parts.add(CodeBlock.of("executionAttributes.getAttribute($T.AWS_REGION)", awsExecAttr)); + } + if (authSchemeSpecUtils.usesSigV4a()) { + parts.add(CodeBlock.of("executionAttributes.getAttribute($T.AWS_SIGV4A_SIGNING_REGION_SET)", awsExecAttr)); + } + + if (parts.isEmpty()) { + builder.addStatement("$T cacheKey = $S", String.class, "default"); + } else if (parts.size() == 1) { + builder.addStatement("$T cacheKey = $T.valueOf($L)", String.class, String.class, parts.get(0)); + } else { + builder.addStatement("$T cacheKey = $L", String.class, CodeBlock.join(parts, " + \":\" + ")); + } + + builder.beginControlFlow("if (useCache)"); + builder.addStatement("$T<$T> cached = authSchemeCache.get(cacheKey)", + List.class, AuthSchemeOption.class); + builder.beginControlFlow("if (cached != null)"); + builder.addStatement("return cached"); + builder.endControlFlow(); + builder.endControlFlow(); + } + + // Any AwsExecutionAttribute added here must also be added to addAuthSchemeCacheLookup(). Enforced by AuthSchemeCacheKeyTest. private static void addSimpleAuthSchemeResolution(MethodSpec.Builder builder, AuthSchemeSpecUtils authSchemeSpecUtils) { ClassName paramsInterface = authSchemeSpecUtils.parametersInterfaceName(); - ClassName awsClientOption = ClassName.get("software.amazon.awssdk.awscore.client.config", "AwsClientOption"); + ClassName awsExecutionAttribute = ClassName.get("software.amazon.awssdk.awscore", "AwsExecutionAttribute"); builder.addStatement("$T.Builder paramsBuilder = $T.builder().operation(operationName)", paramsInterface, paramsInterface); if (authSchemeSpecUtils.usesSigV4()) { - builder.addStatement("paramsBuilder.region(clientConfiguration.option($T.AWS_REGION))", awsClientOption); + builder.addStatement("paramsBuilder.region(executionAttributes.getAttribute($T.AWS_REGION))", + awsExecutionAttribute); } if (authSchemeSpecUtils.hasSigV4aSupport()) { ClassName regionSet = ClassName.get("software.amazon.awssdk.http.auth.aws.signer", "RegionSet"); - builder.addStatement("$T sigv4aRegionSet = clientConfiguration.option($T.AWS_SIGV4A_SIGNING_REGION_SET)", - ClassName.get(Set.class), awsClientOption); + builder.addStatement("$T sigv4aRegionSet = executionAttributes" + + ".getAttribute($T.AWS_SIGV4A_SIGNING_REGION_SET)", + ClassName.get(Set.class), awsExecutionAttribute); builder.beginControlFlow("if (!$T.isNullOrEmpty(sigv4aRegionSet))", CollectionUtils.class); builder.addStatement("paramsBuilder.regionSet($T.create(sigv4aRegionSet))", regionSet); builder.endControlFlow(); @@ -437,32 +513,12 @@ private static void addEndpointBasedAuthSchemeResolution(MethodSpec.Builder buil AuthSchemeSpecUtils authSchemeSpecUtils, EndpointRulesSpecUtils endpointRulesSpecUtils) { ClassName paramsInterface = authSchemeSpecUtils.parametersInterfaceName(); - ClassName awsClientOption = ClassName.get("software.amazon.awssdk.awscore.client.config", "AwsClientOption"); + ClassName awsExecutionAttribute = ClassName.get("software.amazon.awssdk.awscore", "AwsExecutionAttribute"); ClassName endpointParamsClass = endpointRulesSpecUtils.parametersClassName(); ClassName endpointResolverUtils = endpointRulesSpecUtils.endpointResolverUtilsName(); - ClassName executionAttributesClass = ClassName.get("software.amazon.awssdk.core.interceptor", "ExecutionAttributes"); - ClassName awsExecutionAttribute = ClassName.get("software.amazon.awssdk.awscore", "AwsExecutionAttribute"); - ClassName sdkExecutionAttribute = ClassName.get("software.amazon.awssdk.core.interceptor", "SdkExecutionAttribute"); ClassName sdkInternalExecutionAttribute = ClassName.get("software.amazon.awssdk.core.interceptor", "SdkInternalExecutionAttribute"); - builder.addStatement("$T executionAttributes = new $T()", executionAttributesClass, executionAttributesClass); - builder.addStatement("executionAttributes.putAttribute($T.AWS_REGION, clientConfiguration.option($T.AWS_REGION))", - awsExecutionAttribute, awsClientOption); - builder.addStatement("executionAttributes.putAttribute($T.DUALSTACK_ENDPOINT_ENABLED, " - + "clientConfiguration.option($T.DUALSTACK_ENDPOINT_ENABLED))", - awsExecutionAttribute, awsClientOption); - builder.addStatement("executionAttributes.putAttribute($T.FIPS_ENDPOINT_ENABLED, " - + "clientConfiguration.option($T.FIPS_ENDPOINT_ENABLED))", - awsExecutionAttribute, awsClientOption); - builder.addStatement("executionAttributes.putAttribute($T.OPERATION_NAME, operationName)", sdkExecutionAttribute); - builder.addStatement("executionAttributes.putAttribute($T.CLIENT_ENDPOINT_PROVIDER, " - + "clientConfiguration.option($T.CLIENT_ENDPOINT_PROVIDER))", - sdkInternalExecutionAttribute, SdkClientOption.class); - builder.addStatement("executionAttributes.putAttribute($T.CLIENT_CONTEXT_PARAMS, " - + "clientConfiguration.option($T.CLIENT_CONTEXT_PARAMS))", - sdkInternalExecutionAttribute, SdkClientOption.class); - builder.addStatement("$T endpointParams = $T.ruleParams(request, executionAttributes)", endpointParamsClass, endpointResolverUtils); @@ -481,13 +537,15 @@ private static void addEndpointBasedAuthSchemeResolution(MethodSpec.Builder buil builder.addStatement("paramsBuilder.operation(operationName)"); if (authSchemeSpecUtils.usesSigV4() && !regionIncluded) { - builder.addStatement("paramsBuilder.region(clientConfiguration.option($T.AWS_REGION))", awsClientOption); + builder.addStatement("paramsBuilder.region(executionAttributes.getAttribute($T.AWS_REGION))", + awsExecutionAttribute); } if (authSchemeSpecUtils.hasSigV4aSupport()) { ClassName regionSet = ClassName.get("software.amazon.awssdk.http.auth.aws.signer", "RegionSet"); - builder.addStatement("$T sigv4aRegionSet = clientConfiguration.option($T.AWS_SIGV4A_SIGNING_REGION_SET)", - ClassName.get(Set.class), awsClientOption); + builder.addStatement("$T sigv4aRegionSet = executionAttributes" + + ".getAttribute($T.AWS_SIGV4A_SIGNING_REGION_SET)", + ClassName.get(Set.class), awsExecutionAttribute); builder.beginControlFlow("if (!$T.isNullOrEmpty(sigv4aRegionSet))", CollectionUtils.class); builder.addStatement("paramsBuilder.regionSet($T.create(sigv4aRegionSet))", regionSet); builder.endControlFlow(); @@ -497,8 +555,10 @@ private static void addEndpointBasedAuthSchemeResolution(MethodSpec.Builder buil ClassName endpointProviderInterface = endpointRulesSpecUtils.providerInterfaceName(); builder.beginControlFlow("if (paramsBuilder instanceof $T)", paramsBuilderClass); - builder.addStatement("$T endpointProvider = clientConfiguration.option($T.ENDPOINT_PROVIDER)", - ClassName.get("software.amazon.awssdk.endpoints", "EndpointProvider"), SdkClientOption.class); + builder.addStatement("$T endpointProvider = ($T) executionAttributes.getAttribute($T.ENDPOINT_PROVIDER)", + ClassName.get("software.amazon.awssdk.endpoints", "EndpointProvider"), + ClassName.get("software.amazon.awssdk.endpoints", "EndpointProvider"), + sdkInternalExecutionAttribute); builder.beginControlFlow("if (endpointProvider instanceof $T)", endpointProviderInterface); builder.addStatement("(($T) paramsBuilder).endpointProvider(($T) endpointProvider)", paramsBuilderClass, endpointProviderInterface); @@ -509,39 +569,6 @@ private static void addEndpointBasedAuthSchemeResolution(MethodSpec.Builder buil List.class, AuthSchemeOption.class); } - /** - * Generates a factory method that creates an {@code AuthSchemeOptionsResolver} for a given operation name. - * This avoids creating a new lambda per operation in the generated client class, which reduces constant pool - * pressure for services with a large number of operations (e.g., EC2). - */ - static MethodSpec authSchemeResolverFactoryMethod() { - ClassName authSchemeOptionsResolver = ClassName.get(AuthSchemeOptionsResolver.class); - - return MethodSpec.methodBuilder("authSchemeResolver") - .addModifiers(PRIVATE) - .returns(authSchemeOptionsResolver) - .addParameter(String.class, "operationName") - .addParameter(SdkClientConfiguration.class, "clientConfiguration") - .addStatement("return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration)") - .build(); - } - - /** - * Generates a factory method that creates an {@code EndpointResolver} for a given operation name. - * This avoids creating a new lambda per operation in the generated client class, which reduces constant pool - * pressure for services with a large number of operations (e.g., EC2). - */ - static MethodSpec endpointResolverFactoryMethod() { - ClassName endpointResolver = ClassName.get(EndpointResolver.class); - - return MethodSpec.methodBuilder("endpointResolver") - .addModifiers(PRIVATE) - .returns(endpointResolver) - .addParameter(String.class, "operationName") - .addStatement("return (r, a) -> resolveEndpoint(r, a, operationName)") - .build(); - } - static MethodSpec resolveEndpointMethod(AuthSchemeSpecUtils authSchemeSpecUtils, EndpointRulesSpecUtils endpointRulesSpecUtils) { ClassName utilsClass = endpointRulesSpecUtils.endpointResolverUtilsName(); @@ -555,8 +582,9 @@ static MethodSpec resolveEndpointMethod(AuthSchemeSpecUtils authSchemeSpecUtils, .addModifiers(PRIVATE) .returns(Endpoint.class) .addParameter(SdkRequest.class, "request") - .addParameter(ExecutionAttributes.class, "executionAttributes") - .addParameter(String.class, "operationName"); + .addParameter(ExecutionAttributes.class, "executionAttributes"); + + b.addStatement("String operationName = executionAttributes.getAttribute($T.OPERATION_NAME)", SdkExecutionAttribute.class); b.addStatement("$1T provider = ($1T) executionAttributes.getAttribute($2T.ENDPOINT_PROVIDER)", providerInterface, SdkInternalExecutionAttribute.class); @@ -623,4 +651,80 @@ static MethodSpec resolveEndpointMethod(AuthSchemeSpecUtils authSchemeSpecUtils, return b.build(); } + + static MethodSpec resolveMetricPublishersMethod() { + String clientConfigName = "clientConfiguration"; + String requestOverrideConfigName = "requestOverrideConfiguration"; + + MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("resolveMetricPublishers") + .addModifiers(PRIVATE, STATIC) + .returns(ParameterizedTypeName.get(List.class, MetricPublisher.class)) + .addParameter(SdkClientConfiguration.class, clientConfigName) + .addParameter(RequestOverrideConfiguration.class, requestOverrideConfigName); + + String publishersName = "publishers"; + + methodBuilder.addStatement("$T $N = null", ParameterizedTypeName.get(List.class, MetricPublisher.class), publishersName); + + methodBuilder.beginControlFlow("if ($N != null)", requestOverrideConfigName) + .addStatement("$N = $N.metricPublishers()", publishersName, requestOverrideConfigName) + .endControlFlow(); + + methodBuilder.beginControlFlow("if ($1N == null || $1N.isEmpty())", publishersName) + .addStatement("$N = $N.option($T.$N)", + publishersName, + clientConfigName, + SdkClientOption.class, + "METRIC_PUBLISHERS") + .endControlFlow(); + + methodBuilder.beginControlFlow("if ($1N == null)", publishersName) + .addStatement("$N = $T.emptyList()", publishersName, Collections.class) + .endControlFlow(); + + methodBuilder.addStatement("return $N", publishersName); + + return methodBuilder.build(); + } + + /** + * Generates the shared {@code publishMetrics} helper that every operation body calls to publish its API call metrics. + * Inline, the equivalent {@code metricPublishers.forEach(...)} costs one synthetic lambda, and its constant pool + * machinery, per generated operation. + */ + static MethodSpec publishMetricsMethod() { + return MethodSpec.methodBuilder("publishMetrics") + .addJavadoc("Publishes the collected API call metrics to each configured publisher.\n") + .addModifiers(PRIVATE, STATIC) + .addParameter(ParameterizedTypeName.get(List.class, MetricPublisher.class), "metricPublishers") + .addParameter(MetricCollector.class, "apiCallMetricCollector") + .beginControlFlow("for ($T metricPublisher : metricPublishers)", MetricPublisher.class) + .addStatement("metricPublisher.publish(apiCallMetricCollector.collect())") + .endControlFlow() + .build(); + } + + /** + * Generates the shared {@code publishMetricsWhenComplete} helper used by non-streaming async operation bodies. Holds + * the single {@code whenComplete} callback for the whole client, which inline would cost one synthetic lambda per + * generated operation. + */ + static MethodSpec publishMetricsWhenCompleteMethod() { + TypeVariableName typeVariable = TypeVariableName.get("T"); + ParameterizedTypeName futureType = ParameterizedTypeName.get(ClassName.get(CompletableFuture.class), typeVariable); + + return MethodSpec.methodBuilder("publishMetricsWhenComplete") + .addJavadoc("Publishes the collected API call metrics once {@code future} completes, normally or " + + "exceptionally.\n") + .addModifiers(PRIVATE, STATIC) + .addTypeVariable(typeVariable) + .returns(futureType) + .addParameter(futureType, "future") + .addParameter(ParameterizedTypeName.get(List.class, MetricPublisher.class), "metricPublishers") + .addParameter(MetricCollector.class, "apiCallMetricCollector") + .addStatement("return future.whenComplete((r, e) -> publishMetrics(metricPublishers, " + + "apiCallMetricCollector))") + .build(); + } + } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClass.java index 5af2c45ad0bc..3fd5fcec9f51 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClass.java @@ -222,4 +222,9 @@ protected MethodSpec.Builder waiterOperationBody(MethodSpec.Builder builder) { protected MethodSpec.Builder batchManagerOperationBody(MethodSpec.Builder builder) { return builder.addAnnotation(Override.class).addStatement("return delegate.batchManager()"); } + + @Override + protected MethodSpec.Builder presignedUrlExtensionOperationBody(MethodSpec.Builder builder) { + return builder.addAnnotation(Override.class).addStatement("return delegate.presignedUrlExtension()"); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java index 99e37ea13aea..7d44fd3b1013 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/SyncClientClass.java @@ -22,6 +22,7 @@ import static javax.lang.model.element.Modifier.STATIC; import static software.amazon.awssdk.codegen.poet.PoetUtils.classNameFromFqcn; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.addS3ArnableFieldCode; +import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.resolveMetricPublishersMethod; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.transformServiceId; import static software.amazon.awssdk.codegen.poet.client.ClientClassUtils.updateSdkClientConfigurationMethod; @@ -34,7 +35,6 @@ import com.squareup.javapoet.WildcardTypeName; import java.net.URI; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -62,7 +62,6 @@ import software.amazon.awssdk.codegen.poet.client.specs.XmlProtocolSpec; import software.amazon.awssdk.codegen.poet.model.ServiceClientConfigurationUtils; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; -import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.SyncClientHandler; @@ -129,6 +128,8 @@ protected void addFields(TypeSpec.Builder type) { .addField(SyncClientHandler.class, "clientHandler", PRIVATE, FINAL) .addField(protocolSpec.protocolFactory(model)) .addField(SdkClientConfiguration.class, "clientConfiguration", PRIVATE, FINAL); + protocolSpec.errorResponseMapperField().ifPresent(type::addField); + ClientClassUtils.authSchemeCacheField(authSchemeSpecUtils).ifPresent(type::addField); } @Override @@ -140,10 +141,9 @@ protected void addAdditionalMethods(TypeSpec.Builder type) { .addMethod(nameMethod()) .addMethods(protocolSpec.additionalMethods()) .addMethod(resolveMetricPublishersMethod()) + .addMethod(ClientClassUtils.publishMetricsMethod()) .addMethod(ClientClassUtils.resolveAuthSchemeOptionsMethod(authSchemeSpecUtils, endpointRulesSpecUtils)) - .addMethod(ClientClassUtils.resolveEndpointMethod(authSchemeSpecUtils, endpointRulesSpecUtils)) - .addMethod(ClientClassUtils.authSchemeResolverFactoryMethod()) - .addMethod(ClientClassUtils.endpointResolverFactoryMethod()); + .addMethod(ClientClassUtils.resolveEndpointMethod(authSchemeSpecUtils, endpointRulesSpecUtils)); protocolSpec.createErrorResponseHandler().ifPresent(type::addMethod); type.addMethod(ClientClassUtils.updateRetryStrategyClientConfigurationMethod()); @@ -342,7 +342,7 @@ private MethodSpec traditionalMethod(OperationModel opModel) { method.addCode(protocolSpec.executionHandler(opModel)) .endControlFlow() .beginControlFlow("finally") - .addStatement("metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()))") + .addStatement("publishMetrics(metricPublishers, apiCallMetricCollector)") .endControlFlow(); return method.build(); @@ -414,41 +414,6 @@ static ProtocolSpec getProtocolSpecs(PoetExtension poetExtensions, IntermediateM } } - private MethodSpec resolveMetricPublishersMethod() { - String clientConfigName = "clientConfiguration"; - String requestOverrideConfigName = "requestOverrideConfiguration"; - - MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("resolveMetricPublishers") - .addModifiers(PRIVATE, STATIC) - .returns(ParameterizedTypeName.get(List.class, MetricPublisher.class)) - .addParameter(SdkClientConfiguration.class, clientConfigName) - .addParameter(RequestOverrideConfiguration.class, requestOverrideConfigName); - - String publishersName = "publishers"; - - methodBuilder.addStatement("$T $N = null", ParameterizedTypeName.get(List.class, MetricPublisher.class), publishersName); - - methodBuilder.beginControlFlow("if ($N != null)", requestOverrideConfigName) - .addStatement("$N = $N.metricPublishers()", publishersName, requestOverrideConfigName) - .endControlFlow(); - - methodBuilder.beginControlFlow("if ($1N == null || $1N.isEmpty())", publishersName) - .addStatement("$N = $N.option($T.$N)", - publishersName, - clientConfigName, - SdkClientOption.class, - "METRIC_PUBLISHERS") - .endControlFlow(); - - methodBuilder.beginControlFlow("if ($1N == null)", publishersName) - .addStatement("$N = $T.emptyList()", publishersName, Collections.class) - .endControlFlow(); - - methodBuilder.addStatement("return $N", publishersName); - - return methodBuilder.build(); - } - @Override protected MethodSpec.Builder waiterOperationBody(MethodSpec.Builder builder) { return builder.addAnnotation(Override.class) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java index d5937678ac21..879a71d1ad66 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java @@ -168,39 +168,48 @@ public Optional errorResponseHandler(OperationModel opModel) { String protocolFactory = protocolFactoryLiteral(model, opModel); CodeBlock.Builder builder = CodeBlock.builder(); + builder.add("\n$T<$T> errorResponseHandler = createErrorResponseHandler($L, operationMetadata, " + + "exceptionMetadataMapper);", + HttpResponseHandler.class, AwsServiceException.class, protocolFactory); + + return Optional.of(builder.build()); + } + + @Override + public Optional errorResponseMapperField() { ParameterizedTypeName metadataMapperType = ParameterizedTypeName.get( ClassName.get(Function.class), ClassName.get(String.class), ParameterizedTypeName.get(Optional.class, ExceptionMetadata.class)); - builder.add("\n$T exceptionMetadataMapper = errorCode -> {\n", metadataMapperType); - builder.add("if (errorCode == null) {\n"); - builder.add("return $T.empty();\n", Optional.class); - builder.add("}\n"); - builder.add("switch (errorCode) {\n"); + CodeBlock.Builder initializer = CodeBlock.builder(); + initializer.add("errorCode -> {\n"); + initializer.add("if (errorCode == null) {\n"); + initializer.add("return $T.empty();\n", Optional.class); + initializer.add("}\n"); + initializer.add("switch (errorCode) {\n"); model.getShapes().values().stream() .filter(shape -> shape.getShapeType() == ShapeType.Exception) .forEach(exceptionShape -> { - String exceptionName = exceptionShape.getShapeName(); String errorCode = exceptionShape.getErrorCode(); - builder.add("case $S:\n", errorCode); - builder.add("return $T.of($T.builder()\n", Optional.class, ExceptionMetadata.class) - .add(".errorCode($S)\n", errorCode); - builder.add(populateHttpStatusCode(exceptionShape, model)); - builder.add(".exceptionBuilderSupplier($T::builder)\n", - poetExtensions.getModelClassFromShape(exceptionShape)) - .add(".build());\n"); + initializer.add("case $S:\n", errorCode); + initializer.add("return $T.of($T.builder()\n", Optional.class, ExceptionMetadata.class) + .add(".errorCode($S)\n", errorCode); + initializer.add(populateHttpStatusCode(exceptionShape, model)); + initializer.add(".exceptionBuilderSupplier($T::builder)\n", + poetExtensions.getModelClassFromShape(exceptionShape)) + .add(".build());\n"); }); - builder.add("default: return $T.empty();\n", Optional.class); - builder.add("}\n"); - builder.add("};\n"); - - builder.add("$T<$T> errorResponseHandler = createErrorResponseHandler($L, operationMetadata, exceptionMetadataMapper);", - HttpResponseHandler.class, AwsServiceException.class, protocolFactory); + initializer.add("default: return $T.empty();\n", Optional.class); + initializer.add("}\n"); + initializer.add("}"); - return Optional.of(builder.build()); + return Optional.of(FieldSpec.builder(metadataMapperType, "exceptionMetadataMapper", + Modifier.PRIVATE, Modifier.FINAL) + .initializer(initializer.build()) + .build()); } @Override @@ -224,10 +233,8 @@ public CodeBlock executionHandler(OperationModel opModel) { .add(".withRequestConfiguration(clientConfiguration)") .add(".withInput($L)\n", opModel.getInput().getVariableName()) .add(".withMetricCollector(apiCallMetricCollector)\n") - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -302,10 +309,8 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper .add(".withErrorResponseHandler(errorResponseHandler)\n") .add(".withRequestConfiguration(clientConfiguration)") .add(".withMetricCollector(apiCallMetricCollector)\n") - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(hostPrefixExpression(opModel)) .add(discoveredEndpoint(opModel)) .add(credentialType(opModel, model)) @@ -329,14 +334,11 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper } String customerResponseHandler = opModel.hasEventStreamOutput() ? "asyncResponseHandler" : "finalAsyncResponseTransformer"; - String whenComplete = whenCompleteBody(opModel, customerResponseHandler); - if (!whenComplete.isEmpty()) { - String whenCompletedFutureName = "whenCompleted"; - builder.addStatement("$T<$T> $N = $N$L", CompletableFuture.class, executeFutureValueType, - whenCompletedFutureName, "executeFuture", whenComplete); - builder.addStatement("executeFuture = $T.forwardExceptionTo($N, executeFuture)", - CompletableFutureUtils.class, whenCompletedFutureName); - } + String whenCompletedFutureName = "whenCompleted"; + builder.addStatement("$T<$T> $N = $L", CompletableFuture.class, executeFutureValueType, + whenCompletedFutureName, whenCompleteBody(opModel, customerResponseHandler)); + builder.addStatement("executeFuture = $T.forwardExceptionTo($N, executeFuture)", + CompletableFutureUtils.class, whenCompletedFutureName); if (opModel.hasEventStreamOutput()) { builder.addStatement("return $T.forwardExceptionTo(future, executeFuture)", CompletableFutureUtils.class); } else { @@ -405,16 +407,15 @@ private CodeBlock restAsyncResponseTransformer(TypeName pojoResponseType, ClassN * * @param operationModel Op model. * @param responseHandlerName Variable name of response handler customer passed in. - * @return whenComplete to append to future. + * @return Expression producing the future that completes once metrics have been published. */ private String whenCompleteBody(OperationModel operationModel, String responseHandlerName) { if (operationModel.hasEventStreamOutput()) { - return eventStreamOutputWhenComplete(responseHandlerName); + return "executeFuture" + eventStreamOutputWhenComplete(responseHandlerName); } else if (operationModel.hasStreamingOutput()) { - return streamingOutputWhenComplete(responseHandlerName); + return "executeFuture" + streamingOutputWhenComplete(responseHandlerName); } else { - // Non streaming can just return the future as is - return publishMetricsWhenComplete(); + return publishMetricsWhenComplete("executeFuture"); } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java index a6bfd997fba5..ac85a59ca859 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java @@ -70,6 +70,15 @@ default Optional createEventstreamErrorResponseHandler() { return Optional.empty(); } + /** + * The per-client field holding the non-streaming {@code exceptionMetadataMapper}, when the protocol emits one. The + * mapper switches over the whole model's exceptions and is identical for every operation, so it is generated once as + * a client field instead of once per operation body. + */ + default Optional errorResponseMapperField() { + return Optional.empty(); + } + default List additionalMethods() { return new ArrayList<>(); } @@ -210,13 +219,19 @@ default TypeName getPojoResponseType(OperationModel opModel, PoetExtension poetE return poetExtensions.getModelClass(opModel.getReturnType().getReturnType()); } - default String publishMetricsWhenComplete() { - return String.format(".whenComplete((r, e) -> {%n" - + "%s%n" - + "})", publishMetrics()); + /** + * Invocation of the client's shared {@code publishMetrics} helper. Emitted instead of an inline + * {@code metricPublishers.forEach(...)} so the operation body carries no synthetic lambda. + */ + default String publishMetrics() { + return "publishMetrics(metricPublishers, apiCallMetricCollector);"; } - default String publishMetrics() { - return "metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect()));"; + /** + * Invocation of the client's shared {@code publishMetricsWhenComplete} helper, which holds the {@code whenComplete} + * callback that non-streaming async operations would otherwise each declare as a lambda. + */ + default String publishMetricsWhenComplete(String futureName) { + return String.format("publishMetricsWhenComplete(%s, metricPublishers, apiCallMetricCollector)", futureName); } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java index 302b99c9cec4..9f6bb3e21383 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java @@ -116,10 +116,8 @@ public CodeBlock executionHandler(OperationModel opModel) { .add(".withRequestConfiguration(clientConfiguration)") .add(".withInput($L)", opModel.getInput().getVariableName()) .add(".withMetricCollector(apiCallMetricCollector)") - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -159,10 +157,8 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper .add(credentialType(opModel, intermediateModel)) .add(".withRequestConfiguration(clientConfiguration)") .add(".withMetricCollector(apiCallMetricCollector)\n") - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -186,7 +182,7 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper builder.addStatement("$N = executeFuture$L", whenCompleteFutureName, streamingOutputWhenComplete("finalAsyncResponseTransformer")); } else { - builder.addStatement("$N = executeFuture$L", whenCompleteFutureName, publishMetricsWhenComplete()); + builder.addStatement("$N = $L", whenCompleteFutureName, publishMetricsWhenComplete("executeFuture")); } builder.addStatement("return $T.forwardExceptionTo($N, executeFuture)", CompletableFutureUtils.class, whenCompleteFutureName); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java index fb421b0ccb77..676bcc668b40 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java @@ -135,10 +135,8 @@ public CodeBlock executionHandler(OperationModel opModel) { .add(credentialType(opModel, model)) .add(".withRequestConfiguration(clientConfiguration)") .add(".withInput($L)", opModel.getInput().getVariableName()) - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -217,10 +215,8 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper builder.add(hostPrefixExpression(opModel)) .add(credentialType(opModel, model)) .add(".withMetricCollector(apiCallMetricCollector)\n") - .add(".withAuthSchemeOptionsResolver(authSchemeResolver($S, clientConfiguration))\n", - opModel.getOperationName()) - .add(".withEndpointResolver(endpointResolver($S))\n", - opModel.getOperationName()) + .add(".withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions)\n") + .add(".withEndpointResolver(this::resolveEndpoint)\n") .add(asyncRequestBody(opModel)) .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -244,7 +240,7 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper whenCompleteBlock(opModel, "asyncResponseHandler", eventStreamTransformFutureName)); } else { - builder.addStatement("$N = executeFuture$L", whenCompleteFutureName, publishMetricsWhenComplete()); + builder.addStatement("$N = $L", whenCompleteFutureName, publishMetricsWhenComplete("executeFuture")); } builder.addStatement("$T.forwardExceptionTo($N, executeFuture)", CompletableFutureUtils.class, diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerBuilderInterfaceSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerBuilderInterfaceSpec.java index 0d8685ef4227..f05a0638a327 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerBuilderInterfaceSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerBuilderInterfaceSpec.java @@ -67,8 +67,10 @@ protected TypeSpec.Builder createTypeSpecBuilder() { return PoetUtils.createInterfaceBuilder(className()).addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addJavadoc("Builder for {@link $1T}. This can be used to create the {@link $1T} in a more " - + "functional way, you may also directly implement the {@link $1T} interface if " - + "preferred.", + + "functional way. Directly implementing the {@link $1T} interface is possible but " + + "requires subscribing to the event publisher, requesting data via the Subscription, " + + "resetting state on retry, and freeing resources on error; the builder handles all " + + "of this automatically.", responseHandlerType) .addSuperinterface(superBuilderInterface); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerSpec.java index 8fa6aaa29a96..9560d97e6a30 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/eventstream/EventStreamResponseHandlerSpec.java @@ -15,11 +15,13 @@ package software.amazon.awssdk.codegen.poet.eventstream; +import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeSpec; import javax.lang.model.element.Modifier; +import software.amazon.awssdk.annotations.SdkAdvancedApi; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.awscore.eventstream.EventStreamResponseHandler; import software.amazon.awssdk.codegen.emitters.GeneratorTaskParams; @@ -60,6 +62,7 @@ public TypeSpec poetSpec() { return PoetUtils.createInterfaceBuilder(className()) .addModifiers(Modifier.PUBLIC) .addAnnotation(SdkPublicApi.class) + .addAnnotation(advancedApiAnnotation()) .addSuperinterface(superResponseHandlerInterface) .addJavadoc("Response handler for the $L API.", apiName) .addMethod(builderMethodSpec()) @@ -68,6 +71,22 @@ public TypeSpec poetSpec() { .build(); } + private AnnotationSpec advancedApiAnnotation() { + return AnnotationSpec.builder(SdkAdvancedApi.class) + .addMember("cautionWhen", "$T.$L", SdkAdvancedApi.Usage.class, "IMPLEMENTED") + .addMember("guidance", "$S", + "onEventStream() receives a reactive-streams Publisher; the implementation must " + + "subscribe to it and call Subscription.request(n) to pull events -- a handler " + + "that never subscribes or never requests stalls the stream and hangs the " + + "operation. On retry the SDK calls onEventStream() again with a new Publisher; " + + "the implementation must reset accumulated state or throw to refuse the retry. " + + "Free resources in exceptionOccurred().") + .addMember("saferAlternative", "$S", + "Prefer the generated builder() with subscriber(Consumer) or subscriber(Visitor) " + + "which handle subscription, backpressure, and retry-state reset automatically.") + .build(); + } + @Override public ClassName className() { return poetExt.eventStreamResponseHandlerType(operationModel); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignIdentifierVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignIdentifierVisitor.java similarity index 95% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignIdentifierVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignIdentifierVisitor.java index 61679386a5e1..1ff5df78053f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignIdentifierVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignIdentifierVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Assigns an identifier to each rule then we use as a name for the generated method. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignTypesVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignTypesVisitor.java similarity index 90% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignTypesVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignTypesVisitor.java index 3c3b9a0efdb5..626c9f2f1319 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/AssignTypesVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/AssignTypesVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.List; @@ -117,16 +117,21 @@ public RuleExpression visitBooleanAndExpression(BooleanAndExpression e) { @Override public RuleExpression visitLetExpression(LetExpression e) { - LetExpression expr = (LetExpression) super.visitLetExpression(e); - expr.bindings().forEach((k, v) -> { - RuleType type = v.type(); + // Process bindings sequentially so that each binding's type is registered before subsequent bindings are + // visited. This allows later bindings to reference variables assigned by earlier bindings within the same + // let expression (e.g., `isoArn = aws.parseArn(...)` followed by `isoArnType = getAttr(isoArn, ...)`). + LetExpression.Builder builder = LetExpression.builder(); + e.bindings().forEach((k, v) -> { + RuleExpression visited = v.accept(this); + RuleType type = visited.type(); if (type == null) { - addError("Cannot find type for variable `%s`, expression: `%s`", k, v); + addError("Cannot find type for variable `%s`, expression: `%s`", k, visited); } else { putLocal(k, type); } + builder.putBinding(k, visited); }); - return expr; + return builder.build(); } @Override diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanAndExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanAndExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanAndExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanAndExpression.java index 1ea95065bafc..9f3d628d3932 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanAndExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanAndExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanNotExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanNotExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanNotExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanNotExpression.java index 93ee93dff9cd..f2efd0e050b1 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/BooleanNotExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/BooleanNotExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; import software.amazon.awssdk.utils.Validate; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodeGeneratorVisitor.java similarity index 96% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodeGeneratorVisitor.java index daf0d5ff7f39..0fa69d2923d9 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodeGeneratorVisitor.java @@ -13,11 +13,10 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; -import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -29,7 +28,6 @@ import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair; import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.utils.uri.SdkUri; public class CodeGeneratorVisitor extends WalkRuleExpressionVisitor { private static final Logger log = LoggerFactory.getLogger(CodeGeneratorVisitor.class); @@ -39,20 +37,17 @@ public class CodeGeneratorVisitor extends WalkRuleExpressionVisitor { private final SymbolTable symbolTable; private final Map knownEndpointAttributes; private final Map ruleIdToScope; - private final boolean endpointCaching; public CodeGeneratorVisitor(RuleRuntimeTypeMirror typeMirror, SymbolTable symbolTable, Map knownEndpointAttributes, Map ruleIdToScope, - boolean endpointCaching, CodeBlock.Builder builder) { this.builder = builder; this.symbolTable = symbolTable; this.knownEndpointAttributes = knownEndpointAttributes; this.ruleIdToScope = ruleIdToScope; this.typeMirror = typeMirror; - this.endpointCaching = endpointCaching; } @Override @@ -333,13 +328,9 @@ private String callParams(String ruleId) { @Override public Void visitEndpointExpression(EndpointExpression e) { builder.add("return $T.endpoint(", typeMirror.rulesResult().type()); - if (endpointCaching) { - builder.add("$T.builder().url($T.getInstance().create(", Endpoint.class, SdkUri.class); - } else { - builder.add("$T.builder().url($T.create(", Endpoint.class, URI.class); - } - e.url().accept(this); - builder.add("))"); + builder.add("$T.builder().endpointUrl(", Endpoint.class); + EndpointUrlCodeEmitter.emit(e.url(), builder, this); + builder.add(")"); e.headers().accept(this); e.properties().accept(this); builder.add(".build()"); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodegenExpressionBuidler.java similarity index 95% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodegenExpressionBuidler.java index 6488f015ad7b..150895ebd2d5 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodegenExpressionBuidler.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/CodegenExpressionBuidler.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.List; import java.util.Map; @@ -64,10 +64,6 @@ public RuleSetExpression root() { return root; } - public String regionParamName() { - return symbolTable.regionParamName(); - } - public SymbolTable symbolTable() { return symbolTable; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ComputeScopeTree.java similarity index 99% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ComputeScopeTree.java index 42f612f87418..0ee98f43d7cd 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ComputeScopeTree.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ComputeScopeTree.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayDeque; import java.util.ArrayList; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointExpression.java index 29fa872718bb..24206049728f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; import software.amazon.awssdk.utils.Validate; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java index eebe516b02d2..18ae695da40a 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParametersClassSpec.java @@ -25,9 +25,11 @@ import javax.lang.model.element.Modifier; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.utils.builder.CopyableBuilder; import software.amazon.awssdk.utils.builder.ToCopyableBuilder; @@ -56,6 +58,9 @@ public TypeSpec poetSpec() { parameters().forEach((name, model) -> { b.addField(endpointRulesSpecUtils.parameterClassField(name, model)); b.addMethod(endpointRulesSpecUtils.parameterClassAccessorMethod(name, model)); + if (model.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { + b.addMethod(regionIdAccessorMethod(name)); + } }); b.addMethod(toBuilderMethod()); @@ -121,7 +126,7 @@ private ClassName builderClassName() { } private Map parameters() { - return intermediateModel.getEndpointRuleSetModel().getParameters(); + return intermediateModel.getEndpointParameters(); } private MethodSpec ctor() { @@ -156,6 +161,22 @@ private String variableName(String name) { return intermediateModel.getNamingStrategy().getVariableName(name); } + /** + * Creates a convenience accessor for Region-typed parameters that returns the region ID as a String. + */ + private MethodSpec regionIdAccessorMethod(String name) { + String varName = variableName(name); + String methodName = endpointRulesSpecUtils.paramMethodName(name) + "Id"; + return MethodSpec.methodBuilder(methodName) + .addModifiers(Modifier.PUBLIC) + .addJavadoc("Returns the region ID (the {@link $T#id()} value) as a String," + + " or null if region is not set.", + Region.class) + .returns(String.class) + .addStatement("return $N == null ? null : $N.id()", varName, varName) + .build(); + } + private MethodSpec.Builder toBuilderConstructor() { MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder(); constructorBuilder.addModifiers(Modifier.PRIVATE); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParamsKnowledgeIndex.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParamsKnowledgeIndex.java index 7d200aeae0b5..2fb79a380fea 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParamsKnowledgeIndex.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParamsKnowledgeIndex.java @@ -70,7 +70,7 @@ public final class EndpointParamsKnowledgeIndex { private EndpointParamsKnowledgeIndex(IntermediateModel intermediateModel) { this.intermediateModel = intermediateModel; - this.parametersToGenerate = builtInsForClientBuilder(intermediateModel.getEndpointRuleSetModel().getParameters()); + this.parametersToGenerate = builtInsForClientBuilder(intermediateModel.getEndpointParameters()); } /** @@ -191,7 +191,11 @@ public MethodSpec recordAccountIdEndpointModeMethod() { + ".ifPresent(m -> executionAttributes.getAttribute($T.BUSINESS_METRICS).addMetric(m))", BusinessMetricsUtils.class, SdkInternalExecutionAttribute.class); - builder.addStatement("return mode.name().toLowerCase()"); + // Use value() rather than name().toLowerCase() so that the returned String is an interned compile-time + // literal. That keeps the reference stable across calls and removes a per-request allocation. It also + // avoids name().toLowerCase()'s dependence on the default locale, which mangles the value under a + // Turkish locale. + builder.addStatement("return mode.value()"); return builder.build(); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderSpec.java index 0577934790b5..3c1a930bc919 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderSpec.java @@ -17,189 +17,216 @@ import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterSpec; -import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; -import com.squareup.javapoet.TypeVariableName; -import com.squareup.javapoet.WildcardTypeName; -import java.net.URI; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import javax.lang.model.element.Modifier; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.codegen.model.config.customization.EndpointAuthSchemeConfig; +import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.Metadata; import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Validate; public class EndpointProviderSpec implements ClassSpec { - private static final String RULE_SET_FIELD_NAME = "ENDPOINT_RULE_SET"; - private static final String LOGGER_FIELD_NAME = "LOG"; - private final IntermediateModel intermediateModel; private final EndpointRulesSpecUtils endpointRulesSpecUtils; + private final Map knownEndpointAttributes; + private final CodegenExpressionBuidler utils; + private final RuleRuntimeTypeMirror typeMirror; public EndpointProviderSpec(IntermediateModel intermediateModel) { this.intermediateModel = intermediateModel; this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel); + String packageName = intermediateModel.getMetadata().getFullInternalEndpointRulesPackageName(); + this.typeMirror = new RuleRuntimeTypeMirror(packageName); + this.utils = createCodegenRulesUtil(intermediateModel.getEndpointRules(), + intermediateModel.getEndpointParameters(), + typeMirror); + this.knownEndpointAttributes = knownEndpointAttributes(intermediateModel); + } + + private static RuleType fromParameterModel(ParameterModel model) { + switch (model.getType().toLowerCase(Locale.ENGLISH)) { + case "boolean": + return RuleRuntimeTypeMirror.BOOLEAN; + case "string": + return RuleRuntimeTypeMirror.STRING; + case "stringarray": + return RuleRuntimeTypeMirror.LIST_OF_STRING; + default: + throw new IllegalStateException("Cannot find rule type for: " + model.getType()); + } } - @Override - public TypeSpec poetSpec() { - FieldSpec endpointAuthSchemeStrategyFieldSpec = endpointAuthSchemeStrategyFieldSpec(); - TypeSpec.Builder b = PoetUtils.createClassBuilder(className()) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addSuperinterface(endpointRulesSpecUtils.providerInterfaceName()) - .addField(logger()) - .addField(ruleSet()) - .addField(endpointAuthSchemeStrategyFieldSpec) - .addMethod(resolveEndpointMethod()) - .addMethod(toIdentifierValueMap()) - .addAnnotation(SdkInternalApi.class); - - MethodSpec constructorMethod = constructorMethodSpec(endpointAuthSchemeStrategyFieldSpec.name); - MethodSpec valueAsEndpointOrThrowMethod = valueAsEndpointOrThrowMethodSpec(); + private static RuleModel createRootRule(List rules) { + RuleModel root = new RuleModel(); + root.setRules(rules); + root.setType("tree"); + root.setConditions(Collections.emptyList()); + return root; + } - b.addMethod(constructorMethod); - b.addMethod(valueAsEndpointOrThrowMethod); - b.addMethod(ruleSetBuildMethod(b)); - b.addMethod(equalsMethod()); - b.addMethod(hashCodeMethod()); - addKnownPropertiesMethodSpec(b, endpointAuthSchemeStrategyFieldSpec.name); + private static CodegenExpressionBuidler createCodegenRulesUtil(List rules, + Map parameters, + RuleRuntimeTypeMirror typeMirror) { + RuleSetExpression root = ExpressionParser.parseRuleSetExpression(createRootRule(rules)); + return CodegenExpressionBuidler.from(root, typeMirror, initSymbolTable(parameters)); + } - return b.build(); + private static SymbolTable initSymbolTable(Map parameters) { + SymbolTable.Builder builder = SymbolTable.builder(); + parameters.forEach((k, v) -> { + builder.putParam(k, fromParameterModel(v)); + if (v.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { + builder.addRegionParam(k); + } + }); + return builder.build(); } - private FieldSpec endpointAuthSchemeStrategyFieldSpec() { - return FieldSpec.builder(endpointRulesSpecUtils.rulesRuntimeClassName("EndpointAuthSchemeStrategy"), - "endpointAuthSchemeStrategy", Modifier.PRIVATE, Modifier.FINAL) - .build(); + private static Map knownEndpointAttributes(IntermediateModel intermediateModel) { + Map knownEndpointAttributes = null; + EndpointAuthSchemeConfig config = intermediateModel.getCustomizationConfig().getEndpointAuthSchemeConfig(); + if (config != null) { + knownEndpointAttributes = config.getEndpointProviderTestKeys(); + } + if (knownEndpointAttributes == null) { + knownEndpointAttributes = Collections.emptyMap(); + } + return knownEndpointAttributes; } - private MethodSpec constructorMethodSpec(String endpointAuthSchemeFieldName) { - MethodSpec.Builder b = MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC); - EndpointAuthSchemeConfig endpointAuthSchemeConfig = - intermediateModel.getCustomizationConfig().getEndpointAuthSchemeConfig(); - String factoryLocalVarName = "endpointAuthSchemeStrategyFactory"; - if (endpointAuthSchemeConfig != null && endpointAuthSchemeConfig.getAuthSchemeStrategyFactoryClass() != null) { - String endpointAuthSchemeStrategyFactory = endpointAuthSchemeConfig.getAuthSchemeStrategyFactoryClass(); - b.addStatement("$T $N = new $T()", - endpointRulesSpecUtils.rulesRuntimeClassName("EndpointAuthSchemeStrategyFactory"), - factoryLocalVarName, - PoetUtils.classNameFromFqcn(endpointAuthSchemeStrategyFactory)); - } else { - b.addStatement("$T $N = new $T()", - endpointRulesSpecUtils.rulesRuntimeClassName("EndpointAuthSchemeStrategyFactory"), - factoryLocalVarName, - endpointRulesSpecUtils.rulesRuntimeClassName("DefaultEndpointAuthSchemeStrategyFactory")); + @Override + public TypeSpec poetSpec() { + TypeSpec.Builder builder = PoetUtils.createClassBuilder(className()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addSuperinterface(endpointRulesSpecUtils.providerInterfaceName()) + .addAnnotation(SdkInternalApi.class); + + builder.addMethod(resolveEndpointMethod()); + List methods = new ArrayList<>(); + createRuleMethod(utils.root(), methods); + for (MethodSpec.Builder methodBuilder : methods) { + builder.addMethod(methodBuilder.build()); } - b.addStatement("this.$N = $N.endpointAuthSchemeStrategy()", endpointAuthSchemeFieldName, factoryLocalVarName); - return b.build(); + builder.addMethod(equalsMethod()); + builder.addMethod(hashCodeMethod()); + return builder.build(); } - private MethodSpec valueAsEndpointOrThrowMethodSpec() { - String valueParamName = "value"; - ParameterSpec param = ParameterSpec.builder(endpointRulesSpecUtils.rulesRuntimeClassName("Value"), valueParamName) - .build(); - MethodSpec.Builder b = MethodSpec.methodBuilder("valueAsEndpointOrThrow") - .returns(ClassName.get(Endpoint.class)) - .addParameter(param); + @Override + public ClassName className() { + Metadata md = intermediateModel.getMetadata(); + return ClassName.get(md.getFullInternalEndpointRulesPackageName(), + "Default" + endpointRulesSpecUtils.providerInterfaceName().simpleName()); + } - CodeBlock.Builder methodCode = - CodeBlock.builder() - .beginControlFlow("if ($N instanceof $T)", - valueParamName, - endpointRulesSpecUtils.rulesRuntimeClassName("Value.Endpoint")) - .addStatement("$T endpoint = $N.expectEndpoint()", - endpointRulesSpecUtils.rulesRuntimeClassName("Value.Endpoint"), valueParamName) - .addStatement("$T builder = Endpoint.builder()", Endpoint.Builder.class) - .addStatement("builder.url($T.create(endpoint.getUrl()))", URI.class) - .addStatement("$T headers = endpoint.getHeaders()", - ParameterizedTypeName.get(ClassName.get(Map.class), - TypeName.get(String.class), - ParameterizedTypeName.get(List.class, String.class))) - .beginControlFlow("if (headers != null)") - .addStatement("headers.forEach((name, values) -> values.forEach(v -> builder.putHeader(name, v)))") - .endControlFlow() - .addStatement("addKnownProperties(builder, endpoint.getProperties())") - .addStatement("return builder.build()") + private MethodSpec resolveEndpointMethod() { + MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveEndpoint") + .addModifiers(Modifier.PUBLIC) + .returns(endpointRulesSpecUtils.resolverReturnType()) + .addAnnotation(Override.class) + .addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); + + builder.addCode(validateRequiredParams()); + builder.beginControlFlow("try"); + builder.addStatement("$T result = $L(params)", ruleResult(), utils.root().ruleId()); + builder.beginControlFlow("if (result.canContinue())") + .addStatement("throw $T.create($S)", SdkClientException.class, "Rule engine did not reach an error or " + + "endpoint result") + .endControlFlow(); + + builder.beginControlFlow("if (result.isError())") + .addStatement("String errorMsg = result.error()") + .beginControlFlow("if (errorMsg.contains(\"Invalid ARN\") && errorMsg.contains(\":s3:::\"))") + .addStatement("errorMsg += $S", ". Use the bucket name instead of simple bucket ARNs in " + + "GetBucketLocationRequest.") + .endControlFlow() + .addStatement("throw $T.create(errorMsg)", SdkClientException.class) + .endControlFlow(); + + builder.addStatement("return $T.completedFuture(result.endpoint())", CompletableFuture.class); + builder.nextControlFlow("catch ($T error)", Exception.class); + builder.addStatement("return $T.failedFuture(error)", CompletableFutureUtils.class); + builder.endControlFlow(); + + return builder.build(); + } - .nextControlFlow("else if ($N instanceof $T)", - valueParamName, - endpointRulesSpecUtils.rulesRuntimeClassName("Value.Str")) - .addStatement("$T errorMsg = $N.expectString()", String.class, valueParamName) - .beginControlFlow("if (errorMsg.contains($S) && errorMsg.contains($S))", - "Invalid ARN", ":s3:::") - .addStatement("errorMsg += $S", ". Use the bucket name instead of simple bucket ARNs in " - + "GetBucketLocationRequest.") - .endControlFlow() - .addStatement("throw $T.create(errorMsg)", SdkClientException.class) - .nextControlFlow("else") - .addStatement("throw SdkClientException.create($S + $N)", - "Rule engine return neither an endpoint result or error value. Returned value was: ", - valueParamName) - .endControlFlow(); + private CodeBlock validateRequiredParams() { + CodeBlock.Builder b = CodeBlock.builder(); + Map parameters = intermediateModel.getEndpointParameters(); + parameters.entrySet().stream() + .filter(e -> Boolean.TRUE.equals(e.getValue().isRequired())) + .forEach(e -> { + b.addStatement("$T.notNull($N.$N(), $S)", + Validate.class, + "params", + endpointRulesSpecUtils.paramMethodName(e.getKey()), + String.format("Parameter '%s' must not be null", e.getKey())); + }); - b.addCode(methodCode.build()); return b.build(); } - private void addKnownPropertiesMethodSpec(TypeSpec.Builder b, String endpointAuthSpecStrategyFieldName) { - EndpointAuthSchemeConfig endpointAuthSchemeConfig = - intermediateModel.getCustomizationConfig().getEndpointAuthSchemeConfig(); - if (endpointAuthSchemeConfig != null && endpointAuthSchemeConfig.getKnownEndpointProperties() != null) { - addKnownEndpointPropertiesMethodOverride(b, endpointAuthSchemeConfig.getKnownEndpointProperties()); - } else { - b.addMethod(defaultAddKnownEndpointPropertyMethod(endpointAuthSpecStrategyFieldName)); + private void createRuleMethod(RuleSetExpression expr, List methods) { + MethodSpec.Builder builder = methodBuilderForRule(expr); + methods.add(builder); + CodeBlock.Builder block = CodeBlock.builder(); + codegenExpr(expr, block); + builder.addCode(block.build()); + if (expr.isTree()) { + for (RuleSetExpression child : expr.children()) { + if (child.isTree()) { + createRuleMethod(child, methods); + } + } } } - private MethodSpec defaultAddKnownEndpointPropertyMethod(String endpointAuthSpecStrategyFieldName) { - String builderParamName = "builder"; - String propertiesParamName = "properties"; - MethodSpec.Builder b = addKnowPropertiesSignature(builderParamName, propertiesParamName); + private MethodSpec.Builder methodBuilderForRule(RuleSetExpression expr) { + MethodSpec.Builder builder = + MethodSpec.methodBuilder(expr.ruleId()) + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .returns(ruleResult()); + ComputeScopeTree.Scope scope = utils.scopesByName().get(expr.ruleId()); + builder.addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); + for (String param : scope.usesLocals()) { + if (scope.defines().contains(param)) { + continue; + } + RuleType type = utils.symbolTable().localType(param); + builder.addParameter(type.javaType(), param); + } + return builder; + } - CodeBlock.Builder switchStatementCode = CodeBlock.builder(); - switchStatementCode.beginControlFlow("switch (n)") - .add("case $S:\n", "authSchemes").indent() - .add(CodeBlock.builder() - .addStatement("$N.putAttribute($T.AUTH_SCHEMES, $N.createAuthSchemes(v))", - builderParamName, - AwsEndpointAttribute.class, - endpointAuthSpecStrategyFieldName) - .build()) - .addStatement("break") - .add("default:\n").indent() - .add(CodeBlock.builder() - .addStatement("$N.debug(() -> $S + n)", - LOGGER_FIELD_NAME, - "Ignoring unknown endpoint property: ") - .build()) - .addStatement("break") - .endControlFlow(); - CodeBlock.Builder methodCode = CodeBlock.builder(); - CodeBlock lambda = CodeBlock.builder() - .add("(n, v) -> {\n").indent() - .add(switchStatementCode.build()) - .unindent().add("}") - .build(); - methodCode.add("$N.forEach($L);", propertiesParamName, lambda); - b.addCode(methodCode.build()); - return b.build(); + private void codegenExpr(RuleSetExpression expr, CodeBlock.Builder builder) { + CodeGeneratorVisitor visitor = new CodeGeneratorVisitor(typeMirror, + utils.symbolTable(), + knownEndpointAttributes, + utils.scopesByName(), + builder); + visitor.visitRuleSetExpression(expr); + } + + private TypeName ruleResult() { + return typeMirror.rulesResult().type(); } private MethodSpec equalsMethod() { @@ -220,181 +247,4 @@ private MethodSpec hashCodeMethod() { .addStatement("return getClass().hashCode()") .build(); } - - private void addKnownEndpointPropertiesMethodOverride(TypeSpec.Builder b, String knowPropertyExpression) { - MethodSpec singlePropertyMethod = - MethodSpec.methodBuilder("addKnownProperty") - .addModifiers(Modifier.PRIVATE) - .addTypeVariable(TypeVariableName.get("T")) - .addParameter(ParameterSpec.builder( - ParameterizedTypeName.get(endpointRulesSpecUtils.rulesRuntimeClassName("EndpointAttributeProvider"), - TypeVariableName.get("T")), - "provider").build()) - .addParameter(Endpoint.Builder.class, "builder") - .addParameter(endpointRulesSpecUtils.rulesRuntimeClassName("Value"), "value") - .addStatement("builder.putAttribute(provider.attributeKey(), provider.attributeValue(value))") - .build(); - b.addMethod(singlePropertyMethod); - - String builderParamName = "builder"; - String propertiesParamName = "properties"; - MethodSpec.Builder methodBuilder = addKnowPropertiesSignature(builderParamName, propertiesParamName); - - TypeName wildcardEndpointAttrType = ParameterizedTypeName.get( - endpointRulesSpecUtils.rulesRuntimeClassName("EndpointAttributeProvider"), - WildcardTypeName.subtypeOf(Object.class)); - methodBuilder.addStatement("$T knownProperties = $N", - ParameterizedTypeName.get(ClassName.get(List.class), wildcardEndpointAttrType), - knowPropertyExpression); - methodBuilder.beginControlFlow("for ($T p: knownProperties)", wildcardEndpointAttrType); - methodBuilder.beginControlFlow("if ($N.containsKey(p.propertyName()))", propertiesParamName); - methodBuilder.addStatement("$N(p, $N, $N.get(p.propertyName()))", - singlePropertyMethod.name, - builderParamName, - propertiesParamName); - methodBuilder.endControlFlow(); - methodBuilder.endControlFlow(); - - b.addMethod(methodBuilder.build()); - } - - private MethodSpec.Builder addKnowPropertiesSignature(String builderParamName, String propertiesParamName) { - ParameterSpec builderParam = ParameterSpec.builder(ClassName.get(Endpoint.Builder.class), builderParamName).build(); - ParameterSpec propertiesParam = ParameterSpec - .builder(ParameterizedTypeName.get( - ClassName.get(Map.class), - ClassName.get(String.class), - endpointRulesSpecUtils.rulesRuntimeClassName("Value")), - propertiesParamName) - .build(); - return MethodSpec.methodBuilder("addKnownProperties") - .addModifiers(Modifier.PRIVATE) - .addParameter(builderParam) - .addParameter(propertiesParam); - } - - @Override - public ClassName className() { - Metadata md = intermediateModel.getMetadata(); - return ClassName.get(md.getFullInternalEndpointRulesPackageName(), - "Default" + endpointRulesSpecUtils.providerInterfaceName().simpleName()); - } - - private FieldSpec logger() { - return FieldSpec.builder(Logger.class, LOGGER_FIELD_NAME) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) - .initializer("$T.loggerFor($T.class)", Logger.class, className()) - .build(); - } - - private FieldSpec ruleSet() { - return FieldSpec.builder(endpointRulesSpecUtils.rulesRuntimeClassName("EndpointRuleset"), RULE_SET_FIELD_NAME) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) - .initializer("ruleSet()") - .build(); - } - - private MethodSpec toIdentifierValueMap() { - ParameterizedTypeName resultType = ParameterizedTypeName.get(ClassName.get(Map.class), - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - endpointRulesSpecUtils.rulesRuntimeClassName("Value")); - - String paramsName = "params"; - MethodSpec.Builder b = MethodSpec.methodBuilder("toIdentifierValueMap") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .addParameter(endpointRulesSpecUtils.parametersClassName(), paramsName) - .returns(resultType); - - Map params = intermediateModel.getEndpointRuleSetModel().getParameters(); - - String resultName = "paramsMap"; - b.addStatement("$T $N = new $T<>()", resultType, resultName, HashMap.class); - - params.forEach((name, model) -> { - String methodVarName = endpointRulesSpecUtils.paramMethodName(name); - - CodeBlock identifierExpr = - CodeBlock.of("$T.of($S)", endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), name); - - CodeBlock coerce; - // We treat region specially and generate it as the Region type, - // so we need to call id() to convert it back to string - if (model.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { - coerce = CodeBlock.builder().add(".id()").build(); - } else { - coerce = CodeBlock.builder().build(); - } - - CodeBlock valueExpr = endpointRulesSpecUtils.valueCreationCode( - model.getType(), - CodeBlock.builder() - .add("$N.$N()$L", paramsName, methodVarName, coerce) - .build()); - - b.beginControlFlow("if ($N.$N() != null)", paramsName, methodVarName); - b.addStatement("$N.put($L, $L)", resultName, identifierExpr, valueExpr); - b.endControlFlow(); - }); - - b.addStatement("return $N", resultName); - - return b.build(); - } - - private MethodSpec resolveEndpointMethod() { - String paramsName = "endpointParams"; - - MethodSpec.Builder b = MethodSpec.methodBuilder("resolveEndpoint") - .addModifiers(Modifier.PUBLIC) - .returns(endpointRulesSpecUtils.resolverReturnType()) - .addAnnotation(Override.class) - .addParameter(endpointRulesSpecUtils.parametersClassName(), paramsName); - - b.addCode(validateRequiredParams()); - - b.addStatement("$T res = new $T().evaluate($N, toIdentifierValueMap($N))", - endpointRulesSpecUtils.rulesRuntimeClassName("Value"), - endpointRulesSpecUtils.rulesRuntimeClassName("DefaultRuleEngine"), - RULE_SET_FIELD_NAME, - paramsName); - - b.beginControlFlow("try"); - b.addStatement("return $T.completedFuture(valueAsEndpointOrThrow($N))", - CompletableFuture.class, - "res"); - b.endControlFlow(); - b.beginControlFlow("catch ($T error)", Exception.class); - b.addStatement("return $T.failedFuture(error)", CompletableFutureUtils.class); - b.endControlFlow(); - - return b.build(); - } - - private MethodSpec ruleSetBuildMethod(TypeSpec.Builder classBuilder) { - RuleSetCreationSpec ruleSetCreationSpec = new RuleSetCreationSpec(intermediateModel); - MethodSpec.Builder b = MethodSpec.methodBuilder("ruleSet") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .returns(endpointRulesSpecUtils.rulesRuntimeClassName("EndpointRuleset")) - .addStatement("return $L", ruleSetCreationSpec.ruleSetCreationExpr()); - - ruleSetCreationSpec.helperMethods().forEach(classBuilder::addMethod); - return b.build(); - } - - private CodeBlock validateRequiredParams() { - CodeBlock.Builder b = CodeBlock.builder(); - - Map parameters = intermediateModel.getEndpointRuleSetModel().getParameters(); - parameters.entrySet().stream() - .filter(e -> Boolean.TRUE.equals(e.getValue().isRequired())) - .forEach(e -> { - b.addStatement("$T.notNull($N.$N(), $S)", - Validate.class, - "endpointParams", - endpointRulesSpecUtils.paramMethodName(e.getKey()), - String.format("Parameter '%s' must not be null", e.getKey())); - }); - - return b.build(); - } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderTestSpec.java index 4104703f88d8..23852b0323ee 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderTestSpec.java @@ -87,8 +87,9 @@ private MethodSpec testsCasesMethod() { CustomizationConfig customizationConfig = model.getCustomizationConfig(); model.getEndpointTestSuiteModel().getTestCases().forEach(test -> { - b.addStatement("testCases.add(new $T($L, $L))", + b.addStatement("testCases.add(new $T($S, $L, $L))", EndpointProviderTestCase.class, + test.getDocumentation(), createTestCase(test), TestGeneratorUtils.createExpect(customizationConfig, test.getExpect(), null, null)); }); @@ -142,7 +143,7 @@ private CodeBlock createTestCase(EndpointTestModel test) { } private boolean isRegionBuiltIn(String paramName) { - Map parameters = model.getEndpointRuleSetModel().getParameters(); + Map parameters = model.getEndpointParameters(); ParameterModel param = parameters.get(paramName); return param.getBuiltInEnum() == BuiltInParameter.AWS_REGION; } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpec.java index 84677fcae0cd..4649419ea56c 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpec.java @@ -22,11 +22,15 @@ import com.fasterxml.jackson.jr.stree.JrsString; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.NameAllocator; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeSpec; import com.squareup.javapoet.TypeVariableName; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Locale; @@ -34,6 +38,8 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.Modifier; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsExecutionAttribute; @@ -49,6 +55,7 @@ import software.amazon.awssdk.codegen.model.service.ContextParam; import software.amazon.awssdk.codegen.model.service.EndpointTrait; import software.amazon.awssdk.codegen.model.service.HostPrefixProcessor; +import software.amazon.awssdk.codegen.model.service.OperationContextParam; import software.amazon.awssdk.codegen.model.service.StaticContextParam; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.PoetExtension; @@ -86,6 +93,7 @@ public class EndpointResolverUtilsSpec implements ClassSpec { private final EndpointParamsKnowledgeIndex endpointParamsKnowledgeIndex; private final PoetExtension poetExtension; private final JmesPathAcceptorGenerator jmesPathGenerator; + private final JmesPathTypedGetterGenerator jmesPathTypedGetterGenerator; private final boolean dependsOnHttpAuthAws; private final boolean multiAuthSigv4a; private final boolean legacyAuthFromEndpointRulesService; @@ -96,6 +104,7 @@ public EndpointResolverUtilsSpec(IntermediateModel model) { this.endpointParamsKnowledgeIndex = EndpointParamsKnowledgeIndex.of(model); this.poetExtension = new PoetExtension(model); this.jmesPathGenerator = new JmesPathAcceptorGenerator(poetExtension.jmesPathRuntimeClass()); + this.jmesPathTypedGetterGenerator = new JmesPathTypedGetterGenerator(model); Set> supportedAuthSchemes = ModelAuthSchemeClassesKnowledgeIndex.of(model).serviceConcreteAuthSchemeClasses(); @@ -119,6 +128,7 @@ public TypeSpec poetSpec() { b.addMethod(setStaticContextParamsMethod()); addStaticContextParamMethods(b); + addStaticListFields(b); b.addMethod(authSchemeWithEndpointSignerPropertiesMethod()); @@ -156,7 +166,7 @@ private MethodSpec ruleParams() { b.addStatement("$T builder = $T.builder()", paramsBuilderClass(), endpointRulesSpecUtils.parametersClassName()); - Map parameters = model.getEndpointRuleSetModel().getParameters(); + Map parameters = model.getEndpointParameters(); parameters.forEach((n, m) -> { if (m.getBuiltInEnum() == null) { return; @@ -342,9 +352,8 @@ private MethodSpec addStaticContextParamsMethod(OperationModel opModel) { b.addStatement("params.$N($L)", setterName, ((JrsBoolean) value).booleanValue()); break; case START_ARRAY: - JrsArray arrayValue = (JrsArray) value; - CodeBlock arrayCode = endpointRulesSpecUtils.treeNodeToLiteral(arrayValue); - b.addStatement("params.$N($L)", setterName, arrayCode); + String fieldName = staticListFieldName(opModel, n); + b.addStatement("params.$N($N)", setterName, fieldName); break; default: throw new RuntimeException("Don't know how to set parameter of type " + value.asToken()); @@ -358,6 +367,57 @@ private String staticContextParamsMethodName(OperationModel opModel) { return opModel.getMethodName() + "StaticContextParams"; } + /** + * Generates the name of the {@code static final List} field holding the static array value of + * {@code paramName} for {@code opModel}. + * + *

Format: {@code STATIC_LIST_{OPERATION}_{PARAM}} + */ + private static String staticListFieldName(OperationModel opModel, String paramName) { + return "STATIC_LIST_" + screamCase(opModel.getOperationName()) + "_" + screamCase(paramName); + } + + private static String screamCase(String word) { + return Stream.of(CodegenNamingUtils.splitOnWordBoundaries(word)) + .map(s -> s.toUpperCase(Locale.US)) + .collect(Collectors.joining("_")); + } + + /** + * Generates a {@code private static final List} field for every {@code staticContextParams} entry whose + * value is an array, so that {@code setStaticContextParams} hands the same list reference to the endpoint params + * builder on every call rather than constructing a new list each time. + */ + private void addStaticListFields(TypeSpec.Builder classBuilder) { + ParameterizedTypeName listOfString = ParameterizedTypeName.get(List.class, String.class); + + model.getOperations().forEach((opName, opModel) -> { + Map statics = opModel.getStaticContextParams(); + if (CollectionUtils.isNullOrEmpty(statics)) { + return; + } + statics.forEach((paramName, scp) -> { + TreeNode value = scp.getValue(); + if (value.asToken() != JsonToken.START_ARRAY) { + return; + } + JrsArray arrayValue = (JrsArray) value; + CodeBlock initializer; + if (arrayValue.size() == 0) { + initializer = CodeBlock.of("$T.emptyList()", Collections.class); + } else { + initializer = CodeBlock.of("$T.unmodifiableList($L)", Collections.class, + endpointRulesSpecUtils.treeNodeToLiteral(arrayValue)); + } + FieldSpec field = FieldSpec.builder(listOfString, staticListFieldName(opModel, paramName), + Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .initializer(initializer) + .build(); + classBuilder.addField(field); + }); + }); + } + private boolean hasStaticContextParams(OperationModel opModel) { Map staticContextParams = opModel.getStaticContextParams(); return staticContextParams != null && !staticContextParams.isEmpty(); @@ -412,34 +472,70 @@ private MethodSpec setOperationContextParamsMethod(OperationModel opModel) { .addParameter(requestClass, "request") .returns(void.class); - b.addStatement("$1T input = new $1T(request)", poetExtension.jmesPathRuntimeClass().nestedClass("Value")); + Map operationContextParams = opModel.getOperationContextParams(); - opModel.getOperationContextParams().forEach((key, value) -> { - if (Objects.requireNonNull(value.getPath().asToken()) == JsonToken.VALUE_STRING) { - String setterName = endpointRulesSpecUtils.paramMethodName(key); - String jmesPathString = ((JrsString) value.getPath()).getValue(); - CodeBlock addParam = CodeBlock.builder() - .add("params.$N(", setterName) - .add(jmesPathGenerator.interpret(jmesPathString, "input")) - .add(matchToParameterType(key)) - .add(")") - .build(); - b.addStatement(addParam); - } else { + // Validated up front rather than while lowering, so a malformed path is reported even when an earlier binding + // sends the operation down the reflective path. + for (OperationContextParam value : operationContextParams.values()) { + JsonToken token = Objects.requireNonNull(value.getPath().asToken()); + if (token != JsonToken.VALUE_STRING) { throw new RuntimeException("Invalid operation context parameter path for " + opModel.getOperationName() + - ". Expected VALUE_STRING, but got " + value.getPath().asToken()); + ". Expected VALUE_STRING, but got " + token); } - }); + } + + List loweredBindings = new ArrayList<>(); + NameAllocator names = jmesPathTypedGetterGenerator.newNameAllocator(); + boolean allBindingsLowered = true; + for (Map.Entry entry : operationContextParams.entrySet()) { + String key = entry.getKey(); + OperationContextParam value = entry.getValue(); + String jmesPathString = ((JrsString) value.getPath()).getValue(); + String setterName = endpointRulesSpecUtils.paramMethodName(key); + try { + loweredBindings.add(jmesPathTypedGetterGenerator.lower(opModel.getInputShape(), jmesPathString, + operationContextParamType(key), setterName, names)); + } catch (JmesPathTypedGetterGenerator.UnsupportedLoweringException e) { + allBindingsLowered = false; + break; + } + } + if (allBindingsLowered) { + loweredBindings.forEach(b::addCode); + return b.build(); + } + + b.addStatement("$1T input = new $1T(request)", poetExtension.jmesPathRuntimeClass().nestedClass("Value")); + operationContextParams.forEach((key, value) -> { + String setterName = endpointRulesSpecUtils.paramMethodName(key); + String jmesPathString = ((JrsString) value.getPath()).getValue(); + CodeBlock addParam = CodeBlock.builder() + .add("params.$N(", setterName) + .add(jmesPathGenerator.interpret(jmesPathString, "input")) + .add(matchToParameterType(key)) + .add(")") + .build(); + b.addStatement(addParam); + }); return b.build(); } + private String operationContextParamType(String paramName) { + Map parameters = model.getEndpointParameters(); + return parameters.entrySet().stream() + .filter(e -> e.getKey().toLowerCase(Locale.US).equals(paramName.toLowerCase(Locale.US))) + .map(e -> e.getValue().getType()) + .findFirst() + .orElse(null); + } + private boolean hasOperationContextParams(OperationModel opModel) { return CollectionUtils.isNotEmpty(opModel.getOperationContextParams()); } private CodeBlock matchToParameterType(String paramName) { - Map parameters = model.getEndpointRuleSetModel().getParameters(); + Map parameters = model.getEndpointParameters(); Optional endpointParameter = parameters.entrySet().stream() .filter(e -> e.getKey().toLowerCase(Locale.US) .equals(paramName.toLowerCase(Locale.US))) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java index d077473f532a..8f0a389c58dd 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpec.java @@ -661,7 +661,7 @@ private boolean isClientParam(String name) { } private ParameterModel param(String name) { - return model.getEndpointRuleSetModel().getParameters().get(name); + return model.getEndpointParameters().get(name); } private boolean hasSyncClient() { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java index 04cc97420d5e..7ccda4108c01 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesSpecUtils.java @@ -253,6 +253,10 @@ public List rulesEngineResourceFiles() { } public List rulesEngineFilesFromDirectory(URL location) { + return rulesEngineFilesFromDirectory(location, RULES_ENGINE_RESOURCE_FILES_PREFIX); + } + + public List rulesEngineFilesFromDirectory(URL location, String prefix) { URI locationUri; try { locationUri = location.toURI(); @@ -268,32 +272,19 @@ public List rulesEngineFilesFromDirectory(URL location) { return Files.walk(directory) // Remove the root directory if the classes, paths are expected to be relative to this directory .map(f -> directory.relativize(f).toString()) - .filter(f -> f.startsWith(RULES_ENGINE_RESOURCE_FILES_PREFIX)) + .filter(f -> f.startsWith(prefix)) .collect(Collectors.toList()); } catch (IOException e) { throw new UncheckedIOException(e); } } - public List rulesEngineResourceFiles2() { - URL currentJarUrl = EndpointRulesSpecUtils.class.getProtectionDomain().getCodeSource().getLocation(); - try (JarFile jarFile = new JarFile(currentJarUrl.getFile())) { - return jarFile.stream() - .map(ZipEntry::getName) - .filter(e -> e.startsWith("software/amazon/awssdk/codegen/rules2/")) - .collect(Collectors.toList()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - public Map parameters() { - return intermediateModel.getEndpointRuleSetModel().getParameters(); + return intermediateModel.getEndpointParameters(); } public boolean isDeclaredParam(String paramName) { - Map parameters = intermediateModel.getEndpointRuleSetModel().getParameters(); - return parameters.containsKey(paramName); + return intermediateModel.getEndpointParameters().containsKey(paramName); } /** diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitter.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitter.java new file mode 100644 index 000000000000..3fe67f951a2b --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitter.java @@ -0,0 +1,376 @@ +/* + * 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.codegen.poet.rules; + +import com.squareup.javapoet.CodeBlock; +import java.util.ArrayList; +import java.util.List; +import software.amazon.awssdk.endpoints.EndpointUrl; + +/** + * Emits the optimal {@code EndpointUrl} construction code for a URL expression. + * + *

This class encapsulates both the analysis of the URL expression structure (determining whether + * it can be statically decomposed) and the code emission. When the URL starts with a literal scheme + * prefix ({@code https://} or {@code http://}) and the components (scheme, host, port, path) can be + * identified at codegen time then we eliminate runtime parsing and use {@code EndpointUrl.fromComponents()}. + * Otherwise, falls back to {@code EndpointUrl.fromString()} for runtime parsing. + * + *

The endpoint URL spec guarantees that URLs contain only scheme, host, optional port, and optional + * base path (no query or fragment). Dynamic (template based) resolution are only supported in the host + * and path segments in pre-parsing. Otherwise, we fall back to runtime parsing. + */ +public final class EndpointUrlCodeEmitter { + + private static final String HTTPS_SCHEME_PREFIX = "https://"; + private static final String HTTP_SCHEME_PREFIX = "http://"; + + private EndpointUrlCodeEmitter() { + } + + /** + * Emit the optimal EndpointUrl construction code for the given URL expression. + * + *

Writes to {@code builder} either: + *

    + *
  • {@code EndpointUrl.fromComponents(scheme, hostExpr, port, pathExpr)} when the URL + * can be statically decomposed, or
  • + *
  • {@code EndpointUrl.fromString(urlExpr)} as a fallback.
  • + *
+ * + * @param urlExpr the URL expression from the endpoint rule + * @param builder the CodeBlock builder to emit into + * @param codegenVisitor the parent code generator, used to emit sub-expressions + */ + static void emit(RuleExpression urlExpr, CodeBlock.Builder builder, CodeGeneratorVisitor codegenVisitor) { + emit(urlExpr, builder, (RuleExpressionVisitor) codegenVisitor); + } + + /** + * Emit the optimal EndpointUrl construction code for the given URL expression. + * + *

This overload accepts any {@link RuleExpressionVisitor} that emits code into the same builder, + * allowing both the standard CodeGeneratorVisitor and BDD visitors to share the same URL emission logic. + */ + public static void emit(RuleExpression urlExpr, CodeBlock.Builder builder, RuleExpressionVisitor visitor) { + if (urlExpr instanceof LiteralStringExpression) { + emitFromLiteralString(((LiteralStringExpression) urlExpr).value(), builder); + return; + } + if (urlExpr instanceof StringConcatExpression) { + emitFromStringConcat((StringConcatExpression) urlExpr, builder, visitor); + return; + } + // Expression type we can't decompose (e.g. variable reference, function call) + emitRuntimeParse(urlExpr, builder, visitor); + } + + /** + * Emit a fully static URL as EndpointUrl.fromComponents() with all literal arguments. + */ + private static void emitFromLiteralString(String url, CodeBlock.Builder builder) { + int schemeEnd = url.indexOf("://"); + if (schemeEnd < 0) { + // No scheme found — shouldn't happen per spec, but fall back safely + builder.add("$T.fromString($S)", EndpointUrl.class, url); + return; + } + + String scheme = url.substring(0, schemeEnd); + int authorityStart = schemeEnd + 3; + int pathStart = url.indexOf('/', authorityStart); + + String authority; + String encodedPath; + if (pathStart < 0) { + authority = url.substring(authorityStart); + encodedPath = ""; + } else { + authority = url.substring(authorityStart, pathStart); + encodedPath = url.substring(pathStart); + } + + int port = -1; + String host; + int colonPos = authority.lastIndexOf(':'); + if (colonPos >= 0) { + try { + port = Integer.parseInt(authority.substring(colonPos + 1)); + host = authority.substring(0, colonPos); + } catch (NumberFormatException e) { + // Not a valid port — can't reliably decompose, fall back to runtime parsing + builder.add("$T.fromString($S)", EndpointUrl.class, url); + return; + } + } else { + host = authority; + } + + builder.add("$T.fromComponents($S, $S, $L, $S)", EndpointUrl.class, scheme, host, port, encodedPath); + } + + /** + * Emit code for a StringConcatExpression URL template. If the URL can be statically decomposed + * (starts with a literal scheme prefix), emits {@code EndpointUrl.fromComponents()}. Otherwise, + * falls back to {@code EndpointUrl.fromString()} for runtime parsing. + * + *

StringConcatExpressions are created by our codegen pre-parser: {@link ExpressionParser}. + * It splits on "{...}" boundaries, producing alternating literal strings and variable/member-access references. The + * result is a StringConcatExpression whose expressions() list interleaves: + *

    + *
  • LiteralStringExpression — static text fragments
  • + *
  • VariableReferenceExpression — "{Region}" eg a variable reference to "Region"
  • + *
  • MemberAccessExpression — "{PartitionResult#dnsSuffix}" → member access on variable "PartitionResult"
  • + *
+ * + *

Typical service endpoints follow something like: "https://sts.{Region}.{PartitionResult#dnsSuffix}" which + * parses to something like: + * {@snippet : + * StringConcatExpression([ + * LiteralStringExpression("https://sts."), + * VariableReferenceExpression("Region"), + * LiteralStringExpression("."), + * MemberAccessExpression(source=VarRef("PartitionResult"), name="dnsSuffix") + * ]) + * } + * + */ + private static void emitFromStringConcat(StringConcatExpression concatExpr, + CodeBlock.Builder builder, + RuleExpressionVisitor codegenVisitor) { + List expressions = concatExpr.expressions(); + if (expressions.isEmpty()) { + emitRuntimeParse(concatExpr, builder, codegenVisitor); + return; + } + + // The first expression must be a literal starting with a scheme to preparse + RuleExpression firstExpr = expressions.get(0); + if (!(firstExpr instanceof LiteralStringExpression)) { + emitRuntimeParse(concatExpr, builder, codegenVisitor); + return; + } + + String firstLiteral = ((LiteralStringExpression) firstExpr).value(); + String scheme; + String hostStartStr; + if (firstLiteral.startsWith(HTTPS_SCHEME_PREFIX)) { + scheme = "https"; + hostStartStr = firstLiteral.substring(HTTPS_SCHEME_PREFIX.length()); + } else if (firstLiteral.startsWith(HTTP_SCHEME_PREFIX)) { + scheme = "http"; + hostStartStr = firstLiteral.substring(HTTP_SCHEME_PREFIX.length()); + } else { + emitRuntimeParse(concatExpr, builder, codegenVisitor); + return; + } + + // Scan expressions to find port and path boundaries, collecting host and path parts + int port = -1; + List hostParts = new ArrayList<>(); + List pathParts = new ArrayList<>(); + boolean foundPath = false; + + // Process the remainder of the first literal (after "scheme://") + if (!hostStartStr.isEmpty()) { + ScanResult scanResult = scanLiteral(hostStartStr, hostParts, pathParts); + if (!scanResult.parseable) { + emitRuntimeParse(concatExpr, builder, codegenVisitor); + return; + } + if (scanResult.foundPort) { + port = scanResult.port; + } + foundPath = scanResult.foundPath; + } + + // Process remaining expressions + for (int i = 1; i < expressions.size(); i++) { + RuleExpression expr = expressions.get(i); + + if (foundPath) { + // Everything after the path boundary is path — literals and expressions alike + pathParts.add(expr); + continue; + } + + if (expr instanceof LiteralStringExpression) { + String literal = ((LiteralStringExpression) expr).value(); + ScanResult scanResult = scanLiteral(literal, hostParts, pathParts); + if (!scanResult.parseable) { + emitRuntimeParse(concatExpr, builder, codegenVisitor); + return; + } + if (scanResult.foundPort) { + port = scanResult.port; + } + foundPath = scanResult.foundPath; + } else { + // Non-literal expression — part of the host since we haven't hit a path + hostParts.add(expr); + } + } + + // Emit: EndpointUrl.fromComponents(scheme, hostExpr, port, pathExpr) + builder.add("$T.fromComponents($S, ", EndpointUrl.class, scheme); + emitConcatExpression(hostParts, builder, codegenVisitor); + builder.add(", $L, ", port); + emitConcatExpression(pathParts, builder, codegenVisitor); + builder.add(")"); + } + + /** + * Emit EndpointUrl.fromString(urlExpr) for runtime parsing when static decomposition isn't possible. + */ + private static void emitRuntimeParse(RuleExpression urlExpr, CodeBlock.Builder builder, + RuleExpressionVisitor codegenVisitor) { + builder.add("$T.fromString(", EndpointUrl.class); + urlExpr.accept(codegenVisitor); + builder.add(")"); + } + + /** + * Emit a list of expression parts as a concatenated expression. + * + *

If the list is empty, emits an empty string literal. Otherwise, wraps them in a + * {@link StringConcatExpression} and delegates to the code generator's existing concat + * emission logic. + */ + private static void emitConcatExpression(List parts, CodeBlock.Builder builder, + RuleExpressionVisitor codegenVisitor) { + if (parts.isEmpty()) { + builder.add("$S", ""); + return; + } + StringConcatExpression.Builder concatBuilder = StringConcatExpression.builder(); + for (RuleExpression part : parts) { + concatBuilder.addExpression(part); + } + concatBuilder.build().accept(codegenVisitor); + } + + /** + * Scan a literal string segment for port (:{digits}) and path (/) boundaries. + * + *

This method mutates {@code hostParts} and {@code pathParts} as a side effect, appending + * the relevant portions of the literal to each list. On a {@code NOT_PARSEABLE} result, the + * lists may have been partially modified — callers must not reuse the lists after a failure. + */ + private static ScanResult scanLiteral(String literal, + List hostParts, + List pathParts) { + int slashIdx = literal.indexOf('/'); + int portColonIdx = findPortColon(literal); + + if (slashIdx >= 0 && (portColonIdx < 0 || slashIdx < portColonIdx)) { + // Path found before any port in this literal + String hostPart = literal.substring(0, slashIdx); + if (!hostPart.isEmpty()) { + hostParts.add(new LiteralStringExpression(hostPart)); + } + pathParts.add(new LiteralStringExpression(literal.substring(slashIdx))); + return ScanResult.pathFound(); + } + if (portColonIdx >= 0) { + // Port found + String hostPart = literal.substring(0, portColonIdx); + if (!hostPart.isEmpty()) { + hostParts.add(new LiteralStringExpression(hostPart)); + } + String portAndRest = literal.substring(portColonIdx + 1); + int restSlashIdx = portAndRest.indexOf('/'); + int port; + if (restSlashIdx >= 0) { + try { + port = Integer.parseInt(portAndRest.substring(0, restSlashIdx)); + } catch (NumberFormatException e) { + return ScanResult.NOT_PARSEABLE; + } + pathParts.add(new LiteralStringExpression(portAndRest.substring(restSlashIdx))); + return ScanResult.portAndPathFound(port); + } else { + try { + port = Integer.parseInt(portAndRest); + } catch (NumberFormatException e) { + return ScanResult.NOT_PARSEABLE; + } + return ScanResult.portFound(port); + } + } else { + // No port or path — this literal is part of the host + hostParts.add(new LiteralStringExpression(literal)); + return ScanResult.HOST_CONTINUE; + } + } + + /** + * Find the index of a port colon in a literal string. A port colon is a ':' followed by + * one or more digits (optionally followed by '/' or end of string). + */ + private static int findPortColon(String literal) { + int idx = literal.indexOf(':'); + while (idx >= 0) { + int digitStart = idx + 1; + if (digitStart < literal.length() && isDigit(literal.charAt(digitStart))) { + int digitEnd = digitStart; + while (digitEnd < literal.length() && isDigit(literal.charAt(digitEnd))) { + digitEnd++; + } + if (digitEnd == literal.length() || literal.charAt(digitEnd) == '/') { + return idx; + } + } + idx = literal.indexOf(':', idx + 1); + } + return -1; + } + + private static boolean isDigit(char c) { + return c >= '0' && c <= '9'; + } + + /** + * Internal result type for the literal scanning step. + */ + private static final class ScanResult { + private static final ScanResult NOT_PARSEABLE = new ScanResult(false, false, false, -1); + private static final ScanResult HOST_CONTINUE = new ScanResult(true, false, false, -1); + + private final boolean parseable; + private final boolean foundPort; + private final boolean foundPath; + private final int port; + + private ScanResult(boolean parseable, boolean foundPort, boolean foundPath, int port) { + this.parseable = parseable; + this.foundPort = foundPort; + this.foundPath = foundPath; + this.port = port; + } + + static ScanResult pathFound() { + return new ScanResult(true, false, true, -1); + } + + static ScanResult portFound(int port) { + return new ScanResult(true, true, false, port); + } + + static ScanResult portAndPathFound(int port) { + return new ScanResult(true, true, true, port); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ErrorExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ErrorExpression.java similarity index 97% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ErrorExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ErrorExpression.java index 7394adaf6637..8fe8aaddee81 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ErrorExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ErrorExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParser.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParser.java similarity index 93% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParser.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParser.java index 189a8bb63cf0..a73aca7fd0a0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParser.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParser.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.core.TreeNode; @@ -301,7 +301,7 @@ private static RuleExpression getAttrExpression(List argv) { } TreeNode argv0 = argv.get(0); TreeNode argv1 = argv.get(1); - RuleExpression variable = getReference(argv0); + RuleExpression variable = parseExpressionFrom(argv0); TreeNode nameNode = argv1; if (!(nameNode instanceof JrsString)) { throw new IllegalArgumentException("expecting node to be string, got instead starting token: " + nameNode.asToken()); @@ -325,6 +325,22 @@ private static RuleExpression getAttrExpression(List argv) { tokenizer.expectAtEof("indexed access"); return indexedAccessBuilder.build(); } + if (tokenizer.isDirectNegativeIndexedAccess()) { + IndexedAccessExpression.Builder indexedAccessBuilder = IndexedAccessExpression.builder(); + tokenizer.consumeDirectNegativeIndexed(i -> indexedAccessBuilder + .source(memberAccessBuilder.directIndex(true).build()) + .index(i) + .build()); + tokenizer.expectAtEof("negative indexed access"); + return indexedAccessBuilder.build(); + } + if (tokenizer.isNegativeIndexedAccess()) { + IndexedAccessExpression.Builder indexedAccessBuilder = IndexedAccessExpression.builder(); + tokenizer.consumeNegativeIndexed((n, i) -> indexedAccessBuilder.source(memberAccessBuilder.name(n).build()) + .index(i)); + tokenizer.expectAtEof("negative indexed access"); + return indexedAccessBuilder.build(); + } if (tokenizer.isIdentifier()) { tokenizer.consumeIdentifier(memberAccessBuilder::name); tokenizer.expectAtEof("member access"); @@ -335,15 +351,6 @@ private static RuleExpression getAttrExpression(List argv) { tokenizer.peek())); } - private static RuleExpression getReference(TreeNode node) { - if (!node.isObject()) { - throw new IllegalArgumentException("expecting reference object, got instead: " + node); - } - JrsObject obj = (JrsObject) node; - String reference = obj.get("ref").asText(); - return new VariableReferenceExpression(reference); - } - public static PropertiesExpression parsePropertiesExpression(JrsObject object) { PropertiesExpression.Builder builder = PropertiesExpression.builder(); Iterator fieldsIterator = object.fieldNames(); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/FunctionCallExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/FunctionCallExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/FunctionCallExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/FunctionCallExpression.java index fba584cb68a9..e70d505cdc08 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/FunctionCallExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/FunctionCallExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/HeadersExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/HeadersExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/HeadersExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/HeadersExpression.java index 426d4137b726..d867832701d2 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/HeadersExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/HeadersExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/IndexedAccessExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/IndexedAccessExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/IndexedAccessExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/IndexedAccessExpression.java index 6521f242658f..04d77a4baff3 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/IndexedAccessExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/IndexedAccessExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; import software.amazon.awssdk.utils.Validate; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGenerator.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGenerator.java new file mode 100644 index 000000000000..6f9f0f64366b --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGenerator.java @@ -0,0 +1,700 @@ +/* + * 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.codegen.poet.rules; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.NameAllocator; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeName; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import software.amazon.awssdk.codegen.internal.Utils; +import software.amazon.awssdk.codegen.jmespath.component.AndExpression; +import software.amazon.awssdk.codegen.jmespath.component.BracketSpecifier; +import software.amazon.awssdk.codegen.jmespath.component.BracketSpecifierWithContents; +import software.amazon.awssdk.codegen.jmespath.component.BracketSpecifierWithQuestionMark; +import software.amazon.awssdk.codegen.jmespath.component.BracketSpecifierWithoutContents; +import software.amazon.awssdk.codegen.jmespath.component.ComparatorExpression; +import software.amazon.awssdk.codegen.jmespath.component.CurrentNode; +import software.amazon.awssdk.codegen.jmespath.component.Expression; +import software.amazon.awssdk.codegen.jmespath.component.ExpressionType; +import software.amazon.awssdk.codegen.jmespath.component.FunctionArg; +import software.amazon.awssdk.codegen.jmespath.component.FunctionExpression; +import software.amazon.awssdk.codegen.jmespath.component.IndexExpression; +import software.amazon.awssdk.codegen.jmespath.component.Literal; +import software.amazon.awssdk.codegen.jmespath.component.MultiSelectHash; +import software.amazon.awssdk.codegen.jmespath.component.MultiSelectList; +import software.amazon.awssdk.codegen.jmespath.component.NotExpression; +import software.amazon.awssdk.codegen.jmespath.component.OrExpression; +import software.amazon.awssdk.codegen.jmespath.component.ParenExpression; +import software.amazon.awssdk.codegen.jmespath.component.PipeExpression; +import software.amazon.awssdk.codegen.jmespath.component.SliceExpression; +import software.amazon.awssdk.codegen.jmespath.component.SubExpression; +import software.amazon.awssdk.codegen.jmespath.component.SubExpressionRight; +import software.amazon.awssdk.codegen.jmespath.component.WildcardExpression; +import software.amazon.awssdk.codegen.jmespath.parser.JmesPathParser; +import software.amazon.awssdk.codegen.jmespath.parser.JmesPathVisitor; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.MemberModel; +import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; +import software.amazon.awssdk.codegen.poet.model.TypeProvider; + +/** + * Generates direct getter bindings for a validated subset of endpoint operation-context JMESPath expressions. + * Expressions outside the subset throw {@link UnsupportedLoweringException} before code is emitted. + */ +final class JmesPathTypedGetterGenerator { + + /** + * Signals that an expression cannot be lowered and the caller should fall back to the reflective runtime. A + * dedicated type so that the fallback catch cannot mask an unexpected exception from a genuine codegen bug. + */ + static final class UnsupportedLoweringException extends RuntimeException { + UnsupportedLoweringException(String message) { + super(message); + } + } + + private static final TypeName STRING_TYPE = ClassName.get(String.class); + private static final TypeName BOOLEAN_TYPE = ClassName.get(Boolean.class); + + private final IntermediateModel model; + private final TypeProvider typeProvider; + + JmesPathTypedGetterGenerator(IntermediateModel model) { + this.model = model; + this.typeProvider = new TypeProvider(model); + } + + NameAllocator newNameAllocator() { + NameAllocator names = new NameAllocator(); + names.newName("params"); + names.newName("request"); + names.newName("input"); + return names; + } + + CodeBlock lower(ShapeModel inputShape, String jmesPath, String terminalType, String setterName) { + return lower(inputShape, jmesPath, terminalType, setterName, newNameAllocator()); + } + + CodeBlock lower(ShapeModel inputShape, String jmesPath, String terminalType, String setterName, NameAllocator names) { + String normalizedTerminalType = terminalType == null ? "" : terminalType.toLowerCase(Locale.US); + if (!"string".equals(normalizedTerminalType) + && !"boolean".equals(normalizedTerminalType) + && !"stringarray".equals(normalizedTerminalType)) { + throw new UnsupportedLoweringException("Unsupported endpoint parameter type for " + setterName); + } + + List steps = new StepCollector().collect(JmesPathParser.parse(jmesPath)); + boolean listTerminal = "stringarray".equals(normalizedTerminalType); + + if (steps.size() == 1 && steps.get(0) instanceof KeysStep) { + if (!listTerminal) { + throw new UnsupportedLoweringException("keys() result can only bind a stringarray parameter"); + } + List argument = ((KeysStep) steps.get(0)).arg; + validateKeys(inputShape, argument); + return emitKeys(inputShape, argument, setterName, names); + } + if (steps.stream().anyMatch(s -> s instanceof KeysStep)) { + throw new UnsupportedLoweringException("keys() is only supported as the top-level expression"); + } + + int projectionIndex = indexOfProjection(steps); + if (projectionIndex < 0) { + if (listTerminal) { + throw new UnsupportedLoweringException("List parameter requires a projection or keys()"); + } + List fields = fieldNames(steps); + MemberModel leaf = resolvePath(inputShape, fields); + validateScalarTerminal(leaf, normalizedTerminalType); + return emitScalarPath(inputShape, fields, setterName, names); + } + + if (!listTerminal) { + throw new UnsupportedLoweringException("Projection result can only bind a stringarray parameter"); + } + ProjectionParts parts = projectionParts(steps, projectionIndex); + validateProjection(inputShape, parts); + return emitProjection(inputShape, parts, setterName, names); + } + + private ShapeModel targetShape(MemberModel member) { + if (member.getShape() != null) { + return member.getShape(); + } + return model.getShapes().get(member.getC2jShape()); + } + + private CodeBlock emitKeys(ShapeModel inputShape, List argSteps, String setterName, NameAllocator names) { + List fields = fieldNames(argSteps); + CodeBlock.Builder b = CodeBlock.builder(); + + TypeName resultType = ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(String.class)); + String resultVar = names.newName(setterName); + // If the prefix is guarded, the loop may never run: seed the result the reflective runtime returns for a + // null prefix, which for keys() is a mutable empty list (a null projection prefix yields an immutable one). + boolean prefixGuarded = fields.size() > 1; + if (prefixGuarded) { + b.addStatement("$T $N = new $T<>()", resultType, resultVar, ClassName.get(ArrayList.class)); + } + + Walk walk = walkToLast(b, names, inputShape, fields); + String mapVar = names.newName(baseName(walk.lastMember)); + b.addStatement("$T $N = $L", typeProvider.returnType(walk.lastMember), mapVar, + accessLast(walk, walk.lastMember)); + if (prefixGuarded) { + b.addStatement("$N = new $T<>($N.size())", resultVar, ClassName.get(ArrayList.class), mapVar); + } else { + b.addStatement("$T $N = new $T<>($N.size())", resultType, resultVar, ClassName.get(ArrayList.class), mapVar); + } + String keyVar = names.newName("key"); + b.beginControlFlow("for ($T $N : $N.keySet())", String.class, keyVar, mapVar); + b.beginControlFlow("if ($N != null)", keyVar); + b.addStatement("$N.add($N)", resultVar, keyVar); + b.endControlFlow(); + b.endControlFlow(); + for (int i = 0; i < walk.openedGuards; i++) { + b.endControlFlow(); + } + b.addStatement("params.$N($N)", setterName, resultVar); + return b.build(); + } + + private CodeBlock emitScalarPath(ShapeModel inputShape, List fields, String setterName, + NameAllocator names) { + CodeBlock.Builder b = CodeBlock.builder(); + CodeBlock value = scalarChain(b, names, inputShape, fields); + b.addStatement("params.$N($L)", setterName, value); + return b.build(); + } + + private CodeBlock emitProjection(ShapeModel inputShape, ProjectionParts parts, + String setterName, NameAllocator names) { + CodeBlock.Builder b = CodeBlock.builder(); + TypeName listElementType = ParameterizedTypeName.get(ClassName.get(List.class), ClassName.get(String.class)); + String resultVar = names.newName(setterName); + // walkToLast guards every prefix field but the last, so a single-field prefix always reaches the loop. If the + // prefix is guarded, seed the immutable empty list that the reflective runtime's stringValues() returns for a + // null prefix. + boolean prefixGuarded = parts.prefix.size() > 1; + if (prefixGuarded) { + b.addStatement("$T $N = $T.emptyList()", listElementType, resultVar, ClassName.get(Collections.class)); + } + + Walk walk = walkToLast(b, names, inputShape, parts.prefix); + MemberModel listMember = walk.lastMember; + String listVar = names.newName(baseName(listMember)); + b.addStatement("$T $N = $L", typeProvider.returnType(listMember), listVar, accessLast(walk, listMember)); + // Presizing to the source list size avoids growth in the common one-result-per-element case and reduces + // growth for multiselects; null filtering can leave the result smaller. + if (prefixGuarded) { + b.addStatement("$N = new $T<>($N.size())", resultVar, ClassName.get(ArrayList.class), listVar); + } else { + b.addStatement("$T $N = new $T<>($N.size())", listElementType, resultVar, ClassName.get(ArrayList.class), + listVar); + } + MemberModel elementMember = listMember.getListModel().getListMemberModel(); + ShapeModel elementShape = targetShape(elementMember); + TypeName elementType = typeProvider.returnType(elementMember); + String elementVar = names.newName(elementBaseName(elementMember)); + + b.beginControlFlow("for ($T $N : $N)", elementType, elementVar, listVar); + b.beginControlFlow("if ($N != null)", elementVar); + if (parts.isMultiSelect()) { + for (List branch : parts.multiSelect().branches) { + emitLeafAppend(b, names, elementVar, elementShape, fieldNames(branch), resultVar); + } + } else { + emitLeafAppend(b, names, elementVar, elementShape, fieldNames(parts.rest), resultVar); + } + b.endControlFlow(); + b.endControlFlow(); + for (int i = 0; i < walk.openedGuards; i++) { + b.endControlFlow(); + } + b.addStatement("params.$N($N)", setterName, resultVar); + return b.build(); + } + + /** + * Emit a null-guarded walk of {@code fields} starting from {@code startVar} (of {@code startShape}), appending the non-null + * scalar leaf to {@code resultVar}. Opens and closes its own guard blocks (balanced). + */ + private void emitLeafAppend(CodeBlock.Builder b, NameAllocator names, String startVar, ShapeModel startShape, + List fields, String resultVar) { + ShapeModel current = startShape; + String parentVar = startVar; + int opened = 0; + for (int i = 0; i < fields.size() - 1; i++) { + MemberModel m = resolve(current, fields.get(i)); + if (targetShape(m) == null) { + throw new UnsupportedLoweringException("Field path traverses a non-structure member: " + fields.get(i)); + } + String var = names.newName(baseName(m)); + b.addStatement("$T $N = $N.$N()", typeProvider.returnType(m), var, parentVar, m.getFluentGetterMethodName()); + b.beginControlFlow("if ($N != null)", var); + opened++; + parentVar = var; + current = targetShape(m); + } + MemberModel leaf = resolve(current, fields.get(fields.size() - 1)); + String leafVar = names.newName(baseName(leaf)); + b.addStatement("$T $N = $N.$N()", typeProvider.returnType(leaf), leafVar, parentVar, leaf.getFluentGetterMethodName()); + b.beginControlFlow("if ($N != null)", leafVar); + b.addStatement("$N.add($N)", resultVar, leafVar); + b.endControlFlow(); + for (int i = 0; i < opened; i++) { + b.endControlFlow(); + } + } + + private void validateKeys(ShapeModel inputShape, List argument) { + MemberModel mapMember = resolvePath(inputShape, fieldNames(argument)); + if (!mapMember.isMap()) { + throw new UnsupportedLoweringException("keys() argument must resolve to a map"); + } + requireType(mapMember.getMapModel().getKeyModel(), STRING_TYPE, "keys() map key"); + } + + private void validateProjection(ShapeModel inputShape, ProjectionParts parts) { + MemberModel listMember = resolvePath(inputShape, parts.prefix); + if (!listMember.isList()) { + throw new UnsupportedLoweringException("Projection [*] must apply to a list member"); + } + if (parts.rest.isEmpty()) { + throw new UnsupportedLoweringException("Projection must select a scalar field"); + } + + MemberModel elementMember = listMember.getListModel().getListMemberModel(); + ShapeModel elementShape = targetShape(elementMember); + if (parts.isMultiSelect()) { + if (!parts.flatten) { + throw new UnsupportedLoweringException("multi-select-list in a projection must be followed by []"); + } + for (List branch : parts.multiSelect().branches) { + MemberModel leaf = resolvePath(elementShape, fieldNames(branch)); + requireType(leaf, STRING_TYPE, "multi-select-list leaf"); + } + return; + } + if (parts.flatten) { + throw new UnsupportedLoweringException("Flatten is only supported after a multi-select-list"); + } + MemberModel leaf = resolvePath(elementShape, fieldNames(parts.rest)); + requireType(leaf, STRING_TYPE, "projection leaf"); + } + + private void validateScalarTerminal(MemberModel leaf, String terminalType) { + if ("string".equals(terminalType)) { + requireType(leaf, STRING_TYPE, "string terminal"); + } else if ("boolean".equals(terminalType)) { + requireType(leaf, BOOLEAN_TYPE, "boolean terminal"); + } else { + throw new UnsupportedLoweringException("Unsupported scalar endpoint parameter type: " + terminalType); + } + } + + private void requireType(MemberModel member, TypeName expected, String description) { + if (!expected.equals(typeProvider.returnType(member))) { + throw new UnsupportedLoweringException(description + " has incompatible type"); + } + } + + private MemberModel resolvePath(ShapeModel startShape, List fields) { + if (fields.isEmpty()) { + throw new UnsupportedLoweringException("Field path must not be empty"); + } + ShapeModel current = startShape; + MemberModel member = null; + for (int i = 0; i < fields.size(); i++) { + member = resolve(current, fields.get(i)); + if (hasRuntimeDefault(member)) { + throw new UnsupportedLoweringException("Field uses an SdkField runtime default: " + fields.get(i)); + } + if (i < fields.size() - 1) { + current = targetShape(member); + if (current == null) { + throw new UnsupportedLoweringException("Field path traverses a non-structure member: " + fields.get(i)); + } + } + } + return member; + } + + private boolean hasRuntimeDefault(MemberModel member) { + if (member.isIdempotencyToken()) { + return true; + } + if (model.getCustomizationConfig() == null) { + return false; + } + Map defaults = model.getCustomizationConfig().getModelMarshallerDefaultValueSupplier(); + return defaults != null && defaults.containsKey(member.getC2jName()); + } + + /** + * Walk a scalar field path, emitting a null-guarded local per intermediate hop as a ternary (never an {@code if} block, so + * the setter is still invoked with {@code null} when the path breaks, matching the reflective runtime). Returns a null-safe + * expression yielding the final member's value. + */ + private CodeBlock scalarChain(CodeBlock.Builder b, NameAllocator names, ShapeModel inputShape, List fields) { + ShapeModel current = inputShape; + String prevVar = null; + for (int i = 0; i < fields.size() - 1; i++) { + MemberModel m = resolve(current, fields.get(i)); + if (targetShape(m) == null) { + throw new UnsupportedLoweringException("Field path traverses a non-structure member: " + fields.get(i)); + } + String var = names.newName(baseName(m)); + if (prevVar == null) { + b.addStatement("$T $N = request.$N()", typeProvider.returnType(m), var, m.getFluentGetterMethodName()); + } else { + b.addStatement("$T $N = $N == null ? null : $N.$N()", typeProvider.returnType(m), var, prevVar, prevVar, + m.getFluentGetterMethodName()); + } + prevVar = var; + current = targetShape(m); + } + MemberModel last = resolve(current, fields.get(fields.size() - 1)); + if (prevVar == null) { + return CodeBlock.of("request.$N()", last.getFluentGetterMethodName()); + } + return CodeBlock.of("$N == null ? null : $N.$N()", prevVar, prevVar, last.getFluentGetterMethodName()); + } + + /** + * Result of walking a field path: the resolved terminal member, the code expression for its parent object, and how many + * guard control-flow blocks were opened (which the caller must close). + */ + private static final class Walk { + private final MemberModel lastMember; + private final CodeBlock parentExpr; + private final int openedGuards; + + private Walk(MemberModel lastMember, CodeBlock parentExpr, int openedGuards) { + this.lastMember = lastMember; + this.parentExpr = parentExpr; + this.openedGuards = openedGuards; + } + } + + /** + * Walk all-but-last fields as null-guarded locals rooted at {@code request}, returning the parent expression from which the + * last field is accessed. Guards are opened with {@code beginControlFlow} and must be closed by the caller. + */ + private Walk walkToLast(CodeBlock.Builder b, NameAllocator names, ShapeModel inputShape, List fields) { + ShapeModel current = inputShape; + CodeBlock parentExpr = CodeBlock.of("request"); + int opened = 0; + for (int i = 0; i < fields.size() - 1; i++) { + MemberModel m = resolve(current, fields.get(i)); + if (targetShape(m) == null) { + throw new UnsupportedLoweringException("Field path traverses a non-structure member: " + fields.get(i)); + } + String var = names.newName(baseName(m)); + b.addStatement("$T $N = $L.$N()", typeProvider.returnType(m), var, parentExpr, m.getFluentGetterMethodName()); + b.beginControlFlow("if ($N != null)", var); + opened++; + parentExpr = CodeBlock.of("$N", var); + current = targetShape(m); + } + MemberModel last = resolve(current, fields.get(fields.size() - 1)); + return new Walk(last, parentExpr, opened); + } + + /** + * Expression reading the walked path's final member from its parent. Safe to consume without a null guard only + * for collection members: generated list and map getters return auto-construct empties, never null. + */ + private CodeBlock accessLast(Walk walk, MemberModel lastMember) { + return CodeBlock.of("$L.$N()", walk.parentExpr, lastMember.getFluentGetterMethodName()); + } + + private MemberModel resolve(ShapeModel shape, String c2jName) { + if (shape == null) { + throw new UnsupportedLoweringException("Cannot resolve '" + c2jName + "' against a non-structure"); + } + MemberModel member = shape.getMemberByC2jName(c2jName); + if (member == null) { + throw new UnsupportedLoweringException("No member '" + c2jName + "' on shape " + shape.getShapeName()); + } + return member; + } + + private String baseName(MemberModel m) { + return m.getVariable().getVariableName(); + } + + private String elementBaseName(MemberModel elementMember) { + ShapeModel shape = targetShape(elementMember); + if (shape != null && shape.getShapeName() != null) { + return Utils.unCapitalize(shape.getShapeName()); + } + return "item"; + } + + private static int indexOfProjection(List steps) { + for (int i = 0; i < steps.size(); i++) { + if (steps.get(i) instanceof ProjectionStep) { + return i; + } + } + return -1; + } + + private static List fieldNames(List steps) { + List names = new ArrayList<>(); + for (Step s : steps) { + if (!(s instanceof FieldStep)) { + throw new UnsupportedLoweringException("Expected a plain field path"); + } + names.add(((FieldStep) s).c2jName); + } + return names; + } + + /** + * The structural decomposition of a projection expression, computed once so that validation and emission cannot + * disagree about the shape they are processing. + */ + private static final class ProjectionParts { + /** Field path before the projection. */ + private final List prefix; + /** Steps applied to each projected element, with a trailing flatten already removed. */ + private final List rest; + private final boolean flatten; + + private ProjectionParts(List prefix, List rest, boolean flatten) { + this.prefix = prefix; + this.rest = rest; + this.flatten = flatten; + } + + private boolean isMultiSelect() { + return rest.size() == 1 && rest.get(0) instanceof MultiSelectStep; + } + + private MultiSelectStep multiSelect() { + return (MultiSelectStep) rest.get(0); + } + } + + private static ProjectionParts projectionParts(List steps, int projectionIndex) { + List prefix = fieldNames(steps.subList(0, projectionIndex)); + List rest = new ArrayList<>(steps.subList(projectionIndex + 1, steps.size())); + boolean flatten = !rest.isEmpty() && rest.get(rest.size() - 1) instanceof FlattenStep; + if (flatten) { + rest.remove(rest.size() - 1); + } + return new ProjectionParts(prefix, rest, flatten); + } + + private interface Step { + } + + private static final class FieldStep implements Step { + private final String c2jName; + + private FieldStep(String c2jName) { + this.c2jName = c2jName; + } + } + + private static final class ProjectionStep implements Step { + } + + private static final class FlattenStep implements Step { + } + + private static final class MultiSelectStep implements Step { + private final List> branches; + + private MultiSelectStep(List> branches) { + this.branches = branches; + } + } + + private static final class KeysStep implements Step { + private final List arg; + + private KeysStep(List arg) { + this.arg = arg; + } + } + + /** + * Flattens the parsed JMESPath AST into a linear {@link Step} list. Any node type outside the supported subset + * throws {@link UnsupportedLoweringException}. + */ + private static final class StepCollector implements JmesPathVisitor { + private final List steps = new ArrayList<>(); + + private List collect(Expression expression) { + expression.visit(this); + return steps; + } + + @Override + public void visitExpression(Expression input) { + input.visit(this); + } + + @Override + public void visitSubExpression(SubExpression input) { + input.leftExpression().visit(this); + visitSubExpressionRight(input.rightSubExpression()); + } + + @Override + public void visitSubExpressionRight(SubExpressionRight input) { + input.visit(this); + } + + @Override + public void visitIndexExpression(IndexExpression input) { + input.expression().ifPresent(e -> e.visit(this)); + input.bracketSpecifier().visit(this); + } + + @Override + public void visitBracketSpecifier(BracketSpecifier input) { + input.visit(this); + } + + @Override + public void visitBracketSpecifierWithContents(BracketSpecifierWithContents input) { + if (input.isWildcardExpression()) { + steps.add(new ProjectionStep()); + } else if (input.isMultiSelectList()) { + visitMultiSelectList(input.asMultiSelectList()); + } else { + throw new UnsupportedLoweringException("Unsupported bracket specifier"); + } + } + + @Override + public void visitBracketSpecifierWithoutContents(BracketSpecifierWithoutContents input) { + steps.add(new FlattenStep()); + } + + @Override + public void visitBracketSpecifierWithQuestionMark(BracketSpecifierWithQuestionMark input) { + throw new UnsupportedLoweringException("Filter expressions are not supported"); + } + + @Override + public void visitWildcardExpression(WildcardExpression input) { + steps.add(new ProjectionStep()); + } + + @Override + public void visitMultiSelectList(MultiSelectList input) { + List> branches = new ArrayList<>(); + for (Expression expression : input.expressions()) { + branches.add(new StepCollector().collect(expression)); + } + steps.add(new MultiSelectStep(branches)); + } + + @Override + public void visitFunctionExpression(FunctionExpression input) { + if (!"keys".equals(input.function())) { + throw new UnsupportedLoweringException("Unsupported function: " + input.function()); + } + List args = input.functionArgs(); + if (args.size() != 1 || !args.get(0).isExpression()) { + throw new UnsupportedLoweringException("keys() requires a single expression argument"); + } + steps.add(new KeysStep(new StepCollector().collect(args.get(0).asExpression()))); + } + + @Override + public void visitIdentifier(String input) { + steps.add(new FieldStep(input)); + } + + @Override + public void visitSliceExpression(SliceExpression input) { + throw new UnsupportedLoweringException("slice expression is not supported"); + } + + @Override + public void visitComparatorExpression(ComparatorExpression input) { + throw new UnsupportedLoweringException("comparator expression is not supported"); + } + + @Override + public void visitOrExpression(OrExpression input) { + throw new UnsupportedLoweringException("or expression is not supported"); + } + + @Override + public void visitAndExpression(AndExpression input) { + throw new UnsupportedLoweringException("and expression is not supported"); + } + + @Override + public void visitNotExpression(NotExpression input) { + throw new UnsupportedLoweringException("not expression is not supported"); + } + + @Override + public void visitParenExpression(ParenExpression input) { + throw new UnsupportedLoweringException("paren expression is not supported"); + } + + @Override + public void visitMultiSelectHash(MultiSelectHash input) { + throw new UnsupportedLoweringException("multi select hash is not supported"); + } + + @Override + public void visitExpressionType(ExpressionType input) { + throw new UnsupportedLoweringException("expression type is not supported"); + } + + @Override + public void visitPipeExpression(PipeExpression input) { + throw new UnsupportedLoweringException("pipe expression is not supported"); + } + + @Override + public void visitCurrentNode(CurrentNode input) { + throw new UnsupportedLoweringException("current node is not supported"); + } + + @Override + public void visitRawString(String input) { + throw new UnsupportedLoweringException("raw string is not supported"); + } + + @Override + public void visitLiteral(Literal input) { + throw new UnsupportedLoweringException("literal is not supported"); + } + + @Override + public void visitNumber(int input) { + throw new UnsupportedLoweringException("number is not supported"); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LetExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LetExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LetExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LetExpression.java index d812ce095681..571a79dcb826 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LetExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LetExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ListExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ListExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ListExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ListExpression.java index 5d8bb9d87ef4..5284a9c784ec 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/ListExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/ListExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralBooleanExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralBooleanExpression.java similarity index 97% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralBooleanExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralBooleanExpression.java index e87228a78445..9858a2b42ddc 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralBooleanExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralBooleanExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Represents a literal boolean value. E.g., {@code true} or {@code false}. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralIntegerExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralIntegerExpression.java similarity index 97% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralIntegerExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralIntegerExpression.java index 439c4a1eaf69..a4a4969a43f9 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralIntegerExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralIntegerExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Represents a literal integer value. E.g., {@code 123}. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralStringExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralStringExpression.java similarity index 97% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralStringExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralStringExpression.java index 253d79e3c18b..b8cd93389e74 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/LiteralStringExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/LiteralStringExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Represents a literal string value. E.g., {@code "accesspoint"}. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MemberAccessExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MemberAccessExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MemberAccessExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MemberAccessExpression.java index 0c14a2e99264..6192f0b22a33 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MemberAccessExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MemberAccessExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; import software.amazon.awssdk.utils.Validate; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MethodCallExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MethodCallExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MethodCallExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MethodCallExpression.java index e54f6d7e509d..25c27a2a5241 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/MethodCallExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/MethodCallExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PrepareForCodegenVisitor.java similarity index 99% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PrepareForCodegenVisitor.java index a453812bd5a0..ce90249b707e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PrepareForCodegenVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PrepareForCodegenVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.List; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PropertiesExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PropertiesExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PropertiesExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PropertiesExpression.java index a40882aa0322..1eb914d3416b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/PropertiesExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/PropertiesExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RenameForCodegenVisitor.java similarity index 83% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RenameForCodegenVisitor.java index 1c09b51c398a..8561a766d31d 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RenameForCodegenVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RenameForCodegenVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import software.amazon.awssdk.codegen.internal.Utils; import software.amazon.awssdk.utils.internal.CodegenNamingUtils; @@ -35,9 +35,9 @@ public RenameForCodegenVisitor(SymbolTable symbolTable) { * Returns the new symbol table with the renamed symbols. */ public SymbolTable symbolTable() { - String regionParamName = symbolTable.regionParamName(); - if (regionParamName != null) { - renames.regionParamName(javaName(regionParamName)); + // Carry over region params with their renamed java names + for (String regionParam : symbolTable.regionParams()) { + renames.addRegionParam(javaName(regionParam)); } return renames.build(); } @@ -58,11 +58,14 @@ public RuleExpression visitVariableReferenceExpression(VariableReferenceExpressi RuleType type = symbolTable.paramType(name); String newName = javaName(name); renames.putParam(newName, type); + // Region params return a Region object in Java but the rules use it as a String. + // Access the "{name}Id" method which returns the region ID as a String (null-safe). + String accessorName = symbolTable.isRegionParam(name) ? newName + "Id" : newName; return MemberAccessExpression .builder() .type(e.type()) .source(VariableReferenceExpression.builder().variableName("params").build()) - .name(newName) + .name(accessorName) .build(); } return e; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RewriteRuleExpressionVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RewriteRuleExpressionVisitor.java similarity index 99% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RewriteRuleExpressionVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RewriteRuleExpressionVisitor.java index c43e295c471e..9f76cdda0701 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RewriteRuleExpressionVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RewriteRuleExpressionVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpression.java similarity index 96% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpression.java index 475bbb366b6b..cae3f2b2f367 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Represents an expression within an endpoint rules set, either explicit or synthetically created for codegen. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpressionVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpressionVisitor.java similarity index 97% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpressionVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpressionVisitor.java index 61d64ff4e647..907ddc800ec0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleExpressionVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleExpressionVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; /** * Visitor for all the expressions defined in the endpoints rule sets. diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleFunctionMirror.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleFunctionMirror.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleFunctionMirror.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleFunctionMirror.java index 5578173275ee..2de2050e899f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleFunctionMirror.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleFunctionMirror.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Collections; import java.util.LinkedHashMap; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleRuntimeTypeMirror.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleRuntimeTypeMirror.java similarity index 79% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleRuntimeTypeMirror.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleRuntimeTypeMirror.java index ff42af43d8f4..f4676ce03d3b 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleRuntimeTypeMirror.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleRuntimeTypeMirror.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.TypeName; @@ -49,6 +49,13 @@ public final class RuleRuntimeTypeMirror { .addTypeParam(ClassName.get(String.class)) .ruleTypeParam(STRING) .build(); + + /** + * Registry name of the synthetic {@code substringEquals} function emitted by the BDD peephole + * pass. Prefixed with {@code __} so it cannot collide with a rules standard library function. + */ + public static final String SUBSTRING_EQUALS_FN = "__substringEquals"; + private static final String URL_TYPE_NAME = "Url"; private static final String PARTITION_TYPE_NAME = "Partition"; private static final String ARN_TYPE_NAME = "Arn"; @@ -133,6 +140,20 @@ static List builtInFunctions(Map types) { .addArgument("reverse", BOOLEAN) .containingType(containingType) .build(), + // Synthetic. Not a rules standard library function; BddPeepholeVisitor rewrites + // stringEquals(coalesce(substring(...), ""), literal) into this to avoid allocating the + // intermediate substring. The "__" prefix cannot collide with a spec function name. + RuleFunctionMirror + .builder(SUBSTRING_EQUALS_FN) + .javaName("substringEquals") + .returns(BOOLEAN) + .addArgument("value", STRING) + .addArgument("startIdx", INTEGER) + .addArgument("stopIdx", INTEGER) + .addArgument("reverse", BOOLEAN) + .addArgument("literal", STRING) + .containingType(containingType) + .build(), RuleFunctionMirror .builder("stringEquals") .returns(BOOLEAN) @@ -192,10 +213,34 @@ static List builtInFunctions(Map types) { // still does the trick for codegen. RuleFunctionMirror .builder("listAccess") - .returns(BOOLEAN) + .returns(STRING) .addArgument("value", LIST_OF_STRING) .addArgument("index", INTEGER) .containingType(containingType) + .build(), + RuleFunctionMirror + .builder("split") + .returns(LIST_OF_STRING) + .addArgument("value", STRING) + .addArgument("delimiter", STRING) + .addArgument("limit", INTEGER) + .containingType(containingType) + .build(), + RuleFunctionMirror + .builder("ite") + .returns(STRING) + .addArgument("condition", BOOLEAN) + .addArgument("ifTrue", STRING) + .addArgument("ifFalse", STRING) + .containingType(containingType) + .build(), + // coalesce is variadic and generic (return type mirrors type of arguments) + RuleFunctionMirror + .builder("coalesce") + .returns(VOID) // generic, but we must provide a type + .addArgument("value1", VOID) // variadic and generic, but add 2 generic args + .addArgument("value2", VOID) + .containingType(containingType) .build() ); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetCreationSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetCreationSpec.java deleted file mode 100644 index 9ba974d74b28..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetCreationSpec.java +++ /dev/null @@ -1,431 +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.codegen.poet.rules; - -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.jr.stree.JrsArray; -import com.fasterxml.jackson.jr.stree.JrsBoolean; -import com.fasterxml.jackson.jr.stree.JrsNumber; -import com.fasterxml.jackson.jr.stree.JrsObject; -import com.fasterxml.jackson.jr.stree.JrsString; -import com.fasterxml.jackson.jr.stree.JrsValue; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.lang.model.element.Modifier; -import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.ConditionModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterDeprecatedModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; -import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; -import software.amazon.awssdk.utils.MapUtils; - -public class RuleSetCreationSpec { - private static final String RULE_METHOD_PREFIX = "endpointRule_"; - - private final EndpointRulesSpecUtils endpointRulesSpecUtils; - private final EndpointRuleSetModel ruleSetModel; - - private int ruleCounter = 0; - - private final List helperMethods = new ArrayList<>(); - - public RuleSetCreationSpec(IntermediateModel intermediateModel) { - this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel); - this.ruleSetModel = intermediateModel.getEndpointRuleSetModel(); - } - - public CodeBlock ruleSetCreationExpr() { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("EndpointRuleset")) - .add(".version($S)", ruleSetModel.getVersion()) - .add(".serviceId($S)", ruleSetModel.getServiceId()) - .add(".parameters($L)", parameters(ruleSetModel.getParameters())); - - ruleSetModel.getRules().stream() - .map(this::rule) - .forEach(m -> b.add(".addRule($N())", m.name)); - - b.add(".build()"); - return b.build(); - } - - public List helperMethods() { - return helperMethods; - } - - private CodeBlock parameters(Map params) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("Parameters")); - - params.forEach((name, model) -> { - b.add(".addParameter($L)", parameter(name, model)); - }); - - b.add(".build()"); - - return b.build(); - } - - private CodeBlock parameter(String name, ParameterModel model) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("Parameter")) - .add(".name($S)", name) - .add(".type($T.fromValue($S))", endpointRulesSpecUtils.rulesRuntimeClassName("ParameterType"), model.getType()) - .add(".required($L)", Boolean.TRUE.equals(model.isRequired())); - - if (model.getBuiltIn() != null) { - b.add(".builtIn($S)", model.getBuiltIn()); - } - - if (model.getDocumentation() != null) { - b.add(".documentation($S)", model.getDocumentation()); - } - - if (model.getDefault() != null) { - TreeNode defaultValue = model.getDefault(); - JsonToken token = defaultValue.asToken(); - CodeBlock value; - if (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE) { - value = endpointRulesSpecUtils.valueCreationCode("boolean", - CodeBlock.builder() - .add("$L", ((JrsBoolean) defaultValue).booleanValue()) - .build()); - } else if (token == JsonToken.VALUE_STRING) { - value = endpointRulesSpecUtils.valueCreationCode("string", - CodeBlock.builder() - .add("$S", ((JrsString) defaultValue).getValue()) - .build()); - } else if (token == JsonToken.START_ARRAY) { - validateStringArrayType(model); - value = endpointRulesSpecUtils.valueCreationCode("stringarray", - buildStringArrayDefaultValue((JrsArray) defaultValue)); - } else { - throw new RuntimeException("Can't set default value type " + token.name()); - } - b.add(".defaultValue($L)", value); - } - - if (model.getDeprecated() != null) { - ParameterDeprecatedModel deprecated = model.getDeprecated(); - b.add(".deprecated(new $T($S, $S))", - endpointRulesSpecUtils.rulesRuntimeClassName("Parameter.Deprecated"), - deprecated.getMessage(), - deprecated.getSince()); - } - - b.add(".build()"); - - return b.build(); - } - - private MethodSpec rule(RuleModel model) { - MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(nextRuleMethodName()); - - methodBuilder.addModifiers(Modifier.PRIVATE, Modifier.STATIC); - methodBuilder.returns(endpointRulesSpecUtils.rulesRuntimeClassName("Rule")); - - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("Rule")); - - model.getConditions().forEach(c -> b.add(".addCondition($L)", condition(c))); - - if ("error".equals(model.getType())) { - b.add(".error($S)", model.getError()); - } else if ("tree".equals(model.getType())) { - CodeBlock.Builder rulesArray = CodeBlock.builder() - .add("$T.asList(", Arrays.class); - - int nRules = model.getRules().size(); - for (int i = 0; i < nRules; ++i) { - MethodSpec childRule = rule(model.getRules().get(i)); - rulesArray.add("$N()", childRule.name); - if (i + 1 < nRules) { - rulesArray.add(", "); - } - } - rulesArray.add(")"); - - b.add(".treeRule($L)", rulesArray.build()); - } else if ("endpoint".equals(model.getType())) { - CodeBlock endpoint = endpoint(model.getEndpoint()); - b.add(".endpoint($L)", endpoint); - } - - MethodSpec m = methodBuilder.addStatement("return $L", b.build()).build(); - - helperMethods.add(m); - - return m; - } - - private CodeBlock endpoint(EndpointModel model) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("EndpointResult")); - - TreeNode url = model.getUrl(); - b.add(".url($L)", expr(url)); - - if (model.getHeaders() != null) { - model.getHeaders().forEach((name, valueList) -> { - valueList.forEach(value -> b.add(".addHeaderValue($S, $L)", name, expr(value))); - }); - } - - if (model.getProperties() != null) { - // Explicitly only support known properties - model.getProperties().forEach((name, property) -> { - switch (name) { - case "authSchemes": - b.add(".addProperty($T.of($S), $T.fromTuple($T.asList(", - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - "authSchemes", - endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - Arrays.class); - - Iterator authSchemesIter = ((JrsArray) property).elements(); - - while (authSchemesIter.hasNext()) { - b.add("$T.fromRecord($T.of(", endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - MapUtils.class); - JrsObject authScheme = (JrsObject) authSchemesIter.next(); - - Iterator authSchemeFieldsIter = authScheme.fieldNames(); - while (authSchemeFieldsIter.hasNext()) { - String schemeProp = authSchemeFieldsIter.next(); - JrsValue propValue = authScheme.get(schemeProp); - b.add("$T.of($S), ", endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), schemeProp); - if ("signingRegionSet".equalsIgnoreCase(schemeProp)) { - b.add("$T.fromTuple($T.asList(", endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - Arrays.class); - Iterator signingRegions = ((JrsArray) propValue).elements(); - - while (signingRegions.hasNext()) { - JrsString region = (JrsString) signingRegions.next(); - b.add("$T.fromStr($S)", endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - region.getValue()); - - if (signingRegions.hasNext()) { - b.add(", "); - } - } - b.add("))"); - } else if ("disableDoubleEncoding".equalsIgnoreCase(schemeProp)) { - b.add("$T.fromBool($L)", endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - ((JrsBoolean) propValue).booleanValue()); - } else { - b.add("$T.fromStr($S)", endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - ((JrsString) propValue).getValue()); - } - - if (authSchemeFieldsIter.hasNext()) { - b.add(", "); - } - } - - b.add("))"); - - if (authSchemesIter.hasNext()) { - b.add(", "); - } - } - b.add(")))"); - - break; - case "bucketType": - b.add(".addProperty($T.of($S), $T.fromStr($S))", - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - "bucketType", - endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - ((JrsString) property).getValue()); - break; - case "useS3ExpressSessionAuth": - b.add(".addProperty($T.of($S), $T.fromBool($L))", - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - "useS3ExpressSessionAuth", - endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - ((JrsBoolean) property).booleanValue()); - break; - case "backend": - b.add(".addProperty($T.of($S), $T.fromStr($S))", - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - "backend", - endpointRulesSpecUtils.rulesRuntimeClassName("Literal"), - ((JrsString) property).getValue()); - break; - default: - break; - } - }); - } - - b.add(".build()"); - return b.build(); - } - - private CodeBlock condition(ConditionModel model) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("Condition")) - .add(".fn($L.validate())", fnNode(model)); - - if (model.getAssign() != null) { - b.add(".result($S)", model.getAssign()); - } - - b.add(".build()"); - - return b.build(); - } - - private CodeBlock fnNode(ConditionModel model) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("FnNode")) - .add(".fn($S)", model.getFn()) - .add(".argv($T.asList(", Arrays.class); - - List args = model.getArgv(); - for (int i = 0; i < args.size(); ++i) { - b.add("$L", expr(args.get(i))); - if (i + 1 < args.size()) { - b.add(","); - } - } - b.add("))"); - - b.add(".build()"); - - return b.build(); - } - - private CodeBlock expr(TreeNode n) { - if (n.isValueNode()) { - return valueExpr((JrsValue) n); - } - - if (n.isObject()) { - return objectExpr((JrsObject) n); - } - - throw new RuntimeException("Don't know how to create expression from " + n); - } - - private CodeBlock valueExpr(JrsValue n) { - CodeBlock.Builder b = CodeBlock.builder(); - - b.add("$T.of(", endpointRulesSpecUtils.rulesRuntimeClassName("Expr")); - JsonToken token = n.asToken(); - switch (token) { - case VALUE_STRING: - b.add("$S", ((JrsString) n).getValue()); - break; - case VALUE_NUMBER_INT: - b.add("$L", ((JrsNumber) n).getValue().intValue()); - break; - case VALUE_TRUE: - case VALUE_FALSE: - b.add("$L", ((JrsBoolean) n).booleanValue()); - break; - default: - throw new RuntimeException("Don't know how to create expression JSON type " + token); - } - - b.add(")"); - - return b.build(); - } - - private CodeBlock objectExpr(JrsObject n) { - CodeBlock.Builder b = CodeBlock.builder(); - - JrsValue ref = n.get("ref"); - JrsValue fn = n.get("fn"); - - if (ref != null) { - b.add("$T.ref($T.of($S))", - endpointRulesSpecUtils.rulesRuntimeClassName("Expr"), - endpointRulesSpecUtils.rulesRuntimeClassName("Identifier"), - ref.asText()); - } else if (fn != null) { - String name = fn.asText(); - CodeBlock.Builder fnNode = CodeBlock.builder(); - fnNode.add("$T.builder()", endpointRulesSpecUtils.rulesRuntimeClassName("FnNode")) - .add(".fn($S)", name); - - JrsArray argv = (JrsArray) n.get("argv"); - - fnNode.add(".argv($T.asList(", Arrays.class); - Iterator iter = argv.elements(); - - while (iter.hasNext()) { - fnNode.add(expr(iter.next())); - - if (iter.hasNext()) { - fnNode.add(","); - } - } - - fnNode.add(")).build().validate()"); - - b.add(fnNode.build()); - } - - return b.build(); - } - - private String nextRuleMethodName() { - String n = String.format("%s%d", RULE_METHOD_PREFIX, ruleCounter); - ruleCounter += 1; - return n; - } - - private static void validateStringArrayType(ParameterModel model) { - if (!"stringarray".equalsIgnoreCase(model.getType())) { - throw new RuntimeException(String.format("Only String array is supported but the type received is %s", - model.getType())); - } - } - - private CodeBlock buildStringArrayDefaultValue(JrsArray defaultValue) { - CodeBlock.Builder builder = CodeBlock.builder(); - Iterator elementValuesIter = defaultValue.elements(); - if (elementValuesIter.hasNext()) { - builder.add("$T.asList(", Arrays.class); - } - while (elementValuesIter.hasNext()) { - JrsValue v = elementValuesIter.next(); - builder.add("\"" + v.asText() + "\""); - if (elementValuesIter.hasNext()) { - builder.add(","); - } - } - builder.add(")"); - return builder.build(); - } -} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetExpression.java similarity index 99% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetExpression.java index 13a3ccafc51b..22c5f541e21f 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleSetExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleSetExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleType.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleType.java similarity index 99% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleType.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleType.java index fd86b78066d3..ed2344107e50 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/RuleType.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/RuleType.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.ParameterizedTypeName; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/StringConcatExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/StringConcatExpression.java similarity index 92% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/StringConcatExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/StringConcatExpression.java index 106f3cc0291a..811216f600af 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/StringConcatExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/StringConcatExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.Collections; @@ -98,6 +98,11 @@ public Builder addExpression(RuleExpression expr) { return this; } + public Builder addExpressions(List expressions) { + this.expressions.addAll(expressions); + return this; + } + public StringConcatExpression build() { return new StringConcatExpression(this); } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/SymbolTable.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/SymbolTable.java new file mode 100644 index 000000000000..a04c73f93d68 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/SymbolTable.java @@ -0,0 +1,125 @@ +/* + * 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.codegen.poet.rules; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import software.amazon.awssdk.utils.Validate; + +public final class SymbolTable { + private final Map params; + private final Map locals; + private final Set regionParams; + + SymbolTable(Builder builder) { + this.params = Collections.unmodifiableMap(new LinkedHashMap<>(builder.params)); + this.locals = Collections.unmodifiableMap(new LinkedHashMap<>(builder.locals)); + this.regionParams = Collections.unmodifiableSet(new HashSet<>(builder.regionParams)); + } + + public static Builder builder() { + return new Builder(); + } + + public boolean isParam(String name) { + return params.containsKey(name); + } + + public RuleType paramType(String name) { + return params.get(name); + } + + public boolean isLocal(String name) { + return locals.containsKey(name); + } + + public RuleType localType(String name) { + return locals.get(name); + } + + public Map locals() { + return locals; + } + + public Map params() { + return params; + } + + /** + * Returns the set of parameter names that are Region-typed in Java (i.e., the Java getter returns {@code Region} + * rather than {@code String}). The codegen needs to append {@code .id()} when accessing these params to convert + * to the String value expected by the endpoint rules. + */ + public Set regionParams() { + return regionParams; + } + + /** + * Returns true if the given parameter name is a Region-typed param that needs {@code .id()} appended. + */ + public boolean isRegionParam(String name) { + return regionParams.contains(name); + } + + public Builder toBuilder() { + return new Builder(this); + } + + public static class Builder { + private final Map params = new LinkedHashMap<>(); + private final Map locals = new LinkedHashMap<>(); + private final Set regionParams = new HashSet<>(); + + public Builder() { + } + + public Builder(SymbolTable table) { + this.params.putAll(table.params); + this.locals.putAll(table.locals); + this.regionParams.addAll(table.regionParams); + } + + public Builder putParam(String name, RuleType type) { + params.put(Validate.paramNotNull(name, "name"), Validate.paramNotNull(type, "type")); + return this; + } + + public RuleType param(String name) { + return params.get(name); + } + + public Builder putLocal(String name, RuleType type) { + locals.put(Validate.paramNotNull(name, "name"), Validate.paramNotNull(type, "type")); + return this; + } + + public RuleType local(String name) { + return locals.get(name); + } + + public Builder addRegionParam(String name) { + regionParams.add(Validate.paramNotNull(name, "name")); + return this; + } + + public SymbolTable build() { + return new SymbolTable(this); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/Tokenizer.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/Tokenizer.java similarity index 83% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/Tokenizer.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/Tokenizer.java index c1f48710c816..0d772717e2db 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/Tokenizer.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/Tokenizer.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.ArrayList; import java.util.List; @@ -37,7 +37,8 @@ private static List tokenize(String source) { List tokens = new ArrayList<>(); TokenizerState state = new TokenizerState(source); do { - Token token = next(state); + Token previous = tokens.isEmpty() ? null : tokens.get(tokens.size() - 1); + Token token = next(state, previous); tokens.add(token); if (token.type == TokenKind.EOF) { break; @@ -46,7 +47,7 @@ private static List tokenize(String source) { return tokens; } - private static Token next(TokenizerState state) { + private static Token next(TokenizerState state, Token previous) { if (!state.hasNext()) { return EOF; } @@ -82,6 +83,13 @@ private static Token next(TokenizerState state) { if (ch == '#') { return new Token(TokenKind.HASH, "#"); } + // Only treat '-' as a distinct token when it opens a negative index, i.e. directly after '[' and followed by a + // digit, as in "[-2]" or "resourceId[-1]". Anywhere else '-' is an ordinary string character (for example + // "s3-fips" or "not a valid host-label"), so it must fall through to string handling to avoid splitting + // literals into extra concatenation terms. + if (ch == '-' && previous != null && previous.type == TokenKind.OPEN_SQUARE && isDigit(state.peek())) { + return new Token(TokenKind.MINUS, "-"); + } if (isDigit(ch)) { return consumeNumber(state, ch); } @@ -224,6 +232,33 @@ public void consumeDirectIndexed(Consumer consumer) { index += 3; } + // e.g., [-2] + public boolean isDirectNegativeIndexedAccess() { + return matches(TokenKind.OPEN_SQUARE, TokenKind.MINUS, TokenKind.NUMBER, TokenKind.CLOSE_SQUARE); + } + + public void consumeDirectNegativeIndexed(Consumer consumer) { + if (!isDirectNegativeIndexedAccess()) { + throw new IllegalStateException("not at direct negative indexed"); + } + consumer.accept(-Integer.parseInt(tokens.get(index + 2).value)); + index += 4; + } + + // e.g., resourceId[-1] + public boolean isNegativeIndexedAccess() { + return matches(TokenKind.IDENTIFIER, TokenKind.OPEN_SQUARE, TokenKind.MINUS, TokenKind.NUMBER, + TokenKind.CLOSE_SQUARE); + } + + public void consumeNegativeIndexed(BiConsumer consumer) { + if (!isNegativeIndexedAccess()) { + throw new IllegalStateException("not at negative indexed"); + } + consumer.accept(tokens.get(index).value, -Integer.parseInt(tokens.get(index + 3).value)); + index += 5; + } + // e.g., {url#scheme} public boolean isNamedAccess() { return matches(TokenKind.OPEN_CURLY, TokenKind.IDENTIFIER, TokenKind.HASH, TokenKind.IDENTIFIER, TokenKind.CLOSE_CURLY); @@ -278,6 +313,7 @@ enum TokenKind { NUMBER, IDENTIFIER, HASH, + MINUS, OPEN_CURLY, CLOSE_CURLY, OPEN_SQUARE, diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/VariableReferenceExpression.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/VariableReferenceExpression.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/VariableReferenceExpression.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/VariableReferenceExpression.java index ab208ac88422..b0311aad0755 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/VariableReferenceExpression.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/VariableReferenceExpression.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Objects; import software.amazon.awssdk.utils.Validate; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/WalkRuleExpressionVisitor.java similarity index 98% rename from codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java rename to codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/WalkRuleExpressionVisitor.java index de952b6d67da..fb164de3fc3e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/WalkRuleExpressionVisitor.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/WalkRuleExpressionVisitor.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import java.util.Collection; import java.util.List; diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/AssignTypeInferringVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/AssignTypeInferringVisitor.java new file mode 100644 index 000000000000..e16f8dfb5756 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/AssignTypeInferringVisitor.java @@ -0,0 +1,180 @@ +/* + * 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.codegen.poet.rules.bdd; + +import java.util.Map; +import software.amazon.awssdk.codegen.poet.rules.BooleanAndExpression; +import software.amazon.awssdk.codegen.poet.rules.BooleanNotExpression; +import software.amazon.awssdk.codegen.poet.rules.EndpointExpression; +import software.amazon.awssdk.codegen.poet.rules.ErrorExpression; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.HeadersExpression; +import software.amazon.awssdk.codegen.poet.rules.IndexedAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.LetExpression; +import software.amazon.awssdk.codegen.poet.rules.ListExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralIntegerExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.MemberAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.MethodCallExpression; +import software.amazon.awssdk.codegen.poet.rules.PropertiesExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpressionVisitor; +import software.amazon.awssdk.codegen.poet.rules.RuleFunctionMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleSetExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleType; +import software.amazon.awssdk.codegen.poet.rules.StringConcatExpression; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; + +public class AssignTypeInferringVisitor implements RuleExpressionVisitor { + private final RuleRuntimeTypeMirror typeMirror; + private final Map registerInfoMap; + + public AssignTypeInferringVisitor(RuleRuntimeTypeMirror typeMirror, Map registerInfoMap) { + this.typeMirror = typeMirror; + this.registerInfoMap = registerInfoMap; + } + + @Override + public RuleType visitLiteralBooleanExpression(LiteralBooleanExpression e) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitLiteralIntegerExpression(LiteralIntegerExpression e) { + return RuleRuntimeTypeMirror.INTEGER; + } + + @Override + public RuleType visitLiteralStringExpression(LiteralStringExpression e) { + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitBooleanNotExpression(BooleanNotExpression e) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitBooleanAndExpression(BooleanAndExpression e) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitFunctionCallExpression(FunctionCallExpression e) { + String fn = e.name(); + if ("not".equals(fn)) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isSet".equals(fn)) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isNotSet".equals(fn)) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + RuleFunctionMirror func = typeMirror.resolveFunction(e.name()); + return func.returns(); + } + + @Override + public RuleType visitMethodCallExpression(MethodCallExpression e) { + throw new IllegalStateException("Unexpected methodCallExpression"); + } + + @Override + public RuleType visitVariableReferenceExpression(VariableReferenceExpression e) { + RuleType type = registerInfoMap.get(e.variableName()).getRuleType(); + if (type == null) { + // visit the assign condition for this + registerInfoMap.get(e.variableName()).getRuleSetExpression().accept(this); + type = registerInfoMap.get(e.variableName()).getRuleType(); + if (type == null) { + throw new IllegalStateException("Unable to infer registry type information for `" + e.variableName() + "`"); + } + } + return type; + } + + @Override + public RuleType visitMemberAccessExpression(MemberAccessExpression e) { + RuleType sourceType = e.source().accept(this); + if (e.directIndex() && e.name() == null) { + return sourceType; + } + return sourceType.property(e.name()); + } + + @Override + public RuleType visitIndexedAccessExpression(IndexedAccessExpression e) { + RuleType sourceType = e.source().accept(this); + return sourceType.ruleTypeParam(); // get the list inner type + } + + @Override + public RuleType visitStringConcatExpression(StringConcatExpression e) { + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitLetExpression(LetExpression e) { + if (e.bindings().size() != 1) { + throw new IllegalStateException("Expected exactly one binding"); + } + for (Map.Entry kvp : e.bindings().entrySet()) { + String k = kvp.getKey(); + RuleExpression v = kvp.getValue(); + RuleType assignedType = v.accept(this); + registerInfoMap.get(k).setRuleType(assignedType); + } + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitRuleSetExpression(RuleSetExpression e) { + if (e.conditions().size() != 1) { + throw new IllegalStateException("Expected exactly one condition"); + } + e.conditions().get(0).accept(this); + return RuleRuntimeTypeMirror.VOID; + } + + @Override + public RuleType visitListExpression(ListExpression e) { + // TODO: this could potentially be another type + return RuleRuntimeTypeMirror.LIST_OF_STRING; + } + + @Override + public RuleType visitEndpointExpression(EndpointExpression e) { + throw new IllegalStateException("Unexpected EndpointExpression"); + } + + @Override + public RuleType visitErrorExpression(ErrorExpression e) { + throw new IllegalStateException("Unexpected ErrorExpression"); + } + + @Override + public RuleType visitPropertiesExpression(PropertiesExpression e) { + throw new IllegalStateException("Unexpected PropertiesExpression"); + } + + @Override + public RuleType visitHeadersExpression(HeadersExpression e) { + throw new IllegalStateException("Unexpected HeadersExpression"); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpec.java new file mode 100644 index 000000000000..b09b18c71484 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpec.java @@ -0,0 +1,992 @@ +/* + * 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.codegen.poet.rules.bdd; + +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.jr.stree.JrsValue; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeName; +import com.squareup.javapoet.TypeSpec; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import javax.lang.model.element.Modifier; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.codegen.model.config.customization.EndpointAuthSchemeConfig; +import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.Metadata; +import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; +import software.amazon.awssdk.codegen.model.rules.endpoints.ConditionModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; +import software.amazon.awssdk.codegen.model.service.ClientContextParam; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; +import software.amazon.awssdk.codegen.poet.rules.ExpressionParser; +import software.amazon.awssdk.codegen.poet.rules.PrepareForCodegenVisitor; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleType; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +/** + * Generates the BDD (binary decision diagram) based endpoint provider using a smithy-java-inspired + * approach: each BDD node is emitted as a {@code nodeP} method that returns {@code Endpoint} + * directly (null for no-match). When a complement edge references a node, a {@code nodeN} + * variant is also emitted with swapped branches (condition true → lowRef, false → highRef). + * Simple conditions (isSet, booleanEquals, stringEquals on plain register references) are inlined + * as ternary expressions. Complex conditions that compute and store values are emitted as separate + * {@code cond()} methods. + * + *

The evaluator is allocated per call (lightweight — just register fields, no maps). The shared + * RulesFunctions helpers it calls are stateless. + */ +public class BddEndpointProviderSpec implements ClassSpec { + /** + * Node references at or above this value denote results; {@code ref - RESULT_OFFSET} is the result index. + * The SEP defines 100_000_000 as the implicit NoMatchRule. The model's results list excludes NoMatchRule, + * so result indices start at 100_000_001 (result 0 in the list). + */ + private static final int RESULT_OFFSET = 100_000_001; + + /** + * The SEP's implicit NoMatchRule reference — indicates no endpoint matched. + */ + private static final int NO_MATCH_RESULT = 100_000_000; + + /** + * A {@code stringArray} cache key parameter longer than this reports a miss without comparing elements, so the cost + * of a cache check cannot grow with the size of the caller's list. + * + *

The cap is a cost bound, not a coverage target. Above it the provider resolves, which is what it would have + * done anyway, so the value trades hit rate against a bounded worst case and can never affect correctness. Four is + * arbitrary but deliberately conservative. + * + *

No shipped service needs this path today. DynamoDB's {@code ResourceArnList} is the only {@code stringArray} + * any shipped rule set declares, and it is read only at index 0, so it is compared by + * {@link #cacheFirstElementsMatchMethod()} with no cap at all. + */ + private static final int MAX_LIST_COMPARISON_SIZE = 4; + + private final IntermediateModel intermediateModel; + private final EndpointBddModel endpointBddModel; + private final EndpointRulesSpecUtils endpointRulesSpecUtils; + private final Map knownEndpointAttributes; + private final RuleRuntimeTypeMirror typeMirror; + private final Map registerInfoMap; + private final ClassName evaluatorType; + private final ClassName cacheEntryType; + private final List bddNodes; + private final List conditionTypes; + private final Map paramUsage; + + public BddEndpointProviderSpec(IntermediateModel intermediateModel) { + this.intermediateModel = intermediateModel; + this.endpointBddModel = intermediateModel.getEndpointBddModel(); + this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel); + String packageName = intermediateModel.getMetadata().getFullInternalEndpointRulesPackageName(); + this.typeMirror = new RuleRuntimeTypeMirror(packageName); + this.knownEndpointAttributes = knownEndpointAttributes(intermediateModel); + this.registerInfoMap = buildRegisterInfoMap(); + this.evaluatorType = className().nestedClass("Evaluator"); + this.cacheEntryType = className().nestedClass("CacheEntry"); + this.bddNodes = endpointBddModel.getDecodedNodes(); + this.conditionTypes = analyzeConditions(); + this.paramUsage = BddParameterReferences.analyze(endpointBddModel); + } + + @Override + public TypeSpec poetSpec() { + TypeSpec.Builder builder = PoetUtils.createClassBuilder(className()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addSuperinterface(endpointRulesSpecUtils.providerInterfaceName()) + .addAnnotation(SdkInternalApi.class); + + builder.addField(cacheField()); + builder.addType(evaluatorClass()); + builder.addType(cacheEntryClass()); + builder.addMethod(resolveEndpointMethod()); + builder.addMethod(cacheParamsMatchMethod()); + if (needsFullListHelper()) { + builder.addMethod(cacheListsMatchMethod()); + } + if (needsFirstElementHelper()) { + builder.addMethod(cacheFirstElementsMatchMethod()); + } + + return builder.build(); + } + + // ---- Single-entry result cache ---- + + /** + * Generates {@code private volatile CacheEntry cache;}. + * + *

One entry, holding the most recent successfully resolved {@code (params, endpoint)} pair. A single entry is + * enough because the overwhelmingly common shape is a client resolving the same endpoint repeatedly: same region, + * same flags, and for most services no request-derived parameters at all. A service whose endpoint genuinely varies + * per request simply misses every time and pays only the key check. + * + *

{@code volatile} is the whole of the synchronisation. Racing threads compute equivalent entries for equal + * params, so a lost write costs one re-resolution and nothing more; {@code CacheEntry} is immutable with final + * fields, so a thread that reads the reference sees fully initialised contents. + */ + private FieldSpec cacheField() { + return FieldSpec.builder(cacheEntryType, "cache") + .addModifiers(Modifier.PRIVATE, Modifier.VOLATILE) + .build(); + } + + /** + * Generates the immutable {@code CacheEntry} holding one {@code (params, endpoint)} snapshot. + * + *

The entry keeps the caller's params object rather than copying it, so it relies on that object and any + * collections it holds being effectively immutable after {@code build()}. Generated params do not copy list values + * ({@code this.resourceArnList = builder.resourceArnList;}), so the assumption is load-bearing rather than + * enforced. + * + *

It holds on every SDK path, because request objects are immutable and the params for a request are built and + * discarded within the call. It is an assumption only for a caller that invokes + * {@code EndpointProvider#resolveEndpoint} directly, retains a list it passed in, and mutates it afterwards: the + * mutation reaches the stored key, and a later call carrying the post-mutation contents can then hit an entry that + * was resolved for the pre-mutation contents. Snapshotting list parameters here would close that off, at the cost + * of an allocation on every miss. + */ + private TypeSpec cacheEntryClass() { + ClassName paramsClass = endpointRulesSpecUtils.parametersClassName(); + return TypeSpec.classBuilder(cacheEntryType) + .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .addField(paramsClass, "params", Modifier.FINAL) + .addField(Endpoint.class, "endpoint", Modifier.FINAL) + .addMethod(MethodSpec.constructorBuilder() + .addParameter(paramsClass, "params") + .addParameter(Endpoint.class, "endpoint") + .addStatement("this.params = params") + .addStatement("this.endpoint = endpoint") + .build()) + .build(); + } + + /** + * Generates {@code cacheParamsMatch(a, b)}: true when the two parameter objects are interchangeable as far as + * endpoint resolution is concerned. + * + *

One uniform {@link Objects#equals} term per parameter, joined with {@code &&} so the chain short-circuits on + * the first mismatch. {@code Objects.equals} tries identity before {@code equals}, which is what makes a single + * emitter sufficient: a parameter whose reference the SDK keeps stable settles on the identity check, and one that + * arrives as a fresh reference falls through to {@code equals} and still matches. + * + *

Parameter order comes from {@link #cacheKeyParameterOrder()}. Order is the only thing that varies between + * parameters, and it only affects how quickly a mismatch is found. + * + *

List-valued parameters are special cased to avoid slow comparisons for large lists. + * See {@link #cacheListsMatchMethod()}. + */ + private MethodSpec cacheParamsMatchMethod() { + ClassName paramsClass = endpointRulesSpecUtils.parametersClassName(); + Map parameters = endpointBddModel.getParameters(); + + MethodSpec.Builder b = MethodSpec.methodBuilder("cacheParamsMatch") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .returns(boolean.class) + .addParameter(paramsClass, "a") + .addParameter(paramsClass, "b"); + + CodeBlock.Builder chain = CodeBlock.builder().add("return "); + boolean first = true; + for (String paramName : cacheKeyParameterOrder()) { + String getter = endpointRulesSpecUtils.paramMethodName(paramName) + "()"; + if (!first) { + chain.add("\n && "); + } + if (!isListParam(parameters.get(paramName))) { + chain.add("$T.equals(a.$L, b.$L)", Objects.class, getter, getter); + } else if (paramUsage.get(paramName) == BddParameterReferences.Usage.FIRST_ELEMENT_ONLY) { + chain.add("cacheFirstElementsMatch(a.$L, b.$L)", getter, getter); + } else { + chain.add("cacheListsMatch(a.$L, b.$L)", getter, getter); + } + first = false; + } + if (first) { + // Either the model declares no parameters, or it reads none of them. Both mean one endpoint for every + // request, so any two parameter objects are interchangeable. + chain.add("true"); + } + b.addStatement(chain.build()); + return b.build(); + } + + /** + * Returns the parameter names in the order the generated cache key compares them: booleans, then strings whose + * reference the SDK keeps stable across requests, then everything else. Each group keeps the model's declaration + * order, so the result is deterministic across builds. + * + *

Ordering exists only to reach a mismatch sooner. It cannot change the outcome, because the chain compares + * every parameter before returning true. Booleans come first because they can never fall through to a real + * {@code equals}; reference-stable strings come next because they normally settle on the identity check; and the + * request-derived values that may have to compare characters come last. + */ + private List cacheKeyParameterOrder() { + Map parameters = endpointBddModel.getParameters(); + Map clientContextParams = intermediateModel.getClientContextParams(); + + List booleans = new ArrayList<>(); + List stableStrings = new ArrayList<>(); + List rest = new ArrayList<>(); + + parameters.forEach((name, model) -> { + if (paramUsage.get(name) == BddParameterReferences.Usage.UNREFERENCED) { + // Nothing reads it, so it cannot change the endpoint and must not force a miss. + return; + } + if (isBooleanParam(model)) { + booleans.add(name); + } else if (isReferenceStable(name, model, clientContextParams)) { + stableStrings.add(name); + } else { + rest.add(name); + } + }); + + List order = new ArrayList<>(booleans.size() + stableStrings.size() + rest.size()); + order.addAll(booleans); + order.addAll(stableStrings); + order.addAll(rest); + return order; + } + + /** + * Returns true for a string parameter the SDK hands to every request as the same reference: {@code AWS::Region}, + * which {@code Region.of} interns, and {@code clientContextParams}, which are read from the client's + * {@code AttributeMap}. + * + *

Only used to order the comparison. If one of these ever stops being reference-stable, the + * {@code Objects.equals} term still compares it correctly; the check simply costs an extra call. + */ + private static boolean isReferenceStable(String paramName, + ParameterModel model, + Map clientContextParams) { + if (model.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { + return true; + } + if (clientContextParams == null) { + return false; + } + // Endpoint parameter names are unique case-insensitively, so a case-insensitive match is the same parameter. + for (String key : clientContextParams.keySet()) { + if (key.equalsIgnoreCase(paramName)) { + return true; + } + } + return false; + } + + /** + * Generates the {@code cacheListsMatch} helper, emitted only when the model declares a {@code stringArray} + * parameter. + * + *

{@code Objects.equals} would be correct here, but {@code List.equals} is unbounded: a request carrying a large + * list would walk every element on every cache check, which can cost more than the resolution the cache exists to + * avoid. The comparison is therefore capped at {@value #MAX_LIST_COMPARISON_SIZE} elements. A service handling + * longer lists simply misses and pays resolution, which is what it would have paid anyway. + */ + private MethodSpec cacheListsMatchMethod() { + TypeName listOfString = RuleRuntimeTypeMirror.LIST_OF_STRING.type(); + return MethodSpec.methodBuilder("cacheListsMatch") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .returns(boolean.class) + .addParameter(listOfString, "a") + .addParameter(listOfString, "b") + .addStatement("if (a == b) return true") + .addStatement("if (a == null || b == null) return false") + .addStatement("int size = a.size()") + .addStatement("if (size != b.size()) return false") + .addComment("Bounded so that a long list cannot make the cache check cost more than " + + "resolving.") + .addStatement("if (size > $L) return false", MAX_LIST_COMPARISON_SIZE) + .beginControlFlow("for (int i = 0; i < size; i++)") + .addStatement("if (!$T.equals(a.get(i), b.get(i))) return false", Objects.class) + .endControlFlow() + .addStatement("return true") + .build(); + } + + /** + * Generates the {@code cacheFirstElementsMatch} helper, emitted only when a {@code stringArray} parameter is read + * exclusively as {@code param[0]}. + * + *

When the rules can only see whether the list is present and what its first element is, comparing the rest is + * work that cannot change the answer. + */ + private MethodSpec cacheFirstElementsMatchMethod() { + TypeName listOfString = RuleRuntimeTypeMirror.LIST_OF_STRING.type(); + return MethodSpec.methodBuilder("cacheFirstElementsMatch") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .returns(boolean.class) + .addParameter(listOfString, "a") + .addParameter(listOfString, "b") + .addStatement("if (a == b) return true") + .addComment("isSet can tell an absent list from an empty one, so presence is part of the key.") + .addStatement("if (a == null || b == null) return false") + .addComment("Nothing past element 0 can reach the endpoint.") + .addStatement("$T firstA = a.isEmpty() ? null : a.get(0)", String.class) + .addStatement("$T firstB = b.isEmpty() ? null : b.get(0)", String.class) + .addStatement("return $T.equals(firstA, firstB)", Objects.class) + .build(); + } + + /** + * True when some list parameter in the cache key needs a whole-list comparison. + */ + private boolean needsFullListHelper() { + return listParamsInKeyWithUsage(BddParameterReferences.Usage.FULL); + } + + /** + * True when some list parameter in the cache key is read only at index 0. + */ + private boolean needsFirstElementHelper() { + return listParamsInKeyWithUsage(BddParameterReferences.Usage.FIRST_ELEMENT_ONLY); + } + + private boolean listParamsInKeyWithUsage(BddParameterReferences.Usage usage) { + Map parameters = endpointBddModel.getParameters(); + return cacheKeyParameterOrder().stream() + .filter(name -> isListParam(parameters.get(name))) + .anyMatch(name -> paramUsage.get(name) == usage); + } + + private static boolean isBooleanParam(ParameterModel model) { + return "boolean".equalsIgnoreCase(model.getType()); + } + + /** + * Shared with {@link BddParameterReferences}, which must agree with this class on what a list is: the usage it + * derives selects which comparison helper gets emitted for the parameter. + */ + static boolean isListParam(ParameterModel model) { + return "stringarray".equalsIgnoreCase(model.getType()); + } + + private TypeSpec evaluatorClass() { + TypeSpec.Builder builder = TypeSpec.classBuilder(evaluatorType) + .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL); + + // params field + builder.addField(FieldSpec.builder(endpointRulesSpecUtils.parametersClassName(), "params").build()); + + // Register fields + registerInfoMap.forEach((k, r) -> { + TypeName type = r.getRuleType().type(); + if (type.isPrimitive() && r.isNullable()) { + type = type.box(); + } + if (!r.isNonRegionParam()) { + builder.addField(FieldSpec.builder(type, r.getName()).build()); + } + }); + + // BDD node methods + builder.addMethods(bddNodeMethods()); + + // Condition methods (only for complex conditions) + builder.addMethods(conditionMethods()); + + // Result methods + builder.addMethods(resultMethods()); + + return builder.build(); + } + + /** + * Generates methods for each BDD node. For each node, emits: + *

    + *
  • {@code nodeP} — positive edge: condition true → highRef, false → lowRef
  • + *
  • {@code nodeN} — complement edge: condition true → lowRef, false → highRef (branches swapped)
  • + *
+ * + *

Complement edges allow the BDD to share nodes: a negative reference {@code -N} means + * "evaluate node N-1 with inverted condition result." Only nodeN variants that are actually + * referenced are emitted to avoid dead code. + * + *

Simple conditions are inlined as ternary expressions. Complex conditions call cond(). + */ + private List bddNodeMethods() { + // First pass: determine which nodes need a complement (nodeN) variant + boolean[] needsNodeN = new boolean[bddNodes.size()]; + for (EndpointBddModel.BddNode node : bddNodes) { + markComplementRef(needsNodeN, node.getHighRef()); + markComplementRef(needsNodeN, node.getLowRef()); + } + // Also check the root reference + markComplementRef(needsNodeN, endpointBddModel.getRoot()); + + List methods = new ArrayList<>(); + + for (int i = 0; i < bddNodes.size(); i++) { + EndpointBddModel.BddNode node = bddNodes.get(i); + int condIdx = node.getConditionIndex(); + + // Node 0 is the terminal sentinel (conditionIndex = -1) — returns null (no match) + if (i == 0) { + if (condIdx != -1) { + throw new IllegalStateException( + "BDD node 0 must be the terminal sentinel with conditionIndex=-1, got: " + condIdx); + } + methods.add(MethodSpec.methodBuilder("nodeP0") + .addModifiers(Modifier.PRIVATE) + .returns(Endpoint.class) + .addStatement("return null") + .build()); + if (needsNodeN[0]) { + methods.add(MethodSpec.methodBuilder("nodeN0") + .addModifiers(Modifier.PRIVATE) + .returns(Endpoint.class) + .addStatement("return null") + .build()); + } + continue; + } + + // All other nodes must have a valid condition index + if (condIdx < 0 || condIdx >= conditionTypes.size()) { + throw new IllegalStateException( + "BDD node " + i + " has invalid conditionIndex=" + condIdx + + " (valid range: 0.." + (conditionTypes.size() - 1) + ")"); + } + + ConditionType ct = conditionTypes.get(condIdx); + + // nodeP: condition true → highRef, false → lowRef + methods.add(MethodSpec.methodBuilder("nodeP" + i) + .addModifiers(Modifier.PRIVATE) + .returns(Endpoint.class) + .addCode(nodeBody(ct, condIdx, node.getHighRef(), node.getLowRef())) + .build()); + + // nodeN: complement — condition true → lowRef, false → highRef (swapped) + if (needsNodeN[i]) { + methods.add(MethodSpec.methodBuilder("nodeN" + i) + .addModifiers(Modifier.PRIVATE) + .returns(Endpoint.class) + .addCode(nodeBody(ct, condIdx, node.getLowRef(), node.getHighRef())) + .build()); + } + } + + return methods; + } + + /** + * Marks a node as needing a complement (nodeN) variant if the reference is a negative node ref. + */ + private void markComplementRef(boolean[] needsNodeN, int ref) { + if (ref < -1) { + int nodeIndex = (-ref) - 1; + if (nodeIndex < needsNodeN.length) { + needsNodeN[nodeIndex] = true; + } + } + } + + /** + * Generates the body of a nodeP method as a ternary return statement. + */ + private CodeBlock nodeBody(ConditionType ct, int condIdx, int highRef, int lowRef) { + CodeBlock.Builder code = CodeBlock.builder(); + String condExpr = conditionExpression(ct, condIdx); + code.addStatement("return $L\n ? $L\n : $L", + condExpr, + referenceExpression(highRef), + referenceExpression(lowRef)); + return code.build(); + } + + /** + * Returns the Java expression for evaluating a condition. + * Simple conditions are inlined; complex ones call cond(). + */ + private String conditionExpression(ConditionType ct, int condIdx) { + switch (ct.kind) { + case ISSET: + return ct.registerName + " != null"; + case BOOL_TRUE: + return "Boolean.TRUE.equals(" + ct.registerName + ")"; + case BOOL_FALSE: + return "Boolean.FALSE.equals(" + ct.registerName + ")"; + case STRING_EQ: + return ct.registerName + " != null && " + ct.registerName + ".equals(" + ct.stringConstant + ")"; + case COMPLEX: + default: + return "cond" + condIdx + "()"; + } + } + + /** + * Returns the Java expression for a BDD reference: a node call, a result call, or null (terminal/no-match). + * A negative reference (other than -1) is a complement edge: {@code -N} means "call nodeN()" + * which evaluates the same condition but swaps the branch targets. + */ + private String referenceExpression(int ref) { + // Terminal refs: SEP defines 1 and -1 as terminals (true/false sinks) + if (ref == 1 || ref == -1) { + return "null"; + } + // NoMatchRule: SEP defines 100_000_000 as implicit no-match + if (ref == NO_MATCH_RESULT) { + return "null"; + } + // Result refs + if (ref >= RESULT_OFFSET) { + int resultIndex = ref - RESULT_OFFSET; + if (resultIndex >= endpointBddModel.getResults().size()) { + throw new IllegalStateException( + "BDD result reference " + ref + " maps to index " + resultIndex + + " but only " + endpointBddModel.getResults().size() + " results exist"); + } + return "result" + resultIndex + "()"; + } + // Invalid ref + if (ref == 0) { + throw new IllegalStateException("BDD reference 0 is invalid (node indices are 1-based)"); + } + // Complement edge: negative ref → nodeN (swapped branches) + if (ref < 0) { + int nodeIndex = (-ref) - 1; + if (nodeIndex >= bddNodes.size()) { + throw new IllegalStateException( + "BDD complement reference " + ref + " maps to node index " + nodeIndex + + " but only " + bddNodes.size() + " nodes exist"); + } + return "nodeN" + nodeIndex + "()"; + } + // Positive node ref (1-based → 0-based) + int nodeIndex = ref - 1; + if (nodeIndex >= bddNodes.size()) { + throw new IllegalStateException( + "BDD node reference " + ref + " maps to index " + nodeIndex + + " but only " + bddNodes.size() + " nodes exist"); + } + return "nodeP" + nodeIndex + "()"; + } + + /** + * Generates condition methods only for complex conditions (those that compute and store values). + */ + private List conditionMethods() { + List methods = new ArrayList<>(); + for (int cI = 0; cI < endpointBddModel.getConditions().size(); cI++) { + if (conditionTypes.get(cI).kind != ConditionKind.COMPLEX) { + continue; + } + CodeBlock.Builder codeBuilder = CodeBlock.builder(); + ConditionModel c = endpointBddModel.getConditions().get(cI); + // Use existing expression parser for complex conditions + RuleModel synthetic = new RuleModel(); + synthetic.setType("error"); + synthetic.setError("synthetic"); + synthetic.setConditions(Collections.singletonList(c)); + RuleExpression parsedSynthetic = ExpressionParser + .parseRuleSetExpression(synthetic) + .accept(new BddPeepholeVisitor()) + .accept(new PrepareForCodegenVisitor()); + parsedSynthetic.accept(new ConditionFnCodeGeneratorVisitor(codeBuilder, typeMirror, registerInfoMap, + endpointRulesSpecUtils)); + methods.add(MethodSpec.methodBuilder("cond" + cI) + .addModifiers(Modifier.PRIVATE) + .returns(boolean.class) + .addCode(codeBuilder.build()) + .build()); + } + return methods; + } + + /** + * Generates result methods that return Endpoint directly or throw SdkClientException for errors. + */ + private List resultMethods() { + List methods = new ArrayList<>(); + for (int rI = 0; rI < endpointBddModel.getResults().size(); rI++) { + CodeBlock.Builder codeBuilder = CodeBlock.builder(); + // BddPeepholeVisitor is deliberately not applied here. It rewrites condition-shaped + // expressions (stringEquals, coalesce-with-boolean-default, ite, isValidHostLabel), and a + // BDD result cannot contain any: the BDD hoists all computation into conditions, so + // results only consume already-assigned registers. BddResultCodeGeneratorVisitor enforces + // that by rejecting conditions and let-bindings outright. Applying the peephole here + // produced identical output while requiring a duplicate copy of every emitter. + RuleExpression parsedSynthetic = ExpressionParser + .parseRuleSetExpression(endpointBddModel.getResults().get(rI)) + .accept(new PrepareForCodegenVisitor()); + parsedSynthetic.accept(new BddResultCodeGeneratorVisitor( + codeBuilder, typeMirror, registerInfoMap, knownEndpointAttributes, endpointRulesSpecUtils, + intermediateModel.getCustomizationConfig().useS3ExpressSessionAuth())); + methods.add(MethodSpec.methodBuilder("result" + rI) + .addModifiers(Modifier.PRIVATE) + .returns(Endpoint.class) + .addCode(codeBuilder.build()) + .build()); + } + return methods; + } + + private MethodSpec resolveEndpointMethod() { + MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveEndpoint") + .addModifiers(Modifier.PUBLIC) + .returns(endpointRulesSpecUtils.resolverReturnType()) + .addAnnotation(Override.class) + .addParameter(endpointRulesSpecUtils.parametersClassName(), "endpointParams"); + + builder.addCode(validateRequiredParams()); + + // Cache check. This sits after required-param validation so that invalid params fail the same way on a hit as + // on a miss. One volatile read into a local, so the entry cannot be replaced between the null check and the + // comparison. + builder.addComment("Single-entry result cache: reuse the last endpoint when the params still match."); + builder.addStatement("$T cached = this.cache", cacheEntryType); + builder.beginControlFlow("if (cached != null && cacheParamsMatch(endpointParams, cached.params))"); + builder.addStatement("return $T.completedFuture(cached.endpoint)", CompletableFuture.class); + builder.endControlFlow(); + + builder.beginControlFlow("try"); + + // Allocate evaluator per call — lightweight (just fields, no maps), immediately young-gen collected. + builder.addStatement("$T evaluator = new $T()", evaluatorType, evaluatorType); + + // Initialize evaluator from params + builder.addStatement("evaluator.params = endpointParams"); + String regionParamName = regionParamName(); + if (regionParamName != null) { + String regionMethodName = endpointRulesSpecUtils.paramMethodName(regionParamName); + builder.addStatement("evaluator.$L = endpointParams.$L() == null ? null : endpointParams.$L().id()", + registerInfoMap.get(regionParamName).getName(), + regionMethodName, regionMethodName); + } + + // Evaluate BDD — returns Endpoint directly (null = no match) + builder.addStatement("$T result = evaluator.$L", + Endpoint.class, referenceExpression(endpointBddModel.getRoot())); + builder.beginControlFlow("if (result == null)") + .addStatement("return $T.failedFuture($T.create($S))", + CompletableFutureUtils.class, SdkClientException.class, + "Rule engine did not reach an error or endpoint result") + .endControlFlow(); + // Populate on success only. A rule error and a no-match both leave the previous entry in place, so a transient + // bad-params call cannot poison the cache and an error is never replayed from it. + builder.addStatement("this.cache = new $T(endpointParams, result)", cacheEntryType); + builder.addStatement("return $T.completedFuture(result)", CompletableFuture.class); + + // Catch errors thrown from result methods + builder.nextControlFlow("catch ($T e)", SdkClientException.class); + builder.addStatement("String errorMsg = e.getMessage()"); + builder.beginControlFlow("if (errorMsg != null && errorMsg.contains(\"Invalid ARN\") && errorMsg.contains(\":s3:::\"))") + .addStatement("return $T.failedFuture($T.create(errorMsg + $S, e))", + CompletableFutureUtils.class, SdkClientException.class, + ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest.") + .endControlFlow(); + builder.addStatement("return $T.failedFuture(e)", CompletableFutureUtils.class); + + builder.nextControlFlow("catch ($T error)", Exception.class); + builder.addStatement("return $T.failedFuture(error)", CompletableFutureUtils.class); + + builder.endControlFlow(); + + return builder.build(); + } + + @Override + public ClassName className() { + Metadata md = intermediateModel.getMetadata(); + return ClassName.get(md.getFullInternalEndpointRulesPackageName(), + "Default" + endpointRulesSpecUtils.providerInterfaceName().simpleName()); + } + + // ---- Condition analysis ---- + + /** + * Analyzes each condition in the BDD model to determine if it can be inlined in a node method + * or needs a full cond() method. + */ + private List analyzeConditions() { + List types = new ArrayList<>(); + for (ConditionModel condition : endpointBddModel.getConditions()) { + types.add(classifyCondition(condition)); + } + return types; + } + + private ConditionType classifyCondition(ConditionModel condition) { + // Conditions with assign always need a method (they have side effects) + if (condition.getAssign() != null) { + return ConditionType.complex(); + } + + String fn = condition.getFn(); + List argv = condition.getArgv(); + + // isSet({ref}) -> ISSET + if ("isSet".equals(fn) && argv.size() == 1 && isSimpleRef(argv.get(0))) { + String refName = getRefName(argv.get(0)); + return ConditionType.isSet(resolveRegisterAccessExpression(refName)); + } + + // booleanEquals({ref}, true/false) -> BOOL_TRUE or BOOL_FALSE + if ("booleanEquals".equals(fn) && argv.size() == 2 && isSimpleRef(argv.get(0)) && isBooleanLiteral(argv.get(1))) { + String refName = getRefName(argv.get(0)); + boolean value = getBooleanValue(argv.get(1)); + String registerExpr = resolveRegisterAccessExpression(refName); + return value ? ConditionType.boolTrue(registerExpr) : ConditionType.boolFalse(registerExpr); + } + + // stringEquals({ref}, "literal") -> STRING_EQ + if ("stringEquals".equals(fn) && argv.size() == 2 && isSimpleRef(argv.get(0)) && isStringLiteral(argv.get(1))) { + String refName = getRefName(argv.get(0)); + String literal = getStringValue(argv.get(1)); + String registerExpr = resolveRegisterAccessExpression(refName); + // Quote the string literal for use in generated code + String quotedLiteral = "\"" + escapeJavaString(literal) + "\""; + return ConditionType.stringEq(registerExpr, quotedLiteral); + } + + return ConditionType.complex(); + } + + /** + * Resolves a parameter/register name to the Java expression that accesses it in the Evaluator. + * For non-region params, this is {@code params.xxx()}; for registers, it's the field name. + */ + private String resolveRegisterAccessExpression(String name) { + RegistryInfo info = registerInfoMap.get(name); + if (info == null) { + // Fallback — shouldn't happen for well-formed models + return intermediateModel.getNamingStrategy().getVariableName(name); + } + if (info.isNonRegionParam()) { + return "params." + endpointRulesSpecUtils.paramMethodName(info.getNonRegionParamKey()) + "()"; + } + return info.getName(); + } + + private static boolean isSimpleRef(TreeNode node) { + // A simple ref is: {"ref": "SomeName"} — an object with exactly one field "ref" that is a string value + if (!node.isObject() || node.size() != 1) { + return false; + } + TreeNode refNode = node.get("ref"); + return refNode != null && refNode.isValueNode() && refNode.asToken() == JsonToken.VALUE_STRING; + } + + private static String getRefName(TreeNode node) { + return ((JrsValue) node.get("ref")).asText(); + } + + private static boolean isBooleanLiteral(TreeNode node) { + if (!node.isValueNode()) { + return false; + } + JsonToken token = node.asToken(); + return token == JsonToken.VALUE_TRUE || token == JsonToken.VALUE_FALSE; + } + + private static boolean getBooleanValue(TreeNode node) { + return node.asToken() == JsonToken.VALUE_TRUE; + } + + private static boolean isStringLiteral(TreeNode node) { + return node.isValueNode() && node.asToken() == JsonToken.VALUE_STRING; + } + + private static String getStringValue(TreeNode node) { + return ((JrsValue) node).asText(); + } + + private static String escapeJavaString(String s) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case '"': + sb.append("\\\""); + break; + case '\\': + sb.append("\\\\"); + break; + case '\n': + sb.append("\\n"); + break; + case '\r': + sb.append("\\r"); + break; + case '\t': + sb.append("\\t"); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + + // ---- Helpers ---- + + private String regionParamName() { + for (Map.Entry entry : endpointBddModel.getParameters().entrySet()) { + if (entry.getValue().getBuiltInEnum() == BuiltInParameter.AWS_REGION) { + return entry.getKey(); + } + } + return null; + } + + private CodeBlock validateRequiredParams() { + CodeBlock.Builder b = CodeBlock.builder(); + Map parameters = endpointBddModel.getParameters(); + parameters.entrySet().stream() + .filter(e -> Boolean.TRUE.equals(e.getValue().isRequired()) && e.getValue().getDefault() == null) + .forEach(e -> { + b.addStatement("$T.notNull($N.$N(), $S)", + Validate.class, + "endpointParams", + endpointRulesSpecUtils.paramMethodName(e.getKey()), + String.format("Parameter '%s' must not be null", e.getKey())); + }); + return b.build(); + } + + private Map buildRegisterInfoMap() { + Map registryInfo = new LinkedHashMap<>(); + // first add an entry for every parameter + for (Map.Entry entry : endpointBddModel.getParameters().entrySet()) { + String name = intermediateModel.getNamingStrategy().getVariableName(entry.getKey()); + boolean nullable = entry.getValue().getDefault() == null; + boolean isRegionBuiltIn = entry.getValue().getBuiltInEnum() == BuiltInParameter.AWS_REGION; + String nonRegionParamKey = isRegionBuiltIn ? null : entry.getKey(); + registryInfo.put( + entry.getKey(), + new RegistryInfo(name, fromParameterModel(entry.getValue()), + null, nullable, nonRegionParamKey)); + } + // add an entry for every assigned variable. assigns are guaranteed to be globally unique + for (ConditionModel conditionModel : endpointBddModel.getConditions()) { + if (conditionModel.getAssign() != null) { + RuleModel synthetic = new RuleModel(); + synthetic.setType("error"); + synthetic.setError("synthetic"); + synthetic.setConditions(Collections.singletonList(conditionModel)); + String name = intermediateModel.getNamingStrategy().getVariableName(conditionModel.getAssign()); + registryInfo.put( + conditionModel.getAssign(), + new RegistryInfo(name, ExpressionParser.parseRuleSetExpression(synthetic))); + } + } + // visit all the conditions/assignments and infer types + AssignTypeInferringVisitor typeVisitor = new AssignTypeInferringVisitor(typeMirror, registryInfo); + registryInfo.values().forEach(r -> { + if (r.getRuleSetExpression() != null) { + r.getRuleSetExpression().accept(typeVisitor); + } + }); + // assert that we have type information for all registry values + registryInfo.values().forEach(r -> { + if (r.getRuleType() == null) { + throw new IllegalStateException("Unable to infer type for `" + r.getName() + "`"); + } + }); + return Collections.unmodifiableMap(registryInfo); + } + + private static RuleType fromParameterModel(ParameterModel model) { + switch (model.getType().toLowerCase(Locale.ENGLISH)) { + case "boolean": + return RuleRuntimeTypeMirror.BOOLEAN; + case "string": + return RuleRuntimeTypeMirror.STRING; + case "stringarray": + return RuleRuntimeTypeMirror.LIST_OF_STRING; + default: + throw new IllegalStateException("Cannot find rule type for: " + model.getType()); + } + } + + private static Map knownEndpointAttributes(IntermediateModel intermediateModel) { + Map knownEndpointAttributes = null; + EndpointAuthSchemeConfig config = intermediateModel.getCustomizationConfig().getEndpointAuthSchemeConfig(); + if (config != null) { + knownEndpointAttributes = config.getEndpointProviderTestKeys(); + } + if (knownEndpointAttributes == null) { + knownEndpointAttributes = Collections.emptyMap(); + } + return knownEndpointAttributes; + } + + // ---- Condition type classification ---- + + enum ConditionKind { + ISSET, + BOOL_TRUE, + BOOL_FALSE, + STRING_EQ, + COMPLEX + } + + static class ConditionType { + final ConditionKind kind; + final String registerName; // Java expression to access the register/param + final String stringConstant; // Only for STRING_EQ + + private ConditionType(ConditionKind kind, String registerName, String stringConstant) { + this.kind = kind; + this.registerName = registerName; + this.stringConstant = stringConstant; + } + + static ConditionType complex() { + return new ConditionType(ConditionKind.COMPLEX, null, null); + } + + static ConditionType isSet(String registerName) { + return new ConditionType(ConditionKind.ISSET, registerName, null); + } + + static ConditionType boolTrue(String registerName) { + return new ConditionType(ConditionKind.BOOL_TRUE, registerName, null); + } + + static ConditionType boolFalse(String registerName) { + return new ConditionType(ConditionKind.BOOL_FALSE, registerName, null); + } + + static ConditionType stringEq(String registerName, String stringConstant) { + return new ConditionType(ConditionKind.STRING_EQ, registerName, stringConstant); + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddParameterReferences.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddParameterReferences.java new file mode 100644 index 000000000000..a718f5def3d2 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddParameterReferences.java @@ -0,0 +1,180 @@ +/* + * 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.codegen.poet.rules.bdd; + +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import software.amazon.awssdk.codegen.model.rules.endpoints.ConditionModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; +import software.amazon.awssdk.codegen.poet.rules.ExpressionParser; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.IndexedAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.MemberAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; +import software.amazon.awssdk.codegen.poet.rules.WalkRuleExpressionVisitor; + +/** + * Works out how each endpoint parameter is used by a BDD, so that the generated result cache only compares what can + * actually change the resolved endpoint. + * + *

Analysis runs over the BDD's conditions and results using the same parser the generator uses, so the answer + * reflects what the generated provider reads rather than what the model happens to declare. + * + *

Two things fall out of it: + * + *

    + *
  • {@link Usage#UNREFERENCED} - a parameter no condition and no result reads. It cannot change the endpoint, so + * comparing it can only produce misses that resolve to the endpoint already cached. S3 is the motivating case: + * it declares {@code Key}, {@code Prefix} and {@code CopySource}, no rule reads any of them, and {@code Key} + * changes on essentially every object request - so including it means the cache almost never hits.
  • + *
  • {@link Usage#FIRST_ELEMENT_ONLY} - a {@code stringArray} whose every use is an index-0 access. Only the first + * element can reach the endpoint, so the generated comparison is optimized by comparing only that element instead + * of walking the list.
  • + *
+ */ +final class BddParameterReferences { + + /** + * How much of a parameter's value can influence the resolved endpoint. + */ + enum Usage { + /** No condition and no result reads it. It cannot be part of the cache key. */ + UNREFERENCED, + + /** + * A {@code stringArray} the rules can only observe through {@code isSet(param)} and {@code param[0]}. Whether + * the list is present, plus its first element, is therefore the whole of what can reach the endpoint, and + * nothing past element 0 can change the answer. + */ + FIRST_ELEMENT_ONLY, + + /** Read in a way that can depend on the entire value. */ + FULL + } + + private BddParameterReferences() { + } + + /** + * Returns the usage of every parameter the model declares, in declaration order. + */ + static Map analyze(EndpointBddModel model) { + Collector collector = new Collector(); + + for (ConditionModel condition : model.getConditions()) { + RuleModel synthetic = new RuleModel(); + synthetic.setType("error"); + synthetic.setError("synthetic"); + synthetic.setConditions(Collections.singletonList(condition)); + ExpressionParser.parseRuleSetExpression(synthetic).accept(collector); + } + for (RuleModel result : model.getResults()) { + ExpressionParser.parseRuleSetExpression(result).accept(collector); + } + + Map usage = new LinkedHashMap<>(); + model.getParameters().forEach((name, parameter) -> usage.put(name, usageOf(name, parameter, collector))); + return Collections.unmodifiableMap(usage); + } + + private static Usage usageOf(String name, ParameterModel parameter, Collector collector) { + if (!collector.referenced.contains(name)) { + return Usage.UNREFERENCED; + } + if (collector.wholeValue.contains(name)) { + return Usage.FULL; + } + // Only lists benefit, and only lists can be read element-wise. Anything else that somehow reached here is + // compared in full rather than guessed at. + return BddEndpointProviderSpec.isListParam(parameter) ? Usage.FIRST_ELEMENT_ONLY : Usage.FULL; + } + + /** + * Collects, for every name the expressions reference, whether any reference needs more than the first element. + * + *

Erring towards {@link Usage#FULL} is the safe direction: it costs comparison work, whereas erring the other + * way would drop something from the cache key that can change the endpoint. + */ + private static final class Collector extends WalkRuleExpressionVisitor { + private final Set referenced = new HashSet<>(); + private final Set wholeValue = new HashSet<>(); + + @Override + public Void visitIndexedAccessExpression(IndexedAccessExpression e) { + String subject = firstElementSubject(e); + if (subject != null) { + referenced.add(subject); + // Deliberately not descending. Descending would reach the variable reference underneath and record it + // as a whole-value read, which is the thing this case exists to avoid. + return null; + } + return super.visitIndexedAccessExpression(e); + } + + /** + * {@code isSet(param)} observes only whether the parameter is present, so on its own it does not force a + * whole-value comparison. + */ + @Override + public Void visitFunctionCallExpression(FunctionCallExpression e) { + if ("isSet".equals(e.name()) && e.arguments().size() == 1) { + RuleExpression argument = e.arguments().get(0); + if (argument instanceof VariableReferenceExpression) { + referenced.add(((VariableReferenceExpression) argument).variableName()); + return null; + } + } + return super.visitFunctionCallExpression(e); + } + + @Override + public Void visitVariableReferenceExpression(VariableReferenceExpression e) { + referenced.add(e.variableName()); + wholeValue.add(e.variableName()); + return null; + } + + /** + * Returns the parameter name when this is an index-0 read of a plain parameter, otherwise null. + * + *

Both spellings reach here: {@code "list[0]"} inside a template parses to an indexed access straight over + * the variable, while {@code getAttr(list, "[0]")} wraps it in a direct-index member access first. + */ + private static String firstElementSubject(IndexedAccessExpression e) { + if (e.index() != 0) { + return null; + } + RuleExpression source = e.source(); + if (source instanceof MemberAccessExpression) { + MemberAccessExpression member = (MemberAccessExpression) source; + if (!member.directIndex()) { + return null; + } + source = member.source(); + } + if (source instanceof VariableReferenceExpression) { + return ((VariableReferenceExpression) source).variableName(); + } + return null; + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitor.java new file mode 100644 index 000000000000..a7c33b5e6321 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitor.java @@ -0,0 +1,251 @@ +/* + * 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.codegen.poet.rules.bdd; + +import java.util.List; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralIntegerExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.RewriteRuleExpressionVisitor; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; + +/** + * BDD-only peephole optimization pass. Rewrites endpoint rule expressions into synthetic function + * calls that the BDD code generators emit as allocation-free native Java. + * + *

This runs before {@link software.amazon.awssdk.codegen.poet.rules.PrepareForCodegenVisitor} on + * the BDD path only, so the tree-based rules code generation is unaffected. + * + *

Optimizations applied: + *

    + *
  • {@code stringEquals(coalesce(substring(str, X, Y, reverse), ""), literal)} → + * {@code RulesFunctions.substringEquals(str, X, Y, reverse, literal)}, which compares in + * place instead of allocating the substring and the coalesce varargs array. The helper + * reproduces {@code substring}'s semantics exactly, including its rejection of non-ASCII + * input, so the rewrite cannot change which branch a rule takes.
  • + *
  • {@code coalesce(boolExpr, boolLiteral)} → {@code __coalesceBoolean(expr, default)}
  • + *
  • {@code ite(cond, ifTrue, ifFalse)} → {@code __ite(cond, ifTrue, ifFalse)}
  • + *
  • {@code isValidHostLabel(str, boolLiteral)} → {@code __isValidHostLabel(str, allowDots)}
  • + *
+ * + *

Synthetic function names are prefixed with {@code __} so they cannot collide with endpoint + * rule standard library function names. Those in {@link #isCustomEmitted(String)} are emitted as + * inline Java by the code generators; {@code __substringEquals} is instead registered as a real + * function in {@link RuleRuntimeTypeMirror} and emitted by the ordinary static-call path. + */ +public final class BddPeepholeVisitor extends RewriteRuleExpressionVisitor { + public static final String ITE = "__ite"; + public static final String COALESCE_BOOL = "__coalesceBoolean"; + public static final String IS_VALID_HOST_LABEL = "__isValidHostLabel"; + + /** + * Returns true for synthetic functions that the BDD code generator emits as inline Java rather + * than as a plain static call. {@link RuleRuntimeTypeMirror#SUBSTRING_EQUALS_FN} is deliberately + * absent: it is registered as a real function and so needs no custom emitter. + */ + public static boolean isCustomEmitted(String functionName) { + return ITE.equals(functionName) + || COALESCE_BOOL.equals(functionName) + || IS_VALID_HOST_LABEL.equals(functionName); + } + + @Override + public RuleExpression visitFunctionCallExpression(FunctionCallExpression e) { + e = (FunctionCallExpression) super.visitFunctionCallExpression(e); + switch (e.name()) { + case "stringEquals": + return simplifyStringEquals(e); + case "coalesce": + return simplifyCoalesce(e); + case "ite": + return simplifyIte(e); + case "isValidHostLabel": + return simplifyIsValidHostLabel(e); + default: + return e; + } + } + + /** + * Rewrites {@code stringEquals} into a {@code substringEquals} call when either side is a + * {@code coalesce(substring(..), "")}. Any other {@code stringEquals} is returned unchanged for + * {@link software.amazon.awssdk.codegen.poet.rules.PrepareForCodegenVisitor} to handle. + */ + private RuleExpression simplifyStringEquals(FunctionCallExpression e) { + List args = e.arguments(); + if (args.size() != 2) { + return e; + } + RuleExpression left = args.get(0); + RuleExpression right = args.get(1); + + RuleExpression peephole = trySubstringPeephole(left, right); + if (peephole != null) { + return peephole; + } + peephole = trySubstringPeephole(right, left); + if (peephole != null) { + return peephole; + } + + // Leave the plain comparison alone. PrepareForCodegenVisitor runs immediately after and + // rewrites it to constant.equals(other) only when one side is a string constant, keeping the + // null-safe RulesFunctions.stringEquals call otherwise. Rewriting it here would emit + // left.equals(right) even when both sides are nullable at runtime, which turns the + // spec-mandated false into a NullPointerException. + return e; + } + + /** + * Matches {@code coalesce(substring(str, start, stop, reverse), "")} compared against a string + * literal, returning the corresponding synthetic expression, or null when the pattern does not + * apply. + */ + private RuleExpression trySubstringPeephole(RuleExpression coalesceCandidate, RuleExpression literalCandidate) { + if (literalCandidate.kind() != RuleExpression.RuleExpressionKind.STRING_VALUE) { + return null; + } + String literal = ((LiteralStringExpression) literalCandidate).value(); + + FunctionCallExpression coalesceExpr = extractCoalesceWithEmptyDefault(coalesceCandidate); + if (coalesceExpr == null) { + return null; + } + + RuleExpression substringCandidate = coalesceExpr.arguments().get(0); + if (!(substringCandidate instanceof FunctionCallExpression)) { + return null; + } + FunctionCallExpression substringExpr = (FunctionCallExpression) substringCandidate; + if (!"substring".equals(substringExpr.name())) { + return null; + } + + List subArgs = substringExpr.arguments(); + if (subArgs.size() != 4) { + return null; + } + if (!(subArgs.get(1) instanceof LiteralIntegerExpression) + || !(subArgs.get(2) instanceof LiteralIntegerExpression) + || !(subArgs.get(3) instanceof LiteralBooleanExpression)) { + return null; + } + + RuleExpression strExpr = subArgs.get(0); + int startIdx = ((LiteralIntegerExpression) subArgs.get(1)).value(); + int stopIdx = ((LiteralIntegerExpression) subArgs.get(2)).value(); + boolean reverse = ((LiteralBooleanExpression) subArgs.get(3)).value(); + + // The comparison can only ever be true when the lengths line up. + if (literal.length() != stopIdx - startIdx) { + return null; + } + + // Degenerate case: startIdx == stopIdx makes the spec's substring return null, so the + // coalesce yields "" and the comparison against an empty literal is true even for a null + // input. substringEquals cannot express that, so leave it to the general path. + if (literal.isEmpty()) { + return null; + } + + return FunctionCallExpression.builder() + .name(RuleRuntimeTypeMirror.SUBSTRING_EQUALS_FN) + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(strExpr) + .addArgument(new LiteralIntegerExpression(startIdx)) + .addArgument(new LiteralIntegerExpression(stopIdx)) + .addArgument(new LiteralBooleanExpression(reverse)) + .addArgument(new LiteralStringExpression(literal)) + .build(); + } + + /** + * Returns the {@code coalesce(expr, "")} call when the candidate matches that shape, else null. + */ + private FunctionCallExpression extractCoalesceWithEmptyDefault(RuleExpression candidate) { + if (!(candidate instanceof FunctionCallExpression)) { + return null; + } + FunctionCallExpression fn = (FunctionCallExpression) candidate; + if (!"coalesce".equals(fn.name())) { + return null; + } + List args = fn.arguments(); + if (args.size() != 2) { + return null; + } + RuleExpression defaultArg = args.get(1); + if (defaultArg.kind() != RuleExpression.RuleExpressionKind.STRING_VALUE) { + return null; + } + if (!"".equals(((LiteralStringExpression) defaultArg).value())) { + return null; + } + return fn; + } + + /** + * Rewrites {@code coalesce(boolExpr, boolLiteral)} so the generator can emit + * {@code expr != null ? expr : default} instead of a varargs call that boxes its arguments. + */ + private RuleExpression simplifyCoalesce(FunctionCallExpression e) { + List args = e.arguments(); + if (args.size() != 2 || args.get(1).kind() != RuleExpression.RuleExpressionKind.BOOLEAN_VALUE) { + return e; + } + return booleanFunction(COALESCE_BOOL, args.get(0), args.get(1)); + } + + /** + * Rewrites {@code ite(condition, ifTrue, ifFalse)} so the generator can emit a native ternary. + */ + private RuleExpression simplifyIte(FunctionCallExpression e) { + List args = e.arguments(); + if (args.size() != 3) { + return e; + } + return FunctionCallExpression.builder() + .name(ITE) + .type(RuleRuntimeTypeMirror.STRING) + .addArgument(args.get(0)) + .addArgument(args.get(1)) + .addArgument(args.get(2)) + .build(); + } + + /** + * Rewrites {@code isValidHostLabel(str, allowDots)} when {@code allowDots} is a compile-time + * constant, letting the generator call the specialized runtime helper that skips the branch. + */ + private RuleExpression simplifyIsValidHostLabel(FunctionCallExpression e) { + List args = e.arguments(); + if (args.size() != 2 || !(args.get(1) instanceof LiteralBooleanExpression)) { + return e; + } + return booleanFunction(IS_VALID_HOST_LABEL, args.get(0), args.get(1)); + } + + private RuleExpression booleanFunction(String name, RuleExpression arg0, RuleExpression arg1) { + return FunctionCallExpression.builder() + .name(name) + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(arg0) + .addArgument(arg1) + .build(); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddResultCodeGeneratorVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddResultCodeGeneratorVisitor.java new file mode 100644 index 000000000000..963fb6c92415 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddResultCodeGeneratorVisitor.java @@ -0,0 +1,427 @@ +/* + * 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.codegen.poet.rules.bdd; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; +import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair; +import software.amazon.awssdk.codegen.poet.rules.BooleanAndExpression; +import software.amazon.awssdk.codegen.poet.rules.BooleanNotExpression; +import software.amazon.awssdk.codegen.poet.rules.EndpointExpression; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; +import software.amazon.awssdk.codegen.poet.rules.EndpointUrlCodeEmitter; +import software.amazon.awssdk.codegen.poet.rules.ErrorExpression; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.HeadersExpression; +import software.amazon.awssdk.codegen.poet.rules.IndexedAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.LetExpression; +import software.amazon.awssdk.codegen.poet.rules.ListExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralIntegerExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.MemberAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.MethodCallExpression; +import software.amazon.awssdk.codegen.poet.rules.PropertiesExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpressionVisitor; +import software.amazon.awssdk.codegen.poet.rules.RuleFunctionMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleSetExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleType; +import software.amazon.awssdk.codegen.poet.rules.StringConcatExpression; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; + +/** + * Code generator visitor for BDD result methods that returns {@link Endpoint} directly + * and throws {@link SdkClientException} for error results. This eliminates the RuleResult + * wrapper allocation on the hot path. + */ +public class BddResultCodeGeneratorVisitor implements RuleExpressionVisitor { + private static final Logger log = LoggerFactory.getLogger(BddResultCodeGeneratorVisitor.class); + + private static final ClassName DYNAMIC_ENDPOINT_AUTH_SCHEME_FACTORY = + ClassName.get("software.amazon.awssdk.services.s3.endpoints.authscheme", "DynamicEndpointAuthSchemeFactory"); + + private final CodeBlock.Builder builder; + private final RuleRuntimeTypeMirror typeMirror; + private final Map registerInfoMap; + private final Map knownEndpointAttributes; + private final EndpointRulesSpecUtils endpointRulesSpecUtils; + private final boolean useS3ExpressSessionAuth; + + public BddResultCodeGeneratorVisitor( + CodeBlock.Builder builder, RuleRuntimeTypeMirror typeMirror, + Map registerInfoMap, + Map knownEndpointAttributes, + EndpointRulesSpecUtils endpointRulesSpecUtils, + boolean useS3ExpressSessionAuth) { + this.builder = builder; + this.typeMirror = typeMirror; + this.registerInfoMap = registerInfoMap; + this.knownEndpointAttributes = knownEndpointAttributes; + this.endpointRulesSpecUtils = endpointRulesSpecUtils; + this.useS3ExpressSessionAuth = useS3ExpressSessionAuth; + } + + @Override + public RuleType visitLiteralBooleanExpression(LiteralBooleanExpression e) { + builder.add(Boolean.toString(e.value())); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitLiteralIntegerExpression(LiteralIntegerExpression e) { + builder.add(Integer.toString(e.value())); + return RuleRuntimeTypeMirror.INTEGER; + } + + @Override + public RuleType visitLiteralStringExpression(LiteralStringExpression e) { + builder.add("$S", e.value()); + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitBooleanNotExpression(BooleanNotExpression e) { + builder.add("!"); + e.expression().accept(this); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitBooleanAndExpression(BooleanAndExpression e) { + List expressions = e.expressions(); + boolean isFirst = true; + for (RuleExpression expr : expressions) { + if (!isFirst) { + builder.add(" && "); + } + expr.accept(this); + isFirst = false; + } + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitFunctionCallExpression(FunctionCallExpression e) { + String fn = e.name(); + if ("not".equals(fn)) { + builder.add("!("); + e.arguments().get(0).accept(this); + builder.add(")"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isSet".equals(fn)) { + e.arguments().get(0).accept(this); + builder.add(" != null"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isNotSet".equals(fn)) { + e.arguments().get(0).accept(this); + builder.add(" == null"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + RuleFunctionMirror func = typeMirror.resolveFunction(e.name()); + builder.add("$T.$L(", func.containingType().type(), func.javaName()); + List args = e.arguments(); + for (int i = 0; i < args.size(); i++) { + if (i > 0) { + builder.add(", "); + } + args.get(i).accept(this); + } + builder.add(")"); + return func.returns(); + } + + @Override + public RuleType visitMethodCallExpression(MethodCallExpression e) { + e.source().accept(this); + builder.add(".$L(", e.name()); + boolean isFirst = true; + for (RuleExpression arg : e.arguments()) { + if (!isFirst) { + builder.add(", "); + } + arg.accept(this); + isFirst = false; + } + builder.add(")"); + return e.type(); + } + + @Override + public RuleType visitVariableReferenceExpression(VariableReferenceExpression e) { + RegistryInfo registryInfo = registerInfoMap.get(e.variableName()); + if (registryInfo.isNonRegionParam()) { + builder.add("params.$L()", endpointRulesSpecUtils.paramMethodName(registryInfo.getNonRegionParamKey())); + } else { + builder.add("$L", registryInfo.getName()); + } + return registerInfoMap.get(e.variableName()).getRuleType(); + } + + @Override + public RuleType visitMemberAccessExpression(MemberAccessExpression e) { + RuleType sourceType = e.source().accept(this); + if (!e.directIndex()) { + builder.add(".$L()", e.name()); + } + return sourceType.property(e.name()); + } + + @Override + public RuleType visitIndexedAccessExpression(IndexedAccessExpression e) { + RuleFunctionMirror func = typeMirror.resolveFunction("listAccess"); + builder.add("$T.$L(", func.containingType().type(), func.javaName()); + RuleType sourceType = e.source().accept(this); + builder.add(", $L)", e.index()); + return sourceType.typeParam(); + } + + @Override + public RuleType visitStringConcatExpression(StringConcatExpression e) { + boolean isFirst = true; + for (RuleExpression expr : e.expressions()) { + if (!isFirst) { + builder.add(" + "); + } + expr.accept(this); + isFirst = false; + } + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitLetExpression(LetExpression e) { + throw new IllegalStateException("Unexpected LetExpression in BDD result"); + } + + @Override + public RuleType visitRuleSetExpression(RuleSetExpression e) { + // BDD results MUST NOT contain any conditions + if (e.conditions().size() != 0) { + throw new IllegalStateException("Expected exactly zero conditions in BDD result"); + } + if (e.isError()) { + return e.error().accept(this); + } + if (e.isEndpoint()) { + return e.endpoint().accept(this); + } + throw new IllegalStateException("Expected Result to be either error or endpoint."); + } + + @Override + public RuleType visitListExpression(ListExpression e) { + builder.add("$T.asList(", Arrays.class); + boolean isFirst = true; + for (RuleExpression expr : e.expressions()) { + if (!isFirst) { + builder.add(", "); + } + expr.accept(this); + isFirst = false; + } + builder.add(")"); + return RuleRuntimeTypeMirror.LIST_OF_STRING; + } + + @Override + public RuleType visitEndpointExpression(EndpointExpression e) { + // Return Endpoint directly — no RuleResult wrapper + builder.add("return $T.builder().endpointUrl(", Endpoint.class); + EndpointUrlCodeEmitter.emit(e.url(), builder, this); + builder.add(")"); + e.headers().accept(this); + e.properties().accept(this); + builder.addStatement(".build()"); + return null; + } + + @Override + public RuleType visitPropertiesExpression(PropertiesExpression e) { + Map properties = e.properties(); + properties.forEach((k, v) -> { + if ("authSchemes".equals(k)) { + addAuthSchemesBlock(v); + } else if ("metricValues".equals(k)) { + addMetricValuesBlock(v); + } else if (knownEndpointAttributes.containsKey(k)) { + addAttributeBlock(k, v); + } else { + log.warn("Ignoring unknown endpoint property: {}", k); + } + }); + return null; + } + + @Override + public RuleType visitHeadersExpression(HeadersExpression e) { + e.headers().forEach((k, v) -> { + for (RuleExpression value : v.expressions()) { + builder.add(".putHeader($S, ", k); + value.accept(this); + builder.add(")"); + } + }); + return null; + } + + @Override + public RuleType visitErrorExpression(ErrorExpression e) { + // Throw SdkClientException directly — no RuleResult wrapper + builder.add("throw $T.create(", SdkClientException.class); + e.error().accept(this); + builder.addStatement(")"); + return null; + } + + private void addAuthSchemesBlock(RuleExpression e) { + ListExpression expr = (ListExpression) e; + builder.add(".putAttribute($T.AUTH_SCHEMES, ", AwsEndpointAttribute.class); + builder.add("$T.asList(", Arrays.class); + boolean isFirst = true; + for (RuleExpression authSchemeExpr : expr.expressions()) { + if (!isFirst) { + builder.add(", "); + } + addAuthSchemesBody(authSchemeExpr); + isFirst = false; + } + builder.add("))"); + } + + private void addAuthSchemesBody(RuleExpression e) { + if (e.kind() != RuleExpression.RuleExpressionKind.PROPERTIES) { + throw new RuntimeException("Expecting properties, got: " + e); + } + PropertiesExpression expr = (PropertiesExpression) e; + RuleExpression nameExpr = expr.properties().get("name"); + boolean isStaticName = nameExpr.kind() == RuleExpression.RuleExpressionKind.STRING_VALUE; + + if (isStaticName) { + builder.add("$T.builder()", authSchemeClass(stringValueOf(nameExpr))); + } else { + validateDynamicAuthSchemeSupported(nameExpr); + builder.add("$T.builder()", DYNAMIC_ENDPOINT_AUTH_SCHEME_FACTORY); + } + + expr.properties().forEach((k, v) -> { + if (!"name".equals(k)) { + builder.add(".$L(", k); + v.accept(this); + builder.add(")"); + } + }); + + if (isStaticName) { + builder.add(".build()"); + } else { + builder.add(".create("); + nameExpr.accept(this); + builder.add(")"); + } + } + + private void validateDynamicAuthSchemeSupported(RuleExpression nameExpr) { + if (!useS3ExpressSessionAuth) { + throw new IllegalStateException( + "Endpoint ruleset contains an auth scheme whose name is resolved at runtime (" + nameExpr + "), but the " + + "'useS3ExpressSessionAuth' customization is not enabled for this service. Dynamically resolved auth " + + "scheme names are currently only supported for S3."); + } + } + + private String stringValueOf(RuleExpression e) { + if (e.kind() != RuleExpression.RuleExpressionKind.STRING_VALUE) { + throw new RuntimeException("Expecting string value, got: " + e); + } + return ((LiteralStringExpression) e).value(); + } + + private ClassName authSchemeClass(String name) { + switch (name) { + case "sigv4": + return ClassName.get(SigV4AuthScheme.class); + case "sigv4a": + return ClassName.get(SigV4aAuthScheme.class); + case "sigv4-s3express": + return ClassName.get("software.amazon.awssdk.services.s3.endpoints.authscheme", + "S3ExpressEndpointAuthScheme"); + default: + throw new RuntimeException("Unknown auth scheme: " + name); + } + } + + private void addAttributeBlock(String k, RuleExpression v) { + KeyTypePair keyType = knownEndpointAttributes.get(k); + ClassConstant classConstant = parseClassConstant(keyType.getKey()); + builder.add(".putAttribute($T.$L, ", classConstant.className(), classConstant.fieldName()); + v.accept(this); + builder.add(")"); + } + + private ClassConstant parseClassConstant(String value) { + int lastDot = value.lastIndexOf('.'); + if (lastDot == -1) { + throw new IllegalArgumentException("cannot parse class constant: " + value); + } + String fieldName = value.substring(lastDot + 1); + String className = value.substring(0, lastDot); + int classLastDot = className.lastIndexOf('.'); + if (classLastDot == -1) { + throw new IllegalArgumentException("cannot parse class constant: " + value); + } + String simpleName = className.substring(classLastDot + 1); + String packageName = className.substring(0, classLastDot); + return new ClassConstant(ClassName.get(packageName, simpleName), fieldName); + } + + private void addMetricValuesBlock(RuleExpression v) { + builder.add(".putAttribute($T.METRIC_VALUES, ", AwsEndpointAttribute.class); + v.accept(this); + builder.add(")"); + } + + static class ClassConstant { + private final ClassName className; + private final String fieldName; + + ClassConstant(ClassName className, String fieldName) { + this.className = className; + this.fieldName = fieldName; + } + + public ClassName className() { + return className; + } + + public String fieldName() { + return fieldName; + } + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitor.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitor.java new file mode 100644 index 000000000000..e5b8f6419b1a --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitor.java @@ -0,0 +1,399 @@ +/* + * 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.codegen.poet.rules.bdd; + +import com.squareup.javapoet.CodeBlock; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.codegen.poet.rules.BooleanAndExpression; +import software.amazon.awssdk.codegen.poet.rules.BooleanNotExpression; +import software.amazon.awssdk.codegen.poet.rules.EndpointExpression; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; +import software.amazon.awssdk.codegen.poet.rules.ErrorExpression; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.HeadersExpression; +import software.amazon.awssdk.codegen.poet.rules.IndexedAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.LetExpression; +import software.amazon.awssdk.codegen.poet.rules.ListExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralIntegerExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.MemberAccessExpression; +import software.amazon.awssdk.codegen.poet.rules.MethodCallExpression; +import software.amazon.awssdk.codegen.poet.rules.PropertiesExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpressionVisitor; +import software.amazon.awssdk.codegen.poet.rules.RuleFunctionMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.RuleSetExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleType; +import software.amazon.awssdk.codegen.poet.rules.StringConcatExpression; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; + +public class ConditionFnCodeGeneratorVisitor implements RuleExpressionVisitor { + private static final Logger log = LoggerFactory.getLogger(ConditionFnCodeGeneratorVisitor.class); + private final CodeBlock.Builder builder; + private final RuleRuntimeTypeMirror typeMirror; + private final Map registerInfoMap; + private final EndpointRulesSpecUtils endpointRulesSpecUtils; + + public ConditionFnCodeGeneratorVisitor(CodeBlock.Builder builder, RuleRuntimeTypeMirror typeMirror, + Map registerInfoMap, + EndpointRulesSpecUtils endpointRulesSpecUtils) { + this.builder = builder; + this.typeMirror = typeMirror; + this.registerInfoMap = registerInfoMap; + this.endpointRulesSpecUtils = endpointRulesSpecUtils; + } + + @Override + public RuleType visitLiteralBooleanExpression(LiteralBooleanExpression e) { + builder.add(Boolean.toString(e.value())); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitLiteralIntegerExpression(LiteralIntegerExpression e) { + builder.add(Integer.toString(e.value())); + return RuleRuntimeTypeMirror.INTEGER; + } + + @Override + public RuleType visitLiteralStringExpression(LiteralStringExpression e) { + builder.add("$S", e.value()); + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitBooleanNotExpression(BooleanNotExpression e) { + builder.add("!"); + e.expression().accept(this); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitBooleanAndExpression(BooleanAndExpression e) { + List expressions = e.expressions(); + boolean isFirst = true; + for (RuleExpression expr : expressions) { + if (!isFirst) { + builder.add(" && "); + } + expr.accept(this); + isFirst = false; + } + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitFunctionCallExpression(FunctionCallExpression e) { + String fn = e.name(); + if ("not".equals(fn)) { + builder.add("!("); + e.arguments().get(0).accept(this); + builder.add(")"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isSet".equals(fn)) { + e.arguments().get(0).accept(this); + builder.add(" != null"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + if ("isNotSet".equals(fn)) { + e.arguments().get(0).accept(this); + builder.add(" == null"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + // Synthetic functions that are emitted as inline Java rather than a static call. + // __substringEquals is not among them: it is a registered function and falls through below. + if (BddPeepholeVisitor.isCustomEmitted(fn)) { + return emitPeepholeOptimized(fn, e.arguments()); + } + + RuleFunctionMirror func = typeMirror.resolveFunction(e.name()); + builder.add("$T.$L(", func.containingType().type(), func.javaName()); + List args = e.arguments(); + RuleType lastArgType = RuleRuntimeTypeMirror.VOID; + for (int i = 0; i < args.size(); i++) { + if (i > 0) { + builder.add(", "); + } + lastArgType = args.get(i).accept(this); + } + builder.add(")"); + if ("coalesce".equals(fn)) { + // special case type inference for coalesce + return lastArgType; + } + return func.returns(); + } + + /** + * Emits inline Java for synthetic function calls that have no static-call equivalent, avoiding + * the boxing and varargs allocation of the corresponding RulesFunctions calls. + */ + private RuleType emitPeepholeOptimized(String fn, List args) { + switch (fn) { + case BddPeepholeVisitor.ITE: + // __ite(cond, ifTrue, ifFalse) → (cond ? ifTrue : ifFalse) + return emitIte(args); + case BddPeepholeVisitor.COALESCE_BOOL: + // __coalesceBoolean(expr, default) → (expr != null ? expr : default) + return emitCoalesceBoolean(args); + case BddPeepholeVisitor.IS_VALID_HOST_LABEL: + // __isValidHostLabel(str, allowDots) → inline validation + return emitIsValidHostLabel(args); + default: + throw new IllegalStateException("Unknown peephole function: " + fn); + } + } + + /** + * Emits: {@code (cond ? ifTrue : ifFalse)} + */ + private RuleType emitIte(List args) { + builder.add("("); + args.get(0).accept(this); + builder.add(" ? "); + args.get(1).accept(this); + builder.add(" : "); + args.get(2).accept(this); + builder.add(")"); + return RuleRuntimeTypeMirror.STRING; + } + + /** + * Emits a single-evaluation equivalent of {@code coalesce(expr, defaultValue)} for a boolean + * default. Wrapper equality gives exact coalesce semantics with no branch and no boxing: + * + * + * + * + * + * + * + * + *
Rewrite table
rewriteemittednullTRUEFALSE
{@code coalesce(x, false)}{@code Boolean.TRUE.equals(x)}falsetruefalse
{@code coalesce(x, true)}{@code !Boolean.FALSE.equals(x)}truetruefalse
+ * + *

The subject is emitted once. A ternary would emit it twice, which runs any non-trivial + * operand (a nested rules function, for instance) twice per evaluation. + */ + private RuleType emitCoalesceBoolean(List args) { + boolean defaultValue = ((LiteralBooleanExpression) args.get(1)).value(); + if (defaultValue) { + builder.add("!Boolean.FALSE.equals("); + } else { + builder.add("Boolean.TRUE.equals("); + } + args.get(0).accept(this); + builder.add(")"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + /** + * Emits: {@code RulesFunctions.isValidHostLabelSingle(str)} or + * {@code RulesFunctions.isValidHostLabelMulti(str)} depending on the allowDots constant. + * Avoids the boolean parameter dispatch branch at runtime. + */ + private RuleType emitIsValidHostLabel(List args) { + boolean allowDots = ((LiteralBooleanExpression) args.get(1)).value(); + RuleFunctionMirror func = typeMirror.resolveFunction("isValidHostLabel"); + builder.add("$T.$L(", func.containingType().type(), + allowDots ? "isValidHostLabelMulti" : "isValidHostLabelSingle"); + args.get(0).accept(this); + builder.add(")"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + + @Override + public RuleType visitMethodCallExpression(MethodCallExpression e) { + e.source().accept(this); + builder.add(".$L(", e.name()); + boolean isFirst = true; + for (RuleExpression arg : e.arguments()) { + if (!isFirst) { + builder.add(", "); + } + arg.accept(this); + isFirst = false; + } + builder.add(")"); + if ("equals".equals(e.name())) { + return RuleRuntimeTypeMirror.BOOLEAN; + } + return e.type(); + } + + @Override + public RuleType visitVariableReferenceExpression(VariableReferenceExpression e) { + RegistryInfo registryInfo = registerInfoMap.get(e.variableName()); + if (registryInfo.isNonRegionParam()) { + builder.add("params.$L()", endpointRulesSpecUtils.paramMethodName(registryInfo.getNonRegionParamKey())); + } else { + builder.add("$L", registryInfo.getName()); + } + return registerInfoMap.get(e.variableName()).getRuleType(); + } + + @Override + public RuleType visitMemberAccessExpression(MemberAccessExpression e) { + RuleType sourceType = e.source().accept(this); + if (!e.directIndex()) { + builder.add(".$L()", e.name()); + } + return sourceType.property(e.name()); + } + + @Override + public RuleType visitIndexedAccessExpression(IndexedAccessExpression e) { + RuleFunctionMirror func = typeMirror.resolveFunction("listAccess"); + builder.add("$T.$L(", func.containingType().type(), func.javaName()); + RuleType sourceType = e.source().accept(this); + builder.add(", $L)", e.index()); + return sourceType.typeParam(); + } + + @Override + public RuleType visitStringConcatExpression(StringConcatExpression e) { + boolean isFirst = true; + for (RuleExpression expr : e.expressions()) { + if (!isFirst) { + builder.add(" + "); + } + expr.accept(this); + isFirst = false; + } + return RuleRuntimeTypeMirror.STRING; + } + + @Override + public RuleType visitLetExpression(LetExpression e) { + if (e.bindings().size() != 1) { + throw new IllegalStateException("Expected exactly one binding"); + } + for (Map.Entry kvp : e.bindings().entrySet()) { + String k = kvp.getKey(); + RuleExpression v = kvp.getValue(); + String registerName = registerInfoMap.get(k).getName(); + builder.add("$L = ", registerName); + v.accept(this); + builder.addStatement(""); // end the statement we started + // Assign conditions succeed only when the assigned value is non-null. Skip the check + // only where the value is provably non-null, otherwise emit it. + if (isAlwaysNonNull(v)) { + builder.addStatement("return true"); + } else { + builder.addStatement("return $L != null", registerName); + } + } + return RuleRuntimeTypeMirror.BOOLEAN; + } + + /** + * Returns true only if the expression is provably non-null at runtime. + * + *

Recognizes {@code __ite} whose two branches are both string literals, which + * {@link #emitIte} emits as a ternary between them. {@code BddPeepholeVisitor.simplifyIte} does + * not constrain the branches, and {@code RuleRuntimeTypeMirror} types them as {@code STRING}, so + * a {@code {"ref": ...}} branch is legal input from the endpoint compiler and can be null. Both + * branches are therefore checked here rather than assumed: eliding the register null-check for a + * nullable branch would report an assign condition as satisfied with a null register, flipping a + * BDD edge and resolving an endpoint the spec does not permit. + */ + private static boolean isAlwaysNonNull(RuleExpression expr) { + if (!(expr instanceof FunctionCallExpression)) { + return false; + } + FunctionCallExpression fn = (FunctionCallExpression) expr; + if (!BddPeepholeVisitor.ITE.equals(fn.name()) || fn.arguments().size() != 3) { + return false; + } + return fn.arguments().get(1).kind() == RuleExpression.RuleExpressionKind.STRING_VALUE + && fn.arguments().get(2).kind() == RuleExpression.RuleExpressionKind.STRING_VALUE; + } + + @Override + public RuleType visitRuleSetExpression(RuleSetExpression e) { + // generate the conditions - there may be multiple assigns (LET) + // but there will be only one condition + if (e.conditions().size() != 1) { + throw new IllegalStateException("Expected exactly one condition"); + } + RuleExpression condition = e.conditions().get(0); + if (condition.kind() == RuleExpression.RuleExpressionKind.LET) { + condition.accept(this); // lets are self contained + } else { + builder.add("return ("); + if (RuleExpression.RuleExpressionKind.VARIABLE_REFERENCE == condition.kind()) { + VariableReferenceExpression varRef = (VariableReferenceExpression) condition; + RegistryInfo registryInfo = registerInfoMap.get(varRef.variableName()); + // special case optimization: do not auto-box booleanEquals! + if (registryInfo.isNullable() && RuleRuntimeTypeMirror.BOOLEAN.equals(registryInfo.getRuleType())) { + builder.add("Boolean.TRUE.equals($L)", registryInfo.getName()); + builder.addStatement(")"); + return RuleRuntimeTypeMirror.BOOLEAN; + } + } + RuleType type = condition.accept(this); + if (type != null && !RuleRuntimeTypeMirror.BOOLEAN.equals(type)) { + log.warn("Expected boolean, got {}. Rewriting condition with a != null. Condition: `{}`", type, condition); + builder.add(" != null"); + } + builder.addStatement(")"); // finish the expression we started + } + return RuleRuntimeTypeMirror.VOID; + } + + @Override + public RuleType visitListExpression(ListExpression e) { + builder.add("$T.asList(", Arrays.class); + boolean isFirst = true; + for (RuleExpression expr : e.expressions()) { + if (!isFirst) { + builder.add(", "); + } + expr.accept(this); + isFirst = false; + } + builder.add(")"); + // TODO: this could potentially be another type + return RuleRuntimeTypeMirror.LIST_OF_STRING; + } + + @Override + public RuleType visitEndpointExpression(EndpointExpression e) { + throw new IllegalStateException("Unexpected EndpointExpression"); + } + + @Override + public RuleType visitErrorExpression(ErrorExpression e) { + throw new IllegalStateException("Unexpected ErrorExpression"); + } + + @Override + public RuleType visitPropertiesExpression(PropertiesExpression e) { + throw new IllegalStateException("Unexpected PropertiesExpression"); + } + + @Override + public RuleType visitHeadersExpression(HeadersExpression e) { + throw new IllegalStateException("Unexpected HeadersExpression"); + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/RegistryInfo.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/RegistryInfo.java new file mode 100644 index 000000000000..8246d1071335 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/bdd/RegistryInfo.java @@ -0,0 +1,76 @@ +/* + * 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.codegen.poet.rules.bdd; + +import software.amazon.awssdk.codegen.poet.rules.RuleSetExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleType; + +public class RegistryInfo { + private final String name; + // ruleType may be set after construction by the type-inference pass (AssignTypeInferringVisitor) + private RuleType ruleType; + // set only when this value is assigned from a condition, NOT set for parameters + private final RuleSetExpression ruleSetExpression; + // defaults to true; false only when we guarantee that the value cannot be null. + private final boolean nullable; + // set only when this is an endpoint parameter, EXCEPT in the case of Region built-in which is a special case + private final String nonRegionParamKey; + + public RegistryInfo(String name, RuleType ruleType, RuleSetExpression ruleSetExpression, boolean nullable, + String nonRegionParamKey) { + this.name = name; + this.ruleType = ruleType; + this.ruleSetExpression = ruleSetExpression; + this.nullable = nullable; + this.nonRegionParamKey = nonRegionParamKey; + } + + public RegistryInfo(String name, RuleType ruleType, String paramKey) { + this(name, ruleType, null, true, paramKey); + } + + public RegistryInfo(String name, RuleSetExpression ruleSetExpression) { + this(name, null, ruleSetExpression, true, null); + } + + public String getName() { + return name; + } + + public RuleType getRuleType() { + return ruleType; + } + + public void setRuleType(RuleType ruleType) { + this.ruleType = ruleType; + } + + public RuleSetExpression getRuleSetExpression() { + return ruleSetExpression; + } + + public boolean isNullable() { + return nullable; + } + + public String getNonRegionParamKey() { + return nonRegionParamKey; + } + + public boolean isNonRegionParam() { + return nonRegionParamKey != null; + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java deleted file mode 100644 index 55dbf5358842..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/EndpointProviderSpec2.java +++ /dev/null @@ -1,264 +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.codegen.poet.rules2; - -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeName; -import com.squareup.javapoet.TypeSpec; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import javax.lang.model.element.Modifier; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.codegen.model.config.customization.EndpointAuthSchemeConfig; -import software.amazon.awssdk.codegen.model.config.customization.KeyTypePair; -import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; -import software.amazon.awssdk.codegen.model.intermediate.Metadata; -import software.amazon.awssdk.codegen.model.rules.endpoints.BuiltInParameter; -import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; -import software.amazon.awssdk.codegen.model.rules.endpoints.RuleModel; -import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; -import software.amazon.awssdk.codegen.poet.ClassSpec; -import software.amazon.awssdk.codegen.poet.PoetUtils; -import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Validate; - -public class EndpointProviderSpec2 implements ClassSpec { - private final IntermediateModel intermediateModel; - private final EndpointRulesSpecUtils endpointRulesSpecUtils; - private final Map knownEndpointAttributes; - private final CodegenExpressionBuidler utils; - private final RuleRuntimeTypeMirror typeMirror; - - public EndpointProviderSpec2(IntermediateModel intermediateModel) { - this.intermediateModel = intermediateModel; - this.endpointRulesSpecUtils = new EndpointRulesSpecUtils(intermediateModel); - String packageName = intermediateModel.getMetadata().getFullInternalEndpointRulesPackageName(); - this.typeMirror = new RuleRuntimeTypeMirror(packageName); - EndpointRuleSetModel model = intermediateModel.getEndpointRuleSetModel(); - this.utils = createCodegenRulesUtil(model.getRules(), model.getParameters(), typeMirror); - this.knownEndpointAttributes = knownEndpointAttributes(intermediateModel); - } - - private static RuleType fromParameterModel(ParameterModel model) { - switch (model.getType().toLowerCase(Locale.ENGLISH)) { - case "boolean": - return RuleRuntimeTypeMirror.BOOLEAN; - case "string": - return RuleRuntimeTypeMirror.STRING; - case "stringarray": - return RuleRuntimeTypeMirror.LIST_OF_STRING; - default: - throw new IllegalStateException("Cannot find rule type for: " + model.getType()); - } - } - - private static RuleModel createRootRule(List rules) { - RuleModel root = new RuleModel(); - root.setRules(rules); - root.setType("tree"); - root.setConditions(Collections.emptyList()); - return root; - } - - private static CodegenExpressionBuidler createCodegenRulesUtil(List rules, - Map parameters, - RuleRuntimeTypeMirror typeMirror) { - RuleSetExpression root = ExpressionParser.parseRuleSetExpression(createRootRule(rules)); - return CodegenExpressionBuidler.from(root, typeMirror, initSymbolTable(parameters)); - } - - private static SymbolTable initSymbolTable(Map parameters) { - SymbolTable.Builder builder = SymbolTable.builder(); - parameters.forEach((k, v) -> { - builder.putParam(k, fromParameterModel(v)); - if (v.getBuiltInEnum() == BuiltInParameter.AWS_REGION) { - // Region is a special case since it's already public API and uses an actual `Region` instance instead of - // `String`. We then introduce here a local with the same name but with String type such that we don't have - // to do the conversion everywhere a string represented region is used. - builder.regionParamName(k); - builder.putLocal(k, RuleRuntimeTypeMirror.STRING); - } - }); - return builder.build(); - } - - private static Map knownEndpointAttributes(IntermediateModel intermediateModel) { - Map knownEndpointAttributes = null; - EndpointAuthSchemeConfig config = intermediateModel.getCustomizationConfig().getEndpointAuthSchemeConfig(); - if (config != null) { - knownEndpointAttributes = config.getEndpointProviderTestKeys(); - } - if (knownEndpointAttributes == null) { - knownEndpointAttributes = Collections.emptyMap(); - } - return knownEndpointAttributes; - } - - @Override - public TypeSpec poetSpec() { - TypeSpec.Builder builder = PoetUtils.createClassBuilder(className()) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .addSuperinterface(endpointRulesSpecUtils.providerInterfaceName()) - .addAnnotation(SdkInternalApi.class); - - builder.addMethod(resolveEndpointMethod()); - List methods = new ArrayList<>(); - createRuleMethod(utils.root(), methods); - for (MethodSpec.Builder methodBuilder : methods) { - builder.addMethod(methodBuilder.build()); - } - builder.addMethod(equalsMethod()); - builder.addMethod(hashCodeMethod()); - return builder.build(); - } - - @Override - public ClassName className() { - Metadata md = intermediateModel.getMetadata(); - return ClassName.get(md.getFullInternalEndpointRulesPackageName(), - "Default" + endpointRulesSpecUtils.providerInterfaceName().simpleName()); - } - - private MethodSpec resolveEndpointMethod() { - MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveEndpoint") - .addModifiers(Modifier.PUBLIC) - .returns(endpointRulesSpecUtils.resolverReturnType()) - .addAnnotation(Override.class) - .addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); - - builder.addCode(validateRequiredParams()); - builder.beginControlFlow("try"); - String regionParamName = utils.regionParamName(); - if (regionParamName != null) { - builder.addStatement("$T region = params.$L()", Region.class, regionParamName); - builder.addStatement("$T regionId = region == null ? null : region.id()", String.class); - builder.addStatement("$T result = $L(params, regionId)", ruleResult(), utils.root().ruleId()); - } else { - builder.addStatement("$T result = $L(params)", ruleResult(), utils.root().ruleId()); - } - builder.beginControlFlow("if (result.canContinue())") - .addStatement("throw $T.create($S)", SdkClientException.class, "Rule engine did not reach an error or " - + "endpoint result") - .endControlFlow(); - - builder.beginControlFlow("if (result.isError())") - .addStatement("String errorMsg = result.error()") - .beginControlFlow("if (errorMsg.contains(\"Invalid ARN\") && errorMsg.contains(\":s3:::\"))") - .addStatement("errorMsg += $S", ". Use the bucket name instead of simple bucket ARNs in " - + "GetBucketLocationRequest.") - .endControlFlow() - .addStatement("throw $T.create(errorMsg)", SdkClientException.class) - .endControlFlow(); - - builder.addStatement("return $T.completedFuture(result.endpoint())", CompletableFuture.class); - builder.nextControlFlow("catch ($T error)", Exception.class); - builder.addStatement("return $T.failedFuture(error)", CompletableFutureUtils.class); - builder.endControlFlow(); - - return builder.build(); - } - - private CodeBlock validateRequiredParams() { - CodeBlock.Builder b = CodeBlock.builder(); - Map parameters = intermediateModel.getEndpointRuleSetModel().getParameters(); - parameters.entrySet().stream() - .filter(e -> Boolean.TRUE.equals(e.getValue().isRequired())) - .forEach(e -> { - b.addStatement("$T.notNull($N.$N(), $S)", - Validate.class, - "params", - endpointRulesSpecUtils.paramMethodName(e.getKey()), - String.format("Parameter '%s' must not be null", e.getKey())); - }); - - return b.build(); - } - - private void createRuleMethod(RuleSetExpression expr, List methods) { - MethodSpec.Builder builder = methodBuilderForRule(expr); - methods.add(builder); - CodeBlock.Builder block = CodeBlock.builder(); - codegenExpr(expr, block); - builder.addCode(block.build()); - if (expr.isTree()) { - for (RuleSetExpression child : expr.children()) { - if (child.isTree()) { - createRuleMethod(child, methods); - } - } - } - } - - private MethodSpec.Builder methodBuilderForRule(RuleSetExpression expr) { - MethodSpec.Builder builder = - MethodSpec.methodBuilder(expr.ruleId()) - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .returns(ruleResult()); - ComputeScopeTree.Scope scope = utils.scopesByName().get(expr.ruleId()); - builder.addParameter(endpointRulesSpecUtils.parametersClassName(), "params"); - for (String param : scope.usesLocals()) { - if (scope.defines().contains(param)) { - continue; - } - RuleType type = utils.symbolTable().localType(param); - builder.addParameter(type.javaType(), param); - } - return builder; - } - - private void codegenExpr(RuleSetExpression expr, CodeBlock.Builder builder) { - boolean useEndpointCaching = intermediateModel.getCustomizationConfig().getEnableEndpointProviderUriCaching(); - CodeGeneratorVisitor visitor = new CodeGeneratorVisitor(typeMirror, - utils.symbolTable(), - knownEndpointAttributes, - utils.scopesByName(), - useEndpointCaching, - builder); - visitor.visitRuleSetExpression(expr); - } - - private TypeName ruleResult() { - return typeMirror.rulesResult().type(); - } - - private MethodSpec equalsMethod() { - return MethodSpec.methodBuilder("equals") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(boolean.class) - .addParameter(Object.class, "rhs") - .addStatement("return rhs != null && getClass().equals(rhs.getClass())") - .build(); - } - - private MethodSpec hashCodeMethod() { - return MethodSpec.methodBuilder("hashCode") - .addAnnotation(Override.class) - .addModifiers(Modifier.PUBLIC) - .returns(int.class) - .addStatement("return getClass().hashCode()") - .build(); - } -} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java deleted file mode 100644 index 67176abfa146..000000000000 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/SymbolTable.java +++ /dev/null @@ -1,111 +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.codegen.poet.rules2; - -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; -import software.amazon.awssdk.utils.Validate; - -public final class SymbolTable { - private final Map params; - private final Map locals; - private final String regionParamName; - - SymbolTable(Builder builder) { - this.params = Collections.unmodifiableMap(new LinkedHashMap<>(builder.params)); - this.locals = Collections.unmodifiableMap(new LinkedHashMap<>(builder.locals)); - this.regionParamName = builder.regionParamName; - } - - public static Builder builder() { - return new Builder(); - } - - public boolean isParam(String name) { - return params.containsKey(name); - } - - public RuleType paramType(String name) { - return params.get(name); - } - - public boolean isLocal(String name) { - return locals.containsKey(name); - } - - public RuleType localType(String name) { - return locals.get(name); - } - - public Map locals() { - return locals; - } - - public Map params() { - return params; - } - - public String regionParamName() { - return regionParamName; - } - - public Builder toBuilder() { - return new Builder(this); - } - - public static class Builder { - private final Map params = new LinkedHashMap<>(); - private final Map locals = new LinkedHashMap<>(); - private String regionParamName; - - public Builder() { - } - - public Builder(SymbolTable table) { - this.params.putAll(table.params); - this.locals.putAll(table.locals); - this.regionParamName = table.regionParamName; - } - - public Builder putParam(String name, RuleType type) { - params.put(Validate.paramNotNull(name, "name"), Validate.paramNotNull(type, "type")); - return this; - } - - public RuleType param(String name) { - return params.get(name); - } - - public Builder putLocal(String name, RuleType type) { - locals.put(Validate.paramNotNull(name, "name"), Validate.paramNotNull(type, "type")); - return this; - } - - public RuleType local(String name) { - return locals.get(name); - } - - public Builder regionParamName(String regionParamName) { - this.regionParamName = regionParamName; - return this; - } - - public SymbolTable build() { - return new SymbolTable(this); - } - } -} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelector.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelector.java new file mode 100644 index 000000000000..f056c0e63df9 --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelector.java @@ -0,0 +1,163 @@ +/* + * 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.codegen.poet.warmup; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +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.codegen.model.intermediate.ShapeModel; +import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.NumericUtils; + +/** + * Selects the operation used for the warm-up call: filters out streaming/event-stream and deprecated + * operations, plus operations that cannot be dummy-filled (see {@link #membersRequiringDummyValue}), then ranks the + * rest (see {@link #warmUpPreference}). + */ +public final class WarmUpOperationSelector { + + private static final List PREFERRED_VERBS = Arrays.asList("List", "Describe", "Get"); + + private static final Comparator BY_HAS_OUTPUT_FIRST = + Comparator.comparing(op -> hasOutput(op) ? 0 : 1); + + private static final Comparator BY_AUTHENTICATED_FIRST = + Comparator.comparing(op -> op.isAuthenticated() ? 0 : 1); + + private static final Comparator BY_EMPTY_REQUEST_FIRST = + Comparator.comparing(op -> acceptsEmptyRequest(op) ? 0 : 1); + + private static final Comparator BY_FEWEST_REQUIRED_INPUTS = + Comparator.comparingInt(WarmUpOperationSelector::requiredInputMemberCount); + + private static final Comparator BY_PREFERRED_VERB = + Comparator.comparingInt(WarmUpOperationSelector::verbRank); + + private static final Comparator BY_NAME_ALPHABETICAL = + Comparator.comparing(OperationModel::getOperationName); + + private WarmUpOperationSelector() { + } + + /** + * Selects the warm-up operation for the given service, or {@link Optional#empty()} if no operation is safe to + * call as a warm-up. + */ + public static Optional selectWarmUpOperation(IntermediateModel model) { + List verifiedSimpleMethods = model.getCustomizationConfig().getVerifiedSimpleMethods(); + Comparator preference = warmUpPreference(verifiedSimpleMethods); + + return model.getOperations().values().stream() + .filter(WarmUpOperationSelector::passesHardGates) + .min(preference); + } + + /** + * Returns the required input members that need a dummy value in the warm-up call. A member needs one when it is + * bound to the URI path (a null breaks marshalling) or is an endpoint context param (a null breaks endpoint + * resolution). + */ + static List membersRequiringDummyValue(OperationModel operation) { + return inputMembers(operation).stream() + .filter(MemberModel::isRequired) + .filter(WarmUpOperationSelector::isUriOrEndpointBound) + .collect(Collectors.toList()); + } + + /** + * Preference order: returns output (so the unmarshaller is warmed too), is authenticated (so auth-scheme + * resolution and the signer are warmed too; {@code noAuth} operations resolve to a no-op signer instead), verified + * simple method, accepts an empty request, fewest required input members, read-only verb, then operation name as + * the deterministic tie-break. + */ + private static Comparator warmUpPreference(List verifiedSimpleMethods) { + return BY_HAS_OUTPUT_FIRST + .thenComparing(BY_AUTHENTICATED_FIRST) + .thenComparing(byVerifiedSimpleFirst(verifiedSimpleMethods)) + .thenComparing(BY_EMPTY_REQUEST_FIRST) + .thenComparing(BY_FEWEST_REQUIRED_INPUTS) + .thenComparing(BY_PREFERRED_VERB) + .thenComparing(BY_NAME_ALPHABETICAL); + } + + /** + * Unlike the other tiers, this one depends on the service's customization config, so it cannot be a static + * comparator constant. + */ + private static Comparator byVerifiedSimpleFirst(List verifiedSimpleMethods) { + return Comparator.comparing(op -> verifiedSimpleMethods.contains(op.getMethodName()) ? 0 : 1); + } + + private static boolean passesHardGates(OperationModel operation) { + return !isStreamingOrEventStream(operation) + && !operation.isDeprecated() + && allDummyMembersAreFillable(operation); + } + + /** + * A member is fillable only if it is a string, since the warm-up call emits a string dummy value + * ({@code "warmup"}). + */ + private static boolean allDummyMembersAreFillable(OperationModel operation) { + return membersRequiringDummyValue(operation).stream() + .allMatch(member -> "String".equals(member.getVariable().getSimpleType())); + } + + private static boolean isUriOrEndpointBound(MemberModel member) { + return (member.getHttp() != null && member.getHttp().isUri()) + || member.getContextParam() != null; + } + + private static boolean isStreamingOrEventStream(OperationModel operation) { + return operation.isStreaming() || operation.hasEventStreamInput() || operation.hasEventStreamOutput(); + } + + private static boolean acceptsEmptyRequest(OperationModel operation) { + return requiredInputMemberCount(operation) == 0; + } + + private static boolean hasOutput(OperationModel operation) { + return operation.getOutputShape() != null; + } + + private static int requiredInputMemberCount(OperationModel operation) { + return NumericUtils.saturatedCast(inputMembers(operation).stream().filter(MemberModel::isRequired).count()); + } + + private static List inputMembers(OperationModel operation) { + ShapeModel inputShape = operation.getInputShape(); + if (inputShape == null || CollectionUtils.isNullOrEmpty(inputShape.getMembers())) { + return Collections.emptyList(); + } + return inputShape.getMembers(); + } + + private static int verbRank(OperationModel operation) { + String operationName = operation.getOperationName(); + for (int i = 0; i < PREFERRED_VERBS.size(); i++) { + if (operationName.startsWith(PREFERRED_VERBS.get(i))) { + return i; + } + } + return Integer.MAX_VALUE; + } +} diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpec.java new file mode 100644 index 000000000000..0bdef4a2251e --- /dev/null +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpec.java @@ -0,0 +1,260 @@ +/* + * 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.codegen.poet.warmup; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.TypeSpec; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Optional; +import javax.lang.model.element.Modifier; +import software.amazon.awssdk.annotations.SdkInternalApi; +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.codegen.model.intermediate.Protocol; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.PoetExtension; +import software.amazon.awssdk.codegen.poet.PoetUtils; +import software.amazon.awssdk.codegen.utils.AuthUtils; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Generates an {@link SdkWarmUpProvider} implementation per service. + * + *

The {@code warmUpClient(ClientType)} body instantiates and closes a synthetic sync client (when the service + * generates one) and a synthetic async client, each guarded by the requested {@link ClientType} and wired to an + * in-memory canned HTTP client, anonymous credentials, a fixed region and a local {@code endpointOverride}. Building + * the clients JIT-compiles the client construction and configuration-resolution path before a CRaC checkpoint. Each + * client also invokes the operation chosen by {@link WarmUpOperationSelector}, if any, to warm up the marshalling, + * auth-scheme resolution and unmarshalling paths. The {@code syncClientClassName()}/{@code asyncClientClassName()} + * strings let {@code SdkWarmUp.warmUp(Class...)} match a requested client class to this provider. + */ +public class WarmUpProviderSpec implements ClassSpec { + + private static final String CANNED_RESPONSE_FIELD = "CANNED_RESPONSE"; + + // Values emitted into the warm-up call. Anonymous credentials and a local endpoint keep the call offline; a 200 + // status exercises the success path. + private static final int SUCCESS_STATUS_CODE = 200; + private static final String DUMMY_TOKEN = "warmup-dummy-token"; + private static final String LOCAL_ENDPOINT = "http://localhost"; + + private static final String DUMMY_MEMBER_VALUE = "warmup"; + + private static final ClassName CANNED_RESPONSE_HTTP_CLIENT = + ClassName.get("software.amazon.awssdk.core.warmup.http", "CannedResponseHttpClient"); + private static final ClassName CANNED_RESPONSE_ASYNC_HTTP_CLIENT = + ClassName.get("software.amazon.awssdk.core.warmup.http", "CannedResponseAsyncHttpClient"); + private static final ClassName SDK_HTTP_CLIENT = + ClassName.get("software.amazon.awssdk.http", "SdkHttpClient"); + private static final ClassName SDK_ASYNC_HTTP_CLIENT = + ClassName.get("software.amazon.awssdk.http.async", "SdkAsyncHttpClient"); + private static final ClassName ANONYMOUS_CREDENTIALS_PROVIDER = + ClassName.get("software.amazon.awssdk.auth.credentials", "AnonymousCredentialsProvider"); + private static final ClassName STATIC_TOKEN_PROVIDER = + ClassName.get("software.amazon.awssdk.auth.token.credentials", "StaticTokenProvider"); + private static final ClassName REGION = + ClassName.get("software.amazon.awssdk.regions", "Region"); + + private final IntermediateModel model; + private final PoetExtension poetExtensions; + private final Optional warmUpOperation; + + public WarmUpProviderSpec(IntermediateModel model) { + this.model = model; + this.poetExtensions = new PoetExtension(model); + this.warmUpOperation = WarmUpOperationSelector.selectWarmUpOperation(model); + } + + @Override + public ClassName className() { + return ClassName.get(model.getMetadata().getFullWarmUpInternalPackageName(), + model.getMetadata().getServiceName() + "WarmUpProvider"); + } + + @Override + public TypeSpec poetSpec() { + return PoetUtils.createClassBuilder(className()) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .addAnnotation(SdkInternalApi.class) + .addSuperinterface(SdkWarmUpProvider.class) + .addField(cannedResponseField()) + .addMethod(syncClientClassNameMethod()) + .addMethod(asyncClientClassNameMethod()) + .addMethod(warmUpClientMethod()) + .build(); + } + + private MethodSpec syncClientClassNameMethod() { + MethodSpec.Builder method = MethodSpec.methodBuilder("syncClientClassName") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(String.class); + if (model.getCustomizationConfig().isSkipSyncClientGeneration()) { + method.addStatement("return null"); + } else { + method.addStatement("return $S", syncClientClass().toString()); + } + return method.build(); + } + + private MethodSpec asyncClientClassNameMethod() { + return MethodSpec.methodBuilder("asyncClientClassName") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .returns(String.class) + .addStatement("return $S", asyncClientClass().toString()) + .build(); + } + + private MethodSpec warmUpClientMethod() { + CodeBlock.Builder body = CodeBlock.builder(); + if (!model.getCustomizationConfig().isSkipSyncClientGeneration()) { + body.beginControlFlow("if (clientType == $T.SYNC)", ClientType.class) + .add(clientBlock(syncClientClass(), + CANNED_RESPONSE_HTTP_CLIENT, SDK_HTTP_CLIENT, "httpClient", "client", false)) + .endControlFlow(); + } + body.beginControlFlow("if (clientType == $T.ASYNC)", ClientType.class) + .add(clientBlock(asyncClientClass(), + CANNED_RESPONSE_ASYNC_HTTP_CLIENT, SDK_ASYNC_HTTP_CLIENT, "asyncHttpClient", "asyncClient", true)) + .endControlFlow(); + + return MethodSpec.methodBuilder("warmUpClient") + .addAnnotation(Override.class) + .addModifiers(Modifier.PUBLIC) + .addParameter(ClientType.class, "clientType") + .addCode(body.build()) + .build(); + } + + private ClassName syncClientClass() { + return poetExtensions.getClientClass(model.getMetadata().getSyncInterface()); + } + + private ClassName asyncClientClass() { + return poetExtensions.getClientClass(model.getMetadata().getAsyncInterface()); + } + + /** + * Emits a canned HTTP client plus a try-with-resources that builds {@code clientType}, calls the selected + * warm-up operation (if any) and closes the client. The sync and async paths differ only in these types, variable + * names and joining the async call, so they share this emitter. + */ + private CodeBlock clientBlock(ClassName clientType, ClassName cannedHttpClientType, ClassName httpClientType, + String httpClientVar, String clientVar, boolean async) { + CodeBlock.Builder block = CodeBlock.builder() + .addStatement("$T $N = $T.builder().responseBody($L).statusCode($L).build()", + httpClientType, httpClientVar, cannedHttpClientType, CANNED_RESPONSE_FIELD, + SUCCESS_STATUS_CODE) + .beginControlFlow("try ($L)", clientBuilder(clientType, clientVar, httpClientVar)); + + warmUpOperation.ifPresent(op -> block.add(warmUpOperationCall(op, clientVar, async))); + + return block.endControlFlow() + .build(); + } + + /** + * Builds the warm-up client: canned HTTP client, anonymous credentials, local endpoint, plus any service-specific + * options from {@link #addServiceSpecificOptions}. + */ + private CodeBlock clientBuilder(ClassName clientType, String clientVar, String httpClientVar) { + CodeBlock.Builder builder = CodeBlock.builder() + .add("$1T $2N = $1T.builder()\n", clientType, clientVar) + .add(".httpClient($N)\n", httpClientVar) + .add(".credentialsProvider($T.create())\n", ANONYMOUS_CREDENTIALS_PROVIDER); + addServiceSpecificOptions(builder); + return builder.add(".region($T.US_EAST_1)\n", REGION) + .add(".endpointOverride($T.create($S))\n", URI.class, LOCAL_ENDPOINT) + .add(".build()") + .build(); + } + + /** + * Options only some services need: a dummy token for bearer-auth services, and disabling endpoint discovery for + * services that have it (avoids a WARN about the endpoint override disabling it). + */ + private void addServiceSpecificOptions(CodeBlock.Builder builder) { + if (AuthUtils.usesBearerAuth(model)) { + builder.add(".tokenProvider($T.create(() -> $S))\n", STATIC_TOKEN_PROVIDER, DUMMY_TOKEN); + } + if (model.getEndpointOperation().isPresent()) { + builder.add(".endpointDiscoveryEnabled(false)\n"); + } + } + + /** + * Verified simple methods use the generated no-arg overload. Other operations pass an empty request, except for + * members from {@link WarmUpOperationSelector#membersRequiringDummyValue} which get a dummy value. + */ + private CodeBlock warmUpOperationCall(OperationModel operation, String clientVar, boolean async) { + String join = async ? ".join()" : ""; + if (operation.getInputShape().isSimpleMethod()) { + return CodeBlock.builder() + .addStatement("$N.$N()" + join, clientVar, operation.getMethodName()) + .build(); + } + ClassName requestType = poetExtensions.getModelClass(operation.getInputShape().getShapeName()); + CodeBlock.Builder request = CodeBlock.builder().add("$T.builder()", requestType); + for (MemberModel member : WarmUpOperationSelector.membersRequiringDummyValue(operation)) { + request.add(".$N($S)", member.getFluentSetterMethodName(), DUMMY_MEMBER_VALUE); + } + request.add(".build()"); + return CodeBlock.builder() + .addStatement("$N.$N($L)" + join, clientVar, operation.getMethodName(), request.build()) + .build(); + } + + private FieldSpec cannedResponseField() { + return FieldSpec.builder(byte[].class, CANNED_RESPONSE_FIELD, + Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL) + .initializer(cannedResponseInitializer(model.getMetadata().getProtocol())) + .build(); + } + + /** + * A minimal, valid 200 response body per protocol. An empty body unmarshals for every protocol. + */ + private CodeBlock cannedResponseInitializer(Protocol protocol) { + switch (protocol) { + case REST_JSON: + case AWS_JSON: + return textInitializer("{}"); + case QUERY: + case EC2: + case REST_XML: + return textInitializer(""); + case CBOR: + case SMITHY_RPC_V2_CBOR: + // Both are binary CBOR protocols, so a text "{}" is not a valid body. 0xA0 is the single-byte CBOR + // encoding of an empty map, the equivalent of "{}" for JSON. + return CodeBlock.of("new byte[] {(byte) 0xA0}"); + default: + throw new IllegalStateException("Unsupported protocol for warm-up canned response: " + protocol + + " (service: " + model.getMetadata().getServiceName() + ")"); + } + } + + private CodeBlock textInitializer(String body) { + return CodeBlock.of("$S.getBytes($T.UTF_8)", body, StandardCharsets.class); + } +} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/default-read-write-timeout-exemptions.json b/codegen/src/main/resources/software/amazon/awssdk/codegen/default-read-write-timeout-exemptions.json new file mode 100644 index 000000000000..89bbc5e49239 --- /dev/null +++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/default-read-write-timeout-exemptions.json @@ -0,0 +1,85 @@ +{ + "Bedrock Runtime": -1, + "CloudSearch Domain": -1, + "codeartifact": -1, + "ConnectHealth": -1, + "EBS": -1, + "Glacier": -1, + "Lambda": -1, + "Lex Runtime Service": -1, + "Lex Runtime V2": -1, + "MediaStore Data": -1, + "Omics": -1, + "Polly": -1, + "QBusiness": -1, + "S3": -1, + "SageMaker Runtime HTTP2": -1, + "Transcribe Streaming": -1, + "b2bi": 900000, + "Bedrock Agent Runtime": 900000, + "Bedrock AgentCore": 900000, + "Bedrock Data Automation Runtime": 900000, + "Data Pipeline": 900000, + "DataExchange": 900000, + "ECS": 900000, + "Glue": 900000, + "Kinesis": 900000, + "Kinesis Analytics V2": 900000, + "Kinesis Video Archived Media": 900000, + "Kinesis Video Media": 900000, + "Kinesis Video Signaling": 900000, + "Kinesis Video WebRTC Storage": 900000, + "Neptune Graph": 900000, + "neptunedata": 900000, + "Nova Act": 900000, + "QApps": 900000, + "QConnect": 900000, + "QuickSight": 900000, + "SageMaker Runtime": 900000, + "SagemakerJobRuntime": 900000, + "SFN": 900000, + "SQS": 900000, + "SWF": 900000, + "Timestream Query": 900000, + "Wisdom": 900000, + "API Gateway": 900000, + "ApiGatewayV2": 900000, + "AppIntegrations": 900000, + "AppStream": 900000, + "Athena": 900000, + "Auto Scaling": 900000, + "Batch": 900000, + "Bedrock": 900000, + "Bedrock Agent": 900000, + "Bedrock AgentCore Control": 900000, + "CloudFormation": 900000, + "CloudWatch": 900000, + "CodeBuild": 900000, + "CodeCatalyst": 900000, + "CodeDeploy": 900000, + "Config Service": 900000, + "Connect": 900000, + "DataBrew": 900000, + "DataZone": 900000, + "Device Farm": 900000, + "EC2": 900000, + "Elastic Load Balancing v2": 900000, + "EMR Serverless": 900000, + "GameLift": 900000, + "GameLiftStreams": 900000, + "IoT": 900000, + "IoT Data Plane": 900000, + "IoT Jobs Data Plane": 900000, + "IoTSecureTunneling": 900000, + "Lex Model Building Service": 900000, + "Lex Models V2": 900000, + "mgn": 900000, + "RDS": 900000, + "RDS Data": 900000, + "RTBFabric": 900000, + "SageMaker": 900000, + "SSM": 900000, + "Storage Gateway": 900000, + "WorkSpaces": 900000, + "WorkSpaces Web": 900000 +} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Arn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Arn.java.resource deleted file mode 100644 index cee045e523e3..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Arn.java.resource +++ /dev/null @@ -1,112 +0,0 @@ -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * An AWS Arn. - */ -@SdkInternalApi -public final class Arn { - private final String partition; - private final String service; - private final String region; - private final String accountId; - private final List resource; - - public Arn(String partition, String service, String region, String accountId, List resource) { - this.partition = partition; - this.service = service; - this.region = region; - this.accountId = accountId; - this.resource = resource; - } - - public static Optional parse(String arn) { - String[] base = arn.split(":", 6); - if (base.length != 6) { - return Optional.empty(); - } - // service, resource and `arn` may not be null - if (!base[0].equals("arn")) { - return Optional.empty(); - } - if (base[1].isEmpty() || base[2].isEmpty()) { - return Optional.empty(); - } - if (base[5].isEmpty()) { - return Optional.empty(); - } - return Optional.of(new Arn(base[1], base[2], base[3], base[4], - Arrays.stream(base[5].split("[:/]", -1)) - .collect(Collectors.toList()))); - } - - public String partition() { - return partition; - } - - public String service() { - return service; - } - - public String region() { - return region; - } - - public String accountId() { - return accountId; - } - - public List resource() { - return resource; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Arn arn = (Arn) o; - - if (partition != null ? !partition.equals(arn.partition) : arn.partition != null) { - return false; - } - if (service != null ? !service.equals(arn.service) : arn.service != null) { - return false; - } - if (region != null ? !region.equals(arn.region) : arn.region != null) { - return false; - } - if (accountId != null ? !accountId.equals(arn.accountId) : arn.accountId != null) { - return false; - } - return resource != null ? resource.equals(arn.resource) : arn.resource == null; - } - - @Override - public int hashCode() { - int result = partition != null ? partition.hashCode() : 0; - result = 31 * result + (service != null ? service.hashCode() : 0); - result = 31 * result + (region != null ? region.hashCode() : 0); - result = 31 * result + (accountId != null ? accountId.hashCode() : 0); - result = 31 * result + (resource != null ? resource.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Arn[" + - "partition=" + partition + ", " + - "service=" + service + ", " + - "region=" + region + ", " + - "accountId=" + accountId + ", " + - "resource=" + resource + ']'; - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/BooleanEqualsFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/BooleanEqualsFn.java.resource deleted file mode 100644 index 1efb616d2d0d..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/BooleanEqualsFn.java.resource +++ /dev/null @@ -1,39 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.Pair; - -@SdkInternalApi -public class BooleanEqualsFn extends Fn { - public static final String ID = "booleanEquals"; - - public BooleanEqualsFn(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitBoolEquals(this); - } - - public static BooleanEqualsFn ofExprs(Expr left, Expr right) { - return new BooleanEqualsFn(FnNode.ofExprs(ID, left, right)); - } - - public Expr getLeft() { - return expectTwoArgs().left(); - } - - public Expr getRight() { - return expectTwoArgs().right(); - } - - @Override - public Value eval(Scope scope) { - Pair args = expectTwoArgs(); - return RuleError.ctx("while evaluating booleanEquals", - () -> Value.fromBool(args.left().eval(scope).expectBool() == args.right().eval(scope).expectBool())); - } - - public static BooleanEqualsFn fromParam(Parameter param, Expr value) { - return ofExprs(param.expr(), value); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Condition.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Condition.java.resource deleted file mode 100644 index 711bc627cffb..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Condition.java.resource +++ /dev/null @@ -1,92 +0,0 @@ -import java.util.Map; -import java.util.Optional; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public final class Condition implements Eval, IntoSelf { - public static final String ASSIGN = "assign"; - - private final Expr fn; - private final Identifier result; - - private Condition(Builder builder) { - this.fn = builder.fn; - this.result = builder.result; - } - - public Expr getFn() { - return fn; - } - - public Optional getResult() { - return Optional.ofNullable(result); - } - - public static Condition fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder b = builder(); - - Fn fn = FnNode.fromNode(node).validate(); - - b.fn(fn); - - JsonNode assignNode = objNode.get(ASSIGN); - if (assignNode != null) { - b.result(assignNode.asString()); - } - - return b.build(); - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - this.getResult().ifPresent(res -> sb.append(res).append(" = ")); - sb.append(this.fn); - return sb.toString(); - } - - @Override - public Value eval(Scope scope) { - Value value = this.fn.eval(scope); - if (!value.isNone()) { - this.getResult().ifPresent(res -> scope.insert(res, value)); - } - return value; - } - - public Expr expr() { - if (this.getResult().isPresent()) { - return Expr.ref(this.getResult().get()); - } else { - throw new RuntimeException("Cannot generate expr from a condition without a result"); - } - } - - - public static class Builder { - private Fn fn; - private Identifier result; - - public Builder fn(Fn fn) { - this.fn = fn; - return this; - } - - public Builder result(String result) { - this.result = Identifier.of(result); - return this; - } - - public Condition build() { - return new Condition(this); - } - - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategy.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategy.java.resource deleted file mode 100644 index 6f2a22e1ce9b..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategy.java.resource +++ /dev/null @@ -1,45 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.utils.Logger; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public final class DefaultEndpointAuthSchemeStrategy implements EndpointAuthSchemeStrategy { - private static final Logger LOG = Logger.loggerFor(DefaultEndpointAuthSchemeStrategy.class); - - private final Map> knownAuthSchemesMapping; - - public DefaultEndpointAuthSchemeStrategy(Map> knownAuthSchemesMapping) { - this.knownAuthSchemesMapping = knownAuthSchemesMapping; - } - - @Override - public EndpointAuthScheme chooseAuthScheme(List authSchemes) { - return authSchemes.stream() - .filter(scheme -> knownAuthSchemesMapping.containsKey(scheme.name())) - .findFirst() - .orElseThrow(() -> SdkClientException.create("Endpoint did not contain any known auth schemes: " + authSchemes)); - } - - @Override - public List createAuthSchemes(Value authSchemesValue) { - Value.Array schemesArray = authSchemesValue.expectArray(); - List authSchemes = new ArrayList<>(); - for (int i = 0; i < schemesArray.size(); ++i) { - Value.Record scheme = schemesArray.get(i).expectRecord(); - String authSchemeName = scheme.get(Identifier.of("name")).expectString(); - Function mapper = knownAuthSchemesMapping.get(authSchemeName); - if (mapper == null) { - LOG.debug(() -> "Ignoring unknown auth scheme: " + authSchemeName); - continue; - } - authSchemes.add(mapper.apply(scheme)); - } - return authSchemes; - } -} - diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategyFactory.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategyFactory.java.resource deleted file mode 100644 index 2c819a232b8c..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultEndpointAuthSchemeStrategyFactory.java.resource +++ /dev/null @@ -1,63 +0,0 @@ -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; - -public final class DefaultEndpointAuthSchemeStrategyFactory implements EndpointAuthSchemeStrategyFactory { - private static final String SIGV4_NAME = "sigv4"; - private static final String SIGV4A_NAME = "sigv4a"; - - public EndpointAuthSchemeStrategy endpointAuthSchemeStrategy() { - Map> knownAuthSchemesMapping = new HashMap<>(); - knownAuthSchemesMapping.put(SIGV4A_NAME, this::sigV4A); - knownAuthSchemesMapping.put(SIGV4_NAME, this::sigV4); - return new DefaultEndpointAuthSchemeStrategy(knownAuthSchemesMapping); - } - - private EndpointAuthScheme sigV4A(Value.Record scheme) { - SigV4aAuthScheme.Builder schemeBuilder = SigV4aAuthScheme.builder(); - - Value signingName = scheme.get(Identifier.of("signingName")); - if (signingName != null) { - schemeBuilder.signingName(signingName.expectString()); - } - - Value signingRegionSet = scheme.get(Identifier.of("signingRegionSet")); - if (signingRegionSet != null) { - Value.Array signingRegionSetArray = signingRegionSet.expectArray(); - for (int j = 0; j < signingRegionSetArray.size(); ++j) { - schemeBuilder.addSigningRegion(signingRegionSetArray.get(j).expectString()); - } - } - - Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding")); - if (disableDoubleEncoding != null) { - schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool()); - } - - return schemeBuilder.build(); - } - - private EndpointAuthScheme sigV4(Value.Record scheme) { - SigV4AuthScheme.Builder schemeBuilder = SigV4AuthScheme.builder(); - - Value signingName = scheme.get(Identifier.of("signingName")); - if (signingName != null) { - schemeBuilder.signingName(signingName.expectString()); - } - - Value signingRegion = scheme.get(Identifier.of("signingRegion")); - if (signingRegion != null) { - schemeBuilder.signingRegion(signingRegion.expectString()); - } - - Value disableDoubleEncoding = scheme.get(Identifier.of("disableDoubleEncoding")); - if (disableDoubleEncoding != null) { - schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool()); - } - - return schemeBuilder.build(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultRuleEngine.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultRuleEngine.java.resource deleted file mode 100644 index 70fc540c9013..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/DefaultRuleEngine.java.resource +++ /dev/null @@ -1,12 +0,0 @@ -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class DefaultRuleEngine implements RuleEngine { - private final RuleEvaluator evaluator = new RuleEvaluator(); - - @Override - public Value evaluate(EndpointRuleset ruleset, Map args) { - return evaluator.evaluateRuleset(ruleset, args); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAttributeProvider.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAttributeProvider.java.resource deleted file mode 100644 index 77e9645f46c9..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAttributeProvider.java.resource +++ /dev/null @@ -1,14 +0,0 @@ -import software.amazon.awssdk.endpoints.EndpointAttributeKey; -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * Link between an endpoint property and the {@link AwsEndpointAttribute} it represents. - * - @param the {@link AwsEndpointAttribute} type - */ -@SdkInternalApi -public interface EndpointAttributeProvider { - String propertyName(); - EndpointAttributeKey attributeKey(); - T attributeValue(Value value); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategy.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategy.java.resource deleted file mode 100644 index 61217fb3c8e1..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategy.java.resource +++ /dev/null @@ -1,10 +0,0 @@ -import java.util.List; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface EndpointAuthSchemeStrategy { - EndpointAuthScheme chooseAuthScheme(List authSchemes); - - List createAuthSchemes(Value authSchemesValue); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategyFactory.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategyFactory.java.resource deleted file mode 100644 index 294ea10bad0b..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointAuthSchemeStrategyFactory.java.resource +++ /dev/null @@ -1,12 +0,0 @@ -import java.util.function.Supplier; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface EndpointAuthSchemeStrategyFactory extends Supplier { - EndpointAuthSchemeStrategy endpointAuthSchemeStrategy(); - - @Override - default EndpointAuthSchemeStrategy get() { - return endpointAuthSchemeStrategy(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointResult.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointResult.java.resource deleted file mode 100644 index 8c40f6fba3c9..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointResult.java.resource +++ /dev/null @@ -1,132 +0,0 @@ -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public final class EndpointResult { - private static final String URL = "url"; - private static final String PROPERTIES = "properties"; - private static final String HEADERS = "headers"; - - private Expr url; - private Map properties; - private Map> headers; - - private EndpointResult(Builder builder) { - this.url = builder.url; - this.properties = builder.properties; - this.headers = builder.headers; - } - - public Expr getUrl() { - return url; - } - - public Map getProperties() { - return properties; - } - - public Map> getHeaders() { - return headers; - } - - public static EndpointResult fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder b = builder(); - - b.url(Expr.fromNode(objNode.get(URL))); - - JsonNode propertiesNode = objNode.get(PROPERTIES); - if (propertiesNode != null) { - propertiesNode.asObject().forEach((k, v) -> { - b.addProperty(Identifier.of(k), Literal.fromNode(v)); - }); - } - - JsonNode headersNode = objNode.get(HEADERS); - if (headersNode != null) { - headersNode.asObject().forEach((k, v) -> { - b.addHeader(k, v.asArray().stream().map(Literal::fromNode).collect(Collectors.toList())); - }); - } - - return b.build(); - } - - @Override - public String toString() { - return "Endpoint{" + - "url=" + url + - ", properties=" + properties + - ", headers=" + headers + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - EndpointResult endpoint = (EndpointResult) o; - - if (url != null ? !url.equals(endpoint.url) : endpoint.url != null) { - return false; - } - if (properties != null ? !properties.equals(endpoint.properties) : endpoint.properties != null) { - return false; - } - return headers != null ? headers.equals(endpoint.headers) : endpoint.headers == null; - } - - @Override - public int hashCode() { - int result = url != null ? url.hashCode() : 0; - result = 31 * result + (properties != null ? properties.hashCode() : 0); - result = 31 * result + (headers != null ? headers.hashCode() : 0); - return result; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private Expr url; - private final Map properties = new HashMap<>(); - private final Map> headers = new HashMap<>(); - - public Builder url(Expr url) { - this.url = url; - return this; - } - - public Builder addProperty(Identifier name, Expr value) { - properties.put(name, value); - return this; - } - - public Builder addHeader(String name, List value) { - this.headers.put(name, value); - return this; - } - - public Builder addHeaderValue(String name, Expr value) { - List values = this.headers.computeIfAbsent(name, n -> new ArrayList<>()); - values.add(value); - return this; - } - - public EndpointResult build() { - return new EndpointResult(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRule.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRule.java.resource deleted file mode 100644 index c66b069a11ed..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRule.java.resource +++ /dev/null @@ -1,29 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public final class EndpointRule extends Rule { - private final EndpointResult endpoint; - - protected EndpointRule(Builder builder, EndpointResult endpoint) { - super(builder); - this.endpoint = endpoint; - } - - public EndpointResult getEndpoint() { - return endpoint; - } - - @Override - public T accept(RuleValueVisitor visitor) { - return visitor.visitEndpointRule(this.getEndpoint()); - } - - @Override - public String toString() { - return "EndpointRule{" + - "endpoint=" + endpoint + - ", conditions=" + conditions + - ", documentation='" + documentation + '\'' + - '}'; - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRuleset.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRuleset.java.resource deleted file mode 100644 index 8a9b30c838fe..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/EndpointRuleset.java.resource +++ /dev/null @@ -1,117 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -/** - * The set of rules that are used to compute the endpoint to use for a request. - */ -@SdkInternalApi -public final class EndpointRuleset { - private static final String SERVICE_ID = "serviceId"; - private static final String VERSION = "version"; - private static final String PARAMETERS = "parameters"; - private static final String RULES = "rules"; - - - private final String serviceId; - private final List rules; - private final String version; - private final Parameters parameters; - - private EndpointRuleset(Builder b) { - this.serviceId = b.serviceId; - this.rules = b.rules; - this.version = b.version; - this.parameters = b.parameters; - } - - public String getServiceId() { - return serviceId; - } - - public List getRules() { - return rules; - } - - public String getVersion() { - return version; - } - - public Parameters getParameters() { - return parameters; - } - - public static Builder builder() { - return new Builder(); - } - - public static EndpointRuleset fromNode(JsonNode node) { - Builder b = builder(); - - Map obj = node.asObject(); - - JsonNode serviceIdNode = obj.get(SERVICE_ID); - if (serviceIdNode != null) { - b.serviceId(serviceIdNode.asString()); - } - - JsonNode versionNode = obj.get(VERSION); - if (versionNode != null) { - b.version(versionNode.asString()); - } - - b.parameters(Parameters.fromNode(obj.get(PARAMETERS))); - - obj.get(RULES).asArray().forEach(rn -> b.addRule(Rule.fromNode(rn))); - - return b.build(); - } - - @Override - public String toString() { - return "EndpointRuleset{" + - "serviceId='" + serviceId + '\'' + - ", rules=" + rules + - ", version='" + version + '\'' + - ", parameters=" + parameters + - '}'; - } - - public static class Builder { - private String serviceId; - private final List rules = new ArrayList<>(); - private String version; - private Parameters parameters; - - public Builder serviceId(String serviceId) { - this.serviceId = serviceId; - return this; - } - - public Builder withDefaultVersion() { - this.version = "1.0"; - return this; - } - - public Builder version(String version) { - this.version = version; - return this; - } - - public Builder addRule(Rule rule) { - rules.add(rule); - return this; - } - - public Builder parameters(Parameters parameters) { - this.parameters = parameters; - return this; - } - - public EndpointRuleset build() { - return new EndpointRuleset(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ErrorRule.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ErrorRule.java.resource deleted file mode 100644 index 9dd7d97026f3..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ErrorRule.java.resource +++ /dev/null @@ -1,25 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class ErrorRule extends Rule { - private final Expr error; - - public ErrorRule(Builder builder, Expr error) { - super(builder); - this.error = error; - } - - @Override - public T accept(RuleValueVisitor v) { - return v.visitErrorRule(error); - } - - @Override - public String toString() { - return "ErrorRule{" + - "error=" + error + - ", conditions=" + conditions + - ", documentation='" + documentation + '\'' + - '}'; - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Eval.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Eval.java.resource deleted file mode 100644 index cd64069ac420..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Eval.java.resource +++ /dev/null @@ -1,6 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface Eval { - Value eval(Scope scope); -} \ No newline at end of file diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Expr.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Expr.java.resource deleted file mode 100644 index fdd6067db226..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Expr.java.resource +++ /dev/null @@ -1,78 +0,0 @@ -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public abstract class Expr implements Eval { - - public abstract R accept(ExprVisitor visitor); - - public GetAttr getAttr(String path) { - return GetAttr.builder().target(this).path(path).build(); - } - - public GetAttr getAttr(Identifier path) { - return GetAttr.builder().target(this).path(path.asString()).build(); - } - - public static Expr fromNode(JsonNode node) { - if (node.isObject()) { - Map objNode = node.asObject(); - JsonNode ref = objNode.get("ref"); - JsonNode fn = objNode.get("fn"); - if ((ref != null ? 1 : 0) + (fn != null ? 1 : 0) != 1) { - throw SourceException.builder().message("expected exactly one of `ref` or `fn` to be set").build(); - } - if (ref != null) { - return ref(Identifier.of(ref.asString())); - } - return RuleError.ctx("while parsing fn", () -> FnNode.fromNode(node).validate()); - } else if (node.isString()) { - return Literal.fromStr(node.asString()); - } else { - return Literal.fromNode(node); - } - } - - /** - * Parse a value from a "short form" used within a template - * - * @param shortForm - * @return - */ - public static Expr parseShortform(String shortForm) { - return RuleError.ctx("while parsing `" + shortForm + "` within a template", () -> { - if (shortForm.contains("#")) { - String[] parts = shortForm.split("#", 2); - String base = parts[0]; - String pattern = parts[1]; - return GetAttr.builder() - .target(ref(Identifier.of(base))) - .path(pattern).build(); - } else { - return ref(Identifier.of(shortForm)); - } - }); - } - - public String template() { - throw new RuntimeException(String.format("cannot convert %s to a string template", this)); - } - - public static Ref ref(Identifier name) { - return new Ref(name); - } - - public static Expr of(boolean value) { - return Literal.fromBool(value); - } - - public static Expr of(int value) { - return Literal.fromInteger(value); - } - - public static Expr of(String value) { - return Literal.fromStr(value); - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ExprVisitor.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ExprVisitor.java.resource deleted file mode 100644 index 2cb0325d36f2..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ExprVisitor.java.resource +++ /dev/null @@ -1,31 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface ExprVisitor { - - R visitLiteral(Literal literal); - - R visitRef(Ref ref); - - R visitFn(Fn fn); - - abstract class Default implements ExprVisitor { - - public abstract R getDefault(); - - @Override - public R visitLiteral(Literal literal) { - return getDefault(); - } - - @Override - public R visitRef(Ref ref) { - return getDefault(); - } - - @Override - public R visitFn(Fn fn) { - return getDefault(); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FatScope.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FatScope.java.resource deleted file mode 100644 index 2da5c6d152ba..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FatScope.java.resource +++ /dev/null @@ -1,57 +0,0 @@ -import java.util.HashMap; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public final class FatScope { - private final HashMap types; - private final HashMap facts; - - public FatScope(HashMap types, HashMap facts) { - this.types = types; - this.facts = facts; - } - - public FatScope() { - this(new HashMap<>(), new HashMap<>()); - } - - public HashMap types() { - return types; - } - - public HashMap facts() { - return facts; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - FatScope fatScope = (FatScope) o; - - if (types != null ? !types.equals(fatScope.types) : fatScope.types != null) { - return false; - } - return facts != null ? facts.equals(fatScope.facts) : fatScope.facts == null; - } - - @Override - public int hashCode() { - int result = types != null ? types.hashCode() : 0; - result = 31 * result + (facts != null ? facts.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "FatScope[" + - "types=" + types + ", " + - "facts=" + facts + ']'; - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Fn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Fn.java.resource deleted file mode 100644 index f25fbdfc5d9e..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Fn.java.resource +++ /dev/null @@ -1,120 +0,0 @@ -import java.util.List; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.Pair; - -@SdkInternalApi -public abstract class Fn extends Expr implements Into { - protected FnNode fnNode; - - public Fn(FnNode fnNode) { - this.fnNode = fnNode; - } - - /** - * Convert this fn into a condition - */ - public Condition condition() { - return new Condition.Builder().fn(this).build(); - } - - public Condition condition(String result) { - return new Condition.Builder().fn(this).result(result).build(); - } - - public abstract T acceptFnVisitor(FnVisitor visitor); - - public R accept(ExprVisitor visitor) { - return visitor.visitFn(this); - } - - /** - * Returns the name of this function, eg. {@code isSet}, {@code parseUrl} - * @return The name - */ - public String getName() { - return fnNode.getId(); - } - - /** - * @return The arguments to this function - */ - public List getArgv() { - return fnNode.getArgv(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - Fn fn = (Fn) o; - - return fnNode != null ? fnNode.equals(fn.fnNode) : fn.fnNode == null; - } - - @Override - public int hashCode() { - return fnNode != null ? fnNode.hashCode() : 0; - } - - @Override - public String toString() { - return String.format("%s(%s)", fnNode.getId(), - fnNode.getArgv().stream().map(Expr::toString).collect(Collectors.joining(", "))); - } - - protected Expr expectOneArg() { - List argv = this.fnNode.getArgv(); - if (argv.size() == 1) { - return argv.get(0); - } else { - throw RuleError.builder() - .cause(SourceException.builder() - .message("expected 1 argument but found " + argv.size()) - .build()) - .build(); - } - } - - protected Pair expectTwoArgs() { - List argv = this.fnNode.getArgv(); - if (argv.size() == 2) { - return Pair.of(argv.get(0), argv.get(1)); - } else { - throw RuleError.builder() - .cause(SourceException.builder() - .message("expected 2 arguments but found " + argv.size()) - .build()) - .build(); - } - - } - - protected List expectVariableArgs(int expectedNumberArgs) { - List argv = this.fnNode.getArgv(); - if (argv.size() == expectedNumberArgs) { - return argv; - } else { - throw RuleError.builder() - .cause(SourceException.builder() - .message(String.format("expected %d arguments but found %d", - expectedNumberArgs, argv.size())) - .build()) - .build(); - } - - } - - @Override - public Condition into() { - return this.condition(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnNode.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnNode.java.resource deleted file mode 100644 index 776bc53a93e5..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnNode.java.resource +++ /dev/null @@ -1,136 +0,0 @@ -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -/** - * Parsed but not validated function contents containing the `fn` name and `argv` - */ -@SdkInternalApi -public final class FnNode { - private static final String ARGV = "argv"; - private static final String FN = "fn"; - - private final String fn; - private final List argv; - - private FnNode(Builder builder) { - this.fn = builder.fn; - this.argv = builder.argv; - } - - public static FnNode ofExprs(String fn, Expr... expr) { - return builder() - .fn(fn) - .argv(Arrays.stream(expr).collect(Collectors.toList())) - .build(); - } - - public Fn validate() { - switch (fn) { - case BooleanEqualsFn.ID: - return new BooleanEqualsFn(this); - case PartitionFn.ID: - return new PartitionFn(this); - case StringEqualsFn.ID: - return new StringEqualsFn(this); - case IsSet.ID: - return new IsSet(this); - case IsValidHostLabel.ID: - return new IsValidHostLabel(this); - case GetAttr.ID: - return new GetAttr(this); - case ParseArn.ID: - return new ParseArn(this); - case Not.ID: - return new Not(this); - case ParseUrl.ID: - return new ParseUrl(this); - case Substring.ID: - return new Substring(this); - case UriEncodeFn.ID: - return new UriEncodeFn(this); - case IsVirtualHostableS3Bucket.ID: - return new IsVirtualHostableS3Bucket(this); - default: - throw RuleError.builder() - .cause(SourceException.builder() - .message(String.format("`%s` is not a valid function", fn)) - .build()) - .build(); - } - } - - public String getId() { - return fn; - } - - public List getArgv() { - return argv; - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - FnNode fnNode = (FnNode) o; - - if (fn != null ? !fn.equals(fnNode.fn) : fnNode.fn != null) { - return false; - } - return argv != null ? argv.equals(fnNode.argv) : fnNode.argv == null; - } - - @Override - public int hashCode() { - int result = fn != null ? fn.hashCode() : 0; - result = 31 * result + (argv != null ? argv.hashCode() : 0); - return result; - } - - public static FnNode fromNode(JsonNode node) { - Map objNode = node.asObject(); - - return builder() - .fn(objNode.get(FN).asString()) - .argv(objNode.get(ARGV).asArray() - .stream() - .map(Expr::fromNode) - .collect(Collectors.toList())) - .build(); - } - - public static class Builder { - private String fn; - private List argv; - - public Builder() { - } - - public Builder argv(List argv) { - this.argv = argv; - return this; - } - - public Builder fn(String fn) { - this.fn = fn; - return this; - } - - public FnNode build() { - return new FnNode(this); - } - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnVisitor.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnVisitor.java.resource deleted file mode 100644 index e51c9c2b0684..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/FnVisitor.java.resource +++ /dev/null @@ -1,28 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface FnVisitor { - R visitPartition(PartitionFn fn); - - R visitParseArn(ParseArn fn); - - R visitIsValidHostLabel(IsValidHostLabel fn); - - R visitBoolEquals(BooleanEqualsFn fn); - - R visitStringEquals(StringEqualsFn fn); - - R visitIsSet(IsSet fn); - - R visitNot(Not not); - - R visitGetAttr(GetAttr getAttr); - - R visitParseUrl(ParseUrl parseUrl); - - R visitSubstring(Substring substring); - - R visitUriEncode(UriEncodeFn fn); - - R visitIsVirtualHostLabelsS3Bucket(IsVirtualHostableS3Bucket fn); -} \ No newline at end of file diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/GetAttr.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/GetAttr.java.resource deleted file mode 100644 index ea775a619841..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/GetAttr.java.resource +++ /dev/null @@ -1,240 +0,0 @@ -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class GetAttr extends Fn { - public static final String ID = "getAttr"; - - public GetAttr(FnNode node) { - super(node); - } - - @Override - public Value eval(Scope scope) { - Value root = target().eval(scope); - List path; - try { - path = path(); - } catch (InnerParseError e) { - throw new RuntimeException(e); - } - for (Part part : path) { - root = part.eval(root); - } - return root; - } - - public interface Part { - - Value eval(Value container); - - final class Key implements Part { - private final Identifier key; - - public Key(Identifier key) { - this.key = key; - } - - @Override - public String toString() { - return key.asString(); - } - - public static Key of(String key) { - return new Key(Identifier.of(key)); - } - - @Override - public Value eval(Value container) { - return container.expectRecord().get(key); - } - - public Identifier key() { - return key; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null || obj.getClass() != this.getClass()) { - return false; - } - Key that = (Key) obj; - return Objects.equals(this.key, that.key); - } - - @Override - public int hashCode() { - return key != null ? key.hashCode() : 0; - } - } - - final class Index implements Part { - private final int index; - - public Index(int index) { - this.index = index; - } - - @Override - public Value eval(Value container) { - return container.expectArray().get(index); - } - - @Override - public String toString() { - return String.format("[%s]", index); - } - - public int index() { - return index; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj == null || obj.getClass() != this.getClass()) { - return false; - } - Index that = (Index) obj; - return this.index == that.index; - } - - @Override - public int hashCode() { - return index; - } - } - } - - - private static GetAttr fromBuilder(Builder builder) { - return new GetAttr(FnNode - .builder() - .fn("getAttr") - .argv( - Arrays.asList( - builder.target, - Literal.fromStr(String.join(".", builder.path)))) - .build()); - } - - public static Builder builder() { - return new Builder(); - } - - public Expr target() { - return expectTwoArgs().left(); - } - - public List path() throws InnerParseError { - Expr right = expectTwoArgs().right(); - if (right instanceof Literal) { - Literal path = (Literal) right; - return parse(path.expectLiteralString()); - } else { - throw SourceException.builder().message("second argument must be a string literal").build(); - } - } - - private static List parse(String path) throws InnerParseError { - String[] components = path.split("\\."); - List result = new ArrayList<>(); - for (String component : components) { - if (component.contains("[")) { - int slicePartIndex = component.indexOf("["); - String slicePart = component.substring(slicePartIndex); - if (!slicePart.endsWith("]")) { - throw new InnerParseError("Invalid path component: %s. Must end with `]`"); - } - try { - String number = slicePart.substring(1, slicePart.length() - 1); - int slice = Integer.parseInt(number); - if (slice < 0) { - throw new InnerParseError("Invalid path component: slice index must be >= 0"); - } - if (slicePartIndex > 0) { - result.add(Part.Key.of(component.substring(0, slicePartIndex))); - } - result.add(new Part.Index(slice)); - } catch (NumberFormatException ex) { - throw new InnerParseError(String.format("%s could not be parsed as a number", slicePart)); - } - } else { - result.add(Part.Key.of(component)); - } - } - if (result.isEmpty()) { - throw new InnerParseError("Invalid argument to GetAttr: path may not be empty"); - } - return result; - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitGetAttr(this); - } - - @Override - public String toString() { - StringBuilder out = new StringBuilder(); - out.append(target()); - try { - for (Part part : path()) { - out.append("."); - out.append(part); - } - } catch (InnerParseError e) { - throw new RuntimeException(e); - } - return out.toString(); - } - - @Override - public String template() { - String target = ((Ref) this.target()).getName().asString(); - StringBuilder pathPart = new StringBuilder(); - - List partList; - try { - partList = path(); - } catch (InnerParseError e) { - throw new RuntimeException(e); - } - for (int i = 0; i < partList.size(); i ++) { - if (i != 0) { - if (partList.get(i) instanceof Part.Key) { - pathPart.append("."); - } - } - pathPart.append(partList.get(i).toString()); - } - return "{" + target + "#" + pathPart + "}"; - } - - public static class Builder { - Expr target; - String path; - - public Builder target(Expr target) { - this.target = target; - return this; - } - - public Builder path(String path) { - this.path = path; - return this; - } - - public GetAttr build() { - return GetAttr.fromBuilder(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Identifier.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Identifier.java.resource deleted file mode 100644 index 3e4160fd8118..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Identifier.java.resource +++ /dev/null @@ -1,48 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * Identifiers for variables declared within the rule engine, e.g. from an {@code assign} statement. - */ -@SdkInternalApi -public final class Identifier { - private String name; - - public Identifier(String name) { - this.name = name; - } - - public static Identifier fromString(String name) { - return new Identifier(name); - } - - public static Identifier of(String name) { - return new Identifier(name); - } - - public String asString() { - return name; - } - - public String toString() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Identifier that = (Identifier) o; - - return name != null ? name.equals(that.name) : that.name == null; - } - - @Override - public int hashCode() { - return name != null ? name.hashCode() : 0; - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/InnerParseError.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/InnerParseError.java.resource deleted file mode 100644 index 005230e0e789..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/InnerParseError.java.resource +++ /dev/null @@ -1,10 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class InnerParseError extends RuntimeException { - private static final long serialVersionUID = -7808901449079805477L; - - public InnerParseError(String message) { - super(message); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Into.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Into.java.resource deleted file mode 100644 index 88bbae20edc8..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Into.java.resource +++ /dev/null @@ -1,6 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface Into { - T into(); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IntoSelf.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IntoSelf.java.resource deleted file mode 100644 index f58965e81098..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IntoSelf.java.resource +++ /dev/null @@ -1,9 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface IntoSelf> extends Into { - @Override - default T into() { - return (T) this; - } -} \ No newline at end of file diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsSet.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsSet.java.resource deleted file mode 100644 index e537d4918135..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsSet.java.resource +++ /dev/null @@ -1,25 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class IsSet extends SingleArgFn { - public static final String ID = "isSet"; - - public IsSet(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitIsSet(this); - } - - public static IsSet ofExpr(Expr expr) { - return new IsSet(FnNode.ofExprs(ID, expr)); - } - - @Override - protected Value evalArg(Value arg) { - return Value.fromBool(!arg.isNone()); - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsValidHostLabel.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsValidHostLabel.java.resource deleted file mode 100644 index 3dddcf1366fb..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsValidHostLabel.java.resource +++ /dev/null @@ -1,42 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class IsValidHostLabel extends VarargFn { - public static final String ID = "isValidHostLabel"; - - public IsValidHostLabel(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitIsValidHostLabel(this); - } - - public static IsValidHostLabel ofExprs(Expr expr, boolean allowDots) { - return new IsValidHostLabel(FnNode.ofExprs(ID, expr, Expr.of(allowDots))); - } - - public Expr hostLabel() { - return expectTwoArgs().left(); - } - - public Expr allowDots() { - return expectTwoArgs().right(); - } - - @Override - public Value eval(Scope scope) { - String hostLabel = expectTwoArgs().left().eval(scope).expectString(); - // TODO: use compiled Pattern - if (allowDots(scope)) { - return Value.fromBool(hostLabel.matches("[a-zA-Z\\d][a-zA-Z\\d\\-.]{0,62}")); - } else { - return Value.fromBool(hostLabel.matches("[a-zA-Z\\d][a-zA-Z\\d\\-]{0,62}")); - } - } - - private boolean allowDots(Scope scope) { - return allowDots().eval(scope).expectBool(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsVirtualHostableS3Bucket.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsVirtualHostableS3Bucket.java.resource deleted file mode 100644 index 679fc1c6b4c6..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/IsVirtualHostableS3Bucket.java.resource +++ /dev/null @@ -1,46 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class IsVirtualHostableS3Bucket extends VarargFn { - public static final String ID = "aws.isVirtualHostableS3Bucket"; - - public IsVirtualHostableS3Bucket(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitIsVirtualHostLabelsS3Bucket(this); - } - - public static IsVirtualHostableS3Bucket ofExprs(Expr expr, boolean allowDots) { - return new IsVirtualHostableS3Bucket(FnNode.ofExprs(ID, expr, Expr.of(allowDots))); - } - - public Expr hostLabel() { - return expectTwoArgs().left(); - } - - public Expr allowDots() { - return expectTwoArgs().right(); - } - - @Override - public Value eval(Scope scope) { - String hostLabel = expectTwoArgs().left().eval(scope).expectString(); - if (allowDots(scope)) { - // TODO: use compiled Pattern - return Value.fromBool( - hostLabel.matches("[a-z\\d][a-z\\d\\-.]{1,61}[a-z\\d]") - && !hostLabel.matches("(\\d+\\.){3}\\d+") // don't allow ip address - && !hostLabel.matches(".*[.-]{2}.*") // don't allow names like bucket-.name or bucket.-name - ); - } else { - return Value.fromBool(hostLabel.matches("[a-z\\d][a-z\\d\\-]{1,61}[a-z\\d]")); - } - } - - private boolean allowDots(Scope scope) { - return allowDots().eval(scope).expectBool(); - } -} \ No newline at end of file diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Literal.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Literal.java.resource deleted file mode 100644 index 5e191fdc1136..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Literal.java.resource +++ /dev/null @@ -1,370 +0,0 @@ -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public class Literal extends Expr { - public interface Visitor { - - T visitBool(boolean b); - - T visitStr(Template value); - - T visitObject(Map members); - - T visitTuple(List members); - - T visitInt(int value); - } - - private final Lit source; - - private Literal(Lit source) { - this.source = source; - } - - public T accept(Visitor visitor) { - return this.source.accept(visitor); - } - - public String expectLiteralString() { - if (source instanceof Str) { - Str s = (Str) source; - - return s.value.expectLiteral(); - } else { - throw RuleError.builder() - .cause(SourceException.builder() - .message("Expected a literal string, got " + source) - .build()) - .build(); - } - } - - @Override - public R accept(ExprVisitor visitor) { - return visitor.visitLiteral(this); - } - - @Override - public Value eval(Scope scope) { - return source.accept(new Visitor() { - @Override - public Value visitInt(int value) { - return Value.fromInteger(value); - } - - @Override - public Value visitBool(boolean b) { - return Value.fromBool(b); - } - - @Override - public Value visitStr(Template value) { - return value.eval(scope); - } - - @Override - public Value visitObject(Map members) { - Map tpe = new HashMap<>(); - members.forEach((k, v) -> { - tpe.put(k, v.eval(scope)); - }); - return Value.fromRecord(tpe); - } - - @Override - public Value visitTuple(List members) { - List tuples = new ArrayList<>(); - for (Literal el : ((Tuple) source).members) { - tuples.add(el.eval(scope)); - } - return Value.fromArray(tuples); - } - }); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - Literal literal = (Literal) o; - - return source != null ? source.equals(literal.source) : literal.source == null; - } - - @Override - public int hashCode() { - return source != null ? source.hashCode() : 0; - } - - public String toString() { - return source.toString(); - } - - public static Literal fromNode(JsonNode node) { - Lit lit; - if (node.isArray()) { - List array = node.asArray().stream().map(Literal::fromNode).collect(Collectors.toList()); - lit = new Tuple(array); - } else if (node.isBoolean()) { - lit = new Bool(node.asBoolean()); - } else if (node.isNull()) { - throw SdkClientException.create("null node not supported"); - } else if (node.isNumber()) { - lit = new Int(Integer.parseInt(node.asNumber())); - } else if (node.isObject()) { - Map obj = new HashMap<>(); - node.asObject().forEach((k, v) -> obj.put(Identifier.of(k), fromNode(v))); - lit = new Obj(obj); - } else if (node.isString()) { - lit = new Str(new Template(node.asString())); - } else { - throw SdkClientException.create("Unable to create literal from " + node); - } - return new Literal(lit); - } - - public static Literal fromTuple(List authSchemes) { - return new Literal(new Tuple(authSchemes)); - } - - public static Literal fromRecord(Map record) { - return new Literal(new Obj(record)); - } - - public static Literal fromStr(Template value) { - return new Literal(new Str(value)); - } - - public static Literal fromStr(String s) { - return fromStr(new Template(s)); - } - - public static Literal fromInteger(int value) { - return new Literal(new Int(value)); - } - - public static Literal fromBool(boolean value) { - return new Literal(new Bool(value)); - } - - private interface Lit { - T accept(Visitor visitor); - } - - static final class Int implements Lit { - private final Integer value; - - Int(Integer value) { - this.value = value; - } - - @Override - public T accept(Visitor visitor) { - return visitor.visitInt(value); - } - - @Override - public String toString() { - return Integer.toString(value); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Int anInt = (Int) o; - - return value != null ? value.equals(anInt.value) : anInt.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } - - static final class Tuple implements Lit { - private final List members; - - Tuple(List members) { - this.members = members; - } - - @Override - public T accept(Visitor visitor) { - return visitor.visitTuple(members); - } - - @Override - public String toString() { - return members.stream().map(Literal::toString).collect(Collectors.joining(", ", "[", "]")); - } - - public List members() { - return members; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Tuple tuple = (Tuple) o; - - return members != null ? members.equals(tuple.members) : tuple.members == null; - } - - @Override - public int hashCode() { - return members != null ? members.hashCode() : 0; - } - } - - static final class Obj implements Lit { - private final Map members; - - Obj(Map members) { - this.members = members; - } - - @Override - public T accept(Visitor visitor) { - return visitor.visitObject(members); - } - - @Override - public String toString() { - return members.toString(); - } - - public Map members() { - return members; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Obj obj = (Obj) o; - - return members != null ? members.equals(obj.members) : obj.members == null; - } - - @Override - public int hashCode() { - return members != null ? members.hashCode() : 0; - } - } - - static final class Bool implements Lit { - private final boolean value; - - Bool(boolean value) { - this.value = value; - } - - @Override - public T accept(Visitor visitor) { - return visitor.visitBool(value); - } - - @Override - public String toString() { - return Boolean.toString(value); - } - - public Boolean value() { - return value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Bool bool = (Bool) o; - - return value == bool.value; - } - - @Override - public int hashCode() { - return value ? 1 : 0; - } - } - - - static final class Str implements Lit { - private final Template value; - - Str(Template value) { - this.value = value; - } - - @Override - public T accept(Visitor visitor) { - return visitor.visitStr(value); - } - - @Override - public String toString() { - return value.toString(); - } - - public Template value() { - return value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Str str = (Str) o; - - return value != null ? value.equals(str.value) : str.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Not.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Not.java.resource deleted file mode 100644 index 74b2f28acd77..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Not.java.resource +++ /dev/null @@ -1,33 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class Not extends SingleArgFn { - - public static final String ID = "not"; - - public Not(FnNode fnNode) { - super(fnNode); - } - - public static Not ofExpr(Expr expr) { - return new Not(FnNode.ofExprs(ID, expr)); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitNot(this); - } - - public static Not ofExprs(Expr expr) { - return new Not(FnNode.ofExprs(ID, expr)); - } - - @Override - protected Value evalArg(Value arg) { - return Value.fromBool(!arg.expectBool()); - } - - public Expr target() { - return expectOneArg(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameter.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameter.java.resource deleted file mode 100644 index 436ca3aa9851..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameter.java.resource +++ /dev/null @@ -1,341 +0,0 @@ -import java.util.Map; -import java.util.Optional; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public final class Parameter implements ToParameterReference { - public static final String TYPE = "type"; - public static final String DEPRECATED = "deprecated"; - public static final String DOCUMENTATION = "documentation"; - public static final String DEFAULT = "default"; - private static final String BUILT_IN = "builtIn"; - private static final String REQUIRED = "required"; - - private final ParameterType type; - private final Identifier name; - private final Value value; - private final String builtIn; - private final Value defaultValue; - private final Deprecated deprecated; - private final String documentation; - private final boolean required; - - public Parameter(Builder builder) { - if (builder.defaultValue != null && !builder.required) { - throw new RuntimeException("When a default value is set, the field must also be marked as required"); - } - this.type = builder.type; - this.name = builder.name; - this.builtIn = builder.builtIn; - this.value = builder.value; - this.required = builder.required; - this.deprecated = builder.deprecated; - this.documentation = builder.documentation; - this.defaultValue = builder.defaultValue; - } - - public Optional getBuiltIn() { - return Optional.ofNullable(builtIn); - } - - public Optional getDefaultValue() { - return Optional.ofNullable(defaultValue); - } - - public boolean isRequired() { - return required; - } - - public Optional getDeprecated() { - return Optional.ofNullable(deprecated); - } - - public static Parameter fromNode(String name, JsonNode node) throws RuleError { - Map objNode = node.asObject(); - - Builder b = builder(); - b.name(name); - b.type(ParameterType.fromNode(objNode.get(TYPE))); - - JsonNode builtIn = objNode.get(BUILT_IN); - if (builtIn != null) { - b.builtIn(builtIn.asString()); - } - - JsonNode documentation = objNode.get(DOCUMENTATION); - if (documentation != null) { - b.documentation(documentation.asString()); - } - - JsonNode defaultNode = objNode.get(DEFAULT); - if (defaultNode != null) { - b.defaultValue(Value.fromNode(defaultNode)); - } - - JsonNode required = objNode.get(REQUIRED); - if (required != null) { - b.required(required.asBoolean()); - } else { - b.required(false); - } - - JsonNode deprecated = objNode.get(DEPRECATED); - if (deprecated != null) { - b.deprecated(Deprecated.fromNode(deprecated)); - } - - return b.build(); - } - - public ParameterType getType() { - return type; - } - - public Identifier getName() { - return name; - } - - public boolean isBuiltIn() { - return builtIn != null; - } - - public Optional getValue() { - return Optional.ofNullable(value); - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(name).append(": ").append(type); - if (builtIn != null) { - sb.append("; builtIn(").append(builtIn).append(")"); - } - if (required) { - sb.append("; required"); - } - getDeprecated().ifPresent(dep -> sb.append("; ").append(deprecated).append("!")); - return sb.toString(); - } - - @Override - public ParameterReference toParameterReference() { - return ParameterReference.builder() - .name(getName().asString()) - .build(); - } - - public String template() { - return "{" + name + "}"; - } - - public Expr expr() { - return Expr.ref(this.name); - } - - public BooleanEqualsFn eq(boolean b) { - return BooleanEqualsFn.fromParam(this, Expr.of(b)); - } - - public BooleanEqualsFn eq(Expr e) { - return BooleanEqualsFn.fromParam(this, e); - } - - public Optional getDocumentation() { - return Optional.ofNullable(documentation); - } - - /** - * The default value for this Parameter - * @return The value. This value must match the type of this parameter. - */ - public Optional getDefault() { - return Optional.ofNullable(this.defaultValue); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Parameter parameter = (Parameter) o; - - if (required != parameter.required) { - return false; - } - if (type != parameter.type) { - return false; - } - if (name != null ? !name.equals(parameter.name) : parameter.name != null) { - return false; - } - if (value != null ? !value.equals(parameter.value) : parameter.value != null) { - return false; - } - if (builtIn != null ? !builtIn.equals(parameter.builtIn) : parameter.builtIn != null) { - return false; - } - if (defaultValue != null ? !defaultValue.equals(parameter.defaultValue) : parameter.defaultValue != null) { - return false; - } - if (deprecated != null ? !deprecated.equals(parameter.deprecated) : parameter.deprecated != null) { - return false; - } - return documentation != null ? documentation.equals(parameter.documentation) : parameter.documentation == null; - } - - @Override - public int hashCode() { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (name != null ? name.hashCode() : 0); - result = 31 * result + (value != null ? value.hashCode() : 0); - result = 31 * result + (builtIn != null ? builtIn.hashCode() : 0); - result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0); - result = 31 * result + (required ? 1 : 0); - result = 31 * result + (deprecated != null ? deprecated.hashCode() : 0); - result = 31 * result + (documentation != null ? documentation.hashCode() : 0); - return result; - } - - public static final class Deprecated { - private static final String MESSAGE = "message"; - private static final String SINCE = "since"; - private final String message; - private final String since; - - public Deprecated(String message, String since) { - this.message = message; - this.since = since; - } - - public static Deprecated fromNode(JsonNode node) { - Map objNode = node.asObject(); - - String message = null; - String since = null; - - JsonNode messageNode = objNode.get(MESSAGE); - if (messageNode != null) { - message = messageNode.asString(); - } - - JsonNode sinceNode = objNode.get(SINCE); - if (sinceNode != null) { - since = sinceNode.asString(); - } - - return new Deprecated(message, since); - } - - public String message() { - return message; - } - - public String since() { - return since; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Deprecated that = (Deprecated) o; - - if (message != null ? !message.equals(that.message) : that.message != null) { - return false; - } - return since != null ? since.equals(that.since) : that.since == null; - } - - @Override - public int hashCode() { - int result = message != null ? message.hashCode() : 0; - result = 31 * result + (since != null ? since.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Deprecated[" + - "message=" + message + ", " + - "since=" + since + ']'; - } - - } - - public static final class Builder { - private ParameterType type; - private Identifier name; - private String builtIn; - - private Deprecated deprecated; - - private Value value; - private boolean required; - private String documentation; - - private Value defaultValue; - - public Builder type(ParameterType type) { - this.type = type; - return this; - } - - public Builder deprecated(Deprecated deprecated) { - this.deprecated = deprecated; - return this; - } - - public Builder name(String name) { - this.name = Identifier.of(name); - return this; - } - - public Builder name(Identifier name) { - this.name = name; - return this; - } - - public Builder builtIn(String builtIn) { - this.builtIn = builtIn; - return this; - } - - public Builder value(Value value) { - this.value = value; - return this; - } - - public Builder defaultValue(Value defaultValue) { - this.defaultValue = defaultValue; - return this; - } - - public Parameter build() { - return new Parameter(this); - } - - public Builder required(boolean required) { - this.required = required; - return this; - } - - public Builder documentation(String s) { - this.documentation = s; - return this; - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterReference.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterReference.java.resource deleted file mode 100644 index d94f999fac71..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterReference.java.resource +++ /dev/null @@ -1,90 +0,0 @@ -import java.util.Objects; -import java.util.Optional; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public final class ParameterReference implements ToParameterReference { - private final String name; - private final String context; - - private ParameterReference(Builder builder) { - this.name = builder.name; - this.context = builder.context; - } - - public String getName() { - return name; - } - - public Optional getContext() { - return Optional.ofNullable(context); - } - - public static ParameterReference from(String reference) { - String[] split = reference.split("\\.", 2); - return from(split[0], split.length == 2 ? split[1] : null); - } - - public static ParameterReference from(String name, String context) { - Builder builder = builder().name(name); - if (context != null) { - builder.context(context); - } - return builder.build(); - } - - public static Builder builder() { - return new Builder(); - } - - @Override - public ParameterReference toParameterReference() { - return this; - } - - @Override - public String toString() { - if (context == null) { - return name; - } - return name + "." + context; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ParameterReference that = (ParameterReference) o; - return getName().equals(that.getName()) && Objects.equals(getContext(), that.getContext()); - } - - @Override - public int hashCode() { - int result = name != null ? name.hashCode() : 0; - result = 31 * result + (context != null ? context.hashCode() : 0); - return result; - } - - public static class Builder { - private String name; - private String context; - - public Builder name(String name) { - this.name = name; - return this; - } - - public Builder context(String context) { - this.context = context; - return this; - } - - public ParameterReference build() { - return new ParameterReference(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterType.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterType.java.resource deleted file mode 100644 index 54a89bd124fb..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParameterType.java.resource +++ /dev/null @@ -1,40 +0,0 @@ -import java.util.Locale; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public enum ParameterType { - STRING("String"), - BOOLEAN("Boolean"), - STRING_ARRAY("StringArray"), - ; - - private final String name; - - ParameterType(String name) { - this.name = name; - } - - @Override - public String toString() { - return name; - } - - public static ParameterType fromNode(JsonNode node) { - return fromValue(node.asString()); - } - - public static ParameterType fromValue(String value) { - switch (value.toLowerCase(Locale.ENGLISH)) { - case "string": - return STRING; - case "boolean": - return BOOLEAN; - case "stringarray": - return STRING_ARRAY; - default: - throw SdkClientException.create("Unknown parameter type: " + value); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameters.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameters.java.resource deleted file mode 100644 index 0eb97572cd9b..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Parameters.java.resource +++ /dev/null @@ -1,79 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public class Parameters { - private final List parameters; - - private Parameters(Builder b) { - this.parameters = b.parameters; - } - - public List toList() { - return parameters; - } - - public Optional get(Identifier name) { - return parameters.stream().filter((param) -> param.getName().equals(name)).findFirst(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Parameters that = (Parameters) o; - - return parameters != null ? parameters.equals(that.parameters) : that.parameters == null; - } - - @Override - public int hashCode() { - return parameters != null ? parameters.hashCode() : 0; - } - - @Override - public String toString() { - return "Parameters{" + - "parameters=" + parameters + - '}'; - } - - public static Parameters fromNode(JsonNode node) { - Map paramsObj = node.asObject(); - - Builder b = builder(); - - paramsObj.forEach((name, obj) -> { - b.addParameter(Parameter.fromNode(name, obj)); - }); - - return b.build(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private List parameters = new ArrayList<>(); - - public Builder addParameter(Parameter parameter) { - this.parameters.add(parameter); - return this; - } - - public Parameters build() { - return new Parameters(this); - } - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseArn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseArn.java.resource deleted file mode 100644 index a94ea0522b28..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseArn.java.resource +++ /dev/null @@ -1,44 +0,0 @@ -import java.util.Optional; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.MapUtils; - -@SdkInternalApi -public class ParseArn extends SingleArgFn { - public static final String ID = "aws.parseArn"; - public static final Identifier PARTITION = Identifier.of("partition"); - public static final Identifier SERVICE = Identifier.of("service"); - public static final Identifier REGION = Identifier.of("region"); - public static final Identifier ACCOUNT_ID = Identifier.of("accountId"); - private static final Identifier RESOURCE_ID = Identifier.of("resourceId"); - - public ParseArn(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitParseArn(this); - } - - public static ParseArn ofExprs(Expr expr) { - return new ParseArn(FnNode.ofExprs(ID, expr)); - } - - @Override - protected Value evalArg(Value arg) { - String value = arg.expectString(); - Optional arnOpt = Arn.parse(value); - return arnOpt.map(arn -> - (Value) Value.fromRecord(MapUtils.of( - PARTITION, Value.fromStr(arn.partition()), - SERVICE, Value.fromStr(arn.service()), - REGION, Value.fromStr(arn.region()), - ACCOUNT_ID, Value.fromStr(arn.accountId()), - RESOURCE_ID, Value.fromArray(arn.resource().stream() - .map(v -> (Value) Value.fromStr(v)) - .collect(Collectors.toList())) - )) - ).orElse(new Value.None()); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseUrl.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseUrl.java.resource deleted file mode 100644 index 6894cefb167c..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ParseUrl.java.resource +++ /dev/null @@ -1,87 +0,0 @@ -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Arrays; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.MapUtils; -import software.amazon.awssdk.utils.StringUtils; - -/** - * Function to parse a URI from a string. - */ -@SdkInternalApi -public class ParseUrl extends SingleArgFn { - public static final String ID = "parseURL"; - - public static final Identifier SCHEME = Identifier.of("scheme"); - public static final Identifier AUTHORITY = Identifier.of("authority"); - public static final Identifier PATH = Identifier.of("path"); - public static final Identifier NORMALIZED_PATH = Identifier.of("normalizedPath"); - public static final Identifier IS_IP = Identifier.of("isIp"); - - public ParseUrl(FnNode fnNode) { - super(fnNode); - } - - public static ParseUrl ofExprs(Expr expr) { - return new ParseUrl(FnNode.ofExprs(ID, expr)); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitParseUrl(this); - } - - @Override - protected Value evalArg(Value arg) { - String url = arg.expectString(); - try { - URL parsed = new URL(url); - String path = parsed.getPath(); - if (parsed.getQuery() != null) { - return Value.none(); - - } - boolean isIpAddr = false; - String host = parsed.getHost(); - if (host.startsWith("[") && host.endsWith("]")) { - isIpAddr = true; - } - String[] dottedParts = host.split("\\."); - if (dottedParts.length == 4) { - if (Arrays.stream(dottedParts).allMatch(part -> { - try { - int value = Integer.parseInt(part); - return value >= 0 && value <= 255; - } catch (NumberFormatException ex) { - return false; - } - })) { - isIpAddr = true; - } - } - String normalizedPath; - if (StringUtils.isBlank(path)) { - normalizedPath = "/"; - } else { - StringBuilder builder = new StringBuilder(); - if (!path.startsWith("/")) { - builder.append("/"); - } - builder.append(path); - if (!path.endsWith("/")) { - builder.append("/"); - } - normalizedPath = builder.toString(); - } - return Value.fromRecord(MapUtils.of( - SCHEME, Value.fromStr(parsed.getProtocol()), - AUTHORITY, Value.fromStr(parsed.getAuthority()), - PATH, Value.fromStr(path), - NORMALIZED_PATH, Value.fromStr(normalizedPath), - IS_IP, Value.fromBool(isIpAddr) - )); - } catch (MalformedURLException e) { - return Value.none(); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/PartitionFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/PartitionFn.java.resource deleted file mode 100644 index eac93ca36887..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/PartitionFn.java.resource +++ /dev/null @@ -1,153 +0,0 @@ -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import java.util.regex.Pattern; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.MapUtils; - -@SdkInternalApi -public class PartitionFn extends SingleArgFn { - public static final String ID = "aws.partition"; - - public static final Identifier NAME = Identifier.of("name"); - public static final Identifier DNS_SUFFIX = Identifier.of("dnsSuffix"); - public static final Identifier DUAL_STACK_DNS_SUFFIX = Identifier.of("dualStackDnsSuffix"); - public static final Identifier SUPPORTS_FIPS = Identifier.of("supportsFIPS"); - public static final Identifier SUPPORTS_DUAL_STACK = Identifier.of("supportsDualStack"); - public static final Identifier IMPLICIT_GLOBAL_REGION = Identifier.of("implicitGlobalRegion"); - public static final Identifier INFERRED = Identifier.of("inferred"); - - private final LazyValue partitionData = LazyValue.builder() - .initializer(this::loadPartitionData) - .build(); - - private final LazyValue awsPartition = LazyValue.builder() - .initializer(this::findAwsPartition) - .build(); - - public PartitionFn(FnNode node) { - super(node); - } - - public static PartitionFn ofExprs(Expr expr) { - return new PartitionFn(FnNode.ofExprs(ID, expr)); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitPartition(this); - } - - public static PartitionFn fromParam(Parameter param) { - return PartitionFn.ofExprs(param.expr()); - } - - @Override - public Value evalArg(Value arg) { - String regionName = arg.expectString(); - - PartitionData data = partitionData.value(); - - Partition matchedPartition; - boolean inferred = false; - - // Known region - matchedPartition = data.regionMap.get(regionName); - if (matchedPartition == null) { - // try matching on region name pattern - for (Partition p : data.partitions) { - Pattern regex = Pattern.compile(p.regionRegex()); - if (regex.matcher(regionName).matches()) { - matchedPartition = p; - inferred = true; - break; - } - } - } - - // Couldn't find the region by name or pattern matching. Fallback to 'aws' partition. - if (matchedPartition == null) { - matchedPartition = awsPartition.value(); - } - - Outputs matchedOutputs = matchedPartition.outputs(); - return Value.fromRecord(MapUtils.of( - NAME, Value.fromStr(matchedPartition.id()), - DNS_SUFFIX, Value.fromStr(matchedOutputs.dnsSuffix()), - DUAL_STACK_DNS_SUFFIX, Value.fromStr(matchedOutputs.dualStackDnsSuffix()), - SUPPORTS_FIPS, Value.fromBool(matchedOutputs.supportsFips()), - SUPPORTS_DUAL_STACK, Value.fromBool(matchedOutputs.supportsDualStack()), - IMPLICIT_GLOBAL_REGION, Value.fromStr(matchedOutputs.implicitGlobalRegion()), - INFERRED, Value.fromBool(inferred))); - } - - private PartitionData loadPartitionData() { - PartitionDataProvider provider = new DefaultPartitionDataProvider(); - - // TODO: support custom partitions.json - Partitions partitions = provider.loadPartitions(); - - PartitionData partitionData = new PartitionData(); - - partitions.partitions().forEach(part -> { - partitionData.partitions.add(part); - part.regions().forEach((name, override) -> { - partitionData.regionMap.put(name, part); - }); - }); - - return partitionData; - } - - private Partition findAwsPartition() { - return partitionData.value() - .partitions - .stream() - .filter(p -> p.id().equalsIgnoreCase("aws")) - .findFirst().orElse(null); - } - - private static class PartitionData { - private final List partitions = new ArrayList<>(); - private final Map regionMap = new HashMap<>(); - } - - - private static final class LazyValue { - private final Supplier initializer; - private T value; - private boolean initialized; - - private LazyValue(Builder builder) { - this.initializer = builder.initializer; - } - - public T value() { - if (!initialized) { - value = initializer.get(); - initialized = true; - } - return value; - } - - public static Builder builder() { - return new Builder<>(); - } - - public static class Builder { - private Supplier initializer; - - public Builder initializer(Supplier initializer) { - this.initializer = initializer; - return this; - } - - public LazyValue build() { - return new LazyValue<>(this); - } - } - } - -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Ref.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Ref.java.resource deleted file mode 100644 index e2ef45422202..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Ref.java.resource +++ /dev/null @@ -1,54 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * A reference to a field. - */ -@SdkInternalApi -public class Ref extends Expr { - private final Identifier name; - - public Ref(Identifier name) { - this.name = name; - } - - @Override - public R accept(ExprVisitor visitor) { - return visitor.visitRef(this); - } - - public Identifier getName() { - return name; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - Ref ref = (Ref) o; - return name.equals(ref.name); - } - - @Override - public String template() { - return String.format("{%s}", name); - } - - @Override - public String toString() { - return name.asString(); - } - - @Override - public int hashCode() { - return name != null ? name.hashCode() : 0; - } - - @Override - public Value eval(Scope scope) { - return scope.getValue(this.name).orElse(new Value.None()); - } -} \ No newline at end of file diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Rule.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Rule.java.resource deleted file mode 100644 index 4253316b2d98..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Rule.java.resource +++ /dev/null @@ -1,87 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -@SdkInternalApi -public abstract class Rule { - public static final String CONDITIONS = "conditions"; - public static final String DOCUMENTATION = "documentation"; - public static final String ENDPOINT = "endpoint"; - public static final String ERROR = "error"; - - public static final String TREE = "tree"; - public static final String RULES = "rules"; - public static final String TYPE = "type"; - - protected final List conditions; - protected final String documentation; - - protected Rule(Builder builder) { - this.conditions = builder.conditions; - this.documentation = builder.documentation; - } - - public List getConditions() { - return conditions; - } - - public abstract T accept(RuleValueVisitor v); - - public static Rule fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder builder = builder(); - - objNode.get(CONDITIONS).asArray().forEach(cn -> builder.addCondition(Condition.fromNode(cn))); - - JsonNode documentation = objNode.get(DOCUMENTATION); - if (documentation != null) { - builder.documentation(documentation.asString()); - } - - String type = objNode.get(TYPE).asString(); - switch (type) { - case ENDPOINT: return builder.endpoint(EndpointResult.fromNode(objNode.get(ENDPOINT))); - case ERROR: return builder.error(objNode.get(ERROR).asString()); - case TREE: return builder.treeRule(objNode.get(RULES).asArray() - .stream() - .map(Rule::fromNode) - .collect(Collectors.toList())); - default: throw new IllegalStateException("Unexpected rule type: " + type); - } - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String documentation; - private final List conditions = new ArrayList<>(); - - public Builder addCondition(Condition condition) { - this.conditions.add(condition); - return this; - } - - public Builder documentation(String documentation) { - this.documentation = documentation; - return this; - } - - public EndpointRule endpoint(EndpointResult endpoint) { - return new EndpointRule(this, endpoint); - } - - public ErrorRule error(String error) { - return new ErrorRule(this, Literal.fromStr(error)); - } - - public TreeRule treeRule(List rules) { - return new TreeRule(this, rules); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleArn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleArn.java.resource similarity index 100% rename from codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleArn.java.resource rename to codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleArn.java.resource diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEngine.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEngine.java.resource deleted file mode 100644 index 20052f2d61b9..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEngine.java.resource +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface RuleEngine { - /** - * Evaluate the given {@link EndpointRuleset} using the named values in {@code args} as input into the rule set. - * - * @param ruleset The rule set to evaluate. - * @param args The arguments. - * @return The computed value. - */ - Value evaluate(EndpointRuleset ruleset, Map args); - - static RuleEngine defaultEngine() { - return new DefaultRuleEngine(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleError.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleError.java.resource deleted file mode 100644 index dda246ab3680..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleError.java.resource +++ /dev/null @@ -1,42 +0,0 @@ -import java.util.function.Supplier; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkException; - -@SdkInternalApi -public class RuleError extends SdkException { - - protected RuleError(BuilderImpl builder) { - super(builder); - } - - public static Builder builder() { - return new BuilderImpl(); - } - - public interface Builder extends SdkException.Builder { - @Override - RuleError build(); - } - - public static T ctx(String message, Supplier f) { - try { - return f.get(); - } catch (Exception e) { - throw builder().message(message).cause(e).build(); - } - } - - public static T ctx(String message, Runnable f) { - return ctx(message, () -> { - f.run(); - return null; - }); - } - - private static class BuilderImpl extends SdkException.BuilderImpl implements Builder { - @Override - public RuleError build() { - return new RuleError(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEvaluator.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEvaluator.java.resource deleted file mode 100644 index 8ff203fa43ef..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleEvaluator.java.resource +++ /dev/null @@ -1,171 +0,0 @@ -import java.util.List; -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class RuleEvaluator implements FnVisitor, ExprVisitor { - private final Scope scope = new Scope<>(); - - public Value evaluateRuleset(EndpointRuleset ruleset, Map input) { - return scope.inScope( - () -> { - ruleset - .getParameters() - .toList() - .forEach( - param -> { - param.getDefault().ifPresent(value -> scope.insert(param.getName(), value)); - }); - input.forEach(scope::insert); - for (Rule rule : ruleset.getRules()) { - Value result = handleRule(rule); - if (!result.isNone()) { - return result; - } - } - throw new RuntimeException("No rules in ruleset matched"); - }); - } - - @Override - public Value visitLiteral(Literal literal) { - return literal.eval(scope); - } - - @Override - public Value visitRef(Ref ref) { - return scope - .getValue(ref.getName()) - .orElseThrow( - () -> new RuntimeException(String.format("Invalid ruleset: %s was not in scope", ref))); - } - - @Override - public Value visitFn(Fn fn) { - return fn.acceptFnVisitor(this); - } - - @Override - public Value visitPartition(PartitionFn fn) { - return fn.eval(scope); - } - - @Override - public Value visitParseArn(ParseArn fn) { - return fn.eval(scope); - } - - @Override - public Value visitIsValidHostLabel(IsValidHostLabel fn) { - return fn.eval(scope); - } - - @Override - public Value visitBoolEquals(BooleanEqualsFn fn) { - return fn.eval(scope); - } - - @Override - public Value visitStringEquals(StringEqualsFn fn) { - return fn.eval(scope); - } - - @Override - public Value visitIsSet(IsSet fn) { - return fn.eval(scope); - } - - @Override - public Value visitNot(Not not) { - return Value.fromBool(!not.target().accept(this).expectBool()); - } - - @Override - public Value visitGetAttr(GetAttr getAttr) { - return getAttr.eval(scope); - } - - @Override - public Value visitParseUrl(ParseUrl parseUrl) { - return parseUrl.eval(scope); - } - - @Override - public Value visitSubstring(Substring fn) { - return fn.eval(scope); - } - - @Override - public Value visitUriEncode(UriEncodeFn fn) { - return fn.eval(scope); - } - - @Override - public Value visitIsVirtualHostLabelsS3Bucket(IsVirtualHostableS3Bucket fn) { - return fn.eval(scope); - } - - private Value handleRule(Rule rule) { - RuleEvaluator self = this; - return scope.inScope( - () -> { - for (Condition condition : rule.getConditions()) { - Value value = evaluateCondition(condition); - if (value.isNone() || value.equals(Value.fromBool(false))) { - return Value.none(); - } - } - return rule.accept(new RuleValueVisitor() { - @Override - public Value visitTreeRule(List rules) { - for (Rule subrule : rules) { - Value result = handleRule(subrule); - if (!result.isNone()) { - return result; - } - } - throw new RuntimeException( - String.format("no rules inside of tree rule matched—invalid rules (%s)", this)); - } - - @Override - public Value visitErrorRule(Expr error) { - return error.accept(self); - } - - @Override - public Value visitEndpointRule(EndpointResult endpoint) { - return generateEndpoint(endpoint); - } - }); - }); - } - - public Value evaluateCondition(Condition condition) { - Value value = condition.getFn().accept(this); - if (!value.isNone()) { - condition.getResult().ifPresent(res -> scope.insert(res, value)); - } - return value; - } - - public Value generateEndpoint(EndpointResult endpoint) { - Value.Endpoint.Builder builder = Value.Endpoint.builder() - .url(endpoint.getUrl() - .accept(this) - .expectString()); - endpoint.getProperties() - .forEach( - (key, value) -> { - builder.property(key.toString(), value.accept(this)); - }); - endpoint - .getHeaders() - .forEach( - (name, exprs) -> { - exprs.forEach(expr -> builder.addHeader(name, expr.accept(this).expectString())); - }); - - return builder.build(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulePartition.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RulePartition.java.resource similarity index 100% rename from codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulePartition.java.resource rename to codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RulePartition.java.resource diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleResult.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleResult.java.resource similarity index 100% rename from codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleResult.java.resource rename to codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleResult.java.resource diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleUrl.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleUrl.java.resource similarity index 100% rename from codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RuleUrl.java.resource rename to codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleUrl.java.resource diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleValueVisitor.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleValueVisitor.java.resource deleted file mode 100644 index fdbd1823c9e0..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RuleValueVisitor.java.resource +++ /dev/null @@ -1,15 +0,0 @@ -import java.util.List; -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * Visitor for the right-hand side of rules (tree, error, endpoint) - * @param The return type of the visitor - */ -@SdkInternalApi -public interface RuleValueVisitor { - R visitTreeRule(List rules); - - R visitErrorRule(Expr error); - - R visitEndpointRule(EndpointResult endpoint); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RulesFunctions.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RulesFunctions.java.resource new file mode 100644 index 000000000000..93a7c28412c6 --- /dev/null +++ b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/RulesFunctions.java.resource @@ -0,0 +1,553 @@ +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; + +@SdkInternalApi +public class RulesFunctions { + private static final String[] ENCODED_CHARACTERS = { "+", "*", "%7E" }; + private static final String[] ENCODED_CHARACTERS_REPLACEMENTS = { "%20", "%2A", "~" }; + + private static final LazyValue PARTITION_DATA = LazyValue. builder() + .initializer(RulesFunctions::loadPartitionData).build(); + + private static final int MAX_HOST_LABEL_SIZE = 63; + private static final int MIN_BUCKET_SIZE = 3; + + @SafeVarargs + public static T coalesce(T... args) { + if (args == null || args.length < 2) { + throw new IllegalArgumentException("coalesce requires at least two arguments"); + } + for (T arg : args) { + if (arg != null) { + return arg; + } + } + // All preceding arguments empty, return last argument (even if empty) + return args[args.length - 1]; + } + + @SafeVarargs + public static String coalesce(String... args) { + if (args == null || args.length < 2) { + throw new IllegalArgumentException("coalesce requires at least two arguments"); + } + for (String arg : args) { + if (arg != null && !arg.isEmpty()) { + return arg; + } + } + return args[args.length - 1]; + } + + /** + * Splits {@code value} around {@code delimiter} into at most {@code limit} parts, or into as many parts + * as there are when {@code limit} is 0. + * + *

None of the three arguments is optional. The rules language types {@code value} as a plain string, + * which its type checker only permits once the value is known to be set, and the specification requires a + * delimiter that is neither null nor empty and a limit that is not negative. A violation therefore means + * the rule set, or the code generated from it, is wrong - not that the request was unusual - so each is + * raised as an {@link SdkClientException} naming the offending argument. Generated providers surface that + * as a failed resolution rather than letting it escape as an unchecked exception. + * + *

The checks precede the {@code limit == 1} shortcut deliberately. That shortcut returns before either + * string is dereferenced, so validating after it would let {@code split(null, ",", 1)} return a list + * holding null, which reads downstream as an unset value and quietly redirects the rule rather than + * failing. + * + * @throws SdkClientException if {@code value} is null, if {@code delimiter} is null or empty, or if + * {@code limit} is negative. + */ + public static List split(String value, String delimiter, int limit) { + if (value == null) { + throw SdkClientException.create( + "Cannot split a null value. The endpoint rules language requires a value to be set before it " + + "is split, so this is a defect in the rule set or in the provider generated from it."); + } + if (delimiter == null || delimiter.isEmpty()) { + // An empty delimiter is the dangerous one: indexOf("") matches at the current position forever, so + // an unlimited split would accumulate empty strings until the heap is gone. + throw SdkClientException.create( + "Cannot split on " + (delimiter == null ? "a null" : "an empty") + " delimiter. The endpoint " + + "rules specification requires a delimiter that is neither null nor empty."); + } + if (limit < 0) { + throw SdkClientException.create( + "Cannot split with a negative limit (" + limit + "). The endpoint rules specification requires " + + "a limit of 0, meaning unlimited, or greater."); + } + + if (limit == 1) { + return Collections.singletonList(value); + } + if (value.isEmpty()) { + return Collections.singletonList(""); + } + final int delimLen = delimiter.length(); + // Unlimited split if limit == 0 + final int maxSplits = (limit == 0) ? Integer.MAX_VALUE : limit - 1; + // limit 0 means unlimited, so it carries no size hint; Math.min would turn it into a capacity of zero + // and make the list regrow from empty on the most common call shape. + List result = new ArrayList<>(limit == 0 ? 8 : Math.min(limit, 8)); + int fromIndex = 0; + int splits = 0; + while (splits < maxSplits) { + int index = value.indexOf(delimiter, fromIndex); + if (index < 0) { + break; + } + result.add(value.substring(fromIndex, index)); + fromIndex = index + delimLen; + splits++; + } + // Remainder (always added) + result.add(value.substring(fromIndex)); + return result; + } + + public static String ite(boolean condition, String ifTrue, String ifFalse) { + return condition ? ifTrue : ifFalse; + } + + public static String substring(String value, int startIndex, int stopIndex, boolean reverse) { + if (value == null) { + return null; + } + + int len = value.length(); + if (startIndex >= stopIndex || len < stopIndex) { + return null; + } + + if (!isAsciiOnly(value)) { + return null; + } + + if (reverse) { + int revStart = len - stopIndex; + int revStop = len - startIndex; + return value.substring(revStart, revStop); + } else { + return value.substring(startIndex, stopIndex); + } + } + + /** + * Equivalent to {@code stringEquals(coalesce(substring(value, startIndex, stopIndex, reverse), ""), literal)} + * without allocating the intermediate substring. Called by optimized codegen. + * + *

This mirrors {@link #substring} exactly, including its rejection of any input containing a + * character outside the 7-bit ASCII range. The positional comparison is done first because it + * fails for almost every input; the O(n) ASCII scan is only reached once the characters already + * match, which is precisely where {@link #substring} would have paid the same cost. + * + *

Only equivalent for a non-empty {@code literal}. When {@code startIndex == stopIndex} the + * spec's {@code substring} returns null and the coalesce makes the comparison against {@code ""} + * true even for a null input; codegen does not rewrite that case into this method. + */ + public static boolean substringEquals(String value, int startIndex, int stopIndex, boolean reverse, String literal) { + if (value == null) { + return false; + } + + int len = value.length(); + if (startIndex >= stopIndex || len < stopIndex) { + return false; + } + + int subLen = stopIndex - startIndex; + if (literal.length() != subLen) { + return false; + } + + int offset = reverse ? len - stopIndex : startIndex; + if (!value.regionMatches(offset, literal, 0, subLen)) { + return false; + } + + return isAsciiOnly(value); + } + + private static boolean isAsciiOnly(String value) { + for (int i = 0; i < value.length(); i++) { + // non-ascii characters (values outside of the 7bit ASCII range) + if (value.charAt(i) > 127) { + return false; + } + } + return true; + } + + // URI related functions + public static String uriEncode(String uri) { + try { + String encoded = URLEncoder.encode(uri, "UTF-8"); + for (int i = 0; i < ENCODED_CHARACTERS.length; i++) { + encoded = encoded.replace(ENCODED_CHARACTERS[i], ENCODED_CHARACTERS_REPLACEMENTS[i]); + } + return encoded; + } catch (UnsupportedEncodingException e) { + throw SdkClientException.create("Unable to URI encode value: " + uri, e); + } + } + + public static RuleUrl parseURL(String url) { + try { + return RuleUrl.parse(url); + } catch (MalformedURLException e) { + return null; + } + } + + public static boolean isValidHostLabel(String hostLabel, boolean allowDots) { + return allowDots ? isValidHostLabelMulti(hostLabel) : isValidHostLabelSingle(hostLabel); + } + + // Validates a single label in s[start..end): ^[A-Za-z0-9][A-Za-z0-9\-]{0,62}$ + private static boolean isValidSingleLabel(String s, int start, int end) { + int length = end - start; + if (length < 1 || length > MAX_HOST_LABEL_SIZE) { + return false; + } + + // first char must be [A-Za-z0-9] + if (!isAlphanumeric(s.charAt(start))) { + return false; + } + + // remaining chars must be [A-Za-z0-9-] + for (int i = start + 1; i < end; i++) { + char c = s.charAt(i); + if (!isAlphanumeric(c) && c != '-') { + return false; + } + } + + return true; + } + + private static boolean isAlphanumeric(char c) { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); + } + + /** + * Validates a single DNS label (no dots allowed), the {@code allowDots == false} case of + * {@link #isValidHostLabel}. Called directly by optimized codegen when {@code allowDots} is a + * compile-time constant, which skips the dispatch. + */ + public static boolean isValidHostLabelSingle(String hostLabel) { + int len = hostLabel == null ? 0 : hostLabel.length(); + if (len == 0) { + return false; + } + return isValidSingleLabel(hostLabel, 0, len); + } + + /** + * Validates a multi-label DNS name (dots allowed), the {@code allowDots == true} case of + * {@link #isValidHostLabel}. Called directly by optimized codegen when {@code allowDots} is a + * compile-time constant, which skips the dispatch. + */ + public static boolean isValidHostLabelMulti(String hostLabel) { + int len = hostLabel == null ? 0 : hostLabel.length(); + if (len == 0) { + return false; + } + int start = 0; + for (int i = 0; i <= len; i++) { + if (i == len || hostLabel.charAt(i) == '.') { + int chunkLen = i - start; + if (chunkLen < 1 || chunkLen > MAX_HOST_LABEL_SIZE) { + return false; + } else if (!isValidSingleLabel(hostLabel, start, i)) { + return false; + } + start = i + 1; + } + } + return true; + } + + private static boolean isLowerCaseAlphanumeric(char c) { + return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); + } + + // AWS related functions + + /** + * Resolves the partition a region belongs to. + * + *

{@link RulePartition} is immutable and is a pure function of the matched {@link Partition}, + * of which there are only a handful, loaded once. The instances are therefore built up front in + * {@link #loadPartitionData()} and shared, so this method allocates nothing on any path that + * resolves, and holds no per-call state. + * + * @throws SdkClientException if the region matches no partition and the loaded metadata declares no + * 'aws' partition to fall back to. + */ + public static RulePartition awsPartition(String regionName) { + PartitionData data = PARTITION_DATA.value(); + + // Known region + RulePartition matched = data.regionMap.get(regionName); + if (matched != null) { + return matched; + } + + // Try matching on region name pattern + List entries = data.partitions; + for (int i = 0; i < entries.size(); i++) { + PartitionEntry entry = entries.get(i); + if (entry.partition.regionMatches(regionName)) { + return entry.rulePartition; + } + } + + // Couldn't find the region by name or pattern matching. Fallback to 'aws' partition. + // + // Only this path needs 'aws', so it is also the only path that can reject partition metadata for + // lacking it. Validating at load instead would refuse every region, including the ones the + // metadata does describe. Returning null is not an option either: generated code null-checks the + // result and would read null as "condition not satisfied", quietly taking a different rule branch. + if (data.awsRulePartition == null) { + throw SdkClientException.create( + "Region '" + regionName + "' matched no partition by name or by region pattern, and the " + + "partition metadata in use does not declare the 'aws' partition that is the fallback for " + + "an unmatched region. Check the partitions file supplied through the aws.partitionsFile " + + "system property, the AWS_PARTITIONS_FILE environment variable, or a " + + "software/amazon/awssdk/global/partitions.json resource on the classpath."); + } + return data.awsRulePartition; + } + + public static RuleArn awsParseArn(String value) { + return RuleArn.parse(value); + } + + public static boolean stringEquals(String left, String right) { + if (left == null || right == null) { + return false; + } + return left.equals(right); + } + + public static T listAccess(List values, int index) { + if (values == null) { + return null; + } + if (index < 0) { + index = values.size() + index; + if (index < 0) { + return null; + } + } + if (index >= values.size()) { + return null; + } + return values.get(index); + } + + public static boolean awsIsVirtualHostableS3Bucket(String hostLabel, boolean allowDots) { + // Bucket names must be between 3 (min) and 63 (max) characters long. + int bucketLength = hostLabel == null ? 0 : hostLabel.length(); + if (bucketLength < MIN_BUCKET_SIZE || bucketLength > MAX_HOST_LABEL_SIZE) { + return false; + } + + // Bucket names must begin and end with a letter or number. + if (!isLowerCaseAlphanumeric(hostLabel.charAt(0)) || !isLowerCaseAlphanumeric(hostLabel.charAt(bucketLength - 1))) { + return false; + } + + // Bucket names can consist only of lowercase letters, numbers, periods (.), and hyphens (-). + if (!allowDots) { + for (int i = 1; i < bucketLength - 1; i++) { // already validated 0 and N - 1. + if (!isValidBucketSegmentChar(hostLabel.charAt(i))) { + return false; + } + } + return true; + } + + // Check for consecutive dots or hyphens + char last = hostLabel.charAt(0); + for (int i = 1; i < bucketLength; i++) { + char c = hostLabel.charAt(i); + // Don't allow "bucket-.foo" or "bucket.-foo" + if (c == '.') { + if (last == '.' || last == '-') { + return false; + } + } else if (c == '-') { + if (last == '.') { + return false; + } + } else if (!isLowerCaseAlphanumeric(c)) { + return false; + } + last = c; + } + + // Bucket names must not be formatted as an IP address (for example, 192.168.5.4). + return !isIpAddr(hostLabel); + } + + private static boolean isValidBucketSegmentChar(char c) { + return isLowerCaseAlphanumeric(c) || c == '-'; + } + + private static boolean isIpAddr(String host) { + if (host == null || host.length() < 2) { + return false; + } + + // Simple check for IPv6 (enclosed in square brackets) + if (host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']') { + return true; + } + + int from = 0; + int segments = 0; + boolean done = false; + while (!done) { + int index = host.indexOf('.', from); + if (index == -1) { + if (segments != 3) { + // E.g., 123.com + return false; + } + index = host.length(); + done = true; + } else if (segments == 3) { + // E.g., 1.2.3.4.5 + return false; + } + int length = index - from; + if (length == 1) { + char ch0 = host.charAt(from); + if (ch0 < '0' || ch0 > '9') { + return false; + } + } else if (length == 2) { + char ch0 = host.charAt(from); + char ch1 = host.charAt(from + 1); + if ((ch0 <= '0' || ch0 > '9') || (ch1 < '0' || ch1 > '9')) { + return false; + } + } else if (length == 3) { + char ch0 = host.charAt(from); + char ch1 = host.charAt(from + 1); + char ch2 = host.charAt(from + 2); + if ((ch0 <= '0' || ch0 > '9') || (ch1 < '0' || ch1 > '9') || (ch2 < '0' || ch2 > '9')) { + return false; + } + // This is a heuristic; We are intentionally not checking for the range 000-255. + } else { + return false; + } + from = index + 1; + segments += 1; + } + return true; + } + + private static PartitionData loadPartitionData() { + PartitionDataProvider provider = new DefaultPartitionDataProvider(); + + // TODO: support custom partitions.json + Partitions partitions = provider.loadPartitions(); + + List entries = new ArrayList<>(); + Map regionMap = new HashMap<>(); + RulePartition awsRulePartition = null; + + for (Partition part : partitions.partitions()) { + RulePartition rulePartition = RulePartition.from(part.id(), part.outputs()); + entries.add(new PartitionEntry(part, rulePartition)); + for (String regionName : part.regions().keySet()) { + regionMap.put(regionName, rulePartition); + } + if ("aws".equalsIgnoreCase(part.id())) { + awsRulePartition = rulePartition; + } + } + + // Stays null when the metadata declares no 'aws' partition. That only matters for a region this + // data cannot match, so awsPartition raises it there rather than failing the load and taking the + // regions the metadata does describe down with it. + return new PartitionData(entries, regionMap, awsRulePartition); + } + + private static final class PartitionData { + private final List partitions; + private final Map regionMap; + // Fallback used when a region matches neither a known region name nor a partition pattern. Null if + // the loaded metadata declares no 'aws' partition, which only fails the requests that need it. + private final RulePartition awsRulePartition; + + private PartitionData(List partitions, Map regionMap, + RulePartition awsRulePartition) { + this.partitions = partitions; + this.regionMap = regionMap; + this.awsRulePartition = awsRulePartition; + } + } + + /** + * Pairs a {@link Partition} with its precomputed {@link RulePartition}. The former is needed to + * evaluate the region pattern, the latter is what callers get back. + */ + private static final class PartitionEntry { + private final Partition partition; + private final RulePartition rulePartition; + + private PartitionEntry(Partition partition, RulePartition rulePartition) { + this.partition = partition; + this.rulePartition = rulePartition; + } + } + + private static final class LazyValue { + private final Supplier initializer; + private T value; + private boolean initialized; + + private LazyValue(Builder builder) { + this.initializer = builder.initializer; + } + + public T value() { + if (!initialized) { + value = initializer.get(); + initialized = true; + } + return value; + } + + public static Builder builder() { + return new Builder<>(); + } + + public static class Builder { + private Supplier initializer; + + public Builder initializer(Supplier initializer) { + this.initializer = initializer; + return this; + } + + public LazyValue build() { + return new LazyValue<>(this); + } + } + } +} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Scope.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Scope.java.resource deleted file mode 100644 index 55ce7596b1e8..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Scope.java.resource +++ /dev/null @@ -1,90 +0,0 @@ -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashMap; -import java.util.Optional; -import java.util.function.Supplier; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class Scope { - private final Deque> scope; - - public Scope() { - this.scope = new ArrayDeque<>(); - this.scope.push(new FatScope()); - } - - public void push() { - scope.push(new FatScope<>()); - } - - public void pop() { - scope.pop(); - } - - public void insert(String name, T value) { - this.insert(Identifier.of(name), value); - } - - public void insert(Identifier name, T value) { - this.scope.getFirst().types().put(name, value); - } - - public void insertFact(Expr name, T value) { - this.scope.getFirst().facts().put(name, value); - } - - public U inScope(Supplier func) { - this.push(); - try { - return func.get(); - } finally { - this.pop(); - } - } - - @Override - public String toString() { - HashMap toPrint = new HashMap<>(); - for (FatScope layer: scope) { - toPrint.putAll(layer.types()); - } - return toPrint.toString(); - } - - /** - * Search the fact stack for an explicitly calculated value for [expr] - *

- * Currently, this is only impacted by the `isSet` function which will record - * `T`, rather than {@code Option} for its arguments - * - * @param expr The expression to evaluate - * @return The value from the scope - */ - public Optional eval(Expr expr) { - for (FatScope layer : scope) { - if (layer.facts().containsKey(expr)) { - return Optional.of(layer.facts().get(expr)); - } - } - return Optional.empty(); - } - - public T expectValue(Identifier name) { - for (FatScope layer : scope) { - if (layer.types().containsKey(name)) { - return layer.types().get(name); - } - } - throw new InnerParseError(String.format("No field named %s", name)); - } - - public Optional getValue(Identifier name) { - for (FatScope layer : scope) { - if (layer.types().containsKey(name)) { - return Optional.of(layer.types().get(name)); - } - } - return Optional.empty(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SingleArgFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SingleArgFn.java.resource deleted file mode 100644 index 5c65095bf654..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SingleArgFn.java.resource +++ /dev/null @@ -1,20 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public abstract class SingleArgFn extends Fn { - - public SingleArgFn(FnNode fnNode) { - super(fnNode); - } - - public Expr target() { - return expectOneArg(); - } - - @Override - public Value eval(Scope scope) { - return evalArg(expectOneArg().eval(scope)); - } - - protected abstract Value evalArg(Value arg); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SourceException.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SourceException.java.resource deleted file mode 100644 index 01c42c05a68e..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/SourceException.java.resource +++ /dev/null @@ -1,61 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkException; - -@SdkInternalApi -public class SourceException extends SdkException { - private SourceException(Builder b) { - super(b); - } - - public static Builder builder() { - return new BuilderImpl(); - } - - interface Builder extends SdkException.Builder { - @Override - Builder cause(Throwable cause); - - @Override - Builder writableStackTrace(Boolean writableStackTrace); - - @Override - Builder message(String message); - - @Override - SourceException build(); - - @Override - Builder numAttempts(Integer numAttempts); - } - - public static class BuilderImpl extends SdkException.BuilderImpl implements Builder { - @Override - public Builder cause(Throwable cause) { - super.cause(cause); - return this; - } - - @Override - public Builder message(String message) { - super.message(message); - return this; - } - - @Override - public Builder writableStackTrace(Boolean writableStackTrace) { - super.writableStackTrace(writableStackTrace); - return this; - } - - @Override - public SourceException build() { - return new SourceException(this); - } - - @Override - public Builder numAttempts(Integer numAttempts) { - super.numAttempts(numAttempts); - return this; - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/StringEqualsFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/StringEqualsFn.java.resource deleted file mode 100644 index 9166e78826e6..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/StringEqualsFn.java.resource +++ /dev/null @@ -1,34 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.utils.Pair; - -@SdkInternalApi -public class StringEqualsFn extends Fn { - public static final String ID = "stringEquals"; - - public StringEqualsFn(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitStringEquals(this); - } - - public static StringEqualsFn ofExprs(Expr expr, Expr of) { - return new StringEqualsFn(FnNode.ofExprs(ID, expr, of)); - } - - public Expr getLeft() { - return expectTwoArgs().left(); - } - - public Expr getRight() { - return expectTwoArgs().right(); - } - - @Override - public Value eval(Scope scope) { - Pair args = expectTwoArgs(); - return Value.fromBool(args.left().eval(scope).expectString().equals(args.right().eval(scope).expectString())); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Substring.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Substring.java.resource deleted file mode 100644 index 3c260388a0a8..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Substring.java.resource +++ /dev/null @@ -1,62 +0,0 @@ -import java.util.List; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class Substring extends VarargFn { - public static final String ID = "substring"; - public static final Identifier SUBSTRING = Identifier.of("substring"); - private static final int EXPECTED_NUMBER_ARGS = 4; - - public Substring(FnNode fnNode) { - super(fnNode); - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitSubstring(this); - } - - public static Substring ofExprs(Expr expr, int startIndex, int stopIndex, Boolean reverse) { - return new Substring(FnNode.ofExprs(ID, expr, Expr.of(startIndex), Expr.of(stopIndex), Expr.of(reverse))); - } - - public Expr stringToParse() { - return expectVariableArgs(EXPECTED_NUMBER_ARGS).get(0); - } - - public Expr startIndex() { - return expectVariableArgs(EXPECTED_NUMBER_ARGS).get(1); - } - - public Expr stopIndex() { - return expectVariableArgs(EXPECTED_NUMBER_ARGS).get(2); - } - - public Expr reverse() { - return expectVariableArgs(EXPECTED_NUMBER_ARGS).get(3); - } - - @Override - public Value eval(Scope scope) { - List args = expectVariableArgs(EXPECTED_NUMBER_ARGS); - String str = args.get(0).eval(scope).expectString(); - int startIndex = args.get(1).eval(scope).expectInt(); - int stopIndex = args.get(2).eval(scope).expectInt(); - boolean reverse = args.get(3).eval(scope).expectBool(); - - if (startIndex >= stopIndex || str.length() - 1 < stopIndex) { - return new Value.None(); - } - - String substr; - if (reverse) { - String reversedStr = new StringBuilder(str).reverse().toString(); - substr = new StringBuilder(reversedStr.substring(startIndex, stopIndex)).reverse().toString(); - } else { - substr = str.substring(startIndex, stopIndex); - } - - return Value.fromStr(substr); - - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Template.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Template.java.resource deleted file mode 100644 index fcf3799098d1..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Template.java.resource +++ /dev/null @@ -1,247 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * Template represents a "Template Literal". This is a literal string within the rules language. A template can contain 0 or more - * dynamic sections. The dynamic sections use getAttr short-form: - *

- * `https://{Region}.{partition#dnsSuffix}` -------- ------------ | | Dynamic getAttr short - * form - */ -@SdkInternalApi -public class Template { - private final List parts; - - Template(String template) { - this.parts = RuleError.ctx("when parsing template", () -> parseTemplate(template)); - } - - public Stream accept(TemplateVisitor visitor) { - if (isStatic()) { - return Stream.of(visitor.visitStaticTemplate(expectLiteral())); - } - if (parts.size() == 1) { - // must be dynamic because previous branch handled single-element static template - return Stream.of(visitor.visitSingleDynamicTemplate(((Dynamic) parts.get(0)).expr)); - } - Stream start = Stream.of(visitor.startMultipartTemplate()); - Stream components = parts.stream().map(part -> part.accept(visitor)); - Stream end = Stream.of(visitor.finishMultipartTemplate()); - return Stream.concat(start, Stream.concat(components, end)); - } - - public List getParts() { - return parts; - } - - public boolean isStatic() { - return this.parts.stream().allMatch(it -> it instanceof Literal); - } - - public String expectLiteral() { - assert isStatic(); - return this.parts.stream().map(Part::toString).collect(Collectors.joining()); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Template template = (Template) o; - - return parts != null ? parts.equals(template.parts) : template.parts == null; - } - - @Override - public int hashCode() { - return parts != null ? parts.hashCode() : 0; - } - - public static Template fromString(String s) { - return new Template(s); - } - - @Override - public String toString() { - return String.format("\"%s\"", this.parts.stream().map(Part::toString).collect(Collectors.joining())); - } - - public Value eval(Scope scope) { - return Value.fromStr(parts.stream().map(part -> part.eval(scope)).collect(Collectors.joining())); - } - - private List parseTemplate(String template) { - List out = new ArrayList<>(); - Optional templateStart = Optional.empty(); - int depth = 0; - int templateEnd = 0; - for (int i = 0; i < template.length(); i++) { - if (template.substring(i).startsWith("{{")) { - i++; - continue; - } - if (template.substring(i).startsWith("}}")) { - i++; - continue; - } - if (template.charAt(i) == '{') { - if (depth == 0) { - if (templateEnd != i) { - out.add(Literal.unescape(template.substring(templateEnd, i))); - } - templateStart = Optional.of(i + 1); - } - depth++; - } - if (template.charAt(i) == '}') { - depth--; - if (depth < 0) { - throw new InnerParseError("unmatched `}` in template"); - } - if (depth == 0) { - out.add(Dynamic.parse(template.substring(templateStart.get(), i))); - templateStart = Optional.empty(); - } - templateEnd = i + 1; - } - } - if (depth != 0) { - throw new InnerParseError("unmatched `{` in template"); - } - if (templateEnd < template.length()) { - out.add(Literal.unescape(template.substring(templateEnd))); - } - return out; - } - - public abstract static class Part { - abstract String eval(Scope scope); - - abstract T accept(TemplateVisitor visitor); - } - - public static class Literal extends Part { - private final String value; - - public Literal(String value) { - if (value.isEmpty()) { - throw new RuntimeException("value cannot blank"); - } - this.value = value; - } - - public static Literal unescape(String value) { - return new Literal(value.replace("{{", "{").replace("}}", "}")); - } - - public String getValue() { - return value; - } - - @Override - public String toString() { - return this.value; - } - - @Override - String eval(Scope scope) { - return this.value; - } - - @Override - T accept(TemplateVisitor visitor) { - return visitor.visitStaticElement(this.value); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - Literal literal = (Literal) o; - - return value != null ? value.equals(literal.value) : literal.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } - - public static class Dynamic extends Part { - private final String raw; - private final Expr expr; - - private Dynamic(String raw, Expr expr) { - this.raw = raw; - this.expr = expr; - } - - @Override - public String toString() { - return String.format("{dyn %s}", this.raw); - } - - @Override - String eval(Scope scope) { - return RuleError.ctx("while evaluating " + this, () -> expr.eval(scope).expectString()); - } - - @Override - T accept(TemplateVisitor visitor) { - return visitor.visitDynamicElement(this.expr); - } - - public Expr getExpr() { - return expr; - } - - public static Dynamic parse(String value) { - return new Dynamic(value, Expr.parseShortform(value)); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - if (!super.equals(o)) { - return false; - } - - Dynamic dynamic = (Dynamic) o; - - if (raw != null ? !raw.equals(dynamic.raw) : dynamic.raw != null) { - return false; - } - return expr != null ? expr.equals(dynamic.expr) : dynamic.expr == null; - } - - @Override - public int hashCode() { - int result = raw != null ? raw.hashCode() : 0; - result = 31 * result + (expr != null ? expr.hashCode() : 0); - return result; - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TemplateVisitor.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TemplateVisitor.java.resource deleted file mode 100644 index a83584414a74..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TemplateVisitor.java.resource +++ /dev/null @@ -1,55 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -/** - * For code generating from a template, use a `TemplateVisitor`. Template visitor is written to enable optimized - * behavior for static templates with no dynamic components. - * @param The return type of this visitor - */ -@SdkInternalApi -public interface TemplateVisitor { - /** - * The template contains a single static string, eg. `"https://mystaticendpoing.com"` - * @param value: The static value of the template. - * @return T - */ - T visitStaticTemplate(String value); - - /** - * The template contains a single dynamic element, eg. `{Region}`. In this case, string formatting is not required. - * The type of the value is guaranteed to be a string. - * @param value: The single expression that represents this template. - * @return T - */ - T visitSingleDynamicTemplate(Expr value); - - /** - * Visit a static element within a multipart template. This will only be called after - * {@link #startMultipartTemplate()} has been invoked. - * @param value A static element within a larger template - * @return T - */ - T visitStaticElement(String value); - - /** - * Visit a dynamic element within a multipart template. This will only be called after - * {@link #startMultipartTemplate()} has been invoked. - * @param value The dynamic template value - * @return T - */ - T visitDynamicElement(Expr value); - - /** - * Invoked prior to visiting a multipart template like `https://{Region}.{dnsSuffix}`. This function will - * be followed by invocations of {@link #visitStaticTemplate(String)} and - * {@link #visitDynamicElement(Expr)}. - * @return T - */ - T startMultipartTemplate(); - - /** - * Invoked at the conclusion of visiting a multipart template like `https://{Region}.{dnsSuffix}`. This allows - * implementations to do something like call `string.join()` or `stringbuilder.toString()`. - * @return T - */ - T finishMultipartTemplate(); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ToParameterReference.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ToParameterReference.java.resource deleted file mode 100644 index 26049b384187..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/ToParameterReference.java.resource +++ /dev/null @@ -1,6 +0,0 @@ -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public interface ToParameterReference { - ParameterReference toParameterReference(); -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TreeRule.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TreeRule.java.resource deleted file mode 100644 index 63b6c9002825..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/TreeRule.java.resource +++ /dev/null @@ -1,26 +0,0 @@ -import java.util.List; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -public class TreeRule extends Rule { - private final List rules; - - protected TreeRule(Builder builder, List rules) { - super(builder); - this.rules = rules; - } - - @Override - public T accept(RuleValueVisitor v) { - return v.visitTreeRule(rules); - } - - @Override - public String toString() { - return "TreeRule{" + - "conditions=" + conditions + - ", documentation='" + documentation + '\'' + - ", rules=" + rules + - '}'; - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/UriEncodeFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/UriEncodeFn.java.resource deleted file mode 100644 index cb5d4e8614ef..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/UriEncodeFn.java.resource +++ /dev/null @@ -1,34 +0,0 @@ -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkClientException; - -@SdkInternalApi -public class UriEncodeFn extends SingleArgFn { - public static final String ID = "uriEncode"; - private static final String[] ENCODED_CHARACTERS = new String[]{"+", "*", "%7E"}; - private static final String[] ENCODED_CHARACTERS_REPLACEMENTS = new String[]{"%20", "%2A", "~"}; - - public UriEncodeFn(FnNode fnNode) { - super(fnNode); - } - - @Override - protected Value evalArg(Value arg) { - String url = arg.expectString(); - try { - String encoded = URLEncoder.encode(url, "UTF-8"); - for (int i = 0; i < ENCODED_CHARACTERS.length; i++) { - encoded = encoded.replace(ENCODED_CHARACTERS[i], ENCODED_CHARACTERS_REPLACEMENTS[i]); - } - return Value.fromStr(encoded); - } catch (UnsupportedEncodingException e) { - throw SdkClientException.create("Unable to URI encode value: " + url, e); - } - } - - @Override - public T acceptFnVisitor(FnVisitor visitor) { - return visitor.visitUriEncode(this); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Value.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Value.java.resource deleted file mode 100644 index e32aa87ac5df..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/Value.java.resource +++ /dev/null @@ -1,448 +0,0 @@ -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.stream.Collectors; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; - -/** - * Base class for the types of values computable by the {@link RuleEngine}. - */ -@SdkInternalApi -public abstract class Value { - - public boolean isNone() { - return false; - } - - public String expectString() { - throw new RuntimeException("Expected string but was: " + this); - } - - public boolean expectBool() { - throw new RuntimeException("Expected bool but was: " + this); - } - - public Record expectRecord() { - throw new RuntimeException("Expected object but was: " + this); - } - - public Endpoint expectEndpoint() { - throw new RuntimeException("Expected endpoint, found " + this); - } - - public Array expectArray() { - throw new RuntimeException("Expected array, found " + this); - } - - public int expectInt() { - throw new RuntimeException("Expected int, found " + this); - } - - public static Value fromNode(JsonNode node) { - if (node.isArray()) { - return new Array(node.asArray().stream().map(Value::fromNode).collect(Collectors.toList())); - } else if (node.isBoolean()) { - return fromBool(node.asBoolean()); - } else if (node.isNull()) { - throw SdkClientException.create("null cannot be used as a literal"); - } else if (node.isNumber()) { - return fromInteger(Integer.parseInt(node.asNumber())); - } else if (node.isObject()) { - HashMap out = new HashMap<>(); - node.asObject().forEach((k, v) -> out.put(Identifier.of(k), fromNode(v))); - return fromRecord(out); - } else if (node.isString()) { - return fromStr(node.asString()); - } - throw SdkClientException.create("Unable to create Value from " + node); - } - - public static Endpoint endpointFromNode(JsonNode source) { - return Endpoint.fromNode(source); - } - - /** - * A string value. - */ - public static class Str extends Value { - private final String value; - - private Str(String value) { - this.value = value; - } - - @Override - public String expectString() { - return value; - } - - @Override - public String toString() { - return "Str{" + - "value='" + value + '\'' + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Str str = (Str) o; - - return value != null ? value.equals(str.value) : str.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } - - /** - * An integer value. - */ - public static class Int extends Value { - private final int value; - - private Int(int value) { - this.value = value; - } - - @Override - public int expectInt() { - return value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Int anInt = (Int) o; - - return value == anInt.value; - } - - @Override - public int hashCode() { - return value; - } - } - - /** - * A boolean value. - */ - public static class Bool extends Value { - private final boolean value; - - private Bool(boolean value) { - this.value = value; - } - - @Override - public boolean expectBool() { - return value; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Bool bool = (Bool) o; - - return value == bool.value; - } - - @Override - public int hashCode() { - return value ? 1 : 0; - } - } - - /** - * An array value. - */ - public static class Array extends Value { - private List inner; - - private Array(List inner) { - this.inner = inner; - } - - @Override - public Array expectArray() { - return this; - } - - public Value get(int idx) { - if (this.inner.size() > idx) { - return this.inner.get(idx); - } else { - return new Value.None(); - } - } - - public int size() { - return inner.size(); - } - - @Override - public String toString() { - return "Array{" + - "inner=" + inner + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Array array = (Array) o; - - return inner != null ? inner.equals(array.inner) : array.inner == null; - } - - @Override - public int hashCode() { - return inner != null ? inner.hashCode() : 0; - } - } - - /** - * A record (map) value. - */ - public static class Record extends Value { - private final Map value; - - private Record(Map value) { - this.value = value; - } - - public Value get(Identifier id) { - return value.get(id); - } - - public Map getValue() { - return value; - } - - public void forEach(BiConsumer fn) { - value.forEach(fn); - } - - @Override - public Record expectRecord() { - return this; - } - - @Override - public String toString() { - return "Record{" + - "value=" + value + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Record record = (Record) o; - - return value != null ? value.equals(record.value) : record.value == null; - } - - @Override - public int hashCode() { - return value != null ? value.hashCode() : 0; - } - } - - public static class Endpoint extends Value { - private static final String URL = "url"; - private static final String PROPERTIES = "properties"; - private static final String HEADERS = "headers"; - - private final String url; - private final Map properties; - private final Map> headers; - - private Endpoint(Builder b) { - this.url = b.url; - this.properties = b.properties; - this.headers = b.headers; - } - - public String getUrl() { - return url; - } - - public Map getProperties() { - return properties; - } - - public Map> getHeaders() { - return headers; - } - - @Override - public Endpoint expectEndpoint() { - return this; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Endpoint endpoint = (Endpoint) o; - - if (url != null ? !url.equals(endpoint.url) : endpoint.url != null) { - return false; - } - if (properties != null ? !properties.equals(endpoint.properties) : endpoint.properties != null) { - return false; - } - return headers != null ? headers.equals(endpoint.headers) : endpoint.headers == null; - } - - @Override - public int hashCode() { - int result = url != null ? url.hashCode() : 0; - result = 31 * result + (properties != null ? properties.hashCode() : 0); - result = 31 * result + (headers != null ? headers.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "Endpoint{" + - "url='" + url + '\'' + - ", properties=" + properties + - ", headers=" + headers + - '}'; - } - - public static Endpoint fromNode(JsonNode node) { - Builder b = builder(); - - Map objNode = node.asObject(); - - b.url(objNode.get(URL).asString()); - - JsonNode propertiesNode = objNode.get(PROPERTIES); - if (propertiesNode != null) { - propertiesNode.asObject() - .forEach((k, v) -> { - b.property(k, Value.fromNode(v)); - }); - } - - JsonNode headersNode = objNode.get(HEADERS); - if (headersNode != null) { - headersNode.asObject() - .forEach((k, v) -> v.asArray().forEach(e -> b.addHeader(k, e.asString()))); - } - - return b.build(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String url; - private final Map properties = new HashMap<>(); - private final Map> headers = new HashMap<>(); - - public Builder url(String url) { - this.url = url; - return this; - } - - public Builder properties(Map properties) { - this.properties.clear(); - this.properties.putAll(properties); - return this; - } - - public Builder property(String name, Value value) { - this.properties.put(name, value); - return this; - } - - public Builder addHeader(String name, String value) { - List values = this.headers.computeIfAbsent(name, (k) -> new ArrayList<>()); - values.add(value); - return this; - } - - public Endpoint build() { - return new Endpoint(this); - } - } - } - - public static class None extends Value { - @Override - public boolean isNone() { - return true; - } - } - - public static Str fromStr(String value) { - return new Str(value); - } - - public static Int fromInteger(int value) { - return new Int(value); - } - - public static Bool fromBool(boolean value) { - return new Bool(value); - } - - public static Array fromArray(List value) { - return new Array(value); - } - - public static Record fromRecord(Map value) { - return new Record(value); - } - - public static None none() { - return new None(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/VarargFn.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/VarargFn.java.resource deleted file mode 100644 index e671494ea3ba..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules/VarargFn.java.resource +++ /dev/null @@ -1,16 +0,0 @@ -import java.util.List; -import software.amazon.awssdk.annotations.SdkInternalApi; - -@SdkInternalApi -abstract class VarargFn extends Fn { - - VarargFn(FnNode fnNode) { - super(fnNode); - } - - public abstract Value eval(Scope scope); - - protected List args() { - return this.fnNode.getArgv(); - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/Partitions.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/Partitions.java.resource deleted file mode 100644 index c53df6f93822..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/Partitions.java.resource +++ /dev/null @@ -1,109 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.utils.ToString; - -@SdkInternalApi -public final class Partitions { - private static final String VERSION = "version"; - private static final String PARTITIONS = "partitions"; - - private final String version; - private final List partitions; - - private Partitions(Builder builder) { - this.version = builder.version; - this.partitions = new ArrayList<>(builder.partitions); - } - - public String version() { - return version; - } - - public List partitions() { - return partitions; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - Partitions that = (Partitions) o; - - if (version != null ? !version.equals(that.version) : that.version != null) { - return false; - } - return partitions != null ? partitions.equals(that.partitions) : that.partitions == null; - } - - @Override - public int hashCode() { - int result = version != null ? version.hashCode() : 0; - result = 31 * result + (partitions != null ? partitions.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return ToString.builder("Partitions") - .add("version", version) - .add("partitions", partitions) - .build(); - } - - public static Partitions fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder b = builder(); - - JsonNode version = objNode.get(VERSION); - if (version != null) { - b.version(version.asString()); - } - - JsonNode partitions = objNode.get(PARTITIONS); - if (partitions != null) { - partitions.asArray().forEach(partNode -> b.addPartition(Partition.fromNode(partNode))); - } - - return b.build(); - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String version; - private List partitions = new ArrayList<>(); - - public Builder version(String version) { - this.version = version; - return this; - } - - public Builder partitions(List partitions) { - this.partitions.clear(); - if (partitions != null) { - this.partitions.addAll(partitions); - } - return this; - } - - public Builder addPartition(Partition p) { - this.partitions.add(p); - return this; - } - - public Partitions build() { - return new Partitions(this); - } - } -} diff --git a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource b/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource deleted file mode 100644 index d1944d9ed01e..000000000000 --- a/codegen/src/main/resources/software/amazon/awssdk/codegen/rules2/RulesFunctions.java.resource +++ /dev/null @@ -1,343 +0,0 @@ -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.exception.SdkClientException; - -@SdkInternalApi -public class RulesFunctions { - private static final String[] ENCODED_CHARACTERS = { "+", "*", "%7E" }; - private static final String[] ENCODED_CHARACTERS_REPLACEMENTS = { "%20", "%2A", "~" }; - - private static final LazyValue PARTITION_DATA = LazyValue. builder() - .initializer(RulesFunctions::loadPartitionData).build(); - - private static final LazyValue AWS_PARTITION = LazyValue. builder() - .initializer(RulesFunctions::findAwsPartition).build(); - - private static final int MAX_HOST_LABEL_SIZE = 63; - private static final int MIN_BUCKET_SIZE = 3; - - public static String substring(String value, int startIndex, int stopIndex, boolean reverse) { - if (value == null) { - return null; - } - - int len = value.length(); - if (startIndex >= stopIndex || len < stopIndex) { - return null; - } - - for (int i = 0; i < len; i++) { - // non-ascii characters (values outside of the 7bit ASCII range) - if (value.charAt(i) > 127) { - return null; - } - } - - if (reverse) { - int revStart = len - stopIndex; - int revStop = len - startIndex; - return value.substring(revStart, revStop); - } else { - return value.substring(startIndex, stopIndex); - } - } - - // URI related functions - public static String uriEncode(String uri) { - try { - String encoded = URLEncoder.encode(uri, "UTF-8"); - for (int i = 0; i < ENCODED_CHARACTERS.length; i++) { - encoded = encoded.replace(ENCODED_CHARACTERS[i], ENCODED_CHARACTERS_REPLACEMENTS[i]); - } - return encoded; - } catch (UnsupportedEncodingException e) { - throw SdkClientException.create("Unable to URI encode value: " + uri, e); - } - } - - public static RuleUrl parseURL(String url) { - try { - return RuleUrl.parse(url); - } catch (MalformedURLException e) { - return null; - } - } - - public static boolean isValidHostLabel(String hostLabel, boolean allowDots) { - int len = hostLabel == null ? 0 : hostLabel.length(); - if (len == 0) { - return false; - } - - // Single-label mode - if (!allowDots) { - return isValidSingleLabel(hostLabel, 0, len); - } - - // Multi-label mode - int start = 0; - for (int i = 0; i <= len; i++) { - if (i == len || hostLabel.charAt(i) == '.') { - // chunk is hostLabel[start..i) - int chunkLen = i - start; - if (chunkLen < 1 || chunkLen > MAX_HOST_LABEL_SIZE) { - return false; - } else if (!isValidSingleLabel(hostLabel, start, i)) { - return false; - } - start = i + 1; - } - } - return true; - } - - // Validates a single label in s[start..end): ^[A-Za-z0-9][A-Za-z0-9\-]{0,62}$ - private static boolean isValidSingleLabel(String s, int start, int end) { - int length = end - start; - if (length < 1 || length > MAX_HOST_LABEL_SIZE) { - return false; - } - - // first char must be [A-Za-z0-9] - if (!isAlphanumeric(s.charAt(start))) { - return false; - } - - // remaining chars must be [A-Za-z0-9-] - for (int i = start + 1; i < end; i++) { - char c = s.charAt(i); - if (!isAlphanumeric(c) && c != '-') { - return false; - } - } - - return true; - } - - private static boolean isAlphanumeric(char c) { - return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - } - - private static boolean isLowerCaseAlphanumeric(char c) { - return (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); - } - - // AWS related functions - - public static RulePartition awsPartition(String regionName) { - PartitionData data = PARTITION_DATA.value(); - Partition matchedPartition; - - // Known region - matchedPartition = data.regionMap.get(regionName); - if (matchedPartition == null) { - // try matching on region name pattern - for (Partition p : data.partitions) { - if (p.regionMatches(regionName)) { - matchedPartition = p; - break; - } - } - } - - // Couldn't find the region by name or pattern matching. Fallback to 'aws' partition. - if (matchedPartition == null) { - matchedPartition = AWS_PARTITION.value(); - } - - return RulePartition.from(matchedPartition.id(), matchedPartition.outputs()); - } - - public static RuleArn awsParseArn(String value) { - return RuleArn.parse(value); - } - - public static boolean stringEquals(String left, String right) { - if (left == null || right == null) { - return false; - } - return left.equals(right); - } - - public static T listAccess(List values, int index) { - if (values == null) { - return null; - } - if (index >= values.size()) { - return null; - } - return values.get(index); - } - - public static boolean awsIsVirtualHostableS3Bucket(String hostLabel, boolean allowDots) { - // Bucket names must be between 3 (min) and 63 (max) characters long. - int bucketLength = hostLabel == null ? 0 : hostLabel.length(); - if (bucketLength < MIN_BUCKET_SIZE || bucketLength > MAX_HOST_LABEL_SIZE) { - return false; - } - - // Bucket names must begin and end with a letter or number. - if (!isLowerCaseAlphanumeric(hostLabel.charAt(0)) || !isLowerCaseAlphanumeric(hostLabel.charAt(bucketLength - 1))) { - return false; - } - - // Bucket names can consist only of lowercase letters, numbers, periods (.), and hyphens (-). - if (!allowDots) { - for (int i = 1; i < bucketLength - 1; i++) { // already validated 0 and N - 1. - if (!isValidBucketSegmentChar(hostLabel.charAt(i))) { - return false; - } - } - return true; - } - - // Check for consecutive dots or hyphens - char last = hostLabel.charAt(0); - for (int i = 1; i < bucketLength; i++) { - char c = hostLabel.charAt(i); - // Don't allow "bucket-.foo" or "bucket.-foo" - if (c == '.') { - if (last == '.' || last == '-') { - return false; - } - } else if (c == '-') { - if (last == '.') { - return false; - } - } else if (!isLowerCaseAlphanumeric(c)) { - return false; - } - last = c; - } - - // Bucket names must not be formatted as an IP address (for example, 192.168.5.4). - return !isIpAddr(hostLabel); - } - - private static boolean isValidBucketSegmentChar(char c) { - return isLowerCaseAlphanumeric(c) || c == '-'; - } - - private static boolean isIpAddr(String host) { - if (host == null || host.length() < 2) { - return false; - } - - // Simple check for IPv6 (enclosed in square brackets) - if (host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']') { - return true; - } - - int from = 0; - int segments = 0; - boolean done = false; - while (!done) { - int index = host.indexOf('.', from); - if (index == -1) { - if (segments != 3) { - // E.g., 123.com - return false; - } - index = host.length(); - done = true; - } else if (segments == 3) { - // E.g., 1.2.3.4.5 - return false; - } - int length = index - from; - if (length == 1) { - char ch0 = host.charAt(from); - if (ch0 < '0' || ch0 > '9') { - return false; - } - } else if (length == 2) { - char ch0 = host.charAt(from); - char ch1 = host.charAt(from + 1); - if ((ch0 <= '0' || ch0 > '9') || (ch1 < '0' || ch1 > '9')) { - return false; - } - } else if (length == 3) { - char ch0 = host.charAt(from); - char ch1 = host.charAt(from + 1); - char ch2 = host.charAt(from + 2); - if ((ch0 <= '0' || ch0 > '9') || (ch1 < '0' || ch1 > '9') || (ch2 < '0' || ch2 > '9')) { - return false; - } - // This is a heuristic; We are intentionally not checking for the range 000-255. - } else { - return false; - } - from = index + 1; - segments += 1; - } - return true; - } - - private static PartitionData loadPartitionData() { - PartitionDataProvider provider = new DefaultPartitionDataProvider(); - - // TODO: support custom partitions.json - Partitions partitions = provider.loadPartitions(); - PartitionData partitionData = new PartitionData(); - - partitions.partitions().forEach(part -> { - partitionData.partitions.add(part); - part.regions().forEach((name, override) -> { - partitionData.regionMap.put(name, part); - }); - }); - - return partitionData; - } - - private static Partition findAwsPartition() { - return PARTITION_DATA.value().partitions.stream().filter(p -> p.id().equalsIgnoreCase("aws")).findFirst().orElse(null); - } - - private static class PartitionData { - private final List partitions = new ArrayList<>(); - private final Map regionMap = new HashMap<>(); - } - - private static final class LazyValue { - private final Supplier initializer; - private T value; - private boolean initialized; - - private LazyValue(Builder builder) { - this.initializer = builder.initializer; - } - - public T value() { - if (!initialized) { - value = initializer.get(); - initialized = true; - } - return value; - } - - public static Builder builder() { - return new Builder<>(); - } - - public static class Builder { - private Supplier initializer; - - public Builder initializer(Supplier initializer) { - this.initializer = initializer; - return this; - } - - public LazyValue build() { - return new LazyValue<>(this); - } - } - } -} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java index abba97770279..2524dd490d7e 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/IntermediateModelBuilderTest.java @@ -16,6 +16,8 @@ package software.amazon.awssdk.codegen; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -26,6 +28,9 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; +import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.ServiceModel; import software.amazon.awssdk.codegen.utils.ModelLoaderUtils; @@ -104,4 +109,136 @@ public void assertAwsQueryCompatibleTrait_notNull() { assertNotNull(testModel.getMetadata().getAwsQueryCompatible()); } + /** + * A service ships either endpoint model, and both declare the same parameters, so codegen must read them from + * whichever one is present. Reading them off the rule set specifically left a BDD-only service with the two + * parameters of the default rule set, which surfaces as a compile error in the generated provider. + */ + @Test + public void endpointParameters_bddModelOnly_comeFromTheBddModel() { + IntermediateModel model = modelWithEndpoints(null, "query/endpoint-bdd-s3.json"); + + assertThat(model.getEndpointParameters()).hasSize(17) + .containsKeys("Bucket", "ForcePathStyle", "UseFIPS", "UseDualStack"); + } + + @Test + public void endpointParameters_ruleSetOnly_comeFromTheRuleSet() { + IntermediateModel model = modelWithEndpoints("query/endpoint-rule-set.json", null); + + assertThat(model.getEndpointParameters()).hasSize(14) + .containsKeys("region", "endpointId", "AccountIdEndpointMode"); + } + + /** + * The BDD model is preferred when a service ships both, so deleting a service's rule set should not change the parameters + * codegen sees. The two fixtures declare different parameters only so that the winner is observable. + */ + @Test + public void endpointParameters_bothModels_comeFromTheBddModel() { + IntermediateModel model = modelWithEndpoints("query/endpoint-rule-set-default-regional.json", + "query/endpoint-bdd-s3.json"); + + assertThat(model.getEndpointParameters()).hasSize(17).containsKey("Bucket"); + assertThat(model.getEndpointParameters()).doesNotContainKey("unusedParam"); + } + + /** + * Only codegen test fixtures ship neither model; every service ships at least one. + */ + @Test + public void endpointParameters_neitherModel_fallBackToTheDefaultRuleSet() { + IntermediateModel model = modelWithEndpoints(null, null); + + assertThat(model.getEndpointParameters()).containsOnlyKeys("Endpoint", "Region"); + } + + /** + * Parameters are assembled once, by this builder, so that the customization merge is the only writer. + */ + @Test + public void endpointParameters_areUnmodifiable() { + IntermediateModel model = modelWithEndpoints("query/endpoint-rule-set.json", null); + + assertThatThrownBy(() -> model.getEndpointParameters().put("Extra", new ParameterModel())) + .isInstanceOf(UnsupportedOperationException.class); + } + + @Test + public void endpointParameters_includeParametersDeclaredByTheCustomizationConfig() { + IntermediateModel model = new IntermediateModelBuilder( + C2jModels.builder() + .serviceModel(serviceModel("query/service-2.json")) + .customizationConfig(customizationConfig("query/customization.config")) + .endpointRuleSetModel(endpointRuleSetModel("query/endpoint-rule-set.json")) + .build()) + .build(); + + assertThat(model.getEndpointParameters()).containsKeys("CustomEndpointArray", "ArnList"); + } + + /** + * The customization merge also has to reach a BDD-only service, which is the case that used to NPE: it read the + * rule set field directly rather than the parameters codegen actually uses. + */ + @Test + public void endpointParameters_customizationParametersReachABddOnlyService() { + IntermediateModel model = new IntermediateModelBuilder( + C2jModels.builder() + .serviceModel(serviceModel("query/service-2.json")) + .customizationConfig(customizationConfig("query/customization.config")) + .endpointBddModel(endpointBddModel("query/endpoint-bdd-s3.json")) + .build()) + .build(); + + assertThat(model.getEndpointParameters()).hasSize(19) + .containsKeys("Bucket", "CustomEndpointArray", "ArnList"); + } + + @Test + public void endpointParameters_customizationParameterAlreadyDeclared_throws() { + assertThatIllegalStateException() + .isThrownBy(() -> new IntermediateModelBuilder( + C2jModels.builder() + .serviceModel(serviceModel("query/service-2.json")) + .customizationConfig( + customizationConfig("query/customization-with-duplicate-endpointparameter.config")) + .endpointRuleSetModel(endpointRuleSetModel("query/endpoint-rule-set.json")) + .build()) + .build()) + .withMessageContaining("Duplicate parameters found in customizationConfig"); + } + + private static IntermediateModel modelWithEndpoints(String ruleSetResource, String bddResource) { + C2jModels.Builder models = C2jModels.builder() + .serviceModel(serviceModel("query/service-2.json")) + .customizationConfig(CustomizationConfig.create()); + if (ruleSetResource != null) { + models.endpointRuleSetModel(endpointRuleSetModel(ruleSetResource)); + } + if (bddResource != null) { + models.endpointBddModel(endpointBddModel(bddResource)); + } + return new IntermediateModelBuilder(models.build()).build(); + } + + private static ServiceModel serviceModel(String resource) { + return ModelLoaderUtils.loadModel(ServiceModel.class, resource(resource)); + } + + private static CustomizationConfig customizationConfig(String resource) { + return ModelLoaderUtils.loadModel(CustomizationConfig.class, resource(resource)); + } + + private static EndpointRuleSetModel endpointRuleSetModel(String resource) { + return ModelLoaderUtils.loadModel(EndpointRuleSetModel.class, resource(resource)); + } + + private static EndpointBddModel endpointBddModel(String resource) { + return ModelLoaderUtils.loadModel(EndpointBddModel.class, resource(resource)); + } + + private static File resource(String resource) { + return new File(IntermediateModelBuilderTest.class.getResource("poet/client/c2j/" + resource).getFile()); + } } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessorTest.java new file mode 100644 index 000000000000..eb42cc3ca5e8 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/customization/processors/DefaultReadWriteTimeoutExemptionProcessorTest.java @@ -0,0 +1,147 @@ +/* + * 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.codegen.customization.processors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.Metadata; +import software.amazon.awssdk.protocols.jsoncore.JsonNode; +import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser; + +class DefaultReadWriteTimeoutExemptionProcessorTest { + + private static final String EXEMPTIONS_RESOURCE = "software/amazon/awssdk/codegen/default-read-write-timeout-exemptions.json"; + private static final Pattern SERVICE_ID = Pattern.compile("\"serviceId\"\\s*:\\s*\"([^\"]+)\""); + + @ParameterizedTest + @MethodSource("exemptionEntries") + void postprocess_serviceInArtifact_bakesExpectedTier(String serviceId, long expectedMillis) { + IntermediateModel model = modelWithServiceId(serviceId); + + new DefaultReadWriteTimeoutExemptionProcessor().postprocess(model); + + assertThat(model.getMetadata().getDefaultReadWriteTimeoutMillis()).isEqualTo(expectedMillis); + } + + @ParameterizedTest + @ValueSource(strings = {"sqs", "s3", "lambda", "kinesis", "CODEARTIFACT", "MGN", "Sqs"}) + void postprocess_misCasedServiceId_bakesNothing(String misCasedServiceId) { + IntermediateModel model = modelWithServiceId(misCasedServiceId); + + new DefaultReadWriteTimeoutExemptionProcessor().postprocess(model); + + assertThat(model.getMetadata().getDefaultReadWriteTimeoutMillis()).isNull(); + } + + @Test + void postprocess_serviceNotInArtifact_bakesNothing() { + IntermediateModel model = modelWithServiceId("Not A Real Service"); + + new DefaultReadWriteTimeoutExemptionProcessor().postprocess(model); + + assertThat(model.getMetadata().getDefaultReadWriteTimeoutMillis()).isNull(); + } + + @Test + void validateArtifactKeys_everyKeyMatchesARealServiceId() throws IOException { + new DefaultReadWriteTimeoutExemptionProcessor().validateArtifactKeys(realServiceIds()); + } + + @Test + void validateArtifactKeys_keyMatchingNoServiceId_throws() { + DefaultReadWriteTimeoutExemptionProcessor processor = + new DefaultReadWriteTimeoutExemptionProcessor(Collections.singletonMap("sqs", 900000L)); + + assertThatThrownBy(() -> processor.validateArtifactKeys(Collections.singleton("SQS"))) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("sqs"); + } + + private static IntermediateModel modelWithServiceId(String serviceId) { + IntermediateModel model = new IntermediateModel(); + model.setMetadata(new Metadata().withServiceId(serviceId)); + return model; + } + + private static Stream exemptionEntries() throws IOException { + try (InputStream stream = DefaultReadWriteTimeoutExemptionProcessorTest.class.getClassLoader() + .getResourceAsStream(EXEMPTIONS_RESOURCE)) { + Map artifact = JsonNodeParser.create().parse(stream).asObject(); + return artifact.entrySet().stream() + .map(e -> Arguments.of(e.getKey(), Long.parseLong(e.getValue().asNumber()))); + } + } + + private static Set realServiceIds() throws IOException { + Path servicesDir = locateServicesDir(); + Set serviceIds = new HashSet<>(); + try (DirectoryStream modules = Files.newDirectoryStream(servicesDir)) { + for (Path module : modules) { + Path model = module.resolve("src/main/resources/codegen-resources/service-2.json"); + if (Files.isRegularFile(model)) { + extractServiceId(model).ifPresent(serviceIds::add); + } + } + } + assertThat(serviceIds).as("expected to harvest serviceIds from the service models").isNotEmpty(); + return serviceIds; + } + + private static Optional extractServiceId(Path serviceModel) throws IOException { + try (BufferedReader reader = Files.newBufferedReader(serviceModel, StandardCharsets.UTF_8)) { + String line; + while ((line = reader.readLine()) != null) { + Matcher matcher = SERVICE_ID.matcher(line); + if (matcher.find()) { + return Optional.of(matcher.group(1)); + } + } + } + return Optional.empty(); + } + + private static Path locateServicesDir() { + for (Path candidate : new Path[] {Paths.get("..", "services"), Paths.get("services"), Paths.get("..", "..", "services")}) { + if (Files.isDirectory(candidate)) { + return candidate; + } + } + throw new IllegalStateException("Could not locate the services/ directory from " + Paths.get("").toAbsolutePath()); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProviderTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProviderTest.java new file mode 100644 index 000000000000..29af62b0585c --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/GeneratorPathProviderTest.java @@ -0,0 +1,41 @@ +/* + * 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.codegen.emitters; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.Metadata; + +public class GeneratorPathProviderTest { + + @Test + public void warmUpProviderDirectory_isUnderSourceDirInWarmupInternalPackage() { + Metadata metadata = new Metadata(); + metadata.setRootPackageName("software.amazon.awssdk.services"); + metadata.setClientPackageName("query"); + + IntermediateModel model = new IntermediateModel(); + model.setMetadata(metadata); + + GeneratorPathProvider provider = + new GeneratorPathProvider(model, "/src", "/test", "/resources"); + + assertThat(provider.getWarmUpProviderDirectory()) + .isEqualTo("/src/software/amazon/awssdk/services/query/internal/warmup"); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTaskTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTaskTest.java new file mode 100644 index 000000000000..68333155ece5 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/emitters/WarmUpProviderRegistrationTaskTest.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.codegen.emitters; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.xmlServiceModels; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import software.amazon.awssdk.codegen.poet.warmup.WarmUpProviderSpec; + +public class WarmUpProviderRegistrationTaskTest { + + private static final String SPI_PATH = + "META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider"; + + private static final String QUERY_PROVIDER = new WarmUpProviderSpec(queryServiceModels()).className().toString(); + private static final String XML_PROVIDER = new WarmUpProviderSpec(xmlServiceModels()).className().toString(); + + @TempDir + Path resourcesDir; + + @Test + public void writesProviderClassName() throws IOException { + new WarmUpProviderRegistrationTask(resourcesDir.toString(), QUERY_PROVIDER).compute(); + + List lines = Files.readAllLines(resourcesDir.resolve(SPI_PATH), StandardCharsets.UTF_8); + assertThat(lines).contains(QUERY_PROVIDER); + } + + @Test + public void appendsSecondProviderWithoutClobbering() throws IOException { + new WarmUpProviderRegistrationTask(resourcesDir.toString(), QUERY_PROVIDER).compute(); + new WarmUpProviderRegistrationTask(resourcesDir.toString(), XML_PROVIDER).compute(); + + List lines = Files.readAllLines(resourcesDir.resolve(SPI_PATH), StandardCharsets.UTF_8); + assertThat(lines).contains(QUERY_PROVIDER).contains(XML_PROVIDER); + } + + @Test + public void doesNotDuplicateOnSecondIdenticalRun() throws IOException { + new WarmUpProviderRegistrationTask(resourcesDir.toString(), QUERY_PROVIDER).compute(); + new WarmUpProviderRegistrationTask(resourcesDir.toString(), QUERY_PROVIDER).compute(); + + List lines = Files.readAllLines(resourcesDir.resolve(SPI_PATH), StandardCharsets.UTF_8); + long count = lines.stream().filter(l -> l.equals(QUERY_PROVIDER)).count(); + assertThat(count).isEqualTo(1); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MetadataTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MetadataTest.java new file mode 100644 index 000000000000..c95819919ec7 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/model/intermediate/MetadataTest.java @@ -0,0 +1,33 @@ +/* + * 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.codegen.model.intermediate; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class MetadataTest { + + @Test + public void fullWarmUpInternalPackageName_appendsInternalWarmUpToClientPackage() { + Metadata metadata = new Metadata(); + metadata.setRootPackageName("software.amazon.awssdk.services"); + metadata.setClientPackageName("query"); + + assertThat(metadata.getFullWarmUpInternalPackageName()) + .isEqualTo("software.amazon.awssdk.services.query.internal.warmup"); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java index acd08400564a..167f8942f5f3 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java @@ -22,6 +22,7 @@ import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.rules.endpoints.EndpointTestSuiteModel; +import software.amazon.awssdk.codegen.model.service.EndpointBddModel; import software.amazon.awssdk.codegen.model.service.EndpointRuleSetModel; import software.amazon.awssdk.codegen.model.service.Paginators; import software.amazon.awssdk.codegen.model.service.ServiceModel; @@ -248,6 +249,32 @@ public static IntermediateModel queryServiceModelsWithUriCache() { return new IntermediateModelBuilder(models).build(); } + /** + * Returns a model where the root endpoint rule delegates to child rules without directly using the region parameter. + * This exercises the scenario where ComputeScopeTree does not include region in the root method's signature. + */ + public static IntermediateModel queryServiceModelsWithDelegatingRootRule() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/service-2.json").getFile()); + File customizationModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/customization.config").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/waiters-2.json").getFile()); + File endpointRuleSetModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/endpoint-rule-set.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query-delegating-root/endpoint-tests.json").getFile()); + + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .customizationConfig(getCustomizationConfig(customizationModel)) + .waitersModel(getWaiters(waitersModel)) + .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel)) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .build(); + + return new IntermediateModelBuilder(models).build(); + } + public static IntermediateModel queryServiceModelsEndpointAuthParamsWithAllowList() { File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); File customizationModel = @@ -606,10 +633,115 @@ public static IntermediateModel batchManagerModels() { return new IntermediateModelBuilder(models).build(); } + public static IntermediateModel presignedUrlExtensionModels() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/presignedurl/service-2.json").getFile()); + File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/presignedurl/customization.config").getFile()); + + C2jModels models = C2jModels.builder() + .serviceModel(getServiceModel(serviceModel)) + .customizationConfig(getCustomizationConfig(customizationModel)) + .build(); + + return new IntermediateModelBuilder(models).build(); + } + + /** + * Uses the S3 BDD, which contains an auth scheme whose name is resolved at runtime. That requires the + * {@code useS3ExpressSessionAuth} customization to be enabled. + */ + public static IntermediateModel queryServiceModelsWithBddEndpoints() { + return queryServiceModelsWithBddEndpoints(true); + } + + public static IntermediateModel queryServiceModelsWithBddEndpoints(boolean useS3ExpressSessionAuth) { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile()); + File endpointBddModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-bdd-s3.json").getFile()); + CustomizationConfig customizationConfig = CustomizationConfig.create(); + customizationConfig.setUseS3ExpressSessionAuth(useS3ExpressSessionAuth); + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .waitersModel(getWaiters(waitersModel)) + .customizationConfig(customizationConfig) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .endpointBddModel(getEndpointBdd(endpointBddModel)) + .build(); + return new IntermediateModelBuilder(models).build(); + } + + /** + * Uses the simple default-regional BDD (Connect-like, no dynamic auth schemes). + * Suitable for fixture-based golden file tests. + */ + public static IntermediateModel queryServiceModelsWithSimpleBddEndpoints() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile()); + File endpointBddModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-bdd-default-regional.json").getFile()); + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .waitersModel(getWaiters(waitersModel)) + .customizationConfig(CustomizationConfig.create()) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .endpointBddModel(getEndpointBdd(endpointBddModel)) + .build(); + return new IntermediateModelBuilder(models).build(); + } + + /** + * Uses a hand-crafted BDD with a complement edge (negative node reference) to verify that + * nodeN methods are generated correctly with swapped branches. + */ + public static IntermediateModel queryServiceModelsWithComplementBddEndpoints() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile()); + File endpointBddModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-bdd-complement.json").getFile()); + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .waitersModel(getWaiters(waitersModel)) + .customizationConfig(CustomizationConfig.create()) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .endpointBddModel(getEndpointBdd(endpointBddModel)) + .build(); + return new IntermediateModelBuilder(models).build(); + } + private static ServiceModel getServiceModel(File file) { return ModelLoaderUtils.loadModel(ServiceModel.class, file); } + public static IntermediateModel queryServiceModelsNoRegionEndpointRules() { + File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile()); + File customizationModel = new File(ClientTestModels.class.getResource("client/c2j/query/customization.config").getFile()); + File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile()); + File endpointRuleSetModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set-no-region.json").getFile()); + File endpointTestsModel = + new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests-no-region.json").getFile()); + + C2jModels models = C2jModels + .builder() + .serviceModel(getServiceModel(serviceModel)) + .customizationConfig(getCustomizationConfig(customizationModel)) + .waitersModel(getWaiters(waitersModel)) + .endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel)) + .endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel)) + .build(); + + return new IntermediateModelBuilder(models).build(); + } + private static CustomizationConfig getCustomizationConfig(File file) { return ModelLoaderUtils.loadModel(CustomizationConfig.class, file); } @@ -629,4 +761,8 @@ private static EndpointTestSuiteModel getEndpointTestSuite(File file) { private static Paginators getPaginatorsModel(File file) { return ModelLoaderUtils.loadModel(Paginators.class, file); } + + private static EndpointBddModel getEndpointBdd(File file) { + return ModelLoaderUtils.loadModel(EndpointBddModel.class, file); + } } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassReadWriteTimeoutTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassReadWriteTimeoutTest.java new file mode 100644 index 000000000000..9dabf03da41e --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassReadWriteTimeoutTest.java @@ -0,0 +1,67 @@ +/* + * 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.codegen.poet.builder; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.codegen.poet.PoetUtils.buildJavaFile; + +import java.io.IOException; +import java.io.UncheckedIOException; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.poet.ClientTestModels; + +/** + * Emission cases for the codegen-baked read/write timeout tier. + */ +class BaseClientBuilderClassReadWriteTimeoutTest { + + @Test + void serviceHttpConfig_fullyExemptTier_bakesDurationZero() { + IntermediateModel model = ClientTestModels.queryServiceModels(); + model.getMetadata().setDefaultReadWriteTimeoutMillis(-1L); + + assertThat(generate(model)) + .contains(".put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, Duration.ZERO)"); + } + + @Test + void serviceHttpConfig_partialTier_bakesDurationMillis() { + IntermediateModel model = ClientTestModels.queryServiceModels(); + model.getMetadata().setDefaultReadWriteTimeoutMillis(900000L); + + assertThat(generate(model)) + .contains(".put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, Duration.ofMillis(900000L))"); + } + + @Test + void serviceHttpConfig_noTierBaked_omitsFallbackTimeout() { + IntermediateModel model = ClientTestModels.queryServiceModels(); + model.getMetadata().setDefaultReadWriteTimeoutMillis(null); + + assertThat(generate(model)).doesNotContain("SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT"); + } + + private static String generate(IntermediateModel model) { + StringBuilder output = new StringBuilder(); + try { + buildJavaFile(new BaseClientBuilderClass(model)).writeTo(output); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + return output.toString(); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java index 52b5677b2d5f..a48a74c9163c 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClassTest.java @@ -23,6 +23,7 @@ import static software.amazon.awssdk.codegen.poet.ClientTestModels.opsWithSigv4a; import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModelsEndpointAuthParamsWithAllowList; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModelsNoRegionEndpointRules; import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.serviceWithH2; import static software.amazon.awssdk.codegen.poet.ClientTestModels.serviceWithH2UsePriorKnowledgeForH2; @@ -100,6 +101,21 @@ void baseClientBuilderClassWithH2_usePriorKnowledgeForH2() { validateBaseClientBuilderClassGeneration(serviceWithH2UsePriorKnowledgeForH2(), "test-h2-usePriorKnowledgeForH2-service-client-builder-class.java"); } + @Test + void baseClientBuilderClass_noRegionEndpointRules() { + validateBaseClientBuilderClassGeneration(queryServiceModelsNoRegionEndpointRules(), + "test-no-region-client-builder-class.java"); + } + + @Test + void baseClientBuilderClassWithReadWriteTimeout() { + IntermediateModel model = serviceWithH2(); + // Simulate the exemption processor baking a 15-minute partial tier; verify it composes with the existing H2 + // serviceHttpConfig content. + model.getMetadata().setDefaultReadWriteTimeoutMillis(900000L); + validateBaseClientBuilderClassGeneration(model, "test-read-write-timeout-service-client-builder-class.java"); + } + private void validateBaseClientBuilderClassGeneration(IntermediateModel model, String expectedClassName) { validateGeneration(BaseClientBuilderClass::new, model, expectedClassName); } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java index 6e2082fc4175..ab3bfeb68c92 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClassTest.java @@ -24,6 +24,7 @@ import static software.amazon.awssdk.codegen.poet.ClientTestModels.customPackageModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.endpointDiscoveryModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.opsWithSigv4a; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.presignedUrlExtensionModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.serviceWithCustomContextParamsModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.queryServiceModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels; @@ -102,6 +103,12 @@ public void asyncClientBatchManager() { ClassSpec aSyncClientBatchManager = createAsyncClientClass(batchManagerModels()); assertThat(aSyncClientBatchManager, generatesTo("test-batchmanager-async.java")); } + + @Test + public void asyncClientPresignedUrlExtension() { + ClassSpec asyncClientPresignedUrlExtension = createAsyncClientClass(presignedUrlExtensionModels()); + assertThat(asyncClientPresignedUrlExtension, generatesTo("test-presignedurl-async.java")); + } @Test public void asyncClientWithStreamingUnsignedPayload() { diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java index fda4c6f2b459..aae45702e837 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterfaceTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static software.amazon.awssdk.codegen.poet.ClientTestModels.batchManagerModels; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.presignedUrlExtensionModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels; import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; @@ -35,4 +36,10 @@ public void asyncClientInterfaceWithBatchManager() { ClassSpec asyncClientInterface = new AsyncClientInterface(batchManagerModels()); assertThat(asyncClientInterface, generatesTo("test-json-async-client-interface-batchmanager.java")); } + + @Test + public void asyncClientInterfaceWithPresignedUrlExtension() { + ClassSpec asyncClientInterface = new AsyncClientInterface(presignedUrlExtensionModels()); + assertThat(asyncClientInterface, generatesTo("test-json-async-client-interface-presignedurl.java")); + } } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AuthSchemeCacheKeyTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AuthSchemeCacheKeyTest.java new file mode 100644 index 000000000000..eec629b11e58 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/AuthSchemeCacheKeyTest.java @@ -0,0 +1,95 @@ +/* + * 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.codegen.poet.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.customPackageModels; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.opsWithSigv4a; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels; + +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.junit.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.poet.auth.scheme.AuthSchemeSpecUtils; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; + +/** + * Verifies that every AwsExecutionAttribute used in auth scheme params building is also present in the cache key. + * If a new attribute is added to the params without updating the cache key, this test will fail. + */ +public class AuthSchemeCacheKeyTest { + + private static final Pattern AWS_EXEC_ATTR_PATTERN = + Pattern.compile("AwsExecutionAttribute\\.(\\w+)"); + + @Test + public void restJson_cacheKeyCoversAllParamAttributes() { + verifyConsistency(restJsonServiceModels()); + } + + @Test + public void sigv4a_cacheKeyCoversAllParamAttributes() { + verifyConsistency(opsWithSigv4a()); + } + + @Test + public void uniformAuth_cacheKeyCoversAllParamAttributes() { + verifyConsistency(customPackageModels()); + } + + private void verifyConsistency(IntermediateModel model) { + AuthSchemeSpecUtils authSchemeSpecUtils = new AuthSchemeSpecUtils(model); + EndpointRulesSpecUtils endpointRulesSpecUtils = new EndpointRulesSpecUtils(model); + + String source = ClientClassUtils.resolveAuthSchemeOptionsMethod(authSchemeSpecUtils, endpointRulesSpecUtils) + .toString(); + + int resolveCallIndex = source.indexOf(".resolveAuthScheme("); + assertThat(resolveCallIndex).as("resolveAuthScheme call should exist in generated method").isGreaterThan(0); + + int cacheKeyStart = source.indexOf("cacheKey ="); + if (cacheKeyStart < 0) { + // No cache — endpoint-based service, nothing to verify + return; + } + int cacheKeyEnd = source.indexOf(";", cacheKeyStart); + + int paramsStart = source.indexOf("paramsBuilder"); + String paramsSection = source.substring(paramsStart, resolveCallIndex); + + Set paramsAttributes = extractAttributes(paramsSection); + assertThat(paramsAttributes).as("Expected auth params to reference AwsExecutionAttributes").isNotEmpty(); + String cacheKeySection = source.substring(cacheKeyStart, cacheKeyEnd); + Set cacheKeyAttributes = extractAttributes(cacheKeySection); + + assertThat(cacheKeyAttributes) + .as("Cache key must include all AwsExecutionAttributes used in params building. " + + "If you added a new attribute to params, add it to addAuthSchemeCacheLookup() too.") + .containsAll(paramsAttributes); + } + + private Set extractAttributes(String section) { + Set attributes = new HashSet<>(); + Matcher matcher = AWS_EXEC_ATTR_PATTERN.matcher(section); + while (matcher.find()) { + attributes.add(matcher.group(1)); + } + return attributes; + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientConstantPoolBudgetTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientConstantPoolBudgetTest.java new file mode 100644 index 000000000000..55bed64ca380 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientConstantPoolBudgetTest.java @@ -0,0 +1,368 @@ +/* + * 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.codegen.poet.client; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.stream.Stream; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.codegen.C2jModels; +import software.amazon.awssdk.codegen.CodeGenerator; +import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; +import software.amazon.awssdk.codegen.model.service.ErrorMap; +import software.amazon.awssdk.codegen.model.service.ErrorTrait; +import software.amazon.awssdk.codegen.model.service.Http; +import software.amazon.awssdk.codegen.model.service.Input; +import software.amazon.awssdk.codegen.model.service.Member; +import software.amazon.awssdk.codegen.model.service.Operation; +import software.amazon.awssdk.codegen.model.service.Output; +import software.amazon.awssdk.codegen.model.service.ServiceMetadata; +import software.amazon.awssdk.codegen.model.service.ServiceModel; +import software.amazon.awssdk.codegen.model.service.Shape; + +/** + * Bounds the marginal constant pool cost of one additional operation in the generated clients and client interfaces. + * + *

A class file holds at most 65,535 constant pool entries, and a generated client grows with the operation count of + * its service model. That growth is affine, not proportional: {@code entries = fixed + marginal * ops}, measured here as + * {@code 742 + 25 * ops} for the async client. The fixed part is the constructor, builder plumbing, endpoint and + * auth-scheme resolution, and shared helpers, all of which a client pays for even with no operations at all. + * + *

This test generates one synthetic model at two operation counts and subtracts the totals. The fixed cost is + * present in both and cancels, leaving the marginal cost: the entries that one additional operation adds, which + * is the quantity a per-operation regression changes. Something added once per client moves both totals equally and the + * budget holds, correctly; something added once per operation moves only the larger model and the budget breaks. + * + */ +public class ClientConstantPoolBudgetTest { + private static final int CONSTANT_POOL_LIMIT = 65_535; + private static final int FEWER_OPERATIONS = 50; + private static final int MORE_OPERATIONS = 150; + + private static final String SERVICE_NAME = "PoolGuard"; + private static final String CLIENT_PACKAGE = "software.amazon.awssdk.services.poolguard"; + + private static Map growthByClass; + private static Path workDir; + + @BeforeAll + static void measurePoolGrowth() throws IOException { + workDir = Files.createTempDirectory("constant-pool-budget"); + Map fewer = compileAndCountPoolEntries(FEWER_OPERATIONS); + Map more = compileAndCountPoolEntries(MORE_OPERATIONS); + + Map growth = new LinkedHashMap<>(); + fewer.forEach((className, entries) -> growth.put(className, new PoolGrowth(className, entries, more.get(className)))); + growthByClass = growth; + } + + @AfterAll + static void deleteWorkDir() throws IOException { + deleteRecursively(workDir); + } + + /** + * Budgets are the cost measured when this test was written plus a margin. Every margin is under 6 entries per + * operation, the cost of one reintroduced per-operation lambda, so that such a regression still breaches the budget. + * + *

Measured on this synthetic model: 25.0 entries/operation for the async client (budget 28.0, +12%), 24.0 for the + * sync client (27.0, +12.5%), and 15.0 for each interface (17.0, +13%). + */ + private static Stream budgets() { + return Stream.of( + Arguments.of("DefaultPoolGuardAsyncClient", 28.0), + Arguments.of("DefaultPoolGuardClient", 27.0), + Arguments.of("PoolGuardAsyncClient", 17.0), + Arguments.of("PoolGuardClient", 17.0) + ); + } + + @ParameterizedTest + @MethodSource("budgets") + void constantPoolEntries_perAdditionalOperation_areWithinBudget(String className, double budget) { + PoolGrowth growth = growthByClass.get(className); + assertThat(growth).as("no measurement for %s; measured: %s", className, growthByClass.keySet()).isNotNull(); + assertThat(growth.marginalCostPerOperation()) + .withFailMessage(growth.regressionMessage(budget)) + .isLessThanOrEqualTo(budget); + } + + private static Map compileAndCountPoolEntries(int operationCount) throws IOException { + Path root = workDir.resolve("ops-" + operationCount); + Path sources = root.resolve("sources"); + Path classes = root.resolve("classes"); + Files.createDirectories(classes); + + CodeGenerator.builder() + .models(syntheticModels(operationCount)) + .sourcesDirectory(sources.toString()) + .resourcesDirectory(root.resolve("resources").toString()) + .testsDirectory(root.resolve("tests").toString()) + .build() + .execute(); + + compile(sources, classes); + + Path clientPackage = classes.resolve(CLIENT_PACKAGE.replace('.', '/')); + Map entriesByClass = new LinkedHashMap<>(); + for (String className : Arrays.asList("Default" + SERVICE_NAME + "AsyncClient", + "Default" + SERVICE_NAME + "Client", + SERVICE_NAME + "AsyncClient", + SERVICE_NAME + "Client")) { + entriesByClass.put(className, constantPoolEntries(clientPackage.resolve(className + ".class"))); + } + return entriesByClass; + } + + /** + * Reads {@code constant_pool_count}, the big-endian u2 at offset 8 of a class file. Index 0 is unused, so the entry + * count is one less than the stored count. + */ + private static int constantPoolEntries(Path classFile) throws IOException { + byte[] bytes = Files.readAllBytes(classFile); + return (((bytes[8] & 0xFF) << 8) | (bytes[9] & 0xFF)) - 1; + } + + private static void compile(Path sources, Path classes) throws IOException { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + assertThat(compiler).as("no system Java compiler; this test requires a JDK, not a JRE").isNotNull(); + + List sourceFiles = new ArrayList<>(); + Files.walkFileTree(sources, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (file.toString().endsWith(".java")) { + sourceFiles.add(file); + } + return FileVisitResult.CONTINUE; + } + }); + + DiagnosticCollector diagnostics = new DiagnosticCollector<>(); + try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null)) { + fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(classes.toFile())); + boolean succeeded = compiler.getTask(null, fileManager, diagnostics, + Arrays.asList("-nowarn", "-proc:none", "-classpath", testClasspath()), + null, + fileManager.getJavaFileObjectsFromFiles(toFiles(sourceFiles))) + .call(); + assertThat(succeeded).as("failed to compile the generated client: %s", errors(diagnostics)).isTrue(); + } + } + + /** + * The generated client compiles against the same dependencies this test runs with, so the test JVM's own classpath is + * the compilation classpath. + */ + private static String testClasspath() { + return System.getProperty("java.class.path"); + } + + private static List toFiles(List paths) { + List files = new ArrayList<>(); + paths.forEach(p -> files.add(p.toFile())); + return files; + } + + private static String errors(DiagnosticCollector diagnostics) { + StringBuilder message = new StringBuilder(); + diagnostics.getDiagnostics().stream() + .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) + .limit(10) + .forEach(d -> message.append('\n').append(d)); + return message.toString(); + } + + /** + * A service model that differs from the other operation count only in how many operations it declares, so that + * differencing the two pool totals leaves the per-operation cost. + */ + private static C2jModels syntheticModels(int operationCount) { + ServiceMetadata metadata = new ServiceMetadata(); + metadata.setApiVersion("2010-05-08"); + metadata.setEndpointPrefix("poolguard"); + metadata.setJsonVersion("1.1"); + metadata.setProtocol("json"); + metadata.setServiceAbbreviation(SERVICE_NAME); + metadata.setServiceFullName("Pool Guard Service"); + metadata.setServiceId(SERVICE_NAME); + metadata.setSignatureVersion("v4"); + metadata.setSigningName("poolguard"); + metadata.setTargetPrefix("PoolGuard"); + metadata.setUid("poolguard-2010-05-08"); + + Map operations = new LinkedHashMap<>(); + Map shapes = new LinkedHashMap<>(); + shapes.put("StringType", stringShape()); + shapes.put("InvalidInputException", exceptionShape()); + + for (int i = 0; i < operationCount; i++) { + String operationName = String.format(Locale.ROOT, "Operation%03d", i); + operations.put(operationName, operation(operationName)); + shapes.put(operationName + "Request", structureShape()); + shapes.put(operationName + "Response", structureShape()); + } + + ServiceModel serviceModel = new ServiceModel(); + serviceModel.setMetadata(metadata); + serviceModel.setDocumentation("A synthetic service used to measure constant pool growth."); + serviceModel.setOperations(operations); + serviceModel.setShapes(shapes); + + return C2jModels.builder() + .serviceModel(serviceModel) + .customizationConfig(CustomizationConfig.create()) + .build(); + } + + private static Operation operation(String operationName) { + Http http = new Http(); + http.setMethod("POST"); + http.setRequestUri("/"); + + Input input = new Input(); + input.setShape(operationName + "Request"); + + Output output = new Output(); + output.setShape(operationName + "Response"); + + ErrorMap error = new ErrorMap(); + error.setShape("InvalidInputException"); + + Operation operation = new Operation(); + operation.setName(operationName); + operation.setHttp(http); + operation.setInput(input); + operation.setOutput(output); + operation.setErrors(Collections.singletonList(error)); + operation.setDocumentation("Performs " + operationName + "."); + return operation; + } + + private static Shape structureShape() { + Member member = new Member(); + member.setShape("StringType"); + member.setDocumentation("A string member."); + + Shape shape = new Shape(); + shape.setType("structure"); + shape.setMembers(Collections.singletonMap("StringMember", member)); + return shape; + } + + private static Shape stringShape() { + Shape shape = new Shape(); + shape.setType("string"); + return shape; + } + + private static Shape exceptionShape() { + ErrorTrait errorTrait = new ErrorTrait(); + errorTrait.setHttpStatusCode(400); + + Shape shape = new Shape(); + shape.setType("structure"); + shape.setException(true); + shape.setError(errorTrait); + shape.setDocumentation("The request was rejected."); + return shape; + } + + private static void deleteRecursively(Path dir) throws IOException { + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path visited, IOException exc) throws IOException { + Files.delete(visited); + return FileVisitResult.CONTINUE; + } + }); + } + + private static final class PoolGrowth { + private final String className; + private final int fewerEntries; + private final int moreEntries; + + private PoolGrowth(String className, int fewerEntries, int moreEntries) { + this.className = className; + this.fewerEntries = fewerEntries; + this.moreEntries = moreEntries; + } + + private double marginalCostPerOperation() { + return (moreEntries - fewerEntries) / (double) (MORE_OPERATIONS - FEWER_OPERATIONS); + } + + private int fixedCost() { + return (int) Math.round(fewerEntries - marginalCostPerOperation() * FEWER_OPERATIONS); + } + + private long operationCeiling(double budget) { + return Math.round((CONSTANT_POOL_LIMIT - fixedCost()) / budget); + } + + private String regressionMessage(double budget) { + return String.format( + Locale.ROOT, + "Per-operation constant pool cost of %s regressed.%n%n" + + " measured %.1f entries/operation (%d entries at %d ops vs %d at %d ops)%n" + + " budget %.1f entries/operation%n" + + " fixed cost %d entries (operation-count independent)%n%n" + + "At %.1f entries/operation a client exceeds the JVM's %d-entry class constant pool limit at ~%d " + + "operations. The largest service model in the SDK (EC2) currently has over 750 operations.%n%n" + + "Something in the generated operation body is now emitted once per operation instead of once per " + + "client. The usual cause is an inline lambda or method reference; each one costs ~6 entries per " + + "operation. Hoist it into a shared private helper on the client, as " + + "ClientClassUtils.publishMetrics and publishMetricsWhenComplete do for metric publishing.%n%n" + + "If this growth is intended and justified, raise the budget deliberately and record the reason " + + "alongside it.", + className, marginalCostPerOperation(), fewerEntries, FEWER_OPERATIONS, moreEntries, MORE_OPERATIONS, + budget, fixedCost(), marginalCostPerOperation(), CONSTANT_POOL_LIMIT, + operationCeiling(marginalCostPerOperation())); + } + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientLambdaCallSiteCeilingTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientLambdaCallSiteCeilingTest.java new file mode 100644 index 000000000000..c457fd266243 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/ClientLambdaCallSiteCeilingTest.java @@ -0,0 +1,118 @@ +/* + * 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.codegen.poet.client; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Locale; +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.utils.IoUtils; +import software.amazon.awssdk.utils.Validate; + +/** + * Bounds the number of lambda call sites in each generated client reference fixture. + * + *

Per-operation lambdas are the dominant removable constant pool cost in generated clients. + * These fixtures span all five protocols and the special operation kinds such as event streams, streaming payloads. + * + */ +public class ClientLambdaCallSiteCeilingTest { + + /** + * Ceilings are the count when this test was written plus 2. Any construct added to every operation body raises a + * fixture's count by its operation count, which is at least 4 for every fixture listed here, so the headroom absorbs + * a couple of new shared per-client lambdas without absorbing a per-operation one. Single-operation fixtures are + * excluded for that reason: no headroom smaller than one operation exists. + */ + private static Stream ceilings() { + return Stream.of( + Arguments.of("test-json-async-client-class.java", 29), + Arguments.of("test-json-client-class.java", 6), + Arguments.of("test-aws-json-async-client-class.java", 25), + Arguments.of("test-cbor-async-client-class.java", 25), + Arguments.of("test-cbor-client-class.java", 6), + Arguments.of("test-rpcv2-async-client-class.java", 7), + Arguments.of("test-rpcv2-sync.java", 6), + Arguments.of("test-query-async-client-class.java", 14), + Arguments.of("test-query-client-class.java", 5), + Arguments.of("test-xml-async-client-class.java", 18), + Arguments.of("test-xml-client-class.java", 5), + Arguments.of("test-unsigned-payload-trait-async-client-class.java", 7), + Arguments.of("test-unsigned-payload-trait-sync-client-class.java", 6) + ); + } + + @ParameterizedTest + @MethodSource("ceilings") + void lambdaCallSites_inGeneratedClient_areWithinCeiling(String fixture, int ceiling) throws IOException { + String client = fixtureContent(fixture); + int callSites = lambdaCallSites(client); + + assertThat(callSites) + .withFailMessage(regressionMessage(fixture, callSites, ceiling, operationCount(client))) + .isLessThanOrEqualTo(ceiling); + } + + private static String regressionMessage(String fixture, int callSites, int ceiling, int operations) { + return String.format( + Locale.ROOT, + "%s contains %d lambda call sites, ceiling is %d.%n%n" + + "Per-operation lambdas are the dominant removable constant pool cost in generated clients: each one costs " + + "roughly 5 pool entries per operation. This fixture has %d operations, so a lambda added to every " + + "operation body raises this count by %d.%n%n" + + "If you added a construct to every operation body, hoist it into a shared helper.%n%n" + + "If the growth is intended and justified, raise the ceiling deliberately and record the reason " + + "alongside it.", + fixture, callSites, ceiling, operations, operations); + } + + /** + * Comment lines are excluded so that a lambda in generated javadoc is not counted as a call site. + */ + private static int lambdaCallSites(String client) { + return (int) Stream.of(client.split("\n")) + .map(String::trim) + .filter(line -> !line.startsWith("*") && !line.startsWith("//") && !line.startsWith("/*")) + .mapToLong(line -> countOccurrences(line, "->")) + .sum(); + } + + private static int operationCount(String client) { + return (int) countOccurrences(client, ".withOperationName("); + } + + private static long countOccurrences(String text, String token) { + long count = 0; + int from = text.indexOf(token); + while (from >= 0) { + count++; + from = text.indexOf(token, from + token.length()); + } + return count; + } + + private static String fixtureContent(String fixture) throws IOException { + try (InputStream resource = ClientLambdaCallSiteCeilingTest.class.getResourceAsStream(fixture)) { + Validate.notNull(resource, "Failed to load fixture " + fixture); + return IoUtils.toUtf8String(resource); + } + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java index a12ab3ac659c..a9af3d6a8b3b 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/client/DelegatingAsyncClientClassTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.codegen.poet.client; import static org.hamcrest.MatcherAssert.assertThat; +import static software.amazon.awssdk.codegen.poet.ClientTestModels.presignedUrlExtensionModels; import static software.amazon.awssdk.codegen.poet.ClientTestModels.restJsonServiceModels; import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; @@ -28,4 +29,11 @@ public void delegatingAsyncClientClass() { new DelegatingAsyncClientClass(restJsonServiceModels()); assertThat(asyncClientDecoratorAbstractClass, generatesTo("test-abstract-async-client-class.java")); } + + @Test + public void delegatingAsyncClientClassWithPresignedUrlExtension() { + DelegatingAsyncClientClass asyncClientDecoratorAbstractClass = + new DelegatingAsyncClientClass(presignedUrlExtensionModels()); + assertThat(asyncClientDecoratorAbstractClass, generatesTo("test-abstract-async-client-class-presignedurl.java")); + } } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderClassSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderClassSpecTest.java deleted file mode 100644 index e2f10b7fefab..000000000000 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderClassSpecTest.java +++ /dev/null @@ -1,37 +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.codegen.poet.rules; - -import static org.hamcrest.MatcherAssert.assertThat; -import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; - -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.codegen.poet.ClassSpec; -import software.amazon.awssdk.codegen.poet.ClientTestModels; - -public class EndpointProviderClassSpecTest { - @Test - public void endpointProviderClass() { - ClassSpec endpointProviderSpec = new EndpointProviderSpec(ClientTestModels.queryServiceModels()); - assertThat(endpointProviderSpec, generatesTo("endpoint-provider-class.java")); - } - - @Test - void knowPropertiesOverride() { - ClassSpec endpointProviderSpec = new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithOverrideKnowProperties()); - assertThat(endpointProviderSpec, generatesTo("endpoint-provider-know-prop-override-class.java")); - } -} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java index abf2ed3e3e22..f5be2cda506f 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java @@ -21,41 +21,49 @@ import org.junit.jupiter.api.Test; import software.amazon.awssdk.codegen.poet.ClassSpec; import software.amazon.awssdk.codegen.poet.ClientTestModels; -import software.amazon.awssdk.codegen.poet.rules2.EndpointProviderSpec2; +import software.amazon.awssdk.codegen.poet.rules.EndpointProviderSpec; class EndpointProviderCompiledRulesClassSpecTest { @Test public void endpointProviderClass() { - ClassSpec endpointProviderSpec = new EndpointProviderSpec2(ClientTestModels.queryServiceModels()); + ClassSpec endpointProviderSpec = new EndpointProviderSpec(ClientTestModels.queryServiceModels()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-class.java")); } @Test void knowPropertiesOverride() { ClassSpec endpointProviderSpec = - new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithOverrideKnowProperties()); + new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithOverrideKnowProperties()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-know-prop-override-class.java")); } @Test void unknownEndpointProperties() { ClassSpec endpointProviderSpec = - new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUnknownEndpointProperties()); + new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithUnknownEndpointProperties()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-unknown-property-class.java")); } @Test void endpointProviderClassWithUriCache() { ClassSpec endpointProviderSpec = - new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUriCache()); + new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithUriCache()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-uri-cache-class.java")); } @Test void endpointProviderClassWithMetricValues() { ClassSpec endpointProviderSpec = - new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUnknownEndpointMetricValues()); + new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithUnknownEndpointMetricValues()); assertThat(endpointProviderSpec, generatesTo("endpoint-provider-metric-values-class.java")); } + + @Test + void endpointProviderClass_regionDeclaredButNeverReferenced_compilesSuccessfully() { + // Covers the case where region is declared as a parameter but never referenced in any rule. + ClassSpec endpointProviderSpec = + new EndpointProviderSpec(ClientTestModels.queryServiceModelsWithDelegatingRootRule()); + assertThat(endpointProviderSpec, generatesTo("endpoint-provider-delegating-root-class.java")); + } } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpecTest.java index ba70047a40db..5781dd8e3247 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpecTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverUtilsSpecTest.java @@ -16,11 +16,24 @@ package software.amazon.awssdk.codegen.poet.rules; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.jr.stree.JrsNumber; +import com.fasterxml.jackson.jr.stree.JrsString; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.OperationModel; +import software.amazon.awssdk.codegen.model.rules.endpoints.ParameterModel; +import software.amazon.awssdk.codegen.model.service.OperationContextParam; import software.amazon.awssdk.codegen.poet.ClientTestModels; +import software.amazon.awssdk.codegen.poet.PoetUtils; public class EndpointResolverUtilsSpecTest { @@ -48,4 +61,75 @@ void endpointResolverUtilsClassWithStringArray() { ClassSpec spec = new EndpointResolverUtilsSpec(ClientTestModels.stringArrayServiceModels()); assertThat(spec, generatesTo("endpoint-resolver-utils-with-stringarray.java")); } + + @Test + void multipleLoweredBindingsUseUniqueNames() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + addStringArrayBinding(model, "ListOfObjectsOperation", "stringArrayParam2", + "nested.listOfObjects[*].key"); + + String generated = PoetUtils.buildJavaFile(new EndpointResolverUtilsSpec(model)).toString(); + String method = operationBindingMethod(generated, "ListOfObjectsOperationRequest request"); + + assertTrue(method.contains("Nested nested = request.nested()")); + assertTrue(method.contains("Nested nested_ = request.nested()")); + } + + @Test + void unsupportedBindingFallsBackForWholeOperation() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + addStringArrayBinding(model, "ListOfObjectsOperation", "stringArrayParam2", "nested.listOfObjects"); + + String generated = PoetUtils.buildJavaFile(new EndpointResolverUtilsSpec(model)).toString(); + String method = operationBindingMethod(generated, "ListOfObjectsOperationRequest request"); + + assertTrue(method.contains("JmesPathRuntime.Value input = new JmesPathRuntime.Value(request)")); + assertTrue(method.contains("params.stringArrayParam(input.field(\"nested\")")); + assertTrue(method.contains("params.stringArrayParam2(input.field(\"nested\")")); + assertFalse(method.contains("List stringArrayParam = new ArrayList<>()")); + } + + @Test + void malformedPathOrderedAfterUnsupportedBindingStillReportsTheOperation() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + addStringArrayBinding(model, "ListOfObjectsOperation", "stringArrayParam2", "nested.listOfObjects"); + addBinding(model, "ListOfObjectsOperation", "stringArrayParam3", new JrsNumber(1)); + + RuntimeException e = assertThrows(RuntimeException.class, + () -> PoetUtils.buildJavaFile(new EndpointResolverUtilsSpec(model))); + + assertTrue(e.getMessage() != null && e.getMessage().contains("ListOfObjectsOperation"), + "expected the descriptive model error naming the operation, but got: " + e); + assertTrue(e.getMessage().contains("VALUE_NUMBER_INT")); + } + + private static void addStringArrayBinding(IntermediateModel model, String operationName, String parameterName, + String path) { + addBinding(model, operationName, parameterName, new JrsString(path)); + } + + private static void addBinding(IntermediateModel model, String operationName, String parameterName, + TreeNode path) { + Map parameters = new LinkedHashMap<>(model.getEndpointParameters()); + parameters.put(parameterName, parameters.get("stringArrayParam")); + model.setEndpointParameters(parameters); + + OperationContextParam operationContextParam = new OperationContextParam(); + operationContextParam.setPath(path); + OperationModel operation = model.getOperation(operationName); + Map params = new LinkedHashMap<>(operation.getOperationContextParams()); + params.put(parameterName, operationContextParam); + operation.setOperationContextParams(params); + } + + private static String operationBindingMethod(String generated, String requestParameter) { + int request = generated.indexOf(requestParameter); + int start = generated.lastIndexOf("private static void setOperationContextParams", request); + int end = generated.indexOf("private static void", request + requestParameter.length()); + if (end < 0) { + end = generated.length(); + } + return generated.substring(start, end); + } + } diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitterTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitterTest.java new file mode 100644 index 000000000000..c52eff82764f --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointUrlCodeEmitterTest.java @@ -0,0 +1,334 @@ +/* + * 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.codegen.poet.rules; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.squareup.javapoet.CodeBlock; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link EndpointUrlCodeEmitter}. + * + *

Verifies that URL expressions are correctly decomposed into {@code EndpointUrl.fromComponents()} + * calls when possible, and fall back to {@code EndpointUrl.fromString()} otherwise.

+ */ +class EndpointUrlCodeEmitterTest { + + private static VariableReferenceExpression varRef(String name) { + return new VariableReferenceExpression(name); + } + + private static LiteralStringExpression literal(String value) { + return new LiteralStringExpression(value); + } + + private static MemberAccessExpression memberAccess(String source, String name) { + return MemberAccessExpression.builder() + .source(new VariableReferenceExpression(source)) + .name(name) + .build(); + } + + /** + * Creates a minimal CodeGeneratorVisitor suitable for testing expression emission. + * Only the expression visiting methods (literal, varRef, memberAccess, stringConcat) are used. + */ + private static String emitUrl(RuleExpression urlExpr) { + CodeBlock.Builder builder = CodeBlock.builder(); + CodeGeneratorVisitor visitor = new CodeGeneratorVisitor( + new RuleRuntimeTypeMirror("software.amazon.awssdk.test"), + SymbolTable.builder().build(), + Collections.emptyMap(), + Collections.emptyMap(), + builder + ); + EndpointUrlCodeEmitter.emit(urlExpr, builder, visitor); + return builder.build().toString(); + } + + // --- Pre-parseable cases: emit fromComponents --- + + /** + * "https://sts.{Region}.{PartitionResult#dnsSuffix}" — typical service URL. + */ + @Test + void emit_simpleHostConcat_emitsFromComponents() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://sts.")) + .addExpression(varRef("region")) + .addExpression(literal(".")) + .addExpression(memberAccess("partitionResult", "dnsSuffix")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("\"sts.\""); + assertThat(code).contains("region"); + assertThat(code).contains("partitionResult.dnsSuffix()"); + assertThat(code).contains("-1"); + assertThat(code).contains("\"\""); // empty path + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://runtime.sagemaker.{Region}.{dnsSuffix}:8443" — URL with port. + */ + @Test + void emit_withPort_emitsFromComponentsWithPort() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://runtime.sagemaker.")) + .addExpression(varRef("region")) + .addExpression(literal(".")) + .addExpression(varRef("dnsSuffix")) + .addExpression(literal(":8443")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("8443"); + assertThat(code).contains("\"\""); // empty path + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://places.geo.{Region}.{dnsSuffix}/v2" — URL with static path. + */ + @Test + void emit_withStaticPath_emitsFromComponentsWithPath() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://places.geo.")) + .addExpression(varRef("region")) + .addExpression(literal(".")) + .addExpression(varRef("dnsSuffix")) + .addExpression(literal("/v2")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("-1"); + assertThat(code).contains("\"/v2\""); // static path emitted as literal + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://service.{Region}:8443/v2" — URL with port and path in same literal. + */ + @Test + void emit_withPortAndPath_emitsFromComponentsWithBoth() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://service.")) + .addExpression(varRef("region")) + .addExpression(literal(":8443/v2")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("8443"); + assertThat(code).contains("\"/v2\""); + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://s3.{Region}.{dnsSuffix}/{uriEncodedBucket}" — URL with dynamic path variable. + * This should now be pre-parseable (path contains dynamic expression). + */ + @Test + void emit_withDynamicPath_emitsFromComponentsWithPathExpression() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://s3.")) + .addExpression(varRef("region")) + .addExpression(literal(".")) + .addExpression(varRef("dnsSuffix")) + .addExpression(literal("/")) + .addExpression(varRef("uriEncodedBucket")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("region"); + assertThat(code).contains("dnsSuffix"); + // Path is dynamic: "/" + uriEncodedBucket + assertThat(code).contains("\"/\""); + assertThat(code).contains("uriEncodedBucket"); + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://sts.amazonaws.com" — fully static literal URL. + */ + @Test + void emit_fullyStaticLiteral_emitsFromComponentsAllLiterals() { + LiteralStringExpression urlExpr = literal("https://sts.amazonaws.com"); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("\"sts.amazonaws.com\""); + assertThat(code).contains("-1"); + assertThat(code).contains("\"\""); + assertThat(code).doesNotContain("fromString"); + } + + /** + * "https://example.com:443/api/v1" — static URL with port and path. + */ + @Test + void emit_fullyStaticWithPortAndPath_emitsFromComponentsAllLiterals() { + LiteralStringExpression urlExpr = literal("https://example.com:443/api/v1"); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("\"example.com\""); + assertThat(code).contains("443"); + assertThat(code).contains("\"/api/v1\""); + assertThat(code).doesNotContain("fromString"); + } + + // --- Fallback cases: emit fromString --- + + /** + * "{url#scheme}://{Bucket}.{url#authority}{url#path}" — scheme is dynamic. + */ + @Test + void emit_dynamicScheme_emitsFromString() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(memberAccess("url", "scheme")) + .addExpression(literal("://")) + .addExpression(varRef("Bucket")) + .addExpression(literal(".")) + .addExpression(memberAccess("url", "authority")) + .addExpression(memberAccess("url", "path")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromString("); + assertThat(code).doesNotContain("fromComponents"); + } + + /** + * VariableReferenceExpression (e.g. just a variable) — not a string template or literal. + */ + @Test + void emit_variableReferenceExpression_emitsFromString() { + VariableReferenceExpression urlExpr = varRef("computedUrl"); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromString("); + assertThat(code).contains("computedUrl"); + assertThat(code).doesNotContain("fromComponents"); + } + + /** + * region + ".amazonaws.com" — first expression is not a scheme literal. + */ + @Test + void emit_firstExpressionNotSchemeLiteral_emitsFromString() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(varRef("region")) + .addExpression(literal(".amazonaws.com")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromString("); + assertThat(code).doesNotContain("fromComponents"); + } + + // --- Edge cases --- + + /** + * "http://localhost:8080/test" — http scheme (not https). + */ + @Test + void emit_httpScheme_emitsFromComponents() { + LiteralStringExpression urlExpr = literal("http://localhost:8080/test"); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"http\""); + assertThat(code).contains("\"localhost\""); + assertThat(code).contains("8080"); + assertThat(code).contains("\"/test\""); + } + + /** + * "https://{Bucket}.s3.{Region}.{dnsSuffix}" — host starts with a dynamic expression + * after the scheme prefix (the literal "https://" is followed by nothing before the first varRef). + */ + @Test + void emit_hostStartsWithVariable_emitsFromComponents() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(literal("https://")) + .addExpression(varRef("Bucket")) + .addExpression(literal(".s3.")) + .addExpression(varRef("region")) + .addExpression(literal(".")) + .addExpression(varRef("dnsSuffix")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromComponents("); + assertThat(code).contains("\"https\""); + assertThat(code).contains("Bucket"); + assertThat(code).doesNotContain("fromString"); + } + + /** + * Custom endpoint override: "{url#scheme}://{url#authority}{url#path}" + * + *

This is the standard representation when a user provides a custom endpoint URL via + * client configuration. The endpoint rule decomposes the user-provided URL into its parts + * (scheme, authority, path) and reassembles them with possible modifications (e.g., host prefix). + * Since the scheme is a dynamic expression (not a literal "https://" or "http://"), this + * cannot be pre-parsed and must fall back to runtime parsing. + */ + @Test + void emit_customEndpointOverride_emitsFromString() { + StringConcatExpression urlExpr = StringConcatExpression.builder() + .addExpression(memberAccess("url", "scheme")) + .addExpression(literal("://")) + .addExpression(memberAccess("url", "authority")) + .addExpression(memberAccess("url", "path")) + .build(); + + String code = emitUrl(urlExpr); + + assertThat(code).contains("EndpointUrl.fromString("); + assertThat(code).contains("url.scheme()"); + assertThat(code).contains("url.authority()"); + assertThat(code).contains("url.path()"); + assertThat(code).doesNotContain("fromComponents"); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParserTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParserTest.java similarity index 98% rename from codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParserTest.java rename to codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParserTest.java index 18138ba69a0f..31c1834a9cd3 100644 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/ExpressionParserTest.java +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/ExpressionParserTest.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.codegen.poet.rules2; +package software.amazon.awssdk.codegen.poet.rules; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGeneratorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGeneratorTest.java new file mode 100644 index 000000000000..de29cd72c9d8 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/JmesPathTypedGetterGeneratorTest.java @@ -0,0 +1,210 @@ +/* + * 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.codegen.poet.rules; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.NameAllocator; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; +import software.amazon.awssdk.codegen.poet.ClientTestModels; + +class JmesPathTypedGetterGeneratorTest { + + @Test + void sharedAllocatorAvoidsMethodParametersAndPreviousBindings() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + NameAllocator names = generator.newNameAllocator(); + + CodeBlock first = generator.lower(input, "Request.Value", "string", "firstParam", names); + CodeBlock second = generator.lower(input, "Request.Value", "string", "secondParam", names); + String generated = first.toString() + second.toString(); + + assertTrue(generated.contains("request_ = request.request()")); + assertTrue(generated.contains("request__ = request.request()")); + } + + @Test + void bareProjectionFallsBack() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("TransactionOperation").getInputShape(); + + assertThrows(JmesPathTypedGetterGenerator.UnsupportedLoweringException.class, + () -> generator.lower(input, "TransactItems[*]", "stringarray", "stringArrayParam")); + } + + @Test + void collectionFlattenFallsBack() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + assertThrows(JmesPathTypedGetterGenerator.UnsupportedLoweringException.class, + () -> generator.lower(input, "nested.listOfObjects[*].aliases[]", "stringarray", + "stringArrayParam")); + } + + @Test + void incompatibleTerminalConversionFallsBack() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + assertThrows(JmesPathTypedGetterGenerator.UnsupportedLoweringException.class, + () -> generator.lower(input, "Request.Value", "boolean", "booleanParam")); + } + + @Test + void idempotencyTokenFallsBack() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + assertThrows(JmesPathTypedGetterGenerator.UnsupportedLoweringException.class, + () -> generator.lower(input, "Request.Token", "string", "stringParam")); + } + + /** + * A boolean leaf three hops deep exercises the boolean terminal check and the mid-chain ternary guard. + */ + @Test + void booleanLeafThroughDeepScalarChainLowers() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "Request.Inner.Flag", "boolean", "booleanParam"); + + String code = generated.toString(); + assertTrue(code.contains("inner = request_ == null ? null : request_.inner()"), + "expected a ternary-guarded mid-chain hop, but got: " + code); + assertTrue(code.contains("params.booleanParam(inner == null ? null : inner.flag())"), + "expected the setter to be invoked with a null-safe boolean leaf, but got: " + code); + } + + @Test + void customizedRuntimeDefaultFallsBack() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + model.getCustomizationConfig().setModelMarshallerDefaultValueSupplier( + Collections.singletonMap("Value", "example.DefaultSupplier")); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + assertThrows(JmesPathTypedGetterGenerator.UnsupportedLoweringException.class, + () -> generator.lower(input, "Request.Value", "string", "stringParam")); + } + + @Test + void keysFiltersNullEntries() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("MapKeysOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "keys(RequestItems)", "stringarray", "stringArrayParam"); + + assertTrue(generated.toString().contains("if (key != null)")); + } + + @Test + void keysLoopVariableDoesNotShadowResultLocal() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("MapKeysOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "keys(RequestItems)", "stringarray", "key"); + + assertFalse(generated.toString().contains("for (java.lang.String key :")); + assertFalse(generated.toString().contains("key.add(key)")); + } + + @Test + void keysLoopVariableParticipatesInSharedNamespace() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("MapKeysOperation").getInputShape(); + NameAllocator names = generator.newNameAllocator(); + // Stand in for an earlier binding in the same method that already took "key". + names.newName("key"); + + CodeBlock generated = generator.lower(input, "keys(RequestItems)", "stringarray", "stringArrayParam", names); + + assertFalse(generated.toString().contains("for (java.lang.String key :")); + } + + /** + * {@code keys()} behind a nullable struct must seed the mutable empty list that the reflective runtime returns + * for a null prefix: keys() normalizes null to an empty list value whose {@code stringValues()} is mutable, + * unlike a null projection prefix. + */ + @Test + void keysWithNullablePrefixSeedsAMutableEmptyList() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "keys(Request.ItemMap)", "stringarray", "stringArrayParam"); + + String code = generated.toString(); + assertTrue(code.contains("stringArrayParam = new java.util.ArrayList<>();"), + "expected the result to be seeded with a mutable empty list, but got: " + code); + assertTrue(code.contains("if (request_ != null)"), + "expected the struct prefix to be null-guarded, but got: " + code); + assertTrue(code.contains("stringArrayParam = new java.util.ArrayList<>(itemMap.size())"), + "expected the guarded branch to switch to a presized list, but got: " + code); + assertTrue(code.contains("for (java.lang.String key : itemMap.keySet())"), + "expected the key loop to iterate the map directly, but got: " + code); + } + + /** + * {@code stringValues()} returns an immutable list when the projected prefix is null, so a projection behind a + * nullable prefix must not hand the endpoint params an always-mutable list. + */ + @Test + void nullableProjectionPrefixSeedsAnImmutableEmptyList() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("ListOfObjectsOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "nested.listOfObjects[*].key", "stringarray", "stringArrayParam"); + + assertTrue(generated.toString().contains("java.util.Collections.emptyList()"), + "expected the result to be seeded with an immutable empty list, but got: " + generated); + } + + /** + * A projection with no nullable prefix always reaches its loop, so the result list is allocated directly. + */ + @Test + void projectionWithoutNullablePrefixAllocatesDirectly() { + IntermediateModel model = ClientTestModels.stringArrayServiceModels(); + JmesPathTypedGetterGenerator generator = new JmesPathTypedGetterGenerator(model); + ShapeModel input = model.getOperation("TransactionOperation").getInputShape(); + + CodeBlock generated = generator.lower(input, "TransactItems[*].Put.TableName", "stringarray", + "stringArrayParam"); + + assertFalse(generated.toString().contains("java.util.Collections.emptyList()"), + "unguarded projection should allocate directly, but got: " + generated); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/TokenizerTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/TokenizerTest.java new file mode 100644 index 000000000000..e4ffc8aa2301 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/TokenizerTest.java @@ -0,0 +1,114 @@ +/* + * 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.codegen.poet.rules; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class TokenizerTest { + + @Test + public void recognizesReferenceExpression() { + Tokenizer tokenizer = new Tokenizer("{foobar}"); + assertTrue(tokenizer.isReference()); + tokenizer.consumeReferenceAccess((n) -> assertEquals("foobar", n)); + assertTrue(tokenizer.atEof()); + } + + @Test + public void recognizesIndexedExpression() { + Tokenizer tokenizer = new Tokenizer("foobar[123]"); + assertTrue(tokenizer.isIndexedAccess()); + tokenizer.consumeIndexed((name, index) -> { + assertEquals("foobar", name); + assertEquals(123, index); + }); + assertTrue(tokenizer.atEof()); + } + + @Test + public void recognizesDirectIndexedExpression() { + Tokenizer tokenizer = new Tokenizer("[123]"); + assertTrue(tokenizer.isDirectIndexedAccess()); + tokenizer.consumeDirectIndexed(i -> assertEquals(123, i)); + assertTrue(tokenizer.atEof()); + } + + @Test + public void recognizesNamedAccessExpression() { + Tokenizer tokenizer = new Tokenizer("{url#authority}"); + assertTrue(tokenizer.isNamedAccess()); + tokenizer.consumeNamedAccess((reference, name) -> { + assertEquals("url", reference); + assertEquals("authority", name); + }); + assertTrue(tokenizer.atEof()); + } + + @Test + public void recognizesDirectNegativeIndexedExpression() { + Tokenizer tokenizer = new Tokenizer("[-2]"); + assertTrue(tokenizer.isDirectNegativeIndexedAccess()); + tokenizer.consumeDirectNegativeIndexed(i -> assertEquals(-2, i)); + assertTrue(tokenizer.atEof()); + } + + @Test + public void recognizesNegativeIndexedExpression() { + Tokenizer tokenizer = new Tokenizer("resourceId[-1]"); + assertTrue(tokenizer.isNegativeIndexedAccess()); + tokenizer.consumeNegativeIndexed((name, index) -> { + assertEquals("resourceId", name); + assertEquals(-1, index); + }); + assertTrue(tokenizer.atEof()); + } + + @Test + public void negativeIndexIsNotConfusedWithPositiveIndex() { + assertTrue(new Tokenizer("[2]").isDirectIndexedAccess()); + assertFalse(new Tokenizer("[2]").isDirectNegativeIndexedAccess()); + assertTrue(new Tokenizer("[-2]").isDirectNegativeIndexedAccess()); + assertFalse(new Tokenizer("[-2]").isDirectIndexedAccess()); + } + + /** + * A hyphen is only a distinct token when it opens a negative index. Everywhere else it is an ordinary string + * character, otherwise literals such as "s3-fips" would be split into extra concatenation terms by + * {@code ExpressionParser.parseStringConcat}. + */ + @Test + public void hyphenOutsideIndexRemainsPartOfString() { + // Hyphen followed by a digit, but not inside an index - must stay in the string. + Tokenizer tokenizer = new Tokenizer("{Region}-1a"); + assertTrue(tokenizer.isReference()); + tokenizer.consumeReferenceAccess(n -> assertEquals("Region", n)); + assertEquals("-1a", tokenizer.next().value()); + assertTrue(tokenizer.atEof()); + } + + @Test + public void hyphenatedHostLabelIsSingleToken() { + Tokenizer tokenizer = new Tokenizer("{Region}s3-fips-2.example"); + assertTrue(tokenizer.isReference()); + tokenizer.consumeReferenceAccess(n -> assertEquals("Region", n)); + assertEquals("s3-fips-2.example", tokenizer.next().value()); + assertTrue(tokenizer.atEof()); + } +} \ No newline at end of file diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpecTest.java new file mode 100644 index 000000000000..5bf5ca7d6779 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddEndpointProviderSpecTest.java @@ -0,0 +1,332 @@ +/* + * 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.codegen.poet.rules.bdd; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.poet.ClientTestModels; + +public class BddEndpointProviderSpecTest { + + /** + * The trailing nodes of {@code endpoint-bdd-default-regional.json} were appended by hand with {@code high == low}, + * so that each parameter is read by a condition without altering any resolved endpoint. That is the one shape a + * reduced BDD can never contain, which is why it shows up in the golden file as degenerate {@code nodeP} methods + * whose branches are identical. A future peephole pass that collapses {@code high == low} nodes would silently make + * those parameters unreferenced and void the cache-key coverage the tests below rely on. + */ + @Test + void endpointProviderClass_simpleBdd_generatesExpectedCode() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()); + MatcherAssert.assertThat(spec, generatesTo("endpoint-provider-bdd-class.java")); + } + + /** + * The S3 BDD is the only model that exercises all four peephole rewrites, the dynamic auth scheme + * name, and the {@code ite} assign conditions. The simple-BDD fixture above contains none of + * those shapes, so this golden file is what makes the pass's effect on generated code reviewable + * and pins it against unintended change. + */ + @Test + void endpointProviderClass_s3Bdd_generatesExpectedCode() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints()); + MatcherAssert.assertThat(spec, generatesTo("endpoint-provider-bdd-s3-class.java")); + } + + /** + * Correctness invariants that must hold no matter what the golden file above happens to contain. + * + *

These are deliberately not left to the fixture. Regenerating a golden file after changing an + * emitter is a one-command operation, and doing it without reading the diff is how a defect gets + * blessed into a fixture - this repo has an instance of exactly that. Every assertion here is + * phrased negatively and carries the reason, so restoring the faster-but-wrong form means + * consciously deleting a stated invariant rather than accepting a regenerated file. + */ + @Test + void s3Bdd_neverEmitsSpecViolatingForms() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints()); + String generated = spec.poetSpec().toString(); + + // Inlined String comparisons skip substring's rejection of non-ASCII input, which would route + // a bucket like "mybuck\u00e9t--x-s3" to S3 Express with sigv4-s3express instead of to a + // regular S3 endpoint with SigV4. RulesFunctions.substringEquals exists to preserve that. + assertThat(generated) + .as("substring comparisons must go through substringEquals, which checks for non-ASCII input") + .doesNotContain(".startsWith(") + .doesNotContain(".endsWith(") + .doesNotContain(".regionMatches("); + + // The spec's stringEquals returns false for a null operand; .equals throws. Only a comparison + // with a string constant on the receiver is safe to inline. + assertThat(generated) + .as("stringEquals with two nullable operands must stay null-safe") + .doesNotContain("region.equals(bucketArn.region())") + .doesNotContain("bucketArn.partition().equals(") + .doesNotContain("bucketPartition.name().equals("); + + // A ternary would emit the coalesce subject twice, running any non-trivial operand twice. + assertThat(generated) + .as("boolean coalesce must evaluate its subject once") + .doesNotContain("!= null ?"); + + // Each rewrite must actually fire; falling back to the generic dispatch is a silent + // de-optimization that the fixture alone would absorb without comment. + assertThat(generated) + .as("no rewritten shape may fall back to a RulesFunctions dispatch") + .doesNotContain("RulesFunctions.ite(") + .doesNotContain("RulesFunctions.coalesce(") + .doesNotContain("RulesFunctions.isValidHostLabel("); + } + + /** + * The three {@code ite} nodes in the S3 BDD all have string-literal branches, so their assign + * conditions are provably non-null and keep the elided null check. Paired with + * {@code ConditionFnCodeGeneratorVisitorTest}, which pins the nullable-branch case that must emit + * the check. Stated here as an invariant because the two halves only make sense together. + */ + @Test + void literalBranchIteAssigns_keepElidedNullCheck() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints()); + String generated = spec.poetSpec().toString(); + + assertThat(generated).contains("_s3e_ds = (params.useDualStack() ? \".dualstack\" : \"\");\n return true;"); + assertThat(generated).contains("_s3e_fips = (params.useFips() ? \"-fips\" : \"\");\n return true;"); + } + + /** + * The S3 BDD merges results that differ only in their auth scheme name, so the name is resolved at runtime via + * {@code DynamicEndpointAuthSchemeFactory.create(name)}. The sibling properties must still be emitted, otherwise + * the signing configuration would be silently dropped. + */ + @Test + void dynamicAuthSchemeName_delegatesToFactoryAndKeepsProperties() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints()); + + String generated = spec.poetSpec().toString(); + + assertThat(generated).contains("DynamicEndpointAuthSchemeFactory.builder()"); + assertThat(generated).contains(".create(_s3e_auth)"); + assertThat(generated).contains(".signingName(\"s3express\")"); + assertThat(generated).contains(".disableDoubleEncoding(true)"); + assertThat(generated).doesNotContain("DynamicEndpointAuthSchemeFactory.builder().build()"); + } + + /** + * Verifies that complement edges (negative node references) generate nodeN methods with + * swapped branches. A complement edge to node N means: evaluate the same condition, but + * follow lowRef when true and highRef when false (the inverse of nodeP). + */ + @Test + void complementEdge_generatesNodeNWithSwappedBranches() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithComplementBddEndpoints()); + + String generated = spec.poetSpec().toString(); + + // nodeP1 should exist with normal branch order + assertThat(generated).contains("nodeP1()"); + // nodeN1 should exist (complement variant with swapped branches) + assertThat(generated).contains("nodeN1()"); + // nodeP2's false branch should reference nodeN1 (the complement edge) + assertThat(generated).contains("Endpoint nodeN1()"); + } + + /** + * The invariant the result cache depends on: every parameter the BDD reads must appear in the generated + * key. A parameter left out is not a slow cache, it is a cache that returns an endpoint resolved for a different + * value of that parameter, and nothing else in the test suite would catch it. + * + *

Asserted against the generated source rather than an intermediate model, so it holds regardless of how the + * comparison is built. + */ + @Test + void cacheKeyComparesEveryReferencedParameter() { + // The simple BDD declares 10 parameters and reads 9; unusedParam is the one it does not read. + assertThat(cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()))) + .containsExactlyInAnyOrder("useDualStack", "useFips", "region", "stringContextParam", "endpoint", + "staticStringParam", "operationContextParam", "arnList", + "customEndpointArray"); + + // The S3 BDD declares 17 and reads 14; Key, Prefix and CopySource are vestigial declarations. + assertThat(cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithBddEndpoints()))) + .containsExactlyInAnyOrder("useFips", "useDualStack", "forcePathStyle", "accelerate", "useGlobalEndpoint", + "useObjectLambdaEndpoint", "disableAccessPoints", + "disableMultiRegionAccessPoints", "useArnRegion", + "useS3ExpressControlEndpoint", "disableS3ExpressSessionAuth", "region", + "bucket", "endpoint"); + + // The complement BDD declares and reads exactly two. + assertThat(cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithComplementBddEndpoints()))) + .containsExactlyInAnyOrder("region", "endpoint"); + } + + /** + * A parameter no condition and no result reads cannot change the resolved endpoint, so comparing it could only turn + * hits into misses that resolve to the endpoint already cached. + * + *

This is what makes the cache worth having for S3, whose rule set declares {@code Key}, {@code Prefix} and + * {@code CopySource} and reads none of them. {@code Key} changes on essentially every object request, so including + * it would mean the cache almost never hits. + */ + @Test + void cacheKeyOmitsParametersTheBddNeverReads() { + assertThat(cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()))) + .as("a parameter nothing reads must not force a cache miss") + .doesNotContain("unusedParam"); + + assertThat(cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithBddEndpoints()))) + .as("S3 declares Key, Prefix and CopySource but reads none of them") + .doesNotContain("key", "prefix", "copySource") + .contains("bucket"); + } + + /** + * The generated key compares booleans first, then the strings whose reference the SDK keeps stable, then everything + * else. Ordering cannot change the result - the chain compares every parameter before returning true - it only + * decides how quickly a mismatch is found, so this is a performance property rather than a correctness one. It is + * pinned because the ordering is the entire reason the grouping exists; if it silently degraded to declaration + * order the code would still be correct and the benefit would be gone. + */ + @Test + void cacheKeyOrdersBooleansThenStableStringsThenTheRest() { + List order = cacheKeyGetterOrder( + new BddEndpointProviderSpec(ClientTestModels.queryServiceModelsWithSimpleBddEndpoints())); + + assertThat(order).containsExactly("useDualStack", "useFips", // booleans + "region", "stringContextParam", // reference-stable strings + "endpoint", "staticStringParam", // everything else, declaration order + "operationContextParam", "arnList", "customEndpointArray"); + } + + /** + * A list read as a whole needs a bounded comparison, so it routes through the emitted helper rather than + * {@code Objects.equals}, whose {@code List.equals} would walk every element however long the list is. + */ + @Test + void listReadAsAWholeUsesTheBoundedHelper() { + String generated = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()).poetSpec().toString(); + + assertThat(generated).contains("cacheListsMatch(a.customEndpointArray(), b.customEndpointArray())"); + assertThat(generated).contains("if (size > 4) return false"); + } + + /** + * When the rules can only see whether a list is present and what its first element is, the rest of the list cannot + * reach the endpoint, so the key compares presence and element 0. This is the DynamoDB shape: it reads + * {@code ResourceArnList} through {@code isSet} and {@code getAttr(ResourceArnList, "[0]")} and nothing else, and + * comparing the whole list costs more than half of a regional resolution. + * + *

The {@code isSet} guard is not incidental. The rules language requires a null check before an indexed access, + * so every real model that reads {@code list[0]} also reads {@code isSet(list)}; if the null check disqualified the + * parameter this case would never fire in production. + * + *

Also asserts the generated provider really does read only element 0, so the two halves cannot drift apart: were + * a read past the head to appear, this comparison would silently become wrong. + */ + @Test + void listReadOnlyAtIndexZeroComparesPresenceAndTheFirstElement() { + String generated = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()).poetSpec().toString(); + + assertThat(generated).contains("cacheFirstElementsMatch(a.arnList(), b.arnList())"); + assertThat(generated).doesNotContain("cacheListsMatch(a.arnList()"); + assertThat(generated) + .as("the first-element comparison is only valid while the provider reads nothing past element 0") + .contains("RulesFunctions.listAccess(params.arnList(), 0)") + .doesNotContain("RulesFunctions.listAccess(params.arnList(), 1)"); + assertThat(generated) + .as("isSet distinguishes an absent list from an empty one, so presence stays part of the key") + .contains("if (a == null || b == null) return false"); + } + + /** + * A read past the head disqualifies the first-element comparison, because elements beyond the first can then reach + * the endpoint. Pinned because the difference between the two helpers is a correctness boundary, not a preference. + */ + @Test + void listReadPastTheHeadIsComparedInFull() { + String generated = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithSimpleBddEndpoints()).poetSpec().toString(); + + assertThat(generated).contains("cacheListsMatch(a.customEndpointArray(), b.customEndpointArray())"); + assertThat(generated).doesNotContain("cacheFirstElementsMatch(a.customEndpointArray()"); + assertThat(generated).contains("RulesFunctions.listAccess(params.customEndpointArray(), 1)"); + } + + /** + * Neither helper is worth emitting when nothing needs it, and the S3 BDD keeps no list parameter in its key. + */ + @Test + void listHelpersAreOmittedWhenNoListParameterIsInTheKey() { + String generated = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints()).poetSpec().toString(); + + assertThat(generated).doesNotContain("cacheListsMatch"); + assertThat(generated).doesNotContain("cacheFirstElementsMatch"); + } + + /** + * Returns the parameter getters referenced by the generated {@code cacheParamsMatch}, in the order they are + * compared. + */ + private static List cacheKeyGetterOrder(BddEndpointProviderSpec spec) { + String generated = spec.poetSpec().toString(); + int start = generated.indexOf("boolean cacheParamsMatch("); + assertThat(start).as("generated provider must contain cacheParamsMatch").isNotNegative(); + int end = generated.indexOf(";", start); + String body = generated.substring(start, end); + + List getters = new ArrayList<>(); + Matcher matcher = Pattern.compile("\\ba\\.(\\w+)\\(\\)").matcher(body); + while (matcher.find()) { + getters.add(matcher.group(1)); + } + return getters; + } + + /** + * {@code DynamicEndpointAuthSchemeFactory} is S3-specific, so a dynamically resolved auth scheme name in any other + * service must fail codegen rather than emitting code that cannot compile. + */ + @Test + void dynamicAuthSchemeName_withoutS3ExpressCustomization_failsCodegen() { + BddEndpointProviderSpec spec = new BddEndpointProviderSpec( + ClientTestModels.queryServiceModelsWithBddEndpoints(false)); + + assertThatThrownBy(spec::poetSpec) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("useS3ExpressSessionAuth") + .hasMessageContaining("resolved at runtime"); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitorTest.java new file mode 100644 index 000000000000..9a694c36babc --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/BddPeepholeVisitorTest.java @@ -0,0 +1,163 @@ +/* + * 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.codegen.poet.rules.bdd; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralIntegerExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; + +/** + * Covers the substring peephole matcher in {@link BddPeepholeVisitor}: when it rewrites + * {@code stringEquals(coalesce(substring(..), ""), literal)} into + * {@code RulesFunctions.substringEquals}, and when it must leave the expression alone. + */ +class BddPeepholeVisitorTest { + + @Test + void substringComparisonIsRewrittenToSubstringEquals() { + RuleExpression result = rewrite(substringEqualsExpr(0, 6, true, "--x-s3")); + + assertThat(result).isInstanceOf(FunctionCallExpression.class); + FunctionCallExpression fn = (FunctionCallExpression) result; + assertThat(fn.name()).isEqualTo(RuleRuntimeTypeMirror.SUBSTRING_EQUALS_FN); + assertThat(fn.arguments()).hasSize(5); + assertThat(((LiteralIntegerExpression) fn.arguments().get(1)).value()).isEqualTo(0); + assertThat(((LiteralIntegerExpression) fn.arguments().get(2)).value()).isEqualTo(6); + assertThat(((LiteralBooleanExpression) fn.arguments().get(3)).value()).isTrue(); + assertThat(((LiteralStringExpression) fn.arguments().get(4)).value()).isEqualTo("--x-s3"); + } + + @Test + void forwardInteriorComparisonIsRewritten() { + FunctionCallExpression fn = (FunctionCallExpression) rewrite(substringEqualsExpr(16, 18, false, "--")); + + assertThat(fn.name()).isEqualTo(RuleRuntimeTypeMirror.SUBSTRING_EQUALS_FN); + assertThat(((LiteralIntegerExpression) fn.arguments().get(1)).value()).isEqualTo(16); + assertThat(((LiteralIntegerExpression) fn.arguments().get(2)).value()).isEqualTo(18); + assertThat(((LiteralBooleanExpression) fn.arguments().get(3)).value()).isFalse(); + } + + @Test + void lengthMismatchIsNotRewritten() { + // The window is 6 wide but the literal is 4, so the comparison can never be true. Leave it to + // the general path rather than emitting a call whose arguments contradict each other. + assertThat(isSubstringEqualsCall(rewrite(substringEqualsExpr(0, 6, true, "arn:")))).isFalse(); + } + + /** + * {@code startIndex == stopIndex} makes the spec's {@code substring} return null, so the coalesce + * yields {@code ""} and comparing against an empty literal is true even for a null input. + * {@code substringEquals} returns false there, so this must not be rewritten. Paired with + * {@code RulesFunctionsSubstringEqualsTest.degenerateEmptyWindowDivergesFromTheSpecAndIsGuardedInCodegen} + * in the s3 module, which pins the runtime side of the same divergence. + */ + @Test + void emptyLiteralIsNotRewritten() { + assertThat(isSubstringEqualsCall(rewrite(substringEqualsExpr(3, 3, false, "")))).isFalse(); + } + + /** + * A {@code stringEquals} that is not a substring comparison must be left intact for + * {@link software.amazon.awssdk.codegen.poet.rules.PrepareForCodegenVisitor}, which only rewrites + * to {@code constant.equals(other)} when one side is a string constant. + * + *

Rewriting it here would emit {@code left.equals(right)} for two nullable operands, and the + * spec's {@code stringEquals} returns false for a null operand rather than throwing. The S3 BDD + * reaches this with {@code stringEquals(region, bucketArn.region())} among others. + */ + @Test + void plainStringEqualsIsLeftForPrepareForCodegen() { + RuleExpression expr = FunctionCallExpression + .builder() + .name("stringEquals") + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(VariableReferenceExpression.builder().variableName("region").build()) + .addArgument(VariableReferenceExpression.builder().variableName("arnRegion").build()) + .build(); + + RuleExpression result = rewrite(expr); + + assertThat(result).isInstanceOf(FunctionCallExpression.class); + assertThat(((FunctionCallExpression) result).name()).isEqualTo("stringEquals"); + } + + /** + * Same for a constant operand: the peephole must not pre-empt PrepareForCodegenVisitor, which + * already places the constant on the receiver side. + */ + @Test + void constantOperandStringEqualsIsAlsoLeftForPrepareForCodegen() { + RuleExpression expr = FunctionCallExpression + .builder() + .name("stringEquals") + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(VariableReferenceExpression.builder().variableName("region").build()) + .addArgument(new LiteralStringExpression("us-east-1")) + .build(); + + assertThat(((FunctionCallExpression) rewrite(expr)).name()).isEqualTo("stringEquals"); + } + + private static RuleExpression rewrite(RuleExpression expr) { + return expr.accept(new BddPeepholeVisitor()); + } + + /** + * When the substring peephole declines, {@code simplifyStringEquals} still rewrites the comparison + * into a {@code MethodCallExpression} for {@code left.equals(right)}, so the result is not + * necessarily a {@link FunctionCallExpression} at all. + */ + private static boolean isSubstringEqualsCall(RuleExpression expr) { + return expr instanceof FunctionCallExpression + && RuleRuntimeTypeMirror.SUBSTRING_EQUALS_FN.equals(((FunctionCallExpression) expr).name()); + } + + /** + * Builds {@code stringEquals(coalesce(substring(Bucket, start, stop, reverse), ""), literal)}. + */ + private static RuleExpression substringEqualsExpr(int start, int stop, boolean reverse, String literal) { + FunctionCallExpression substring = + FunctionCallExpression.builder() + .name("substring") + .type(RuleRuntimeTypeMirror.STRING) + .addArgument(VariableReferenceExpression.builder().variableName("Bucket").build()) + .addArgument(new LiteralIntegerExpression(start)) + .addArgument(new LiteralIntegerExpression(stop)) + .addArgument(new LiteralBooleanExpression(reverse)) + .build(); + + FunctionCallExpression coalesce = + FunctionCallExpression.builder() + .name("coalesce") + .type(RuleRuntimeTypeMirror.STRING) + .addArgument(substring) + .addArgument(new LiteralStringExpression("")) + .build(); + + return FunctionCallExpression.builder() + .name("stringEquals") + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(coalesce) + .addArgument(new LiteralStringExpression(literal)) + .build(); + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitorTest.java new file mode 100644 index 000000000000..1d1b0eca0b94 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/bdd/ConditionFnCodeGeneratorVisitorTest.java @@ -0,0 +1,163 @@ +/* + * 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.codegen.poet.rules.bdd; + +import static org.assertj.core.api.Assertions.assertThat; +import com.squareup.javapoet.CodeBlock; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.poet.ClientTestModels; +import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; +import software.amazon.awssdk.codegen.poet.rules.FunctionCallExpression; +import software.amazon.awssdk.codegen.poet.rules.LetExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralBooleanExpression; +import software.amazon.awssdk.codegen.poet.rules.LiteralStringExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleExpression; +import software.amazon.awssdk.codegen.poet.rules.RuleRuntimeTypeMirror; +import software.amazon.awssdk.codegen.poet.rules.VariableReferenceExpression; + +/** + * Covers the null-check elision in {@code visitLetExpression}. An assign condition is satisfied only + * when the assigned value is non-null, so emitting {@code return true} instead of + * {@code return reg != null} is only sound when the value is provably non-null. + * + *

{@code __ite} is emitted as a ternary between its two branches. Only string-literal branches + * make it provably non-null: {@code BddPeepholeVisitor.simplifyIte} does not constrain the branches, + * and the BDD model is produced by the endpoint compiler rather than by this repo, so a + * {@code {"ref": ...}} branch is legal input and may be null at runtime. + */ +class ConditionFnCodeGeneratorVisitorTest { + + private static final String REGISTER = "suffix"; + private static final String NULLABLE_REF = "someNullableString"; + + private RuleRuntimeTypeMirror typeMirror; + private EndpointRulesSpecUtils specUtils; + private Map registers; + + @BeforeEach + void setUp() { + IntermediateModel model = ClientTestModels.queryServiceModelsWithSimpleBddEndpoints(); + typeMirror = new RuleRuntimeTypeMirror(model.getMetadata().getFullInternalEndpointRulesPackageName()); + specUtils = new EndpointRulesSpecUtils(model); + + registers = new HashMap<>(); + registers.put(REGISTER, register(REGISTER)); + registers.put(NULLABLE_REF, register(NULLABLE_REF)); + } + + @Test + void visitLetExpression_whenIteBranchesAreStringLiterals_elidesNullCheck() { + String generated = generate(ite(new LiteralStringExpression(".dualstack"), new LiteralStringExpression(""))); + + assertThat(generated).contains("return true"); + assertThat(generated).doesNotContain(REGISTER + " != null"); + } + + @Test + void visitLetExpression_whenIteBranchIsNullableReference_emitsNullCheck() { + String generated = generate(ite(reference(NULLABLE_REF), new LiteralStringExpression(""))); + + assertThat(generated) + .as("a ref branch can be null at runtime, so the assign condition must check the register") + .contains("return " + REGISTER + " != null"); + assertThat(generated).doesNotContain("return true"); + } + + @Test + void visitLetExpression_whenIteFalseBranchIsNullableReference_emitsNullCheck() { + String generated = generate(ite(new LiteralStringExpression(""), reference(NULLABLE_REF))); + + assertThat(generated).contains("return " + REGISTER + " != null"); + assertThat(generated).doesNotContain("return true"); + } + + @Test + void visitLetExpression_whenValueIsNotIte_emitsNullCheck() { + String generated = generate(reference(NULLABLE_REF)); + + assertThat(generated).contains("return " + REGISTER + " != null"); + assertThat(generated).doesNotContain("return true"); + } + + /** + * The single-evaluation form for a boolean coalesce. A ternary would emit the subject twice, + * running any non-trivial operand twice per evaluation. + */ + @Test + void coalesceBoolean_emitsWrapperEqualityEvaluatingSubjectOnce() { + String withFalseDefault = generate(coalesceBoolean(false)); + assertThat(withFalseDefault).contains("Boolean.TRUE.equals(" + NULLABLE_REF + ")"); + assertThat(withFalseDefault).doesNotContain("!= null ?"); + + String withTrueDefault = generate(coalesceBoolean(true)); + assertThat(withTrueDefault).contains("!Boolean.FALSE.equals(" + NULLABLE_REF + ")"); + assertThat(withTrueDefault).doesNotContain("!= null ?"); + + // Subject appears exactly once in each. + assertThat(countOccurrences(withFalseDefault, NULLABLE_REF)).isEqualTo(1); + assertThat(countOccurrences(withTrueDefault, NULLABLE_REF)).isEqualTo(1); + } + + private String generate(RuleExpression boundValue) { + CodeBlock.Builder code = CodeBlock.builder(); + LetExpression let = LetExpression.builder() + .putBinding(REGISTER, boundValue) + .build(); + let.accept(new ConditionFnCodeGeneratorVisitor(code, typeMirror, registers, specUtils)); + return code.build().toString(); + } + + private static RuleExpression ite(RuleExpression ifTrue, RuleExpression ifFalse) { + return FunctionCallExpression.builder() + .name(BddPeepholeVisitor.ITE) + .type(RuleRuntimeTypeMirror.STRING) + .addArgument(new LiteralBooleanExpression(true)) + .addArgument(ifTrue) + .addArgument(ifFalse) + .build(); + } + + private static RuleExpression coalesceBoolean(boolean defaultValue) { + return FunctionCallExpression.builder() + .name(BddPeepholeVisitor.COALESCE_BOOL) + .type(RuleRuntimeTypeMirror.BOOLEAN) + .addArgument(reference(NULLABLE_REF)) + .addArgument(new LiteralBooleanExpression(defaultValue)) + .build(); + } + + private static RuleExpression reference(String name) { + return VariableReferenceExpression.builder().variableName(name).build(); + } + + private static RegistryInfo register(String name) { + return new RegistryInfo(name, RuleRuntimeTypeMirror.STRING, null, true, null); + } + + private static int countOccurrences(String haystack, String needle) { + int count = 0; + int i = 0; + while ((i = haystack.indexOf(needle, i)) >= 0) { + count++; + i += needle.length(); + } + return count; + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/TokenizerTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/TokenizerTest.java deleted file mode 100644 index f9d14eb3076d..000000000000 --- a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules2/TokenizerTest.java +++ /dev/null @@ -1,62 +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.codegen.poet.rules2; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -class TokenizerTest { - - @Test - public void recognizesReferenceExpression() { - Tokenizer tokenizer = new Tokenizer("{foobar}"); - assertTrue(tokenizer.isReference()); - tokenizer.consumeReferenceAccess((n) -> assertEquals("foobar", n)); - assertTrue(tokenizer.atEof()); - } - - @Test - public void recognizesIndexedExpression() { - Tokenizer tokenizer = new Tokenizer("foobar[123]"); - assertTrue(tokenizer.isIndexedAccess()); - tokenizer.consumeIndexed((name, index) -> { - assertEquals("foobar", name); - assertEquals(123, index); - }); - assertTrue(tokenizer.atEof()); - } - - @Test - public void recognizesDirectIndexedExpression() { - Tokenizer tokenizer = new Tokenizer("[123]"); - assertTrue(tokenizer.isDirectIndexedAccess()); - tokenizer.consumeDirectIndexed(i -> assertEquals(123, i)); - assertTrue(tokenizer.atEof()); - } - - @Test - public void recognizesNamedAccessExpression() { - Tokenizer tokenizer = new Tokenizer("{url#authority}"); - assertTrue(tokenizer.isNamedAccess()); - tokenizer.consumeNamedAccess((reference, name) -> { - assertEquals("url", reference); - assertEquals("authority", name); - }); - assertTrue(tokenizer.atEof()); - } -} \ No newline at end of file diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelectorTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelectorTest.java new file mode 100644 index 000000000000..05a9b4a5cc77 --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpOperationSelectorTest.java @@ -0,0 +1,421 @@ +/* + * 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.codegen.poet.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; +import software.amazon.awssdk.codegen.model.intermediate.MemberModel; +import software.amazon.awssdk.codegen.model.intermediate.Metadata; +import software.amazon.awssdk.codegen.model.intermediate.OperationModel; +import software.amazon.awssdk.codegen.model.intermediate.ParameterHttpMapping; +import software.amazon.awssdk.codegen.model.intermediate.ShapeModel; +import software.amazon.awssdk.codegen.model.intermediate.VariableModel; +import software.amazon.awssdk.codegen.model.service.ContextParam; +import software.amazon.awssdk.codegen.model.service.Location; +import software.amazon.awssdk.codegen.poet.warmup.WarmUpOperationSelector; + +public class WarmUpOperationSelectorTest { + + @ParameterizedTest(name = "{0}") + @MethodSource("selectionScenarios") + public void selectsExpectedOperation(Scenario scenario) { + Optional selected = WarmUpOperationSelector.selectWarmUpOperation(scenario.model()); + + if (scenario.expected == null) { + assertThat(selected).isEmpty(); + } else { + assertThat(selected).map(OperationModel::getOperationName).contains(scenario.expected); + } + } + + private static Stream selectionScenarios() { + return Stream.of( + // Filter: streaming, event-stream and deprecated operations. + scenario("streamingInputOperationOnly_isNotSelected") + .operation(op("PutObject").withStreamingInput()) + .expectNothing(), + scenario("streamingOutputOperationOnly_isNotSelected") + .operation(op("GetObject").withStreamingOutput()) + .expectNothing(), + scenario("eventStreamInputOperationOnly_isNotSelected") + .operation(op("StartConversation").withEventStreamInput()) + .expectNothing(), + scenario("eventStreamOutputOperationOnly_isNotSelected") + .operation(op("SubscribeToShard").withEventStreamOutput()) + .expectNothing(), + scenario("deprecatedOperationOnly_isNotSelected") + .operation(op("OldListThings").deprecated()) + .expectNothing(), + scenario("serviceWithNoOperations_selectsNothing") + .expectNothing(), + + // Preference 1: returns output, so the unmarshaller is warmed too. An operation with no output shape + // (e.g. S3's DeleteBucket) can win every other tier and still lose here. + scenario("hasOutput_beatsVoidOutput_whenOtherwiseEqual") + .operation(op("ListThings").withOutput()) + .operation(op("ListOthers")) + .expect("ListThings"), + scenario("hasOutput_outranksVerifiedSimpleMethod") + .verifiedSimpleMethods("listThings") + .operation(op("ListThings")) + .operation(op("ListOthers").withOutput()) + .expect("ListOthers"), + scenario("hasOutput_outranksEmptyRequest") + .operation(op("ListThings")) + .operation(op("ListOthers").withOutput().withRequiredMembers(1)) + .expect("ListOthers"), + scenario("hasOutput_outranksFewestRequiredMembers") + .operation(op("ListThings").withRequiredMembers(1)) + .operation(op("ListOthers").withOutput().withRequiredMembers(2)) + .expect("ListOthers"), + scenario("hasOutput_outranksPreferredVerb") + .operation(op("ListThings")) + .operation(op("DescribeThings").withOutput()) + .expect("DescribeThings"), + scenario("hasOutput_outranksEveryOtherPreferenceCombined") + .verifiedSimpleMethods("deleteThings") + .operation(op("DeleteThings")) + .operation(op("ListOthers").withOutput().withRequiredMembers(1)) + .expect("ListOthers"), + + // Preference 2: is authenticated, so auth-scheme resolution is warmed too. Both operations have output so + // tier 1 ties. + scenario("authenticated_beatsNoAuth_whenOtherwiseEqual") + .operation(op("ListThings").withOutput()) + .operation(op("ListOthers").withOutput().withNoAuth()) + .expect("ListThings"), + scenario("authenticated_outranksVerifiedSimpleMethod") + .verifiedSimpleMethods("listOthers") + .operation(op("ListThings").withOutput()) + .operation(op("ListOthers").withOutput().withNoAuth()) + .expect("ListThings"), + + // Preference 3: verified simple method. Both operations have output and are authenticated, so tiers + // 1-2 tie. + scenario("verifiedSimpleMethod_beatsNonVerified_whenOtherwiseEqual") + .verifiedSimpleMethods("listThings") + .operation(op("ListThings").withOutput()) + .operation(op("ListOthers").withOutput()) + .expect("ListThings"), + scenario("verifiedSimpleMethod_outranksEmptyRequest") + .verifiedSimpleMethods("listThings") + .operation(op("ListThings").withOutput().withRequiredMembers(1)) + .operation(op("ListOthers").withOutput()) + .expect("ListThings"), + + // Preference 4: accepts an empty request. Both operations have output and are authenticated, and + // neither is verified simple, so tiers 1-3 tie. + scenario("emptyRequest_beatsRequiredMembers") + .operation(op("ListThings").withOutput()) + .operation(op("ListOthers").withOutput().withRequiredMembers(1)) + .expect("ListThings"), + + // Preference 5: fewest required input members. Both operations have output and require input, so + // tiers 1-4 tie. + scenario("fewerRequiredMembers_beatsMore_whenBothRequireInput") + .operation(op("ListThings").withOutput().withRequiredMembers(1)) + .operation(op("ListOthers").withOutput().withRequiredMembers(2)) + .expect("ListThings"), + + // Preference 6: read-only verb, List > Describe > Get. Fixtures are chosen so the alphabetical + // tie-break would pick the loser. + scenario("verb_listBeatsDescribe") + .operation(op("DescribeThings").withOutput()) + .operation(op("ListThings").withOutput()) + .expect("ListThings"), + scenario("verb_describeBeatsNonPreferred") + .operation(op("BatchThings").withOutput()) + .operation(op("DescribeThings").withOutput()) + .expect("DescribeThings"), + scenario("verb_getBeatsNonPreferred") + .operation(op("CountThings").withOutput()) + .operation(op("GetThings").withOutput()) + .expect("GetThings"), + scenario("verb_describeBeatsGet") + .operation(op("DescribeThings").withOutput()) + .operation(op("GetThings").withOutput()) + .expect("DescribeThings"), + + // Preference 7: alphabetical tie-break. + scenario("fullyTiedOperations_areBrokenAlphabetically") + .operation(op("BravoOperation").withOutput()) + .operation(op("AlphaOperation").withOutput()) + .expect("AlphaOperation"), + + scenario("dynamoDbWorkedExample_selectsListTables") + .verifiedSimpleMethods("listTables", "describeLimits") + .operation(op("ListTables").withOutput()) + .operation(op("DescribeLimits").withOutput()) + .operation(op("GetItem").withOutput().withRequiredMembers(2)) + .operation(op("PutItem").withRequiredMembers(2)) + .expect("ListTables"), + + // Hard gate: a required URI/endpoint-bound member is dummy-fillable only when it is a string. + scenario("requiredStringUriMember_isStillEligible") + .operation(op("GetThing").withOutput().withRequiredUriMember("ThingName", "String")) + .expect("GetThing"), + scenario("requiredNonStringUriMemberOnly_isNotSelected") + .operation(op("GetThing").withOutput().withRequiredUriMember("ThingVersion", "Integer")) + .expectNothing(), + scenario("requiredNonStringUriMember_fallsBackToNextBestOperation") + .operation(op("GetThing").withOutput().withRequiredUriMember("ThingVersion", "Integer")) + .operation(op("PutThing").withOutput().withRequiredMembers(2)) + .expect("PutThing"), + // A required string context param is dummy-fillable, so the operation stays eligible. + scenario("requiredContextParamMember_isStillEligible") + .operation(op("ListGrants").withOutput().withRequiredContextParamMember("AccountId", "String")) + .expect("ListGrants") + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("dummyValueScenarios") + public void membersRequiringDummyValue_returnsOnlyUriAndEndpointBoundRequiredMembers(DummyValueScenario scenario) { + List memberNames = WarmUpOperationSelector.membersRequiringDummyValue(scenario.operation).stream() + .map(MemberModel::getName) + .collect(Collectors.toList()); + assertThat(memberNames).containsExactlyElementsOf(scenario.expectedMemberNames); + } + + private static Stream dummyValueScenarios() { + return Stream.of( + new DummyValueScenario("requiredUriMember_needsDummy", + op("GetThing").withRequiredUriMember("ThingName", "String").build(), + Collections.singletonList("ThingName")), + new DummyValueScenario("requiredEndpointContextParamMember_needsDummy", + op("ListGrants").withRequiredContextParamMember("AccountId", "String").build(), + Collections.singletonList("AccountId")), + new DummyValueScenario("requiredBodyMember_staysNull", + op("ListThings").withRequiredMembers(2).build(), + Collections.emptyList()), + new DummyValueScenario("optionalUriMember_staysNull", + op("GetThing").withOptionalUriMember("ThingName", "String").build(), + Collections.emptyList()), + new DummyValueScenario("noInputShape_needsNothing", + op("ListThings").build(), + Collections.emptyList()) + ); + } + + private static final class DummyValueScenario { + private final String name; + private final OperationModel operation; + private final List expectedMemberNames; + + private DummyValueScenario(String name, OperationModel operation, List expectedMemberNames) { + this.name = name; + this.operation = operation; + this.expectedMemberNames = expectedMemberNames; + } + + @Override + public String toString() { + return name; + } + } + + private static Scenario scenario(String name) { + return new Scenario(name); + } + + private static OperationBuilder op(String operationName) { + return new OperationBuilder(operationName); + } + + private static final class Scenario { + private final String name; + private final List operations = new ArrayList<>(); + private List verifiedSimpleMethods = Collections.emptyList(); + private String expected; + + private Scenario(String name) { + this.name = name; + } + + private Scenario verifiedSimpleMethods(String... methodNames) { + this.verifiedSimpleMethods = Arrays.asList(methodNames); + return this; + } + + private Scenario operation(OperationBuilder operation) { + this.operations.add(operation.build()); + return this; + } + + private Scenario expect(String operationName) { + this.expected = operationName; + return this; + } + + private Scenario expectNothing() { + this.expected = null; + return this; + } + + private IntermediateModel model() { + Map operationsByName = new HashMap<>(); + for (OperationModel operation : operations) { + operationsByName.put(operation.getOperationName(), operation); + } + + CustomizationConfig config = CustomizationConfig.create(); + config.setVerifiedSimpleMethods(verifiedSimpleMethods); + + Metadata metadata = new Metadata().withServiceName("TestService"); + return new IntermediateModel(metadata, operationsByName, Collections.emptyMap(), config); + } + + @Override + public String toString() { + return name; + } + } + + private static final class OperationBuilder { + private final OperationModel operation = new OperationModel(); + + private OperationBuilder(String operationName) { + operation.setOperationName(operationName); + } + + private OperationBuilder withOutput() { + operation.setOutputShape(new ShapeModel()); + return this; + } + + private OperationBuilder withRequiredMembers(int requiredCount) { + ShapeModel shape = new ShapeModel(); + List members = new ArrayList<>(); + for (int i = 0; i < requiredCount; i++) { + MemberModel member = new MemberModel(); + member.setName("Member" + i); + member.setRequired(true); + members.add(member); + } + shape.setMembers(members); + operation.setInputShape(shape); + return this; + } + + private OperationBuilder withRequiredUriMember(String memberName, String simpleType) { + addMember(uriMember(memberName, simpleType, true)); + return this; + } + + private OperationBuilder withOptionalUriMember(String memberName, String simpleType) { + addMember(uriMember(memberName, simpleType, false)); + return this; + } + + private OperationBuilder withRequiredContextParamMember(String memberName, String simpleType) { + MemberModel member = member(memberName, simpleType, true); + member.setContextParam(new ContextParam()); + addMember(member); + return this; + } + + private OperationBuilder withStreamingInput() { + operation.setInputShape(streamingShape()); + return this; + } + + private OperationBuilder withStreamingOutput() { + operation.setOutputShape(streamingShape()); + return this; + } + + private OperationBuilder withEventStreamInput() { + operation.setInputShape(eventStreamShape()); + return this; + } + + private OperationBuilder withEventStreamOutput() { + operation.setOutputShape(eventStreamShape()); + return this; + } + + private OperationBuilder deprecated() { + operation.setDeprecated(true); + return this; + } + + private OperationBuilder withNoAuth() { + operation.setIsAuthenticated(false); + return this; + } + + private OperationModel build() { + return operation; + } + + private void addMember(MemberModel member) { + ShapeModel shape = operation.getInputShape(); + if (shape == null) { + shape = new ShapeModel(); + shape.setMembers(new ArrayList<>()); + operation.setInputShape(shape); + } + shape.getMembers().add(member); + } + + private static MemberModel uriMember(String memberName, String simpleType, boolean required) { + MemberModel member = member(memberName, simpleType, required); + ParameterHttpMapping http = new ParameterHttpMapping(); + http.setLocation(Location.URI); + member.setHttp(http); + return member; + } + + private static MemberModel member(String memberName, String simpleType, boolean required) { + MemberModel member = new MemberModel(); + member.setName(memberName); + member.setRequired(required); + member.setVariable(new VariableModel(memberName, simpleType)); + return member; + } + + private static ShapeModel streamingShape() { + ShapeModel shape = new ShapeModel(); + shape.setHasStreamingMember(true); + return shape; + } + + private static ShapeModel eventStreamShape() { + ShapeModel eventStreamShape = new ShapeModel(); + eventStreamShape.withIsEventStream(true); + + MemberModel member = new MemberModel(); + member.setShape(eventStreamShape); + + ShapeModel shape = new ShapeModel(); + shape.setMembers(Collections.singletonList(member)); + return shape; + } + } +} diff --git a/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpecTest.java b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpecTest.java new file mode 100644 index 000000000000..d1f9145d39cd --- /dev/null +++ b/codegen/src/test/java/software/amazon/awssdk/codegen/poet/warmup/WarmUpProviderSpecTest.java @@ -0,0 +1,82 @@ +/* + * 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.codegen.poet.warmup; + +import static org.hamcrest.MatcherAssert.assertThat; +import static software.amazon.awssdk.codegen.poet.PoetMatchers.generatesTo; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.codegen.poet.ClassSpec; +import software.amazon.awssdk.codegen.poet.ClientTestModels; +import software.amazon.awssdk.codegen.poet.warmup.WarmUpProviderSpec; + +public class WarmUpProviderSpecTest { + + @Test + public void warmUpProvider_queryProtocol_generatesSyncAndAsyncClients() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.queryServiceModels()); + assertThat(spec, generatesTo("warmup-provider-query.java")); + } + + @Test + public void warmUpProvider_whenSyncClientSkipped_generatesAsyncClientOnly() { + ClassSpec spec = new WarmUpProviderSpec( + ClientTestModels.queryServiceModelWithSpecialCustomization("customization-skip-sync.config")); + assertThat(spec, generatesTo("warmup-provider-async-only.java")); + } + + @Test + public void warmUpProvider_restJsonProtocol_usesJsonCannedResponse() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.restJsonServiceModels()); + assertThat(spec, generatesTo("warmup-provider-rest-json.java")); + } + + @Test + public void warmUpProvider_restXmlProtocol_usesXmlCannedResponse() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.xmlServiceModels()); + assertThat(spec, generatesTo("warmup-provider-xml.java")); + } + + @Test + public void warmUpProvider_smithyRpcV2CborProtocol_usesEmptyCborMapCannedResponse() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.rpcv2ServiceModels()); + assertThat(spec, generatesTo("warmup-provider-rpcv2.java")); + } + + @Test + public void warmUpProvider_cborProtocol_usesEmptyCborMapCannedResponse() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.cborServiceModels()); + assertThat(spec, generatesTo("warmup-provider-cbor.java")); + } + + @Test + public void warmUpProvider_bearerAuthService_setsDummyTokenProvider() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.bearerAuthServiceModels()); + assertThat(spec, generatesTo("warmup-provider-bearer-auth.java")); + } + + @Test + public void warmUpProvider_endpointDiscoveryService_disablesEndpointDiscovery() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.endpointDiscoveryModels()); + assertThat(spec, generatesTo("warmup-provider-endpoint-discovery.java")); + } + + @Test + public void warmUpProvider_requiredEndpointBoundMember_getsDummyValue() { + ClassSpec spec = new WarmUpProviderSpec(ClientTestModels.serviceS3Control()); + assertThat(spec, generatesTo("warmup-provider-s3control.java")); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java index 8fc91e2069fe..a39463292122 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-default-params.java @@ -36,6 +36,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java index 37a202d5ee3a..96769a75478d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/ops-auth-sigv4a-value-auth-scheme-params.java @@ -31,6 +31,14 @@ static Builder builder() { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java index 8d4589400e62..67ae1b14f8e5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-default-params.java @@ -47,6 +47,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public QueryAuthSchemeParams.Builder toBuilder() { return new Builder(this); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java index b726c4a81e09..40dff2b6c01b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-auth-scheme-params.java @@ -45,6 +45,14 @@ static Builder builder() { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns a {@link Builder} to customize the parameters. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java index 87eaf93e4db4..90787b2a7359 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-with-allowlist.java @@ -73,6 +73,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java index ee65f8d60da4..dc56b5a01cae 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-default-params-without-allowlist.java @@ -81,6 +81,11 @@ public Region region() { return region; } + @Override + public String regionId() { + return region == null ? null : region.id(); + } + @Override public RegionSet regionSet() { return regionSet; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java index 4ac1f03ed9e3..ae925b907d34 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-with-allowlist.java @@ -66,6 +66,14 @@ static Builder fromEndpointParams(QueryEndpointParams endpointParams) { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java index b583bd4c120d..9ac4afccd3ed 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/auth/scheme/query-endpoint-auth-params-auth-scheme-params-without-allowlist.java @@ -59,6 +59,14 @@ static Builder fromEndpointParams(QueryEndpointParams endpointParams) { */ Region region(); + /** + * Returns the region ID as a string. Returns null if region is not set. + */ + default String regionId() { + Region region = region(); + return region == null ? null : region.id(); + } + /** * Returns the RegionSet. The regionSet parameter may be used with the "aws.auth#sigv4a" auth scheme. */ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java index 1b7d802857d9..b6301bb1d629 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-bearer-auth-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.json; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -14,14 +16,20 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; @@ -29,12 +37,14 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -90,20 +100,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson") - .serviceProfileProperty("json_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson").serviceProfileProperty("json_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } 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 cdba2ca0888c..da14d53a1e07 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 @@ -1,9 +1,11 @@ package software.amazon.awssdk.services.json; +import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.MyServiceHttpConfig; import software.amazon.MyServiceRetryPolicy; @@ -16,9 +18,13 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin1; import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin2; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; @@ -27,9 +33,11 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; @@ -38,14 +46,16 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonClientContextParams; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -186,20 +196,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson") - .serviceProfileProperty("json_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson").serviceProfileProperty("json_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); SdkClientConfiguration clientConfig = config; builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); 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 0fe341a73bca..dd5b5f9ff3af 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 @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.query; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -16,7 +18,11 @@ import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode; import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; @@ -25,9 +31,11 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme; import software.amazon.awssdk.http.auth.aws.signer.RegionSet; @@ -37,13 +45,15 @@ import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; import software.amazon.awssdk.services.query.endpoints.QueryClientContextParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -105,20 +115,60 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(AwsClientOption.ACCOUNT_ID_ENDPOINT_MODE, resolveAccountIdEndpointMode(config)); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_QUERY_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlQuery") - .serviceProfileProperty("query_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_QUERY_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlQuery") + .serviceProfileProperty("query_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + QueryEndpointParams endpointParams = QueryEndpointParams.builder().region(region) + .useDualStack(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + QueryEndpointParams endpointParams = QueryEndpointParams.builder().region(region) + .useDualStack(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); SdkClientConfiguration clientConfig = config; builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java index e5d1cf583c58..d4a7d48d2b92 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-internal-defaults-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.json; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -12,26 +14,34 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; /** * Internal base class for {@link DefaultJsonClientBuilder} and {@link DefaultJsonAsyncClientBuilder}. @@ -67,6 +77,7 @@ protected final SdkClientConfiguration mergeInternalDefaults(SdkClientConfigurat c.option(SdkClientOption.INTERNAL_USER_AGENT, "md/foobar"); c.option(SdkClientOption.DEFAULT_RETRY_MODE, RetryMode.STANDARD); c.option(SdkClientOption.DEFAULT_NEW_RETRIES_2026, true); + c.option(SdkClientOption.DEFAULT_ENABLE_SOCKET_TIMEOUT_2026, true); }); } @@ -92,20 +103,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson") - .serviceProfileProperty("json_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson").serviceProfileProperty("json_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } 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 168c15a64e31..71f969a5ba7f 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 @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.json; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -14,7 +16,11 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; @@ -23,9 +29,11 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; @@ -34,13 +42,15 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonClientContextParams; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -109,20 +119,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.SERVICE_CONFIGURATION, finalServiceConfig); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson") - .serviceProfileProperty("json_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson").serviceProfileProperty("json_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); SdkClientConfiguration clientConfig = config; builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-env-bearer-token-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-env-bearer-token-client-builder-class.java index 615f6a76d1a5..d8b7056db198 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-env-bearer-token-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-env-bearer-token-client-builder-class.java @@ -1,5 +1,6 @@ package software.amazon.awssdk.services.json; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -16,16 +17,22 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; @@ -33,13 +40,15 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.internal.EnvironmentTokenSystemSettings; import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -107,20 +116,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson") - .serviceProfileProperty("json_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_JSON_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlJson").serviceProfileProperty("json_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + JsonEndpointParams endpointParams = JsonEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java index 2e5198dac4b6..0d4a53a08dd2 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-service-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.h2; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -12,14 +14,20 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.ProtocolNegotiation; import software.amazon.awssdk.http.SdkHttpConfigurationOption; @@ -29,13 +37,15 @@ import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.h2.auth.scheme.H2AuthSchemeProvider; +import software.amazon.awssdk.services.h2.endpoints.H2EndpointParams; import software.amazon.awssdk.services.h2.endpoints.H2EndpointProvider; import software.amazon.awssdk.services.h2.internal.H2ServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; /** * Internal base class for {@link DefaultH2ClientBuilder} and {@link DefaultH2AsyncClientBuilder}. @@ -87,20 +97,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2") - .serviceProfileProperty("h2_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2").serviceProfileProperty("h2_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java index 80d554e50d1f..8939c3ba4c34 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-h2-usePriorKnowledgeForH2-service-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.h2; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -12,14 +14,20 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.SdkHttpConfigurationOption; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; @@ -28,13 +36,15 @@ import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.h2.auth.scheme.H2AuthSchemeProvider; +import software.amazon.awssdk.services.h2.endpoints.H2EndpointParams; import software.amazon.awssdk.services.h2.endpoints.H2EndpointProvider; import software.amazon.awssdk.services.h2.internal.H2ServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; /** * Internal base class for {@link DefaultH2ClientBuilder} and {@link DefaultH2AsyncClientBuilder}. @@ -86,20 +96,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2") - .serviceProfileProperty("h2_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2").serviceProfileProperty("h2_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-multi-auth-sigv4a-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-multi-auth-sigv4a-client-builder-class.java index fcc5f72b4e25..f1a2db7b4795 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-multi-auth-sigv4a-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-multi-auth-sigv4a-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.database; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -12,14 +14,20 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme; import software.amazon.awssdk.http.auth.aws.signer.RegionSet; @@ -28,12 +36,14 @@ import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider; +import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointParams; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider; import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; /** * Internal base class for {@link DefaultDatabaseClientBuilder} and {@link DefaultDatabaseAsyncClientBuilder}. @@ -86,20 +96,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") - .serviceProfileProperty("database_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") + .serviceProfileProperty("database_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java index 5da93144892e..cdc499c42158 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-ops-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.database; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -14,14 +16,20 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; @@ -30,12 +38,14 @@ import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider; +import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointParams; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider; import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -96,20 +106,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") - .serviceProfileProperty("database_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") + .serviceProfileProperty("database_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java index 05f0b72afa2b..93536d8160fb 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-auth-service-client-builder-class.java @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.database; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -12,24 +14,32 @@ import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider; +import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointParams; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider; import software.amazon.awssdk.services.database.internal.DatabaseServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; /** * Internal base class for {@link DefaultDatabaseClientBuilder} and {@link DefaultDatabaseAsyncClientBuilder}. @@ -78,20 +88,56 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") - .serviceProfileProperty("database_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_DATABASE_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlDatabase") + .serviceProfileProperty("database_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + DatabaseEndpointParams endpointParams = DatabaseEndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); return builder.build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-region-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-region-client-builder-class.java new file mode 100644 index 000000000000..81951f9927ec --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-no-region-client-builder-class.java @@ -0,0 +1,284 @@ +package software.amazon.awssdk.services.query; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.TokenUtils; +import software.amazon.awssdk.auth.token.credentials.aws.DefaultAwsTokenProvider; +import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver; +import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; +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; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.interceptor.ClasspathInterceptorChainFactory; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; +import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; +import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; +import software.amazon.awssdk.identity.spi.IdentityProvider; +import software.amazon.awssdk.identity.spi.IdentityProviders; +import software.amazon.awssdk.identity.spi.TokenIdentity; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; +import software.amazon.awssdk.services.query.endpoints.QueryClientContextParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder; +import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +/** + * Internal base class for {@link DefaultQueryClientBuilder} and {@link DefaultQueryAsyncClientBuilder}. + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +abstract class DefaultQueryBaseClientBuilder, C> extends AwsDefaultClientBuilder { + private final Map> additionalAuthSchemes = new HashMap<>(); + + @Override + protected final String serviceEndpointPrefix() { + return "query-service"; + } + + @Override + protected final String serviceName() { + return "Query"; + } + + @Override + protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) { + return config.merge(c -> { + c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider()) + .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config)) + .option(SdkClientOption.AUTH_SCHEMES, authSchemes()) + .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false) + .lazyOption(AwsClientOption.TOKEN_PROVIDER, + p -> TokenUtils.toSdkTokenProvider(p.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER))) + .option(AwsClientOption.TOKEN_IDENTITY_PROVIDER, defaultTokenProvider()); + }); + } + + @Override + protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + List endpointInterceptors = new ArrayList<>(); + ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory(); + List interceptors = interceptorFactory + .getInterceptors("software/amazon/awssdk/services/query/execution.interceptors"); + List additionalInterceptors = new ArrayList<>(); + interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors); + interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors); + interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS)); + SdkClientConfiguration.Builder builder = config.toBuilder(); + builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> { + IdentityProviders.Builder result = IdentityProviders.builder(); + IdentityProvider tokenIdentityProvider = c.get(AwsClientOption.TOKEN_IDENTITY_PROVIDER); + if (tokenIdentityProvider != null) { + result.putIdentityProvider(tokenIdentityProvider); + } + IdentityProvider credentialsIdentityProvider = c.get(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER); + if (credentialsIdentityProvider != null) { + result.putIdentityProvider(credentialsIdentityProvider); + } + return result.build(); + }); + builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); + builder.option(SdkClientOption.CLIENT_CONTEXT_PARAMS, clientContextParams.build()); + builder.lazyOptionIfAbsent( + SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_QUERY_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlQuery") + .serviceProfileProperty("query_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + QueryEndpointParams endpointParams = QueryEndpointParams.builder().build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent(AwsClientOption.SIGNING_REGION, c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + return region; + }); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); + return builder.build(); + } + + @Override + protected final String signingName() { + return "query-service"; + } + + private QueryEndpointProvider defaultEndpointProvider() { + return QueryEndpointProvider.defaultProvider(); + } + + public B authSchemeProvider(QueryAuthSchemeProvider authSchemeProvider) { + clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider); + return thisBuilder(); + } + + private QueryAuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) { + AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)).build(); + List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference(); + if (!preferences.isEmpty()) { + return QueryAuthSchemeProvider.defaultProvider(preferences); + } + return QueryAuthSchemeProvider.defaultProvider(); + } + + @Override + public B putAuthScheme(AuthScheme authScheme) { + additionalAuthSchemes.put(authScheme.schemeId(), authScheme); + return thisBuilder(); + } + + private Map> authSchemes() { + Map> schemes = new HashMap<>(3 + this.additionalAuthSchemes.size()); + AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create(); + schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme); + BearerAuthScheme bearerAuthScheme = BearerAuthScheme.create(); + schemes.put(bearerAuthScheme.schemeId(), bearerAuthScheme); + NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create(); + schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme); + schemes.putAll(this.additionalAuthSchemes); + 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(); + } + + public B stringContextParam(String stringContextParam) { + clientContextParams.put(QueryClientContextParams.STRING_CONTEXT_PARAM, stringContextParam); + return thisBuilder(); + } + + private IdentityProvider defaultTokenProvider() { + return DefaultAwsTokenProvider.create(); + } + + @Override + protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) { + List internalPlugins = internalPlugins(config); + List externalPlugins = plugins(); + if (internalPlugins.isEmpty() && externalPlugins.isEmpty()) { + return config; + } + List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins); + SdkClientConfiguration.Builder configuration = config.toBuilder(); + QueryServiceClientConfigurationBuilder serviceConfigBuilder = new QueryServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + 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/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java index db0dae50266e..360ef4e77c36 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 @@ -1,10 +1,12 @@ package software.amazon.awssdk.services.query; +import java.net.URI; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -16,7 +18,11 @@ import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode; import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; @@ -25,9 +31,11 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; 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.interceptor.ClasspathInterceptorChainFactory; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.scheme.BearerAuthScheme; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; @@ -35,13 +43,15 @@ import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.identity.spi.TokenIdentity; -import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; +import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; import software.amazon.awssdk.services.query.endpoints.QueryClientContextParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.services.query.internal.QueryServiceClientConfigurationBuilder; import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Validate; /** @@ -103,20 +113,60 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon builder.option(AwsClientOption.ACCOUNT_ID_ENDPOINT_MODE, resolveAccountIdEndpointMode(config)); builder.lazyOptionIfAbsent( SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - c -> AwsClientEndpointProvider - .builder() - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_QUERY_SERVICE") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlQuery") - .serviceProfileProperty("query_service") - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol("https") - .region(c.get(AwsClientOption.AWS_REGION)) - .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(c.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT, - 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()); + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_QUERY_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlQuery") + .serviceProfileProperty("query_service").profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + QueryEndpointParams endpointParams = QueryEndpointParams.builder().region(region) + .useDualStack(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + QueryEndpointParams endpointParams = QueryEndpointParams.builder().region(region) + .useDualStack(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); SdkClientConfiguration clientConfig = config; builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-read-write-timeout-service-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-read-write-timeout-service-client-builder-class.java new file mode 100644 index 000000000000..765fa5789e03 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-read-write-timeout-service-client-builder-class.java @@ -0,0 +1,250 @@ +package software.amazon.awssdk.services.h2; + +import java.net.URI; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.auth.AuthSchemePreferenceResolver; +import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +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.interceptor.ClasspathInterceptorChainFactory; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.http.Protocol; +import software.amazon.awssdk.http.ProtocolNegotiation; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; +import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; +import software.amazon.awssdk.identity.spi.IdentityProvider; +import software.amazon.awssdk.identity.spi.IdentityProviders; +import software.amazon.awssdk.protocols.json.internal.unmarshall.SdkClientJsonProtocolAdvancedOption; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.h2.auth.scheme.H2AuthSchemeProvider; +import software.amazon.awssdk.services.h2.endpoints.H2EndpointParams; +import software.amazon.awssdk.services.h2.endpoints.H2EndpointProvider; +import software.amazon.awssdk.services.h2.internal.H2ServiceClientConfigurationBuilder; +import software.amazon.awssdk.utils.AttributeMap; +import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.CompletableFutureUtils; + +/** + * Internal base class for {@link DefaultH2ClientBuilder} and {@link DefaultH2AsyncClientBuilder}. + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +abstract class DefaultH2BaseClientBuilder, C> extends AwsDefaultClientBuilder { + private final Map> additionalAuthSchemes = new HashMap<>(); + + @Override + protected final String serviceEndpointPrefix() { + return "h2-service"; + } + + @Override + protected final String serviceName() { + return "H2"; + } + + @Override + protected final SdkClientConfiguration mergeServiceDefaults(SdkClientConfiguration config) { + return config.merge(c -> { + c.option(SdkClientOption.ENDPOINT_PROVIDER, defaultEndpointProvider()) + .option(SdkClientOption.AUTH_SCHEME_PROVIDER, defaultAuthSchemeProvider(config)) + .option(SdkClientOption.AUTH_SCHEMES, authSchemes()) + .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false); + }); + } + + @Override + protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + List endpointInterceptors = new ArrayList<>(); + ClasspathInterceptorChainFactory interceptorFactory = new ClasspathInterceptorChainFactory(); + List interceptors = interceptorFactory + .getInterceptors("software/amazon/awssdk/services/h2/execution.interceptors"); + List additionalInterceptors = new ArrayList<>(); + interceptors = CollectionUtils.mergeLists(endpointInterceptors, interceptors); + interceptors = CollectionUtils.mergeLists(interceptors, additionalInterceptors); + interceptors = CollectionUtils.mergeLists(interceptors, config.option(SdkClientOption.EXECUTION_INTERCEPTORS)); + SdkClientConfiguration.Builder builder = config.toBuilder(); + builder.lazyOption(SdkClientOption.IDENTITY_PROVIDERS, c -> { + IdentityProviders.Builder result = IdentityProviders.builder(); + IdentityProvider credentialsIdentityProvider = c.get(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER); + if (credentialsIdentityProvider != null) { + result.putIdentityProvider(credentialsIdentityProvider); + } + return result.build(); + }); + builder.option(SdkClientOption.EXECUTION_INTERCEPTORS, interceptors); + builder.lazyOptionIfAbsent( + SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + c -> { + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_H2_SERVICE") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlH2").serviceProfileProperty("h2_service") + .profileFile(c.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(c.get(SdkClientOption.PROFILE_NAME)).resolveFromOverrides(); + if (overrideEndpoint.isPresent()) { + return ClientEndpointProvider.create(overrideEndpoint.get(), true); + } + URI clientEndpointUri = null; + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + clientEndpointUri = endpoint.url(); + } catch (Exception e) { + // Endpoint resolution failed. This is expected for services with required parameters + // beyond region, dualstack, and FIPS. Use a placeholder that will be replaced at request time. + return ClientEndpointProvider.create(URI.create("https://localhost"), false); + } + if (clientEndpointUri.getHost() == null) { + throw SdkClientException.create("Configured region (" + region + ") resulted in an invalid URI: " + + clientEndpointUri + ". This is usually caused by an invalid region configuration."); + } + return ClientEndpointProvider.create(clientEndpointUri, false); + }); + builder.lazyOptionIfAbsent( + AwsClientOption.SIGNING_REGION, + c -> { + Region region = c.get(AwsClientOption.AWS_REGION); + try { + H2EndpointParams endpointParams = H2EndpointParams.builder().region(region).build(); + Endpoint endpoint = CompletableFutureUtils.joinLikeSync(defaultEndpointProvider().resolveEndpoint( + endpointParams)); + List authSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + if (authSchemes != null && !authSchemes.isEmpty()) { + EndpointAuthScheme firstScheme = authSchemes.get(0); + if (firstScheme instanceof SigV4AuthScheme) { + String signingRegion = ((SigV4AuthScheme) firstScheme).signingRegion(); + if (signingRegion != null) { + return Region.of(signingRegion); + } + } + } + } catch (Exception e) { + // Endpoint resolution failed. Fall back to using the client region as signing region. + } + return region; + }); + builder.option(SdkClientJsonProtocolAdvancedOption.ENABLE_FAST_UNMARSHALLER, true); + return builder.build(); + } + + @Override + protected final String signingName() { + return "h2-service"; + } + + private H2EndpointProvider defaultEndpointProvider() { + return H2EndpointProvider.defaultProvider(); + } + + public B authSchemeProvider(H2AuthSchemeProvider authSchemeProvider) { + clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER, authSchemeProvider); + return thisBuilder(); + } + + private H2AuthSchemeProvider defaultAuthSchemeProvider(SdkClientConfiguration config) { + AuthSchemePreferenceResolver authSchemePreferenceProvider = AuthSchemePreferenceResolver.builder() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)).build(); + List preferences = authSchemePreferenceProvider.resolveAuthSchemePreference(); + if (!preferences.isEmpty()) { + return H2AuthSchemeProvider.defaultProvider(preferences); + } + return H2AuthSchemeProvider.defaultProvider(); + } + + @Override + public B putAuthScheme(AuthScheme authScheme) { + additionalAuthSchemes.put(authScheme.schemeId(), authScheme); + return thisBuilder(); + } + + private Map> authSchemes() { + Map> schemes = new HashMap<>(2 + this.additionalAuthSchemes.size()); + AwsV4AuthScheme awsV4AuthScheme = AwsV4AuthScheme.create(); + schemes.put(awsV4AuthScheme.schemeId(), awsV4AuthScheme); + NoAuthAuthScheme noAuthAuthScheme = NoAuthAuthScheme.create(); + schemes.put(noAuthAuthScheme.schemeId(), noAuthAuthScheme); + schemes.putAll(this.additionalAuthSchemes); + return schemes; + } + + @Override + protected final AttributeMap serviceHttpConfig() { + AttributeMap result = AttributeMap.empty(); + return result.merge(AttributeMap.builder().put(SdkHttpConfigurationOption.PROTOCOL, Protocol.HTTP2) + .put(SdkHttpConfigurationOption.PROTOCOL_NEGOTIATION, ProtocolNegotiation.ALPN) + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, Duration.ofMillis(900000L)).build()); + } + + @Override + protected SdkClientConfiguration invokePlugins(SdkClientConfiguration config) { + List internalPlugins = internalPlugins(config); + List externalPlugins = plugins(); + if (internalPlugins.isEmpty() && externalPlugins.isEmpty()) { + return config; + } + List plugins = CollectionUtils.mergeLists(internalPlugins, externalPlugins); + SdkClientConfiguration.Builder configuration = config.toBuilder(); + H2ServiceClientConfigurationBuilder serviceConfigBuilder = new H2ServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + private List internalPlugins(SdkClientConfiguration config) { + return Collections.emptyList(); + } + + protected static void validateClientOptions(SdkClientConfiguration c) { + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/internalconfig/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/internalconfig/customization.config index 594a4aceb54d..f37cc8509cb1 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/internalconfig/customization.config +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/internalconfig/customization.config @@ -4,5 +4,6 @@ }, "userAgent": "md/foobar", "defaultRetryMode": "STANDARD", - "defaultNewRetries2026": "true" + "defaultNewRetries2026": "true", + "defaultEnableSocketTimeout2026": "true" } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/customization.config new file mode 100644 index 000000000000..17d6c2306501 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/customization.config @@ -0,0 +1,3 @@ +{ + "presignedUrlExtensionSupported": true +} \ No newline at end of file diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/service-2.json new file mode 100644 index 000000000000..cfeb496ac347 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/presignedurl/service-2.json @@ -0,0 +1,62 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2010-05-08", + "endpointPrefix": "json-service-endpoint", + "globalEndpoint": "json-service.amazonaws.com", + "protocol": "json", + "serviceAbbreviation": "Json Service", + "serviceFullName": "Some Service That Uses AWS Json Protocol", + "serviceId": "Json Service", + "signingName": "json-service", + "signatureVersion": "v4", + "uid": "json-service-2010-05-08", + "xmlNamespace": "https://json-service.amazonaws.com/doc/2010-05-08/" + }, + "operations": { + "APostOperation": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "APostOperationRequest" + }, + "errors": [ + { + "shape": "InvalidInputException" + } + ], + "documentation": "

Performs a post operation to the query service and has no output

" + } + }, + "shapes": { + "APostOperationRequest": { + "type": "structure", + "required": [ + "StringMember" + ], + "members": { + "StringMember": { + "shape": "String", + "documentation": "

String member

" + } + } + }, + "InvalidInputException": { + "type": "structure", + "members": { + "message": { + "shape": "String" + } + }, + "documentation": "

The request was rejected because an invalid or out-of-range value was supplied for an input parameter.

", + "exception": true + }, + "String": { + "type": "string" + } + }, + "documentation": "A service that is implemented using the json protocol" +} \ No newline at end of file diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config new file mode 100644 index 000000000000..2c63c0851048 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/customization.config @@ -0,0 +1,2 @@ +{ +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json new file mode 100644 index 000000000000..bfc38318e6a0 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-rule-set.json @@ -0,0 +1,57 @@ +{ + "version": "1.0", + "parameters": { + "region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint", + "type": "string" + }, + "useFIPSEndpoint": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "type": "boolean" + } + }, + "rules": [ + { + "documentation": "Root rule: region is declared but never referenced in any rule", + "type": "tree", + "conditions": [], + "rules": [ + { + "documentation": "If endpoint override is set, use it directly", + "conditions": [ + { + "fn": "isSet", + "argv": [{"ref": "Endpoint"}] + } + ], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "Default endpoint without using region", + "conditions": [], + "endpoint": { + "url": "https://query.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ] + } + ] +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json new file mode 100644 index 000000000000..3ce5aaf4f010 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/endpoint-tests.json @@ -0,0 +1 @@ +{"testCases": []} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json new file mode 100644 index 000000000000..4182ad4d5d9c --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/service-2.json @@ -0,0 +1,471 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2010-05-08", + "endpointPrefix": "query-service", + "globalEndpoint": "query-service.amazonaws.com", + "protocol": "query", + "serviceAbbreviation": "Query Service", + "serviceFullName": "Some Service That Uses Query Protocol", + "serviceId":"Query Service", + "signatureVersion": "v4", + "uid": "query-service-2010-05-08", + "xmlNamespace": "https://query-service.amazonaws.com/doc/2010-05-08/" + }, + "clientContextParams": { + "booleanContextParam": { + "type": "boolean", + "documentation": "A boolean client context parameter" + }, + "stringContextParam": { + "type": "string", + "documentation": "a string client context parameter" + } + }, + "operations": { + "OperationWithContextParam": { + "name": "OperationWithContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithContextParam"} + }, + "OperationWithOperationContextParam": { + "name": "OperationWithOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "operationContextParams":{ + "customEndpointArray":{"path":"ListMember.StringList[*].LeafString"} + }, + "input":{"shape":"WithOperationContextParam"} + }, + "OperationWithCustomizedOperationContextParam": { + "name": "OperationWithCustomizedOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithOperationContextParam"} + }, + "OperationWithMapOperationContextParam": { + "name": "OperationWithMapOperationContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "operationContextParams":{ + "arnList":{"path":"keys(RequestMap)"} + }, + "input":{"shape":"WithMapOperationContextParam"} + }, + "OperationWithStaticContextParams": { + "name": "OperationWithStaticContextParams", + "http": { + "method": "POST", + "requestUri": "/" + }, + "staticContextParams": { + "staticStringParam" : { + "value": "hello" + } + } + }, + "OperationWithChecksumRequired": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "httpChecksumRequired": true + }, + "OperationWithNoneAuthType": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "authtype": "none" + }, + "OperationWithRequestCompression": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "requestcompression": { + "encodings": ["gzip"] + } + }, + "OperationWithCustomMember": { + "name": "OperationWithCustomMember", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input":{"shape":"WithCustomMember"} + }, + "APostOperation": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "endpoint": { + "hostPrefix": "foo-" + }, + "input": { + "shape": "APostOperationRequest" + }, + "errors": [ + { + "shape": "InvalidInputException" + } + ], + "documentation": "

Performs a post operation to the query service and has no output

" + }, + "APostOperationWithOutput": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "APostOperationWithOutputRequest" + }, + "output": { + "shape": "APostOperationWithOutputResponse", + "resultWrapper": "APostOperationWithOutputResult" + }, + "errors": [ + { + "shape": "InvalidInputException" + } + ], + "documentation": "

Performs a post operation to the query service and has modelled output

" + }, + "BearerAuthOperation": { + "name": "BearerAuthOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "BearerAuthOperationRequest" + }, + "authtype": "bearer" + }, + "StreamingInputOperation": { + "name": "StreamingInputOperation", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/streamingInputOperation" + }, + "input": { + "shape": "StructureWithStreamingMember" + }, + "documentation": "Some operation with a streaming input" + }, + "StreamingOutputOperation": { + "name": "StreamingOutputOperation", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/streamingOutputOperation" + }, + "output": { + "shape": "StructureWithStreamingMember" + }, + "documentation": "Some operation with a streaming output" + }, + "PutOperationWithChecksum":{ + "name":"PutOperationWithChecksum", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructureWithStreaming"}, + "output":{"shape":"ChecksumStructureWithStreaming"}, + "httpChecksum" : { + "requestValidationModeMember": "ChecksumMode", + "responseAlgorithms": ["CRC32C", "CRC32", "CRC64NVME", "MD5", "SHA1", "SHA256", "SHA512", "XXHASH64", "XXHASH3", "XXHASH128"] + } + }, + "GetOperationWithChecksum":{ + "name":"GetOperationWithChecksum", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructure"}, + "output":{"shape":"ChecksumStructure"}, + "httpChecksum" : { + "requestChecksumRequired": true, + "requestAlgorithmMember": "ChecksumAlgorithm" + } + } + }, + "shapes": { + "WithContextParam": { + "type": "structure", + "members": { + "StringMember" : { + "shape": "String", + "contextParam": { + "name": "operationContextParam" + } + }, + "IntegerMember": { + "shape": "Integer" + }, + "DoubleMember": { + "shape": "Double" + }, + "NestedMember": { + "shape": "ChecksumStructure" + } + } + }, + "WithCustomMember": { + "type": "structure", + "members": { + "StringMemberToBeUpdate" : { + "shape": "String" + }, + "StringMember": { + "shape": "String" + } + } + }, + "WithOperationContextParam": { + "type": "structure", + "members": { + "ListMember":{ + "shape":"ListMember" + } + } + }, + "WithMapOperationContextParam": { + "type": "structure", + "members": { + "OperationWithMapOperationContextParam":{ + "shape":"RequestMap" + } + } + }, + "RequestMap":{ + "type":"map", + "key":{"shape":"LeafString"}, + "value":{"shape":"AttributeValue"} + }, + "AttributeValue": { + "type": "structure", + "members": { + "S": { + "shape": "LeafString" + } + } + }, + "ListMember":{ + "type":"structure", + "members":{ + "Strings":{ + "shape":"StringList" + }, + "StringParam":{ + "shape":"String" + } + }, + "documentation":"

Container for the objects to delete.

" + }, + "StringList":{ + "type":"list", + "member":{"shape":"LeafNode"}, + "flattened":true + }, + "LeafNode":{ + "type":"structure", + "members":{ + "LeafString":{ + "shape":"LeafString" + } + }, + "documentation":"" + }, + "LeafString":{ + "type":"string" + }, + "APostOperationRequest": { + "type": "structure", + "required": [ + "SomeNestedMember" + ], + "members": { + "SomeNestedMember": { + "shape": "NestedMember", + "documentation": "

a member that has nested members

" + }, + "OptionalMember": { + "shape": "dateType", + "documentation": "

An optional member

" + } + } + }, + "APostOperationWithOutputRequest": { + "type": "structure", + "required": [ + "SomeNestedMember" + ], + "members": { + "SomeNestedMember": { + "shape": "NestedMember", + "documentation": "

a member that has nested members

" + }, + "OptionalMember": { + "shape": "dateType", + "documentation": "

An optional member

" + } + } + }, + "APostOperationWithOutputResponse": { + "type": "structure", + "required": [ + "NestedMember" + ], + "members": { + "NestedMember": { + "shape": "NestedMember", + "documentation": "

A structure containing nested members

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

Contains the response to a successful APostOperationWithOutput request.

" + }, + "InvalidInputException": { + "type": "structure", + "members": { + "message": { + "shape": "invalidInputMessage" + } + }, + "documentation": "

The request was rejected because an invalid or out-of-range value was supplied for an input parameter.

", + "error": { + "code": "InvalidInput", + "httpStatusCode": 400, + "senderFault": true + }, + "exception": true + }, + "NestedMember": { + "type": "structure", + "required": [ + "SubMember", + "CreateDate" + ], + "members": { + "SubMember": { + "shape": "subMember", + "documentation": "

A sub-member

" + }, + "CreateDate": { + "shape": "dateType", + "documentation": "

The date and time, in ISO 8601 date-time format, when the member was created.

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

A shape with nested sub-members" + }, + "subMember": { + "type": "string", + "max": 63, + "min": 3, + "pattern": "^[a-z0-9](([a-z0-9]|-(?!-))*[a-z0-9])?$" + }, + "dateType": { + "type": "timestamp" + }, + "invalidInputMessage": { + "type": "string" + }, + "StreamType": { + "type": "blob", + "streaming": true + }, + "StructureWithStreamingMember": { + "type": "structure", + "members": { + "StreamingMember": { + "shape": "StreamType", + "documentation": "This be a stream" + } + }, + "payload": "StreamingMember" + }, + "ChecksumAlgorithm":{ + "type":"string", + "enum":[ + "CRC32", + "CRC32C", + "CRC64NVME", + "MD5", + "SHA1", + "SHA256", + "SHA512", + "XXHASH64", + "XXHASH3", + "XXHASH128" + ] + }, + "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" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-sdk-checksum-algorithm" + } + }, + "payload":"Body" + }, + "Body":{"type":"blob"}, + "ChecksumStructure":{ + "type":"structure", + "members":{ + "Body":{"shape":"Body"}, + "ChecksumMode":{ + "shape":"ChecksumMode", + "location":"header", + "locationName":"x-amz-checksum-mode" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-sdk-checksum-algorithm" + } + }, + "payload":"Body" + }, + "String":{"type":"string"}, + "Integer":{"type":"integer"}, + "Double":{"type":"double"}, + "BearerAuthOperationRequest": { + "type": "structure", + "members": { + } + } + }, + "documentation": "A service that is implemented using the query protocol" +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json new file mode 100644 index 000000000000..1b0a71e59472 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query-delegating-root/waiters-2.json @@ -0,0 +1,80 @@ +{ + "version": 2, + "waiters": { + "PostOperationSuccess": { + "delay": 1, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "expected": 200, + "matcher": "status", + "state": "success" + }, + { + "state": "retry", + "matcher": "status", + "expected": 404 + }, + { + "matcher": "pathAny", + "expected": "baz", + "argument": "foo.bar", + "state": "success" + } + ] + }, + "FloatValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 42.5, + "argument": "FloatValue", + "state": "success" + } + ] + }, + "BigDecimalValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 123132.81289319837183771465876127837183719837123, + "argument": "BigDecimalValue", + "state": "success" + } + ] + }, + "LongValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 9223372036854775807, + "argument": "LongValue", + "state": "success" + } + ] + }, + "DoubleValueTest": { + "delay": 15, + "operation": "APostOperation", + "maxAttempts": 40, + "acceptors": [ + { + "matcher": "path", + "expected": 1.7976931348623157E308, + "argument": "DoubleValue", + "state": "success" + } + ] + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-skip-sync.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-skip-sync.config new file mode 100644 index 000000000000..a76859089932 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/customization-skip-sync.config @@ -0,0 +1,3 @@ +{ + "skipSyncClientGeneration": true +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-complement.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-complement.json new file mode 100644 index 000000000000..78e80db96af1 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-complement.json @@ -0,0 +1,55 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [{ "ref": "Region" }] + }, + { + "fn": "isSet", + "argv": [{ "ref": "Endpoint" }] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://service.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Region is required when Endpoint is not set", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "root": 3, + "nodeCount": 3, + "nodes": "/////wAAAAH/////AAAAAAX14QEF9eECAAAAAQX14QP////+" +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-default-regional.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-default-regional.json new file mode 100644 index 000000000000..a05255ae456e --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-default-regional.json @@ -0,0 +1,302 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "stringContextParam": { + "required": false, + "documentation": "A client context parameter, so the cache key compares it early as reference-stable.", + "type": "string" + }, + "staticStringParam": { + "required": false, + "documentation": "Bound to a per-operation static literal.", + "type": "string" + }, + "operationContextParam": { + "required": false, + "documentation": "Bound to a request member, so it can change per request.", + "type": "string" + }, + "arnList": { + "required": false, + "documentation": "Read only as arnList[0], so the cache key compares just the first element.", + "type": "stringArray" + }, + "customEndpointArray": { + "required": false, + "documentation": "Read as a whole, so the cache key compares every element.", + "type": "stringArray" + }, + "unusedParam": { + "required": false, + "documentation": "Declared but read by no condition and no result, so the cache key must leave it out.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + "aws-us-gov", + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "stringContextParam" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "staticStringParam" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "operationContextParam" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "customEndpointArray" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arnList" + }, + "[0]" + ], + "assign": "FirstArn" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "arnList" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "customEndpointArray" + }, + "[1]" + ], + "assign": "SecondEndpoint" + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 22, + "nodeCount": 22, + "nodes": "/////wAAAAH/////AAAABAX14QIF9eEDAAAAAgX14QEAAAACAAAABgX14QQF9eEFAAAABQAAAAQF9eEFAAAABwX14QYF9eEHAAAABQAAAAYF9eEIAAAABAAAAAUAAAAHAAAAAwAAAAgF9eEMAAAABgX14QkF9eEKAAAABAAAAAoF9eELAAAAAwAAAAsF9eEMAAAAAgAAAAkAAAAMAAAAAQAAAA0F9eEMAAAAAAAAAAMAAAAOAAAACAAAABEAAAARAAAACQAAABIAAAASAAAACgAAABMAAAATAAAACwAAABQAAAAUAAAADAAAAA8AAAAPAAAADQAAABAAAAAQAAAADgAAABUAAAAV" +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-s3.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-s3.json new file mode 100644 index 000000000000..3f427f9c104f --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-bdd-s3.json @@ -0,0 +1,2551 @@ +{ + "version": "1.1", + "parameters": { + "Bucket": { + "required": false, + "documentation": "The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "ForcePathStyle": { + "builtIn": "AWS::S3::ForcePathStyle", + "required": true, + "default": false, + "documentation": "When true, force a path-style endpoint to be used where the bucket name is part of the path.", + "type": "boolean" + }, + "Accelerate": { + "builtIn": "AWS::S3::Accelerate", + "required": true, + "default": false, + "documentation": "When true, use S3 Accelerate. NOTE: Not all regions support S3 accelerate.", + "type": "boolean" + }, + "UseGlobalEndpoint": { + "builtIn": "AWS::S3::UseGlobalEndpoint", + "required": true, + "default": false, + "documentation": "Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.", + "type": "boolean" + }, + "UseObjectLambdaEndpoint": { + "required": false, + "documentation": "Internal parameter to use object lambda endpoint for an operation (eg: WriteGetObjectResponse)", + "type": "boolean" + }, + "Key": { + "required": false, + "documentation": "The S3 Key used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Key.", + "type": "string" + }, + "Prefix": { + "required": false, + "documentation": "The S3 Prefix used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Prefix.", + "type": "string" + }, + "CopySource": { + "required": false, + "documentation": "The Copy Source used for Copy Object request. This is an optional parameter that will be set automatically for operations that are scoped to Copy Source.", + "type": "string" + }, + "DisableAccessPoints": { + "required": false, + "documentation": "Internal parameter to disable Access Point Buckets", + "type": "boolean" + }, + "DisableMultiRegionAccessPoints": { + "builtIn": "AWS::S3::DisableMultiRegionAccessPoints", + "required": true, + "default": false, + "documentation": "Whether multi-region access points (MRAP) should be disabled.", + "type": "boolean" + }, + "UseArnRegion": { + "builtIn": "AWS::S3::UseArnRegion", + "required": false, + "documentation": "When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN's region when constructing the endpoint instead of the client's configured region.", + "type": "boolean" + }, + "UseS3ExpressControlEndpoint": { + "required": false, + "documentation": "Internal parameter to indicate whether S3Express operation should use control plane, (ex. CreateBucket)", + "type": "boolean" + }, + "DisableS3ExpressSessionAuth": { + "required": false, + "documentation": "Parameter to indicate whether S3Express session auth should be disabled", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "Accelerate" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Bucket" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 6, + true + ] + }, + "" + ] + }, + "--x-s3" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 7, + true + ] + }, + "" + ] + }, + "--xa-s3" + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "partitionResult" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 7, + true + ], + "assign": "accessPointSuffix" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "accessPointSuffix" + }, + "--op-s3" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 8, + 12, + true + ], + "assign": "regionPrefix" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 32, + 49, + true + ], + "assign": "outpostId_ssa_2" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 49, + 50, + true + ], + "assign": "hardwareType" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "ForcePathStyle" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "ite", + "argv": [ + { + "ref": "UseDualStack" + }, + ".dualstack", + "" + ], + "assign": "_s3e_ds" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_2" + }, + false + ] + }, + { + "fn": "ite", + "argv": [ + { + "ref": "UseFIPS" + }, + "-fips", + "" + ], + "assign": "_s3e_fips" + }, + { + "fn": "ite", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "DisableS3ExpressSessionAuth" + }, + false + ] + }, + "sigv4", + "sigv4-s3express" + ], + "assign": "_s3e_auth" + }, + { + "fn": "aws.isVirtualHostableS3Bucket", + "argv": [ + { + "ref": "Bucket" + }, + false + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "url" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseS3ExpressControlEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "aws.isVirtualHostableS3Bucket", + "argv": [ + { + "ref": "Bucket" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "url" + }, + "scheme" + ] + }, + "http" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "Region" + }, + false + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "Bucket" + } + ], + "assign": "bucketArn" + }, + { + "fn": "getAttr", + "argv": [ + { + "fn": "split", + "argv": [ + { + "ref": "Bucket" + }, + "--", + 0 + ] + }, + "[-2]" + ], + "assign": "s3expressAvailabilityZoneId" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 4, + false + ] + }, + "" + ] + }, + "arn:" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 16, + 18, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "url" + }, + "isIp" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 21, + 23, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 27, + 29, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "regionPrefix" + }, + "beta" + ] + }, + { + "fn": "uriEncode", + "argv": [ + { + "ref": "Bucket" + } + ], + "assign": "uri_encoded_bucket" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "Region" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseObjectLambdaEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[0]" + ], + "assign": "arnType" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "accesspoint" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[1]" + ], + "assign": "accessPointName_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 14, + 16, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "hardwareType" + }, + "e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "hardwareType" + }, + "o" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-global" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 19, + 21, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3-object-lambda" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "DisableAccessPoints" + }, + false + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3-outposts" + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ], + "assign": "bucketPartition" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 26, + 28, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 15, + 17, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[4]" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 20, + 22, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseGlobalEndpoint" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[1]" + ], + "assign": "outpostId_ssa_1" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseArnRegion" + }, + true + ] + }, + true + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_1" + }, + false + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[2]" + ], + "assign": "outpostType" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketPartition" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "DisableMultiRegionAccessPoints" + }, + true + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "partition" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[3]" + ], + "assign": "accessPointName_ssa_2" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "outpostType" + }, + "accesspoint" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_2" + }, + false + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Accelerate cannot be used with FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "Cannot set dual-stack in combination with a custom endpoint.", + "type": "error" + }, + { + "conditions": [], + "error": "A custom endpoint cannot be combined with FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "A custom endpoint cannot be combined with S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3Express does not support S3 Accelerate.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "S3Express bucket name is not a valid virtual hostable name.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control{_s3e_fips}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3express{_s3e_fips}-{s3expressAvailabilityZoneId}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Unrecognized S3Express bucket name format.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control{_s3e_fips}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Expected a endpoint to be specified but no endpoint was found", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.ec2.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.ec2.s3-outposts.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.op-{outpostId_ssa_2}.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.op-{outpostId_ssa_2}.s3-outposts.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Unrecognized hardware type: \"Expected hardware type o or e but got {hardwareType}\"", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Outposts Bucket alias - it must be a valid bucket name.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`.", + "type": "error" + }, + { + "conditions": [], + "error": "Custom endpoint `{Endpoint}` was not a valid URI", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Accelerate cannot be used in this region", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid region: region was not a valid DNS name.", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Object Lambda does not support Dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Object Lambda does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Access points are not supported for this operation", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Missing account id", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{accessPointName_ssa_1}-{bucketArn#accountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-object-lambda-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-object-lambda.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", + "type": "error" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: bucket ARN is missing a region", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `{arnType}`", + "type": "error" + }, + { + "conditions": [], + "error": "Access Points do not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint-fips.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{accessPointName_ssa_1}-{bucketArn#accountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the S3 service, found: {bucketArn#service}", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: Multi-Region Access Point ARNs are disabled.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}.accesspoint.s3-global.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but bucket referred to partition `{bucketArn#partition}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Access Point Name", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support Dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Arn: Outpost Access Point ARN contains sub resources", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_2}-{bucketArn#accountId}.{outpostId_ssa_1}.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_2}-{bucketArn#accountId}.{outpostId_ssa_1}.s3-outposts.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName_ssa_2}`", + "type": "error" + }, + { + "conditions": [], + "error": "Expected an outpost type `accesspoint`, found {outpostType}", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: expected an access point name", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected a 4-component resource", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `{outpostId_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The Outpost Id was not set", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Unrecognized format: {Bucket} (type: {arnType})", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: No ARN type specified", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: `{Bucket}` was not a valid ARN", + "type": "error" + }, + { + "conditions": [], + "error": "Path-style addressing cannot be used with ARN buckets", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Path-style addressing cannot be used with S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-object-lambda-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-object-lambda.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "A region must be set when sending requests to S3.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 553, + "nodes": "/////wAAAAH/////AAAAAAAAAAMF9eFzAAAAAQAAAagAAAAEAAAAAgAAARAAAAAFAAAAAwAAAOkAAAAGAAAABAAAAFUAAAAHAAAABQAAAA8AAAAIAAAACAAAAAkF9eFzAAAAEAAAAAoAAAANAAAAEgAAAAsAAAANAAAAEwAAAAwAAAANAAAAFgX14Q4AAAANAAAAIwAAAA4F9eEqAAAAJAX14WcAAAGzAAAABgAAAQ8AAAAQAAAABwAAAQ4AAAARAAAACAAAABMAAAASAAAADgAAAfUAAABqAAAACQAAABQAAAAYAAAACgAAABUAAAAYAAAACwAAABYAAAAYAAAADAAAABcAAAAYAAAADQAAAiMAAAAYAAAADgAAAE0AAAAZAAAAFAAAAEkAAAAaAAAAGgAAABsAAABOAAAAJQAAABwF9eFWAAAAJgX14VYAAAAdAAAAJwAAAC8AAAAeAAAAMAX14ToAAAAfAAAAMgAAACAF9eFVAAAAMwAAACEAAACIAAAANwX14UwAAAAiAAAAOwAAACMF9eFUAAAAPAAAACcAAAAkAAAAPQAAACUF9eFTAAAAPgAAACYAAACSAAAAPwAAACkF9eEuAAAAPQAAACgF9eFTAAAAPgAAACkAAACWAAAAQAAAACoF9eE2AAAAQgAAACsF9eE1AAAARgAAACwF9eE0AAAARwAAAC0F9eFRAAAASQAAAC4F9eFQAAAASgX14U4F9eFPAAAAKAAAADAF9eE5AAAAKQX14TkAAAAxAAAAKgAAALkAAAAyAAAAMAAAAD4AAAAzAAAAMQX14S0AAAA0AAAAMwAAADUAAAIOAAAAPAAAADgAAAA2AAAAPgX14TcAAAA3AAAAPwAAADkF9eEuAAAAPgX14TcAAAA5AAAAQAAAADoF9eE2AAAAQgAAADsF9eE1AAAARQAAADwF9eFBAAAARgAAAD0F9eE0AAAASAX14UAF9eEzAAAAMQX14S0AAAA/AAAAMwAAAEAAAAIOAAAAPAAAAEMAAABBAAAAPgX14TcAAABCAAAAPwAAAEQF9eEuAAAAPgX14TcAAABEAAAAQAAAAEUF9eE2AAAAQgAAAEYF9eE1AAAARAX14S8AAABHAAAARgAAAEgF9eE0AAAASAX14TIF9eEzAAAAGQAAAEoF9eEqAAAALgX14ScAAABLAAAAOQAAAEwF9eEpAAAAOgX14SgF9eEpAAAAGgX14VgAAABOAAAAHAX14VcAAABPAAAAIgAAAFIAAABQAAAAIwAAAFEAAAIhAAAAJAX14WcF9eFzAAAALgX14WEAAABTAAAAOQAAAFQF9eFjAAAAOgX14WIF9eFjAAAABQAAAGUAAABWAAAACAAAAFcF9eFzAAAAEAAAAFgAAABZAAAAEgAAAFsAAABZAAAAEwAAAFoAAABcAAAAFQAAAGEAAABfAAAAEwAAAF0AAABcAAAAFQAAAGIAAABfAAAAFQAAAGEAAABeAAAAFgX14Q4AAABfAAAAIwAAAGAF9eEqAAAAJAX14WcF9eEqAAAAFgX14Q0AAABiAAAAIwAAAGMF9eEqAAAAJAX14WUAAABkAAAALgX14W4F9eFvAAAABgAAANYAAABmAAAABwAAANAAAABnAAAACAAAAHcAAABoAAAADgAAAHYAAABpAAAAFQAAAGoF9eEXAAAAGgAAAGsAAAH2AAAAJQAAAGwF9eFWAAAAJgX14VYAAABtAAAAJwAAAHAAAABuAAAAMAX14ToAAABvAAAAMgAAAIgF9eFVAAAAKAAAAHEF9eE5AAAAKQX14TkAAAByAAAAKgAAAHMAAAH0AAAAMAX14TgAAAB0AAAANAAAAHUF9eFIAAAAQQX14UUF9eFIAAAAFQAAAfUF9eEXAAAACQAAAHgAAAB8AAAACgAAAHkAAAB8AAAACwAAAHoAAAB8AAAADAAAAHsAAAB8AAAADQAAAMoAAAB8AAAADgAAAMMAAAB9AAAAFAAAAL4AAAB+AAAAFQAAAH8F9eEXAAAAFwAAAIAAAACBAAAAGAAAAL0AAACBAAAAGgAAAIIAAADFAAAAJQAAAIMF9eFWAAAAJgX14VYAAACEAAAAJwAAAJ8AAACFAAAAMAX14ToAAACGAAAAMgAAAIcF9eFVAAAAMwAAAI0AAACIAAAANwX14UwAAACJAAAAOwAAAIoF9eFUAAAAPAX14VMAAACLAAAAPQAAAIwF9eFTAAAAPwX14VMF9eEuAAAANwX14UwAAACOAAAAOwAAAI8F9eFUAAAAPAAAAJQAAACQAAAAPQAAAJEF9eFTAAAAPgAAAJMAAACSAAAAPwAAAJYF9eEuAAAAPwAAAJkF9eEuAAAAPQAAAJUF9eFTAAAAPgAAAJkAAACWAAAAQAAAAJcF9eE2AAAAQgAAAJgF9eE1AAAARgX14VIF9eE0AAAAQAAAAJoF9eE2AAAAQgAAAJsF9eE1AAAARgAAAJwF9eE0AAAARwAAAJ0F9eFRAAAASQAAAJ4F9eFQAAAASgX14U0F9eFPAAAAKAAAAKAF9eE5AAAAKQX14TkAAAChAAAAKgAAALkAAACiAAAAMAAAAK4AAACjAAAAMQX14S0AAACkAAAAMwAAAKUAAAIOAAAAPAAAAKgAAACmAAAAPgX14TcAAACnAAAAPwAAAKkF9eEuAAAAPgX14TcAAACpAAAAQAAAAKoF9eE2AAAAQgAAAKsF9eE1AAAARQAAAKwF9eFBAAAARgAAAK0F9eE0AAAASAX14T8F9eEzAAAAMQX14S0AAACvAAAAMwAAALAAAAIOAAAAPAAAALMAAACxAAAAPgX14TcAAACyAAAAPwAAALQF9eEuAAAAPgX14TcAAAC0AAAAQAAAALUF9eE2AAAAQgAAALYF9eE1AAAARAX14S8AAAC3AAAARgAAALgF9eE0AAAASAX14TAF9eEzAAAAMAX14TgAAAC6AAAANAAAALsF9eFIAAAAQQX14UUAAAC8AAAAQwX14UYF9eFHAAAAGQX14SQF9eEqAAAAFQAAAL8F9eEXAAAAGQAAAMAF9eEqAAAAHgAAAMIAAADBAAAALgX14SIF9eEkAAAALgX14SEF9eEjAAAAFQAAAMQF9eEXAAAAGgX14VgAAADFAAAAHAX14VcAAADGAAAAIgAAAMkAAADHAAAAIwAAAMgAAAIhAAAAJAX14WUF9eFzAAAALgX14V8F9eFgAAAAEQAAAMsF9eEWAAAAFAAAAMwF9eEVAAAAFQAAAM0AAAImAAAAIQAAAM4AAAImAAAALAX14RAAAADPAAAALQX14RIF9eEUAAAACAAAANEAAADXAAAAEAAAANIAAADcAAAAEgAAANMAAADcAAAAEwAAANQAAADgAAAAFAAAANUAAADjAAAAFQAAAOcAAAGRAAAACAAAANoAAADXAAAAEwAAANgF9eEJAAAAFAAAANkAAADjAAAAFQAAAOcF9eEJAAAAEAAAANsAAADcAAAAEgAAAN8AAADcAAAAEwAAAN0AAADgAAAAFAAAAN4AAADjAAAAFQAAAOcF9eEMAAAAEwAAAOIAAADgAAAAFAAAAOEF9eEJAAAAFQX14QkF9eEMAAAAFAAAAOYAAADjAAAAFQAAAOQF9eEJAAAAHgAAAOUF9eEJAAAAIgX14QcF9eEJAAAAFQAAAOcAAAGfAAAAHgAAAOgF9eEIAAAAIgX14QcF9eEIAAAABAX14QIAAADqAAAABQAAAOsAAAHgAAAABgAAAQ8AAADsAAAABwAAAQ4AAADtAAAACAAAAO4AAAHrAAAACQAAAO8AAADzAAAACgAAAPAAAADzAAAACwAAAPEAAADzAAAADAAAAPIAAADzAAAADQAAAiMAAADzAAAADgAAAQoAAAD0AAAAFAAAAQgAAAD1AAAAGgAAAPYAAAELAAAAJQAAAPcF9eFWAAAAJgX14VYAAAD4AAAAJwAAAPkAAAIGAAAAKAAAAPoF9eE5AAAAKQX14TkAAAD7AAAAKgAAAhoAAAD8AAAAMAX14SsAAAD9AAAAMQX14S0AAAD+AAAAMwAAAP8AAAIOAAAAPAAAAQIAAAEAAAAAPgX14TcAAAEBAAAAPwAAAQMF9eEuAAAAPgX14TcAAAEDAAAAQAAAAQQF9eE2AAAAQgAAAQUF9eE1AAAARQAAAQYF9eFBAAAARgAAAQcF9eE0AAAASAX14T4F9eEzAAAAGQAAAQkF9eEqAAAALgX14R8F9eEgAAAAGgX14VgAAAELAAAAHAX14VcAAAEMAAAAIgAAAQ0AAAIgAAAALgX14V0F9eFeAAAACAAAAY0F9eEJAAAACAAAAZcF9eEJAAAAAwAAAVoAAAERAAAABAX14QMAAAESAAAABQAAARwAAAETAAAACAAAARQF9eFzAAAADwX14QUAAAEVAAAAEAAAARYAAAEZAAAAEgAAARcAAAEZAAAAEwAAARgAAAEZAAAAFgX14Q4AAAEZAAAAIwAAARoF9eEqAAAAJAX14WYAAAEbAAAALgX14WoF9eFrAAAABgAAAZUAAAEdAAAABwAAAYsAAAEeAAAACAAAAScAAAEfAAAADgAAAfUAAAEgAAAAGgAAASEAAAH2AAAAJQAAASIF9eFWAAAAJgX14VYAAAEjAAAAJwAAASQAAAEzAAAAKAAAASUF9eE5AAAAKQX14TkAAAEmAAAAKgAAAU8AAAH0AAAACQAAASgAAAEsAAAACgAAASkAAAEsAAAACwAAASoAAAEsAAAADAAAASsAAAEsAAAADQAAAYoAAAEsAAAADgAAAVMAAAEtAAAADwX14QUAAAEuAAAAFAAAAVEAAAEvAAAAGgAAATAAAAFVAAAAJQAAATEF9eFWAAAAJgX14VYAAAEyAAAAJwAAATUAAAEzAAAAMAX14ToAAAE0AAAAMgX14UoF9eFVAAAAKAAAATYF9eE5AAAAKQX14TkAAAE3AAAAKgAAAU8AAAE4AAAAMAAAAUQAAAE5AAAAMQX14S0AAAE6AAAAMwAAATsAAAIOAAAAPAAAAT4AAAE8AAAAPgX14TcAAAE9AAAAPwAAAT8F9eEuAAAAPgX14TcAAAE/AAAAQAAAAUAF9eE2AAAAQgAAAUEF9eE1AAAARQAAAUIF9eFBAAAARgAAAUMF9eE0AAAASAX14T0F9eEzAAAAMQX14S0AAAFFAAAAMwAAAUYAAAIOAAAAPAAAAUkAAAFHAAAAPgX14TcAAAFIAAAAPwAAAUoF9eEuAAAAPgX14TcAAAFKAAAAQAAAAUsF9eE2AAAAQgAAAUwF9eE1AAAARAX14S8AAAFNAAAARgAAAU4F9eE0AAAASAX14TEF9eEzAAAAMAX14TgAAAFQAAAANAX14UMF9eFIAAAAGQAAAVIF9eEqAAAALgX14RsF9eEcAAAADwX14QUAAAFUAAAAGgX14VgAAAFVAAAAHAX14VcAAAFWAAAAIgAAAVkAAAFXAAAAIwAAAVgAAAIhAAAAJAX14WYF9eFzAAAALgX14VsF9eFcAAAABAX14QIAAAFbAAAABQAAAWUAAAFcAAAACAAAAV0F9eFzAAAADwX14QUAAAFeAAAAEAAAAV8AAAFiAAAAEgAAAWAAAAFiAAAAEwAAAWEAAAFiAAAAFgX14Q4AAAFiAAAAIwAAAWMF9eEqAAAAJAX14SsAAAFkAAAALgX14WgF9eFpAAAABgAAAZUAAAFmAAAABwAAAYsAAAFnAAAACAAAAWgAAAHrAAAACQAAAWkAAAFtAAAACgAAAWoAAAFtAAAACwAAAWsAAAFtAAAADAAAAWwAAAFtAAAADQAAAYoAAAFtAAAADgAAAYUAAAFuAAAADwX14QUAAAFvAAAAFAAAAYMAAAFwAAAAGgAAAXEAAAGHAAAAJQAAAXIF9eFWAAAAJgX14VYAAAFzAAAAJwAAAXQAAAIGAAAAKAAAAXUF9eE5AAAAKQX14TkAAAF2AAAAKgAAAhoAAAF3AAAAMAX14SsAAAF4AAAAMQX14S0AAAF5AAAAMwAAAXoAAAIOAAAAPAAAAX0AAAF7AAAAPgX14TcAAAF8AAAAPwAAAX4F9eEuAAAAPgX14TcAAAF+AAAAQAAAAX8F9eE2AAAAQgAAAYAF9eE1AAAARQAAAYEF9eFBAAAARgAAAYIF9eE0AAAASAX14TwF9eEzAAAAGQAAAYQF9eEqAAAALgX14RkF9eEaAAAADwX14QUAAAGGAAAAGgX14VgAAAGHAAAAHAX14VcAAAGIAAAAIgAAAYkAAAIgAAAALgX14VkF9eFaAAAADwX14QUAAAIjAAAACAAAAYwF9eEJAAAADwX14QUAAAGNAAAAEAAAAY4AAAGaAAAAEgAAAY8AAAGaAAAAEwAAAZAAAAGaAAAAFAAAAZEF9eEJAAAAGwAAAZIF9eEMAAAAHQX14QsAAAGTAAAAHwX14QsAAAGUAAAAIAX14QsAAAGmAAAACAAAAZYF9eEJAAAADwX14QUAAAGXAAAAEAAAAZgAAAGaAAAAEgAAAZkAAAGaAAAAEwAAAZsAAAGaAAAAFAX14QwF9eEJAAAAFAAAAZ4AAAGcAAAAFgAAAZ0F9eEJAAAAIgX14QoF9eEJAAAAFgAAAaAAAAGfAAAAGwAAAaMF9eEMAAAAGwAAAaIAAAGhAAAAIgX14QoF9eEMAAAAIgX14QoAAAGjAAAAKwX14QsAAAGkAAAALwX14QsAAAGlAAAANQX14QsAAAGmAAAANgX14QsAAAGnAAAAOAX14QsF9eEMAAAAAgX14QEAAAGpAAAAAwAAAd4AAAGqAAAABAX14QQAAAGrAAAABQAAAbYAAAGsAAAACAAAAa0F9eFzAAAAEAAAAa4AAAGxAAAAEgAAAa8AAAGxAAAAEwAAAbAAAAGxAAAAFgX14Q4AAAGxAAAAIwAAAbIF9eEqAAAAJAX14SwAAAGzAAAALgX14XAAAAG0AAAAOQAAAbUF9eFyAAAAOgX14XEF9eFyAAAABgX14QYAAAG3AAAABwX14QYAAAG4AAAACAAAAcIAAAG5AAAADgAAAfUAAAG6AAAAGgAAAbsAAAH2AAAAJQAAAbwF9eFWAAAAJgX14VYAAAG9AAAAJwAAAb4AAAHRAAAAKAAAAb8F9eE5AAAAKQX14TkAAAHAAAAAKgAAAdcAAAHBAAAAMAX14SwAAAH0AAAACQAAAcMAAAHHAAAACgAAAcQAAAHHAAAACwAAAcUAAAHHAAAADAAAAcYAAAHHAAAADQAAAiMAAAHHAAAADgAAAdkAAAHIAAAADwAAAcwAAAHJAAAAFAAAAcoAAAHNAAAAGQAAAcsF9eEqAAAALgX14SUF9eEmAAAAFAAAAhwAAAHNAAAAGgAAAc4AAAHaAAAAJQAAAc8F9eFWAAAAJgX14VYAAAHQAAAAJwAAAdMAAAHRAAAAMAX14ToAAAHSAAAAMgX14UsF9eFVAAAAKAAAAdQF9eE5AAAAKQX14TkAAAHVAAAAKgAAAdcAAAHWAAAAMAX14SwAAAIMAAAAMAX14SwAAAHYAAAANAX14UQF9eFIAAAAGgX14VgAAAHaAAAAHAX14VcAAAHbAAAAIgX14WQAAAHcAAAAIwAAAd0AAAIhAAAAJAX14SwF9eFzAAAABAX14QIAAAHfAAAABQAAAegAAAHgAAAACAAAAeEF9eFzAAAAEAAAAeIAAAHlAAAAEgAAAeMAAAHlAAAAEwAAAeQAAAHlAAAAFgX14Q4AAAHlAAAAIwAAAeYF9eEqAAAAJAX14SsAAAHnAAAALgX14WwF9eFtAAAABgX14QYAAAHpAAAABwX14QYAAAHqAAAACAAAAfcAAAHrAAAADgAAAfUAAAHsAAAAGgAAAe0AAAH2AAAAJQAAAe4F9eFWAAAAJgX14VYAAAHvAAAAJwAAAfAAAAIGAAAAKAAAAfEF9eE5AAAAKQX14TkAAAHyAAAAKgAAAhoAAAHzAAAAMAX14SsAAAH0AAAAMQX14S0AAAIOAAAAGgX14VgAAAH2AAAAHAX14VcF9eFzAAAACQAAAfgAAAH8AAAACgAAAfkAAAH8AAAACwAAAfoAAAH8AAAADAAAAfsAAAH8AAAADQAAAiMAAAH8AAAADgAAAh0AAAH9AAAADwAAAgEAAAH+AAAAFAAAAf8AAAICAAAAGQAAAgAF9eEqAAAALgX14R0F9eEeAAAAFAAAAhwAAAICAAAAGgAAAgMAAAIeAAAAJQAAAgQF9eFWAAAAJgX14VYAAAIFAAAAJwAAAggAAAIGAAAAMAX14ToAAAIHAAAAMgX14UkF9eFVAAAAKAAAAgkF9eE5AAAAKQX14TkAAAIKAAAAKgAAAhoAAAILAAAAMAX14SsAAAIMAAAAMQX14S0AAAINAAAAMwAAAhEAAAIOAAAAPAX14TcAAAIPAAAAPgX14TcAAAIQAAAAPwX14TcF9eEuAAAAPAAAAhQAAAISAAAAPgX14TcAAAITAAAAPwAAAhUF9eEuAAAAPgX14TcAAAIVAAAAQAAAAhYF9eE2AAAAQgAAAhcF9eE1AAAARQAAAhgF9eFBAAAARgAAAhkF9eE0AAAASAX14TsF9eEzAAAAMAX14SsAAAIbAAAANAX14UIF9eFIAAAAGQX14RgF9eEqAAAAGgX14VgAAAIeAAAAHAX14VcAAAIfAAAAIgX14WQAAAIgAAAAIwAAAiIAAAIhAAAAJAX14SoF9eFzAAAAJAX14SsF9eFzAAAAEQAAAiQF9eEWAAAAFAAAAiUF9eEVAAAAIQAAAigAAAImAAAALAX14REAAAInAAAALQX14RMF9eEUAAAALAX14Q8AAAIpAAAALQX14Q8F9eEU" +} \ No newline at end of file diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-default-regional.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-default-regional.json new file mode 100644 index 000000000000..6c3b34e6e15f --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-default-regional.json @@ -0,0 +1,369 @@ +{ + "version": "1.0", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "stringContextParam": { + "required": false, + "documentation": "A client context parameter, so the cache key compares it early as reference-stable.", + "type": "string" + }, + "staticStringParam": { + "required": false, + "documentation": "Bound to a per-operation static literal.", + "type": "string" + }, + "operationContextParam": { + "required": false, + "documentation": "Bound to a request member, so it can change per request.", + "type": "string" + }, + "arnList": { + "required": false, + "documentation": "Read only as arnList[0], so the cache key compares just the first element.", + "type": "stringArray" + }, + "customEndpointArray": { + "required": false, + "documentation": "Read as a whole, so the cache key compares every element.", + "type": "stringArray" + }, + "unusedParam": { + "required": false, + "documentation": "Declared but read by no condition and no result, so the cache key must leave it out.", + "type": "string" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://query-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "endpoint": { + "url": "https://query.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://query.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ] +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-no-region.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-no-region.json new file mode 100644 index 000000000000..14d83691d85a --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set-no-region.json @@ -0,0 +1,54 @@ +{ + "version": "1.2", + "serviceId": "query", + "parameters": { + "Endpoint": { + "type": "string", + "builtIn": "SDK::Endpoint", + "documentation": "Override the endpoint used to send this request" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + } + ], + "endpoint": { + "url": "{endpoint}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1", + "signingName": "query-service" + } + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query-service.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1", + "signingName": "query-service" + } + ] + } + }, + "type": "endpoint" + } + ] +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set.json index d8325b0153b3..1bf94fa14a4e 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-rule-set.json @@ -416,10 +416,20 @@ } ], "assign": "ParsedArn" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn" + }, + "resourceId[0]" + ], + "assign": "ArnResourceId" } ], "endpoint": { - "url": "https://{endpointId}.query.{partitionResult#dualStackDnsSuffix}", + "url": "https://{ArnResourceId}.{endpointId}.query.{partitionResult#dualStackDnsSuffix}", "properties": { "authSchemes": [ { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-tests-no-region.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-tests-no-region.json new file mode 100644 index 000000000000..727e21bb016f --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/endpoint-tests-no-region.json @@ -0,0 +1,14 @@ +{ + "testCases": [ + { + "documentation": "Default endpoint", + "params": {}, + "expect": { + "endpoint": { + "url": "https://query-service.us-east-1.amazonaws.com" + } + } + } + ], + "version": "1.0" +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3-test/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3-test/customization.config index 4dee2d9e88d9..7751264d4325 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3-test/customization.config +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3-test/customization.config @@ -321,8 +321,6 @@ } }, "endpointAuthSchemeConfig": { - "authSchemeStrategyFactoryClass": "software.amazon.awssdk.services.s3.endpoints.internal.S3EndpointAuthSchemeStrategyFactory", - "knownEndpointProperties": "software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty.KNOWN_S3_ENDPOINT_PROPERTIES", "endpointProviderTestKeys": { "backend": { "key": "software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty.BACKEND", @@ -331,7 +329,6 @@ } }, - "enableGenerateCompiledEndpointRules": true, "endpointParameters": { "DeleteObjectKeys": { "required": false, diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3control-test/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3control-test/customization.config index abf7c5633797..53aa741058be 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3control-test/customization.config +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/s3control-test/customization.config @@ -1,6 +1,5 @@ { - "enableGenerateCompiledEndpointRules": true, "serviceConfig": { "className": "S3ControlConfiguration", "hasDualstackProperty": true, diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/stringarray/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/stringarray/service-2.json index 771df7b3b933..217c98d7bb47 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/stringarray/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/stringarray/service-2.json @@ -50,6 +50,30 @@ "method": "POST", "requestUri": "/" } + }, + "MapKeysOperation": { + "input": { "shape": "MapKeysOperationRequest" }, + "operationContextParams": { + "stringArrayParam": { + "path": "keys(RequestItems)" + } + }, + "http": { + "method": "POST", + "requestUri": "/" + } + }, + "TransactionOperation": { + "input": { "shape": "TransactionOperationRequest" }, + "operationContextParams": { + "stringArrayParam": { + "path": "TransactItems[*].[Put.TableName, Delete.TableName][]" + } + }, + "http": { + "method": "POST", + "requestUri": "/" + } } }, "shapes": { @@ -60,15 +84,29 @@ "ListOfObjectsOperationRequest": { "type": "structure", "members": { - "nested":{"shape":"Nested"} + "nested":{"shape":"Nested"}, + "Request":{"shape":"Nested"} } }, "Nested": { "type": "structure", "members": { - "listOfObjects":{"shape":"ListOfObjects"} + "listOfObjects":{"shape":"ListOfObjects"}, + "Value":{"shape":"String"}, + "Token":{"shape":"String", "idempotencyToken":true}, + "Inner":{"shape":"Inner"}, + "ItemMap":{"shape":"StringMap"} } }, + "Inner": { + "type": "structure", + "members": { + "Flag":{"shape":"Boolean"} + } + }, + "Boolean": { + "type": "boolean" + }, "ListOfObjects": { "type": "list", "member":{"shape":"ObjectMember"} @@ -76,7 +114,52 @@ "ObjectMember": { "type": "structure", "members": { - "key":{"shape":"String"} + "key":{"shape":"String"}, + "aliases":{"shape":"StringList"} + } + }, + "StringList": { + "type": "list", + "member":{"shape":"String"} + }, + "MapKeysOperationRequest": { + "type": "structure", + "members": { + "RequestItems":{"shape":"StringMap"} + } + }, + "StringMap": { + "type": "map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "TransactionOperationRequest": { + "type": "structure", + "members": { + "TransactItems":{"shape":"TransactItemList"} + } + }, + "TransactItemList": { + "type": "list", + "member":{"shape":"TransactItem"} + }, + "TransactItem": { + "type": "structure", + "members": { + "Put":{"shape":"Put"}, + "Delete":{"shape":"Delete"} + } + }, + "Put": { + "type": "structure", + "members": { + "TableName":{"shape":"String"} + } + }, + "Delete": { + "type": "structure", + "members": { + "TableName":{"shape":"String"} } }, "String":{ diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-abstract-async-client-class-presignedurl.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-abstract-async-client-class-presignedurl.java new file mode 100644 index 000000000000..7e5984afccf7 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-abstract-async-client-class-presignedurl.java @@ -0,0 +1,84 @@ +package software.amazon.awssdk.services.json; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.model.JsonRequest; +import software.amazon.awssdk.services.json.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.utils.Validate; + +@Generated("software.amazon.awssdk:codegen") +@SdkPublicApi +public abstract class DelegatingJsonAsyncClient implements JsonAsyncClient { + private final JsonAsyncClient delegate; + + public DelegatingJsonAsyncClient(JsonAsyncClient delegate) { + Validate.paramNotNull(delegate, "delegate"); + this.delegate = delegate; + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + @Override + public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { + return invokeOperation(aPostOperationRequest, request -> delegate.aPostOperation(request)); + } + + /** + * Creates an instance of {@link AsyncPresignedUrlExtension} object with the configuration set on this client. + */ + @Override + public AsyncPresignedUrlExtension presignedUrlExtension() { + return delegate.presignedUrlExtension(); + } + + @Override + public final JsonServiceClientConfiguration serviceClientConfiguration() { + return delegate.serviceClientConfiguration(); + } + + @Override + public final String serviceName() { + return delegate.serviceName(); + } + + public SdkClient delegate() { + return this.delegate; + } + + protected CompletableFuture invokeOperation(T request, + Function> operation) { + return operation.apply(request); + } + + @Override + public void close() { + delegate.close(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-json-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-json-async-client-class.java index 33f5c7b612e0..3d9a8b62f388 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-json-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-json-async-client-class.java @@ -8,6 +8,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; @@ -16,7 +17,7 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; @@ -46,10 +47,10 @@ import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.internal.interceptor.trait.RequestCompression; @@ -57,7 +58,6 @@ import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -71,6 +71,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.endpoints.internal.JsonEndpointResolverUtils; @@ -156,8 +157,27 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + case "ServiceFaultException": + return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) + .exceptionBuilderSupplier(ServiceFaultException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + private final Executor executor; + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -210,21 +230,6 @@ public CompletableFuture aPostOperation(APostOperationRe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); String hostPrefix = "{StringMember}-foo."; @@ -238,16 +243,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -294,21 +297,6 @@ public CompletableFuture aPostOperationWithOut HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationWithOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -318,16 +306,14 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(aPostOperationWithOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -391,21 +377,6 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -428,8 +399,8 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest .withInitialRequestEvent(true).withResponseHandler(voidResponseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EventStreamOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -439,14 +410,14 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -490,21 +461,6 @@ public CompletableFuture eventStreamO HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, EventStreamOperationWithOnlyInputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -525,17 +481,14 @@ public CompletableFuture eventStreamO .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyInput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyInput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationWithOnlyInputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -601,21 +554,6 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); CompletableFuture future = new CompletableFuture<>(); @@ -634,9 +572,8 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationWithOnlyOutputRequest), asyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -646,14 +583,14 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -699,21 +636,6 @@ public CompletableFuture getWithoutRequiredMe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetWithoutRequiredMembersResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -723,16 +645,14 @@ public CompletableFuture getWithoutRequiredMe .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetWithoutRequiredMembers", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetWithoutRequiredMembers")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(getWithoutRequiredMembersRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -775,21 +695,6 @@ public CompletableFuture operationWithChe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithChecksumRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -802,18 +707,15 @@ public CompletableFuture operationWithChe .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -855,21 +757,6 @@ public CompletableFuture operationWithNoneAut HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithNoneAuthTypeResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -879,16 +766,14 @@ public CompletableFuture operationWithNoneAut .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithNoneAuthTypeRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -931,21 +816,6 @@ public CompletableFuture operationWithR HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithRequestCompressionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -958,19 +828,16 @@ public CompletableFuture operationWithR .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withInput(operationWithRequestCompressionRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1013,21 +880,6 @@ public CompletableFuture paginatedOpera HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1040,17 +892,14 @@ public CompletableFuture paginatedOpera .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithResultKey")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(paginatedOperationWithResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1093,21 +942,6 @@ public CompletableFuture paginatedOp HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1120,17 +954,14 @@ public CompletableFuture paginatedOp .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithoutResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithoutResultKey")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(paginatedOperationWithoutResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1177,21 +1008,6 @@ public CompletableFuture streamingInputOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1205,16 +1021,14 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")).withAsyncRequestBody(requestBody) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1271,21 +1085,6 @@ public CompletableFuture streamingInputOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1303,9 +1102,8 @@ public CompletableFuture streamingInputOutputOperation( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("StreamingInputOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncRequestBody(requestBody).withAsyncResponseTransformer(asyncResponseTransformer) .withInput(streamingInputOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; @@ -1315,7 +1113,7 @@ public CompletableFuture streamingInputOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1324,7 +1122,7 @@ public CompletableFuture streamingInputOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1376,21 +1174,6 @@ public CompletableFuture streamingOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1400,8 +1183,8 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncResponseTransformer(asyncResponseTransformer).withInput(streamingOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; @@ -1411,7 +1194,7 @@ public CompletableFuture streamingOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1420,7 +1203,7 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1455,8 +1238,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1464,15 +1265,29 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) .orElse(null); JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(JsonAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(JsonAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1503,14 +1318,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-async-client-class.java index de37281ad310..84728c99d5f1 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-async-client-class.java @@ -7,13 +7,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -31,14 +32,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -52,6 +52,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.QueryToJsonCompatibleAuthSchemeParams; import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.QueryToJsonCompatibleAuthSchemeProvider; +import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.internal.DefaultQueryToJsonCompatibleAuthSchemeProvider; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.QueryToJsonCompatibleEndpointParams; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.QueryToJsonCompatibleEndpointProvider; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.internal.QueryToJsonCompatibleEndpointResolverUtils; @@ -85,6 +86,21 @@ final class DefaultQueryToJsonCompatibleAsyncClient implements QueryToJsonCompat private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultQueryToJsonCompatibleAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -131,18 +147,6 @@ public CompletableFuture aPostOperation(APostOperationRe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); String hostPrefix = "{StringMember}-foo."; @@ -156,16 +160,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -201,8 +203,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryToJsonCompatibleAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -210,16 +230,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of QueryToJsonCompatibleAuthSchemeProvider")).orElse(null); QueryToJsonCompatibleAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(QueryToJsonCompatibleAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of QueryToJsonCompatibleAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultQueryToJsonCompatibleAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } QueryToJsonCompatibleAuthSchemeParams.Builder paramsBuilder = QueryToJsonCompatibleAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryToJsonCompatibleEndpointProvider provider = (QueryToJsonCompatibleEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -251,14 +285,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-sync-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-sync-client-class.java index ead8f03c7bfd..f372a60313c3 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-sync-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-aws-query-compatible-json-sync-client-class.java @@ -4,11 +4,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -26,14 +27,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -47,6 +47,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.QueryToJsonCompatibleAuthSchemeParams; import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.QueryToJsonCompatibleAuthSchemeProvider; +import software.amazon.awssdk.services.querytojsoncompatible.auth.scheme.internal.DefaultQueryToJsonCompatibleAuthSchemeProvider; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.QueryToJsonCompatibleEndpointParams; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.QueryToJsonCompatibleEndpointProvider; import software.amazon.awssdk.services.querytojsoncompatible.endpoints.internal.QueryToJsonCompatibleEndpointResolverUtils; @@ -80,6 +81,21 @@ final class DefaultQueryToJsonCompatibleClient implements QueryToJsonCompatibleC private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultQueryToJsonCompatibleClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -115,18 +131,6 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); @@ -147,11 +151,11 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -175,8 +179,18 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryToJsonCompatibleAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -184,16 +198,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of QueryToJsonCompatibleAuthSchemeProvider")).orElse(null); QueryToJsonCompatibleAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(QueryToJsonCompatibleAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of QueryToJsonCompatibleAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultQueryToJsonCompatibleAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } QueryToJsonCompatibleAuthSchemeParams.Builder paramsBuilder = QueryToJsonCompatibleAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryToJsonCompatibleEndpointProvider provider = (QueryToJsonCompatibleEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -225,14 +253,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-batchmanager-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-batchmanager-async.java index a047a35d87d5..36923ede6e30 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-batchmanager-async.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-batchmanager-async.java @@ -7,6 +7,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import java.util.function.Function; @@ -14,7 +15,7 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -32,14 +33,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -53,6 +53,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.batchmanagertest.auth.scheme.BatchManagerTestAuthSchemeParams; import software.amazon.awssdk.services.batchmanagertest.auth.scheme.BatchManagerTestAuthSchemeProvider; +import software.amazon.awssdk.services.batchmanagertest.auth.scheme.internal.DefaultBatchManagerTestAuthSchemeProvider; import software.amazon.awssdk.services.batchmanagertest.batchmanager.BatchManagerTestAsyncBatchManager; import software.amazon.awssdk.services.batchmanagertest.endpoints.BatchManagerTestEndpointParams; import software.amazon.awssdk.services.batchmanagertest.endpoints.BatchManagerTestEndpointProvider; @@ -85,8 +86,20 @@ final class DefaultBatchManagerTestAsyncClient implements BatchManagerTestAsyncC private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + private final ScheduledExecutorService executorService; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultBatchManagerTestAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -130,15 +143,6 @@ public CompletableFuture sendRequest(SendRequestRequest sen HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, SendRequestResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -148,15 +152,13 @@ public CompletableFuture sendRequest(SendRequestRequest sen .withMarshaller(new SendRequestRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("SendRequest", clientConfiguration)) - .withEndpointResolver(endpointResolver("SendRequest")).withInput(sendRequestRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(sendRequestRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -197,8 +199,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); BatchManagerTestAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -206,16 +226,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of BatchManagerTestAuthSchemeProvider")).orElse(null); BatchManagerTestAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(BatchManagerTestAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of BatchManagerTestAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultBatchManagerTestAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } BatchManagerTestAuthSchemeParams.Builder paramsBuilder = BatchManagerTestAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); BatchManagerTestEndpointProvider provider = (BatchManagerTestEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -247,14 +281,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java index 56c3e6c6c46a..af4884e50e56 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-async-client-class.java @@ -8,6 +8,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; @@ -16,7 +17,7 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; @@ -46,10 +47,10 @@ import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.internal.interceptor.trait.RequestCompression; @@ -57,7 +58,6 @@ import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -72,6 +72,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.endpoints.internal.JsonEndpointResolverUtils; @@ -157,10 +158,29 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + case "ServiceFaultException": + return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) + .exceptionBuilderSupplier(ServiceFaultException::builder).build()); + default: + return Optional.empty(); + } + }; + private final AwsJsonProtocolFactory jsonProtocolFactory; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + private final Executor executor; + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -214,21 +234,6 @@ public CompletableFuture aPostOperation(APostOperationRe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); String hostPrefix = "{StringMember}-foo."; @@ -242,16 +247,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -298,21 +301,6 @@ public CompletableFuture aPostOperationWithOut HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationWithOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -322,16 +310,14 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(aPostOperationWithOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -395,21 +381,6 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -432,8 +403,8 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest .withInitialRequestEvent(true).withResponseHandler(voidResponseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EventStreamOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -443,14 +414,14 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -494,21 +465,6 @@ public CompletableFuture eventStreamO HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, EventStreamOperationWithOnlyInputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -529,17 +485,14 @@ public CompletableFuture eventStreamO .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyInput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyInput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationWithOnlyInputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -605,21 +558,6 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); CompletableFuture future = new CompletableFuture<>(); @@ -638,9 +576,8 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationWithOnlyOutputRequest), asyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -650,14 +587,14 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -703,21 +640,6 @@ public CompletableFuture getWithoutRequiredMe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetWithoutRequiredMembersResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -727,16 +649,14 @@ public CompletableFuture getWithoutRequiredMe .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetWithoutRequiredMembers", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetWithoutRequiredMembers")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(getWithoutRequiredMembersRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -779,21 +699,6 @@ public CompletableFuture operationWithChe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithChecksumRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -806,18 +711,15 @@ public CompletableFuture operationWithChe .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -859,21 +761,6 @@ public CompletableFuture operationWithNoneAut HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithNoneAuthTypeResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -883,16 +770,14 @@ public CompletableFuture operationWithNoneAut .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithNoneAuthTypeRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -935,21 +820,6 @@ public CompletableFuture operationWithR HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithRequestCompressionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -962,19 +832,16 @@ public CompletableFuture operationWithR .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withInput(operationWithRequestCompressionRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1017,21 +884,6 @@ public CompletableFuture paginatedOpera HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1044,17 +896,14 @@ public CompletableFuture paginatedOpera .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithResultKey")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(paginatedOperationWithResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1097,21 +946,6 @@ public CompletableFuture paginatedOp HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1124,17 +958,14 @@ public CompletableFuture paginatedOp .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithoutResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithoutResultKey")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(paginatedOperationWithoutResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1181,21 +1012,6 @@ public CompletableFuture streamingInputOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1209,16 +1025,14 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")).withAsyncRequestBody(requestBody) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1275,21 +1089,6 @@ public CompletableFuture streamingInputOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1307,9 +1106,8 @@ public CompletableFuture streamingInputOutputOperation( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("StreamingInputOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncRequestBody(requestBody).withAsyncResponseTransformer(asyncResponseTransformer) .withInput(streamingInputOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; @@ -1319,7 +1117,7 @@ public CompletableFuture streamingInputOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1328,7 +1126,7 @@ public CompletableFuture streamingInputOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1380,21 +1178,6 @@ public CompletableFuture streamingOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1404,8 +1187,8 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncResponseTransformer(asyncResponseTransformer).withInput(streamingOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; @@ -1415,7 +1198,7 @@ public CompletableFuture streamingOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1424,7 +1207,7 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1459,8 +1242,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1468,15 +1269,29 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) .orElse(null); JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(JsonAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(JsonAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1507,14 +1322,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java index 3198fa31df25..dfcd9c933cb1 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-cbor-client-class.java @@ -4,11 +4,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -26,17 +27,16 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.internal.interceptor.trait.RequestCompression; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.endpoints.Endpoint; @@ -52,6 +52,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.endpoints.internal.JsonEndpointResolverUtils; @@ -116,6 +117,24 @@ final class DefaultJsonClient implements JsonClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + case "ServiceFaultException": + return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) + .exceptionBuilderSupplier(ServiceFaultException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultJsonClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -151,21 +170,6 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); @@ -186,11 +190,10 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -224,21 +227,6 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationWithOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, @@ -256,12 +244,11 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -294,21 +281,6 @@ public GetWithoutRequiredMembersResponse getWithoutRequiredMembers( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetWithoutRequiredMembersResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getWithoutRequiredMembersRequest, @@ -326,12 +298,11 @@ public GetWithoutRequiredMembersResponse getWithoutRequiredMembers( .withOperationName("GetWithoutRequiredMembers").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(getWithoutRequiredMembersRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetWithoutRequiredMembers", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetWithoutRequiredMembers")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -360,21 +331,6 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithChecksumRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, @@ -396,14 +352,13 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( .withRequestConfiguration(clientConfiguration) .withInput(operationWithChecksumRequiredRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()) .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -432,21 +387,6 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithNoneAuthTypeResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, @@ -464,12 +404,11 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -498,21 +437,6 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithRequestCompressionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, @@ -534,14 +458,13 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( .withRequestConfiguration(clientConfiguration) .withInput(operationWithRequestCompressionRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -570,21 +493,6 @@ public PaginatedOperationWithResultKeyResponse paginatedOperationWithResultKey( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithResultKeyRequest, @@ -599,19 +507,14 @@ public PaginatedOperationWithResultKeyResponse paginatedOperationWithResultKey( return clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithResultKey") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(paginatedOperationWithResultKeyRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithResultKey")) + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithResultKeyRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -640,21 +543,6 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithoutResultKeyRequest, @@ -669,19 +557,14 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul return clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithoutResultKey") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(paginatedOperationWithoutResultKeyRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithoutResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithoutResultKey")) + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithoutResultKeyRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -720,21 +603,6 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, @@ -756,15 +624,15 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -812,21 +680,6 @@ public ReturnT streamingInputOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOutputOperationRequest, @@ -848,9 +701,8 @@ public ReturnT streamingInputOutputOperation( .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOutputOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("StreamingInputOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withResponseTransformer(responseTransformer) .withRequestBody(requestBody) .withMarshaller( @@ -860,7 +712,7 @@ public ReturnT streamingInputOutputOperation( new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).transferEncoding(true).build()), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -896,21 +748,6 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInputException": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - case "ServiceFaultException": - return Optional.of(ExceptionMetadata.builder().errorCode("ServiceFaultException").httpStatusCode(500) - .exceptionBuilderSupplier(ServiceFaultException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, @@ -928,13 +765,11 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) - .withResponseTransformer(responseTransformer) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withResponseTransformer(responseTransformer) .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -966,8 +801,17 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -975,15 +819,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) .orElse(null); JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(JsonAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(JsonAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1014,14 +873,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-async-client-class.java index 818e13b3663e..23a669392d17 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-async-client-class.java @@ -8,13 +8,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -32,14 +33,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -53,6 +53,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.foobar.auth.scheme.FooBarAuthSchemeParams; import software.amazon.awssdk.services.foobar.auth.scheme.FooBarAuthSchemeProvider; +import software.amazon.awssdk.services.foobar.auth.scheme.internal.DefaultFooBarAuthSchemeProvider; import software.amazon.awssdk.services.foobar.endpoints.FooBarClientContextParams; import software.amazon.awssdk.services.foobar.endpoints.FooBarEndpointParams; import software.amazon.awssdk.services.foobar.endpoints.FooBarEndpointProvider; @@ -78,7 +79,7 @@ final class DefaultFooBarAsyncClient implements FooBarAsyncClient { private static final Logger log = LoggerFactory.getLogger(DefaultFooBarAsyncClient.class); private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() - .serviceProtocol(AwsServiceProtocol.REST_JSON).build(); + .serviceProtocol(AwsServiceProtocol.REST_JSON).build(); private final AsyncClientHandler clientHandler; @@ -86,10 +87,22 @@ final class DefaultFooBarAsyncClient implements FooBarAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultFooBarAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) - .option(SdkClientOption.API_METADATA, "Foo_Bar" + "#" + ServiceVersionInfo.VERSION).build(); + .option(SdkClientOption.API_METADATA, "Foo_Bar" + "#" + ServiceVersionInfo.VERSION).build(); this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build(); } @@ -118,46 +131,35 @@ protected DefaultFooBarAsyncClient(SdkClientConfiguration clientConfiguration) { @Override public CompletableFuture getDatabaseVersion(GetDatabaseVersionRequest getDatabaseVersionRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getDatabaseVersionRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, getDatabaseVersionRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Foo Bar"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetDatabaseVersion"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) - .isPayloadJson(true).build(); + .isPayloadJson(true).build(); HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( - operationMetadata, GetDatabaseVersionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; + operationMetadata, GetDatabaseVersionResponse::builder); HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, - operationMetadata, exceptionMetadataMapper); + operationMetadata, exceptionMetadataMapper); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("GetDatabaseVersion").withProtocolMetadata(protocolMetadata) - .withMarshaller(new GetDatabaseVersionRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetDatabaseVersion", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetDatabaseVersion")).withInput(getDatabaseVersionRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .execute(new ClientExecutionParams() + .withOperationName("GetDatabaseVersion").withProtocolMetadata(protocolMetadata) + .withMarshaller(new GetDatabaseVersionRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(getDatabaseVersionRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -174,11 +176,11 @@ public final String serviceName() { private > T init(T builder) { return builder.clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(FooBarException::builder) - .protocol(AwsJsonProtocol.REST_JSON).protocolVersion("1.1"); + .protocol(AwsJsonProtocol.REST_JSON).protocolVersion("1.1"); } private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, - RequestOverrideConfiguration requestOverrideConfiguration) { + RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; if (requestOverrideConfiguration != null) { publishers = requestOverrideConfiguration.metricPublishers(); @@ -192,25 +194,57 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); FooBarAuthSchemeProvider requestAuthSchemeProvider = request - .overrideConfiguration() - .flatMap(c -> c.authSchemeProvider()) - .map(p -> Validate.isInstanceOf(FooBarAuthSchemeProvider.class, p, - "Expected an instance of FooBarAuthSchemeProvider")).orElse(null); + .overrideConfiguration() + .flatMap(c -> c.authSchemeProvider()) + .map(p -> Validate.isInstanceOf(FooBarAuthSchemeProvider.class, p, + "Expected an instance of FooBarAuthSchemeProvider")).orElse(null); FooBarAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(FooBarAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), - "Expected an instance of FooBarAuthSchemeProvider"); + .isInstanceOf(FooBarAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), + "Expected an instance of FooBarAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultFooBarAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } FooBarAuthSchemeParams.Builder paramsBuilder = FooBarAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); FooBarEndpointProvider provider = (FooBarEndpointProvider) executionAttributes - .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); + .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { FooBarEndpointParams endpointParams = FooBarEndpointResolverUtils.ruleParams(request, executionAttributes); Endpoint endpoint = provider.resolveEndpoint(endpointParams).join(); @@ -222,10 +256,10 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } List endpointAuthSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); SelectedAuthScheme selectedAuthScheme = executionAttributes - .getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME); + .getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME); if (endpointAuthSchemes != null && selectedAuthScheme != null) { selectedAuthScheme = FooBarEndpointResolverUtils.authSchemeWithEndpointSignerProperties(endpointAuthSchemes, - selectedAuthScheme); + selectedAuthScheme); executionAttributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme); } FooBarEndpointResolverUtils.setMetricValues(endpoint, executionAttributes); @@ -239,14 +273,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); @@ -285,15 +311,15 @@ private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, newContextParams = (newContextParams != null) ? newContextParams : AttributeMap.empty(); originalContextParams = originalContextParams != null ? originalContextParams : AttributeMap.empty(); Validate.validState( - Objects.equals(originalContextParams.get(FooBarClientContextParams.CROSS_REGION_ACCESS_ENABLED), - newContextParams.get(FooBarClientContextParams.CROSS_REGION_ACCESS_ENABLED)), - "CROSS_REGION_ACCESS_ENABLED cannot be modified by request level plugins"); + Objects.equals(originalContextParams.get(FooBarClientContextParams.CROSS_REGION_ACCESS_ENABLED), + newContextParams.get(FooBarClientContextParams.CROSS_REGION_ACCESS_ENABLED)), + "CROSS_REGION_ACCESS_ENABLED cannot be modified by request level plugins"); updateRetryStrategyClientConfiguration(configuration); return configuration.build(); } private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, - JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { + JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-sync-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-sync-client-class.java index 6e29b234a04a..b041e122f432 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-sync-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custom-context-params-sync-client-class.java @@ -5,11 +5,12 @@ import java.util.Objects; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -27,14 +28,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -48,6 +48,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.foobar.auth.scheme.FooBarAuthSchemeParams; import software.amazon.awssdk.services.foobar.auth.scheme.FooBarAuthSchemeProvider; +import software.amazon.awssdk.services.foobar.auth.scheme.internal.DefaultFooBarAuthSchemeProvider; import software.amazon.awssdk.services.foobar.endpoints.FooBarClientContextParams; import software.amazon.awssdk.services.foobar.endpoints.FooBarEndpointParams; import software.amazon.awssdk.services.foobar.endpoints.FooBarEndpointProvider; @@ -81,6 +82,18 @@ final class DefaultFooBarClient implements FooBarClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultFooBarClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -114,15 +127,6 @@ public GetDatabaseVersionResponse getDatabaseVersion(GetDatabaseVersionRequest g HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetDatabaseVersionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getDatabaseVersionRequest, @@ -140,11 +144,11 @@ public GetDatabaseVersionResponse getDatabaseVersion(GetDatabaseVersionRequest g .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(getDatabaseVersionRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetDatabaseVersion", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetDatabaseVersion")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new GetDatabaseVersionRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -168,23 +172,47 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); FooBarAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(FooBarAuthSchemeProvider.class, p, "Expected an instance of FooBarAuthSchemeProvider")).orElse(null); FooBarAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(FooBarAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(FooBarAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of FooBarAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultFooBarAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } FooBarAuthSchemeParams.Builder paramsBuilder = FooBarAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); FooBarEndpointProvider provider = (FooBarEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -215,14 +243,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-async.java index aa23153cdd20..c2d400d99364 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-async.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-async.java @@ -4,6 +4,7 @@ import foo.bar.helloworld.auth.scheme.ProtocolRestJsonWithCustomPackageAuthSchemeParams; import foo.bar.helloworld.auth.scheme.ProtocolRestJsonWithCustomPackageAuthSchemeProvider; +import foo.bar.helloworld.auth.scheme.internal.DefaultProtocolRestJsonWithCustomPackageAuthSchemeProvider; import foo.bar.helloworld.endpoints.ProtocolRestJsonWithCustomPackageEndpointParams; import foo.bar.helloworld.endpoints.ProtocolRestJsonWithCustomPackageEndpointProvider; import foo.bar.helloworld.endpoints.internal.ProtocolRestJsonWithCustomPackageEndpointResolverUtils; @@ -18,13 +19,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -42,14 +44,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -83,6 +84,18 @@ final class DefaultProtocolRestJsonWithCustomPackageAsyncClient implements Proto private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultProtocolRestJsonWithCustomPackageAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration @@ -128,15 +141,6 @@ public CompletableFuture oneOperation(OneOperationRequest HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, OneOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -146,15 +150,13 @@ public CompletableFuture oneOperation(OneOperationRequest .withMarshaller(new OneOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OneOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("OneOperation")).withInput(oneOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(oneOperationRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -191,8 +193,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomPackageAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -200,16 +220,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of ProtocolRestJsonWithCustomPackageAuthSchemeProvider")).orElse(null); ProtocolRestJsonWithCustomPackageAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(ProtocolRestJsonWithCustomPackageAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of ProtocolRestJsonWithCustomPackageAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultProtocolRestJsonWithCustomPackageAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } ProtocolRestJsonWithCustomPackageAuthSchemeParams.Builder paramsBuilder = ProtocolRestJsonWithCustomPackageAuthSchemeParams .builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomPackageEndpointProvider provider = (ProtocolRestJsonWithCustomPackageEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -242,14 +276,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-sync.java index 24811ad10405..dfe6b88dfa19 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-custompackage-sync.java @@ -2,6 +2,7 @@ import foo.bar.helloworld.auth.scheme.ProtocolRestJsonWithCustomPackageAuthSchemeParams; import foo.bar.helloworld.auth.scheme.ProtocolRestJsonWithCustomPackageAuthSchemeProvider; +import foo.bar.helloworld.auth.scheme.internal.DefaultProtocolRestJsonWithCustomPackageAuthSchemeProvider; import foo.bar.helloworld.endpoints.ProtocolRestJsonWithCustomPackageEndpointParams; import foo.bar.helloworld.endpoints.ProtocolRestJsonWithCustomPackageEndpointProvider; import foo.bar.helloworld.endpoints.internal.ProtocolRestJsonWithCustomPackageEndpointResolverUtils; @@ -15,11 +16,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -37,14 +39,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -78,6 +79,18 @@ final class DefaultProtocolRestJsonWithCustomPackageClient implements ProtocolRe private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultProtocolRestJsonWithCustomPackageClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration @@ -112,15 +125,6 @@ public OneOperationResponse oneOperation(OneOperationRequest oneOperationRequest HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, OneOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(oneOperationRequest, this.clientConfiguration); @@ -137,11 +141,11 @@ public OneOperationResponse oneOperation(OneOperationRequest oneOperationRequest .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(oneOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OneOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("OneOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OneOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -165,8 +169,18 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomPackageAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -174,16 +188,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of ProtocolRestJsonWithCustomPackageAuthSchemeProvider")).orElse(null); ProtocolRestJsonWithCustomPackageAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(ProtocolRestJsonWithCustomPackageAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of ProtocolRestJsonWithCustomPackageAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultProtocolRestJsonWithCustomPackageAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } ProtocolRestJsonWithCustomPackageAuthSchemeParams.Builder paramsBuilder = ProtocolRestJsonWithCustomPackageAuthSchemeParams .builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomPackageEndpointProvider provider = (ProtocolRestJsonWithCustomPackageEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -216,14 +244,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-async.java index a4956ab331f3..e6b022bfafd7 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-async.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-async.java @@ -7,13 +7,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -31,14 +32,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -52,6 +52,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.ProtocolRestJsonWithCustomContentTypeAuthSchemeParams; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; +import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.internal.DefaultProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.ProtocolRestJsonWithCustomContentTypeEndpointParams; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.ProtocolRestJsonWithCustomContentTypeEndpointProvider; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.internal.ProtocolRestJsonWithCustomContentTypeEndpointResolverUtils; @@ -83,6 +84,18 @@ final class DefaultProtocolRestJsonWithCustomContentTypeAsyncClient implements P private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultProtocolRestJsonWithCustomContentTypeAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration @@ -128,15 +141,6 @@ public CompletableFuture oneOperation(OneOperationRequest HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, OneOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -146,15 +150,13 @@ public CompletableFuture oneOperation(OneOperationRequest .withMarshaller(new OneOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OneOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("OneOperation")).withInput(oneOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(oneOperationRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -191,8 +193,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -200,16 +220,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider")).orElse(null); ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } ProtocolRestJsonWithCustomContentTypeAuthSchemeParams.Builder paramsBuilder = ProtocolRestJsonWithCustomContentTypeAuthSchemeParams .builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomContentTypeEndpointProvider provider = (ProtocolRestJsonWithCustomContentTypeEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -242,14 +276,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-sync.java index 31f56fe814ef..f08e1ab354c7 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-customservicemetadata-sync.java @@ -4,11 +4,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -26,14 +27,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -47,6 +47,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.ProtocolRestJsonWithCustomContentTypeAuthSchemeParams; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; +import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.auth.scheme.internal.DefaultProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.ProtocolRestJsonWithCustomContentTypeEndpointParams; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.ProtocolRestJsonWithCustomContentTypeEndpointProvider; import software.amazon.awssdk.services.protocolrestjsonwithcustomcontenttype.endpoints.internal.ProtocolRestJsonWithCustomContentTypeEndpointResolverUtils; @@ -78,6 +79,18 @@ final class DefaultProtocolRestJsonWithCustomContentTypeClient implements Protoc private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultProtocolRestJsonWithCustomContentTypeClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration @@ -112,15 +125,6 @@ public OneOperationResponse oneOperation(OneOperationRequest oneOperationRequest HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, OneOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(oneOperationRequest, this.clientConfiguration); @@ -137,11 +141,11 @@ public OneOperationResponse oneOperation(OneOperationRequest oneOperationRequest .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(oneOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OneOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("OneOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OneOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -165,8 +169,18 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -174,16 +188,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider")).orElse(null); ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of ProtocolRestJsonWithCustomContentTypeAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultProtocolRestJsonWithCustomContentTypeAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } ProtocolRestJsonWithCustomContentTypeAuthSchemeParams.Builder paramsBuilder = ProtocolRestJsonWithCustomContentTypeAuthSchemeParams .builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); ProtocolRestJsonWithCustomContentTypeEndpointProvider provider = (ProtocolRestJsonWithCustomContentTypeEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -216,14 +244,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java index d043a064e0ee..4b7c31e64259 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java @@ -8,12 +8,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; @@ -33,16 +35,15 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; @@ -57,6 +58,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.EndpointDiscoveryTestAuthSchemeParams; import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.EndpointDiscoveryTestAuthSchemeProvider; +import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.internal.DefaultEndpointDiscoveryTestAuthSchemeProvider; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.EndpointDiscoveryTestEndpointParams; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.EndpointDiscoveryTestEndpointProvider; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.internal.EndpointDiscoveryTestEndpointResolverUtils; @@ -97,8 +99,20 @@ final class DefaultEndpointDiscoveryTestAsyncClient implements EndpointDiscovery private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + private EndpointDiscoveryRefreshCache endpointDiscoveryCache; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultEndpointDiscoveryTestAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -144,15 +158,6 @@ public CompletableFuture describeEndpoints(DescribeEn HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, DescribeEndpointsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -162,15 +167,13 @@ public CompletableFuture describeEndpoints(DescribeEn .withMarshaller(new DescribeEndpointsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("DescribeEndpoints", clientConfiguration)) - .withEndpointResolver(endpointResolver("DescribeEndpoints")).withInput(describeEndpointsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(describeEndpointsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -211,15 +214,6 @@ public CompletableFuture testDiscovery HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, TestDiscoveryIdentifiersRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -254,24 +248,18 @@ public CompletableFuture testDiscovery CompletableFuture executeFuture = endpointFuture .thenCompose(cachedEndpoint -> clientHandler .execute(new ClientExecutionParams() - .withOperationName("TestDiscoveryIdentifiersRequired") - .withProtocolMetadata(protocolMetadata) + .withOperationName("TestDiscoveryIdentifiersRequired").withProtocolMetadata(protocolMetadata) .withMarshaller(new TestDiscoveryIdentifiersRequiredRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("TestDiscoveryIdentifiersRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryIdentifiersRequired")) - .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryIdentifiersRequiredRequest))); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).discoveredEndpoint(cachedEndpoint) + .withInput(testDiscoveryIdentifiersRequiredRequest))); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -311,15 +299,6 @@ public CompletableFuture testDiscoveryOptional( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, TestDiscoveryOptionalResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -345,24 +324,18 @@ public CompletableFuture testDiscoveryOptional( CompletableFuture executeFuture = endpointFuture .thenCompose(cachedEndpoint -> clientHandler .execute(new ClientExecutionParams() - .withOperationName("TestDiscoveryOptional") - .withProtocolMetadata(protocolMetadata) + .withOperationName("TestDiscoveryOptional").withProtocolMetadata(protocolMetadata) .withMarshaller(new TestDiscoveryOptionalRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("TestDiscoveryOptional", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryOptional")) - .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryOptionalRequest))); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).discoveredEndpoint(cachedEndpoint) + .withInput(testDiscoveryOptionalRequest))); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -402,15 +375,6 @@ public CompletableFuture testDiscoveryRequired( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, TestDiscoveryRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -444,24 +408,18 @@ public CompletableFuture testDiscoveryRequired( CompletableFuture executeFuture = endpointFuture .thenCompose(cachedEndpoint -> clientHandler .execute(new ClientExecutionParams() - .withOperationName("TestDiscoveryRequired") - .withProtocolMetadata(protocolMetadata) + .withOperationName("TestDiscoveryRequired").withProtocolMetadata(protocolMetadata) .withMarshaller(new TestDiscoveryRequiredRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("TestDiscoveryRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryRequired")) - .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryRequiredRequest))); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).discoveredEndpoint(cachedEndpoint) + .withInput(testDiscoveryRequiredRequest))); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -497,8 +455,25 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); EndpointDiscoveryTestAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -506,16 +481,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of EndpointDiscoveryTestAuthSchemeProvider")).orElse(null); EndpointDiscoveryTestAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(EndpointDiscoveryTestAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of EndpointDiscoveryTestAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultEndpointDiscoveryTestAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } EndpointDiscoveryTestAuthSchemeParams.Builder paramsBuilder = EndpointDiscoveryTestAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); EndpointDiscoveryTestEndpointProvider provider = (EndpointDiscoveryTestEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -547,14 +536,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-sync.java index e20ee0df3404..6d6de8fdad2e 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-sync.java @@ -6,10 +6,12 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; @@ -29,16 +31,15 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; @@ -53,6 +54,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.EndpointDiscoveryTestAuthSchemeParams; import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.EndpointDiscoveryTestAuthSchemeProvider; +import software.amazon.awssdk.services.endpointdiscoverytest.auth.scheme.internal.DefaultEndpointDiscoveryTestAuthSchemeProvider; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.EndpointDiscoveryTestEndpointParams; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.EndpointDiscoveryTestEndpointProvider; import software.amazon.awssdk.services.endpointdiscoverytest.endpoints.internal.EndpointDiscoveryTestEndpointResolverUtils; @@ -94,8 +96,21 @@ final class DefaultEndpointDiscoveryTestClient implements EndpointDiscoveryTestC private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + private EndpointDiscoveryRefreshCache endpointDiscoveryCache; + protected DefaultEndpointDiscoveryTestClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -129,15 +144,6 @@ public DescribeEndpointsResponse describeEndpoints(DescribeEndpointsRequest desc HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, DescribeEndpointsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(describeEndpointsRequest, @@ -154,12 +160,11 @@ public DescribeEndpointsResponse describeEndpoints(DescribeEndpointsRequest desc .withOperationName("DescribeEndpoints").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(describeEndpointsRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("DescribeEndpoints", clientConfiguration)) - .withEndpointResolver(endpointResolver("DescribeEndpoints")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new DescribeEndpointsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -186,15 +191,6 @@ public TestDiscoveryIdentifiersRequiredResponse testDiscoveryIdentifiersRequired HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, TestDiscoveryIdentifiersRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -230,20 +226,15 @@ public TestDiscoveryIdentifiersRequiredResponse testDiscoveryIdentifiersRequired return clientHandler .execute(new ClientExecutionParams() - .withOperationName("TestDiscoveryIdentifiersRequired") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .discoveredEndpoint(cachedEndpoint) - .withRequestConfiguration(clientConfiguration) - .withInput(testDiscoveryIdentifiersRequiredRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("TestDiscoveryIdentifiersRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryIdentifiersRequired")) + .withOperationName("TestDiscoveryIdentifiersRequired").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .discoveredEndpoint(cachedEndpoint).withRequestConfiguration(clientConfiguration) + .withInput(testDiscoveryIdentifiersRequiredRequest).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new TestDiscoveryIdentifiersRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -269,15 +260,6 @@ public TestDiscoveryOptionalResponse testDiscoveryOptional(TestDiscoveryOptional HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, TestDiscoveryOptionalResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -308,11 +290,10 @@ public TestDiscoveryOptionalResponse testDiscoveryOptional(TestDiscoveryOptional .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .discoveredEndpoint(cachedEndpoint).withRequestConfiguration(clientConfiguration) .withInput(testDiscoveryOptionalRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("TestDiscoveryOptional", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryOptional")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new TestDiscoveryOptionalRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -338,15 +319,6 @@ public TestDiscoveryRequiredResponse testDiscoveryRequired(TestDiscoveryRequired HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, TestDiscoveryRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); boolean endpointDiscoveryEnabled = clientConfiguration.option(SdkClientOption.ENDPOINT_DISCOVERY_ENABLED); @@ -385,11 +357,10 @@ public TestDiscoveryRequiredResponse testDiscoveryRequired(TestDiscoveryRequired .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .discoveredEndpoint(cachedEndpoint).withRequestConfiguration(clientConfiguration) .withInput(testDiscoveryRequiredRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("TestDiscoveryRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("TestDiscoveryRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new TestDiscoveryRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -413,8 +384,17 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); EndpointDiscoveryTestAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -422,16 +402,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of EndpointDiscoveryTestAuthSchemeProvider")).orElse(null); EndpointDiscoveryTestAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(EndpointDiscoveryTestAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of EndpointDiscoveryTestAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultEndpointDiscoveryTestAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } EndpointDiscoveryTestAuthSchemeParams.Builder paramsBuilder = EndpointDiscoveryTestAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); EndpointDiscoveryTestEndpointProvider provider = (EndpointDiscoveryTestEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -463,14 +457,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); 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 552f5f7056a9..4dc65befa828 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 @@ -8,6 +8,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; @@ -17,7 +18,7 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.client.handler.AwsClientHandlerUtils; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; @@ -50,10 +51,10 @@ import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -62,7 +63,6 @@ import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -76,6 +76,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; import software.amazon.awssdk.services.json.batchmanager.JsonAsyncBatchManager; import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; @@ -167,10 +168,26 @@ final class DefaultJsonAsyncClient implements JsonAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInput": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + private final ScheduledExecutorService executorService; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + private final Executor executor; + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -224,18 +241,6 @@ public CompletableFuture aPostOperation(APostOperationRe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); String hostPrefix = "{StringMember}-foo."; @@ -249,16 +254,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) - .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).hostPrefixExpression(resolvedHostExpression) + .withInput(aPostOperationRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -304,18 +307,6 @@ public CompletableFuture aPostOperationWithOut HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationWithOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -325,16 +316,13 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) - .withInput(aPostOperationWithOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(aPostOperationWithOutputRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -376,18 +364,6 @@ public CompletableFuture bearerAuthOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, BearerAuthOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -397,16 +373,14 @@ public CompletableFuture bearerAuthOperation( .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")).credentialType(CredentialType.TOKEN) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).credentialType(CredentialType.TOKEN) .withInput(bearerAuthOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -476,18 +450,6 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -513,9 +475,9 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withFullDuplex(true) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EventStreamOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperation")) - .withInput(eventStreamOperationRequest), restAsyncResponseTransformer); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(eventStreamOperationRequest), + restAsyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { try { @@ -524,14 +486,14 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -575,18 +537,6 @@ public CompletableFuture eventStreamO HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, EventStreamOperationWithOnlyInputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); EventStreamTaggedUnionJsonMarshaller eventMarshaller = EventStreamTaggedUnionJsonMarshaller.builder() @@ -598,25 +548,18 @@ public CompletableFuture eventStreamO CompletableFuture executeFuture = clientHandler .execute(new ClientExecutionParams() - .withOperationName("EventStreamOperationWithOnlyInput") - .withProtocolMetadata(protocolMetadata) + .withOperationName("EventStreamOperationWithOnlyInput").withProtocolMetadata(protocolMetadata) .withMarshaller(new EventStreamOperationWithOnlyInputRequestMarshaller(protocolFactory)) - .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) + .withAsyncRequestBody(AsyncRequestBody.fromPublisher(adapted)).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyInput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyInput")) - .withInput(eventStreamOperationWithOnlyInputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(eventStreamOperationWithOnlyInputRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -688,18 +631,6 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( HttpResponseHandler errorEventResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, eventstreamExceptionMetadataMapper); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); CompletableFuture future = new CompletableFuture<>(); @@ -719,13 +650,10 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( .withOperationName("EventStreamOperationWithOnlyOutput") .withProtocolMetadata(protocolMetadata) .withMarshaller(new EventStreamOperationWithOnlyOutputRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("EventStreamOperationWithOnlyOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperationWithOnlyOutput")) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationWithOnlyOutputRequest), restAsyncResponseTransformer); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -735,14 +663,14 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( future.completeExceptionally(e); } } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -784,18 +712,6 @@ public CompletableFuture getOperationWithCheck HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetOperationWithChecksumResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -808,21 +724,19 @@ public CompletableFuture getOperationWithCheck .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withInput(getOperationWithChecksumRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -868,18 +782,6 @@ public CompletableFuture getWithoutRequiredMe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetWithoutRequiredMembersResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -889,16 +791,13 @@ public CompletableFuture getWithoutRequiredMe .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetWithoutRequiredMembers", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetWithoutRequiredMembers")) - .withInput(getWithoutRequiredMembersRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(getWithoutRequiredMembersRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -941,18 +840,6 @@ public CompletableFuture operationWithChe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithChecksumRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -965,18 +852,15 @@ public CompletableFuture operationWithChe .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1019,18 +903,6 @@ public CompletableFuture operationWithR HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithRequestCompressionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1043,19 +915,16 @@ public CompletableFuture operationWithR .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withInput(operationWithRequestCompressionRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1098,41 +967,22 @@ public CompletableFuture paginatedOpera HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); CompletableFuture executeFuture = clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithResultKey") - .withProtocolMetadata(protocolMetadata) + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithResultKey")) - .withInput(paginatedOperationWithResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(paginatedOperationWithResultKeyRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1175,41 +1025,22 @@ public CompletableFuture paginatedOp HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); CompletableFuture executeFuture = clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithoutResultKey") - .withProtocolMetadata(protocolMetadata) + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithoutResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithoutResultKey")) - .withInput(paginatedOperationWithoutResultKeyRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(paginatedOperationWithoutResultKeyRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1274,18 +1105,6 @@ public CompletableFuture putOperationWithChecksum( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PutOperationWithChecksumResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1301,8 +1120,8 @@ public CompletableFuture putOperationWithChecksum( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncRequestBody(requestBody) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, @@ -1328,7 +1147,7 @@ public CompletableFuture putOperationWithChecksum( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1337,7 +1156,7 @@ public CompletableFuture putOperationWithChecksum( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1384,18 +1203,6 @@ public CompletableFuture streamingInputOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1409,16 +1216,14 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")).withAsyncRequestBody(requestBody) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1475,18 +1280,6 @@ public CompletableFuture streamingInputOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1500,14 +1293,11 @@ public CompletableFuture streamingInputOutputOperation( .delegateMarshaller( new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) .asyncRequestBody(requestBody).transferEncoding(true).build()) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("StreamingInputOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOutputOperation")) - .withAsyncRequestBody(requestBody).withAsyncResponseTransformer(asyncResponseTransformer) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) + .withAsyncResponseTransformer(asyncResponseTransformer) .withInput(streamingInputOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { @@ -1516,7 +1306,7 @@ public CompletableFuture streamingInputOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1525,7 +1315,7 @@ public CompletableFuture streamingInputOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1577,18 +1367,6 @@ public CompletableFuture streamingOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1598,10 +1376,9 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) - .withAsyncResponseTransformer(asyncResponseTransformer).withInput(streamingOutputOperationRequest), - asyncResponseTransformer); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncResponseTransformer(asyncResponseTransformer) + .withInput(streamingOutputOperationRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { @@ -1609,7 +1386,7 @@ public CompletableFuture streamingOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); @@ -1618,7 +1395,7 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1658,8 +1435,25 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1667,15 +1461,29 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) .orElse(null); JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(JsonAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(JsonAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1706,14 +1514,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); @@ -1760,4 +1560,4 @@ private HttpResponseHandler createErrorResponseHandler(Base public void close() { clientHandler.close(); } -} +} \ No newline at end of file diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface-presignedurl.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface-presignedurl.java new file mode 100644 index 000000000000..4b5bfc7eb400 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface-presignedurl.java @@ -0,0 +1,123 @@ +package software.amazon.awssdk.services.json; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.awscore.AwsClient; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.presignedurl.AsyncPresignedUrlExtension; + +/** + * Service client for accessing Json Service asynchronously. This can be created using the static {@link #builder()} + * method.The asynchronous client performs non-blocking I/O when configured with any {@code SdkAsyncHttpClient} + * supported in the SDK. However, full non-blocking is not guaranteed as the async client may perform blocking calls in + * some cases such as credentials retrieval and endpoint discovery as part of the async API call. + * + * A service that is implemented using the json protocol + */ +@Generated("software.amazon.awssdk:codegen") +@SdkPublicApi +@ThreadSafe +public interface JsonAsyncClient extends AwsClient { + String SERVICE_NAME = "json-service"; + + /** + * Value for looking up the service's metadata from the + * {@link software.amazon.awssdk.regions.ServiceMetadataProvider}. + */ + String SERVICE_METADATA_ID = "json-service-endpoint"; + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + default CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { + throw new UnsupportedOperationException(); + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ *
+ *

+ * This is a convenience which creates an instance of the {@link APostOperationRequest.Builder} avoiding the need to + * create one manually via {@link APostOperationRequest#builder()} + *

+ * + * @param aPostOperationRequest + * A {@link Consumer} that will call methods on + * {@link software.amazon.awssdk.services.json.model.APostOperationRequest.Builder} to create a request. + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + default CompletableFuture aPostOperation(Consumer aPostOperationRequest) { + return aPostOperation(APostOperationRequest.builder().applyMutation(aPostOperationRequest).build()); + } + + /** + * Creates an instance of {@link AsyncPresignedUrlExtension} object with the configuration set on this client. + */ + default AsyncPresignedUrlExtension presignedUrlExtension() { + throw new UnsupportedOperationException(); + } + + @Override + default JsonServiceClientConfiguration serviceClientConfiguration() { + throw new UnsupportedOperationException(); + } + + /** + * Create a {@link JsonAsyncClient} with the region loaded from the + * {@link software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain} and credentials loaded from the + * {@link software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider}. + */ + static JsonAsyncClient create() { + return builder().build(); + } + + /** + * Create a builder that can be used to configure and create a {@link JsonAsyncClient}. + */ + static JsonAsyncClientBuilder builder() { + return new DefaultJsonAsyncClientBuilder(); + } +} 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 a557baa0385d..e3614218d546 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 @@ -4,11 +4,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -28,10 +29,10 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -39,7 +40,6 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.endpoints.Endpoint; @@ -55,6 +55,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; import software.amazon.awssdk.services.json.endpoints.internal.JsonEndpointResolverUtils; @@ -124,6 +125,21 @@ final class DefaultJsonClient implements JsonClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInput": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultJsonClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -159,18 +175,6 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, APostOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); @@ -191,11 +195,10 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -228,18 +231,6 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, APostOperationWithOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, @@ -257,12 +248,11 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -290,18 +280,6 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, BearerAuthOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(bearerAuthOperationRequest, @@ -319,11 +297,10 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -352,18 +329,6 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetOperationWithChecksumResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getOperationWithChecksumRequest, @@ -385,8 +350,8 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withRequestConfiguration(clientConfiguration) .withInput(getOperationWithChecksumRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) @@ -394,7 +359,7 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -427,18 +392,6 @@ public GetWithoutRequiredMembersResponse getWithoutRequiredMembers( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GetWithoutRequiredMembersResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getWithoutRequiredMembersRequest, @@ -456,12 +409,11 @@ public GetWithoutRequiredMembersResponse getWithoutRequiredMembers( .withOperationName("GetWithoutRequiredMembers").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(getWithoutRequiredMembersRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetWithoutRequiredMembers", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetWithoutRequiredMembers")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -490,18 +442,6 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithChecksumRequiredResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, @@ -523,14 +463,13 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( .withRequestConfiguration(clientConfiguration) .withInput(operationWithChecksumRequiredRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()) .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -559,18 +498,6 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithRequestCompressionResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, @@ -592,14 +519,13 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( .withRequestConfiguration(clientConfiguration) .withInput(operationWithRequestCompressionRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -628,18 +554,6 @@ public PaginatedOperationWithResultKeyResponse paginatedOperationWithResultKey( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithResultKeyRequest, @@ -654,19 +568,14 @@ public PaginatedOperationWithResultKeyResponse paginatedOperationWithResultKey( return clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithResultKey") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(paginatedOperationWithResultKeyRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithResultKey")) + .withOperationName("PaginatedOperationWithResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithResultKeyRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -695,18 +604,6 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PaginatedOperationWithoutResultKeyResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(paginatedOperationWithoutResultKeyRequest, @@ -721,19 +618,14 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul return clientHandler .execute(new ClientExecutionParams() - .withOperationName("PaginatedOperationWithoutResultKey") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(paginatedOperationWithoutResultKeyRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("PaginatedOperationWithoutResultKey", clientConfiguration)) - .withEndpointResolver(endpointResolver("PaginatedOperationWithoutResultKey")) + .withOperationName("PaginatedOperationWithoutResultKey").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(paginatedOperationWithoutResultKeyRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -788,18 +680,6 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, PutOperationWithChecksumResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putOperationWithChecksumRequest, @@ -821,8 +701,8 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withRequestConfiguration(clientConfiguration) .withInput(putOperationWithChecksumRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum @@ -845,7 +725,7 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) .requestBody(requestBody).build()), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -884,18 +764,6 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, @@ -917,15 +785,15 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -973,18 +841,6 @@ public ReturnT streamingInputOutputOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingInputOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOutputOperationRequest, @@ -1006,9 +862,8 @@ public ReturnT streamingInputOutputOperation( .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOutputOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("StreamingInputOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withResponseTransformer(responseTransformer) .withRequestBody(requestBody) .withMarshaller( @@ -1018,7 +873,7 @@ public ReturnT streamingInputOutputOperation( new StreamingInputOutputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).transferEncoding(true).build()), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -1054,18 +909,6 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, StreamingOutputOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, @@ -1083,13 +926,11 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) - .withResponseTransformer(responseTransformer) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withResponseTransformer(responseTransformer) .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -1121,8 +962,17 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1130,15 +980,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) .orElse(null); JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(JsonAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(JsonAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1169,14 +1034,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-presignedurl-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-presignedurl-async.java new file mode 100644 index 000000000000..b145e4c312e7 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-presignedurl-async.java @@ -0,0 +1,332 @@ +package software.amazon.awssdk.services.json; + +import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; +import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +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.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SelectedAuthScheme; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.AsyncClientHandler; +import software.amazon.awssdk.core.client.handler.ClientExecutionParams; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +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.metrics.CoreMetric; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.protocols.core.ExceptionMetadata; +import software.amazon.awssdk.protocols.json.AwsJsonProtocol; +import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory; +import software.amazon.awssdk.protocols.json.JsonOperationMetadata; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeParams; +import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.auth.scheme.internal.DefaultJsonAuthSchemeProvider; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointParams; +import software.amazon.awssdk.services.json.endpoints.JsonEndpointProvider; +import software.amazon.awssdk.services.json.endpoints.internal.JsonEndpointResolverUtils; +import software.amazon.awssdk.services.json.internal.JsonServiceClientConfigurationBuilder; +import software.amazon.awssdk.services.json.internal.ServiceVersionInfo; +import software.amazon.awssdk.services.json.internal.presignedurl.DefaultAsyncPresignedUrlExtension; +import software.amazon.awssdk.services.json.model.APostOperationRequest; +import software.amazon.awssdk.services.json.model.APostOperationResponse; +import software.amazon.awssdk.services.json.model.InvalidInputException; +import software.amazon.awssdk.services.json.model.JsonException; +import software.amazon.awssdk.services.json.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.json.transform.APostOperationRequestMarshaller; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +/** + * Internal implementation of {@link JsonAsyncClient}. + * + * @see JsonAsyncClient#builder() + */ +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +final class DefaultJsonAsyncClient implements JsonAsyncClient { + private static final Logger log = LoggerFactory.getLogger(DefaultJsonAsyncClient.class); + + private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() + .serviceProtocol(AwsServiceProtocol.AWS_JSON).build(); + + private final AsyncClientHandler clientHandler; + + private final AwsJsonProtocolFactory protocolFactory; + + private final SdkClientConfiguration clientConfiguration; + + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInputException": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInputException").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + + protected DefaultJsonAsyncClient(SdkClientConfiguration clientConfiguration) { + this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); + this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) + .option(SdkClientOption.API_METADATA, "Json_Service" + "#" + ServiceVersionInfo.VERSION).build(); + this.protocolFactory = init(AwsJsonProtocolFactory.builder()).build(); + } + + /** + *

+ * Performs a post operation to the query service and has no output + *

+ * + * @param aPostOperationRequest + * @return A Java Future containing the result of the APostOperation operation returned by the service.
+ * The CompletableFuture returned by this method can be completed exceptionally with the following + * exceptions. The exception returned is wrapped with CompletionException, so you need to invoke + * {@link Throwable#getCause} to retrieve the underlying exception. + *
    + *
  • InvalidInputException The request was rejected because an invalid or out-of-range value was supplied + * for an input parameter.
  • + *
  • SdkException Base class for all exceptions that can be thrown by the SDK (both service and client). + * Can be used for catch all scenarios.
  • + *
  • SdkClientException If any client side error occurs such as an IO related failure, failure to get + * credentials, etc.
  • + *
  • JsonException Base class for all service exceptions. Unknown exceptions will be thrown as an instance + * of this type.
  • + *
+ * @sample JsonAsyncClient.APostOperation + * @see AWS + * API Documentation + */ + @Override + public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { + SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); + List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector + .create("ApiCall"); + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); + JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) + .isPayloadJson(true).build(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + operationMetadata, APostOperationResponse::builder); + HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, + operationMetadata, exceptionMetadataMapper); + + CompletableFuture executeFuture = clientHandler + .execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(aPostOperationRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); + executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); + return executeFuture; + } catch (Throwable t) { + publishMetrics(metricPublishers, apiCallMetricCollector); + return CompletableFutureUtils.failedFuture(t); + } + } + + @Override + public AsyncPresignedUrlExtension presignedUrlExtension() { + return new DefaultAsyncPresignedUrlExtension(clientHandler, protocolFactory, clientConfiguration, protocolMetadata); + } + + @Override + public final JsonServiceClientConfiguration serviceClientConfiguration() { + return new JsonServiceClientConfigurationBuilder(this.clientConfiguration.toBuilder()).build(); + } + + @Override + public final String serviceName() { + return SERVICE_NAME; + } + + private > T init(T builder) { + return builder.clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(JsonException::builder) + .protocol(AwsJsonProtocol.AWS_JSON).protocolVersion("1.1"); + } + + private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, + RequestOverrideConfiguration requestOverrideConfiguration) { + List publishers = null; + if (requestOverrideConfiguration != null) { + publishers = requestOverrideConfiguration.metricPublishers(); + } + if (publishers == null || publishers.isEmpty()) { + publishers = clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS); + } + if (publishers == null) { + publishers = Collections.emptyList(); + } + return publishers; + } + + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); + JsonAuthSchemeProvider requestAuthSchemeProvider = request + .overrideConfiguration() + .flatMap(c -> c.authSchemeProvider()) + .map(p -> Validate + .isInstanceOf(JsonAuthSchemeProvider.class, p, "Expected an instance of JsonAuthSchemeProvider")) + .orElse(null); + JsonAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate + .isInstanceOf(JsonAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), + "Expected an instance of JsonAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultJsonAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } + JsonAuthSchemeParams.Builder paramsBuilder = JsonAuthSchemeParams.builder().operation(operationName); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } + return options; + } + + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); + JsonEndpointProvider provider = (JsonEndpointProvider) executionAttributes + .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); + try { + JsonEndpointParams endpointParams = JsonEndpointResolverUtils.ruleParams(request, executionAttributes); + Endpoint endpoint = provider.resolveEndpoint(endpointParams).join(); + if (!AwsEndpointProviderUtils.disableHostPrefixInjection(executionAttributes)) { + Optional hostPrefix = JsonEndpointResolverUtils.hostPrefix(operationName, request); + if (hostPrefix.isPresent()) { + endpoint = AwsEndpointProviderUtils.addHostPrefix(endpoint, hostPrefix.get()); + } + } + List endpointAuthSchemes = endpoint.attribute(AwsEndpointAttribute.AUTH_SCHEMES); + SelectedAuthScheme selectedAuthScheme = executionAttributes + .getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME); + if (endpointAuthSchemes != null && selectedAuthScheme != null) { + selectedAuthScheme = JsonEndpointResolverUtils.authSchemeWithEndpointSignerProperties(endpointAuthSchemes, + selectedAuthScheme); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, selectedAuthScheme); + } + JsonEndpointResolverUtils.setMetricValues(endpoint, executionAttributes); + return endpoint; + } catch (CompletionException e) { + Throwable cause = e.getCause(); + if (cause instanceof SdkClientException) { + throw (SdkClientException) cause; + } + throw SdkClientException.create("Endpoint resolution failed: " + cause.getMessage(), cause); + } + } + + private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { + ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); + RetryMode retryMode = builder.retryMode(); + if (retryMode != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.forRetryMode(retryMode)); + } else { + Consumer> configurator = builder.retryStrategyConfigurator(); + if (configurator != null) { + RetryStrategy.Builder defaultBuilder = AwsRetryStrategy.defaultRetryStrategy().toBuilder(); + configurator.accept(defaultBuilder); + configuration.option(SdkClientOption.RETRY_STRATEGY, defaultBuilder.build()); + } else { + RetryStrategy retryStrategy = builder.retryStrategy(); + if (retryStrategy != null) { + configuration.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + configuration.option(SdkClientOption.CONFIGURED_RETRY_MODE, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_STRATEGY, null); + configuration.option(SdkClientOption.CONFIGURED_RETRY_CONFIGURATOR, null); + } + + private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, SdkClientConfiguration clientConfiguration) { + List plugins = request.overrideConfiguration().map(c -> c.plugins()).orElse(Collections.emptyList()); + if (plugins.isEmpty()) { + return clientConfiguration; + } + SdkClientConfiguration.Builder configuration = clientConfiguration.toBuilder(); + JsonServiceClientConfigurationBuilder serviceConfigBuilder = new JsonServiceClientConfigurationBuilder(configuration); + for (SdkPlugin plugin : plugins) { + plugin.configureClient(serviceConfigBuilder); + } + updateRetryStrategyClientConfiguration(configuration); + return configuration.build(); + } + + private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, + JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { + return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); + } + + @Override + public void close() { + clientHandler.close(); + } +} 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 0a6706911756..1db3165fd3d6 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 @@ -7,13 +7,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -37,10 +38,10 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -48,7 +49,6 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -59,6 +59,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; +import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.services.query.endpoints.internal.QueryEndpointResolverUtils; @@ -140,6 +141,8 @@ final class DefaultQueryAsyncClient implements QueryAsyncClient { private final ScheduledExecutorService executorService; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultQueryAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -196,16 +199,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -258,16 +259,14 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(aPostOperationWithOutputRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -317,15 +316,13 @@ public CompletableFuture bearerAuthOperation( .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")).withInput(bearerAuthOperationRequest)); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(bearerAuthOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -377,8 +374,8 @@ public CompletableFuture getOperationWithCheck .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) @@ -386,12 +383,10 @@ public CompletableFuture getOperationWithCheck .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -444,18 +439,15 @@ public CompletableFuture operationWithChe .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -504,16 +496,14 @@ public CompletableFuture operationWithContext .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithContextParam")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithContextParamRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -563,16 +553,14 @@ public CompletableFuture operationWithCustomM .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithCustomMember", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithCustomMember")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithCustomMemberRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -626,17 +614,14 @@ public CompletableFuture o .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithCustomizedOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithCustomizedOperationContextParam")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithCustomizedOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -690,17 +675,14 @@ public CompletableFuture operatio .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithMapOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithMapOperationContextParam")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithMapOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -749,16 +731,14 @@ public CompletableFuture operationWithNoneAut .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithNoneAuthTypeRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -812,17 +792,14 @@ public CompletableFuture operationWi .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithOperationContextParam")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -875,19 +852,16 @@ public CompletableFuture operationWithR .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .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())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -940,17 +914,14 @@ public CompletableFuture operationWith .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithStaticContextParams", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithStaticContextParams")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithStaticContextParamsRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1028,8 +999,8 @@ public CompletableFuture putOperationWithChecksum( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum @@ -1053,7 +1024,7 @@ public CompletableFuture putOperationWithChecksum( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); @@ -1061,7 +1032,7 @@ public CompletableFuture putOperationWithChecksum( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1119,16 +1090,14 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")).withAsyncRequestBody(requestBody) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1187,8 +1156,8 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncResponseTransformer(asyncResponseTransformer).withInput(streamingOutputOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; @@ -1199,7 +1168,7 @@ public CompletableFuture streamingOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); @@ -1207,7 +1176,7 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1251,23 +1220,55 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(QueryAuthSchemeProvider.class, p, "Expected an instance of QueryAuthSchemeProvider")).orElse(null); QueryAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(QueryAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(QueryAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of QueryAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultQueryAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } QueryAuthSchemeParams.Builder paramsBuilder = QueryAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1298,14 +1299,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); 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 004e8f563a94..e2805f5e9075 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 @@ -4,10 +4,11 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -28,10 +29,10 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -39,7 +40,6 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.endpoints.Endpoint; @@ -52,6 +52,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeParams; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; +import software.amazon.awssdk.services.query.auth.scheme.internal.DefaultQueryAuthSchemeProvider; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.services.query.endpoints.internal.QueryEndpointResolverUtils; @@ -130,6 +131,8 @@ final class DefaultQueryClient implements QueryClient { private final SdkClientConfiguration clientConfiguration; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultQueryClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -181,11 +184,10 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -233,12 +235,11 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -281,11 +282,10 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -333,8 +333,8 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withRequestConfiguration(clientConfiguration) .withInput(getOperationWithChecksumRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) @@ -342,7 +342,7 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -390,14 +390,13 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( .withRequestConfiguration(clientConfiguration) .withInput(operationWithChecksumRequiredRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()) .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -441,12 +440,11 @@ public OperationWithContextParamResponse operationWithContextParam( .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(operationWithContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithContextParam")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -491,12 +489,11 @@ public OperationWithCustomMemberResponse operationWithCustomMember( .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(operationWithCustomMemberRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithCustomMember", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithCustomMember")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -539,18 +536,14 @@ public OperationWithCustomizedOperationContextParamResponse operationWithCustomi return clientHandler .execute(new ClientExecutionParams() .withOperationName("OperationWithCustomizedOperationContextParam") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) + .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withInput(operationWithCustomizedOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithCustomizedOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithCustomizedOperationContextParam")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -592,19 +585,15 @@ public OperationWithMapOperationContextParamResponse operationWithMapOperationCo return clientHandler .execute(new ClientExecutionParams() - .withOperationName("OperationWithMapOperationContextParam") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) + .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) - .withInput(operationWithMapOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithMapOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithMapOperationContextParam")) + .withInput(operationWithMapOperationContextParamRequest).withMetricCollector(apiCallMetricCollector) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -648,12 +637,11 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -695,19 +683,14 @@ public OperationWithOperationContextParamResponse operationWithOperationContextP return clientHandler .execute(new ClientExecutionParams() - .withOperationName("OperationWithOperationContextParam") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithOperationContextParam", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithOperationContextParam")) + .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithOperationContextParamRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -755,14 +738,13 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( .withRequestConfiguration(clientConfiguration) .withInput(operationWithRequestCompressionRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -803,19 +785,14 @@ public OperationWithStaticContextParamsResponse operationWithStaticContextParams return clientHandler .execute(new ClientExecutionParams() - .withOperationName("OperationWithStaticContextParams") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithStaticContextParamsRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithStaticContextParams", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithStaticContextParams")) + .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithStaticContextParamsRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -889,8 +866,8 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withRequestConfiguration(clientConfiguration) .withInput(putOperationWithChecksumRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum @@ -911,7 +888,7 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -969,15 +946,15 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -1028,13 +1005,11 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) - .withResponseTransformer(responseTransformer) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withResponseTransformer(responseTransformer) .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -1071,23 +1046,47 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(QueryAuthSchemeProvider.class, p, "Expected an instance of QueryAuthSchemeProvider")).orElse(null); QueryAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(QueryAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(QueryAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of QueryAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultQueryAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } QueryAuthSchemeParams.Builder paramsBuilder = QueryAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1118,14 +1117,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java index dddf865558a1..61690e57d4ed 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java @@ -7,13 +7,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -31,14 +32,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -52,6 +52,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.SmithyRpcV2ProtocolAuthSchemeParams; import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.SmithyRpcV2ProtocolAuthSchemeProvider; +import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.internal.DefaultSmithyRpcV2ProtocolAuthSchemeProvider; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.SmithyRpcV2ProtocolEndpointParams; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.SmithyRpcV2ProtocolEndpointProvider; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.internal.SmithyRpcV2ProtocolEndpointResolverUtils; @@ -122,6 +123,27 @@ final class DefaultSmithyRpcV2ProtocolAsyncClient implements SmithyRpcV2Protocol private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "ValidationException": + return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") + .exceptionBuilderSupplier(ValidationException::builder).build()); + case "InvalidGreeting": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") + .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); + case "ComplexError": + return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") + .exceptionBuilderSupplier(ComplexErrorException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultSmithyRpcV2ProtocolAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -165,24 +187,6 @@ public CompletableFuture emptyInputOutput(EmptyInputOu HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, EmptyInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -192,15 +196,13 @@ public CompletableFuture emptyInputOutput(EmptyInputOu .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EmptyInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EmptyInputOutput")).withInput(emptyInputOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(emptyInputOutputRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -240,24 +242,6 @@ public CompletableFuture float16(Float16Request float16Request) HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, Float16Response::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -266,15 +250,13 @@ public CompletableFuture float16(Float16Request float16Request) .withProtocolMetadata(protocolMetadata).withMarshaller(new Float16RequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("Float16", clientConfiguration)) - .withEndpointResolver(endpointResolver("Float16")).withInput(float16Request)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(float16Request)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -315,24 +297,6 @@ public CompletableFuture fractionalSeconds(Fractional HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, FractionalSecondsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -342,15 +306,13 @@ public CompletableFuture fractionalSeconds(Fractional .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("FractionalSeconds", clientConfiguration)) - .withEndpointResolver(endpointResolver("FractionalSeconds")).withInput(fractionalSecondsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(fractionalSecondsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -393,24 +355,6 @@ public CompletableFuture greetingWithErrors(Greeting HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GreetingWithErrorsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -420,15 +364,13 @@ public CompletableFuture greetingWithErrors(Greeting .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GreetingWithErrors", clientConfiguration)) - .withEndpointResolver(endpointResolver("GreetingWithErrors")).withInput(greetingWithErrorsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(greetingWithErrorsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -468,24 +410,6 @@ public CompletableFuture noInputOutput(NoInputOutputReque HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, NoInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -495,15 +419,13 @@ public CompletableFuture noInputOutput(NoInputOutputReque .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("NoInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("NoInputOutput")).withInput(noInputOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(noInputOutputRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -546,24 +468,6 @@ public CompletableFuture operationWithDefaults( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithDefaultsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -573,16 +477,14 @@ public CompletableFuture operationWithDefaults( .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithDefaults", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithDefaults")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithDefaultsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -624,24 +526,6 @@ public CompletableFuture optionalInputOutput( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OptionalInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -651,15 +535,13 @@ public CompletableFuture optionalInputOutput( .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OptionalInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("OptionalInputOutput")).withInput(optionalInputOutputRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(optionalInputOutputRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -700,24 +582,6 @@ public CompletableFuture recursiveShapes(RecursiveShape HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RecursiveShapesResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -727,15 +591,13 @@ public CompletableFuture recursiveShapes(RecursiveShape .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RecursiveShapes", clientConfiguration)) - .withEndpointResolver(endpointResolver("RecursiveShapes")).withInput(recursiveShapesRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(recursiveShapesRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -777,24 +639,6 @@ public CompletableFuture rpcV2CborDenseMaps(RpcV2Cbo HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RpcV2CborDenseMapsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -804,15 +648,13 @@ public CompletableFuture rpcV2CborDenseMaps(RpcV2Cbo .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborDenseMaps", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborDenseMaps")).withInput(rpcV2CborDenseMapsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(rpcV2CborDenseMapsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -853,24 +695,6 @@ public CompletableFuture rpcV2CborLists(RpcV2CborListsRe HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RpcV2CborListsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -880,15 +704,13 @@ public CompletableFuture rpcV2CborLists(RpcV2CborListsRe .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborLists", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborLists")).withInput(rpcV2CborListsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(rpcV2CborListsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -931,24 +753,6 @@ public CompletableFuture rpcV2CborSparseMaps( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RpcV2CborSparseMapsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -958,15 +762,13 @@ public CompletableFuture rpcV2CborSparseMaps( .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborSparseMaps", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborSparseMaps")).withInput(rpcV2CborSparseMapsRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(rpcV2CborSparseMapsRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1008,24 +810,6 @@ public CompletableFuture simpleScalarProperties( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, SimpleScalarPropertiesResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1035,16 +819,14 @@ public CompletableFuture simpleScalarProperties( .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("SimpleScalarProperties", clientConfiguration)) - .withEndpointResolver(endpointResolver("SimpleScalarProperties")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(simpleScalarPropertiesRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1086,24 +868,6 @@ public CompletableFuture sparseNullsOperation( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, SparseNullsOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -1113,16 +877,14 @@ public CompletableFuture sparseNullsOperation( .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("SparseNullsOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("SparseNullsOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(sparseNullsOperationRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1158,8 +920,26 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); SmithyRpcV2ProtocolAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1167,16 +947,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of SmithyRpcV2ProtocolAuthSchemeProvider")).orElse(null); SmithyRpcV2ProtocolAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(SmithyRpcV2ProtocolAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of SmithyRpcV2ProtocolAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultSmithyRpcV2ProtocolAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } SmithyRpcV2ProtocolAuthSchemeParams.Builder paramsBuilder = SmithyRpcV2ProtocolAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); SmithyRpcV2ProtocolEndpointProvider provider = (SmithyRpcV2ProtocolEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1208,14 +1002,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java index 8beb520ef006..a19916101f43 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java @@ -4,11 +4,12 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -26,14 +27,13 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -47,6 +47,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.SmithyRpcV2ProtocolAuthSchemeParams; import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.SmithyRpcV2ProtocolAuthSchemeProvider; +import software.amazon.awssdk.services.smithyrpcv2protocol.auth.scheme.internal.DefaultSmithyRpcV2ProtocolAuthSchemeProvider; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.SmithyRpcV2ProtocolEndpointParams; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.SmithyRpcV2ProtocolEndpointProvider; import software.amazon.awssdk.services.smithyrpcv2protocol.endpoints.internal.SmithyRpcV2ProtocolEndpointResolverUtils; @@ -117,6 +118,27 @@ final class DefaultSmithyRpcV2ProtocolClient implements SmithyRpcV2ProtocolClien private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "ValidationException": + return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") + .exceptionBuilderSupplier(ValidationException::builder).build()); + case "InvalidGreeting": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") + .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); + case "ComplexError": + return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") + .exceptionBuilderSupplier(ComplexErrorException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultSmithyRpcV2ProtocolClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -148,24 +170,6 @@ public EmptyInputOutputResponse emptyInputOutput(EmptyInputOutputRequest emptyIn HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, EmptyInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(emptyInputOutputRequest, @@ -183,11 +187,11 @@ public EmptyInputOutputResponse emptyInputOutput(EmptyInputOutputRequest emptyIn .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(emptyInputOutputRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EmptyInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("EmptyInputOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -215,24 +219,6 @@ public Float16Response float16(Float16Request float16Request) throws AwsServiceE HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, Float16Response::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(float16Request, this.clientConfiguration); @@ -248,11 +234,11 @@ public Float16Response float16(Float16Request float16Request) throws AwsServiceE .withOperationName("Float16").withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withInput(float16Request).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("Float16", clientConfiguration)) - .withEndpointResolver(endpointResolver("Float16")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new Float16RequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -280,24 +266,6 @@ public FractionalSecondsResponse fractionalSeconds(FractionalSecondsRequest frac HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, FractionalSecondsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(fractionalSecondsRequest, @@ -315,11 +283,11 @@ public FractionalSecondsResponse fractionalSeconds(FractionalSecondsRequest frac .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(fractionalSecondsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("FractionalSeconds", clientConfiguration)) - .withEndpointResolver(endpointResolver("FractionalSeconds")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -350,24 +318,6 @@ public GreetingWithErrorsResponse greetingWithErrors(GreetingWithErrorsRequest g HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, GreetingWithErrorsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(greetingWithErrorsRequest, @@ -385,11 +335,11 @@ public GreetingWithErrorsResponse greetingWithErrors(GreetingWithErrorsRequest g .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(greetingWithErrorsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GreetingWithErrors", clientConfiguration)) - .withEndpointResolver(endpointResolver("GreetingWithErrors")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -417,24 +367,6 @@ public NoInputOutputResponse noInputOutput(NoInputOutputRequest noInputOutputReq HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, NoInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(noInputOutputRequest, this.clientConfiguration); @@ -451,11 +383,11 @@ public NoInputOutputResponse noInputOutput(NoInputOutputRequest noInputOutputReq .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(noInputOutputRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("NoInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("NoInputOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -484,24 +416,6 @@ public OperationWithDefaultsResponse operationWithDefaults(OperationWithDefaults HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OperationWithDefaultsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithDefaultsRequest, @@ -519,11 +433,11 @@ public OperationWithDefaultsResponse operationWithDefaults(OperationWithDefaults .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(operationWithDefaultsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithDefaults", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithDefaults")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -551,24 +465,6 @@ public OptionalInputOutputResponse optionalInputOutput(OptionalInputOutputReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OptionalInputOutputResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(optionalInputOutputRequest, @@ -586,11 +482,11 @@ public OptionalInputOutputResponse optionalInputOutput(OptionalInputOutputReques .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(optionalInputOutputRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OptionalInputOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("OptionalInputOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -618,24 +514,6 @@ public RecursiveShapesResponse recursiveShapes(RecursiveShapesRequest recursiveS HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, RecursiveShapesResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(recursiveShapesRequest, @@ -653,11 +531,11 @@ public RecursiveShapesResponse recursiveShapes(RecursiveShapesRequest recursiveS .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(recursiveShapesRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RecursiveShapes", clientConfiguration)) - .withEndpointResolver(endpointResolver("RecursiveShapes")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -686,24 +564,6 @@ public RpcV2CborDenseMapsResponse rpcV2CborDenseMaps(RpcV2CborDenseMapsRequest r HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RpcV2CborDenseMapsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(rpcV2CborDenseMapsRequest, @@ -721,11 +581,11 @@ public RpcV2CborDenseMapsResponse rpcV2CborDenseMaps(RpcV2CborDenseMapsRequest r .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborDenseMapsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborDenseMaps", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborDenseMaps")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -754,24 +614,6 @@ public RpcV2CborListsResponse rpcV2CborLists(RpcV2CborListsRequest rpcV2CborList HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, RpcV2CborListsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(rpcV2CborListsRequest, this.clientConfiguration); @@ -788,11 +630,11 @@ public RpcV2CborListsResponse rpcV2CborLists(RpcV2CborListsRequest rpcV2CborList .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborListsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborLists", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborLists")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -821,24 +663,6 @@ public RpcV2CborSparseMapsResponse rpcV2CborSparseMaps(RpcV2CborSparseMapsReques HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, RpcV2CborSparseMapsResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(rpcV2CborSparseMapsRequest, @@ -856,11 +680,11 @@ public RpcV2CborSparseMapsResponse rpcV2CborSparseMaps(RpcV2CborSparseMapsReques .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborSparseMapsRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("RpcV2CborSparseMaps", clientConfiguration)) - .withEndpointResolver(endpointResolver("RpcV2CborSparseMaps")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -888,24 +712,6 @@ public SimpleScalarPropertiesResponse simpleScalarProperties(SimpleScalarPropert HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, SimpleScalarPropertiesResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(simpleScalarPropertiesRequest, @@ -924,11 +730,11 @@ public SimpleScalarPropertiesResponse simpleScalarProperties(SimpleScalarPropert .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(simpleScalarPropertiesRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("SimpleScalarProperties", clientConfiguration)) - .withEndpointResolver(endpointResolver("SimpleScalarProperties")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -956,24 +762,6 @@ public SparseNullsOperationResponse sparseNullsOperation(SparseNullsOperationReq HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, SparseNullsOperationResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "ValidationException": - return Optional.of(ExceptionMetadata.builder().errorCode("ValidationException") - .exceptionBuilderSupplier(ValidationException::builder).build()); - case "InvalidGreeting": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidGreeting") - .exceptionBuilderSupplier(InvalidGreetingException::builder).build()); - case "ComplexError": - return Optional.of(ExceptionMetadata.builder().errorCode("ComplexError") - .exceptionBuilderSupplier(ComplexErrorException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(sparseNullsOperationRequest, @@ -991,11 +779,11 @@ public SparseNullsOperationResponse sparseNullsOperation(SparseNullsOperationReq .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(sparseNullsOperationRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("SparseNullsOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("SparseNullsOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -1019,8 +807,18 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); SmithyRpcV2ProtocolAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) @@ -1028,16 +826,30 @@ private List resolveAuthSchemeOptions(SdkRequest request, Stri "Expected an instance of SmithyRpcV2ProtocolAuthSchemeProvider")).orElse(null); SmithyRpcV2ProtocolAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate.isInstanceOf(SmithyRpcV2ProtocolAuthSchemeProvider.class, - clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of SmithyRpcV2ProtocolAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultSmithyRpcV2ProtocolAuthSchemeProvider; + String cacheKey = String.valueOf(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } SmithyRpcV2ProtocolAuthSchemeParams.Builder paramsBuilder = SmithyRpcV2ProtocolAuthSchemeParams.builder().operation( operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); SmithyRpcV2ProtocolEndpointProvider provider = (SmithyRpcV2ProtocolEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1069,14 +881,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-async-client-class.java index 12bceafed07b..ef3bdd024982 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-async-client-class.java @@ -8,13 +8,14 @@ import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -33,15 +34,14 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme; import software.amazon.awssdk.http.auth.aws.signer.AwsV4aHttpSigner; @@ -58,6 +58,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider; +import software.amazon.awssdk.services.database.auth.scheme.internal.DefaultDatabaseAuthSchemeProvider; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointParams; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider; import software.amazon.awssdk.services.database.endpoints.internal.DatabaseEndpointResolverUtils; @@ -121,6 +122,21 @@ final class DefaultDatabaseAsyncClient implements DatabaseAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInput": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultDatabaseAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -167,18 +183,6 @@ public CompletableFuture deleteRow(DeleteRowRequest deleteRow HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, DeleteRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -188,15 +192,13 @@ public CompletableFuture deleteRow(DeleteRowRequest deleteRow .withMarshaller(new DeleteRowRequestMarshaller(protocolFactory)).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("DeleteRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("DeleteRow")).withInput(deleteRowRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(deleteRowRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -240,18 +242,6 @@ public CompletableFuture getRow(GetRowRequest getRowRequest) { HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, GetRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -260,15 +250,13 @@ public CompletableFuture getRow(GetRowRequest getRowRequest) { .withProtocolMetadata(protocolMetadata).withMarshaller(new GetRowRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetRow")).withInput(getRowRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(getRowRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -316,18 +304,6 @@ public CompletableFuture opWithSigv HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, OpWithSigv4AndSigv4AUnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -340,17 +316,14 @@ public CompletableFuture opWithSigv .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opWithSigv4AndSigv4aUnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4AndSigv4aUnSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opWithSigv4AndSigv4AUnSignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -396,18 +369,6 @@ public CompletableFuture opWithSigv4SignedPayl HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4SignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -417,16 +378,14 @@ public CompletableFuture opWithSigv4SignedPayl .withMarshaller(new OpWithSigv4SignedPayloadRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4SignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4SignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opWithSigv4SignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -472,18 +431,6 @@ public CompletableFuture opWithSigv4UnSigned HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4UnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -493,16 +440,14 @@ public CompletableFuture opWithSigv4UnSigned .withMarshaller(new OpWithSigv4UnSignedPayloadRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4UnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4UnSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opWithSigv4UnSignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -556,18 +501,6 @@ public CompletableFuture opWithS HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, OpWithSigv4UnSignedPayloadAndStreamingResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -585,18 +518,15 @@ public CompletableFuture opWithS .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opWithSigv4UnSignedPayloadAndStreaming", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4UnSignedPayloadAndStreaming")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncRequestBody(requestBody).withInput(opWithSigv4UnSignedPayloadAndStreamingRequest)); - CompletableFuture whenCompleted = executeFuture - .whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete( + executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -642,18 +572,6 @@ public CompletableFuture opWithSigv4aSignedPa HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -663,16 +581,14 @@ public CompletableFuture opWithSigv4aSignedPa .withMarshaller(new OpWithSigv4ASignedPayloadRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4aSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opWithSigv4ASignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -718,18 +634,6 @@ public CompletableFuture opWithSigv4aUnSign HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4AUnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -742,16 +646,14 @@ public CompletableFuture opWithSigv4aUnSign .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4aUnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4aUnSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opWithSigv4AUnSignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -799,18 +701,6 @@ public CompletableFuture opsWithSigv HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, OpsWithSigv4AndSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -823,17 +713,14 @@ public CompletableFuture opsWithSigv .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opsWithSigv4andSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opsWithSigv4andSigv4aSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(opsWithSigv4AndSigv4ASignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -877,18 +764,6 @@ public CompletableFuture putRow(PutRowRequest putRowRequest) { HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, PutRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -897,15 +772,13 @@ public CompletableFuture putRow(PutRowRequest putRowRequest) { .withProtocolMetadata(protocolMetadata).withMarshaller(new PutRowRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutRow")).withInput(putRowRequest)); - CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(putRowRequest)); + CompletableFuture whenCompleted = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -953,18 +826,6 @@ public CompletableFuture secon HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, SecondOpsWithSigv4AndSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); @@ -977,18 +838,15 @@ public CompletableFuture secon .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("secondOpsWithSigv4andSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("secondOpsWithSigv4andSigv4aSignedPayload")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(secondOpsWithSigv4AndSigv4ASignedPayloadRequest)); - CompletableFuture whenCompleted = executeFuture - .whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + CompletableFuture whenCompleted = publishMetricsWhenComplete( + executeFuture, metricPublishers, apiCallMetricCollector); executeFuture = CompletableFutureUtils.forwardExceptionTo(whenCompleted, executeFuture); return executeFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -1023,27 +881,60 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); DatabaseAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(DatabaseAuthSchemeProvider.class, p, "Expected an instance of DatabaseAuthSchemeProvider")).orElse(null); DatabaseAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(DatabaseAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(DatabaseAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of DatabaseAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultDatabaseAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION) + ":" + + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } DatabaseAuthSchemeParams.Builder paramsBuilder = DatabaseAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); - Set sigv4aRegionSet = clientConfiguration.option(AwsClientOption.AWS_SIGV4A_SIGNING_REGION_SET); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + Set sigv4aRegionSet = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET); if (!CollectionUtils.isNullOrEmpty(sigv4aRegionSet)) { paramsBuilder.regionSet(RegionSet.create(sigv4aRegionSet)); } List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); DatabaseEndpointProvider provider = (DatabaseEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -1083,14 +974,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-sync-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-sync-client-class.java index 299f08752a84..3d79abaea0da 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-sync-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-unsigned-payload-trait-sync-client-class.java @@ -5,11 +5,12 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -27,15 +28,14 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.aws.scheme.AwsV4aAuthScheme; @@ -53,6 +53,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeParams; import software.amazon.awssdk.services.database.auth.scheme.DatabaseAuthSchemeProvider; +import software.amazon.awssdk.services.database.auth.scheme.internal.DefaultDatabaseAuthSchemeProvider; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointParams; import software.amazon.awssdk.services.database.endpoints.DatabaseEndpointProvider; import software.amazon.awssdk.services.database.endpoints.internal.DatabaseEndpointResolverUtils; @@ -116,6 +117,21 @@ final class DefaultDatabaseClient implements DatabaseClient { private final SdkClientConfiguration clientConfiguration; + private final Function> exceptionMetadataMapper = errorCode -> { + if (errorCode == null) { + return Optional.empty(); + } + switch (errorCode) { + case "InvalidInput": + return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) + .exceptionBuilderSupplier(InvalidInputException::builder).build()); + default: + return Optional.empty(); + } + }; + + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultDatabaseClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -151,18 +167,6 @@ public DeleteRowResponse deleteRow(DeleteRowRequest deleteRowRequest) throws Inv HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, DeleteRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(deleteRowRequest, this.clientConfiguration); @@ -178,11 +182,10 @@ public DeleteRowResponse deleteRow(DeleteRowRequest deleteRowRequest) throws Inv .withOperationName("DeleteRow").withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withInput(deleteRowRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("DeleteRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("DeleteRow")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new DeleteRowRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -214,18 +217,6 @@ public GetRowResponse getRow(GetRowRequest getRowRequest) throws InvalidInputExc HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, GetRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getRowRequest, this.clientConfiguration); @@ -241,11 +232,10 @@ public GetRowResponse getRow(GetRowRequest getRowRequest) throws InvalidInputExc .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withInput(getRowRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetRow")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new GetRowRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -277,18 +267,6 @@ public PutRowResponse putRow(PutRowRequest putRowRequest) throws InvalidInputExc HttpResponseHandler responseHandler = protocolFactory.createResponseHandler(operationMetadata, PutRowResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putRowRequest, this.clientConfiguration); @@ -304,11 +282,10 @@ public PutRowResponse putRow(PutRowRequest putRowRequest) throws InvalidInputExc .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) .withInput(putRowRequest).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutRow", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutRow")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions).withEndpointResolver(this::resolveEndpoint) .withMarshaller(new PutRowRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -342,18 +319,6 @@ public OpWithSigv4AndSigv4AUnSignedPayloadResponse opWithSigv4AndSigv4aUnSignedP HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4AndSigv4AUnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4AndSigv4AUnSignedPayloadRequest, @@ -368,19 +333,14 @@ public OpWithSigv4AndSigv4AUnSignedPayloadResponse opWithSigv4AndSigv4aUnSignedP return clientHandler .execute(new ClientExecutionParams() - .withOperationName("opWithSigv4AndSigv4aUnSignedPayload") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(opWithSigv4AndSigv4AUnSignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opWithSigv4AndSigv4aUnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4AndSigv4aUnSignedPayload")) + .withOperationName("opWithSigv4AndSigv4aUnSignedPayload").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(opWithSigv4AndSigv4AUnSignedPayloadRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpWithSigv4AndSigv4AUnSignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -413,18 +373,6 @@ public OpWithSigv4SignedPayloadResponse opWithSigv4SignedPayload( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4SignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4SignedPayloadRequest, @@ -442,12 +390,11 @@ public OpWithSigv4SignedPayloadResponse opWithSigv4SignedPayload( .withOperationName("opWithSigv4SignedPayload").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(opWithSigv4SignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4SignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4SignedPayload")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpWithSigv4SignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -480,18 +427,6 @@ public OpWithSigv4UnSignedPayloadResponse opWithSigv4UnSignedPayload( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4UnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4UnSignedPayloadRequest, @@ -509,12 +444,11 @@ public OpWithSigv4UnSignedPayloadResponse opWithSigv4UnSignedPayload( .withOperationName("opWithSigv4UnSignedPayload").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(opWithSigv4UnSignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4UnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4UnSignedPayload")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpWithSigv4UnSignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -559,18 +493,6 @@ public OpWithSigv4UnSignedPayloadAndStreamingResponse opWithSigv4UnSignedPayload HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, OpWithSigv4UnSignedPayloadAndStreamingResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4UnSignedPayloadAndStreamingRequest, @@ -592,9 +514,8 @@ public OpWithSigv4UnSignedPayloadAndStreamingResponse opWithSigv4UnSignedPayload .withRequestConfiguration(clientConfiguration) .withInput(opWithSigv4UnSignedPayloadAndStreamingRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opWithSigv4UnSignedPayloadAndStreaming", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4UnSignedPayloadAndStreaming")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller @@ -603,7 +524,7 @@ public OpWithSigv4UnSignedPayloadAndStreamingResponse opWithSigv4UnSignedPayload new OpWithSigv4UnSignedPayloadAndStreamingRequestMarshaller(protocolFactory)) .requestBody(requestBody).transferEncoding(true).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -636,18 +557,6 @@ public OpWithSigv4ASignedPayloadResponse opWithSigv4aSignedPayload( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4ASignedPayloadRequest, @@ -665,12 +574,11 @@ public OpWithSigv4ASignedPayloadResponse opWithSigv4aSignedPayload( .withOperationName("opWithSigv4aSignedPayload").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(opWithSigv4ASignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4aSignedPayload")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpWithSigv4ASignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -703,18 +611,6 @@ public OpWithSigv4AUnSignedPayloadResponse opWithSigv4aUnSignedPayload( HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpWithSigv4AUnSignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opWithSigv4AUnSignedPayloadRequest, @@ -729,18 +625,14 @@ public OpWithSigv4AUnSignedPayloadResponse opWithSigv4aUnSignedPayload( return clientHandler .execute(new ClientExecutionParams() - .withOperationName("opWithSigv4aUnSignedPayload") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(opWithSigv4AUnSignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("opWithSigv4aUnSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opWithSigv4aUnSignedPayload")) + .withOperationName("opWithSigv4aUnSignedPayload").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(opWithSigv4AUnSignedPayloadRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpWithSigv4AUnSignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -774,18 +666,6 @@ public OpsWithSigv4AndSigv4ASignedPayloadResponse opsWithSigv4andSigv4aSignedPay HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( operationMetadata, OpsWithSigv4AndSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(opsWithSigv4AndSigv4ASignedPayloadRequest, @@ -800,19 +680,14 @@ public OpsWithSigv4AndSigv4ASignedPayloadResponse opsWithSigv4andSigv4aSignedPay return clientHandler .execute(new ClientExecutionParams() - .withOperationName("opsWithSigv4andSigv4aSignedPayload") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(opsWithSigv4AndSigv4ASignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("opsWithSigv4andSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("opsWithSigv4andSigv4aSignedPayload")) + .withOperationName("opsWithSigv4andSigv4aSignedPayload").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(opsWithSigv4AndSigv4ASignedPayloadRequest) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OpsWithSigv4AndSigv4ASignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -846,18 +721,6 @@ public SecondOpsWithSigv4AndSigv4ASignedPayloadResponse secondOpsWithSigv4andSig HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(operationMetadata, SecondOpsWithSigv4AndSigv4ASignedPayloadResponse::builder); - Function> exceptionMetadataMapper = errorCode -> { - if (errorCode == null) { - return Optional.empty(); - } - switch (errorCode) { - case "InvalidInput": - return Optional.of(ExceptionMetadata.builder().errorCode("InvalidInput").httpStatusCode(400) - .exceptionBuilderSupplier(InvalidInputException::builder).build()); - default: - return Optional.empty(); - } - }; HttpResponseHandler errorResponseHandler = createErrorResponseHandler(protocolFactory, operationMetadata, exceptionMetadataMapper); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration( @@ -872,19 +735,15 @@ public SecondOpsWithSigv4AndSigv4ASignedPayloadResponse secondOpsWithSigv4andSig return clientHandler .execute(new ClientExecutionParams() - .withOperationName("secondOpsWithSigv4andSigv4aSignedPayload") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) + .withOperationName("secondOpsWithSigv4andSigv4aSignedPayload").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withInput(secondOpsWithSigv4AndSigv4ASignedPayloadRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("secondOpsWithSigv4andSigv4aSignedPayload", clientConfiguration)) - .withEndpointResolver(endpointResolver("secondOpsWithSigv4andSigv4aSignedPayload")) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new SecondOpsWithSigv4AndSigv4ASignedPayloadRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -908,27 +767,52 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); DatabaseAuthSchemeProvider requestAuthSchemeProvider = request .overrideConfiguration() .flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(DatabaseAuthSchemeProvider.class, p, "Expected an instance of DatabaseAuthSchemeProvider")).orElse(null); DatabaseAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(DatabaseAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(DatabaseAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of DatabaseAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultDatabaseAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION) + ":" + + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } DatabaseAuthSchemeParams.Builder paramsBuilder = DatabaseAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); - Set sigv4aRegionSet = clientConfiguration.option(AwsClientOption.AWS_SIGV4A_SIGNING_REGION_SET); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); + Set sigv4aRegionSet = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET); if (!CollectionUtils.isNullOrEmpty(sigv4aRegionSet)) { paramsBuilder.regionSet(RegionSet.create(sigv4aRegionSet)); } List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); DatabaseEndpointProvider provider = (DatabaseEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -968,14 +852,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private HttpResponseHandler createErrorResponseHandler(BaseAwsJsonProtocolFactory protocolFactory, JsonOperationMetadata operationMetadata, Function> exceptionMetadataMapper) { return protocolFactory.createErrorResponseHandler(operationMetadata, exceptionMetadataMapper); 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 55a64c1b706a..29a4cf905133 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 @@ -7,13 +7,14 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -42,10 +43,10 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -53,7 +54,6 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.metrics.MetricCollector; @@ -65,6 +65,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.xml.auth.scheme.XmlAuthSchemeParams; import software.amazon.awssdk.services.xml.auth.scheme.XmlAuthSchemeProvider; +import software.amazon.awssdk.services.xml.auth.scheme.internal.DefaultXmlAuthSchemeProvider; import software.amazon.awssdk.services.xml.endpoints.XmlEndpointParams; import software.amazon.awssdk.services.xml.endpoints.XmlEndpointProvider; import software.amazon.awssdk.services.xml.endpoints.internal.XmlEndpointResolverUtils; @@ -130,8 +131,11 @@ final class DefaultXmlAsyncClient implements XmlAsyncClient { private final SdkClientConfiguration clientConfiguration; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + private final Executor executor; + protected DefaultXmlAsyncClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsAsyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -188,16 +192,14 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler).hostPrefixExpression(resolvedHostExpression) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")).withInput(aPostOperationRequest)); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(aPostOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -249,17 +251,15 @@ public CompletableFuture aPostOperationWithOut .withProtocolMetadata(protocolMetadata) .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(aPostOperationWithOutputRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -308,16 +308,14 @@ public CompletableFuture bearerAuthOperation( .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler).credentialType(CredentialType.TOKEN) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")).withInput(bearerAuthOperationRequest)); + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withInput(bearerAuthOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -383,8 +381,8 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest .withMarshaller(new EventStreamOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("EventStreamOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("EventStreamOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(eventStreamOperationRequest), restAsyncResponseTransformer); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { @@ -393,14 +391,14 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest () -> asyncResponseHandler.exceptionOccurred(e)); eventStreamTransformFuture.completeExceptionally(e); } - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return CompletableFutureUtils.forwardExceptionTo(eventStreamTransformFuture, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -450,8 +448,8 @@ public CompletableFuture getOperationWithCheck .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) @@ -459,13 +457,11 @@ public CompletableFuture getOperationWithCheck .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -516,19 +512,16 @@ public CompletableFuture operationWithChe .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -576,17 +569,15 @@ public CompletableFuture operationWithNoneAut .withProtocolMetadata(protocolMetadata) .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withInput(operationWithNoneAuthTypeRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -637,20 +628,17 @@ public CompletableFuture operationWithR .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) .withCombinedResponseHandler(responseHandler) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .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())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -728,8 +716,8 @@ public CompletableFuture putOperationWithChecksum( .withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum @@ -753,7 +741,7 @@ public CompletableFuture putOperationWithChecksum( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); @@ -761,7 +749,7 @@ public CompletableFuture putOperationWithChecksum( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -818,17 +806,15 @@ public CompletableFuture streamingInputOperatio .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) .asyncRequestBody(requestBody).build()).withCombinedResponseHandler(responseHandler) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")).withAsyncRequestBody(requestBody) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); CompletableFuture whenCompleteFuture = null; - whenCompleteFuture = executeFuture.whenComplete((r, e) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); - }); + whenCompleteFuture = publishMetricsWhenComplete(executeFuture, metricPublishers, apiCallMetricCollector); CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); return whenCompleteFuture; } catch (Throwable t) { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -887,8 +873,8 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withAsyncResponseTransformer(asyncResponseTransformer).withInput(streamingOutputOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; @@ -899,7 +885,7 @@ public CompletableFuture streamingOutputOperation( () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); }); }); return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); @@ -907,7 +893,7 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> finalAsyncResponseTransformer.exceptionOccurred(t)); - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); return CompletableFutureUtils.failedFuture(t); } } @@ -946,21 +932,53 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + /** + * Publishes the collected API call metrics once {@code future} completes, normally or exceptionally. + */ + private static CompletableFuture publishMetricsWhenComplete(CompletableFuture future, + List metricPublishers, MetricCollector apiCallMetricCollector) { + return future.whenComplete((r, e) -> publishMetrics(metricPublishers, apiCallMetricCollector)); + } + + private List resolveAuthSchemeOptions(SdkRequest request, + ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); XmlAuthSchemeProvider requestAuthSchemeProvider = request.overrideConfiguration().flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(XmlAuthSchemeProvider.class, p, "Expected an instance of XmlAuthSchemeProvider")) .orElse(null); XmlAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(XmlAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(XmlAuthSchemeProvider.class, executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of XmlAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultXmlAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } XmlAuthSchemeParams.Builder paramsBuilder = XmlAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); XmlEndpointProvider provider = (XmlEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -991,14 +1009,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); 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 4e48a80ee74f..d19470189ed0 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 @@ -4,10 +4,11 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; import software.amazon.awssdk.awscore.endpoints.AwsEndpointProviderUtils; @@ -28,10 +29,10 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.client.handler.SyncClientHandler; -import software.amazon.awssdk.core.endpoint.EndpointResolver; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.http.HttpResponseHandler; 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.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; @@ -39,7 +40,6 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.runtime.transform.StreamingRequestMarshaller; -import software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.endpoints.Endpoint; @@ -53,6 +53,7 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.services.xml.auth.scheme.XmlAuthSchemeParams; import software.amazon.awssdk.services.xml.auth.scheme.XmlAuthSchemeProvider; +import software.amazon.awssdk.services.xml.auth.scheme.internal.DefaultXmlAuthSchemeProvider; import software.amazon.awssdk.services.xml.endpoints.XmlEndpointParams; import software.amazon.awssdk.services.xml.endpoints.XmlEndpointProvider; import software.amazon.awssdk.services.xml.endpoints.internal.XmlEndpointResolverUtils; @@ -112,6 +113,8 @@ final class DefaultXmlClient implements XmlClient { private final SdkClientConfiguration clientConfiguration; + private final ConcurrentHashMap> authSchemeCache = new ConcurrentHashMap<>(); + protected DefaultXmlClient(SdkClientConfiguration clientConfiguration) { this.clientHandler = new AwsSyncClientHandler(clientConfiguration); this.clientConfiguration = clientConfiguration.toBuilder().option(SdkClientOption.SDK_CLIENT, this) @@ -160,12 +163,11 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) - .withInput(aPostOperationRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperation")) + .withInput(aPostOperationRequest).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -212,11 +214,11 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("APostOperationWithOutput", clientConfiguration)) - .withEndpointResolver(endpointResolver("APostOperationWithOutput")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -257,12 +259,11 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) - .withInput(bearerAuthOperationRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("BearerAuthOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("BearerAuthOperation")) + .withInput(bearerAuthOperationRequest).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -308,8 +309,8 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration) .withInput(getOperationWithChecksumRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("GetOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("GetOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) @@ -317,7 +318,7 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -363,14 +364,13 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( .withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration) .withInput(operationWithChecksumRequiredRequest) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithChecksumRequired", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithChecksumRequired")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()) .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -413,11 +413,11 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) .withCombinedResponseHandler(responseHandler).withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("OperationWithNoneAuthType", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithNoneAuthType")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -463,14 +463,13 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( .withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration) .withInput(operationWithRequestCompressionRequest) - .withAuthSchemeOptionsResolver( - authSchemeResolver("OperationWithRequestCompression", clientConfiguration)) - .withEndpointResolver(endpointResolver("OperationWithRequestCompression")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, RequestCompression.builder().encodings("gzip").isStreaming(false).build()) .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -544,8 +543,8 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withRequestConfiguration(clientConfiguration) .withInput(putOperationWithChecksumRequest) .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("PutOperationWithChecksum", clientConfiguration)) - .withEndpointResolver(endpointResolver("PutOperationWithChecksum")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, HttpChecksum @@ -566,7 +565,7 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -622,15 +621,15 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe .withMetricCollector(apiCallMetricCollector) .withRequestConfiguration(clientConfiguration) .withInput(streamingInputOperationRequest) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingInputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingInputOperation")) + .withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) .requestBody(requestBody).build())); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -681,13 +680,11 @@ public ReturnT streamingOutputOperation(StreamingOutputOperationReques .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withAuthSchemeOptionsResolver(authSchemeResolver("StreamingOutputOperation", clientConfiguration)) - .withEndpointResolver(endpointResolver("StreamingOutputOperation")) - .withResponseTransformer(responseTransformer) + .withMetricCollector(apiCallMetricCollector).withAuthSchemeOptionsResolver(this::resolveAuthSchemeOptions) + .withEndpointResolver(this::resolveEndpoint).withResponseTransformer(responseTransformer) .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { - metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + publishMetrics(metricPublishers, apiCallMetricCollector); } } @@ -711,21 +708,45 @@ private static List resolveMetricPublishers(SdkClientConfigurat return publishers; } - private List resolveAuthSchemeOptions(SdkRequest request, String operationName, - SdkClientConfiguration clientConfiguration) { + /** + * Publishes the collected API call metrics to each configured publisher. + */ + private static void publishMetrics(List metricPublishers, MetricCollector apiCallMetricCollector) { + for (MetricPublisher metricPublisher : metricPublishers) { + metricPublisher.publish(apiCallMetricCollector.collect()); + } + } + + private List resolveAuthSchemeOptions(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); XmlAuthSchemeProvider requestAuthSchemeProvider = request.overrideConfiguration().flatMap(c -> c.authSchemeProvider()) .map(p -> Validate.isInstanceOf(XmlAuthSchemeProvider.class, p, "Expected an instance of XmlAuthSchemeProvider")) .orElse(null); XmlAuthSchemeProvider authSchemeProvider = requestAuthSchemeProvider != null ? requestAuthSchemeProvider : Validate - .isInstanceOf(XmlAuthSchemeProvider.class, clientConfiguration.option(SdkClientOption.AUTH_SCHEME_PROVIDER), + .isInstanceOf(XmlAuthSchemeProvider.class, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_RESOLVER), "Expected an instance of XmlAuthSchemeProvider"); + boolean useCache = requestAuthSchemeProvider == null + && authSchemeProvider instanceof DefaultXmlAuthSchemeProvider; + String cacheKey = operationName + ":" + executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); + if (useCache) { + List cached = authSchemeCache.get(cacheKey); + if (cached != null) { + return cached; + } + } XmlAuthSchemeParams.Builder paramsBuilder = XmlAuthSchemeParams.builder().operation(operationName); - paramsBuilder.region(clientConfiguration.option(AwsClientOption.AWS_REGION)); + paramsBuilder.region(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION)); List options = authSchemeProvider.resolveAuthScheme(paramsBuilder.build()); + if (useCache) { + options = Collections.unmodifiableList(options); + authSchemeCache.put(cacheKey, options); + } return options; } - private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes, String operationName) { + private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executionAttributes) { + String operationName = executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); XmlEndpointProvider provider = (XmlEndpointProvider) executionAttributes .getAttribute(SdkInternalExecutionAttribute.ENDPOINT_PROVIDER); try { @@ -756,14 +777,6 @@ private Endpoint resolveEndpoint(SdkRequest request, ExecutionAttributes executi } } - private AuthSchemeOptionsResolver authSchemeResolver(String operationName, SdkClientConfiguration clientConfiguration) { - return r -> resolveAuthSchemeOptions(r, operationName, clientConfiguration); - } - - private EndpointResolver endpointResolver(String operationName) { - return (r, a) -> resolveEndpoint(r, a, operationName); - } - private void updateRetryStrategyClientConfiguration(SdkClientConfiguration.Builder configuration) { ClientOverrideConfiguration.Builder builder = configuration.asOverrideConfigurationBuilder(); RetryMode retryMode = builder.retryMode(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/eventstream/test-response-handler.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/eventstream/test-response-handler.java index a3f53ee99da6..20f17040879b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/eventstream/test-response-handler.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/eventstream/test-response-handler.java @@ -2,6 +2,7 @@ import java.util.function.Consumer; import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkAdvancedApi; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.awscore.eventstream.EventStreamResponseHandler; @@ -10,6 +11,11 @@ */ @Generated("software.amazon.awssdk:codegen") @SdkPublicApi +@SdkAdvancedApi( + cautionWhen = SdkAdvancedApi.Usage.IMPLEMENTED, + guidance = "onEventStream() receives a reactive-streams Publisher; the implementation must subscribe to it and call Subscription.request(n) to pull events -- a handler that never subscribes or never requests stalls the stream and hangs the operation. On retry the SDK calls onEventStream() again with a new Publisher; the implementation must reset accumulated state or throw to refuse the retry. Free resources in exceptionOccurred().", + saferAlternative = "Prefer the generated builder() with subscriber(Consumer) or subscriber(Visitor) which handle subscription, backpressure, and retry-state reset automatically." +) public interface EventStreamOperationResponseHandler extends EventStreamResponseHandler { /** @@ -21,8 +27,10 @@ static Builder builder() { /** * Builder for {@link EventStreamOperationResponseHandler}. This can be used to create the - * {@link EventStreamOperationResponseHandler} in a more functional way, you may also directly implement the - * {@link EventStreamOperationResponseHandler} interface if preferred. + * {@link EventStreamOperationResponseHandler} in a more functional way. Directly implementing the + * {@link EventStreamOperationResponseHandler} interface is possible but requires subscribing to the event + * publisher, requesting data via the Subscription, resetting state on retry, and freeing resources on error; the + * builder handles all of this automatically. */ @Generated("software.amazon.awssdk:codegen") interface Builder extends EventStreamResponseHandler.Builder { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-class.java new file mode 100644 index 000000000000..c0566ec44f4d --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-class.java @@ -0,0 +1,310 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.utils.CompletableFutureUtils; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + private volatile CacheEntry cache; + + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams endpointParams) { + // Single-entry result cache: reuse the last endpoint when the params still match. + CacheEntry cached = this.cache; + if (cached != null && cacheParamsMatch(endpointParams, cached.params)) { + return CompletableFuture.completedFuture(cached.endpoint); + } + try { + Evaluator evaluator = new Evaluator(); + evaluator.params = endpointParams; + evaluator.region = endpointParams.region() == null ? null : endpointParams.region().id(); + Endpoint result = evaluator.nodeP21(); + if (result == null) { + return CompletableFutureUtils.failedFuture(SdkClientException.create("Rule engine did not reach an error or endpoint result")); + } + this.cache = new CacheEntry(endpointParams, result); + return CompletableFuture.completedFuture(result); + } catch (SdkClientException e) { + String errorMsg = e.getMessage(); + if (errorMsg != null && errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + return CompletableFutureUtils.failedFuture(SdkClientException.create(errorMsg + ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest.", e)); + } + return CompletableFutureUtils.failedFuture(e); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static boolean cacheParamsMatch(QueryEndpointParams a, QueryEndpointParams b) { + return Objects.equals(a.useDualStack(), b.useDualStack()) + && Objects.equals(a.useFips(), b.useFips()) + && Objects.equals(a.region(), b.region()) + && Objects.equals(a.stringContextParam(), b.stringContextParam()) + && Objects.equals(a.endpoint(), b.endpoint()) + && Objects.equals(a.staticStringParam(), b.staticStringParam()) + && Objects.equals(a.operationContextParam(), b.operationContextParam()) + && cacheFirstElementsMatch(a.arnList(), b.arnList()) + && cacheListsMatch(a.customEndpointArray(), b.customEndpointArray()); + } + + private static boolean cacheListsMatch(List a, List b) { + if (a == b) return true; + if (a == null || b == null) return false; + int size = a.size(); + if (size != b.size()) return false; + // Bounded so that a long list cannot make the cache check cost more than resolving. + if (size > 4) return false; + for (int i = 0; i < size; i++) { + if (!Objects.equals(a.get(i), b.get(i))) return false; + } + return true; + } + + private static boolean cacheFirstElementsMatch(List a, List b) { + if (a == b) return true; + // isSet can tell an absent list from an empty one, so presence is part of the key. + if (a == null || b == null) return false; + // Nothing past element 0 can reach the endpoint. + String firstA = a.isEmpty() ? null : a.get(0); + String firstB = b.isEmpty() ? null : b.get(0); + return Objects.equals(firstA, firstB); + } + + private static final class Evaluator { + QueryEndpointParams params; + + String region; + + RulePartition partitionResult; + + String firstArn; + + String secondEndpoint; + + private Endpoint nodeP0() { + return null; + } + + private Endpoint nodeP1() { + return Boolean.TRUE.equals(params.useDualStack()) + ? result1() + : result2(); + } + + private Endpoint nodeP2() { + return Boolean.TRUE.equals(params.useFips()) + ? result0() + : nodeP1(); + } + + private Endpoint nodeP3() { + return cond6() + ? result3() + : result4(); + } + + private Endpoint nodeP4() { + return cond5() + ? nodeP3() + : result4(); + } + + private Endpoint nodeP5() { + return cond7() + ? result5() + : result6(); + } + + private Endpoint nodeP6() { + return cond5() + ? nodeP5() + : result7(); + } + + private Endpoint nodeP7() { + return Boolean.TRUE.equals(params.useDualStack()) + ? nodeP4() + : nodeP6(); + } + + private Endpoint nodeP8() { + return cond3() + ? nodeP7() + : result11(); + } + + private Endpoint nodeP9() { + return cond6() + ? result8() + : result9(); + } + + private Endpoint nodeP10() { + return Boolean.TRUE.equals(params.useDualStack()) + ? nodeP9() + : result10(); + } + + private Endpoint nodeP11() { + return cond3() + ? nodeP10() + : result11(); + } + + private Endpoint nodeP12() { + return Boolean.TRUE.equals(params.useFips()) + ? nodeP8() + : nodeP11(); + } + + private Endpoint nodeP13() { + return region != null + ? nodeP12() + : result11(); + } + + private Endpoint nodeP14() { + return params.endpoint() != null + ? nodeP2() + : nodeP13(); + } + + private Endpoint nodeP15() { + return params.stringContextParam() != null + ? nodeP16() + : nodeP16(); + } + + private Endpoint nodeP16() { + return params.staticStringParam() != null + ? nodeP17() + : nodeP17(); + } + + private Endpoint nodeP17() { + return params.operationContextParam() != null + ? nodeP18() + : nodeP18(); + } + + private Endpoint nodeP18() { + return params.customEndpointArray() != null + ? nodeP19() + : nodeP19(); + } + + private Endpoint nodeP19() { + return cond12() + ? nodeP14() + : nodeP14(); + } + + private Endpoint nodeP20() { + return params.arnList() != null + ? nodeP15() + : nodeP15(); + } + + private Endpoint nodeP21() { + return cond14() + ? nodeP20() + : nodeP20(); + } + + private boolean cond3() { + partitionResult = RulesFunctions.awsPartition(region); + return partitionResult != null; + } + + private boolean cond5() { + return (partitionResult.supportsFIPS()); + } + + private boolean cond6() { + return (partitionResult.supportsDualStack()); + } + + private boolean cond7() { + return ("aws-us-gov".equals(partitionResult.name())); + } + + private boolean cond12() { + firstArn = RulesFunctions.listAccess(params.arnList(), 0); + return firstArn != null; + } + + private boolean cond14() { + secondEndpoint = RulesFunctions.listAccess(params.customEndpointArray(), 1); + return secondEndpoint != null; + } + + private Endpoint result0() { + throw SdkClientException.create("Invalid Configuration: FIPS and custom endpoint are not supported"); + } + + private Endpoint result1() { + throw SdkClientException.create("Invalid Configuration: Dualstack and custom endpoint are not supported"); + } + + private Endpoint result2() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(params.endpoint())).build(); + } + + private Endpoint result3() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")).build(); + } + + private Endpoint result4() { + throw SdkClientException.create("FIPS and DualStack are enabled, but this partition does not support one or both"); + } + + private Endpoint result5() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "query." + region + ".amazonaws.com", -1, "")).build(); + } + + private Endpoint result6() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "query-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")).build(); + } + + private Endpoint result7() { + throw SdkClientException.create("FIPS is enabled but this partition does not support FIPS"); + } + + private Endpoint result8() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dualStackDnsSuffix(), -1, "")).build(); + } + + private Endpoint result9() { + throw SdkClientException.create("DualStack is enabled but this partition does not support DualStack"); + } + + private Endpoint result10() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "query." + region + "." + partitionResult.dnsSuffix(), -1, "")).build(); + } + + private Endpoint result11() { + throw SdkClientException.create("Invalid Configuration: Missing Region"); + } + } + + private static final class CacheEntry { + final QueryEndpointParams params; + + final Endpoint endpoint; + + CacheEntry(QueryEndpointParams params, Endpoint endpoint) { + this.params = params; + this.endpoint = endpoint; + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-s3-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-s3-class.java new file mode 100644 index 000000000000..7b55c6c57497 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/bdd/endpoint-provider-bdd-s3-class.java @@ -0,0 +1,4139 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.services.s3.endpoints.authscheme.DynamicEndpointAuthSchemeFactory; +import software.amazon.awssdk.utils.CompletableFutureUtils; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + private volatile CacheEntry cache; + + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams endpointParams) { + // Single-entry result cache: reuse the last endpoint when the params still match. + CacheEntry cached = this.cache; + if (cached != null && cacheParamsMatch(endpointParams, cached.params)) { + return CompletableFuture.completedFuture(cached.endpoint); + } + try { + Evaluator evaluator = new Evaluator(); + evaluator.params = endpointParams; + evaluator.region = endpointParams.region() == null ? null : endpointParams.region().id(); + Endpoint result = evaluator.nodeP1(); + if (result == null) { + return CompletableFutureUtils.failedFuture(SdkClientException.create("Rule engine did not reach an error or endpoint result")); + } + this.cache = new CacheEntry(endpointParams, result); + return CompletableFuture.completedFuture(result); + } catch (SdkClientException e) { + String errorMsg = e.getMessage(); + if (errorMsg != null && errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + return CompletableFutureUtils.failedFuture(SdkClientException.create(errorMsg + ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest.", e)); + } + return CompletableFutureUtils.failedFuture(e); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static boolean cacheParamsMatch(QueryEndpointParams a, QueryEndpointParams b) { + return Objects.equals(a.useFips(), b.useFips()) + && Objects.equals(a.useDualStack(), b.useDualStack()) + && Objects.equals(a.forcePathStyle(), b.forcePathStyle()) + && Objects.equals(a.accelerate(), b.accelerate()) + && Objects.equals(a.useGlobalEndpoint(), b.useGlobalEndpoint()) + && Objects.equals(a.useObjectLambdaEndpoint(), b.useObjectLambdaEndpoint()) + && Objects.equals(a.disableAccessPoints(), b.disableAccessPoints()) + && Objects.equals(a.disableMultiRegionAccessPoints(), b.disableMultiRegionAccessPoints()) + && Objects.equals(a.useArnRegion(), b.useArnRegion()) + && Objects.equals(a.useS3ExpressControlEndpoint(), b.useS3ExpressControlEndpoint()) + && Objects.equals(a.disableS3ExpressSessionAuth(), b.disableS3ExpressSessionAuth()) + && Objects.equals(a.region(), b.region()) + && Objects.equals(a.bucket(), b.bucket()) + && Objects.equals(a.endpoint(), b.endpoint()); + } + + private static final class Evaluator { + QueryEndpointParams params; + + String region; + + RulePartition partitionResult; + + String accessPointSuffix; + + String regionPrefix; + + String outpostId_ssa_2; + + String hardwareType; + + String _s3e_ds; + + String _s3e_fips; + + String _s3e_auth; + + RuleUrl url; + + RuleArn bucketArn; + + String s3expressAvailabilityZoneId; + + String uri_encoded_bucket; + + String arnType; + + String accessPointName_ssa_1; + + RulePartition bucketPartition; + + String outpostId_ssa_1; + + String outpostType; + + String accessPointName_ssa_2; + + private Endpoint nodeP0() { + return null; + } + + private Endpoint nodeP1() { + return region != null + ? nodeP2() + : result114(); + } + + private Endpoint nodeP2() { + return Boolean.TRUE.equals(params.accelerate()) + ? nodeP423() + : nodeP3(); + } + + private Endpoint nodeP3() { + return Boolean.TRUE.equals(params.useFips()) + ? nodeP271() + : nodeP4(); + } + + private Endpoint nodeP4() { + return Boolean.TRUE.equals(params.useDualStack()) + ? nodeP232() + : nodeP5(); + } + + private Endpoint nodeP5() { + return params.endpoint() != null + ? nodeP84() + : nodeP6(); + } + + private Endpoint nodeP6() { + return params.bucket() != null + ? nodeP14() + : nodeP7(); + } + + private Endpoint nodeP7() { + return cond8() + ? nodeP8() + : result114(); + } + + private Endpoint nodeP8() { + return cond16() + ? nodeP9() + : nodeP12(); + } + + private Endpoint nodeP9() { + return cond18() + ? nodeP10() + : nodeP12(); + } + + private Endpoint nodeP10() { + return cond19() + ? nodeP11() + : nodeP12(); + } + + private Endpoint nodeP11() { + return cond22() + ? result13() + : nodeP12(); + } + + private Endpoint nodeP12() { + return cond35() + ? nodeP13() + : result41(); + } + + private Endpoint nodeP13() { + return cond36() + ? result102() + : nodeP434(); + } + + private Endpoint nodeP14() { + return cond6() + ? nodeP270() + : nodeP15(); + } + + private Endpoint nodeP15() { + return cond7() + ? nodeP269() + : nodeP16(); + } + + private Endpoint nodeP16() { + return cond8() + ? nodeP18() + : nodeP17(); + } + + private Endpoint nodeP17() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP500() + : nodeP105(); + } + + private Endpoint nodeP18() { + return cond9() + ? nodeP19() + : nodeP23(); + } + + private Endpoint nodeP19() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP20() + : nodeP23(); + } + + private Endpoint nodeP20() { + return cond11() + ? nodeP21() + : nodeP23(); + } + + private Endpoint nodeP21() { + return cond12() + ? nodeP22() + : nodeP23(); + } + + private Endpoint nodeP22() { + return cond13() + ? nodeP546() + : nodeP23(); + } + + private Endpoint nodeP23() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP76() + : nodeP24(); + } + + private Endpoint nodeP24() { + return cond20() + ? nodeP72() + : nodeP25(); + } + + private Endpoint nodeP25() { + return cond26() + ? nodeP26() + : nodeP77(); + } + + private Endpoint nodeP26() { + return cond37() + ? nodeP27() + : result85(); + } + + private Endpoint nodeP27() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP28(); + } + + private Endpoint nodeP28() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP46() + : nodeP29(); + } + + private Endpoint nodeP29() { + return cond48() + ? result57() + : nodeP30(); + } + + private Endpoint nodeP30() { + return cond50() + ? nodeP31() + : result84(); + } + + private Endpoint nodeP31() { + return cond51() + ? nodeP32() + : nodeP135(); + } + + private Endpoint nodeP32() { + return cond55() + ? result75() + : nodeP33(); + } + + private Endpoint nodeP33() { + return cond59() + ? nodeP34() + : result83(); + } + + private Endpoint nodeP34() { + return cond60() + ? nodeP38() + : nodeP35(); + } + + private Endpoint nodeP35() { + return cond61() + ? nodeP36() + : result82(); + } + + private Endpoint nodeP36() { + return cond62() + ? nodeP37() + : nodeP145(); + } + + private Endpoint nodeP37() { + return cond63() + ? nodeP40() + : result45(); + } + + private Endpoint nodeP38() { + return cond61() + ? nodeP39() + : result82(); + } + + private Endpoint nodeP39() { + return cond62() + ? nodeP40() + : nodeP149(); + } + + private Endpoint nodeP40() { + return cond64() + ? nodeP41() + : result53(); + } + + private Endpoint nodeP41() { + return cond66() + ? nodeP42() + : result52(); + } + + private Endpoint nodeP42() { + return cond70() + ? nodeP43() + : result51(); + } + + private Endpoint nodeP43() { + return cond71() + ? nodeP44() + : result80(); + } + + private Endpoint nodeP44() { + return outpostType != null && outpostType.equals("accesspoint") + ? nodeP45() + : result79(); + } + + private Endpoint nodeP45() { + return cond74() + ? result77() + : result78(); + } + + private Endpoint nodeP46() { + return cond40() + ? nodeP47() + : result56(); + } + + private Endpoint nodeP47() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP48(); + } + + private Endpoint nodeP48() { + return cond42() + ? nodeP184() + : nodeP49(); + } + + private Endpoint nodeP49() { + return cond48() + ? nodeP61() + : nodeP50(); + } + + private Endpoint nodeP50() { + return cond49() + ? result44() + : nodeP51(); + } + + private Endpoint nodeP51() { + return cond51() + ? nodeP52() + : nodeP525(); + } + + private Endpoint nodeP52() { + return cond60() + ? nodeP55() + : nodeP53(); + } + + private Endpoint nodeP53() { + return cond62() + ? result54() + : nodeP54(); + } + + private Endpoint nodeP54() { + return cond63() + ? nodeP56() + : result45(); + } + + private Endpoint nodeP55() { + return cond62() + ? result54() + : nodeP56(); + } + + private Endpoint nodeP56() { + return cond64() + ? nodeP57() + : result53(); + } + + private Endpoint nodeP57() { + return cond66() + ? nodeP58() + : result52(); + } + + private Endpoint nodeP58() { + return cond69() + ? nodeP59() + : result64(); + } + + private Endpoint nodeP59() { + return cond70() + ? nodeP60() + : result51(); + } + + private Endpoint nodeP60() { + return cond72() + ? result63() + : result50(); + } + + private Endpoint nodeP61() { + return cond49() + ? result44() + : nodeP62(); + } + + private Endpoint nodeP62() { + return cond51() + ? nodeP63() + : nodeP525(); + } + + private Endpoint nodeP63() { + return cond60() + ? nodeP66() + : nodeP64(); + } + + private Endpoint nodeP64() { + return cond62() + ? result54() + : nodeP65(); + } + + private Endpoint nodeP65() { + return cond63() + ? nodeP67() + : result45(); + } + + private Endpoint nodeP66() { + return cond62() + ? result54() + : nodeP67(); + } + + private Endpoint nodeP67() { + return cond64() + ? nodeP68() + : result53(); + } + + private Endpoint nodeP68() { + return cond66() + ? nodeP69() + : result52(); + } + + private Endpoint nodeP69() { + return cond68() + ? result46() + : nodeP70(); + } + + private Endpoint nodeP70() { + return cond70() + ? nodeP71() + : result51(); + } + + private Endpoint nodeP71() { + return cond72() + ? result49() + : result50(); + } + + private Endpoint nodeP72() { + return cond25() + ? nodeP73() + : result41(); + } + + private Endpoint nodeP73() { + return region != null && region.equals("aws-global") + ? result38() + : nodeP74(); + } + + private Endpoint nodeP74() { + return Boolean.TRUE.equals(params.useGlobalEndpoint()) + ? nodeP75() + : result40(); + } + + private Endpoint nodeP75() { + return region != null && region.equals("us-east-1") + ? result39() + : result40(); + } + + private Endpoint nodeP76() { + return cond26() + ? result87() + : nodeP77(); + } + + private Endpoint nodeP77() { + return cond28() + ? result86() + : nodeP78(); + } + + private Endpoint nodeP78() { + return cond34() + ? nodeP81() + : nodeP79(); + } + + private Endpoint nodeP79() { + return cond35() + ? nodeP80() + : nodeP544(); + } + + private Endpoint nodeP80() { + return cond36() + ? result102() + : result114(); + } + + private Endpoint nodeP81() { + return region != null && region.equals("aws-global") + ? result96() + : nodeP82(); + } + + private Endpoint nodeP82() { + return Boolean.TRUE.equals(params.useGlobalEndpoint()) + ? nodeP83() + : result98(); + } + + private Endpoint nodeP83() { + return region != null && region.equals("us-east-1") + ? result97() + : result98(); + } + + private Endpoint nodeP84() { + return params.bucket() != null + ? nodeP100() + : nodeP85(); + } + + private Endpoint nodeP85() { + return cond8() + ? nodeP86() + : result114(); + } + + private Endpoint nodeP86() { + return cond16() + ? nodeP87() + : nodeP88(); + } + + private Endpoint nodeP87() { + return cond18() + ? nodeP90() + : nodeP88(); + } + + private Endpoint nodeP88() { + return cond19() + ? nodeP89() + : nodeP91(); + } + + private Endpoint nodeP89() { + return cond21() + ? nodeP96() + : nodeP94(); + } + + private Endpoint nodeP90() { + return cond19() + ? nodeP92() + : nodeP91(); + } + + private Endpoint nodeP91() { + return cond21() + ? nodeP97() + : nodeP94(); + } + + private Endpoint nodeP92() { + return cond21() + ? nodeP96() + : nodeP93(); + } + + private Endpoint nodeP93() { + return cond22() + ? result13() + : nodeP94(); + } + + private Endpoint nodeP94() { + return cond35() + ? nodeP95() + : result41(); + } + + private Endpoint nodeP95() { + return cond36() + ? result102() + : result41(); + } + + private Endpoint nodeP96() { + return cond22() + ? result12() + : nodeP97(); + } + + private Endpoint nodeP97() { + return cond35() + ? nodeP98() + : result41(); + } + + private Endpoint nodeP98() { + return cond36() + ? result100() + : nodeP99(); + } + + private Endpoint nodeP99() { + return region != null && region.equals("aws-global") + ? result109() + : result110(); + } + + private Endpoint nodeP100() { + return cond6() + ? nodeP213() + : nodeP101(); + } + + private Endpoint nodeP101() { + return cond7() + ? nodeP207() + : nodeP102(); + } + + private Endpoint nodeP102() { + return cond8() + ? nodeP118() + : nodeP103(); + } + + private Endpoint nodeP103() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP117() + : nodeP104(); + } + + private Endpoint nodeP104() { + return cond21() + ? nodeP105() + : result22(); + } + + private Endpoint nodeP105() { + return cond26() + ? nodeP106() + : nodeP501(); + } + + private Endpoint nodeP106() { + return cond37() + ? nodeP107() + : result85(); + } + + private Endpoint nodeP107() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP108(); + } + + private Endpoint nodeP108() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP111() + : nodeP109(); + } + + private Endpoint nodeP109() { + return cond48() + ? result57() + : nodeP110(); + } + + private Endpoint nodeP110() { + return cond50() + ? nodeP135() + : result84(); + } + + private Endpoint nodeP111() { + return cond40() + ? nodeP112() + : result56(); + } + + private Endpoint nodeP112() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP113(); + } + + private Endpoint nodeP113() { + return cond42() + ? nodeP114() + : nodeP499(); + } + + private Endpoint nodeP114() { + return cond48() + ? result55() + : nodeP115(); + } + + private Endpoint nodeP115() { + return cond52() + ? nodeP116() + : result71(); + } + + private Endpoint nodeP116() { + return Boolean.TRUE.equals(params.disableMultiRegionAccessPoints()) + ? result68() + : result71(); + } + + private Endpoint nodeP117() { + return cond21() + ? nodeP500() + : result22(); + } + + private Endpoint nodeP118() { + return cond9() + ? nodeP119() + : nodeP123(); + } + + private Endpoint nodeP119() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP120() + : nodeP123(); + } + + private Endpoint nodeP120() { + return cond11() + ? nodeP121() + : nodeP123(); + } + + private Endpoint nodeP121() { + return cond12() + ? nodeP122() + : nodeP123(); + } + + private Endpoint nodeP122() { + return cond13() + ? nodeP201() + : nodeP123(); + } + + private Endpoint nodeP123() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP194() + : nodeP124(); + } + + private Endpoint nodeP124() { + return cond20() + ? nodeP189() + : nodeP125(); + } + + private Endpoint nodeP125() { + return cond21() + ? nodeP126() + : result22(); + } + + private Endpoint nodeP126() { + return cond23() + ? nodeP127() + : nodeP128(); + } + + private Endpoint nodeP127() { + return cond24() + ? nodeP188() + : nodeP128(); + } + + private Endpoint nodeP128() { + return cond26() + ? nodeP129() + : nodeP196(); + } + + private Endpoint nodeP129() { + return cond37() + ? nodeP130() + : result85(); + } + + private Endpoint nodeP130() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP131(); + } + + private Endpoint nodeP131() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP158() + : nodeP132(); + } + + private Endpoint nodeP132() { + return cond48() + ? result57() + : nodeP133(); + } + + private Endpoint nodeP133() { + return cond50() + ? nodeP134() + : result84(); + } + + private Endpoint nodeP134() { + return cond51() + ? nodeP140() + : nodeP135(); + } + + private Endpoint nodeP135() { + return cond55() + ? result75() + : nodeP136(); + } + + private Endpoint nodeP136() { + return cond59() + ? nodeP137() + : result83(); + } + + private Endpoint nodeP137() { + return cond60() + ? result82() + : nodeP138(); + } + + private Endpoint nodeP138() { + return cond61() + ? nodeP139() + : result82(); + } + + private Endpoint nodeP139() { + return cond63() + ? result82() + : result45(); + } + + private Endpoint nodeP140() { + return cond55() + ? result75() + : nodeP141(); + } + + private Endpoint nodeP141() { + return cond59() + ? nodeP142() + : result83(); + } + + private Endpoint nodeP142() { + return cond60() + ? nodeP147() + : nodeP143(); + } + + private Endpoint nodeP143() { + return cond61() + ? nodeP144() + : result82(); + } + + private Endpoint nodeP144() { + return cond62() + ? nodeP146() + : nodeP145(); + } + + private Endpoint nodeP145() { + return cond63() + ? nodeP149() + : result45(); + } + + private Endpoint nodeP146() { + return cond63() + ? nodeP152() + : result45(); + } + + private Endpoint nodeP147() { + return cond61() + ? nodeP148() + : result82(); + } + + private Endpoint nodeP148() { + return cond62() + ? nodeP152() + : nodeP149(); + } + + private Endpoint nodeP149() { + return cond64() + ? nodeP150() + : result53(); + } + + private Endpoint nodeP150() { + return cond66() + ? nodeP151() + : result52(); + } + + private Endpoint nodeP151() { + return cond70() + ? result81() + : result51(); + } + + private Endpoint nodeP152() { + return cond64() + ? nodeP153() + : result53(); + } + + private Endpoint nodeP153() { + return cond66() + ? nodeP154() + : result52(); + } + + private Endpoint nodeP154() { + return cond70() + ? nodeP155() + : result51(); + } + + private Endpoint nodeP155() { + return cond71() + ? nodeP156() + : result80(); + } + + private Endpoint nodeP156() { + return outpostType != null && outpostType.equals("accesspoint") + ? nodeP157() + : result79(); + } + + private Endpoint nodeP157() { + return cond74() + ? result76() + : result78(); + } + + private Endpoint nodeP158() { + return cond40() + ? nodeP159() + : result56(); + } + + private Endpoint nodeP159() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP160(); + } + + private Endpoint nodeP160() { + return cond42() + ? nodeP184() + : nodeP161(); + } + + private Endpoint nodeP161() { + return cond48() + ? nodeP173() + : nodeP162(); + } + + private Endpoint nodeP162() { + return cond49() + ? result44() + : nodeP163(); + } + + private Endpoint nodeP163() { + return cond51() + ? nodeP164() + : nodeP525(); + } + + private Endpoint nodeP164() { + return cond60() + ? nodeP167() + : nodeP165(); + } + + private Endpoint nodeP165() { + return cond62() + ? result54() + : nodeP166(); + } + + private Endpoint nodeP166() { + return cond63() + ? nodeP168() + : result45(); + } + + private Endpoint nodeP167() { + return cond62() + ? result54() + : nodeP168(); + } + + private Endpoint nodeP168() { + return cond64() + ? nodeP169() + : result53(); + } + + private Endpoint nodeP169() { + return cond66() + ? nodeP170() + : result52(); + } + + private Endpoint nodeP170() { + return cond69() + ? nodeP171() + : result64(); + } + + private Endpoint nodeP171() { + return cond70() + ? nodeP172() + : result51(); + } + + private Endpoint nodeP172() { + return cond72() + ? result62() + : result50(); + } + + private Endpoint nodeP173() { + return cond49() + ? result44() + : nodeP174(); + } + + private Endpoint nodeP174() { + return cond51() + ? nodeP175() + : nodeP525(); + } + + private Endpoint nodeP175() { + return cond60() + ? nodeP178() + : nodeP176(); + } + + private Endpoint nodeP176() { + return cond62() + ? result54() + : nodeP177(); + } + + private Endpoint nodeP177() { + return cond63() + ? nodeP179() + : result45(); + } + + private Endpoint nodeP178() { + return cond62() + ? result54() + : nodeP179(); + } + + private Endpoint nodeP179() { + return cond64() + ? nodeP180() + : result53(); + } + + private Endpoint nodeP180() { + return cond66() + ? nodeP181() + : result52(); + } + + private Endpoint nodeP181() { + return cond68() + ? result46() + : nodeP182(); + } + + private Endpoint nodeP182() { + return cond70() + ? nodeP183() + : result51(); + } + + private Endpoint nodeP183() { + return cond72() + ? result47() + : result50(); + } + + private Endpoint nodeP184() { + return cond48() + ? result55() + : nodeP185(); + } + + private Endpoint nodeP185() { + return cond52() + ? nodeP186() + : result71(); + } + + private Endpoint nodeP186() { + return Boolean.TRUE.equals(params.disableMultiRegionAccessPoints()) + ? result68() + : nodeP187(); + } + + private Endpoint nodeP187() { + return cond67() + ? result69() + : result70(); + } + + private Endpoint nodeP188() { + return cond25() + ? result35() + : result41(); + } + + private Endpoint nodeP189() { + return cond21() + ? nodeP190() + : result22(); + } + + private Endpoint nodeP190() { + return cond25() + ? nodeP191() + : result41(); + } + + private Endpoint nodeP191() { + return cond30() + ? nodeP193() + : nodeP192(); + } + + private Endpoint nodeP192() { + return region != null && region.equals("aws-global") + ? result33() + : result35(); + } + + private Endpoint nodeP193() { + return region != null && region.equals("aws-global") + ? result32() + : result34(); + } + + private Endpoint nodeP194() { + return cond21() + ? nodeP195() + : result22(); + } + + private Endpoint nodeP195() { + return cond26() + ? result87() + : nodeP196(); + } + + private Endpoint nodeP196() { + return cond28() + ? result86() + : nodeP197(); + } + + private Endpoint nodeP197() { + return cond34() + ? nodeP200() + : nodeP198(); + } + + private Endpoint nodeP198() { + return cond35() + ? nodeP199() + : nodeP544(); + } + + private Endpoint nodeP199() { + return cond36() + ? result100() + : result114(); + } + + private Endpoint nodeP200() { + return region != null && region.equals("aws-global") + ? result94() + : result95(); + } + + private Endpoint nodeP201() { + return cond17() + ? nodeP202() + : result21(); + } + + private Endpoint nodeP202() { + return cond20() + ? nodeP203() + : result20(); + } + + private Endpoint nodeP203() { + return cond21() + ? nodeP204() + : nodeP549(); + } + + private Endpoint nodeP204() { + return regionPrefix != null && regionPrefix.equals("beta") + ? nodeP205() + : nodeP549(); + } + + private Endpoint nodeP205() { + return hardwareType != null && hardwareType.equals("e") + ? result15() + : nodeP206(); + } + + private Endpoint nodeP206() { + return hardwareType != null && hardwareType.equals("o") + ? result17() + : result19(); + } + + private Endpoint nodeP207() { + return cond8() + ? nodeP208() + : nodeP214(); + } + + private Endpoint nodeP208() { + return cond16() + ? nodeP209() + : nodeP219(); + } + + private Endpoint nodeP209() { + return cond18() + ? nodeP210() + : nodeP219(); + } + + private Endpoint nodeP210() { + return cond19() + ? nodeP211() + : nodeP223(); + } + + private Endpoint nodeP211() { + return cond20() + ? nodeP212() + : nodeP226(); + } + + private Endpoint nodeP212() { + return cond21() + ? nodeP230() + : nodeP400(); + } + + private Endpoint nodeP213() { + return cond8() + ? nodeP217() + : nodeP214(); + } + + private Endpoint nodeP214() { + return cond19() + ? nodeP215() + : result8(); + } + + private Endpoint nodeP215() { + return cond20() + ? nodeP216() + : nodeP226(); + } + + private Endpoint nodeP216() { + return cond21() + ? nodeP230() + : result8(); + } + + private Endpoint nodeP217() { + return cond16() + ? nodeP218() + : nodeP219(); + } + + private Endpoint nodeP218() { + return cond18() + ? nodeP222() + : nodeP219(); + } + + private Endpoint nodeP219() { + return cond19() + ? nodeP220() + : nodeP223(); + } + + private Endpoint nodeP220() { + return cond20() + ? nodeP221() + : nodeP226(); + } + + private Endpoint nodeP221() { + return cond21() + ? nodeP230() + : result11(); + } + + private Endpoint nodeP222() { + return cond19() + ? nodeP225() + : nodeP223(); + } + + private Endpoint nodeP223() { + return cond20() + ? nodeP224() + : result8(); + } + + private Endpoint nodeP224() { + return cond21() + ? result8() + : result11(); + } + + private Endpoint nodeP225() { + return cond20() + ? nodeP229() + : nodeP226(); + } + + private Endpoint nodeP226() { + return cond21() + ? nodeP227() + : result8(); + } + + private Endpoint nodeP227() { + return cond30() + ? nodeP228() + : result8(); + } + + private Endpoint nodeP228() { + return cond34() + ? result6() + : result8(); + } + + private Endpoint nodeP229() { + return cond21() + ? nodeP230() + : nodeP414(); + } + + private Endpoint nodeP230() { + return cond30() + ? nodeP231() + : result7(); + } + + private Endpoint nodeP231() { + return cond34() + ? result6() + : result7(); + } + + private Endpoint nodeP232() { + return params.endpoint() != null + ? result1() + : nodeP233(); + } + + private Endpoint nodeP233() { + return params.bucket() != null + ? nodeP234() + : nodeP479(); + } + + private Endpoint nodeP234() { + return cond6() + ? nodeP270() + : nodeP235(); + } + + private Endpoint nodeP235() { + return cond7() + ? nodeP269() + : nodeP236(); + } + + private Endpoint nodeP236() { + return cond8() + ? nodeP237() + : nodeP490(); + } + + private Endpoint nodeP237() { + return cond9() + ? nodeP238() + : nodeP242(); + } + + private Endpoint nodeP238() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP239() + : nodeP242(); + } + + private Endpoint nodeP239() { + return cond11() + ? nodeP240() + : nodeP242(); + } + + private Endpoint nodeP240() { + return cond12() + ? nodeP241() + : nodeP242(); + } + + private Endpoint nodeP241() { + return cond13() + ? nodeP546() + : nodeP242(); + } + + private Endpoint nodeP242() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP265() + : nodeP243(); + } + + private Endpoint nodeP243() { + return cond20() + ? nodeP263() + : nodeP244(); + } + + private Endpoint nodeP244() { + return cond26() + ? nodeP245() + : nodeP266(); + } + + private Endpoint nodeP245() { + return cond37() + ? nodeP246() + : result85(); + } + + private Endpoint nodeP246() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP247(); + } + + private Endpoint nodeP247() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP248() + : nodeP517(); + } + + private Endpoint nodeP248() { + return cond40() + ? nodeP249() + : result56(); + } + + private Endpoint nodeP249() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP250(); + } + + private Endpoint nodeP250() { + return cond42() + ? nodeP537() + : nodeP251(); + } + + private Endpoint nodeP251() { + return cond48() + ? result42() + : nodeP252(); + } + + private Endpoint nodeP252() { + return cond49() + ? result44() + : nodeP253(); + } + + private Endpoint nodeP253() { + return cond51() + ? nodeP254() + : nodeP525(); + } + + private Endpoint nodeP254() { + return cond60() + ? nodeP257() + : nodeP255(); + } + + private Endpoint nodeP255() { + return cond62() + ? result54() + : nodeP256(); + } + + private Endpoint nodeP256() { + return cond63() + ? nodeP258() + : result45(); + } + + private Endpoint nodeP257() { + return cond62() + ? result54() + : nodeP258(); + } + + private Endpoint nodeP258() { + return cond64() + ? nodeP259() + : result53(); + } + + private Endpoint nodeP259() { + return cond66() + ? nodeP260() + : result52(); + } + + private Endpoint nodeP260() { + return cond69() + ? nodeP261() + : result64(); + } + + private Endpoint nodeP261() { + return cond70() + ? nodeP262() + : result51(); + } + + private Endpoint nodeP262() { + return cond72() + ? result61() + : result50(); + } + + private Endpoint nodeP263() { + return cond25() + ? nodeP264() + : result41(); + } + + private Endpoint nodeP264() { + return region != null && region.equals("aws-global") + ? result30() + : result31(); + } + + private Endpoint nodeP265() { + return cond26() + ? result87() + : nodeP266(); + } + + private Endpoint nodeP266() { + return cond28() + ? result86() + : nodeP267(); + } + + private Endpoint nodeP267() { + return cond34() + ? nodeP268() + : nodeP543(); + } + + private Endpoint nodeP268() { + return region != null && region.equals("aws-global") + ? result92() + : result93(); + } + + private Endpoint nodeP269() { + return cond8() + ? nodeP396() + : result8(); + } + + private Endpoint nodeP270() { + return cond8() + ? nodeP406() + : result8(); + } + + private Endpoint nodeP271() { + return Boolean.TRUE.equals(params.useDualStack()) + ? nodeP345() + : nodeP272(); + } + + private Endpoint nodeP272() { + return params.endpoint() != null + ? result2() + : nodeP273(); + } + + private Endpoint nodeP273() { + return params.bucket() != null + ? nodeP283() + : nodeP274(); + } + + private Endpoint nodeP274() { + return cond8() + ? nodeP275() + : result114(); + } + + private Endpoint nodeP275() { + return cond15() + ? result4() + : nodeP276(); + } + + private Endpoint nodeP276() { + return cond16() + ? nodeP277() + : nodeP280(); + } + + private Endpoint nodeP277() { + return cond18() + ? nodeP278() + : nodeP280(); + } + + private Endpoint nodeP278() { + return cond19() + ? nodeP279() + : nodeP280(); + } + + private Endpoint nodeP279() { + return cond22() + ? result13() + : nodeP280(); + } + + private Endpoint nodeP280() { + return cond35() + ? nodeP281() + : result41(); + } + + private Endpoint nodeP281() { + return cond36() + ? result101() + : nodeP282(); + } + + private Endpoint nodeP282() { + return region != null && region.equals("aws-global") + ? result105() + : result106(); + } + + private Endpoint nodeP283() { + return cond6() + ? nodeP404() + : nodeP284(); + } + + private Endpoint nodeP284() { + return cond7() + ? nodeP394() + : nodeP285(); + } + + private Endpoint nodeP285() { + return cond8() + ? nodeP294() + : nodeP286(); + } + + private Endpoint nodeP286() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP500() + : nodeP287(); + } + + private Endpoint nodeP287() { + return cond26() + ? nodeP288() + : nodeP501(); + } + + private Endpoint nodeP288() { + return cond37() + ? nodeP289() + : result85(); + } + + private Endpoint nodeP289() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP290(); + } + + private Endpoint nodeP290() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP291() + : nodeP306(); + } + + private Endpoint nodeP291() { + return cond40() + ? nodeP292() + : result56(); + } + + private Endpoint nodeP292() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP293(); + } + + private Endpoint nodeP293() { + return cond42() + ? nodeP334() + : nodeP499(); + } + + private Endpoint nodeP294() { + return cond9() + ? nodeP295() + : nodeP299(); + } + + private Endpoint nodeP295() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP296() + : nodeP299(); + } + + private Endpoint nodeP296() { + return cond11() + ? nodeP297() + : nodeP299(); + } + + private Endpoint nodeP297() { + return cond12() + ? nodeP298() + : nodeP299(); + } + + private Endpoint nodeP298() { + return cond13() + ? nodeP393() + : nodeP299(); + } + + private Endpoint nodeP299() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP338() + : nodeP300(); + } + + private Endpoint nodeP300() { + return cond15() + ? result4() + : nodeP301(); + } + + private Endpoint nodeP301() { + return cond20() + ? nodeP336() + : nodeP302(); + } + + private Endpoint nodeP302() { + return cond26() + ? nodeP303() + : nodeP340(); + } + + private Endpoint nodeP303() { + return cond37() + ? nodeP304() + : result85(); + } + + private Endpoint nodeP304() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP305(); + } + + private Endpoint nodeP305() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP308() + : nodeP306(); + } + + private Endpoint nodeP306() { + return cond48() + ? result57() + : nodeP307(); + } + + private Endpoint nodeP307() { + return cond50() + ? result73() + : result84(); + } + + private Endpoint nodeP308() { + return cond40() + ? nodeP309() + : result56(); + } + + private Endpoint nodeP309() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP310(); + } + + private Endpoint nodeP310() { + return cond42() + ? nodeP334() + : nodeP311(); + } + + private Endpoint nodeP311() { + return cond48() + ? nodeP323() + : nodeP312(); + } + + private Endpoint nodeP312() { + return cond49() + ? result44() + : nodeP313(); + } + + private Endpoint nodeP313() { + return cond51() + ? nodeP314() + : nodeP525(); + } + + private Endpoint nodeP314() { + return cond60() + ? nodeP317() + : nodeP315(); + } + + private Endpoint nodeP315() { + return cond62() + ? result54() + : nodeP316(); + } + + private Endpoint nodeP316() { + return cond63() + ? nodeP318() + : result45(); + } + + private Endpoint nodeP317() { + return cond62() + ? result54() + : nodeP318(); + } + + private Endpoint nodeP318() { + return cond64() + ? nodeP319() + : result53(); + } + + private Endpoint nodeP319() { + return cond66() + ? nodeP320() + : result52(); + } + + private Endpoint nodeP320() { + return cond69() + ? nodeP321() + : result64(); + } + + private Endpoint nodeP321() { + return cond70() + ? nodeP322() + : result51(); + } + + private Endpoint nodeP322() { + return cond72() + ? result60() + : result50(); + } + + private Endpoint nodeP323() { + return cond49() + ? result44() + : nodeP324(); + } + + private Endpoint nodeP324() { + return cond51() + ? nodeP325() + : nodeP525(); + } + + private Endpoint nodeP325() { + return cond60() + ? nodeP328() + : nodeP326(); + } + + private Endpoint nodeP326() { + return cond62() + ? result54() + : nodeP327(); + } + + private Endpoint nodeP327() { + return cond63() + ? nodeP329() + : result45(); + } + + private Endpoint nodeP328() { + return cond62() + ? result54() + : nodeP329(); + } + + private Endpoint nodeP329() { + return cond64() + ? nodeP330() + : result53(); + } + + private Endpoint nodeP330() { + return cond66() + ? nodeP331() + : result52(); + } + + private Endpoint nodeP331() { + return cond68() + ? result46() + : nodeP332(); + } + + private Endpoint nodeP332() { + return cond70() + ? nodeP333() + : result51(); + } + + private Endpoint nodeP333() { + return cond72() + ? result48() + : result50(); + } + + private Endpoint nodeP334() { + return cond48() + ? result55() + : nodeP335(); + } + + private Endpoint nodeP335() { + return cond52() + ? result66() + : result71(); + } + + private Endpoint nodeP336() { + return cond25() + ? nodeP337() + : result41(); + } + + private Endpoint nodeP337() { + return region != null && region.equals("aws-global") + ? result26() + : result27(); + } + + private Endpoint nodeP338() { + return cond15() + ? result4() + : nodeP339(); + } + + private Endpoint nodeP339() { + return cond26() + ? result87() + : nodeP340(); + } + + private Endpoint nodeP340() { + return cond28() + ? result86() + : nodeP341(); + } + + private Endpoint nodeP341() { + return cond34() + ? nodeP344() + : nodeP342(); + } + + private Endpoint nodeP342() { + return cond35() + ? nodeP343() + : nodeP544(); + } + + private Endpoint nodeP343() { + return cond36() + ? result101() + : result114(); + } + + private Endpoint nodeP344() { + return region != null && region.equals("aws-global") + ? result90() + : result91(); + } + + private Endpoint nodeP345() { + return params.endpoint() != null + ? result1() + : nodeP346(); + } + + private Endpoint nodeP346() { + return params.bucket() != null + ? nodeP356() + : nodeP347(); + } + + private Endpoint nodeP347() { + return cond8() + ? nodeP348() + : result114(); + } + + private Endpoint nodeP348() { + return cond15() + ? result4() + : nodeP349(); + } + + private Endpoint nodeP349() { + return cond16() + ? nodeP350() + : nodeP353(); + } + + private Endpoint nodeP350() { + return cond18() + ? nodeP351() + : nodeP353(); + } + + private Endpoint nodeP351() { + return cond19() + ? nodeP352() + : nodeP353(); + } + + private Endpoint nodeP352() { + return cond22() + ? result13() + : nodeP353(); + } + + private Endpoint nodeP353() { + return cond35() + ? nodeP354() + : result41(); + } + + private Endpoint nodeP354() { + return cond36() + ? result42() + : nodeP355(); + } + + private Endpoint nodeP355() { + return region != null && region.equals("aws-global") + ? result103() + : result104(); + } + + private Endpoint nodeP356() { + return cond6() + ? nodeP404() + : nodeP357(); + } + + private Endpoint nodeP357() { + return cond7() + ? nodeP394() + : nodeP358(); + } + + private Endpoint nodeP358() { + return cond8() + ? nodeP359() + : nodeP490(); + } + + private Endpoint nodeP359() { + return cond9() + ? nodeP360() + : nodeP364(); + } + + private Endpoint nodeP360() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP361() + : nodeP364(); + } + + private Endpoint nodeP361() { + return cond11() + ? nodeP362() + : nodeP364(); + } + + private Endpoint nodeP362() { + return cond12() + ? nodeP363() + : nodeP364(); + } + + private Endpoint nodeP363() { + return cond13() + ? nodeP393() + : nodeP364(); + } + + private Endpoint nodeP364() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP388() + : nodeP365(); + } + + private Endpoint nodeP365() { + return cond15() + ? result4() + : nodeP366(); + } + + private Endpoint nodeP366() { + return cond20() + ? nodeP386() + : nodeP367(); + } + + private Endpoint nodeP367() { + return cond26() + ? nodeP368() + : nodeP390(); + } + + private Endpoint nodeP368() { + return cond37() + ? nodeP369() + : result85(); + } + + private Endpoint nodeP369() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP370(); + } + + private Endpoint nodeP370() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP371() + : nodeP517(); + } + + private Endpoint nodeP371() { + return cond40() + ? nodeP372() + : result56(); + } + + private Endpoint nodeP372() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP373(); + } + + private Endpoint nodeP373() { + return cond42() + ? nodeP537() + : nodeP374(); + } + + private Endpoint nodeP374() { + return cond48() + ? result42() + : nodeP375(); + } + + private Endpoint nodeP375() { + return cond49() + ? result44() + : nodeP376(); + } + + private Endpoint nodeP376() { + return cond51() + ? nodeP377() + : nodeP525(); + } + + private Endpoint nodeP377() { + return cond60() + ? nodeP380() + : nodeP378(); + } + + private Endpoint nodeP378() { + return cond62() + ? result54() + : nodeP379(); + } + + private Endpoint nodeP379() { + return cond63() + ? nodeP381() + : result45(); + } + + private Endpoint nodeP380() { + return cond62() + ? result54() + : nodeP381(); + } + + private Endpoint nodeP381() { + return cond64() + ? nodeP382() + : result53(); + } + + private Endpoint nodeP382() { + return cond66() + ? nodeP383() + : result52(); + } + + private Endpoint nodeP383() { + return cond69() + ? nodeP384() + : result64(); + } + + private Endpoint nodeP384() { + return cond70() + ? nodeP385() + : result51(); + } + + private Endpoint nodeP385() { + return cond72() + ? result59() + : result50(); + } + + private Endpoint nodeP386() { + return cond25() + ? nodeP387() + : result41(); + } + + private Endpoint nodeP387() { + return region != null && region.equals("aws-global") + ? result24() + : result25(); + } + + private Endpoint nodeP388() { + return cond15() + ? result4() + : nodeP389(); + } + + private Endpoint nodeP389() { + return cond26() + ? result87() + : nodeP390(); + } + + private Endpoint nodeP390() { + return cond28() + ? result86() + : nodeP391(); + } + + private Endpoint nodeP391() { + return cond34() + ? nodeP392() + : nodeP543(); + } + + private Endpoint nodeP392() { + return region != null && region.equals("aws-global") + ? result88() + : result89(); + } + + private Endpoint nodeP393() { + return cond15() + ? result4() + : nodeP546(); + } + + private Endpoint nodeP394() { + return cond8() + ? nodeP395() + : result8(); + } + + private Endpoint nodeP395() { + return cond15() + ? result4() + : nodeP396(); + } + + private Endpoint nodeP396() { + return cond16() + ? nodeP397() + : nodeP409(); + } + + private Endpoint nodeP397() { + return cond18() + ? nodeP398() + : nodeP409(); + } + + private Endpoint nodeP398() { + return cond19() + ? nodeP399() + : nodeP409(); + } + + private Endpoint nodeP399() { + return cond20() + ? nodeP400() + : result8(); + } + + private Endpoint nodeP400() { + return cond27() + ? nodeP401() + : result11(); + } + + private Endpoint nodeP401() { + return cond29() + ? result10() + : nodeP402(); + } + + private Endpoint nodeP402() { + return cond31() + ? result10() + : nodeP403(); + } + + private Endpoint nodeP403() { + return cond32() + ? result10() + : nodeP421(); + } + + private Endpoint nodeP404() { + return cond8() + ? nodeP405() + : result8(); + } + + private Endpoint nodeP405() { + return cond15() + ? result4() + : nodeP406(); + } + + private Endpoint nodeP406() { + return cond16() + ? nodeP407() + : nodeP409(); + } + + private Endpoint nodeP407() { + return cond18() + ? nodeP408() + : nodeP409(); + } + + private Endpoint nodeP408() { + return cond19() + ? nodeP410() + : nodeP409(); + } + + private Endpoint nodeP409() { + return cond20() + ? result11() + : result8(); + } + + private Endpoint nodeP410() { + return cond20() + ? nodeP413() + : nodeP411(); + } + + private Endpoint nodeP411() { + return cond22() + ? nodeP412() + : result8(); + } + + private Endpoint nodeP412() { + return cond34() + ? result9() + : result8(); + } + + private Endpoint nodeP413() { + return cond22() + ? nodeP415() + : nodeP414(); + } + + private Endpoint nodeP414() { + return cond27() + ? nodeP418() + : result11(); + } + + private Endpoint nodeP415() { + return cond27() + ? nodeP417() + : nodeP416(); + } + + private Endpoint nodeP416() { + return cond34() + ? result9() + : result11(); + } + + private Endpoint nodeP417() { + return cond34() + ? result9() + : nodeP418(); + } + + private Endpoint nodeP418() { + return cond43() + ? result10() + : nodeP419(); + } + + private Endpoint nodeP419() { + return cond47() + ? result10() + : nodeP420(); + } + + private Endpoint nodeP420() { + return cond53() + ? result10() + : nodeP421(); + } + + private Endpoint nodeP421() { + return cond54() + ? result10() + : nodeP422(); + } + + private Endpoint nodeP422() { + return cond56() + ? result10() + : result11(); + } + + private Endpoint nodeP423() { + return Boolean.TRUE.equals(params.useFips()) + ? result0() + : nodeP424(); + } + + private Endpoint nodeP424() { + return Boolean.TRUE.equals(params.useDualStack()) + ? nodeP477() + : nodeP425(); + } + + private Endpoint nodeP425() { + return params.endpoint() != null + ? result3() + : nodeP426(); + } + + private Endpoint nodeP426() { + return params.bucket() != null + ? nodeP437() + : nodeP427(); + } + + private Endpoint nodeP427() { + return cond8() + ? nodeP428() + : result114(); + } + + private Endpoint nodeP428() { + return cond16() + ? nodeP429() + : nodeP432(); + } + + private Endpoint nodeP429() { + return cond18() + ? nodeP430() + : nodeP432(); + } + + private Endpoint nodeP430() { + return cond19() + ? nodeP431() + : nodeP432(); + } + + private Endpoint nodeP431() { + return cond22() + ? result13() + : nodeP432(); + } + + private Endpoint nodeP432() { + return cond35() + ? nodeP433() + : result41(); + } + + private Endpoint nodeP433() { + return cond36() + ? result43() + : nodeP434(); + } + + private Endpoint nodeP434() { + return region != null && region.equals("aws-global") + ? result111() + : nodeP435(); + } + + private Endpoint nodeP435() { + return Boolean.TRUE.equals(params.useGlobalEndpoint()) + ? nodeP436() + : result113(); + } + + private Endpoint nodeP436() { + return region != null && region.equals("us-east-1") + ? result112() + : result113(); + } + + private Endpoint nodeP437() { + return cond6() + ? result5() + : nodeP438(); + } + + private Endpoint nodeP438() { + return cond7() + ? result5() + : nodeP439(); + } + + private Endpoint nodeP439() { + return cond8() + ? nodeP449() + : nodeP440(); + } + + private Endpoint nodeP440() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP500() + : nodeP441(); + } + + private Endpoint nodeP441() { + return cond26() + ? nodeP442() + : nodeP501(); + } + + private Endpoint nodeP442() { + return cond37() + ? nodeP443() + : result85(); + } + + private Endpoint nodeP443() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP444(); + } + + private Endpoint nodeP444() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP445() + : nodeP464(); + } + + private Endpoint nodeP445() { + return cond40() + ? nodeP446() + : result56(); + } + + private Endpoint nodeP446() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP447(); + } + + private Endpoint nodeP447() { + return cond42() + ? nodeP470() + : nodeP448(); + } + + private Endpoint nodeP448() { + return cond48() + ? result43() + : nodeP499(); + } + + private Endpoint nodeP449() { + return cond9() + ? nodeP450() + : nodeP454(); + } + + private Endpoint nodeP450() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP451() + : nodeP454(); + } + + private Endpoint nodeP451() { + return cond11() + ? nodeP452() + : nodeP454(); + } + + private Endpoint nodeP452() { + return cond12() + ? nodeP453() + : nodeP454(); + } + + private Endpoint nodeP453() { + return cond13() + ? nodeP546() + : nodeP454(); + } + + private Endpoint nodeP454() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP472() + : nodeP455(); + } + + private Endpoint nodeP455() { + return cond15() + ? nodeP459() + : nodeP456(); + } + + private Endpoint nodeP456() { + return cond20() + ? nodeP457() + : nodeP460(); + } + + private Endpoint nodeP457() { + return cond25() + ? nodeP458() + : result41(); + } + + private Endpoint nodeP458() { + return region != null && region.equals("aws-global") + ? result36() + : result37(); + } + + private Endpoint nodeP459() { + return cond20() + ? nodeP539() + : nodeP460(); + } + + private Endpoint nodeP460() { + return cond26() + ? nodeP461() + : nodeP473(); + } + + private Endpoint nodeP461() { + return cond37() + ? nodeP462() + : result85(); + } + + private Endpoint nodeP462() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP463(); + } + + private Endpoint nodeP463() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP466() + : nodeP464(); + } + + private Endpoint nodeP464() { + return cond48() + ? result57() + : nodeP465(); + } + + private Endpoint nodeP465() { + return cond50() + ? result74() + : result84(); + } + + private Endpoint nodeP466() { + return cond40() + ? nodeP467() + : result56(); + } + + private Endpoint nodeP467() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP468(); + } + + private Endpoint nodeP468() { + return cond42() + ? nodeP470() + : nodeP469(); + } + + private Endpoint nodeP469() { + return cond48() + ? result43() + : nodeP523(); + } + + private Endpoint nodeP470() { + return cond48() + ? result43() + : nodeP471(); + } + + private Endpoint nodeP471() { + return cond52() + ? result67() + : result71(); + } + + private Endpoint nodeP472() { + return cond26() + ? result87() + : nodeP473(); + } + + private Endpoint nodeP473() { + return cond28() + ? result86() + : nodeP474(); + } + + private Endpoint nodeP474() { + return cond34() + ? result99() + : nodeP475(); + } + + private Endpoint nodeP475() { + return cond35() + ? nodeP476() + : nodeP544(); + } + + private Endpoint nodeP476() { + return cond36() + ? result43() + : result114(); + } + + private Endpoint nodeP477() { + return params.endpoint() != null + ? result1() + : nodeP478(); + } + + private Endpoint nodeP478() { + return params.bucket() != null + ? nodeP487() + : nodeP479(); + } + + private Endpoint nodeP479() { + return cond8() + ? nodeP480() + : result114(); + } + + private Endpoint nodeP480() { + return cond16() + ? nodeP481() + : nodeP484(); + } + + private Endpoint nodeP481() { + return cond18() + ? nodeP482() + : nodeP484(); + } + + private Endpoint nodeP482() { + return cond19() + ? nodeP483() + : nodeP484(); + } + + private Endpoint nodeP483() { + return cond22() + ? result13() + : nodeP484(); + } + + private Endpoint nodeP484() { + return cond35() + ? nodeP485() + : result41(); + } + + private Endpoint nodeP485() { + return cond36() + ? result42() + : nodeP486(); + } + + private Endpoint nodeP486() { + return region != null && region.equals("aws-global") + ? result107() + : result108(); + } + + private Endpoint nodeP487() { + return cond6() + ? result5() + : nodeP488(); + } + + private Endpoint nodeP488() { + return cond7() + ? result5() + : nodeP489(); + } + + private Endpoint nodeP489() { + return cond8() + ? nodeP502() + : nodeP490(); + } + + private Endpoint nodeP490() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP500() + : nodeP491(); + } + + private Endpoint nodeP491() { + return cond26() + ? nodeP492() + : nodeP501(); + } + + private Endpoint nodeP492() { + return cond37() + ? nodeP493() + : result85(); + } + + private Endpoint nodeP493() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP494(); + } + + private Endpoint nodeP494() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP495() + : nodeP517(); + } + + private Endpoint nodeP495() { + return cond40() + ? nodeP496() + : result56(); + } + + private Endpoint nodeP496() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP497(); + } + + private Endpoint nodeP497() { + return cond42() + ? nodeP537() + : nodeP498(); + } + + private Endpoint nodeP498() { + return cond48() + ? result42() + : nodeP499(); + } + + private Endpoint nodeP499() { + return cond49() + ? result44() + : nodeP525(); + } + + private Endpoint nodeP500() { + return cond26() + ? result87() + : nodeP501(); + } + + private Endpoint nodeP501() { + return cond28() + ? result86() + : result114(); + } + + private Endpoint nodeP502() { + return cond9() + ? nodeP503() + : nodeP507(); + } + + private Endpoint nodeP503() { + return accessPointSuffix != null && accessPointSuffix.equals("--op-s3") + ? nodeP504() + : nodeP507(); + } + + private Endpoint nodeP504() { + return cond11() + ? nodeP505() + : nodeP507(); + } + + private Endpoint nodeP505() { + return cond12() + ? nodeP506() + : nodeP507(); + } + + private Endpoint nodeP506() { + return cond13() + ? nodeP546() + : nodeP507(); + } + + private Endpoint nodeP507() { + return Boolean.TRUE.equals(params.forcePathStyle()) + ? nodeP540() + : nodeP508(); + } + + private Endpoint nodeP508() { + return cond15() + ? nodeP512() + : nodeP509(); + } + + private Endpoint nodeP509() { + return cond20() + ? nodeP510() + : nodeP513(); + } + + private Endpoint nodeP510() { + return cond25() + ? nodeP511() + : result41(); + } + + private Endpoint nodeP511() { + return region != null && region.equals("aws-global") + ? result28() + : result29(); + } + + private Endpoint nodeP512() { + return cond20() + ? nodeP539() + : nodeP513(); + } + + private Endpoint nodeP513() { + return cond26() + ? nodeP514() + : nodeP541(); + } + + private Endpoint nodeP514() { + return cond37() + ? nodeP515() + : result85(); + } + + private Endpoint nodeP515() { + return arnType != null && arnType.equals("") + ? result85() + : nodeP516(); + } + + private Endpoint nodeP516() { + return arnType != null && arnType.equals("accesspoint") + ? nodeP519() + : nodeP517(); + } + + private Endpoint nodeP517() { + return cond48() + ? result57() + : nodeP518(); + } + + private Endpoint nodeP518() { + return cond50() + ? result72() + : result84(); + } + + private Endpoint nodeP519() { + return cond40() + ? nodeP520() + : result56(); + } + + private Endpoint nodeP520() { + return accessPointName_ssa_1 != null && accessPointName_ssa_1.equals("") + ? result56() + : nodeP521(); + } + + private Endpoint nodeP521() { + return cond42() + ? nodeP537() + : nodeP522(); + } + + private Endpoint nodeP522() { + return cond48() + ? result42() + : nodeP523(); + } + + private Endpoint nodeP523() { + return cond49() + ? result44() + : nodeP524(); + } + + private Endpoint nodeP524() { + return cond51() + ? nodeP528() + : nodeP525(); + } + + private Endpoint nodeP525() { + return cond60() + ? result54() + : nodeP526(); + } + + private Endpoint nodeP526() { + return cond62() + ? result54() + : nodeP527(); + } + + private Endpoint nodeP527() { + return cond63() + ? result54() + : result45(); + } + + private Endpoint nodeP528() { + return cond60() + ? nodeP531() + : nodeP529(); + } + + private Endpoint nodeP529() { + return cond62() + ? result54() + : nodeP530(); + } + + private Endpoint nodeP530() { + return cond63() + ? nodeP532() + : result45(); + } + + private Endpoint nodeP531() { + return cond62() + ? result54() + : nodeP532(); + } + + private Endpoint nodeP532() { + return cond64() + ? nodeP533() + : result53(); + } + + private Endpoint nodeP533() { + return cond66() + ? nodeP534() + : result52(); + } + + private Endpoint nodeP534() { + return cond69() + ? nodeP535() + : result64(); + } + + private Endpoint nodeP535() { + return cond70() + ? nodeP536() + : result51(); + } + + private Endpoint nodeP536() { + return cond72() + ? result58() + : result50(); + } + + private Endpoint nodeP537() { + return cond48() + ? result42() + : nodeP538(); + } + + private Endpoint nodeP538() { + return cond52() + ? result65() + : result71(); + } + + private Endpoint nodeP539() { + return cond25() + ? result23() + : result41(); + } + + private Endpoint nodeP540() { + return cond26() + ? result87() + : nodeP541(); + } + + private Endpoint nodeP541() { + return cond28() + ? result86() + : nodeP542(); + } + + private Endpoint nodeP542() { + return cond34() + ? result99() + : nodeP543(); + } + + private Endpoint nodeP543() { + return cond35() + ? nodeP545() + : nodeP544(); + } + + private Endpoint nodeP544() { + return cond36() + ? result41() + : result114(); + } + + private Endpoint nodeP545() { + return cond36() + ? result42() + : result114(); + } + + private Endpoint nodeP546() { + return cond17() + ? nodeP547() + : result21(); + } + + private Endpoint nodeP547() { + return cond20() + ? nodeP548() + : result20(); + } + + private Endpoint nodeP548() { + return regionPrefix != null && regionPrefix.equals("beta") + ? nodeP551() + : nodeP549(); + } + + private Endpoint nodeP549() { + return hardwareType != null && hardwareType.equals("e") + ? result16() + : nodeP550(); + } + + private Endpoint nodeP550() { + return hardwareType != null && hardwareType.equals("o") + ? result18() + : result19(); + } + + private Endpoint nodeP551() { + return hardwareType != null && hardwareType.equals("e") + ? result14() + : nodeP552(); + } + + private Endpoint nodeP552() { + return hardwareType != null && hardwareType.equals("o") + ? result14() + : result19(); + } + + private boolean cond6() { + return (RulesFunctions.substringEquals(params.bucket(), 0, 6, true, "--x-s3")); + } + + private boolean cond7() { + return (RulesFunctions.substringEquals(params.bucket(), 0, 7, true, "--xa-s3")); + } + + private boolean cond8() { + partitionResult = RulesFunctions.awsPartition(region); + return partitionResult != null; + } + + private boolean cond9() { + accessPointSuffix = RulesFunctions.substring(params.bucket(), 0, 7, true); + return accessPointSuffix != null; + } + + private boolean cond11() { + regionPrefix = RulesFunctions.substring(params.bucket(), 8, 12, true); + return regionPrefix != null; + } + + private boolean cond12() { + outpostId_ssa_2 = RulesFunctions.substring(params.bucket(), 32, 49, true); + return outpostId_ssa_2 != null; + } + + private boolean cond13() { + hardwareType = RulesFunctions.substring(params.bucket(), 49, 50, true); + return hardwareType != null; + } + + private boolean cond15() { + return ("aws-cn".equals(partitionResult.name())); + } + + private boolean cond16() { + _s3e_ds = (params.useDualStack() ? ".dualstack" : ""); + return true; + } + + private boolean cond17() { + return (RulesFunctions.isValidHostLabelSingle(outpostId_ssa_2)); + } + + private boolean cond18() { + _s3e_fips = (params.useFips() ? "-fips" : ""); + return true; + } + + private boolean cond19() { + _s3e_auth = (Boolean.TRUE.equals(params.disableS3ExpressSessionAuth()) ? "sigv4" : "sigv4-s3express"); + return true; + } + + private boolean cond20() { + return (RulesFunctions.awsIsVirtualHostableS3Bucket(params.bucket(), false)); + } + + private boolean cond21() { + url = RulesFunctions.parseURL(params.endpoint()); + return url != null; + } + + private boolean cond22() { + return (Boolean.TRUE.equals(params.useS3ExpressControlEndpoint())); + } + + private boolean cond23() { + return (RulesFunctions.awsIsVirtualHostableS3Bucket(params.bucket(), true)); + } + + private boolean cond24() { + return ("http".equals(url.scheme())); + } + + private boolean cond25() { + return (RulesFunctions.isValidHostLabelSingle(region)); + } + + private boolean cond26() { + bucketArn = RulesFunctions.awsParseArn(params.bucket()); + return bucketArn != null; + } + + private boolean cond27() { + s3expressAvailabilityZoneId = RulesFunctions.listAccess(RulesFunctions.split(params.bucket(), "--", 0), -2); + return s3expressAvailabilityZoneId != null; + } + + private boolean cond28() { + return (RulesFunctions.substringEquals(params.bucket(), 0, 4, false, "arn:")); + } + + private boolean cond29() { + return (RulesFunctions.substringEquals(params.bucket(), 16, 18, true, "--")); + } + + private boolean cond30() { + return (url.isIp()); + } + + private boolean cond31() { + return (RulesFunctions.substringEquals(params.bucket(), 21, 23, true, "--")); + } + + private boolean cond32() { + return (RulesFunctions.substringEquals(params.bucket(), 27, 29, true, "--")); + } + + private boolean cond34() { + uri_encoded_bucket = RulesFunctions.uriEncode(params.bucket()); + return uri_encoded_bucket != null; + } + + private boolean cond35() { + return (RulesFunctions.isValidHostLabelMulti(region)); + } + + private boolean cond36() { + return (Boolean.TRUE.equals(params.useObjectLambdaEndpoint())); + } + + private boolean cond37() { + arnType = RulesFunctions.listAccess(bucketArn.resourceId(), 0); + return arnType != null; + } + + private boolean cond40() { + accessPointName_ssa_1 = RulesFunctions.listAccess(bucketArn.resourceId(), 1); + return accessPointName_ssa_1 != null; + } + + private boolean cond42() { + return ("".equals(bucketArn.region())); + } + + private boolean cond43() { + return (RulesFunctions.substringEquals(params.bucket(), 14, 16, true, "--")); + } + + private boolean cond47() { + return (RulesFunctions.substringEquals(params.bucket(), 19, 21, true, "--")); + } + + private boolean cond48() { + return ("s3-object-lambda".equals(bucketArn.service())); + } + + private boolean cond49() { + return (Boolean.TRUE.equals(params.disableAccessPoints())); + } + + private boolean cond50() { + return ("s3-outposts".equals(bucketArn.service())); + } + + private boolean cond51() { + bucketPartition = RulesFunctions.awsPartition(bucketArn.region()); + return bucketPartition != null; + } + + private boolean cond52() { + return (RulesFunctions.isValidHostLabelMulti(accessPointName_ssa_1)); + } + + private boolean cond53() { + return (RulesFunctions.substringEquals(params.bucket(), 26, 28, true, "--")); + } + + private boolean cond54() { + return (RulesFunctions.substringEquals(params.bucket(), 15, 17, true, "--")); + } + + private boolean cond55() { + return (RulesFunctions.listAccess(bucketArn.resourceId(), 4) != null); + } + + private boolean cond56() { + return (RulesFunctions.substringEquals(params.bucket(), 20, 22, true, "--")); + } + + private boolean cond59() { + outpostId_ssa_1 = RulesFunctions.listAccess(bucketArn.resourceId(), 1); + return outpostId_ssa_1 != null; + } + + private boolean cond60() { + return (!Boolean.FALSE.equals(params.useArnRegion())); + } + + private boolean cond61() { + return (RulesFunctions.isValidHostLabelSingle(outpostId_ssa_1)); + } + + private boolean cond62() { + outpostType = RulesFunctions.listAccess(bucketArn.resourceId(), 2); + return outpostType != null; + } + + private boolean cond63() { + return (RulesFunctions.stringEquals(region, bucketArn.region())); + } + + private boolean cond64() { + return (RulesFunctions.stringEquals(bucketPartition.name(), partitionResult.name())); + } + + private boolean cond66() { + return (RulesFunctions.isValidHostLabelMulti(bucketArn.region())); + } + + private boolean cond67() { + return (RulesFunctions.stringEquals(bucketArn.partition(), partitionResult.name())); + } + + private boolean cond68() { + return ("".equals(bucketArn.accountId())); + } + + private boolean cond69() { + return ("s3".equals(bucketArn.service())); + } + + private boolean cond70() { + return (RulesFunctions.isValidHostLabelSingle(bucketArn.accountId())); + } + + private boolean cond71() { + accessPointName_ssa_2 = RulesFunctions.listAccess(bucketArn.resourceId(), 3); + return accessPointName_ssa_2 != null; + } + + private boolean cond72() { + return (RulesFunctions.isValidHostLabelSingle(accessPointName_ssa_1)); + } + + private boolean cond74() { + return (RulesFunctions.isValidHostLabelSingle(accessPointName_ssa_2)); + } + + private Endpoint result0() { + throw SdkClientException.create("Accelerate cannot be used with FIPS"); + } + + private Endpoint result1() { + throw SdkClientException.create("Cannot set dual-stack in combination with a custom endpoint."); + } + + private Endpoint result2() { + throw SdkClientException.create("A custom endpoint cannot be combined with FIPS"); + } + + private Endpoint result3() { + throw SdkClientException.create("A custom endpoint cannot be combined with S3 Accelerate"); + } + + private Endpoint result4() { + throw SdkClientException.create("Partition does not support FIPS"); + } + + private Endpoint result5() { + throw SdkClientException.create("S3Express does not support S3 Accelerate."); + } + + private Endpoint result6() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + "/" + uri_encoded_bucket + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(DynamicEndpointAuthSchemeFactory.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).create(_s3e_auth))).build(); + } + + private Endpoint result7() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + params.bucket() + "." + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(DynamicEndpointAuthSchemeFactory.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).create(_s3e_auth))).build(); + } + + private Endpoint result8() { + throw SdkClientException.create("S3Express bucket name is not a valid virtual hostable name."); + } + + private Endpoint result9() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3express-control" + _s3e_fips + _s3e_ds + "." + region + "." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).build())).build(); + } + + private Endpoint result10() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3express" + _s3e_fips + "-" + s3expressAvailabilityZoneId + _s3e_ds + "." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(DynamicEndpointAuthSchemeFactory.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).create(_s3e_auth))).build(); + } + + private Endpoint result11() { + throw SdkClientException.create("Unrecognized S3Express bucket name format."); + } + + private Endpoint result12() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(DynamicEndpointAuthSchemeFactory.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).create(_s3e_auth))).build(); + } + + private Endpoint result13() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3express-control" + _s3e_fips + _s3e_ds + "." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3express").signingRegion(region).build())).build(); + } + + private Endpoint result14() { + throw SdkClientException.create("Expected a endpoint to be specified but no endpoint was found"); + } + + private Endpoint result15() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".ec2." + url.authority(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(region).build())).build(); + } + + private Endpoint result16() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".ec2.s3-outposts." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(region).build())).build(); + } + + private Endpoint result17() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".op-" + outpostId_ssa_2 + "." + url.authority(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(region).build())).build(); + } + + private Endpoint result18() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".op-" + outpostId_ssa_2 + ".s3-outposts." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(region).build())).build(); + } + + private Endpoint result19() { + throw SdkClientException.create("Unrecognized hardware type: \"Expected hardware type o or e but got " + hardwareType + "\""); + } + + private Endpoint result20() { + throw SdkClientException.create("Invalid Outposts Bucket alias - it must be a valid bucket name."); + } + + private Endpoint result21() { + throw SdkClientException.create("Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`."); + } + + private Endpoint result22() { + throw SdkClientException.create("Custom endpoint `" + params.endpoint() + "` was not a valid URI"); + } + + private Endpoint result23() { + throw SdkClientException.create("S3 Accelerate cannot be used in this region"); + } + + private Endpoint result24() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-fips.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result25() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-fips.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result26() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-fips.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result27() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result28() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-accelerate.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result29() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-accelerate.dualstack." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result30() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result31() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result32() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.normalizedPath() + params.bucket())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result33() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + params.bucket() + "." + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result34() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.normalizedPath() + params.bucket())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result35() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + params.bucket() + "." + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result36() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-accelerate." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result37() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3-accelerate." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result38() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result39() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result40() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", params.bucket() + ".s3." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result41() { + throw SdkClientException.create("Invalid region: region was not a valid DNS name."); + } + + private Endpoint result42() { + throw SdkClientException.create("S3 Object Lambda does not support Dual-stack"); + } + + private Endpoint result43() { + throw SdkClientException.create("S3 Object Lambda does not support S3 Accelerate"); + } + + private Endpoint result44() { + throw SdkClientException.create("Access points are not supported for this operation"); + } + + private Endpoint result45() { + throw SdkClientException.create("Invalid configuration: region from ARN `" + bucketArn.region() + "` does not match client region `" + region + "` and UseArnRegion is `false`"); + } + + private Endpoint result46() { + throw SdkClientException.create("Invalid ARN: Missing account id"); + } + + private Endpoint result47() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + accessPointName_ssa_1 + "-" + bucketArn.accountId() + "." + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result48() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-object-lambda-fips." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result49() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-object-lambda." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result50() { + throw SdkClientException.create("Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `" + accessPointName_ssa_1 + "`"); + } + + private Endpoint result51() { + throw SdkClientException.create("Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `" + bucketArn.accountId() + "`"); + } + + private Endpoint result52() { + throw SdkClientException.create("Invalid region in ARN: `" + bucketArn.region() + "` (invalid DNS name)"); + } + + private Endpoint result53() { + throw SdkClientException.create("Client was configured for partition `" + partitionResult.name() + "` but ARN (`" + params.bucket() + "`) has `" + bucketPartition.name() + "`"); + } + + private Endpoint result54() { + throw SdkClientException.create("Invalid ARN: The ARN may only contain a single resource component after `accesspoint`."); + } + + private Endpoint result55() { + throw SdkClientException.create("Invalid ARN: bucket ARN is missing a region"); + } + + private Endpoint result56() { + throw SdkClientException.create("Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided"); + } + + private Endpoint result57() { + throw SdkClientException.create("Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `" + arnType + "`"); + } + + private Endpoint result58() { + throw SdkClientException.create("Access Points do not support S3 Accelerate"); + } + + private Endpoint result59() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-accesspoint-fips.dualstack." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result60() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-accesspoint-fips." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result61() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-accesspoint.dualstack." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result62() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + accessPointName_ssa_1 + "-" + bucketArn.accountId() + "." + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result63() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + "-" + bucketArn.accountId() + ".s3-accesspoint." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result64() { + throw SdkClientException.create("Invalid ARN: The ARN was not for the S3 service, found: " + bucketArn.service()); + } + + private Endpoint result65() { + throw SdkClientException.create("S3 MRAP does not support dual-stack"); + } + + private Endpoint result66() { + throw SdkClientException.create("S3 MRAP does not support FIPS"); + } + + private Endpoint result67() { + throw SdkClientException.create("S3 MRAP does not support S3 Accelerate"); + } + + private Endpoint result68() { + throw SdkClientException.create("Invalid configuration: Multi-Region Access Point ARNs are disabled."); + } + + private Endpoint result69() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_1 + ".accesspoint.s3-global." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegionSet(Arrays.asList("*")).build())).build(); + } + + private Endpoint result70() { + throw SdkClientException.create("Client was configured for partition `" + partitionResult.name() + "` but bucket referred to partition `" + bucketArn.partition() + "`"); + } + + private Endpoint result71() { + throw SdkClientException.create("Invalid Access Point Name"); + } + + private Endpoint result72() { + throw SdkClientException.create("S3 Outposts does not support Dual-stack"); + } + + private Endpoint result73() { + throw SdkClientException.create("S3 Outposts does not support FIPS"); + } + + private Endpoint result74() { + throw SdkClientException.create("S3 Outposts does not support S3 Accelerate"); + } + + private Endpoint result75() { + throw SdkClientException.create("Invalid Arn: Outpost Access Point ARN contains sub resources"); + } + + private Endpoint result76() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_2 + "-" + bucketArn.accountId() + "." + outpostId_ssa_1 + "." + url.authority(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result77() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", accessPointName_ssa_2 + "-" + bucketArn.accountId() + "." + outpostId_ssa_1 + ".s3-outposts." + bucketArn.region() + "." + bucketPartition.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4aAuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegionSet(Arrays.asList("*")).build(), SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-outposts").signingRegion(bucketArn.region()).build())).build(); + } + + private Endpoint result78() { + throw SdkClientException.create("Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `" + accessPointName_ssa_2 + "`"); + } + + private Endpoint result79() { + throw SdkClientException.create("Expected an outpost type `accesspoint`, found " + outpostType); + } + + private Endpoint result80() { + throw SdkClientException.create("Invalid ARN: expected an access point name"); + } + + private Endpoint result81() { + throw SdkClientException.create("Invalid ARN: Expected a 4-component resource"); + } + + private Endpoint result82() { + throw SdkClientException.create("Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `" + outpostId_ssa_1 + "`"); + } + + private Endpoint result83() { + throw SdkClientException.create("Invalid ARN: The Outpost Id was not set"); + } + + private Endpoint result84() { + throw SdkClientException.create("Invalid ARN: Unrecognized format: " + params.bucket() + " (type: " + arnType + ")"); + } + + private Endpoint result85() { + throw SdkClientException.create("Invalid ARN: No ARN type specified"); + } + + private Endpoint result86() { + throw SdkClientException.create("Invalid ARN: `" + params.bucket() + "` was not a valid ARN"); + } + + private Endpoint result87() { + throw SdkClientException.create("Path-style addressing cannot be used with ARN buckets"); + } + + private Endpoint result88() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result89() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result90() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.us-east-1." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result91() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips." + region + "." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result92() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result93() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result94() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.normalizedPath() + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result95() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.normalizedPath() + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result96() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result97() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result98() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + region + "." + partitionResult.dnsSuffix(), -1, "/" + uri_encoded_bucket)).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result99() { + throw SdkClientException.create("Path-style addressing cannot be used with S3 Accelerate"); + } + + private Endpoint result100() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(region).build())).build(); + } + + private Endpoint result101() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-object-lambda-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(region).build())).build(); + } + + private Endpoint result102() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-object-lambda." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3-object-lambda").signingRegion(region).build())).build(); + } + + private Endpoint result103() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result104() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result105() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result106() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3-fips." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result107() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3.dualstack.us-east-1." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result108() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3.dualstack." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result109() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result110() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromString(url.scheme() + "://" + url.authority() + url.path())).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result111() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion("us-east-1").build())).build(); + } + + private Endpoint result112() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result113() { + return Endpoint.builder().endpointUrl(EndpointUrl.fromComponents("https", "s3." + region + "." + partitionResult.dnsSuffix(), -1, "")).putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, Arrays.asList(SigV4AuthScheme.builder().disableDoubleEncoding(true).signingName("s3").signingRegion(region).build())).build(); + } + + private Endpoint result114() { + throw SdkClientException.create("A region must be set when sending requests to S3."); + } + } + + private static final class CacheEntry { + final QueryEndpointParams params; + + final Endpoint endpoint; + + CacheEntry(QueryEndpointParams params, Endpoint endpoint) { + this.params = params; + this.endpoint = endpoint; + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java index 232b9fe14236..3164558e9c4c 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-parameters.java @@ -73,6 +73,13 @@ public Region region() { return region; } + /** + * Returns the region ID (the {@link Region#id()} value) as a String, or null if region is not set. + */ + public String regionId() { + return region == null ? null : region.id(); + } + public Boolean useDualStackEndpoint() { return useDualStackEndpoint; } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-class.java index 7c7e0170f7e5..ed0b132e269a 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-class.java @@ -1,468 +1,159 @@ package software.amazon.awssdk.services.query.endpoints.internal; -import java.net.URI; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Logger; -import software.amazon.awssdk.utils.MapUtils; import software.amazon.awssdk.utils.Validate; @Generated("software.amazon.awssdk:codegen") @SdkInternalApi public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - private static final Logger LOG = Logger.loggerFor(DefaultQueryEndpointProvider.class); - - private static final EndpointRuleset ENDPOINT_RULE_SET = ruleSet(); - - private final EndpointAuthSchemeStrategy endpointAuthSchemeStrategy; - - public DefaultQueryEndpointProvider() { - EndpointAuthSchemeStrategyFactory endpointAuthSchemeStrategyFactory = new DefaultEndpointAuthSchemeStrategyFactory(); - this.endpointAuthSchemeStrategy = endpointAuthSchemeStrategyFactory.endpointAuthSchemeStrategy(); - } - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams endpointParams) { - Validate.notNull(endpointParams.region(), "Parameter 'region' must not be null"); - Value res = new DefaultRuleEngine().evaluate(ENDPOINT_RULE_SET, toIdentifierValueMap(endpointParams)); + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - return CompletableFuture.completedFuture(valueAsEndpointOrThrow(res)); + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); } catch (Exception error) { return CompletableFutureUtils.failedFuture(error); } } - private static Map toIdentifierValueMap(QueryEndpointParams params) { - Map paramsMap = new HashMap<>(); - if (params.region() != null) { - paramsMap.put(Identifier.of("region"), Value.fromStr(params.region().id())); - } - if (params.useDualStackEndpoint() != null) { - paramsMap.put(Identifier.of("useDualStackEndpoint"), Value.fromBool(params.useDualStackEndpoint())); - } - if (params.useFipsEndpoint() != null) { - paramsMap.put(Identifier.of("useFIPSEndpoint"), Value.fromBool(params.useFipsEndpoint())); - } - if (params.accountId() != null) { - paramsMap.put(Identifier.of("AccountId"), Value.fromStr(params.accountId())); - } - if (params.accountIdEndpointMode() != null) { - paramsMap.put(Identifier.of("AccountIdEndpointMode"), Value.fromStr(params.accountIdEndpointMode())); - } - if (params.listOfStrings() != null) { - paramsMap.put(Identifier.of("listOfStrings"), - Value.fromArray(params.listOfStrings().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - if (params.defaultListOfStrings() != null) { - paramsMap.put(Identifier.of("defaultListOfStrings"), - Value.fromArray(params.defaultListOfStrings().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - if (params.endpointId() != null) { - paramsMap.put(Identifier.of("endpointId"), Value.fromStr(params.endpointId())); - } - if (params.defaultTrueParam() != null) { - paramsMap.put(Identifier.of("defaultTrueParam"), Value.fromBool(params.defaultTrueParam())); - } - if (params.defaultStringParam() != null) { - paramsMap.put(Identifier.of("defaultStringParam"), Value.fromStr(params.defaultStringParam())); - } - if (params.deprecatedParam() != null) { - paramsMap.put(Identifier.of("deprecatedParam"), Value.fromStr(params.deprecatedParam())); - } - if (params.booleanContextParam() != null) { - paramsMap.put(Identifier.of("booleanContextParam"), Value.fromBool(params.booleanContextParam())); - } - if (params.stringContextParam() != null) { - paramsMap.put(Identifier.of("stringContextParam"), Value.fromStr(params.stringContextParam())); - } - if (params.operationContextParam() != null) { - paramsMap.put(Identifier.of("operationContextParam"), Value.fromStr(params.operationContextParam())); - } - if (params.customEndpointArray() != null) { - paramsMap.put(Identifier.of("CustomEndpointArray"), - Value.fromArray(params.customEndpointArray().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - if (params.arnList() != null) { - paramsMap.put(Identifier.of("ArnList"), - Value.fromArray(params.arnList().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - return paramsMap; + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - Endpoint valueAsEndpointOrThrow(Value value) { - if (value instanceof Value.Endpoint) { - Value.Endpoint endpoint = value.expectEndpoint(); - Endpoint.Builder builder = Endpoint.builder(); - builder.url(URI.create(endpoint.getUrl())); - Map> headers = endpoint.getHeaders(); - if (headers != null) { - headers.forEach((name, values) -> values.forEach(v -> builder.putHeader(name, v))); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); + if (result.isResolved()) { + return result; + } + result = endpointRule6(params, partitionResult); + if (result.isResolved()) { + return result; } - addKnownProperties(builder, endpoint.getProperties()); - return builder.build(); - } else if (value instanceof Value.Str) { - String errorMsg = value.expectString(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() + && params.arnList() != null) { + String firstArn = RulesFunctions.listAccess(params.arnList(), 0); + if (firstArn != null) { + RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); + if (parsedArn != null) { + String arnResourceId = RulesFunctions.listAccess(parsedArn.resourceId(), 0); + if (arnResourceId != null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", arnResourceId + "." + params.endpointId() + + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + } + } } - throw SdkClientException.create(errorMsg); - } else { - throw SdkClientException.create("Rule engine return neither an endpoint result or error value. Returned value was: " - + value); } + return RuleResult.carryOn(); } - private static Rule endpointRule_2() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()).error("FIPS endpoints not supported with multi-region endpoints"); - } - - private static Rule endpointRule_3() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_4() { - return Rule.builder() - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_1() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("endpointId")))) - .build().validate()).build()) - .treeRule(Arrays.asList(endpointRule_2(), endpointRule_3(), endpointRule_4())); - } - - private static Rule endpointRule_6() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build() - .validate())).build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query-fips.{region}.{partitionResult#dnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_7() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query.{region}.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*"))))), Literal - .fromRecord(MapUtils.of(Identifier.of("name"), Literal.fromStr("sigv4"), - Identifier.of("signingName"), Literal.fromStr("query"), - Identifier.of("signingRegion"), Literal.fromStr("{region}")))))).build()); - } - - private static Rule endpointRule_8() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query-fips.{region}.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_9() { - return Rule.builder().endpoint( - EndpointResult.builder().url(Expr.of("https://query.{region}.{partitionResult#dnsSuffix}")).build()); - } - - private static Rule endpointRule_5() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isValidHostLabel") - .argv(Arrays.asList(Expr.ref(Identifier.of("region")), Expr.of(false))).build() - .validate()).build()) - .treeRule(Arrays.asList(endpointRule_6(), endpointRule_7(), endpointRule_8(), endpointRule_9())); - } - - private static Rule endpointRule_10() { - return Rule.builder().error("{region} is not a valid HTTP host-label"); - } - - private static Rule endpointRule_11() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("ArnList")))).build() - .validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("getAttr") - .argv(Arrays.asList(Expr.ref(Identifier.of("ArnList")), Expr.of("[0]"))).build() - .validate()).result("FirstArn").build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("aws.parseArn").argv(Arrays.asList(Expr.ref(Identifier.of("FirstArn")))) - .build().validate()).result("ParsedArn").build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_0() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("aws.partition").argv(Arrays.asList(Expr.ref(Identifier.of("region")))) - .build().validate()).result("partitionResult").build()) - .treeRule(Arrays.asList(endpointRule_1(), endpointRule_5(), endpointRule_10(), endpointRule_11())); - } - - private static EndpointRuleset ruleSet() { - return EndpointRuleset - .builder() - .version("1.2") - .serviceId("query") - .parameters( - Parameters - .builder() - .addParameter( - Parameter.builder().name("region").type(ParameterType.fromValue("string")).required(true) - .builtIn("AWS::Region").documentation("The region to send requests to").build()) - .addParameter( - Parameter.builder().name("useDualStackEndpoint").type(ParameterType.fromValue("boolean")) - .required(false).builtIn("AWS::UseDualStack").build()) - .addParameter( - Parameter.builder().name("useFIPSEndpoint").type(ParameterType.fromValue("boolean")) - .required(false).builtIn("AWS::UseFIPS").build()) - .addParameter( - Parameter.builder().name("AccountId").type(ParameterType.fromValue("String")) - .required(false).builtIn("AWS::Auth::AccountId").build()) - .addParameter( - Parameter.builder().name("AccountIdEndpointMode").type(ParameterType.fromValue("String")) - .required(false).builtIn("AWS::Auth::AccountIdEndpointMode").build()) - .addParameter( - Parameter.builder().name("listOfStrings").type(ParameterType.fromValue("StringArray")) - .required(false).build()) - .addParameter( - Parameter - .builder() - .name("defaultListOfStrings") - .type(ParameterType.fromValue("stringarray")) - .required(false) - .defaultValue( - Value.fromArray(Arrays.asList("item1", "item2", "item3").stream() - .map(Value::fromStr).collect(Collectors.toList()))).build()) - .addParameter( - Parameter.builder().name("endpointId").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("defaultTrueParam").type(ParameterType.fromValue("boolean")) - .required(false).documentation("A param that defauls to true") - .defaultValue(Value.fromBool(true)).build()) - .addParameter( - Parameter.builder().name("defaultStringParam").type(ParameterType.fromValue("string")) - .required(false).defaultValue(Value.fromStr("hello endpoints")).build()) - .addParameter( - Parameter.builder().name("deprecatedParam").type(ParameterType.fromValue("string")) - .required(false).deprecated(new Parameter.Deprecated("Don't use!", "2021-01-01")) - .build()) - .addParameter( - Parameter.builder().name("booleanContextParam").type(ParameterType.fromValue("boolean")) - .required(false).build()) - .addParameter( - Parameter.builder().name("stringContextParam").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("operationContextParam").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("CustomEndpointArray") - .type(ParameterType.fromValue("StringArray")).required(false) - .documentation("Parameter from the customization config").build()) - .addParameter( - Parameter.builder().name("ArnList").type(ParameterType.fromValue("StringArray")) - .required(false).documentation("Parameter from the customization config").build()) - .build()).addRule(endpointRule_0()).build(); + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { + if (params.endpointId() != null) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); + } + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).build()); + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); + } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); + } + return RuleResult.carryOn(); } @Override @@ -474,17 +165,4 @@ public boolean equals(Object rhs) { public int hashCode() { return getClass().hashCode(); } - - private void addKnownProperties(Endpoint.Builder builder, Map properties) { - properties.forEach((n, v) -> { - switch (n) { - case "authSchemes": - builder.putAttribute(AwsEndpointAttribute.AUTH_SCHEMES, endpointAuthSchemeStrategy.createAuthSchemes(v)); - break; - default: - LOG.debug(() -> "Ignoring unknown endpoint property: " + n); - break; - } - }); - } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-delegating-root-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-delegating-root-class.java new file mode 100644 index 000000000000..0759d0bb5a49 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-delegating-root-class.java @@ -0,0 +1,60 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); + Validate.notNull(params.useFipsEndpoint(), "Parameter 'useFIPSEndpoint' must not be null"); + try { + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); + } + + private static RuleResult endpointRule1(QueryEndpointParams params) { + if (params.endpoint() != null) { + return RuleResult.endpoint(Endpoint.builder().endpointUrl(EndpointUrl.fromString(params.endpoint())).build()); + } + return RuleResult.endpoint(Endpoint.builder() + .endpointUrl(EndpointUrl.fromComponents("https", "query.amazonaws.com", -1, "")).build()); + } + + @Override + public boolean equals(Object rhs) { + return rhs != null && getClass().equals(rhs.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-know-prop-override-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-know-prop-override-class.java index 98af0f39dfe4..ed0b132e269a 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-know-prop-override-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-know-prop-override-class.java @@ -1,459 +1,159 @@ package software.amazon.awssdk.services.query.endpoints.internal; -import java.net.URI; import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Logger; -import software.amazon.awssdk.utils.MapUtils; import software.amazon.awssdk.utils.Validate; @Generated("software.amazon.awssdk:codegen") @SdkInternalApi public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - private static final Logger LOG = Logger.loggerFor(DefaultQueryEndpointProvider.class); - - private static final EndpointRuleset ENDPOINT_RULE_SET = ruleSet(); - - private final EndpointAuthSchemeStrategy endpointAuthSchemeStrategy; - - public DefaultQueryEndpointProvider() { - EndpointAuthSchemeStrategyFactory endpointAuthSchemeStrategyFactory = new DefaultEndpointAuthSchemeStrategyFactory(); - this.endpointAuthSchemeStrategy = endpointAuthSchemeStrategyFactory.endpointAuthSchemeStrategy(); - } - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams endpointParams) { - Validate.notNull(endpointParams.region(), "Parameter 'region' must not be null"); - Value res = new DefaultRuleEngine().evaluate(ENDPOINT_RULE_SET, toIdentifierValueMap(endpointParams)); + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); try { - return CompletableFuture.completedFuture(valueAsEndpointOrThrow(res)); + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); } catch (Exception error) { return CompletableFutureUtils.failedFuture(error); } } - private static Map toIdentifierValueMap(QueryEndpointParams params) { - Map paramsMap = new HashMap<>(); - if (params.region() != null) { - paramsMap.put(Identifier.of("region"), Value.fromStr(params.region().id())); - } - if (params.useDualStackEndpoint() != null) { - paramsMap.put(Identifier.of("useDualStackEndpoint"), Value.fromBool(params.useDualStackEndpoint())); - } - if (params.useFipsEndpoint() != null) { - paramsMap.put(Identifier.of("useFIPSEndpoint"), Value.fromBool(params.useFipsEndpoint())); - } - if (params.accountId() != null) { - paramsMap.put(Identifier.of("AccountId"), Value.fromStr(params.accountId())); - } - if (params.accountIdEndpointMode() != null) { - paramsMap.put(Identifier.of("AccountIdEndpointMode"), Value.fromStr(params.accountIdEndpointMode())); - } - if (params.listOfStrings() != null) { - paramsMap.put(Identifier.of("listOfStrings"), - Value.fromArray(params.listOfStrings().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - if (params.defaultListOfStrings() != null) { - paramsMap.put(Identifier.of("defaultListOfStrings"), - Value.fromArray(params.defaultListOfStrings().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - if (params.endpointId() != null) { - paramsMap.put(Identifier.of("endpointId"), Value.fromStr(params.endpointId())); - } - if (params.defaultTrueParam() != null) { - paramsMap.put(Identifier.of("defaultTrueParam"), Value.fromBool(params.defaultTrueParam())); - } - if (params.defaultStringParam() != null) { - paramsMap.put(Identifier.of("defaultStringParam"), Value.fromStr(params.defaultStringParam())); - } - if (params.deprecatedParam() != null) { - paramsMap.put(Identifier.of("deprecatedParam"), Value.fromStr(params.deprecatedParam())); - } - if (params.booleanContextParam() != null) { - paramsMap.put(Identifier.of("booleanContextParam"), Value.fromBool(params.booleanContextParam())); - } - if (params.stringContextParam() != null) { - paramsMap.put(Identifier.of("stringContextParam"), Value.fromStr(params.stringContextParam())); - } - if (params.operationContextParam() != null) { - paramsMap.put(Identifier.of("operationContextParam"), Value.fromStr(params.operationContextParam())); - } - if (params.arnList() != null) { - paramsMap.put(Identifier.of("ArnList"), - Value.fromArray(params.arnList().stream().map(Value::fromStr).collect(Collectors.toList()))); - } - return paramsMap; + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); } - Endpoint valueAsEndpointOrThrow(Value value) { - if (value instanceof Value.Endpoint) { - Value.Endpoint endpoint = value.expectEndpoint(); - Endpoint.Builder builder = Endpoint.builder(); - builder.url(URI.create(endpoint.getUrl())); - Map> headers = endpoint.getHeaders(); - if (headers != null) { - headers.forEach((name, values) -> values.forEach(v -> builder.putHeader(name, v))); + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); + if (result.isResolved()) { + return result; + } + result = endpointRule6(params, partitionResult); + if (result.isResolved()) { + return result; } - addKnownProperties(builder, endpoint.getProperties()); - return builder.build(); - } else if (value instanceof Value.Str) { - String errorMsg = value.expectString(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() + && params.arnList() != null) { + String firstArn = RulesFunctions.listAccess(params.arnList(), 0); + if (firstArn != null) { + RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); + if (parsedArn != null) { + String arnResourceId = RulesFunctions.listAccess(parsedArn.resourceId(), 0); + if (arnResourceId != null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", arnResourceId + "." + params.endpointId() + + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + } + } } - throw SdkClientException.create(errorMsg); - } else { - throw SdkClientException.create("Rule engine return neither an endpoint result or error value. Returned value was: " - + value); } + return RuleResult.carryOn(); } - private static Rule endpointRule_2() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()).error("FIPS endpoints not supported with multi-region endpoints"); - } - - private static Rule endpointRule_3() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_4() { - return Rule.builder() - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_1() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("endpointId")))) - .build().validate()).build()) - .treeRule(Arrays.asList(endpointRule_2(), endpointRule_3(), endpointRule_4())); - } - - private static Rule endpointRule_6() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build() - .validate())).build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query-fips.{region}.{partitionResult#dnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_7() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query.{region}.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*"))))), Literal - .fromRecord(MapUtils.of(Identifier.of("name"), Literal.fromStr("sigv4"), - Identifier.of("signingName"), Literal.fromStr("query"), - Identifier.of("signingRegion"), Literal.fromStr("{region}")))))).build()); - } - - private static Rule endpointRule_8() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")), Expr.of(true))).build() - .validate()).build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://query-fips.{region}.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_9() { - return Rule.builder().endpoint( - EndpointResult.builder().url(Expr.of("https://query.{region}.{partitionResult#dnsSuffix}")).build()); - } - - private static Rule endpointRule_5() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isValidHostLabel") - .argv(Arrays.asList(Expr.ref(Identifier.of("region")), Expr.of(false))).build() - .validate()).build()) - .treeRule(Arrays.asList(endpointRule_6(), endpointRule_7(), endpointRule_8(), endpointRule_9())); - } - - private static Rule endpointRule_10() { - return Rule.builder().error("{region} is not a valid HTTP host-label"); - } - - private static Rule endpointRule_11() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode - .builder() - .fn("not") - .argv(Arrays.asList(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useFIPSEndpoint")))).build() - .validate())).build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")))).build().validate()) - .build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("booleanEquals") - .argv(Arrays.asList(Expr.ref(Identifier.of("useDualStackEndpoint")), Expr.of(true))) - .build().validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("isSet").argv(Arrays.asList(Expr.ref(Identifier.of("ArnList")))).build() - .validate()).build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("getAttr") - .argv(Arrays.asList(Expr.ref(Identifier.of("ArnList")), Expr.of("[0]"))).build() - .validate()).result("FirstArn").build()) - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("aws.parseArn").argv(Arrays.asList(Expr.ref(Identifier.of("FirstArn")))) - .build().validate()).result("ParsedArn").build()) - .endpoint( - EndpointResult - .builder() - .url(Expr.of("https://{endpointId}.query.{partitionResult#dualStackDnsSuffix}")) - .addProperty( - Identifier.of("authSchemes"), - Literal.fromTuple(Arrays.asList(Literal.fromRecord(MapUtils.of(Identifier.of("name"), - Literal.fromStr("sigv4a"), Identifier.of("signingName"), - Literal.fromStr("query"), Identifier.of("signingRegionSet"), - Literal.fromTuple(Arrays.asList(Literal.fromStr("*")))))))).build()); - } - - private static Rule endpointRule_0() { - return Rule - .builder() - .addCondition( - Condition - .builder() - .fn(FnNode.builder().fn("aws.partition").argv(Arrays.asList(Expr.ref(Identifier.of("region")))) - .build().validate()).result("partitionResult").build()) - .treeRule(Arrays.asList(endpointRule_1(), endpointRule_5(), endpointRule_10(), endpointRule_11())); - } - - private static EndpointRuleset ruleSet() { - return EndpointRuleset - .builder() - .version("1.2") - .serviceId("query") - .parameters( - Parameters - .builder() - .addParameter( - Parameter.builder().name("region").type(ParameterType.fromValue("string")).required(true) - .builtIn("AWS::Region").documentation("The region to send requests to").build()) - .addParameter( - Parameter.builder().name("useDualStackEndpoint").type(ParameterType.fromValue("boolean")) - .required(false).builtIn("AWS::UseDualStack").build()) - .addParameter( - Parameter.builder().name("useFIPSEndpoint").type(ParameterType.fromValue("boolean")) - .required(false).builtIn("AWS::UseFIPS").build()) - .addParameter( - Parameter.builder().name("AccountId").type(ParameterType.fromValue("String")) - .required(false).builtIn("AWS::Auth::AccountId").build()) - .addParameter( - Parameter.builder().name("AccountIdEndpointMode").type(ParameterType.fromValue("String")) - .required(false).builtIn("AWS::Auth::AccountIdEndpointMode").build()) - .addParameter( - Parameter.builder().name("listOfStrings").type(ParameterType.fromValue("StringArray")) - .required(false).build()) - .addParameter( - Parameter - .builder() - .name("defaultListOfStrings") - .type(ParameterType.fromValue("stringarray")) - .required(false) - .defaultValue( - Value.fromArray(Arrays.asList("item1", "item2", "item3").stream() - .map(Value::fromStr).collect(Collectors.toList()))).build()) - .addParameter( - Parameter.builder().name("endpointId").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("defaultTrueParam").type(ParameterType.fromValue("boolean")) - .required(false).documentation("A param that defauls to true") - .defaultValue(Value.fromBool(true)).build()) - .addParameter( - Parameter.builder().name("defaultStringParam").type(ParameterType.fromValue("string")) - .required(false).defaultValue(Value.fromStr("hello endpoints")).build()) - .addParameter( - Parameter.builder().name("deprecatedParam").type(ParameterType.fromValue("string")) - .required(false).deprecated(new Parameter.Deprecated("Don't use!", "2021-01-01")) - .build()) - .addParameter( - Parameter.builder().name("booleanContextParam").type(ParameterType.fromValue("boolean")) - .required(false).build()) - .addParameter( - Parameter.builder().name("stringContextParam").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("operationContextParam").type(ParameterType.fromValue("string")) - .required(false).build()) - .addParameter( - Parameter.builder().name("ArnList").type(ParameterType.fromValue("StringArray")) - .required(false).documentation("Parameter from the customization config").build()) - .build()).addRule(endpointRule_0()).build(); + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { + if (params.endpointId() != null) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); + } + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).build()); + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); + } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); + } + return RuleResult.carryOn(); } @Override @@ -465,17 +165,4 @@ public boolean equals(Object rhs) { public int hashCode() { return getClass().hashCode(); } - - private void addKnownProperty(EndpointAttributeProvider provider, Endpoint.Builder builder, Value value) { - builder.putAttribute(provider.attributeKey(), provider.attributeValue(value)); - } - - private void addKnownProperties(Endpoint.Builder builder, Map properties) { - List> knownProperties = software.module.test.KNOWN_PROPS; - for (EndpointAttributeProvider p : knownProperties) { - if (properties.containsKey(p.propertyName())) { - addKnownProperty(p, builder, properties.get(p.propertyName())); - } - } - } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-metric-values-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-metric-values-class.java new file mode 100644 index 000000000000..fde716375b74 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-metric-values-class.java @@ -0,0 +1,147 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); + try { + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); + } + + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); + if (result.isResolved()) { + return result; + } + result = endpointRule6(params, partitionResult); + if (result.isResolved()) { + return result; + } + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { + if (params.endpointId() != null) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); + } + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).putAttribute(AwsEndpointAttribute.METRIC_VALUES, Arrays.asList("1", "2")).build()); + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); + } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); + } + return RuleResult.carryOn(); + } + + @Override + public boolean equals(Object rhs) { + return rhs != null && getClass().equals(rhs.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-unknown-property-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-unknown-property-class.java similarity index 92% rename from codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-unknown-property-class.java rename to codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-unknown-property-class.java index 18f0c5cb6e42..908313b824e5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-unknown-property-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-unknown-property-class.java @@ -1,11 +1,11 @@ package software.amazon.awssdk.services.query.endpoints.internal; -import java.net.URI; import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -43,7 +43,7 @@ private static RuleResult endpointRule0(QueryEndpointParams params) { private static RuleResult endpointRule1(QueryEndpointParams params) { if (params.endpoint() != null) { - return RuleResult.endpoint(Endpoint.builder().url(URI.create(params.endpoint())).build()); + return RuleResult.endpoint(Endpoint.builder().endpointUrl(EndpointUrl.fromString(params.endpoint())).build()); } return RuleResult.carryOn(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-uri-cache-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-uri-cache-class.java new file mode 100644 index 000000000000..d533d71b5784 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-provider-uri-cache-class.java @@ -0,0 +1,168 @@ +package software.amazon.awssdk.services.query.endpoints.internal; + +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; +import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Validate; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { + @Override + public CompletableFuture resolveEndpoint(QueryEndpointParams params) { + Validate.notNull(params.region(), "Parameter 'region' must not be null"); + try { + RuleResult result = endpointRule0(params); + if (result.canContinue()) { + throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); + } + if (result.isError()) { + String errorMsg = result.error(); + if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { + errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; + } + throw SdkClientException.create(errorMsg); + } + return CompletableFuture.completedFuture(result.endpoint()); + } catch (Exception error) { + return CompletableFutureUtils.failedFuture(error); + } + } + + private static RuleResult endpointRule0(QueryEndpointParams params) { + return endpointRule1(params); + } + + private static RuleResult endpointRule1(QueryEndpointParams params) { + RulePartition partitionResult = RulesFunctions.awsPartition(params.regionId()); + if (partitionResult != null) { + RuleResult result = endpointRule2(params, partitionResult); + if (result.isResolved()) { + return result; + } + result = endpointRule6(params, partitionResult); + if (result.isResolved()) { + return result; + } + return RuleResult.error(params.regionId() + " is not a valid HTTP host-label"); + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() + && params.arnList() != null) { + String firstArn = RulesFunctions.listAccess(params.arnList(), 0); + if (firstArn != null) { + RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); + if (parsedArn != null) { + String arnResourceId = RulesFunctions.listAccess(parsedArn.resourceId(), 0); + if (arnResourceId != null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", arnResourceId + "." + params.endpointId() + + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + } + } + } + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { + if (params.endpointId() != null) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { + return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); + } + if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", params.endpointId() + ".query." + partitionResult.dnsSuffix(), + -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) + .build())).build()); + } + return RuleResult.carryOn(); + } + + private static RuleResult endpointRule6(QueryEndpointParams params, RulePartition partitionResult) { + if (RulesFunctions.isValidHostLabel(params.regionId(), false)) { + if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build(), + SigV4AuthScheme.builder().signingName("query").signingRegion(params.regionId()).build())) + .build()); + } + if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() + && params.useFipsEndpoint()) { + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", + "query-fips." + params.regionId() + "." + partitionResult.dualStackDnsSuffix(), -1, "")) + .putAttribute( + AwsEndpointAttribute.AUTH_SCHEMES, + Arrays.asList(SigV4aAuthScheme.builder().signingName("query") + .signingRegionSet(Arrays.asList("*")).build())).build()); + } + return RuleResult.endpoint(Endpoint + .builder() + .endpointUrl( + EndpointUrl.fromComponents("https", "query." + params.regionId() + "." + partitionResult.dnsSuffix(), + -1, "")).build()); + } + return RuleResult.carryOn(); + } + + @Override + public boolean equals(Object rhs) { + return rhs != null && getClass().equals(rhs.getClass()); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java index cf27b03ed0c3..de8be3aa52a1 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java @@ -62,7 +62,7 @@ public QueryResolveEndpointInterceptor() { @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes @@ -110,7 +110,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); - if (resolvedEndpoint.headers().isEmpty()) { + if (resolvedEndpoint == null || CollectionUtils.isNullOrEmpty(resolvedEndpoint.headers())) { return context.httpRequest(); } SdkHttpRequest.Builder httpRequestBuilder = context.httpRequest().toBuilder(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java index 6d6aa1dc2138..71cd3af7868b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-endpointsbasedauth.java @@ -50,7 +50,7 @@ public final class QueryResolveEndpointInterceptor implements ExecutionIntercept @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes @@ -102,7 +102,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); - if (resolvedEndpoint.headers().isEmpty()) { + if (resolvedEndpoint == null || CollectionUtils.isNullOrEmpty(resolvedEndpoint.headers())) { return context.httpRequest(); } SdkHttpRequest.Builder httpRequestBuilder = context.httpRequest().toBuilder(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java index 858d39fc7a69..26e225ab6fc5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-multiauthsigv4a.java @@ -39,7 +39,7 @@ public final class DatabaseResolveEndpointInterceptor implements ExecutionInterc @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } DatabaseEndpointProvider provider = (DatabaseEndpointProvider) executionAttributes @@ -91,7 +91,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); - if (resolvedEndpoint.headers().isEmpty()) { + if (resolvedEndpoint == null || CollectionUtils.isNullOrEmpty(resolvedEndpoint.headers())) { return context.httpRequest(); } SdkHttpRequest.Builder httpRequestBuilder = context.httpRequest().toBuilder(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java index 0f5033376ffc..23ba5b360972 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-with-stringarray.java @@ -41,7 +41,7 @@ public final class SampleSvcResolveEndpointInterceptor implements ExecutionInter @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } SampleSvcEndpointProvider provider = (SampleSvcEndpointProvider) executionAttributes @@ -84,7 +84,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); - if (resolvedEndpoint.headers().isEmpty()) { + if (resolvedEndpoint == null || CollectionUtils.isNullOrEmpty(resolvedEndpoint.headers())) { return context.httpRequest(); } SdkHttpRequest.Builder httpRequestBuilder = context.httpRequest().toBuilder(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java index abdfedab0455..1d170e6413e8 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java @@ -50,7 +50,7 @@ public final class QueryResolveEndpointInterceptor implements ExecutionIntercept @Override public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { SdkRequest result = context.request(); - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return result; } QueryEndpointProvider provider = (QueryEndpointProvider) executionAttributes @@ -93,7 +93,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { Endpoint resolvedEndpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); - if (resolvedEndpoint.headers().isEmpty()) { + if (resolvedEndpoint == null || CollectionUtils.isNullOrEmpty(resolvedEndpoint.headers())) { return context.httpRequest(); } SdkHttpRequest.Builder httpRequestBuilder = context.httpRequest().toBuilder(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-endpointsbasedauth.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-endpointsbasedauth.java index ad3b2e674750..2bb0ab811240 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-endpointsbasedauth.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-endpointsbasedauth.java @@ -191,7 +191,7 @@ private static String recordAccountIdEndpointMode(ExecutionAttributes executionA AccountIdEndpointMode mode = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE); BusinessMetricsUtils.resolveAccountIdEndpointModeMetric(mode).ifPresent( m -> executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(m)); - return mode.name().toLowerCase(); + return mode.value(); } public static void setMetricValues(Endpoint endpoint, ExecutionAttributes executionAttributes) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-stringarray.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-stringarray.java index aaed43624739..9ffb9eced65c 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-stringarray.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils-with-stringarray.java @@ -1,7 +1,10 @@ package software.amazon.awssdk.services.samplesvc.endpoints.internal; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -21,13 +24,23 @@ import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.services.samplesvc.endpoints.SampleSvcEndpointParams; -import software.amazon.awssdk.services.samplesvc.jmespath.internal.JmesPathRuntime; +import software.amazon.awssdk.services.samplesvc.model.Delete; import software.amazon.awssdk.services.samplesvc.model.ListOfObjectsOperationRequest; +import software.amazon.awssdk.services.samplesvc.model.MapKeysOperationRequest; +import software.amazon.awssdk.services.samplesvc.model.Nested; +import software.amazon.awssdk.services.samplesvc.model.ObjectMember; +import software.amazon.awssdk.services.samplesvc.model.Put; +import software.amazon.awssdk.services.samplesvc.model.TransactItem; +import software.amazon.awssdk.services.samplesvc.model.TransactionOperationRequest; import software.amazon.awssdk.utils.CollectionUtils; @Generated("software.amazon.awssdk:codegen") @SdkInternalApi public final class SampleSvcEndpointResolverUtils { + private static final List STATIC_LIST_EMPTY_STATIC_CONTEXT_OPERATION_STRING_ARRAY_PARAM = Collections.emptyList(); + + private static final List STATIC_LIST_STATIC_CONTEXT_OPERATION_STRING_ARRAY_PARAM = Collections.unmodifiableList(Arrays.asList("staticValue1")); + private SampleSvcEndpointResolverUtils() { } @@ -57,12 +70,12 @@ private static void setStaticContextParams(SampleSvcEndpointParams.Builder param private static void emptyStaticContextOperationStaticContextParams( SampleSvcEndpointParams.Builder params) { - params.stringArrayParam(Arrays.asList()); + params.stringArrayParam(STATIC_LIST_EMPTY_STATIC_CONTEXT_OPERATION_STRING_ARRAY_PARAM); } private static void staticContextOperationStaticContextParams( SampleSvcEndpointParams.Builder params) { - params.stringArrayParam(Arrays.asList("staticValue1")); + params.stringArrayParam(STATIC_LIST_STATIC_CONTEXT_OPERATION_STRING_ARRAY_PARAM); } public static SelectedAuthScheme authSchemeWithEndpointSignerProperties( @@ -109,14 +122,68 @@ private static void setOperationContextParams(SampleSvcEndpointParams.Builder pa switch (operationName) { case "ListOfObjectsOperation":setOperationContextParams(params, (ListOfObjectsOperationRequest) request); break; + case "MapKeysOperation":setOperationContextParams(params, (MapKeysOperationRequest) request); + break; + case "TransactionOperation":setOperationContextParams(params, (TransactionOperationRequest) request); + break; default:break; } } private static void setOperationContextParams(SampleSvcEndpointParams.Builder params, ListOfObjectsOperationRequest request) { - JmesPathRuntime.Value input = new JmesPathRuntime.Value(request); - params.stringArrayParam(input.field("nested").field("listOfObjects").wildcard().field("key").stringValues()); + List stringArrayParam = Collections.emptyList(); + Nested nested = request.nested(); + if (nested != null) { + List listOfObjects = nested.listOfObjects(); + stringArrayParam = new ArrayList<>(listOfObjects.size()); + for (ObjectMember objectMember : listOfObjects) { + if (objectMember != null) { + String key = objectMember.key(); + if (key != null) { + stringArrayParam.add(key); + } + } + } + } + params.stringArrayParam(stringArrayParam); + } + + private static void setOperationContextParams(SampleSvcEndpointParams.Builder params, + MapKeysOperationRequest request) { + Map requestItems = request.requestItems(); + List stringArrayParam = new ArrayList<>(requestItems.size()); + for (String key : requestItems.keySet()) { + if (key != null) { + stringArrayParam.add(key); + } + } + params.stringArrayParam(stringArrayParam); + } + + private static void setOperationContextParams(SampleSvcEndpointParams.Builder params, + TransactionOperationRequest request) { + List transactItems = request.transactItems(); + List stringArrayParam = new ArrayList<>(transactItems.size()); + for (TransactItem transactItem : transactItems) { + if (transactItem != null) { + Put put = transactItem.put(); + if (put != null) { + String tableName = put.tableName(); + if (tableName != null) { + stringArrayParam.add(tableName); + } + } + Delete delete = transactItem.delete(); + if (delete != null) { + String tableName_ = delete.tableName(); + if (tableName_ != null) { + stringArrayParam.add(tableName_); + } + } + } + } + params.stringArrayParam(stringArrayParam); } public static Optional hostPrefix(String operationName, SdkRequest request) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils.java index 01c7ba43831f..e7033a06876e 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolver-utils.java @@ -198,7 +198,7 @@ private static String recordAccountIdEndpointMode(ExecutionAttributes executionA AccountIdEndpointMode mode = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE); BusinessMetricsUtils.resolveAccountIdEndpointModeMetric(mode).ifPresent( m -> executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(m)); - return mode.name().toLowerCase(); + return mode.value(); } public static void setMetricValues(Endpoint endpoint, ExecutionAttributes executionAttributes) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-metric-values-test-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-metric-values-test-class.java index 67576fdf1a95..a40e26d6a0e3 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-metric-values-test-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-metric-values-test-class.java @@ -26,7 +26,7 @@ public void resolvesCorrectEndpoint(EndpointProviderTestCase tc) { private static List testCases() { List testCases = new ArrayList<>(); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 1", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.region(Region.of("us-east-1")); return PROVIDER.resolveEndpoint(builder.build()).join(); @@ -35,50 +35,50 @@ private static List testCases() { .endpoint( Endpoint.builder().url(URI.create("https://myservice.aws")) .putAttribute(AwsEndpointAttribute.METRIC_VALUES, Arrays.asList("1", "2")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 2", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.region(Region.of("us-east-1")); builder.booleanContextParam(true); builder.stringContextParam("this is a test"); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 3", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.region(Region.of("us-east-1")); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 4", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.region(Region.of("us-east-6")); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 5", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.accountId("012345678901"); builder.accountIdEndpointMode("required"); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 6", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.accountId("012345678901"); builder.accountIdEndpointMode("required"); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 7", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); builder.accountId("012345678901"); builder.accountIdEndpointMode("required"); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("For region us-iso-west-1 with FIPS enabled and DualStack enabled", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Should have been skipped!").build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Has complex operation input", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Missing info").build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Has has undeclared input parameter", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Missing info").build())); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-stringarray-test-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-stringarray-test-class.java index 93ea4e6b281c..466cccc5d728 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-stringarray-test-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-stringarray-test-class.java @@ -24,21 +24,21 @@ public void resolvesCorrectEndpoint(EndpointProviderTestCase tc) { private static List testCases() { List testCases = new ArrayList<>(); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Default array values used", () -> { SampleSvcEndpointParams.Builder builder = SampleSvcEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://example.com/defaultValue1")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Empty array", () -> { SampleSvcEndpointParams.Builder builder = SampleSvcEndpointParams.builder(); builder.stringArrayParam(Arrays.asList()); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("no array values set").build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Static value", () -> { SampleSvcEndpointParams.Builder builder = SampleSvcEndpointParams.builder(); builder.stringArrayParam(Arrays.asList("staticValue1")); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://example.com/staticValue1")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("bound value from input", () -> { SampleSvcEndpointParams.Builder builder = SampleSvcEndpointParams.builder(); builder.stringArrayParam(Arrays.asList("key1")); return PROVIDER.resolveEndpoint(builder.build()).join(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-unknown-property-test-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-unknown-property-test-class.java index b471a05fad5c..69f06553b84d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-unknown-property-test-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-rules-unknown-property-test-class.java @@ -38,43 +38,43 @@ public void resolvesCorrectEndpoint(EndpointProviderTestCase tc) { private static List testCases() { List testCases = new ArrayList<>(); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 1", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 2", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 3", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 4", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 5", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 6", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("test case 7", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().endpoint(Endpoint.builder().url(URI.create("https://012345678901.myservice.aws")).build()).build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("For region us-iso-west-1 with FIPS enabled and DualStack enabled", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Should have been skipped!").build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Has complex operation input", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Missing info").build())); - testCases.add(new EndpointProviderTestCase(() -> { + testCases.add(new EndpointProviderTestCase("Has has undeclared input parameter", () -> { QueryEndpointParams.Builder builder = QueryEndpointParams.builder(); return PROVIDER.resolveEndpoint(builder.build()).join(); }, Expect.builder().error("Missing info").build())); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java index 4cfeedb59e46..8895321a6863 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/request-set-endpoint-interceptor.java @@ -14,7 +14,7 @@ public final class QueryRequestSetEndpointInterceptor implements ExecutionInterceptor { @Override public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - if (AwsEndpointProviderUtils.endpointIsDiscovered(executionAttributes)) { + if (AwsEndpointProviderUtils.skipEndpointResolution(executionAttributes)) { return context.httpRequest(); } Endpoint endpoint = executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java deleted file mode 100644 index 684823698760..000000000000 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-class.java +++ /dev/null @@ -1,153 +0,0 @@ -package software.amazon.awssdk.services.query.endpoints.internal; - -import java.net.URI; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import software.amazon.awssdk.annotations.Generated; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; -import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Validate; - -@Generated("software.amazon.awssdk:codegen") -@SdkInternalApi -public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams params) { - Validate.notNull(params.region(), "Parameter 'region' must not be null"); - try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); - if (result.canContinue()) { - throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); - } - if (result.isError()) { - String errorMsg = result.error(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; - } - throw SdkClientException.create(errorMsg); - } - return CompletableFuture.completedFuture(result.endpoint()); - } catch (Exception error) { - return CompletableFutureUtils.failedFuture(error); - } - } - - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); - } - - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); - if (partitionResult != null) { - RuleResult result = endpointRule2(params, partitionResult); - if (result.isResolved()) { - return result; - } - result = endpointRule6(params, region, partitionResult); - if (result.isResolved()) { - return result; - } - return RuleResult.error(region + " is not a valid HTTP host-label"); - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() - && params.arnList() != null) { - String firstArn = RulesFunctions.listAccess(params.arnList(), 0); - if (firstArn != null) { - RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); - if (parsedArn != null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - } - } - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { - if (params.endpointId() != null) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint.builder() - .url(URI.create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); - } - return RuleResult.carryOn(); - } - - @Override - public boolean equals(Object rhs) { - return rhs != null && getClass().equals(rhs.getClass()); - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } -} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java deleted file mode 100644 index 684823698760..000000000000 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-know-prop-override-class.java +++ /dev/null @@ -1,153 +0,0 @@ -package software.amazon.awssdk.services.query.endpoints.internal; - -import java.net.URI; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import software.amazon.awssdk.annotations.Generated; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; -import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Validate; - -@Generated("software.amazon.awssdk:codegen") -@SdkInternalApi -public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams params) { - Validate.notNull(params.region(), "Parameter 'region' must not be null"); - try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); - if (result.canContinue()) { - throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); - } - if (result.isError()) { - String errorMsg = result.error(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; - } - throw SdkClientException.create(errorMsg); - } - return CompletableFuture.completedFuture(result.endpoint()); - } catch (Exception error) { - return CompletableFutureUtils.failedFuture(error); - } - } - - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); - } - - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); - if (partitionResult != null) { - RuleResult result = endpointRule2(params, partitionResult); - if (result.isResolved()) { - return result; - } - result = endpointRule6(params, region, partitionResult); - if (result.isResolved()) { - return result; - } - return RuleResult.error(region + " is not a valid HTTP host-label"); - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() - && params.arnList() != null) { - String firstArn = RulesFunctions.listAccess(params.arnList(), 0); - if (firstArn != null) { - RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); - if (parsedArn != null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." - + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - } - } - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { - if (params.endpointId() != null) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint.builder() - .url(URI.create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); - } - return RuleResult.carryOn(); - } - - @Override - public boolean equals(Object rhs) { - return rhs != null && getClass().equals(rhs.getClass()); - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } -} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java deleted file mode 100644 index 6c854826e953..000000000000 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-metric-values-class.java +++ /dev/null @@ -1,136 +0,0 @@ -package software.amazon.awssdk.services.query.endpoints.internal; - -import java.net.URI; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import software.amazon.awssdk.annotations.Generated; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; -import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Validate; - -@Generated("software.amazon.awssdk:codegen") -@SdkInternalApi -public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams params) { - Validate.notNull(params.region(), "Parameter 'region' must not be null"); - try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); - if (result.canContinue()) { - throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); - } - if (result.isError()) { - String errorMsg = result.error(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; - } - throw SdkClientException.create(errorMsg); - } - return CompletableFuture.completedFuture(result.endpoint()); - } catch (Exception error) { - return CompletableFutureUtils.failedFuture(error); - } - } - - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); - } - - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); - if (partitionResult != null) { - RuleResult result = endpointRule2(params, partitionResult); - if (result.isResolved()) { - return result; - } - result = endpointRule6(params, region, partitionResult); - if (result.isResolved()) { - return result; - } - return RuleResult.error(region + " is not a valid HTTP host-label"); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { - if (params.endpointId() != null) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).putAttribute(AwsEndpointAttribute.METRIC_VALUES, Arrays.asList("1", "2")).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(URI.create("https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint.builder() - .url(URI.create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); - } - return RuleResult.carryOn(); - } - - @Override - public boolean equals(Object rhs) { - return rhs != null && getClass().equals(rhs.getClass()); - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } -} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java deleted file mode 100644 index 53eb66b3c147..000000000000 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules2/endpoint-provider-uri-cache-class.java +++ /dev/null @@ -1,155 +0,0 @@ -package software.amazon.awssdk.services.query.endpoints.internal; - -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import software.amazon.awssdk.annotations.Generated; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointParams; -import software.amazon.awssdk.services.query.endpoints.QueryEndpointProvider; -import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Validate; -import software.amazon.awssdk.utils.uri.SdkUri; - -@Generated("software.amazon.awssdk:codegen") -@SdkInternalApi -public final class DefaultQueryEndpointProvider implements QueryEndpointProvider { - @Override - public CompletableFuture resolveEndpoint(QueryEndpointParams params) { - Validate.notNull(params.region(), "Parameter 'region' must not be null"); - try { - Region region = params.region(); - String regionId = region == null ? null : region.id(); - RuleResult result = endpointRule0(params, regionId); - if (result.canContinue()) { - throw SdkClientException.create("Rule engine did not reach an error or endpoint result"); - } - if (result.isError()) { - String errorMsg = result.error(); - if (errorMsg.contains("Invalid ARN") && errorMsg.contains(":s3:::")) { - errorMsg += ". Use the bucket name instead of simple bucket ARNs in GetBucketLocationRequest."; - } - throw SdkClientException.create(errorMsg); - } - return CompletableFuture.completedFuture(result.endpoint()); - } catch (Exception error) { - return CompletableFutureUtils.failedFuture(error); - } - } - - private static RuleResult endpointRule0(QueryEndpointParams params, String region) { - return endpointRule1(params, region); - } - - private static RuleResult endpointRule1(QueryEndpointParams params, String region) { - RulePartition partitionResult = RulesFunctions.awsPartition(region); - if (partitionResult != null) { - RuleResult result = endpointRule2(params, partitionResult); - if (result.isResolved()) { - return result; - } - result = endpointRule6(params, region, partitionResult); - if (result.isResolved()) { - return result; - } - return RuleResult.error(region + " is not a valid HTTP host-label"); - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint() - && params.arnList() != null) { - String firstArn = RulesFunctions.listAccess(params.arnList(), 0); - if (firstArn != null) { - RuleArn parsedArn = RulesFunctions.awsParseArn(firstArn); - if (parsedArn != null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create( - "https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - } - } - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule2(QueryEndpointParams params, RulePartition partitionResult) { - if (params.endpointId() != null) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint()) { - return RuleResult.error("FIPS endpoints not supported with multi-region endpoints"); - } - if (params.useFipsEndpoint() == null && params.useDualStackEndpoint() != null && params.useDualStackEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create( - "https://" + params.endpointId() + ".query." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create("https://" + params.endpointId() + ".query." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query").signingRegionSet(Arrays.asList("*")) - .build())).build()); - } - return RuleResult.carryOn(); - } - - private static RuleResult endpointRule6(QueryEndpointParams params, String region, RulePartition partitionResult) { - if (RulesFunctions.isValidHostLabel(region, false)) { - if (params.useFipsEndpoint() != null && params.useFipsEndpoint() && params.useDualStackEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create("https://query-fips." + region + "." + partitionResult.dnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useDualStackEndpoint() && params.useFipsEndpoint() == null) { - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create("https://query." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build(), - SigV4AuthScheme.builder().signingName("query").signingRegion(region).build())).build()); - } - if (params.useDualStackEndpoint() != null && params.useFipsEndpoint() != null && params.useDualStackEndpoint() - && params.useFipsEndpoint()) { - return RuleResult.endpoint(Endpoint - .builder() - .url(SdkUri.getInstance().create( - "https://query-fips." + region + "." + partitionResult.dualStackDnsSuffix())) - .putAttribute( - AwsEndpointAttribute.AUTH_SCHEMES, - Arrays.asList(SigV4aAuthScheme.builder().signingName("query") - .signingRegionSet(Arrays.asList("*")).build())).build()); - } - return RuleResult.endpoint(Endpoint.builder() - .url(SdkUri.getInstance().create("https://query." + region + "." + partitionResult.dnsSuffix())).build()); - } - return RuleResult.carryOn(); - } - - @Override - public boolean equals(Object rhs) { - return rhs != null && getClass().equals(rhs.getClass()); - } - - @Override - public int hashCode() { - return getClass().hashCode(); - } -} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-async-only.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-async-only.java new file mode 100644 index 000000000000..e4c9dcc49d0a --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-async-only.java @@ -0,0 +1,45 @@ +package software.amazon.awssdk.services.query.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.query.QueryAsyncClient; +import software.amazon.awssdk.services.query.model.GetOperationWithChecksumRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class QueryWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return null; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.query.QueryAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (QueryAsyncClient asyncClient = QueryAsyncClient.builder().httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.getOperationWithChecksum(GetOperationWithChecksumRequest.builder().build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-bearer-auth.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-bearer-auth.java new file mode 100644 index 000000000000..5317ca5e28de --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-bearer-auth.java @@ -0,0 +1,62 @@ +package software.amazon.awssdk.services.json.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.json.JsonAsyncClient; +import software.amazon.awssdk.services.json.JsonClient; +import software.amazon.awssdk.services.json.model.APostOperationRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class JsonWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "{}".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.json.JsonClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.json.JsonAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (JsonClient client = JsonClient.builder() + .httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + client.aPostOperation(APostOperationRequest.builder().build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (JsonAsyncClient asyncClient = JsonAsyncClient.builder() + .httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + asyncClient.aPostOperation(APostOperationRequest.builder().build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-cbor.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-cbor.java new file mode 100644 index 000000000000..0abf36235d02 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-cbor.java @@ -0,0 +1,52 @@ +package software.amazon.awssdk.services.json.internal.warmup; + +import java.net.URI; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.json.JsonAsyncClient; +import software.amazon.awssdk.services.json.JsonClient; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class JsonWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = new byte[] { (byte) 0xA0 }; + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.json.JsonClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.json.JsonAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (JsonClient client = JsonClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + client.paginatedOperationWithResultKey(); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (JsonAsyncClient asyncClient = JsonAsyncClient.builder().httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.paginatedOperationWithResultKey().join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-endpoint-discovery.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-endpoint-discovery.java new file mode 100644 index 000000000000..043fe7a8b42e --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-endpoint-discovery.java @@ -0,0 +1,61 @@ +package software.amazon.awssdk.services.endpointdiscoverytest.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.endpointdiscoverytest.EndpointDiscoveryTestAsyncClient; +import software.amazon.awssdk.services.endpointdiscoverytest.EndpointDiscoveryTestClient; +import software.amazon.awssdk.services.endpointdiscoverytest.model.DescribeEndpointsRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class EndpointDiscoveryTestWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "{}".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.endpointdiscoverytest.EndpointDiscoveryTestClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.endpointdiscoverytest.EndpointDiscoveryTestAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (EndpointDiscoveryTestClient client = EndpointDiscoveryTestClient.builder() + .httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .endpointDiscoveryEnabled(false) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + client.describeEndpoints(DescribeEndpointsRequest.builder().build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (EndpointDiscoveryTestAsyncClient asyncClient = EndpointDiscoveryTestAsyncClient.builder() + .httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .endpointDiscoveryEnabled(false) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + asyncClient.describeEndpoints(DescribeEndpointsRequest.builder().build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-query.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-query.java new file mode 100644 index 000000000000..c2c598edec5a --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-query.java @@ -0,0 +1,57 @@ +package software.amazon.awssdk.services.query.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.query.QueryAsyncClient; +import software.amazon.awssdk.services.query.QueryClient; +import software.amazon.awssdk.services.query.model.GetOperationWithChecksumRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class QueryWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.query.QueryClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.query.QueryAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (QueryClient client = QueryClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + client.getOperationWithChecksum(GetOperationWithChecksumRequest.builder().build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (QueryAsyncClient asyncClient = QueryAsyncClient.builder().httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.getOperationWithChecksum(GetOperationWithChecksumRequest.builder().build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rest-json.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rest-json.java new file mode 100644 index 000000000000..7a029c3df2a1 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rest-json.java @@ -0,0 +1,56 @@ +package software.amazon.awssdk.services.json.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.json.JsonAsyncClient; +import software.amazon.awssdk.services.json.JsonClient; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class JsonWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "{}".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.json.JsonClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.json.JsonAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (JsonClient client = JsonClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + client.paginatedOperationWithResultKey(); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (JsonAsyncClient asyncClient = JsonAsyncClient.builder().httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.paginatedOperationWithResultKey().join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rpcv2.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rpcv2.java new file mode 100644 index 000000000000..cc0c0e980894 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-rpcv2.java @@ -0,0 +1,54 @@ +package software.amazon.awssdk.services.smithyrpcv2protocol.internal.warmup; + +import java.net.URI; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.smithyrpcv2protocol.SmithyRpcV2ProtocolAsyncClient; +import software.amazon.awssdk.services.smithyrpcv2protocol.SmithyRpcV2ProtocolClient; +import software.amazon.awssdk.services.smithyrpcv2protocol.model.EmptyInputOutputRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class SmithyRpcV2ProtocolWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = new byte[] { (byte) 0xA0 }; + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.smithyrpcv2protocol.SmithyRpcV2ProtocolClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.smithyrpcv2protocol.SmithyRpcV2ProtocolAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (SmithyRpcV2ProtocolClient client = SmithyRpcV2ProtocolClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + client.emptyInputOutput(EmptyInputOutputRequest.builder().build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (SmithyRpcV2ProtocolAsyncClient asyncClient = SmithyRpcV2ProtocolAsyncClient.builder() + .httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.emptyInputOutput(EmptyInputOutputRequest.builder().build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-s3control.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-s3control.java new file mode 100644 index 000000000000..37e91e028c49 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-s3control.java @@ -0,0 +1,59 @@ +package software.amazon.awssdk.services.s3control.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3control.S3ControlAsyncClient; +import software.amazon.awssdk.services.s3control.S3ControlClient; +import software.amazon.awssdk.services.s3control.model.ListAccessGrantsRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class S3ControlWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.s3control.S3ControlClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.s3control.S3ControlAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (S3ControlClient client = S3ControlClient.builder() + .httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + client.listAccessGrants(ListAccessGrantsRequest.builder().accountId("warmup").build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (S3ControlAsyncClient asyncClient = S3ControlAsyncClient.builder() + .httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .build()) { + asyncClient.listAccessGrants(ListAccessGrantsRequest.builder().accountId("warmup").build()).join(); + } + } + } +} diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-xml.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-xml.java new file mode 100644 index 000000000000..53e1939ed800 --- /dev/null +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/warmup/warmup-provider-xml.java @@ -0,0 +1,57 @@ +package software.amazon.awssdk.services.xml.internal.warmup; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import software.amazon.awssdk.annotations.Generated; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.auth.token.credentials.StaticTokenProvider; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.core.warmup.http.CannedResponseAsyncHttpClient; +import software.amazon.awssdk.core.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.xml.XmlAsyncClient; +import software.amazon.awssdk.services.xml.XmlClient; +import software.amazon.awssdk.services.xml.model.GetOperationWithChecksumRequest; + +@Generated("software.amazon.awssdk:codegen") +@SdkInternalApi +public final class XmlWarmUpProvider implements SdkWarmUpProvider { + private static final byte[] CANNED_RESPONSE = "".getBytes(StandardCharsets.UTF_8); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.xml.XmlClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.xml.XmlAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SdkHttpClient httpClient = CannedResponseHttpClient.builder().responseBody(CANNED_RESPONSE).statusCode(200).build(); + try (XmlClient client = XmlClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + client.getOperationWithChecksum(GetOperationWithChecksumRequest.builder().build()); + } + } + if (clientType == ClientType.ASYNC) { + SdkAsyncHttpClient asyncHttpClient = CannedResponseAsyncHttpClient.builder().responseBody(CANNED_RESPONSE) + .statusCode(200).build(); + try (XmlAsyncClient asyncClient = XmlAsyncClient.builder().httpClient(asyncHttpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .tokenProvider(StaticTokenProvider.create(() -> "warmup-dummy-token")) + .region(Region.US_EAST_1).endpointOverride(URI.create("http://localhost")).build()) { + asyncClient.getOperationWithChecksum(GetOperationWithChecksumRequest.builder().build()).join(); + } + } + } +} diff --git a/core/annotations/pom.xml b/core/annotations/pom.xml index 6ea4e8a6822a..ec4be8c4086f 100644 --- a/core/annotations/pom.xml +++ b/core/annotations/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/annotations/src/main/java/software/amazon/awssdk/annotations/SdkAdvancedApi.java b/core/annotations/src/main/java/software/amazon/awssdk/annotations/SdkAdvancedApi.java new file mode 100644 index 000000000000..e7d5dab98bcb --- /dev/null +++ b/core/annotations/src/main/java/software/amazon/awssdk/annotations/SdkAdvancedApi.java @@ -0,0 +1,76 @@ +/* + * 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.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks an API that is error-prone to use: implementing, overriding, or calling it incorrectly, or + * configuring it with an unsafe value, compiles cleanly but can fail or misbehave at runtime rather + * than reporting a clear error. + * + *

The annotation records the risk information on the API in a structured form: {@link #cautionWhen()} + * classifies which kind of use is error-prone, {@link #guidance()} explains the contract that must + * be upheld, {@link #saferAlternative()} points to a lower-risk approach, and {@link #link()} points + * to further documentation. + * + *

This is an advisory marker: it does not gate compilation and imposes no runtime behavior. + */ +@Documented +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) +@Retention(RetentionPolicy.CLASS) +@SdkProtectedApi +public @interface SdkAdvancedApi { + + /** + * Which kind of use of this API is error-prone: IMPLEMENTED if the risk is in implementing + * or extending the annotated type, OVERRIDDEN if it is in overriding the annotated method, + * CONFIGURED if it is in setting the annotated field or option, and CALLED if it is in + * calling the annotated method (for example a factory that accepts an object you supply and does + * not shield you from that object's contract). Required. + */ + Usage cautionWhen(); + + /** + * Explains why this API is error-prone and what you must uphold to use it safely: the parts of + * the contract that are easy to get wrong and the failure that results if they are not met. + */ + String guidance(); + + /** + * An optional pointer to the recommended safer approach that satisfies the same need + * without the risk (for example, a factory method that implements the contract + * correctly). Empty when there is no direct alternative. + */ + String saferAlternative() default ""; + + /** + * An optional link to documentation explaining the risk and correct usage in more + * depth. Empty when there is no dedicated page. + */ + String link() default ""; + + enum Usage { + IMPLEMENTED, + OVERRIDDEN, + CONFIGURED, + CALLED + } +} diff --git a/core/arns/pom.xml b/core/arns/pom.xml index 423a27a23a20..1665146045c3 100644 --- a/core/arns/pom.xml +++ b/core/arns/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/auth-crt/pom.xml b/core/auth-crt/pom.xml index b84af92389c8..e9a7e8bc0644 100644 --- a/core/auth-crt/pom.xml +++ b/core/auth-crt/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT auth-crt diff --git a/core/auth/pom.xml b/core/auth/pom.xml index 5ebbb11a28f8..c5268a8773d4 100644 --- a/core/auth/pom.xml +++ b/core/auth/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT auth diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsProvider.java b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsProvider.java index 5fefed5e8d65..57d14ba41164 100644 --- a/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsProvider.java +++ b/core/auth/src/main/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsProvider.java @@ -307,11 +307,7 @@ private boolean matchesAllowedHostRules(InetAddress inetAddress) { } public boolean isMetadataServiceEndpoint(String host) { - String mode = SdkSystemSetting.AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE.getStringValueOrThrow(); - if ("IPV6".equalsIgnoreCase(mode)) { - return VALID_LOOP_BACK_IPV6.contains(host); - } - return VALID_LOOP_BACK_IPV4.contains(host); + return VALID_LOOP_BACK_IPV4.contains(host) || VALID_LOOP_BACK_IPV6.contains(host); } } diff --git a/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsEndpointProviderTest.java b/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsEndpointProviderTest.java index 01b3d73416f9..d59c85f6b689 100644 --- a/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsEndpointProviderTest.java +++ b/core/auth/src/test/java/software/amazon/awssdk/auth/credentials/ContainerCredentialsEndpointProviderTest.java @@ -164,6 +164,20 @@ private static Stream requestConstruction() { .headers(new HashMap<>()) .build())), + // EKS Pod Identity sets the IPv6 container URI but does NOT set + // AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE (that controls IMDS, not the + // container credentials endpoint). The IPv6 host must be allowed with the + // mode left at its IPv4 default. + Arguments.of("http link-local EKS URI with IPv6, default endpoint mode", + Collections.singletonList(Pair.of(FULL_URI_ENV, EKS_CONTAINER_HOST_IPV6 + "/credentials")), + EKS_CONTAINER_HOST_IPV6 + "/credentials", + new Result().type("success").sdkRequest( + SdkHttpFullRequest.builder() + .uri(URI.create(EKS_CONTAINER_HOST_IPV6 + "/credentials")) + .method(SdkHttpMethod.GET) + .headers(new HashMap<>()) + .build())), + Arguments.of("complex full URI", Collections.singletonList(Pair.of(FULL_URI_ENV, COMPLEX_URI)), COMPLEX_URI, diff --git a/core/aws-core/pom.xml b/core/aws-core/pom.xml index 2437dff00a1e..470d962cd523 100644 --- a/core/aws-core/pom.xml +++ b/core/aws-core/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT aws-core diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java index cf74d712bc26..325585dc6d7b 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilder.java @@ -21,6 +21,7 @@ import static software.amazon.awssdk.core.client.config.SdkClientOption.RETRY_STRATEGY; import java.net.URI; +import java.time.Duration; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -34,7 +35,6 @@ import software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption; import software.amazon.awssdk.awscore.client.config.AwsClientOption; import software.amazon.awssdk.awscore.defaultsmode.DefaultsMode; -import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.endpoint.DualstackEnabledProvider; import software.amazon.awssdk.awscore.endpoint.FipsEnabledProvider; import software.amazon.awssdk.awscore.eventstream.EventStreamInitialRequestInterceptor; @@ -51,6 +51,7 @@ import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.http.EnableDefaultSocketTimeout2026Resolver; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.internal.SdkInternalTestAdvancedClientOption; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; @@ -58,13 +59,13 @@ import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.profiles.ProfileFile; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.regions.ServiceMetadata; import software.amazon.awssdk.regions.ServiceMetadataAdvancedOption; import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain; import software.amazon.awssdk.retries.api.RetryStrategy; @@ -75,6 +76,7 @@ import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.StringUtils; +import software.amazon.awssdk.utils.Validate; /** * An SDK-internal implementation of the methods in {@link AwsClientBuilder}, {@link AwsAsyncClientBuilder} and @@ -97,10 +99,15 @@ public abstract class AwsDefaultClientBuilder implements AwsClientBuilder { private static final Logger log = Logger.loggerFor(AwsClientBuilder.class); - private static final String DEFAULT_ENDPOINT_PROTOCOL = "https"; private static final String[] FIPS_SEARCH = {"fips-", "-fips"}; private static final String[] FIPS_REPLACE = {"", ""}; + /** + * The flat default read/write inactivity timeout applied when the rollout gate is on and the service is not listed in the + * codegen exemption artifact. + */ + private static final Duration DEFAULT_READ_WRITE_TIMEOUT = Duration.ofMinutes(5); + private final AutoDefaultsModeDiscovery autoDefaultsModeDiscovery; protected AwsDefaultClientBuilder() { @@ -188,11 +195,10 @@ private SdkClientConfiguration finalizeAwsConfiguration(SdkClientConfiguration c this::resolveCredentialsIdentityProvider) // Set CREDENTIALS_PROVIDER, because older clients may be relying on it .lazyOptionIfAbsent(AwsClientOption.CREDENTIALS_PROVIDER, this::resolveCredentialsProvider) - .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, this::resolveClientEndpointProvider) // Set ENDPOINT and ENDPOINT_OVERRIDDEN, because older clients may be relying on it .lazyOptionIfAbsent(SdkClientOption.ENDPOINT, this::resolveEndpoint) .lazyOptionIfAbsent(SdkClientOption.ENDPOINT_OVERRIDDEN, this::resolveEndpointOverridden) - .lazyOption(AwsClientOption.SIGNING_REGION, this::resolveSigningRegion) + .lazyOptionIfAbsent(AwsClientOption.SIGNING_REGION, this::resolveSigningRegion) .lazyOption(SdkClientOption.HTTP_CLIENT_CONFIG, this::resolveHttpClientConfig) .applyMutation(this::configureRetryPolicy) .applyMutation(this::configureRetryStrategy) @@ -252,10 +258,47 @@ private void checkEndpointOverriddenOverride(SdkClientConfiguration configuratio * */ private AttributeMap resolveHttpClientConfig(LazyValueSource config) { - AttributeMap attributeMap = serviceHttpConfig(); + AttributeMap attributeMap = applyDefaultReadWriteTimeout(config, serviceHttpConfig()); return mergeSmartHttpDefaults(config, attributeMap); } + /** + * Applies the {@code AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} rollout gate to the codegen-baked + * {@link SdkHttpConfigurationOption#SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT} contributed by {@link #serviceHttpConfig()}. + * The gate resolves from the {@code AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} environment variable/system property, else the + * codegen-baked {@link SdkClientOption#DEFAULT_ENABLE_SOCKET_TIMEOUT_2026} default, else off. + * + *

When the gate is on, an unlisted service (nothing baked) gets the flat 5-minute default and a baked tier is kept as-is + * ({@link Duration#ZERO} for fully-exempt, 15 minutes for partial). When the gate is off, a baked positive tier (partial) + * is forced to {@link Duration#ZERO} so it cannot apply; otherwise the option is left untouched. Leaving it absent for an + * unlisted, gated-off service is equivalent to {@link Duration#ZERO}: the gate being off means the environment variable is + * not truthy, so the HTTP client's option-absent path applies nothing either way. + */ + private AttributeMap applyDefaultReadWriteTimeout(LazyValueSource config, AttributeMap serviceHttpConfig) { + boolean gateEnabled = new EnableDefaultSocketTimeout2026Resolver() + .defaultEnableSocketTimeout2026(config.get(SdkClientOption.DEFAULT_ENABLE_SOCKET_TIMEOUT_2026)) + .resolve(); + + Duration bakedTier = serviceHttpConfig.get(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT); + + if (gateEnabled) { + if (bakedTier != null) { + return serviceHttpConfig; + } + return serviceHttpConfig.toBuilder() + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, + DEFAULT_READ_WRITE_TIMEOUT) + .build(); + } + + if (bakedTier != null && !bakedTier.isZero()) { + return serviceHttpConfig.toBuilder() + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, Duration.ZERO) + .build(); + } + return serviceHttpConfig; + } + /** * Optionally overridden by child classes to define service-specific HTTP configuration defaults. */ @@ -313,32 +356,12 @@ private AttributeMap mergeSmartHttpDefaults(LazyValueSource config, AttributeMap } /** - * Resolve the signing region from the default-applied configuration. + * Fallback signing region resolution. Returns the client region as-is. + * Generated service builders resolve the signing region from endpoint rules in finalizeServiceConfiguration, + * which takes precedence over this fallback via lazyOptionIfAbsent ordering. */ private Region resolveSigningRegion(LazyValueSource config) { - return ServiceMetadata.of(serviceEndpointPrefix()) - .signingRegion(config.get(AwsClientOption.AWS_REGION)); - } - - /** - * Specify the client endpoint provider to use for the client, if the client didn't specify one itself. - *

- * This is only used for older client versions. Newer clients specify this value themselves. - */ - private ClientEndpointProvider resolveClientEndpointProvider(LazyValueSource config) { - ServiceMetadataAdvancedOption useGlobalS3EndpointProperty = - ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT; - return AwsClientEndpointProvider.builder() - .serviceEndpointPrefix(serviceEndpointPrefix()) - .defaultProtocol(DEFAULT_ENDPOINT_PROTOCOL) - .region(config.get(AwsClientOption.AWS_REGION)) - .profileFile(config.get(SdkClientOption.PROFILE_FILE_SUPPLIER)) - .profileName(config.get(SdkClientOption.PROFILE_NAME)) - .putAdvancedOption(useGlobalS3EndpointProperty, - config.get(useGlobalS3EndpointProperty)) - .dualstackEnabled(config.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) - .fipsEnabled(config.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)) - .build(); + return config.get(AwsClientOption.AWS_REGION); } /** @@ -346,7 +369,7 @@ private ClientEndpointProvider resolveClientEndpointProvider(LazyValueSource con * information from the client endpoint provider. */ private URI resolveEndpoint(LazyValueSource config) { - return config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER).clientEndpoint(); + return requireClientEndpointProvider(config).clientEndpoint(); } /** @@ -354,7 +377,16 @@ private URI resolveEndpoint(LazyValueSource config) { * client versions resolve this information from the client endpoint provider. */ private boolean resolveEndpointOverridden(LazyValueSource config) { - return config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER).isEndpointOverridden(); + return requireClientEndpointProvider(config).isEndpointOverridden(); + } + + private ClientEndpointProvider requireClientEndpointProvider(LazyValueSource config) { + ClientEndpointProvider clientEndpointProvider = config.get(SdkClientOption.CLIENT_ENDPOINT_PROVIDER); + Validate.notNull(clientEndpointProvider, + "No CLIENT_ENDPOINT_PROVIDER was configured. This is typically caused by using " + + "an older service client version with a newer sdk-core. " + + "Please align all SDK dependency versions."); + return clientEndpointProvider; } /** diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java index 0bb5119b369e..3b0c77ecec0f 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProvider.java @@ -95,7 +95,8 @@ public boolean isEndpointOverridden() { return clientEndpoint.getValue().isEndpointOverridden; } - private ClientEndpoint resolveClientEndpoint(Builder builder) { + // TODO: Remove once all callers are migrated to use resolveFromOverrides + private static ClientEndpoint resolveClientEndpoint(Builder builder) { return OptionalUtils.firstPresent(clientEndpointFromClientOverride(builder), () -> clientEndpointFromEnvironment(builder), () -> clientEndpointFromServiceMetadata(builder)) @@ -107,14 +108,20 @@ private static SdkClientException failToLoadEndpointException() { AwsClientEndpointProvider.class.getName() + " for more information."); } - private Optional clientEndpointFromClientOverride(Builder builder) { + private static Optional clientEndpointFromClientOverride(Builder builder) { Optional result = Optional.ofNullable(builder.clientEndpointOverride) .map(uri -> new ClientEndpoint(uri, true)); result.ifPresent(e -> log.trace(() -> "Client was configured with endpoint override: " + e.clientEndpoint)); return result; } - private Optional clientEndpointFromEnvironment(Builder builder) { + private static Optional clientEndpointFromEnvironment(Builder builder) { + initializeProfileFileDefaults(builder); + if (shouldIgnoreConfiguredEndpointUrls(builder)) { + log.debug(() -> "Configured endpoint URLs are being ignored because ignore_configured_endpoint_urls is true."); + return Optional.empty(); + } + if (builder.serviceEndpointOverrideEnvironmentVariable == null || builder.serviceEndpointOverrideSystemProperty == null || builder.serviceProfileProperty == null) { @@ -147,19 +154,19 @@ private Optional clientEndpointFromEnvironment(Builder builder) .map(uri -> new ClientEndpoint(uri, true)); } - private Optional systemProperty(String systemProperty) { + private static Optional systemProperty(String systemProperty) { // CHECKSTYLE:OFF - We have to read system properties directly here to match the load order of the other SDKs return createUri("system property " + systemProperty, Optional.ofNullable(System.getProperty(systemProperty))); // CHECKSTYLE:ON } - private Optional environmentVariable(String environmentVariable) { + private static Optional environmentVariable(String environmentVariable) { return createUri("environment variable " + environmentVariable, SystemSettingUtils.resolveEnvironmentVariable(environmentVariable)); } - private Optional profileProperty(Builder builder, String profileProperty) { + private static Optional profileProperty(Builder builder, String profileProperty) { initializeProfileFileDefaults(builder); return createUri("profile property " + profileProperty, Optional.ofNullable(builder.profileFile.get()) @@ -167,7 +174,7 @@ private Optional profileProperty(Builder builder, String profileProperty) { .flatMap(p -> p.property(profileProperty))); } - private Optional servicesProperty(Builder builder) { + private static Optional servicesProperty(Builder builder) { Optional profileFile = Optional.ofNullable(builder.profileFile.get()); Optional servicesSectionName = profileFile .flatMap(pf -> pf.profile(builder.profileName)) @@ -181,7 +188,16 @@ private Optional servicesProperty(Builder builder) { return createUri("services section property", serviceEndpoint); } - private Optional clientEndpointFromServiceMetadata(Builder builder) { + private static boolean shouldIgnoreConfiguredEndpointUrls(Builder builder) { + return IgnoreConfiguredEndpointUrlsProvider.builder() + .profileFile(builder.profileFile) + .profileName(builder.profileName) + .build() + .ignoreConfiguredEndpointUrls() + .orElse(false); + } + + private static Optional clientEndpointFromServiceMetadata(Builder builder) { // This value is generally overridden after endpoints 2.0. It seems to exist for backwards-compatibility // with older client versions or interceptors. @@ -258,7 +274,7 @@ private Optional clientEndpointFromServiceMetadata(Builder build return Optional.of(new ClientEndpoint(endpoint, false)); } - private Optional createUri(String source, Optional uri) { + private static Optional createUri(String source, Optional uri) { return uri.map(u -> { try { URI parsedUri = SdkUri.getInstance().newUri(uri.get()); @@ -270,7 +286,7 @@ private Optional createUri(String source, Optional uri) { }); } - private void initializeProfileFileDefaults(Builder builder) { + private static void initializeProfileFileDefaults(Builder builder) { if (builder.profileFile == null) { builder.profileFile = new Lazy<>(ProfileFile::defaultProfileFile)::getValue; } @@ -479,8 +495,28 @@ public Builder putAdvancedOption(ServiceMetadataAdvancedOption option, T return this; } + /** + * @deprecated This method triggers expensive ServiceMetadata + * initialization and is no longer used by the SDK. Service endpoint resolution is handled + * by Endpoints 2.0 at request time. + */ + @Deprecated public AwsClientEndpointProvider build() { return new AwsClientEndpointProvider(this); } + + /** + * Resolve an endpoint from overrides and environment configuration. + * Checks client override, system properties, environment variables, and profile configuration. + * Returns {@link Optional#empty()} if no override is configured, allowing callers to provide + * their own fallback. + */ + public Optional resolveFromOverrides() { + Builder copy = new Builder(this); + initializeProfileFileDefaults(copy); + return OptionalUtils.firstPresent(clientEndpointFromClientOverride(copy), + () -> clientEndpointFromEnvironment(copy)) + .map(endpoint -> endpoint.clientEndpoint); + } } } diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProvider.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProvider.java new file mode 100644 index 000000000000..c980094e5772 --- /dev/null +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProvider.java @@ -0,0 +1,89 @@ +/* + * 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.awscore.endpoint; + +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.ProfileFileSystemSetting; +import software.amazon.awssdk.profiles.ProfileProperty; +import software.amazon.awssdk.utils.Validate; + +/** + * Resolves whether configured endpoint URLs should be ignored. This checks the system property, environment variable, + * and profile file for the {@code ignore_configured_endpoint_urls} setting. + * + *

When this returns {@code true}, the SDK will not read endpoint URLs from environment variables, system properties, + * or the shared configuration file. Programmatic endpoint overrides on the client builder are not affected. + */ +@SdkProtectedApi +public class IgnoreConfiguredEndpointUrlsProvider { + private final Supplier profileFile; + private final String profileName; + + private IgnoreConfiguredEndpointUrlsProvider(Builder builder) { + this.profileFile = Validate.paramNotNull(builder.profileFile, "profileFile"); + this.profileName = builder.profileName; + } + + public static Builder builder() { + return new Builder(); + } + + /** + * Returns {@code true} when configured endpoint URLs should be ignored, {@code false} otherwise. + * Resolution order: system property, then environment variable, then profile file. If none are set, returns + * empty. + */ + public Optional ignoreConfiguredEndpointUrls() { + Optional setting = SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.getBooleanValue(); + if (setting.isPresent()) { + return setting; + } + + return profileFile.get() + .profile(profileName()) + .flatMap(p -> p.booleanProperty(ProfileProperty.IGNORE_CONFIGURED_ENDPOINT_URLS)); + } + + private String profileName() { + return profileName != null ? profileName : ProfileFileSystemSetting.AWS_PROFILE.getStringValueOrThrow(); + } + + public static final class Builder { + private Supplier profileFile = ProfileFile::defaultProfileFile; + private String profileName; + + private Builder() { + } + + public Builder profileFile(Supplier profileFile) { + this.profileFile = profileFile; + return this; + } + + public Builder profileName(String profileName) { + this.profileName = profileName; + return this; + } + + public IgnoreConfiguredEndpointUrlsProvider build() { + return new IgnoreConfiguredEndpointUrlsProvider(this); + } + } +} diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointMode.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointMode.java index 7e6f0050dc4e..89a0684c4b1d 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointMode.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointMode.java @@ -26,19 +26,25 @@ public enum AccountIdEndpointMode { /** * Default value that indicates account ID values will be used in endpoint rules if available. */ - PREFERRED, + PREFERRED("preferred"), /** * When mode is disabled, any resolved account ID will not be used in endpoint construction and rules that * reference them will be bypassed. */ - DISABLED, + DISABLED("disabled"), /** * Required mode would be used in scenarios where endpoint resolution should return an error if no account ID is * available. */ - REQUIRED; + REQUIRED("required"); + + private final String value; + + AccountIdEndpointMode(String value) { + this.value = value; + } /** * Returns the appropriate AccountIdEndpointMode value after parsing the parameter. @@ -51,12 +57,26 @@ public static AccountIdEndpointMode fromValue(String s) { return null; } - for (AccountIdEndpointMode value : values()) { - if (value.name().equalsIgnoreCase(s)) { - return value; + for (AccountIdEndpointMode mode : values()) { + // Matched against value rather than name() so that the wire form has a single definition. Behaviour is + // unchanged: the two differ only in case, and the comparison is case-insensitive. + if (mode.value.equalsIgnoreCase(s)) { + return mode; } } throw new IllegalArgumentException("Unrecognized value for account id endpoint mode: " + s); } + + /** + * Returns the canonical lowercase string for this mode, as the endpoint rules engine expects to receive it in the + * {@code AWS::Auth::AccountIdEndpointMode} built-in. + *

+ * Unlike {@code name().toLowerCase()}, this returns the same interned {@link String} reference on every call instead + * of a fresh string per request, which removes an allocation from the request path. It is also independent of the + * default locale, which {@code name().toLowerCase()} is not. + */ + public String value() { + return value; + } } diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtils.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtils.java index 53555c1adb53..56ac41f02c69 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtils.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtils.java @@ -15,8 +15,6 @@ package software.amazon.awssdk.awscore.endpoints; -import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; - import java.net.URI; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.awscore.AwsExecutionAttribute; @@ -24,6 +22,7 @@ import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.utils.HostnameValidator; @@ -53,19 +52,19 @@ public static Boolean fipsEnabledBuiltIn(ExecutionAttributes executionAttributes } /** - * Returns the endpoint set on the client. Note that this strips off the query part of the URI because the endpoint - * rules library, e.g. {@code ParseURL} will return an exception if the URI it parses has query parameters. + * Returns the endpoint set on the client, sanitized for the rules engine. The rules engine (e.g. + * {@code ParseURL}) rejects URIs with query parameters, so we strip the query and user-info components. + *

+ * Delegates to {@link ClientEndpointProvider#sanitizedEndpointString()}, which returns a cached reference on + * {@link software.amazon.awssdk.core.internal.StaticClientEndpointProvider} reducing allocations and expensive + * URI.create calls. */ public static String endpointBuiltIn(ExecutionAttributes executionAttributes) { if (endpointIsOverridden(executionAttributes)) { executionAttributes.getOptionalAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).ifPresent( metric -> metric.addMetric(BusinessMetricFeatureId.ENDPOINT_OVERRIDE.value())); - return invokeSafely(() -> { - URI endpointOverride = executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER) - .clientEndpoint(); - return new URI(endpointOverride.getScheme(), null, endpointOverride.getHost(), endpointOverride.getPort(), - endpointOverride.getPath(), null, endpointOverride.getFragment()).toString(); - }); + return executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER) + .sanitizedEndpointString(); } return null; } @@ -80,11 +79,24 @@ public static boolean endpointIsOverridden(ExecutionAttributes attrs) { /** * True if the {@link SdkInternalExecutionAttribute#IS_DISCOVERED_ENDPOINT} attribute is present and its value * is {@code true}, {@code false} otherwise. + * + * @deprecated Use {@link #skipEndpointResolution(ExecutionAttributes)} instead. */ + @Deprecated public static boolean endpointIsDiscovered(ExecutionAttributes attrs) { return attrs.getOptionalAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT).orElse(false); } + /** + * True if endpoint resolution should be skipped for the current request. This returns {@code true} if either + * {@link SdkInternalExecutionAttribute#SKIP_ENDPOINT_RESOLUTION} or + * {@link SdkInternalExecutionAttribute#IS_DISCOVERED_ENDPOINT} is set to {@code true}. + */ + public static boolean skipEndpointResolution(ExecutionAttributes attrs) { + return attrs.getOptionalAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION).orElse(false) + || attrs.getOptionalAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT).orElse(false); + } + /** * True if the {@link SdkInternalExecutionAttribute#DISABLE_HOST_PREFIX_INJECTION} attribute is present and its * value is {@code true}, {@code false} otherwise. @@ -101,11 +113,12 @@ public static Endpoint addHostPrefix(Endpoint endpoint, String prefix) { return endpoint; } validatePrefixIsHostNameCompliant(prefix); - URI originalUrl = endpoint.url(); - String newHost = prefix + endpoint.url().getHost(); - URI newUrl = invokeSafely(() -> new URI(originalUrl.getScheme(), null, newHost, originalUrl.getPort(), - originalUrl.getPath(), originalUrl.getQuery(), originalUrl.getFragment())); - return endpoint.toBuilder().url(newUrl).build(); + + EndpointUrl originalUrl = endpoint.endpointUrl(); + String newHost = prefix + originalUrl.host(); + EndpointUrl newUrl = EndpointUrl.fromComponents(originalUrl.scheme(), newHost, originalUrl.port(), + originalUrl.encodedPath(), originalUrl.queryAndFragment()); + return endpoint.toBuilder().endpointUrl(newUrl).build(); } /** @@ -126,7 +139,11 @@ public static Endpoint addHostPrefix(Endpoint endpoint, String prefix) { * However, we also pass the endpoint to provider as a parameter, and the resolver returns * {@code https://example.com/a/b}. This method takes care of combining the paths correctly so that the resulting * path is {@code https://example.com/a/b/c}. + * + * @deprecated Use {@link #setUri(SdkHttpRequest, URI, EndpointUrl)} instead for better performance by avoiding + * intermediate URI construction. */ + @Deprecated public static SdkHttpRequest setUri(SdkHttpRequest request, URI clientEndpoint, URI resolvedUri) { String clientEndpointPath = clientEndpoint.getRawPath(); String requestPath = request.encodedPath(); @@ -141,6 +158,33 @@ public static SdkHttpRequest setUri(SdkHttpRequest request, URI clientEndpoint, .encodedPath(finalPath).build(); } + /** + * Sets the request URI to the resolved endpoint URL returned by the endpoint provider, reading URL components + * directly from the {@link EndpointUrl} without constructing an intermediate {@link URI}. + *

+ * This overload has the same behavior as {@link #setUri(SdkHttpRequest, URI, URI)} but avoids the cost of + * {@link URI} construction, making it suitable for presigners and other code paths that resolve endpoints outside + * the main pipeline. + * + * @param request the current HTTP request + * @param clientEndpoint the endpoint configured on the client (may include a path prefix from endpoint override) + * @param resolvedUrl the resolved endpoint URL from the rules engine + * @return a new {@link SdkHttpRequest} with scheme, host, port, and path applied from the resolved URL + */ + public static SdkHttpRequest setUri(SdkHttpRequest request, URI clientEndpoint, EndpointUrl resolvedUrl) { + String clientEndpointPath = clientEndpoint.getRawPath(); + String requestPath = request.encodedPath(); + String resolvedUrlPath = resolvedUrl.encodedPath(); + + String finalPath = requestPath; + if (!resolvedUrlPath.equals(clientEndpointPath)) { + finalPath = combinePath(clientEndpointPath, requestPath, resolvedUrlPath); + } + + return request.toBuilder().protocol(resolvedUrl.scheme()).host(resolvedUrl.host()).port(resolvedUrl.port()) + .encodedPath(finalPath).build(); + } + /** * Constructs [resolved URI path]/[request path without client endpoint path]. Strips the client endpoint path from * the marshalled request path to isolate just the part added by the marshaller, then appends it to the resolved path. diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptor.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptor.java index 8a4eab2e5673..dbb4086c06ae 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptor.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptor.java @@ -16,20 +16,11 @@ package software.amazon.awssdk.awscore.interceptor; import java.net.UnknownHostException; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkProtectedApi; -import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.core.exception.SdkClientException; 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.regions.PartitionMetadata; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.regions.RegionMetadata; -import software.amazon.awssdk.regions.ServiceMetadata; -import software.amazon.awssdk.regions.ServicePartitionMetadata; /** * This interceptor will monitor for {@link UnknownHostException}s and provide the customer with additional information they can @@ -37,90 +28,20 @@ */ @SdkProtectedApi public final class HelpfulUnknownHostExceptionInterceptor implements ExecutionInterceptor { + private static final String ERROR_MESSAGE = + "Received an UnknownHostException when attempting to interact with a service. " + + "See cause for the exact endpoint that is failing to resolve. " + + "If this is happening on an endpoint that previously worked, " + + "there may be a network connectivity issue or your DNS cache " + + "could be storing endpoints for too long."; + @Override public Throwable modifyException(Context.FailedExecution context, ExecutionAttributes executionAttributes) { if (!hasCause(context.exception(), UnknownHostException.class)) { return context.exception(); } - StringBuilder error = new StringBuilder(); - error.append("Received an UnknownHostException when attempting to interact with a service. See cause for the " - + "exact endpoint that is failing to resolve. "); - - Optional globalRegionErrorDetails = getGlobalRegionErrorDetails(executionAttributes); - - if (globalRegionErrorDetails.isPresent()) { - error.append(globalRegionErrorDetails.get()); - } else { - error.append("If this is happening on an endpoint that previously worked, there may be a network connectivity " - + "issue or your DNS cache could be storing endpoints for too long."); - } - - return SdkClientException.builder().message(error.toString()).cause(context.exception()).build(); - } - - /** - * If the customer is interacting with a global service (one with a single endpoint/region for an entire partition), this - * will return error details that can instruct the customer on how to configure their client for success. - */ - private Optional getGlobalRegionErrorDetails(ExecutionAttributes executionAttributes) { - Region clientRegion = clientRegion(executionAttributes); - if (clientRegion.isGlobalRegion()) { - return Optional.empty(); - } - - List globalPartitionsForService = globalPartitionsForService(executionAttributes); - if (globalPartitionsForService.isEmpty()) { - return Optional.empty(); - } - - String clientPartition = Optional.ofNullable(clientRegion.metadata()) - .map(RegionMetadata::partition) - .map(PartitionMetadata::id) - .orElse(null); - - Optional globalRegionForClientRegion = - globalPartitionsForService.stream() - .filter(p -> p.partition().id().equals(clientPartition)) - .findAny() - .flatMap(ServicePartitionMetadata::globalRegion); - - if (!globalRegionForClientRegion.isPresent()) { - String globalRegionsForThisService = globalPartitionsForService.stream() - .map(ServicePartitionMetadata::globalRegion) - .filter(Optional::isPresent) - .map(Optional::get) - .filter(Region::isGlobalRegion) - .map(Region::id) - .collect(Collectors.joining("/")); - - return Optional.of("This specific service may be a global service, in which case you should configure a global " - + "region like " + globalRegionsForThisService + " on the client."); - } - - Region globalRegion = globalRegionForClientRegion.get(); - - return Optional.of("This specific service is global in the same partition as the region configured on this client (" - + clientRegion + "). If this is the first time you're trying to talk to this service in this region, " - + "you should try configuring the global region on your client, instead: " + globalRegion); - } - - /** - * Retrieve the region configured on the client. - */ - private Region clientRegion(ExecutionAttributes executionAttributes) { - return executionAttributes.getAttribute(AwsExecutionAttribute.AWS_REGION); - } - - /** - * Retrieve all global partitions for the AWS service that we're interacting with. - */ - private List globalPartitionsForService(ExecutionAttributes executionAttributes) { - return ServiceMetadata.of(executionAttributes.getAttribute(AwsExecutionAttribute.ENDPOINT_PREFIX)) - .servicePartitions() - .stream() - .filter(sp -> sp.globalRegion().isPresent()) - .collect(Collectors.toList()); + return SdkClientException.builder().message(ERROR_MESSAGE).cause(context.exception()).build(); } private boolean hasCause(Throwable thrown, Class cause) { diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilderReadWriteTimeoutTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilderReadWriteTimeoutTest.java new file mode 100644 index 000000000000..7184bc194fa9 --- /dev/null +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/AwsDefaultClientBuilderReadWriteTimeoutTest.java @@ -0,0 +1,205 @@ +/* + * 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.awscore.client.builder; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption.ENABLE_DEFAULT_REGION_DETECTION; + +import java.net.URI; +import java.time.Duration; +import java.util.concurrent.atomic.AtomicReference; +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.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.internal.defaultsmode.AutoDefaultsModeDiscovery; +import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.utils.AttributeMap; + +/** + * Verifies the {@code AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} rollout gate applied in + * {@link AwsDefaultClientBuilder#resolveHttpClientConfig} to the codegen-baked + * {@link SdkHttpConfigurationOption#SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT}. + */ +@ExtendWith(MockitoExtension.class) +class AwsDefaultClientBuilderReadWriteTimeoutTest { + + private static final String GATE_PROPERTY = SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property(); + private static final Duration PARTIAL_TIER = Duration.ofMinutes(15); + private static final Duration FLAT_DEFAULT = Duration.ofMinutes(5); + + @Mock(lenient = true) + private SdkHttpClient.Builder defaultHttpClientBuilder; + + @Mock(lenient = true) + private SdkAsyncHttpClient.Builder defaultAsyncHttpClientFactory; + + @Mock(lenient = true) + private AutoDefaultsModeDiscovery autoModeDiscovery; + + private String savedProperty; + + @BeforeEach + void setup() { + savedProperty = System.getProperty(GATE_PROPERTY); + System.clearProperty(GATE_PROPERTY); + } + + @AfterEach + void teardown() { + if (savedProperty != null) { + System.setProperty(GATE_PROPERTY, savedProperty); + } else { + System.clearProperty(GATE_PROPERTY); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("gateScenarios") + void resolvesReadWriteTimeout(String scenario, String gateProperty, boolean codegenGateDefault, + Duration bakedTier, Duration expected) { + if (gateProperty != null) { + System.setProperty(GATE_PROPERTY, gateProperty); + } + AttributeMap serviceHttpConfig = bakedTier == null ? AttributeMap.empty() : bakedServiceHttpConfig(bakedTier); + + AttributeMap resolved = resolvedServiceDefaults(serviceHttpConfig, codegenGateDefault); + + assertThat(resolved.get(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT)).isEqualTo(expected); + } + + @Test + void unlistedService_gateOff_leavesOptionAbsent() { + AttributeMap resolved = resolvedServiceDefaults(AttributeMap.empty(), false); + + assertThat(resolved.containsKey(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT)).isFalse(); + } + + private static Stream gateScenarios() { + return Stream.of( + Arguments.of("gate off, partial tier baked -> overridden to ZERO", null, false, PARTIAL_TIER, Duration.ZERO), + Arguments.of("gate on, unlisted service -> flat 5-minute default", "true", false, null, FLAT_DEFAULT), + Arguments.of("gate on, fully-exempt tier baked -> ZERO", "true", false, Duration.ZERO, Duration.ZERO), + Arguments.of("gate on, partial tier baked -> 15 minutes", "true", false, PARTIAL_TIER, PARTIAL_TIER), + Arguments.of("gate on via codegen default, unlisted -> flat 5-minute default", null, true, null, FLAT_DEFAULT), + Arguments.of("gate property false overrides codegen default -> ZERO", "false", true, PARTIAL_TIER, Duration.ZERO) + ); + } + + private static AttributeMap bakedServiceHttpConfig(Duration tier) { + return AttributeMap.builder() + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, tier) + .build(); + } + + private AttributeMap resolvedServiceDefaults(AttributeMap bakedServiceHttpConfig, boolean codegenGateDefault) { + AtomicReference captured = new AtomicReference<>(); + ClientOverrideConfiguration overrideConfig = + ClientOverrideConfiguration.builder() + .putAdvancedOption(ENABLE_DEFAULT_REGION_DETECTION, false) + .build(); + + new TestClientBuilder(bakedServiceHttpConfig, codegenGateDefault) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(overrideConfig) + .region(Region.US_WEST_1) + .httpClientBuilder((SdkHttpClient.Builder) serviceDefaults -> { + captured.set(serviceDefaults); + return mock(SdkHttpClient.class); + }) + .build(); + + return captured.get(); + } + + private static class TestClient { + } + + private class TestClientBuilder extends AwsDefaultClientBuilder + implements AwsClientBuilder { + + private final AttributeMap bakedServiceHttpConfig; + private final boolean codegenGateDefault; + + TestClientBuilder(AttributeMap bakedServiceHttpConfig, boolean codegenGateDefault) { + super(defaultHttpClientBuilder, defaultAsyncHttpClientFactory, autoModeDiscovery); + this.bakedServiceHttpConfig = bakedServiceHttpConfig; + this.codegenGateDefault = codegenGateDefault; + } + + @Override + protected TestClient buildClient() { + syncClientConfiguration(); + return new TestClient(); + } + + @Override + protected SdkClientConfiguration mergeInternalDefaults(SdkClientConfiguration config) { + if (!codegenGateDefault) { + return config; + } + return config.merge(c -> c.option(SdkClientOption.DEFAULT_ENABLE_SOCKET_TIMEOUT_2026, true)); + } + + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + + @Override + protected AttributeMap serviceHttpConfig() { + return bakedServiceHttpConfig; + } + + @Override + protected String serviceEndpointPrefix() { + return "test"; + } + + @Override + protected String signingName() { + return "test"; + } + + @Override + protected String serviceName() { + return "test"; + } + } +} diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java index 74d263c68f43..c76b5bb36823 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultAwsClientBuilderTest.java @@ -52,6 +52,7 @@ import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpClient; @@ -161,6 +162,43 @@ public void buildWithEndpointShouldHaveCorrectEndpointAndSigningRegion() { assertThat(client.clientConfiguration.option(SERVICE_SIGNING_NAME)).isEqualTo(SIGNING_NAME); } + @Test + public void resolveSigningRegion_withGlobalRegion_resolvesCorrectlyFromEndpointRules() { + ClientOverrideConfiguration overrideConfig = + ClientOverrideConfiguration.builder() + .putAdvancedOption(SIGNER, TEST_SIGNER) + .putAdvancedOption(ENABLE_DEFAULT_REGION_DETECTION, false) + .build(); + + TestClient client = new TestClientBuilderWithEndpointRulesSigningRegion(Region.US_EAST_1) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(overrideConfig) + .region(Region.AWS_GLOBAL) + .build(); + + // The endpoint-rules-resolved signing region (us-east-1) is used, not the client region (aws-global) + assertThat(client.clientConfiguration.option(SIGNING_REGION)).isEqualTo(Region.US_EAST_1); + } + + @Test + public void signingRegionFromEndpointRules_fallsBackToClientRegionOnFailure() { + // Simulates a generated builder where endpoint resolution fails. + // Should fall back to client region. + ClientOverrideConfiguration overrideConfig = + ClientOverrideConfiguration.builder() + .putAdvancedOption(SIGNER, TEST_SIGNER) + .putAdvancedOption(ENABLE_DEFAULT_REGION_DETECTION, false) + .build(); + + TestClient client = new TestClientBuilderWithFailingEndpointResolution() + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(overrideConfig) + .region(Region.US_WEST_2) + .build(); + + assertThat(client.clientConfiguration.option(SIGNING_REGION)).isEqualTo(Region.US_WEST_2); + } + @Test public void noClientProvided_DefaultHttpClientIsManagedBySdk() { TestClient client = testClientBuilder().region(Region.US_WEST_2).build(); @@ -403,6 +441,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; @@ -444,6 +493,17 @@ protected TestAsyncClient buildClient() { return new TestAsyncClient(super.asyncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; @@ -467,4 +527,104 @@ protected AttributeMap serviceHttpConfig() { private static class TestException extends Throwable { } + + /** + * Test builder that sets SIGNING_REGION from endpoint rules in finalizeServiceConfiguration. + */ + private class TestClientBuilderWithEndpointRulesSigningRegion + extends AwsDefaultClientBuilder + implements AwsClientBuilder { + + private final Region resolvedSigningRegion; + + public TestClientBuilderWithEndpointRulesSigningRegion(Region resolvedSigningRegion) { + super(defaultHttpClientBuilder, null, autoModeDiscovery); + this.resolvedSigningRegion = resolvedSigningRegion; + } + + @Override + protected TestClient buildClient() { + return new TestClient(super.syncClientConfiguration()); + } + + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .lazyOptionIfAbsent(AwsClientOption.SIGNING_REGION, c -> resolvedSigningRegion) + .build(); + } + + @Override + protected String serviceEndpointPrefix() { + return ENDPOINT_PREFIX; + } + + @Override + protected String signingName() { + return SIGNING_NAME; + } + + @Override + protected String serviceName() { + return SERVICE_NAME; + } + + @Override + protected AttributeMap serviceHttpConfig() { + return MOCK_DEFAULTS; + } + } + + /** + * Test builder where finalizeServiceConfiguration does not set SIGNING_REGION. + */ + private class TestClientBuilderWithFailingEndpointResolution + extends AwsDefaultClientBuilder + implements AwsClientBuilder { + + public TestClientBuilderWithFailingEndpointResolution() { + super(defaultHttpClientBuilder, null, autoModeDiscovery); + } + + @Override + protected TestClient buildClient() { + return new TestClient(super.syncClientConfiguration()); + } + + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + + @Override + protected String serviceEndpointPrefix() { + return ENDPOINT_PREFIX; + } + + @Override + protected String signingName() { + return SIGNING_NAME; + } + + @Override + protected String serviceName() { + return SERVICE_NAME; + } + + @Override + protected AttributeMap serviceHttpConfig() { + return MOCK_DEFAULTS; + } + } } diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java index 2b9ea42a5d73..37bfd4dcf901 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/DefaultsModeTest.java @@ -37,6 +37,10 @@ import software.amazon.awssdk.awscore.internal.defaultsmode.DefaultsModeConfiguration; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import java.net.URI; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; import software.amazon.awssdk.core.retry.RetryMode; import software.amazon.awssdk.http.SdkHttpClient; @@ -187,6 +191,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; @@ -220,6 +235,17 @@ protected TestAsyncClient buildClient() { return new TestAsyncClient(super.asyncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java index c20f3d924157..5cf5c5d859e7 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/FipsPseudoRegionTest.java @@ -22,6 +22,7 @@ import static software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption.ENABLE_DEFAULT_REGION_DETECTION; import static software.amazon.awssdk.core.client.config.SdkAdvancedClientOption.SIGNER; +import java.net.URI; import java.time.Duration; import java.util.ArrayList; import java.util.List; @@ -30,8 +31,10 @@ import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpConfigurationOption; @@ -122,6 +125,17 @@ protected TestClient buildClient() { return new TestClient(super.syncClientConfiguration()); } + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } + @Override protected String serviceEndpointPrefix() { return ENDPOINT_PREFIX; diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java index 5c411276e923..6de908763b03 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/client/builder/InternalDefaultsTest.java @@ -28,6 +28,9 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.core.SdkSystemSetting; +import java.net.URI; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.http.SdkHttpClient; @@ -159,5 +162,16 @@ protected TestClient buildClient() { return new TestClient(config); } + + @Override + protected SdkClientConfiguration finalizeServiceConfiguration(SdkClientConfiguration config) { + return config.toBuilder() + .lazyOptionIfAbsent(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, c -> { + URI endpoint = URI.create("https://" + serviceEndpointPrefix() + "." + + c.get(AwsClientOption.AWS_REGION) + ".amazonaws.com"); + return ClientEndpointProvider.create(endpoint, false); + }) + .build(); + } } } diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProviderResolveFromOverridesTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProviderResolveFromOverridesTest.java new file mode 100644 index 000000000000..8ca96cf9aefb --- /dev/null +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/AwsClientEndpointProviderResolveFromOverridesTest.java @@ -0,0 +1,79 @@ +/* + * 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.awscore.endpoint; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.util.Optional; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class AwsClientEndpointProviderResolveFromOverridesTest { + + private static final String TEST_SYSTEM_PROPERTY = "aws.endpointUrlTestService"; + + @AfterEach + void cleanup() { + System.clearProperty(TEST_SYSTEM_PROPERTY); + } + + @Test + void resolveFromOverrides_withClientEndpointOverride_returnsOverrideUri() { + URI override = URI.create("https://custom-endpoint.example.com"); + + Optional result = AwsClientEndpointProvider.builder() + .clientEndpointOverride(override) + .resolveFromOverrides(); + + assertThat(result).isPresent(); + assertThat(result.get()).isEqualTo(override); + } + + @Test + void resolveFromOverrides_withSystemPropertyEndpoint_returnsEndpointUri() { + System.setProperty(TEST_SYSTEM_PROPERTY, "https://sys-prop-endpoint.example.com"); + + Optional result = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideSystemProperty(TEST_SYSTEM_PROPERTY) + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_TEST_SERVICE") + .serviceProfileProperty("testservice") + .resolveFromOverrides(); + + assertThat(result).isPresent(); + assertThat(result.get()).isEqualTo(URI.create("https://sys-prop-endpoint.example.com")); + } + + @Test + void resolveFromOverrides_withNoOverrideOrEnvironment_returnsEmpty() { + Optional result = AwsClientEndpointProvider.builder() + .serviceEndpointOverrideSystemProperty("aws.endpointUrlNonExistent") + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_NON_EXISTENT") + .serviceProfileProperty("nonexistent") + .resolveFromOverrides(); + + assertThat(result).isEmpty(); + } + + @Test + void resolveFromOverrides_withNoParamsConfigured_returnsEmpty() { + Optional result = AwsClientEndpointProvider.builder() + .resolveFromOverrides(); + + assertThat(result).isEmpty(); + } + +} diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProviderTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProviderTest.java new file mode 100644 index 000000000000..0bc6fdd316a5 --- /dev/null +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoint/IgnoreConfiguredEndpointUrlsProviderTest.java @@ -0,0 +1,102 @@ +/* + * 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.awscore.endpoint; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Optional; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; +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.profiles.ProfileFile; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; +import software.amazon.awssdk.utils.StringInputStream; + +class IgnoreConfiguredEndpointUrlsProviderTest { + private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper(); + private static final String PROFILE = "test"; + + @BeforeEach + void setup() { + ENVIRONMENT_VARIABLE_HELPER.reset(); + System.clearProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property()); + } + + @AfterEach + void teardown() { + ENVIRONMENT_VARIABLE_HELPER.reset(); + System.clearProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property()); + } + + @ParameterizedTest(name = "{index} - {0}") + @MethodSource("testCases") + void resolvesCorrectly(String description, String systemProperty, String envVar, String profileValue, + Optional expected) { + if (systemProperty != null) { + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), systemProperty); + } + if (envVar != null) { + ENVIRONMENT_VARIABLE_HELPER.set(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS, envVar); + } + + ProfileFile profileFile = profileFile(profileValue); + + IgnoreConfiguredEndpointUrlsProvider provider = + IgnoreConfiguredEndpointUrlsProvider.builder() + .profileFile(() -> profileFile) + .profileName(PROFILE) + .build(); + + assertThat(provider.ignoreConfiguredEndpointUrls()).isEqualTo(expected); + } + + private static Stream testCases() { + return Stream.of( + Arguments.of("nothing set returns empty", null, null, null, Optional.empty()), + Arguments.of("system property true", "true", null, null, Optional.of(true)), + Arguments.of("system property false", "false", null, null, Optional.of(false)), + Arguments.of("system property case insensitive True", "True", null, null, Optional.of(true)), + Arguments.of("system property case insensitive TRUE", "TRUE", null, null, Optional.of(true)), + Arguments.of("env var true", null, "true", null, Optional.of(true)), + Arguments.of("env var false", null, "false", null, Optional.of(false)), + Arguments.of("profile true", null, null, "true", Optional.of(true)), + Arguments.of("profile false", null, null, "false", Optional.of(false)), + Arguments.of("system property wins over env var", "true", "false", null, Optional.of(true)), + Arguments.of("system property false wins over env var true", "false", "true", null, Optional.of(false)), + Arguments.of("system property wins over profile", "true", null, "false", Optional.of(true)), + Arguments.of("env var wins over profile", null, "true", "false", Optional.of(true)), + Arguments.of("env var false wins over profile true", null, "false", "true", Optional.of(false)), + Arguments.of("system property wins over both", "true", "false", "false", Optional.of(true)), + Arguments.of("system property false wins over both", "false", "true", "true", Optional.of(false)) + ); + } + + private static ProfileFile profileFile(String ignoreConfiguredEndpointUrlsValue) { + StringBuilder content = new StringBuilder(); + content.append("[profile test]\n"); + if (ignoreConfiguredEndpointUrlsValue != null) { + content.append("ignore_configured_endpoint_urls = ").append(ignoreConfiguredEndpointUrlsValue).append("\n"); + } + return ProfileFile.builder() + .type(ProfileFile.Type.CONFIGURATION) + .content(new StringInputStream(content.toString())) + .build(); + } +} diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointModeTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointModeTest.java new file mode 100644 index 000000000000..c19b7a5e21d7 --- /dev/null +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AccountIdEndpointModeTest.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.awscore.endpoints; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Locale; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +/** + * {@link AccountIdEndpointMode#value()} is what generated endpoint resolvers pass to the rules engine as the + * {@code AWS::Auth::AccountIdEndpointMode} built-in, so these tests pin the wire form itself rather than any caller. + */ +class AccountIdEndpointModeTest { + private final Locale defaultLocale = Locale.getDefault(); + + @AfterEach + void restoreLocale() { + Locale.setDefault(defaultLocale); + } + + @Test + void value_returnsTheLowercaseWireForm() { + assertThat(AccountIdEndpointMode.PREFERRED.value()).isEqualTo("preferred"); + assertThat(AccountIdEndpointMode.DISABLED.value()).isEqualTo("disabled"); + assertThat(AccountIdEndpointMode.REQUIRED.value()).isEqualTo("required"); + } + + /** + * The value is a compile-time literal, so the same reference comes back every time. That is what removes the + * per-request allocation the generated resolver used to pay for {@code name().toLowerCase()}. + */ + @ParameterizedTest + @EnumSource(AccountIdEndpointMode.class) + void value_returnsTheSameReferenceEachCall(AccountIdEndpointMode mode) { + assertThat(mode.value()).isSameAs(mode.value()); + } + + /** + * {@code fromValue} and {@code value} must describe the same mapping in both directions, otherwise a + * value the SDK emits is one it cannot read back. + */ + @ParameterizedTest + @EnumSource(AccountIdEndpointMode.class) + void fromValue_roundTripsValue(AccountIdEndpointMode mode) { + assertThat(AccountIdEndpointMode.fromValue(mode.value())).isSameAs(mode); + } + + /** + * The predecessor of this method was {@code name().toLowerCase()}, which uses the default locale. Under a Turkish + * locale that produces a dotless i (U+0131), so {@code DISABLED} became {@code dısabled} and was handed to the rules + * engine in that form. + */ + @ParameterizedTest + @EnumSource(AccountIdEndpointMode.class) + void value_isIndependentOfTheDefaultLocale(AccountIdEndpointMode mode) { + String underDefaultLocale = mode.value(); + + Locale.setDefault(new Locale("tr", "TR")); + + assertThat(mode.value()).isEqualTo(underDefaultLocale); + assertThat(mode.value()).doesNotContain("\u0131"); + } + + @Test + void fromValue_isCaseInsensitive() { + assertThat(AccountIdEndpointMode.fromValue("PREFERRED")).isSameAs(AccountIdEndpointMode.PREFERRED); + assertThat(AccountIdEndpointMode.fromValue("Disabled")).isSameAs(AccountIdEndpointMode.DISABLED); + } + + @Test + void fromValue_nullReturnsNull() { + assertThat(AccountIdEndpointMode.fromValue(null)).isNull(); + } + + @Test + void fromValue_unrecognizedThrows() { + assertThatThrownBy(() -> AccountIdEndpointMode.fromValue("nonsense")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("nonsense"); + } +} diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtilsTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtilsTest.java index b1fa2b82d6a1..19541dc6a8aa 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtilsTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/endpoints/AwsEndpointProviderUtilsTest.java @@ -26,12 +26,33 @@ import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.useragent.BusinessMetricCollection; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.regions.Region; class AwsEndpointProviderUtilsTest { + @Test + void skipEndpointResolution_skipAttrIsTrue_returnsTrue() { + ExecutionAttributes attrs = new ExecutionAttributes(); + attrs.putAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true); + assertThat(AwsEndpointProviderUtils.skipEndpointResolution(attrs)).isTrue(); + } + + @Test + void skipEndpointResolution_discoveredEndpointIsTrue_returnsTrue() { + ExecutionAttributes attrs = new ExecutionAttributes(); + attrs.putAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true); + assertThat(AwsEndpointProviderUtils.skipEndpointResolution(attrs)).isTrue(); + } + + @Test + void skipEndpointResolution_attrsAbsent_returnsFalse() { + ExecutionAttributes attrs = new ExecutionAttributes(); + assertThat(AwsEndpointProviderUtils.skipEndpointResolution(attrs)).isFalse(); + } + @Test void regionBuiltIn_returnsAttrValue() { ExecutionAttributes attrs = new ExecutionAttributes(); @@ -217,6 +238,91 @@ void setUri_noPathDifference_keepsRequestPath() { assertThat(result.encodedPath()).isEqualTo("/operation"); } + @Test + void setUri_endpointUrl_combinesPathsCorrectly() { + URI clientEndpoint = URI.create("https://override.example.com/a"); + EndpointUrl resolvedUrl = EndpointUrl.fromString("https://override.example.com/a/b"); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://override.example.com/a/c")) + .method(SdkHttpMethod.GET) + .build(); + + assertThat(AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl).getUri().toString()) + .isEqualTo("https://override.example.com/a/b/c"); + } + + @Test + void setUri_endpointUrl_doubleSlash_combinesPathsCorrectly() { + URI clientEndpoint = URI.create("https://override.example.com/a"); + EndpointUrl resolvedUrl = EndpointUrl.fromString("https://override.example.com/a/b"); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://override.example.com/a//c")) + .method(SdkHttpMethod.GET) + .build(); + + assertThat(AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl).getUri().toString()) + .isEqualTo("https://override.example.com/a/b//c"); + } + + @Test + void setUri_endpointUrl_withTrailingSlashNoPath_combinesPathsCorrectly() { + URI clientEndpoint = URI.create("https://override.example.com/"); + EndpointUrl resolvedUrl = EndpointUrl.fromString("https://override.example.com/"); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://override.example.com//a")) + .method(SdkHttpMethod.GET) + .build(); + + assertThat(AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl).getUri().toString()) + .isEqualTo("https://override.example.com//a"); + } + + @Test + void setUri_endpointUrl_noPathDifference_keepsRequestPath() { + URI clientEndpoint = URI.create("https://example.com"); + EndpointUrl resolvedUrl = EndpointUrl.fromString("https://resolved.example.com"); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://example.com/operation")) + .method(SdkHttpMethod.GET) + .build(); + + SdkHttpRequest result = AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl); + assertThat(result.host()).isEqualTo("resolved.example.com"); + assertThat(result.encodedPath()).isEqualTo("/operation"); + } + + @Test + void setUri_endpointUrl_withPort_setsPortCorrectly() { + URI clientEndpoint = URI.create("https://example.com:8080"); + EndpointUrl resolvedUrl = EndpointUrl.fromString("https://resolved.example.com:9090/path"); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://example.com:8080/operation")) + .method(SdkHttpMethod.GET) + .build(); + + SdkHttpRequest result = AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl); + assertThat(result.host()).isEqualTo("resolved.example.com"); + assertThat(result.port()).isEqualTo(9090); + assertThat(result.protocol()).isEqualTo("https"); + assertThat(result.encodedPath()).isEqualTo("/path/operation"); + } + + @Test + void setUri_endpointUrl_producesIdenticalResultToUriOverload() { + URI clientEndpoint = URI.create("https://override.example.com/a"); + URI resolvedUri = URI.create("https://override.example.com/a/b"); + EndpointUrl resolvedUrl = EndpointUrl.fromUri(resolvedUri); + SdkHttpRequest request = SdkHttpRequest.builder() + .uri(URI.create("https://override.example.com/a/c")) + .method(SdkHttpMethod.GET) + .build(); + + SdkHttpRequest uriResult = AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUri); + SdkHttpRequest endpointUrlResult = AwsEndpointProviderUtils.setUri(request, clientEndpoint, resolvedUrl); + + assertThat(endpointUrlResult.getUri()).isEqualTo(uriResult.getUri()); + } + private static ClientEndpointProvider endpointProvider(boolean isEndpointOverridden) { return ClientEndpointProvider.create(URI.create("https://foo.aws"), isEndpointOverridden); } diff --git a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptorTest.java b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptorTest.java index 76dc2cc3c465..686f0253b903 100644 --- a/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptorTest.java +++ b/core/aws-core/src/test/java/software/amazon/awssdk/awscore/interceptor/HelpfulUnknownHostExceptionInterceptorTest.java @@ -6,14 +6,12 @@ import java.net.UnknownHostException; import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import software.amazon.awssdk.awscore.AwsExecutionAttribute; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.interceptor.InterceptorContext; import software.amazon.awssdk.core.internal.interceptor.DefaultFailedExecutionContext; -import software.amazon.awssdk.regions.Region; public class HelpfulUnknownHostExceptionInterceptorTest { private static final ExecutionInterceptor INTERCEPTOR = new HelpfulUnknownHostExceptionInterceptor(); @@ -31,76 +29,26 @@ public void modifyException_supportsNestedUnknownHostExceptions() { exception = new IllegalArgumentException(exception); exception = new UnsupportedOperationException(exception); - assertThat(modifyException(exception, Region.AWS_GLOBAL)).isInstanceOf(SdkClientException.class); + assertThat(modifyException(exception)).isInstanceOf(SdkClientException.class); } @Test - public void modifyException_returnsGenericHelp_forGlobalRegions() { + public void modifyException_returnsNetworkHelp_forUnknownHostException() { UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.AWS_GLOBAL)) + assertThat(modifyException(exception)) .isInstanceOf(SdkClientException.class) .hasMessageContaining("network"); } @Test - public void modifyException_returnsGenericHelp_forUnknownServices() { - UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.US_EAST_1, "millems-hotdog-stand")) - .isInstanceOf(SdkClientException.class) - .satisfies(t -> doesNotHaveMessageContaining(t, "global")) - .hasMessageContaining("network"); - } - - @Test - public void modifyException_returnsGenericHelp_forUnknownServicesInUnknownRegions() { - UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.of("cn-north-99"), "millems-hotdog-stand")) - .isInstanceOf(SdkClientException.class) - .satisfies(t -> doesNotHaveMessageContaining(t, "global")) - .hasMessageContaining("network"); - } - - @Test - public void modifyException_returnsGenericHelp_forServicesRegionalizedInAllPartitions() { - UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.US_EAST_1, "dynamodb")) - .isInstanceOf(SdkClientException.class) - .satisfies(t -> doesNotHaveMessageContaining(t, "global")) - .hasMessageContaining("network"); - } - - @Test - public void modifyException_returnsGenericGlobalRegionHelp_forServicesGlobalInSomePartitionOtherThanTheClientPartition() { - UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.of("cn-north-99"), "iam")) - .isInstanceOf(SdkClientException.class) - .satisfies(t -> doesNotHaveMessageContaining(t, "network")) - .hasMessageContaining("aws-global") - .hasMessageContaining("aws-cn-global"); - } - - @Test - public void modifyException_returnsSpecificGlobalRegionHelp_forServicesGlobalInTheClientRegionPartition() { - UnknownHostException exception = new UnknownHostException(); - assertThat(modifyException(exception, Region.of("cn-north-1"), "iam")) - .isInstanceOf(SdkClientException.class) - .satisfies(t -> doesNotHaveMessageContaining(t, "aws-global")) - .hasMessageContaining("aws-cn-global"); - } - - private void doesNotHaveMessageContaining(Throwable throwable, String value) { - assertThat(throwable.getMessage()).doesNotContain(value); + public void modifyException_preservesOriginalExceptionAsCause() { + UnknownHostException exception = new UnknownHostException("iam.us-east-1.amazonaws.com"); + Throwable result = modifyException(exception); + assertThat(result).isInstanceOf(SdkClientException.class); + assertThat(result.getCause()).isSameAs(exception); } private Throwable modifyException(Throwable throwable) { - return modifyException(throwable, null); - } - - private Throwable modifyException(Throwable throwable, Region clientRegion) { - return modifyException(throwable, clientRegion, null); - } - - private Throwable modifyException(Throwable throwable, Region clientRegion, String serviceEndpointPrefix) { SdkRequest sdkRequest = Mockito.mock(SdkRequest.class); DefaultFailedExecutionContext context = @@ -109,10 +57,6 @@ private Throwable modifyException(Throwable throwable, Region clientRegion, Stri .exception(throwable) .build(); - ExecutionAttributes executionAttributes = - new ExecutionAttributes().putAttribute(AwsExecutionAttribute.AWS_REGION, clientRegion) - .putAttribute(AwsExecutionAttribute.ENDPOINT_PREFIX, serviceEndpointPrefix); - - return INTERCEPTOR.modifyException(context, executionAttributes); + return INTERCEPTOR.modifyException(context, new ExecutionAttributes()); } } \ No newline at end of file diff --git a/core/checksums-spi/pom.xml b/core/checksums-spi/pom.xml index 01bb8be7060b..2cf1e9396dc7 100644 --- a/core/checksums-spi/pom.xml +++ b/core/checksums-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT checksums-spi diff --git a/core/checksums/pom.xml b/core/checksums/pom.xml index ae77c3ec51af..6474e56be0c7 100644 --- a/core/checksums/pom.xml +++ b/core/checksums/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 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 65a2940b8aa2..dae3f27db564 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,8 @@ package software.amazon.awssdk.checksums; +import java.util.Collection; +import java.util.Collections; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import software.amazon.awssdk.annotations.SdkProtectedApi; @@ -52,6 +54,13 @@ public static ChecksumAlgorithm fromValue(String algorithm) { return ChecksumAlgorithmsCache.VALUES.get(algorithm.toUpperCase(Locale.US)); } + /** + * Returns all registered checksum algorithms. + */ + public static Collection values() { + return Collections.unmodifiableCollection(ChecksumAlgorithmsCache.VALUES.values()); + } + private static final class ChecksumAlgorithmsCache { private static final ConcurrentHashMap VALUES = new ConcurrentHashMap<>(); diff --git a/core/crt-core/pom.xml b/core/crt-core/pom.xml index be648b6fde23..d9d78cf4d193 100644 --- a/core/crt-core/pom.xml +++ b/core/crt-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT crt-core diff --git a/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtConfigurationUtils.java b/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtConfigurationUtils.java index b9a08ac01903..d03711c9a071 100644 --- a/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtConfigurationUtils.java +++ b/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtConfigurationUtils.java @@ -15,16 +15,21 @@ package software.amazon.awssdk.crtcore; +import java.util.Objects; import java.util.Optional; +import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.crt.http.HttpMonitoringOptions; import software.amazon.awssdk.crt.http.HttpProxyOptions; import software.amazon.awssdk.crt.io.TlsContext; +import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.NumericUtils; @SdkProtectedApi public final class CrtConfigurationUtils { + private static final Logger log = Logger.loggerFor(CrtConfigurationUtils.class); + private CrtConfigurationUtils() { } @@ -39,7 +44,15 @@ public static Optional resolveProxy(CrtProxyConfiguration prox clientProxyOptions.setHost(proxyConfiguration.host()); clientProxyOptions.setPort(proxyConfiguration.port()); if (!proxyConfiguration.nonProxyHosts().isEmpty()) { - clientProxyOptions.setNoProxyHosts(String.join(",", proxyConfiguration.nonProxyHosts())); + proxyConfiguration.nonProxyHosts().stream() + .filter(Objects::nonNull) + .filter(CrtConfigurationUtils::isUnsupportedWildcard) + .forEach(CrtConfigurationUtils::warnUnsupportedWildcard); + String noProxyHosts = proxyConfiguration.nonProxyHosts().stream() + .filter(Objects::nonNull) + .map(CrtConfigurationUtils::toCurlNoProxyHost) + .collect(Collectors.joining(",")); + clientProxyOptions.setNoProxyHosts(noProxyHosts); } if ("https".equalsIgnoreCase(proxyConfiguration.scheme())) { @@ -57,6 +70,29 @@ public static Optional resolveProxy(CrtProxyConfiguration prox return Optional.of(clientProxyOptions); } + /** + * Translates a {@code nonProxyHosts} token to the form expected by the curl-style native matcher: a host name with a + * leading {@code *.} wildcard ({@code *.example.com}) becomes a dot-anchored suffix ({@code .example.com}), while a bare + * {@code *}, exact host names, and CIDR ranges are passed through unchanged. A wildcard in any other position is + * unsupported (see {@link #isUnsupportedWildcard}) and passed through unchanged, so the native matcher will not match it. + */ + private static String toCurlNoProxyHost(String nonProxyHost) { + if (nonProxyHost.startsWith("*.")) { + return nonProxyHost.substring(1); + } + return nonProxyHost; + } + + private static boolean isUnsupportedWildcard(String nonProxyHost) { + return nonProxyHost.contains("*") && !nonProxyHost.equals("*") && !nonProxyHost.startsWith("*."); + } + + private static void warnUnsupportedWildcard(String nonProxyHost) { + log.warn(() -> "Unsupported wildcard in nonProxyHosts entry '" + nonProxyHost + "' for the CRT-based HTTP client: only " + + "an exact host, a leading '*.' suffix wildcard (e.g. *.example.com), a single '*', or a CIDR range " + + "are supported. This entry is ignored, so requests to matching hosts will go through the proxy."); + } + public static Optional resolveHttpMonitoringOptions(CrtConnectionHealthConfiguration config) { if (config == null) { return Optional.empty(); diff --git a/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtProxyConfiguration.java b/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtProxyConfiguration.java index 05969c913a52..014cbd6a044c 100644 --- a/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtProxyConfiguration.java +++ b/core/crt-core/src/main/java/software/amazon/awssdk/crtcore/CrtProxyConfiguration.java @@ -92,7 +92,7 @@ private Set resolveNonProxyHosts(DefaultBuilder builder, ProxyConfigP if (builder.nonProxyHosts != null || proxyConfigProvider == null) { return builder.nonProxyHosts; } - return proxyConfigProvider.nonProxyHosts(); + return proxyConfigProvider.rawNonProxyHosts(); } /** @@ -259,6 +259,9 @@ public interface Builder { * are not provided during building the {@link CrtProxyConfiguration} object. To disable this behaviour, set this value to * false.It is important to note that when this property is set to "true," all proxy settings will exclusively originate * from system properties, and no partial settings will be obtained from EnvironmentVariableValues. + *

Pipe-separated host names in the {@code http.nonProxyHosts} system property indicate multiple hosts to exclude + * from proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com|b.com"} and + * {@code "a.com | b.com"} are accepted. * * @param useSystemPropertyValues The option whether to use system property values * @return This object for method chaining. @@ -272,7 +275,8 @@ public interface Builder { * value to false.It is important to note that when this property is set to "true," all proxy settings will exclusively * originate from environment variableValues, and no partial settings will be obtained from SystemPropertyValues. *

Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from - * proxy settings. + * proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and + * {@code "a.com, b.com"} are accepted. * * @param useEnvironmentVariableValues The option whether to use environment variable values * @return This object for method chaining. @@ -280,19 +284,33 @@ public interface Builder { Builder useEnvironmentVariableValues(Boolean useEnvironmentVariableValues); /** - * Configure the hosts that the client is allowed to access without going through the proxy. - * The only wildcard available is a single "*" character, which matches all hosts. - * IP addresses specified to this option can be provided using CIDR notation: an appended slash and number - * specifies the number of "network bits" out of the address to use in the comparison. + * Configure the hosts that the client is allowed to access without going through the proxy. Each entry accepts the + * same forms as the {@code http.nonProxyHosts} system property: + *

    + *
  • an exact host name, such as {@code example.com}, which matches {@code example.com} and its subdomains;
  • + *
  • a host name with a leading {@code *} wildcard, such as {@code *.example.com}, which matches + * {@code example.com} and its subdomains;
  • + *
  • a single {@code *}, which matches all hosts;
  • + *
  • an IP range in CIDR notation, such as {@code 10.0.0.0/8}.
  • + *
+ * Entries must not carry surrounding whitespace; a leading or trailing space is treated as part of the host and + * prevents matching (for example the space in a comma-space {@code no_proxy=a.com, *.foo.com} value). */ Builder nonProxyHosts(Set nonProxyHosts); /** - * Add a host that the client is allowed to access without going through the proxy. - * The only wildcard available is a single "*" character, which matches all hosts. - * IP addresses specified to this option can be provided using CIDR notation: an appended slash and number - * specifies the number of "network bits" out of the address to use in the comparison. + * Add a host that the client is allowed to access without going through the proxy. The entry accepts the same forms + * as the {@code http.nonProxyHosts} system property: + *
    + *
  • an exact host name, such as {@code example.com}, which matches {@code example.com} and its subdomains;
  • + *
  • a host name with a leading {@code *} wildcard, such as {@code *.example.com}, which matches + * {@code example.com} and its subdomains;
  • + *
  • a single {@code *}, which matches all hosts;
  • + *
  • an IP range in CIDR notation, such as {@code 10.0.0.0/8}.
  • + *
+ * The entry must not carry surrounding whitespace; a leading or trailing space is treated as part of the host and + * prevents matching. */ Builder addNonProxyHost(String nonProxyHost); diff --git a/core/crt-core/src/test/java/software/amazon/awssdk/crtcore/CrtConnectionUtilsTest.java b/core/crt-core/src/test/java/software/amazon/awssdk/crtcore/CrtConnectionUtilsTest.java index 08ca7c119c85..22d15f1a6307 100644 --- a/core/crt-core/src/test/java/software/amazon/awssdk/crtcore/CrtConnectionUtilsTest.java +++ b/core/crt-core/src/test/java/software/amazon/awssdk/crtcore/CrtConnectionUtilsTest.java @@ -22,9 +22,11 @@ import java.util.Optional; import java.util.stream.Collectors; 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.ValueSource; +import org.junit.jupiter.params.provider.CsvSource; import org.mockito.Mockito; import software.amazon.awssdk.crt.http.HttpMonitoringOptions; import software.amazon.awssdk.crt.http.HttpProxyOptions; @@ -32,6 +34,14 @@ class CrtConnectionUtilsTest { + @BeforeEach + @AfterEach + void clearProxyProperties() { + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("http.nonProxyHosts"); + } + @Test void resolveProxy_basicAuthorization() { CrtProxyConfiguration configuration = new TestProxy.Builder().host("1.2.3.4") @@ -73,10 +83,81 @@ void resolveProxy_nonProxyHosts_setAsCommaSeperatedString() { .isEqualTo("host1,host2"); } + @ParameterizedTest(name = "builder nonProxyHost \"{0}\" -> curl \"{1}\"") + @CsvSource({ + "*.internal.example.com, .internal.example.com", + "'*', '*'", + "example.com, example.com", + "10.0.0.0/8, 10.0.0.0/8", + "192.168.*, 192.168.*", + "internal*, internal*", + "*foo.com, *foo.com", + "::1, ::1", + "2001:db8::/32, 2001:db8::/32", + "::1/128, ::1/128" + }) + void resolveProxy_builderNonProxyHost_translatedToCurlForm(String nonProxyHost, String expectedCurl) { + TlsContext tlsContext = Mockito.mock(TlsContext.class); + CrtProxyConfiguration configuration = new TestProxy.Builder().host("1.2.3.4") + .port(123) + .addNonProxyHost(nonProxyHost) + .build(); + + assertThat(CrtConfigurationUtils.resolveProxy(configuration, tlsContext).get().getNoProxyHosts()) + .isEqualTo(expectedCurl); + } + + @ParameterizedTest(name = "http.nonProxyHosts \"{0}\" -> curl \"{1}\"") + @CsvSource({ + "*.internal.example.com, .internal.example.com", + "'*', '*'" + }) + void resolveProxy_systemPropertyNonProxyHost_translatedToCurlForm(String nonProxyHost, String expectedCurl) { + System.setProperty("http.proxyHost", "proxy.example.com"); + System.setProperty("http.proxyPort", "8080"); + System.setProperty("http.nonProxyHosts", nonProxyHost); + + TlsContext tlsContext = Mockito.mock(TlsContext.class); + CrtProxyConfiguration configuration = new TestProxy.Builder().build(); + + assertThat(CrtConfigurationUtils.resolveProxy(configuration, tlsContext).get().getNoProxyHosts()) + .isEqualTo(expectedCurl); + } + + @Test + void resolveProxy_builderMixedGlobExactCidr_eachTokenTranslatedIndependently() { + TlsContext tlsContext = Mockito.mock(TlsContext.class); + CrtProxyConfiguration configuration = new TestProxy.Builder() + .host("1.2.3.4") + .port(123) + .nonProxyHosts(Stream.of("*.internal.example.com", "localhost", "10.0.0.0/8").collect(Collectors.toSet())) + .build(); + + String noProxyHosts = CrtConfigurationUtils.resolveProxy(configuration, tlsContext).get().getNoProxyHosts(); + assertThat(noProxyHosts.split(",")).containsExactlyInAnyOrder(".internal.example.com", "localhost", "10.0.0.0/8"); + } + + @Test + void resolveProxy_builderAndSystemPropertySuffixWildcard_produceSameCurlForm() { + TlsContext tlsContext = Mockito.mock(TlsContext.class); + CrtProxyConfiguration builderConfig = new TestProxy.Builder().host("1.2.3.4") + .port(123) + .addNonProxyHost("*.internal.example.com") + .build(); + String builderNoProxyHosts = CrtConfigurationUtils.resolveProxy(builderConfig, tlsContext).get().getNoProxyHosts(); + + System.setProperty("http.proxyHost", "proxy.example.com"); + System.setProperty("http.proxyPort", "8080"); + System.setProperty("http.nonProxyHosts", "*.internal.example.com"); + CrtProxyConfiguration systemPropertyConfig = new TestProxy.Builder().build(); + String systemPropertyNoProxyHosts = + CrtConfigurationUtils.resolveProxy(systemPropertyConfig, tlsContext).get().getNoProxyHosts(); + assertThat(builderNoProxyHosts).isEqualTo(systemPropertyNoProxyHosts).isEqualTo(".internal.example.com"); + } @Test - void resolveProxy_withNullHostAndNonPorxy_shouldNotReturnEmpty( ) { + void resolveProxy_withNullHostAndLiteralNullToken_shouldNotReturnEmpty( ) { TlsContext tlsContext = Mockito.mock(TlsContext.class); CrtProxyConfiguration configuration = new TestProxy.Builder().host(null) .port(123) @@ -104,6 +185,7 @@ void resolveProxy_basicAuthorization_WithNonMatchingNoProxy() { Optional httpProxyOptions = CrtConfigurationUtils.resolveProxy(configuration, tlsContext); assertThat(httpProxyOptions).hasValueSatisfying(proxy -> { + assertThat(proxy.getNoProxyHosts()).isEqualTo("someRandom"); assertThat(proxy.getTlsContext()).isEqualTo(tlsContext); assertThat(proxy.getAuthorizationPassword()).isEqualTo("bar"); assertThat(proxy.getAuthorizationUsername()).isEqualTo("foo"); diff --git a/core/endpoints-spi/pom.xml b/core/endpoints-spi/pom.xml index 549f1319e19e..0c0a899575fc 100644 --- a/core/endpoints-spi/pom.xml +++ b/core/endpoints-spi/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/Endpoint.java b/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/Endpoint.java index 7db593ba3376..96829aa03924 100644 --- a/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/Endpoint.java +++ b/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/Endpoint.java @@ -17,6 +17,7 @@ import java.net.URI; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,18 +29,41 @@ */ @SdkPublicApi public final class Endpoint { - private final URI url; + /** + * Initial capacity for the attribute and header maps. Endpoints carry very few of either, so the + * default capacity of 16 is extra overhead. + */ + private static final int ATTRIBUTE_MAP_CAPACITY = 4; + private static final int HEADER_MAP_CAPACITY = 4; + + private final EndpointUrl endpointUrl; private final Map> headers; private final Map, Object> attributes; private Endpoint(BuilderImpl b) { - this.url = b.url; - this.headers = b.headers; - this.attributes = b.attributes; + this.endpointUrl = b.endpointUrl; + this.headers = b.headers == null ? Collections.emptyMap() : Collections.unmodifiableMap(b.headers); + this.attributes = b.buildAttributes(); } + /** + * Returns the URI. + * Delegates to {@link EndpointUrl#toUri()} which lazily constructs the URI. + * + * @deprecated Use {@link #endpointUrl()} instead, which provides direct access to URL components + * without the overhead of constructing a {@link URI}. + */ + @Deprecated public URI url() { - return url; + return endpointUrl.toUri(); + } + + /** + * Returns the {@link EndpointUrl} for efficient access to URL components + * without URI construction overhead. + */ + public EndpointUrl endpointUrl() { + return endpointUrl; } public Map> headers() { @@ -66,7 +90,11 @@ public boolean equals(Object o) { Endpoint endpoint = (Endpoint) o; - if (url != null ? !url.equals(endpoint.url) : endpoint.url != null) { + // ensures Endpoints built via url(URI) and + // endpointUrl(EndpointUrl) are equal when the URLs are equivalent (e.g., IPv6 bracket differences). + URI thisUrl = endpointUrl != null ? endpointUrl.toUri() : null; + URI thatUrl = endpoint.endpointUrl != null ? endpoint.endpointUrl.toUri() : null; + if (thisUrl != null ? !thisUrl.equals(thatUrl) : thatUrl != null) { return false; } if (headers != null ? !headers.equals(endpoint.headers) : endpoint.headers != null) { @@ -77,7 +105,9 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = url != null ? url.hashCode() : 0; + // Use toUri() for consistency with equals() + URI uri = endpointUrl != null ? endpointUrl.toUri() : null; + int result = uri != null ? uri.hashCode() : 0; result = 31 * result + (headers != null ? headers.hashCode() : 0); result = 31 * result + (attributes != null ? attributes.hashCode() : 0); return result; @@ -88,8 +118,24 @@ public static Builder builder() { } public interface Builder { + /** + * Sets the endpoint URL from a {@link URI}. + * Internally converts to an {@link EndpointUrl} via {@link EndpointUrl#fromUri(URI)}. + * + * @deprecated Use {@link #endpointUrl(EndpointUrl)} instead. + */ + @Deprecated Builder url(URI url); + /** + * Sets the endpoint URL from an {@link EndpointUrl} directly. + * This is the preferred path for code that already has an {@code EndpointUrl} + * (e.g., generated endpoint providers). + */ + default Builder endpointUrl(EndpointUrl endpointUrl) { + throw new UnsupportedOperationException(); + } + Builder putHeader(String name, String value); Builder putAttribute(EndpointAttributeKey key, T value); @@ -98,31 +144,88 @@ public interface Builder { } private static class BuilderImpl implements Builder { - private URI url; - private final Map> headers = new HashMap<>(); - private final Map, Object> attributes = new HashMap<>(); + private EndpointUrl endpointUrl; + + /** + * Most endpoints declare no headers, so the map is allocated only once a header is added. + */ + private Map> headers; + + /** + * Endpoints almost always carry zero or one attribute (typically {@code AUTH_SCHEMES}), so the first + * entry is held in these two fields and {@link #attributes} is allocated only if a second distinct + * key arrives. This keeps the common cases free of a {@code HashMap} and its backing table. + */ + private EndpointAttributeKey firstAttributeKey; + private Object firstAttributeValue; + private Map, Object> attributes; private BuilderImpl() { } private BuilderImpl(Endpoint e) { - this.url = e.url; - if (e.headers != null) { + this.endpointUrl = e.endpointUrl; + if (!e.headers.isEmpty()) { + this.headers = new HashMap<>(Math.max(HEADER_MAP_CAPACITY, e.headers.size())); e.headers.forEach((n, v) -> { this.headers.put(n, new ArrayList<>(v)); }); } - this.attributes.putAll(e.attributes); + e.attributes.forEach(this::putAttributeUnchecked); + } + + /** + * Collapses the staged attributes into the smallest immutable map that can hold them. + */ + private Map, Object> buildAttributes() { + if (attributes != null) { + return Collections.unmodifiableMap(attributes); + } + if (firstAttributeKey != null) { + return Collections.singletonMap(firstAttributeKey, firstAttributeValue); + } + return Collections.emptyMap(); } + /** + * Stores an attribute without the generic key/value pairing, for use by callers that have already + * had that relationship checked (the {@link #putAttribute} overload and the copy constructor). + */ + private void putAttributeUnchecked(EndpointAttributeKey key, Object value) { + if (attributes != null) { + attributes.put(key, value); + } else if (firstAttributeKey == null || firstAttributeKey.equals(key)) { + firstAttributeKey = key; + firstAttributeValue = value; + } else { + // Sized for the realistic maximum rather than the default 16, whose backing table alone + // costs more than every other allocation on this path combined. + attributes = new HashMap<>(ATTRIBUTE_MAP_CAPACITY); + attributes.put(firstAttributeKey, firstAttributeValue); + attributes.put(key, value); + firstAttributeKey = null; + firstAttributeValue = null; + } + } + + @SuppressWarnings("deprecation") @Override public Builder url(URI url) { - this.url = url; + this.endpointUrl = EndpointUrl.fromUri(url); + return this; + } + + @Override + public Builder endpointUrl(EndpointUrl endpointUrl) { + this.endpointUrl = endpointUrl; return this; } @Override public Builder putHeader(String name, String value) { + if (this.headers == null) { + this.headers = new HashMap<>(HEADER_MAP_CAPACITY); + } List values = this.headers.computeIfAbsent(name, (n) -> new ArrayList<>()); values.add(value); return this; @@ -130,7 +233,7 @@ public Builder putHeader(String name, String value) { @Override public Builder putAttribute(EndpointAttributeKey key, T value) { - this.attributes.put(key, value); + putAttributeUnchecked(key, value); return this; } diff --git a/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/EndpointUrl.java b/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/EndpointUrl.java new file mode 100644 index 000000000000..72650413f21a --- /dev/null +++ b/core/endpoints-spi/src/main/java/software/amazon/awssdk/endpoints/EndpointUrl.java @@ -0,0 +1,387 @@ +/* + * 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.endpoints; + +import java.net.URI; +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * A lightweight, immutable representation of a resolved endpoint URL that stores pre-parsed components + * (scheme, host, port, path) as strings, avoiding the cost of {@link URI} construction. + * + *

Three factory methods are provided: + *

    + *
  • {@link #fromString(String)} — parses a URL string using simple string operations (no URI construction)
  • + *
  • {@link #fromComponents(String, String, int, String)} — creates from individual components (no query/fragment)
  • + *
  • {@link #fromUri(URI)} — creates from an existing URI (pre-populates the cached URI field, preserves + * query and fragment)
  • + *
+ */ +@SdkPublicApi +public final class EndpointUrl { + + private final String scheme; + private final String host; + private final int port; + private final String encodedPath; + private final String queryAndFragment; + private final String rawUrl; + + // Inline lazy URI — avoids dependency on utils module's Lazy. + // Uses double-checked locking. + private volatile URI uri; + + private EndpointUrl(String scheme, String host, int port, String encodedPath, + String queryAndFragment, String rawUrl, URI uri) { + this.scheme = scheme; + this.host = host; + this.port = port; + this.encodedPath = encodedPath; + this.queryAndFragment = queryAndFragment; + this.rawUrl = rawUrl; + this.uri = uri; + } + + /** + * Parse a URL string into its components without constructing a {@link URI}. + * + *

Performs minimal string splitting only. The original URL string is retained for faithful URI reconstruction + * via {@link #toUri()}. Path, query and fragment components (if present) MUST already be url encoded. + * + *

Expected format: {@code scheme://[userinfo@]host[:port][/encodedPath][?query][#fragment]} + * + *

Component extraction matches {@link URI} for well-formed URLs: + *

    + *
  • Userinfo is excluded from {@link #host()}, matching {@link URI#getHost()}. It remains part of the + * string returned by {@link #toUri()}, matching {@link URI#toString()}.
  • + *
  • A trailing {@code ':'} with no digits (e.g. {@code https://example.com:}) yields a port of {@code -1}, + * matching {@link URI#getPort()}.
  • + *
  • An IPv6 literal is stored with its enclosing brackets (e.g. {@code [::1]}).
  • + *
+ * + * @param url the URL string to parse + * @return a new {@code EndpointUrl} with pre-parsed components + * @throws IllegalArgumentException if the URL has no scheme, has a non-numeric or out-of-range port, has more + * than one {@code ':'} separating host and port, or has an unterminated IPv6 + * literal + */ + public static EndpointUrl fromString(String url) { + int schemeEnd = url.indexOf("://"); + if (schemeEnd < 0) { + throw invalidUrl(url, "unable to parse a scheme, which is required. Endpoint URLs must be absolute and " + + "begin with a scheme such as 'https://'"); + } + + String scheme = url.substring(0, schemeEnd); + int authorityStart = schemeEnd + 3; + + // Single pass over the authority. This locates where the authority ends and, at the same time, records the + // positions needed to split it into [userinfo '@'] host [':' port], so the authority is only scanned once. + // RFC 3986: the authority is terminated by '/', '?', '#', or the end of the URI. + int len = url.length(); + int authorityEnd = len; + int lastAt = -1; + int lastColon = -1; + int closeBracket = -1; + for (int i = authorityStart; i < len; i++) { + char c = url.charAt(i); + if (c == '/' || c == '?' || c == '#') { + authorityEnd = i; + break; + } + if (c == ':') { + lastColon = i; + } else if (c == '@') { + lastAt = i; + } else if (c == ']') { + closeBracket = i; + } + } + + String pathAndRest = authorityEnd < len ? url.substring(authorityEnd) : ""; + + // Separate path from query/fragment + String encodedPath; + String queryAndFragment; + int queryStart = pathAndRest.indexOf('?'); + int fragmentStart = pathAndRest.indexOf('#'); + int separatorPos = -1; + if (queryStart >= 0 && fragmentStart >= 0) { + separatorPos = Math.min(queryStart, fragmentStart); + } else if (queryStart >= 0) { + separatorPos = queryStart; + } else if (fragmentStart >= 0) { + separatorPos = fragmentStart; + } + + if (separatorPos >= 0) { + encodedPath = pathAndRest.substring(0, separatorPos); + queryAndFragment = pathAndRest.substring(separatorPos); + } else { + encodedPath = pathAndRest; + queryAndFragment = ""; + } + + // Userinfo, when present, runs up to the last '@' and is not part of the host. + int hostStart = lastAt >= 0 ? lastAt + 1 : authorityStart; + + // A ':' only separates host from port when it falls after any userinfo and, for a bracketed IPv6 literal, + // after the closing ']'. Colons inside userinfo (user:pass@) or inside brackets ([::1]) are not port + // separators. + boolean hasPort = lastColon >= hostStart && lastColon > closeBracket; + int hostEnd = hasPort ? lastColon : authorityEnd; + String host = url.substring(hostStart, hostEnd); + + if (!host.isEmpty() && host.charAt(0) == '[') { + if (closeBracket < hostStart || closeBracket >= hostEnd) { + throw invalidUrl(url, "malformed IPv6 host: missing closing ']'"); + } + } else if (host.indexOf(':') >= 0) { + throw invalidUrl(url, "malformed host '" + host + "': expected at most one ':' separating host and port"); + } + + int port = hasPort ? parsePort(url, lastColon + 1, authorityEnd) : -1; + + return new EndpointUrl(scheme, host, port, encodedPath, queryAndFragment, url, null); + } + + /** + * Parse the port from {@code url} in the range {@code [start, end)}. + * + *

An empty range means the URL ended with a bare ':', which {@link URI} treats as no port. + */ + private static int parsePort(String url, int start, int end) { + if (start == end) { + return -1; + } + + long port = 0; + for (int i = start; i < end; i++) { + char c = url.charAt(i); + if (c < '0' || c > '9') { + throw invalidUrl(url, "invalid port '" + url.substring(start, end) + "': port must be a number"); + } + port = port * 10 + (c - '0'); + if (port > Integer.MAX_VALUE) { + throw invalidUrl(url, "invalid port '" + url.substring(start, end) + "': port is out of range"); + } + } + return (int) port; + } + + private static IllegalArgumentException invalidUrl(String url, String reason) { + return new IllegalArgumentException("Invalid endpoint URL '" + url + "': " + reason); + } + + /** + * Create an {@code EndpointUrl} from individual components. + * + *

Used internally (e.g., by {@code addHostPrefix} and codegen) to avoid re-parsing. + * The {@code rawUrl} field is {@code null} in this case, so {@link #toUri()} reconstructs + * the URI from components. No query or fragment is included. + * + *

Equivalence contract: For any valid endpoint URL string {@code s} with no query or fragment, + * {@code fromComponents(scheme, host, port, path)} MUST produce an {@code EndpointUrl} that equals + * {@code fromString(scheme + "://" + host + (port >= 0 ? ":" + port : "") + path)}. + * The codegen relies on this equivalence — see {@code EndpointUrlCodeEmitter}. + * + * @param scheme the URL scheme (e.g., "https") + * @param host the hostname (e.g., "s3.us-east-1.amazonaws.com") + * @param port the port number, or -1 if not specified + * @param encodedPath the encoded path (e.g., "/bucket/key"), or empty string if no path + * @return a new {@code EndpointUrl} + */ + public static EndpointUrl fromComponents(String scheme, String host, int port, String encodedPath) { + return new EndpointUrl(scheme, host, port, encodedPath, "", null, null); + } + + /** + * Create an {@code EndpointUrl} from individual components, including query and fragment. + * + *

This overload is used when reconstructing an EndpointUrl with modifications (e.g., host prefix) + * while preserving the original query and fragment components. + * + * @param scheme the URL scheme (e.g., "https") + * @param host the hostname (e.g., "s3.us-east-1.amazonaws.com") + * @param port the port number, or -1 if not specified + * @param encodedPath the encoded path (e.g., "/bucket/key"), or empty string if no path + * @param queryAndFragment the query and fragment string (e.g., "?key=value#section"), or empty string if none + * @return a new {@code EndpointUrl} + */ + public static EndpointUrl fromComponents(String scheme, String host, int port, String encodedPath, + String queryAndFragment) { + return new EndpointUrl(scheme, host, port, encodedPath, queryAndFragment, null, null); + } + + /** + * Create an {@code EndpointUrl} from an existing {@link URI}. + * + *

The URI field is pre-populated, so {@link #toUri()} + * returns the original URI instance without any additional construction. + * + * @param uri the URI to create from + * @return a new {@code EndpointUrl} with components extracted from the URI + */ + public static EndpointUrl fromUri(URI uri) { + String rawPath = uri.getRawPath(); + String queryAndFragment = buildQueryAndFragment(uri); + return new EndpointUrl( + uri.getScheme(), + uri.getHost(), + uri.getPort(), + rawPath != null ? rawPath : "", + queryAndFragment, + null, + uri + ); + } + + /** + * Returns the URL scheme (e.g., "https"). + */ + public String scheme() { + return scheme; + } + + /** + * Returns the hostname (e.g., "s3.us-east-1.amazonaws.com"). + */ + public String host() { + return host; + } + + /** + * Returns the port number, or -1 if not explicitly specified. + */ + public int port() { + return port; + } + + /** + * Returns the encoded path (e.g., "/bucket/key"), or an empty string if no path is present. + */ + public String encodedPath() { + return encodedPath; + } + + /** + * Returns the query and fragment portion of the URL (e.g., {@code "?key=value#section"}), + * or an empty string if neither is present. + */ + public String queryAndFragment() { + return queryAndFragment; + } + + /** + * Returns the {@link URI} representation. Lazily constructed on first call using double-checked locking. + * + *

When created via {@link #fromString(String)}, uses the original URL string for faithful reconstruction. + * When created via {@link #fromComponents(String, String, int, String)} reconstructs from components (no query/fragment). + * When created via {@link #fromUri(URI)}, returns the original URI instance. + * + * @return the URI representation of this endpoint URL + */ + public URI toUri() { + URI result = uri; + if (result == null) { + synchronized (this) { + result = uri; + if (result == null) { + if (rawUrl != null) { + result = URI.create(rawUrl); + } else { + StringBuilder sb = new StringBuilder(); + sb.append(scheme).append("://").append(host); + if (port >= 0) { + sb.append(':').append(port); + } + sb.append(encodedPath); + sb.append(queryAndFragment); + result = URI.create(sb.toString()); + } + uri = result; + } + } + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + EndpointUrl that = (EndpointUrl) o; + + if (port != that.port) { + return false; + } + if (scheme != null ? !scheme.equals(that.scheme) : that.scheme != null) { + return false; + } + if (host != null ? !host.equals(that.host) : that.host != null) { + return false; + } + if (encodedPath != null ? !encodedPath.equals(that.encodedPath) : that.encodedPath != null) { + return false; + } + return queryAndFragment.equals(that.queryAndFragment); + } + + @Override + public int hashCode() { + int result = scheme != null ? scheme.hashCode() : 0; + result = 31 * result + (host != null ? host.hashCode() : 0); + result = 31 * result + port; + result = 31 * result + (encodedPath != null ? encodedPath.hashCode() : 0); + result = 31 * result + queryAndFragment.hashCode(); + return result; + } + + @Override + public String toString() { + return "EndpointUrl(" + + "scheme=" + scheme + + ", host=" + host + + ", port=" + port + + ", encodedPath=" + encodedPath + + ", queryAndFragment=" + queryAndFragment + + ")"; + } + + /** + * Build the query and fragment string from a URI, or return empty string if neither is present. + */ + private static String buildQueryAndFragment(URI uri) { + String rawQuery = uri.getRawQuery(); + String rawFragment = uri.getRawFragment(); + if (rawQuery == null && rawFragment == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + if (rawQuery != null) { + sb.append('?').append(rawQuery); + } + if (rawFragment != null) { + sb.append('#').append(rawFragment); + } + return sb.toString(); + } +} diff --git a/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointTest.java b/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointTest.java index e6e3cb2a8983..314c0f499fe8 100644 --- a/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointTest.java +++ b/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.endpoints; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.net.URI; import java.util.Arrays; @@ -88,4 +89,150 @@ public void toBuilder_attrsModified_notReflectedInOriginal() { assertThat(original.attribute(TEST_STRING_ATTR)).isEqualTo("foo"); } + + @Test + public void equality_acrossConstructionPaths() { + URI uri = URI.create("https://[::1]:8080/path?key=value#frag"); + + Endpoint viaUri = Endpoint.builder().url(uri).build(); + Endpoint viaFromString = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://[::1]:8080/path?key=value#frag")) + .build(); + Endpoint viaFromComponents = Endpoint.builder() + .endpointUrl(EndpointUrl.fromComponents("https", "[::1]", 8080, "/path", + "?key=value#frag")) + .build(); + + assertThat(viaUri).isEqualTo(viaFromString); + assertThat(viaUri).isEqualTo(viaFromComponents); + assertThat(viaUri.hashCode()).isEqualTo(viaFromString.hashCode()); + assertThat(viaUri.hashCode()).isEqualTo(viaFromComponents.hashCode()); + } + + @Test + public void inequality_differentUrlComponents() { + Endpoint endpoint1 = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com/path?key=value")) + .build(); + Endpoint endpoint2 = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com/path")) + .build(); + + assertThat(endpoint1).isNotEqualTo(endpoint2); + } + + @Test + public void endpointUrlAccessor_returnsCorrectComponents() { + Endpoint endpoint = Endpoint.builder() + .url(URI.create("https://s3.us-east-1.amazonaws.com:443/bucket")) + .build(); + + EndpointUrl endpointUrl = endpoint.endpointUrl(); + assertThat(endpointUrl.scheme()).isEqualTo("https"); + assertThat(endpointUrl.host()).isEqualTo("s3.us-east-1.amazonaws.com"); + assertThat(endpointUrl.port()).isEqualTo(443); + assertThat(endpointUrl.encodedPath()).isEqualTo("/bucket"); + assertThat(endpointUrl.queryAndFragment()).isEmpty(); + } + + @Test + public void build_noHeadersOrAttributes_returnsEmptyMaps() { + Endpoint endpoint = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .build(); + + assertThat(endpoint.headers()).isEmpty(); + assertThat(endpoint.attribute(TEST_STRING_ATTR)).isNull(); + } + + @Test + public void headers_isUnmodifiable() { + Endpoint noHeaders = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .build(); + Endpoint withHeaders = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putHeader("foo", "bar") + .build(); + + assertThatThrownBy(() -> noHeaders.headers().put("a", Arrays.asList("b"))) + .isInstanceOf(UnsupportedOperationException.class); + assertThatThrownBy(() -> withHeaders.headers().put("a", Arrays.asList("b"))) + .isInstanceOf(UnsupportedOperationException.class); + } + + /** + * A single attribute is staged inline rather than in a map, so exercise the read path for one, two and + * three attributes as well as overwriting the staged entry. + */ + @Test + public void putAttribute_variousArities_allReadable() { + EndpointAttributeKey second = new EndpointAttributeKey<>("Second", String.class); + EndpointAttributeKey third = new EndpointAttributeKey<>("Third", String.class); + + Endpoint one = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putAttribute(TEST_STRING_ATTR, "a") + .build(); + assertThat(one.attribute(TEST_STRING_ATTR)).isEqualTo("a"); + assertThat(one.attribute(second)).isNull(); + + Endpoint two = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putAttribute(TEST_STRING_ATTR, "a") + .putAttribute(second, "b") + .build(); + assertThat(two.attribute(TEST_STRING_ATTR)).isEqualTo("a"); + assertThat(two.attribute(second)).isEqualTo("b"); + + Endpoint three = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putAttribute(TEST_STRING_ATTR, "a") + .putAttribute(second, "b") + .putAttribute(third, "c") + .build(); + assertThat(three.attribute(TEST_STRING_ATTR)).isEqualTo("a"); + assertThat(three.attribute(second)).isEqualTo("b"); + assertThat(three.attribute(third)).isEqualTo("c"); + } + + @Test + public void putAttribute_sameKeyTwice_lastValueWins() { + EndpointAttributeKey second = new EndpointAttributeKey<>("Second", String.class); + + Endpoint staged = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putAttribute(TEST_STRING_ATTR, "first") + .putAttribute(TEST_STRING_ATTR, "second") + .build(); + assertThat(staged.attribute(TEST_STRING_ATTR)).isEqualTo("second"); + + // Same key overwritten after the builder has been promoted to a map. + Endpoint promoted = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .putAttribute(TEST_STRING_ATTR, "first") + .putAttribute(second, "other") + .putAttribute(TEST_STRING_ATTR, "second") + .build(); + assertThat(promoted.attribute(TEST_STRING_ATTR)).isEqualTo("second"); + assertThat(promoted.attribute(second)).isEqualTo("other"); + } + + @Test + public void toBuilder_roundTripsAllAttributeArities() { + EndpointAttributeKey second = new EndpointAttributeKey<>("Second", String.class); + + Endpoint none = Endpoint.builder() + .endpointUrl(EndpointUrl.fromString("https://example.com")) + .build(); + assertThat(none.toBuilder().build()).isEqualTo(none); + + Endpoint one = none.toBuilder().putAttribute(TEST_STRING_ATTR, "a").build(); + assertThat(one.toBuilder().build()).isEqualTo(one); + + Endpoint two = one.toBuilder().putAttribute(second, "b").build(); + assertThat(two.toBuilder().build()).isEqualTo(two); + assertThat(two.attribute(TEST_STRING_ATTR)).isEqualTo("a"); + assertThat(two.attribute(second)).isEqualTo("b"); + } } diff --git a/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointUrlTest.java b/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointUrlTest.java new file mode 100644 index 000000000000..ce3c03a9dd1a --- /dev/null +++ b/core/endpoints-spi/src/test/java/software/amazon/awssdk/endpoints/EndpointUrlTest.java @@ -0,0 +1,468 @@ +/* + * 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.endpoints; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Tests for {@link EndpointUrl}. + */ +public class EndpointUrlTest { + + /** + * Representative AWS URLs used across parameterized tests. + */ + static List urls() { + return Arrays.asList( + "https://s3.us-east-1.amazonaws.com", + "https://s3.us-east-1.amazonaws.com/bucket/key", + "https://localhost:8080/path", + "https://s3.amazonaws.com/", + "https://[::1]:8080/path", + "https://dynamodb.us-west-2.amazonaws.com" + ); + } + + @ParameterizedTest + @MethodSource("urls") + void componentFidelity_scheme(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI uri = URI.create(url); + assertThat(endpointUrl.scheme()).isEqualTo(uri.getScheme()); + } + + /** + * Non-IPv6 URLs for host fidelity comparison against {@code URI.getHost()}. + * + *

IPv6 is excluded because {@code EndpointUrl.fromString()} always stores the host WITH brackets + * (e.g., "[::1]"), while {@code URI.getHost()} behavior for IPv6 varies across JDK versions + * (Java 8 strips brackets, Java 17+ keeps them). IPv6 host parsing is verified directly + * in the dedicated edge-case tests below.

+ */ + static List nonIpv6Urls() { + return Arrays.asList( + "https://s3.us-east-1.amazonaws.com", + "https://s3.us-east-1.amazonaws.com/bucket/key", + "https://localhost:8080/path", + "https://s3.amazonaws.com/", + "https://dynamodb.us-west-2.amazonaws.com" + ); + } + + @ParameterizedTest + @MethodSource("nonIpv6Urls") + void componentFidelity_host(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI uri = URI.create(url); + assertThat(endpointUrl.host()).isEqualTo(uri.getHost()); + } + + @ParameterizedTest + @MethodSource("urls") + void componentFidelity_port(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI uri = URI.create(url); + assertThat(endpointUrl.port()).isEqualTo(uri.getPort()); + } + + @ParameterizedTest + @MethodSource("urls") + void componentFidelity_encodedPath(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI uri = URI.create(url); + String expectedPath = uri.getRawPath() != null ? uri.getRawPath() : ""; + assertThat(endpointUrl.encodedPath()).isEqualTo(expectedPath); + } + + @ParameterizedTest + @MethodSource("urls") + void fromStringToUriRoundTrip(String url) { + assertThat(EndpointUrl.fromString(url).toUri()).isEqualTo(URI.create(url)); + } + + @ParameterizedTest + @MethodSource("urls") + void toUriCaching_fromString(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI first = endpointUrl.toUri(); + URI second = endpointUrl.toUri(); + assertThat(first).isSameAs(second); + } + + @Test + void toUriCaching_fromComponents() { + EndpointUrl endpointUrl = EndpointUrl.fromComponents("https", "s3.us-east-1.amazonaws.com", -1, ""); + URI first = endpointUrl.toUri(); + URI second = endpointUrl.toUri(); + assertThat(first).isSameAs(second); + } + + @Test + void toUriCaching_fromUri() { + URI original = URI.create("https://s3.us-east-1.amazonaws.com"); + EndpointUrl endpointUrl = EndpointUrl.fromUri(original); + URI first = endpointUrl.toUri(); + URI second = endpointUrl.toUri(); + assertThat(first).isSameAs(second); + } + + @ParameterizedTest + @MethodSource("urls") + void fromUriRoundTripIdentity(String url) { + URI original = URI.create(url); + assertThat(EndpointUrl.fromUri(original).toUri()).isSameAs(original); + } + + @Test + void malformedUrl_noSchemeSeparator() { + assertThatThrownBy(() -> EndpointUrl.fromString("not-a-url")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void malformedUrl_emptyString() { + assertThatThrownBy(() -> EndpointUrl.fromString("")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void malformedUrl_singleColon() { + assertThatThrownBy(() -> EndpointUrl.fromString("https:host")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void malformedUrl_noScheme_messageExplainsSchemeIsRequired() { + assertThatThrownBy(() -> EndpointUrl.fromString("lambda.us-east-1.amazonaws.com")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("lambda.us-east-1.amazonaws.com") + .hasMessageContaining("scheme") + .hasMessageContaining("required") + .hasMessageContaining("https://"); + } + + static List userInfoUrls() { + return Arrays.asList( + "https://user:pass@example.com", + "https://user@example.com", + "https://user:pass@example.com:8443/path", + "https://user@example.com:8443", + "https://@example.com" + ); + } + + @ParameterizedTest + @MethodSource("userInfoUrls") + void fromString_userInfo_excludedFromHostMatchingUri(String url) { + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + URI uri = URI.create(url); + + assertThat(endpointUrl.host()).isEqualTo(uri.getHost()); + assertThat(endpointUrl.port()).isEqualTo(uri.getPort()); + assertThat(endpointUrl.encodedPath()).isEqualTo(uri.getRawPath()); + } + + @ParameterizedTest + @MethodSource("userInfoUrls") + void fromString_userInfo_retainedInToUri(String url) { + assertThat(EndpointUrl.fromString(url).toUri()).isEqualTo(URI.create(url)); + } + + @Test + void fromString_userInfoContainingColon_doesNotParseAsPort() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://user:pass@example.com"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + } + + @Test + void fromString_trailingColonWithNoPort_portIsUnset() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com:"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(URI.create("https://example.com:").getPort()); + assertThat(endpointUrl.port()).isEqualTo(-1); + } + + @Test + void fromString_trailingColonWithPath_portIsUnset() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com:/path"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_nonNumericPort_throwsWithActionableMessage() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://example.com:notanumber")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("https://example.com:notanumber") + .hasMessageContaining("port") + .hasMessageContaining("notanumber"); + } + + @Test + void fromString_negativePort_throws() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://example.com:-1")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("port"); + } + + @Test + void fromString_portOutOfIntRange_throws() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://example.com:99999999999")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("out of range"); + } + + @Test + void fromString_multipleColonsInAuthority_throws() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://example.com:80:90")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("host"); + } + + @Test + void fromString_unbracketedIpv6_throws() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://::1/path")) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + void fromString_ipv6MissingClosingBracket_throws() { + assertThatThrownBy(() -> EndpointUrl.fromString("https://[::1:8080")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("IPv6"); + } + + @Test + void fromString_ipv6WithUserInfo() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://user:pass@[::1]:8080/path"); + assertThat(endpointUrl.host()).isEqualTo("[::1]"); + assertThat(endpointUrl.port()).isEqualTo(8080); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_ipv6NoPortWithPath_portIsUnset() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://[2001:db8::1]/path"); + assertThat(endpointUrl.host()).isEqualTo("[2001:db8::1]"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_userInfoWithSlashInPath_authorityScanStopsAtPath() { + // The '@' and ':' delimiters must only be looked for inside the authority, never in the path. + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com/path/with@at/and:colon"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path/with@at/and:colon"); + } + + @Test + void fromString_atAndColonInQuery_notTreatedAsAuthority() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com?a=b@c:1"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("?a=b@c:1"); + } + + @Test + void fromString_noPath_encodedPathIsEmpty() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://dynamodb.us-west-2.amazonaws.com"); + assertThat(endpointUrl.encodedPath()).isEmpty(); + } + + @Test + void fromString_trailingSlash_encodedPathIsSlash() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://s3.amazonaws.com/"); + assertThat(endpointUrl.encodedPath()).isEqualTo("/"); + } + + @Test + void fromString_ipv6WithPort() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://[::1]:8080/path"); + assertThat(endpointUrl.host()).isEqualTo("[::1]"); + assertThat(endpointUrl.port()).isEqualTo(8080); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_ipv6WithoutPort() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://[::1]/path"); + assertThat(endpointUrl.host()).isEqualTo("[::1]"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_explicitPort() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://localhost:8080/path"); + assertThat(endpointUrl.scheme()).isEqualTo("https"); + assertThat(endpointUrl.host()).isEqualTo("localhost"); + assertThat(endpointUrl.port()).isEqualTo(8080); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + } + + @Test + void fromString_noPort() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://s3.us-east-1.amazonaws.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + } + + static List preParsedEquivalenceUrls() { + return Arrays.asList( + // Simple URL (no port, no path) + "https://s3.us-east-1.amazonaws.com", + // URL with port only + "https://runtime.sagemaker.us-east-1.amazonaws.com:8443", + // URL with path only + "https://places.geo.us-east-1.amazonaws.com/v2", + // URL with both port and path + "https://localhost:8443/v2/api", + // URL with trailing slash + "https://s3.amazonaws.com/", + // HTTP scheme with port and path + "http://localhost:8080/path", + // URL with deeper path + "https://s3.us-west-2.amazonaws.com/prefix/key" + ); + } + + @ParameterizedTest + @MethodSource("preParsedEquivalenceUrls") + void preParsedEquivalence_components(String url) { + EndpointUrl parsed = EndpointUrl.fromString(url); + EndpointUrl constructed = EndpointUrl.fromComponents(parsed.scheme(), parsed.host(), parsed.port(), parsed.encodedPath()); + + assertThat(constructed.scheme()).isEqualTo(parsed.scheme()); + assertThat(constructed.host()).isEqualTo(parsed.host()); + assertThat(constructed.port()).isEqualTo(parsed.port()); + assertThat(constructed.encodedPath()).isEqualTo(parsed.encodedPath()); + } + + @ParameterizedTest + @MethodSource("preParsedEquivalenceUrls") + void preParsedEquivalence_toUri(String url) { + EndpointUrl parsed = EndpointUrl.fromString(url); + EndpointUrl constructed = EndpointUrl.fromComponents(parsed.scheme(), parsed.host(), parsed.port(), parsed.encodedPath()); + + assertThat(constructed.toUri()).isEqualTo(parsed.toUri()); + } + + @ParameterizedTest + @MethodSource("preParsedEquivalenceUrls") + void preParsedEquivalence_objectEquality(String url) { + EndpointUrl parsed = EndpointUrl.fromString(url); + EndpointUrl constructed = EndpointUrl.fromComponents(parsed.scheme(), parsed.host(), parsed.port(), parsed.encodedPath()); + + assertThat(constructed).isEqualTo(parsed); + assertThat(constructed.hashCode()).isEqualTo(parsed.hashCode()); + } + + @Test + void fromString_withQueryOnly() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com/path?key=value&foo=bar"); + assertThat(endpointUrl.scheme()).isEqualTo("https"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.port()).isEqualTo(-1); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("?key=value&foo=bar"); + } + + @Test + void fromString_withFragmentOnly() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com/path#section"); + assertThat(endpointUrl.scheme()).isEqualTo("https"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("#section"); + } + + @Test + void fromString_withQueryAndFragment() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com/path?key=value#section"); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("?key=value#section"); + } + + @Test + void fromString_noQueryOrFragment() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com/path"); + assertThat(endpointUrl.queryAndFragment()).isEmpty(); + } + + @Test + void fromString_queryWithNoPath() { + EndpointUrl endpointUrl = EndpointUrl.fromString("https://example.com?key=value"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.encodedPath()).isEmpty(); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("?key=value"); + } + + @Test + void fromString_withQueryAndFragment_toUriRoundTrip() { + String url = "https://example.com/path?key=value#section"; + EndpointUrl endpointUrl = EndpointUrl.fromString(url); + assertThat(endpointUrl.toUri()).isEqualTo(URI.create(url)); + } + + @Test + void fromUri_withQueryAndFragment_preservesComponents() { + URI uri = URI.create("https://example.com/path?key=value#section"); + EndpointUrl endpointUrl = EndpointUrl.fromUri(uri); + assertThat(endpointUrl.scheme()).isEqualTo("https"); + assertThat(endpointUrl.host()).isEqualTo("example.com"); + assertThat(endpointUrl.encodedPath()).isEqualTo("/path"); + assertThat(endpointUrl.queryAndFragment()).isEqualTo("?key=value#section"); + assertThat(endpointUrl.toUri()).isSameAs(uri); + } + + @Test + void fromUri_noQueryOrFragment() { + URI uri = URI.create("https://example.com/path"); + EndpointUrl endpointUrl = EndpointUrl.fromUri(uri); + assertThat(endpointUrl.queryAndFragment()).isEmpty(); + } + + @Test + void fromComponents_withQueryAndFragment_toUriIncludesThem() { + EndpointUrl endpointUrl = EndpointUrl.fromComponents("https", "example.com", -1, "/path", "?key=value#section"); + assertThat(endpointUrl.toUri()).isEqualTo(URI.create("https://example.com/path?key=value#section")); + } + + @Test + void fromComponents_withQueryAndFragment_preservedInEquality() { + EndpointUrl with = EndpointUrl.fromComponents("https", "example.com", -1, "/path", "?key=value"); + EndpointUrl without = EndpointUrl.fromComponents("https", "example.com", -1, "/path"); + assertThat(with).isNotEqualTo(without); + } + + @Test + void fromComponents_withEmptyQueryAndFragment_equalsOfWithoutIt() { + EndpointUrl withEmpty = EndpointUrl.fromComponents("https", "example.com", -1, "/path", ""); + EndpointUrl without = EndpointUrl.fromComponents("https", "example.com", -1, "/path"); + assertThat(withEmpty).isEqualTo(without); + } +} diff --git a/core/http-auth-aws-crt/pom.xml b/core/http-auth-aws-crt/pom.xml index 82fc2125630b..ecc5c2318cab 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-auth-aws-crt diff --git a/core/http-auth-aws-eventstream/pom.xml b/core/http-auth-aws-eventstream/pom.xml index f27b7cc16f17..21dd36a40e04 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-auth-aws-eventstream diff --git a/core/http-auth-aws/pom.xml b/core/http-auth-aws/pom.xml index 3e6848f56cd7..477613bdccb9 100644 --- a/core/http-auth-aws/pom.xml +++ b/core/http-auth-aws/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-auth-aws @@ -126,11 +126,6 @@ equalsverifier test - - org.reactivestreams - reactive-streams-tck - test - software.amazon.awssdk test-utils diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/FlexibleChecksummer.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/FlexibleChecksummer.java index 6c1539462788..2a0108426ef7 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/FlexibleChecksummer.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/FlexibleChecksummer.java @@ -81,9 +81,10 @@ public CompletableFuture> checksum(Publisher p } payload.subscribe(checksumSubscriber); - CompletableFuture> result = checksumSubscriber.completeFuture(); - result.thenRun(() -> addChecksums(request)); - return result; + return checksumSubscriber.completeFuture().thenApply(checksummedPayload -> { + addChecksums(request); + return checksummedPayload; + }); } private void addChecksums(SdkHttpRequest.Builder request) { diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/ChecksumSubscriber.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/ChecksumSubscriber.java index 3e1a878a1d0f..3c0e98028b58 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/ChecksumSubscriber.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/ChecksumSubscriber.java @@ -95,7 +95,8 @@ public void onError(Throwable throwable) { @Override public void onComplete() { - checksumming.complete(new InMemoryPublisher(bufferedPayload)); + long totalBytes = bufferedPayload.stream().mapToLong(ByteBuffer::remaining).sum(); + checksumming.complete(new InMemoryPublisher(bufferedPayload, totalBytes)); } public CompletableFuture> completeFuture() { diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisher.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisher.java index f094ce61ad11..295a90de1b73 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisher.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisher.java @@ -18,24 +18,33 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; import software.amazon.awssdk.utils.Validate; /** - * Temporarily used for buffering all data into memory. + * A content-length-aware publisher that replays buffered data. Used by {@link ChecksumSubscriber} to replay the payload after + * checksumming. */ @SdkInternalApi -public class InMemoryPublisher implements Publisher { +public class InMemoryPublisher implements SdkHttpContentPublisher { private final AtomicBoolean subscribed = new AtomicBoolean(false); private final List data; + private final long length; - public InMemoryPublisher(List data) { + public InMemoryPublisher(List data, long length) { this.data = new ArrayList<>(Validate.noNullElements(data, "Data must not contain null elements.")); + this.length = length; + } + + @Override + public Optional contentLength() { + return Optional.of(length); } @Override @@ -56,6 +65,12 @@ public void subscribe(Subscriber s) { @Override public void request(long n) { + if (n <= 0) { + finish(() -> s.onError( + new IllegalArgumentException("n > 0 required but it was " + n))); + return; + } + if (done.get()) { return; } @@ -70,12 +85,15 @@ public void request(long n) { private void fulfillDemand() { do { - if (sending.compareAndSet(false, true)) { - try { + if (!sending.compareAndSet(false, true)) { + return; + } + try { + while (!done.get() && demand.get() > 0) { send(); - } finally { - sending.set(false); } + } finally { + sending.set(false); } } while (!done.get() && demand.get() > 0); } diff --git a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkedEncodedPublisherTckTest.java b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkedEncodedPublisherTckTest.java index e539e5fe8ad4..69601858fdb1 100644 --- a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkedEncodedPublisherTckTest.java +++ b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/chunkedencoding/ChunkedEncodedPublisherTckTest.java @@ -61,9 +61,14 @@ private Publisher createChunkedPublisher(long chunksToProduce) { Publisher inputPublisher = Flowable.fromIterable(elements); + // Required by the builder; must match the data the input publisher produces. Production sets this from the + // x-amz-decoded-content-length header (see AwsChunkedV4PayloadSigner). + long contentLength = (long) totalElements * INPUT_STREAM_ELEMENT_SIZE; + return ChunkedEncodedPublisher.builder() .chunkSize(CHUNK_SIZE) .publisher(inputPublisher) + .contentLength(contentLength) .addEmptyTrailingChunk(false) .build(); } diff --git a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTckTest.java b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTckTest.java new file mode 100644 index 000000000000..7830789545d6 --- /dev/null +++ b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTckTest.java @@ -0,0 +1,52 @@ +/* + * 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.http.auth.aws.internal.signer.io; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import org.reactivestreams.Publisher; +import org.reactivestreams.tck.PublisherVerification; +import org.reactivestreams.tck.TestEnvironment; + +/** + * TCK verification test for {@link InMemoryPublisher}. + */ +public class InMemoryPublisherTckTest extends PublisherVerification { + + public InMemoryPublisherTckTest() { + super(new TestEnvironment(1000)); + } + + @Override + public Publisher createPublisher(long elements) { + List data = new ArrayList<>(); + for (long i = 0; i < elements; i++) { + data.add(ByteBuffer.wrap(new byte[]{(byte) (i % 127)})); + } + return new InMemoryPublisher(data, elements); + } + + @Override + public Publisher createFailedPublisher() { + return null; + } + + @Override + public long maxElementsFromPublisher() { + return 1024L; + } +} diff --git a/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTest.java b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTest.java new file mode 100644 index 000000000000..30a71b30c537 --- /dev/null +++ b/core/http-auth-aws/src/test/java/software/amazon/awssdk/http/auth/aws/internal/signer/io/InMemoryPublisherTest.java @@ -0,0 +1,183 @@ +/* + * 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.http.auth.aws.internal.signer.io; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +public class InMemoryPublisherTest { + + @Test + public void contentLength_returnsProvidedLength() { + List data = Arrays.asList( + ByteBuffer.wrap("hello".getBytes(StandardCharsets.UTF_8)), + ByteBuffer.wrap(" world".getBytes(StandardCharsets.UTF_8)) + ); + InMemoryPublisher publisher = new InMemoryPublisher(data, 11); + assertThat(publisher.contentLength()).hasValue(11L); + } + + @Test + public void contentLength_emptyPayload_returnsZero() { + InMemoryPublisher publisher = new InMemoryPublisher(new ArrayList<>(), 0); + assertThat(publisher.contentLength()).hasValue(0L); + } + + @Test + public void subscribe_deliversAllData() throws Exception { + byte[] bytes = "test data".getBytes(StandardCharsets.UTF_8); + List data = Arrays.asList(ByteBuffer.wrap(bytes)); + InMemoryPublisher publisher = new InMemoryPublisher(data, bytes.length); + + List received = new ArrayList<>(); + CountDownLatch completed = new CountDownLatch(1); + + publisher.subscribe(new Subscriber() { + @Override + public void onSubscribe(Subscription s) { + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + received.add(byteBuffer); + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onComplete() { + completed.countDown(); + } + }); + + assertThat(completed.await(5, TimeUnit.SECONDS)).isTrue(); + assertThat(received).hasSize(1); + } + + @Test + public void subscribe_reEntrantRequestFromOnNext_doesNotDeadlock() throws Exception { + List data = Arrays.asList( + ByteBuffer.wrap("a".getBytes(StandardCharsets.UTF_8)), + ByteBuffer.wrap("b".getBytes(StandardCharsets.UTF_8)), + ByteBuffer.wrap("c".getBytes(StandardCharsets.UTF_8)) + ); + InMemoryPublisher publisher = new InMemoryPublisher(data, 3); + + List received = new ArrayList<>(); + CountDownLatch completed = new CountDownLatch(1); + AtomicBoolean error = new AtomicBoolean(false); + + publisher.subscribe(new Subscriber() { + private Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + this.subscription = s; + s.request(1); + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + received.add(byteBuffer); + // Re-entrant request — this is what ByteBufferStoringSubscriber does + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + error.set(true); + completed.countDown(); + } + + @Override + public void onComplete() { + completed.countDown(); + } + }); + + assertThat(completed.await(5, TimeUnit.SECONDS)) + .as("Should complete without deadlocking") + .isTrue(); + assertThat(error.get()).isFalse(); + assertThat(received).hasSize(3); + } + + @Test + public void subscribe_secondSubscription_getsError() { + List data = Arrays.asList(ByteBuffer.wrap("x".getBytes(StandardCharsets.UTF_8))); + InMemoryPublisher publisher = new InMemoryPublisher(data, 1); + + publisher.subscribe(new Subscriber() { + @Override public void onSubscribe(Subscription s) { s.request(1); } + @Override public void onNext(ByteBuffer b) { } + @Override public void onError(Throwable t) { } + @Override public void onComplete() { } + }); + + AtomicBoolean gotError = new AtomicBoolean(false); + publisher.subscribe(new Subscriber() { + @Override public void onSubscribe(Subscription s) { } + @Override public void onNext(ByteBuffer b) { } + @Override public void onError(Throwable t) { gotError.set(true); } + @Override public void onComplete() { } + }); + + assertThat(gotError.get()).isTrue(); + } + + @Test + public void subscribe_requestNonPositive_signalsError() throws Exception { + List data = Arrays.asList(ByteBuffer.wrap("x".getBytes(StandardCharsets.UTF_8))); + InMemoryPublisher publisher = new InMemoryPublisher(data, 1); + + AtomicBoolean gotError = new AtomicBoolean(false); + CountDownLatch completed = new CountDownLatch(1); + + publisher.subscribe(new Subscriber() { + @Override + public void onSubscribe(Subscription s) { + s.request(0); + } + + @Override public void onNext(ByteBuffer b) { } + + @Override + public void onError(Throwable t) { + gotError.set(t instanceof IllegalArgumentException); + completed.countDown(); + } + + @Override public void onComplete() { completed.countDown(); } + }); + + assertThat(completed.await(5, TimeUnit.SECONDS)).isTrue(); + assertThat(gotError.get()).isTrue(); + } +} diff --git a/core/http-auth-spi/pom.xml b/core/http-auth-spi/pom.xml index b0566d5021c3..e54ca331781d 100644 --- a/core/http-auth-spi/pom.xml +++ b/core/http-auth-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-auth-spi diff --git a/core/http-auth/pom.xml b/core/http-auth/pom.xml index f419f30481b4..6cb7df77d76e 100644 --- a/core/http-auth/pom.xml +++ b/core/http-auth/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-auth diff --git a/core/identity-spi/pom.xml b/core/identity-spi/pom.xml index 34caeefaf3b7..958966b9cf58 100644 --- a/core/identity-spi/pom.xml +++ b/core/identity-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT identity-spi diff --git a/core/imds/pom.xml b/core/imds/pom.xml index 9c1f365b9b3e..fb1aee67c924 100644 --- a/core/imds/pom.xml +++ b/core/imds/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 imds diff --git a/core/json-utils/pom.xml b/core/json-utils/pom.xml index e60b8f70be45..4d6a9c36ca2e 100644 --- a/core/json-utils/pom.xml +++ b/core/json-utils/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/metrics-spi/pom.xml b/core/metrics-spi/pom.xml index ae6aee206698..cacb1541da06 100644 --- a/core/metrics-spi/pom.xml +++ b/core/metrics-spi/pom.xml @@ -5,7 +5,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index c7873e308b37..58db4cf9c312 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT core diff --git a/core/profiles/pom.xml b/core/profiles/pom.xml index 85de6d663783..8501483355e8 100644 --- a/core/profiles/pom.xml +++ b/core/profiles/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 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 069359c37567..b3243ba6c29b 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 @@ -161,6 +161,8 @@ public final class ProfileProperty { public static final String USE_FIPS_ENDPOINT = "use_fips_endpoint"; + public static final String IGNORE_CONFIGURED_ENDPOINT_URLS = "ignore_configured_endpoint_urls"; + public static final String EC2_METADATA_SERVICE_ENDPOINT_MODE = "ec2_metadata_service_endpoint_mode"; public static final String EC2_METADATA_SERVICE_ENDPOINT = "ec2_metadata_service_endpoint"; diff --git a/core/protocols/aws-cbor-protocol/pom.xml b/core/protocols/aws-cbor-protocol/pom.xml index 55e8ff2e3a27..c33885a274b3 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/aws-json-protocol/pom.xml b/core/protocols/aws-json-protocol/pom.xml index 1e1fa2fc2581..fc307546a147 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/aws-query-protocol/pom.xml b/core/protocols/aws-query-protocol/pom.xml index 3f157ce26489..a39e248eb707 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/aws-xml-protocol/pom.xml b/core/protocols/aws-xml-protocol/pom.xml index 138c7147064b..9bf34933e07d 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/pom.xml b/core/protocols/pom.xml index f20d37bc9139..465dff177ace 100644 --- a/core/protocols/pom.xml +++ b/core/protocols/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/protocol-core/pom.xml b/core/protocols/protocol-core/pom.xml index b28ea39d7f92..ea643c2d3ff3 100644 --- a/core/protocols/protocol-core/pom.xml +++ b/core/protocols/protocol-core/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/protocols/smithy-rpcv2-protocol/pom.xml b/core/protocols/smithy-rpcv2-protocol/pom.xml index e78490a8694b..69f1b47f5580 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/core/regions/pom.xml b/core/regions/pom.xml index 9061aa3b0624..a02419eac830 100644 --- a/core/regions/pom.xml +++ b/core/regions/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 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 7dae17709100..8706986929fa 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 @@ -2723,12 +2723,15 @@ "endpoints" : { "ap-northeast-1" : { }, "ap-northeast-2" : { }, + "ap-northeast-3" : { }, "ap-south-1" : { }, "ap-southeast-1" : { }, "ap-southeast-2" : { }, "ap-southeast-5" : { }, "ca-central-1" : { }, + "ca-west-1" : { }, "eu-central-1" : { }, + "eu-central-2" : { }, "eu-south-1" : { }, "eu-south-2" : { }, "eu-west-1" : { }, @@ -2985,6 +2988,7 @@ "ap-southeast-3" : { }, "ap-southeast-4" : { }, "ap-southeast-5" : { }, + "ap-southeast-6" : { }, "ap-southeast-7" : { }, "ca-central-1" : { }, "ca-west-1" : { }, @@ -4144,16 +4148,26 @@ "endpoints" : { "af-south-1" : { }, "ap-east-1" : { }, + "ap-east-2" : { }, "ap-northeast-1" : { }, "ap-northeast-2" : { }, + "ap-northeast-3" : { }, "ap-south-1" : { }, + "ap-south-2" : { }, "ap-southeast-1" : { }, "ap-southeast-2" : { }, + "ap-southeast-3" : { }, + "ap-southeast-4" : { }, "ap-southeast-5" : { }, + "ap-southeast-6" : { }, "ap-southeast-7" : { }, "ca-central-1" : { }, + "ca-west-1" : { }, "eu-central-1" : { }, + "eu-central-2" : { }, "eu-north-1" : { }, + "eu-south-1" : { }, + "eu-south-2" : { }, "eu-west-1" : { }, "eu-west-2" : { }, "eu-west-3" : { }, @@ -4171,8 +4185,10 @@ "deprecated" : true, "hostname" : "cassandra-fips.us-west-2.amazonaws.com" }, + "il-central-1" : { }, "me-central-1" : { }, "me-south-1" : { }, + "mx-central-1" : { }, "sa-east-1" : { }, "us-east-1" : { "variants" : [ { @@ -7598,16 +7614,33 @@ }, "dax" : { "endpoints" : { + "af-south-1" : { }, + "ap-east-1" : { }, + "ap-east-2" : { }, "ap-northeast-1" : { }, + "ap-northeast-2" : { }, + "ap-northeast-3" : { }, "ap-south-1" : { }, + "ap-south-2" : { }, "ap-southeast-1" : { }, "ap-southeast-2" : { }, + "ap-southeast-3" : { }, + "ap-southeast-4" : { }, + "ap-southeast-5" : { }, + "ap-southeast-6" : { }, + "ap-southeast-7" : { }, + "ca-central-1" : { }, + "ca-west-1" : { }, "eu-central-1" : { }, + "eu-central-2" : { }, "eu-north-1" : { }, + "eu-south-1" : { }, "eu-south-2" : { }, "eu-west-1" : { }, "eu-west-2" : { }, "eu-west-3" : { }, + "il-central-1" : { }, + "mx-central-1" : { }, "sa-east-1" : { }, "us-east-1" : { }, "us-east-2" : { }, @@ -8235,6 +8268,7 @@ "endpoints" : { "af-south-1" : { }, "ap-east-1" : { }, + "ap-east-2" : { }, "ap-northeast-1" : { }, "ap-northeast-2" : { }, "ap-northeast-3" : { }, @@ -8244,7 +8278,9 @@ "ap-southeast-2" : { }, "ap-southeast-3" : { }, "ap-southeast-4" : { }, + "ap-southeast-5" : { }, "ap-southeast-6" : { }, + "ap-southeast-7" : { }, "ca-central-1" : { }, "ca-west-1" : { }, "eu-central-1" : { }, @@ -8286,6 +8322,7 @@ "il-central-1" : { }, "me-central-1" : { }, "me-south-1" : { }, + "mx-central-1" : { }, "sa-east-1" : { }, "us-east-1" : { "variants" : [ { @@ -11749,18 +11786,23 @@ "ap-northeast-2" : { }, "ap-northeast-3" : { }, "ap-south-1" : { }, + "ap-south-2" : { }, "ap-southeast-1" : { }, "ap-southeast-2" : { }, + "ap-southeast-3" : { }, "ap-southeast-5" : { }, "ap-southeast-7" : { }, "ca-central-1" : { }, "eu-central-1" : { }, "eu-north-1" : { }, "eu-south-1" : { }, + "eu-south-2" : { }, "eu-west-1" : { }, "eu-west-2" : { }, "eu-west-3" : { }, + "il-central-1" : { }, "me-south-1" : { }, + "mx-central-1" : { }, "sa-east-1" : { }, "us-east-1" : { }, "us-east-2" : { }, @@ -17811,6 +17853,7 @@ }, "omics" : { "endpoints" : { + "ap-northeast-1" : { }, "ap-northeast-2" : { }, "ap-southeast-1" : { "credentialScope" : { @@ -17866,6 +17909,7 @@ "tags" : [ "fips" ] } ] }, + "us-east-2" : { }, "us-west-2" : { "credentialScope" : { "region" : "us-west-2" @@ -17914,6 +17958,7 @@ "eu-south-2" : { }, "eu-west-1" : { }, "eu-west-2" : { }, + "eu-west-3" : { }, "sa-east-1" : { }, "us-east-1" : { }, "us-east-2" : { }, @@ -27596,6 +27641,7 @@ "ap-southeast-2" : { }, "ap-southeast-3" : { }, "ap-southeast-4" : { }, + "ap-southeast-5" : { }, "ca-central-1" : { }, "ca-west-1" : { }, "eu-central-1" : { }, @@ -28710,6 +28756,7 @@ }, "wisdom" : { "endpoints" : { + "af-south-1" : { }, "ap-northeast-1" : { }, "ap-northeast-2" : { }, "ap-southeast-1" : { }, @@ -30246,6 +30293,12 @@ "cn-northwest-1" : { } } }, + "resource-explorer-2" : { + "endpoints" : { + "cn-north-1" : { }, + "cn-northwest-1" : { } + } + }, "resource-groups" : { "endpoints" : { "cn-north-1" : { }, @@ -34359,6 +34412,12 @@ "isRegionalized" : false, "partitionEndpoint" : "aws-us-gov-global" }, + "osis" : { + "endpoints" : { + "us-gov-east-1" : { }, + "us-gov-west-1" : { } + } + }, "outposts" : { "endpoints" : { "fips-us-gov-east-1" : { @@ -36444,6 +36503,12 @@ "us-iso-west-1" : { } } }, + "appstream2" : { + "endpoints" : { + "us-iso-east-1" : { }, + "us-iso-west-1" : { } + } + }, "arc-zonal-shift" : { "endpoints" : { "us-iso-east-1" : { }, @@ -36596,6 +36661,11 @@ } } }, + "compute-optimizer" : { + "endpoints" : { + "us-iso-east-1" : { } + } + }, "config" : { "endpoints" : { "fips-us-iso-east-1" : { @@ -36626,6 +36696,11 @@ } } }, + "cost-optimization-hub" : { + "endpoints" : { + "us-iso-east-1" : { } + } + }, "datapipeline" : { "endpoints" : { "us-iso-east-1" : { } @@ -36866,6 +36941,11 @@ } } }, + "emr-serverless" : { + "endpoints" : { + "us-iso-east-1" : { } + } + }, "es" : { "endpoints" : { "us-iso-east-1" : { }, @@ -36960,7 +37040,8 @@ "protocols" : [ "https" ] }, "endpoints" : { - "us-iso-east-1" : { } + "us-iso-east-1" : { }, + "us-iso-west-1" : { } }, "isRegionalized" : true }, @@ -37776,7 +37857,8 @@ }, "backup" : { "endpoints" : { - "us-isob-east-1" : { } + "us-isob-east-1" : { }, + "us-isob-west-1" : { } } }, "batch" : { @@ -37861,6 +37943,11 @@ "us-isob-west-1" : { } } }, + "compute-optimizer" : { + "endpoints" : { + "us-isob-east-1" : { } + } + }, "config" : { "endpoints" : { "fips-us-isob-east-1" : { @@ -37879,6 +37966,11 @@ "us-isob-west-1" : { } } }, + "cost-optimization-hub" : { + "endpoints" : { + "us-isob-east-1" : { } + } + }, "datasync" : { "endpoints" : { "us-isob-east-1" : { }, @@ -38044,6 +38136,11 @@ "us-isob-west-1" : { } } }, + "emr-serverless" : { + "endpoints" : { + "us-isob-east-1" : { } + } + }, "es" : { "endpoints" : { "us-isob-east-1" : { }, @@ -38523,7 +38620,8 @@ }, "deprecated" : true, "hostname" : "storagegateway-fips.us-isob-east-1.sc2s.sgov.gov" - } + }, + "us-isob-west-1" : { } } }, "streams.dynamodb" : { @@ -39046,6 +39144,11 @@ "eu-isoe-west-1" : { } } }, + "rolesanywhere" : { + "endpoints" : { + "eu-isoe-west-1" : { } + } + }, "route53" : { "endpoints" : { "aws-iso-e-global" : { @@ -40325,6 +40428,11 @@ "eusc-de-east-1" : { } } }, + "emr-serverless" : { + "endpoints" : { + "eusc-de-east-1" : { } + } + }, "entitlement.marketplace" : { "endpoints" : { "eusc-de-east-1" : { } @@ -40507,6 +40615,11 @@ "eusc-de-east-1" : { } } }, + "redshift-serverless" : { + "endpoints" : { + "eusc-de-east-1" : { } + } + }, "resource-groups" : { "endpoints" : { "eusc-de-east-1" : { } diff --git a/core/regions/src/test/java/software/amazon/awssdk/regions/PartitionServiceMetadataTest.java b/core/regions/src/test/java/software/amazon/awssdk/regions/PartitionServiceMetadataTest.java index b6b5e46e95f9..200d4c3a9a6d 100644 --- a/core/regions/src/test/java/software/amazon/awssdk/regions/PartitionServiceMetadataTest.java +++ b/core/regions/src/test/java/software/amazon/awssdk/regions/PartitionServiceMetadataTest.java @@ -16,6 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.net.URI; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -120,6 +121,54 @@ public void servicePartitions_HasNoGlobalEndpoint_ForRegionalServices() { validateHasGlobalEndpointInPartition(AWS_US_GOV_PARTITION_REGIONALIZED_SERVICES, "aws-us-gov", false); } + @Test + public void endpointFor_ResolvesCorrectFipsEndpoint() { + ServiceEndpointKey key = ServiceEndpointKey.builder() + .region(Region.US_EAST_1) + .tags(EndpointTag.FIPS) + .build(); + assertThat(ServiceMetadata.of("s3").endpointFor(key)) + .isEqualTo(URI.create("s3-fips.us-east-1.amazonaws.com")); + } + + @Test + public void endpointFor_ResolvesCorrectDualstackEndpoint() { + ServiceEndpointKey key = ServiceEndpointKey.builder() + .region(Region.US_WEST_2) + .tags(EndpointTag.DUALSTACK) + .build(); + assertThat(ServiceMetadata.of("s3").endpointFor(key)) + .isEqualTo(URI.create("s3.dualstack.us-west-2.amazonaws.com")); + } + + @Test + public void endpointFor_ResolvesGlobalServiceEndpoint() { + ServiceEndpointKey key = ServiceEndpointKey.builder() + .region(Region.AWS_GLOBAL) + .build(); + assertThat(ServiceMetadata.of("iam").endpointFor(key)) + .isEqualTo(URI.create("iam.amazonaws.com")); + } + + @Test + public void endpointFor_ResolvesCorrectFipsDualstackEndpoint() { + ServiceEndpointKey key = ServiceEndpointKey.builder() + .region(Region.US_WEST_2) + .tags(EndpointTag.FIPS, EndpointTag.DUALSTACK) + .build(); + assertThat(ServiceMetadata.of("s3").endpointFor(key)) + .isEqualTo(URI.create("s3-fips.dualstack.us-west-2.amazonaws.com")); + } + + @Test + public void signingRegion_ResolvesCorrectly_ForGlobalService() { + ServiceEndpointKey key = ServiceEndpointKey.builder() + .region(Region.AWS_GLOBAL) + .build(); + assertThat(ServiceMetadata.of("iam").signingRegion(key)) + .isEqualTo(Region.US_EAST_1); + } + private void validateHasGlobalEndpointInPartition(List services, String partition, boolean hasGlobalEndpoint) { services.forEach(s -> assertThat(ServiceMetadata.of(s) .servicePartitions() diff --git a/core/retries-spi/pom.xml b/core/retries-spi/pom.xml index 94d90d9d49f7..6097f9d49654 100644 --- a/core/retries-spi/pom.xml +++ b/core/retries-spi/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -64,5 +64,11 @@ assertj-core test + + + org.mockito + mockito-core + test + diff --git a/core/retries-spi/src/main/java/software/amazon/awssdk/retries/api/RetryStrategy.java b/core/retries-spi/src/main/java/software/amazon/awssdk/retries/api/RetryStrategy.java index 491bab172e65..ce5732977157 100644 --- a/core/retries-spi/src/main/java/software/amazon/awssdk/retries/api/RetryStrategy.java +++ b/core/retries-spi/src/main/java/software/amazon/awssdk/retries/api/RetryStrategy.java @@ -15,9 +15,12 @@ package software.amazon.awssdk.retries.api; +import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.SdkAutoCloseable; import software.amazon.awssdk.utils.builder.SdkBuilder; /** @@ -40,9 +43,9 @@ */ @ThreadSafe @SdkPublicApi -public interface RetryStrategy { +public interface RetryStrategy extends SdkAutoCloseable { /** - * Invoked before the first request attempt. + * Acquire a retry token synchronously. Invoked before the first request attempt. * *

Callers MUST wait for the {@code delay} returned by this call before making the first attempt. Callers that wish to * retry a failed attempt MUST call {@link #refreshRetryToken} before doing so. @@ -55,7 +58,27 @@ public interface RetryStrategy { AcquireInitialTokenResponse acquireInitialToken(AcquireInitialTokenRequest request); /** - * Invoked before each subsequent (non-first) request attempt. + * Acquire a retry token asynchronously. Invoked before the first request attempt. + * + *

Callers MUST wait for the {@code delay} returned by this call before making the first attempt. Callers that wish to + * retry a failed attempt MUST call {@link #refreshRetryToken} before doing so. + * + *

If the attempt was successful, callers MUST call {@link #recordSuccess}. + * + *

The future is completed exceptionally with {@link NullPointerException} if a required parameter is {@code null}. + *

The future is completed exceptionally with {@link TokenAcquisitionFailedException} if a token cannot be acquired. + */ + default CompletableFuture acquireInitialTokenAsync(AcquireInitialTokenRequest request) { + try { + AcquireInitialTokenResponse response = acquireInitialToken(request); + return CompletableFuture.completedFuture(response); + } catch (Throwable t) { + return CompletableFutureUtils.failedFuture(t); + } + } + + /** + * Refresh a retry token synchronously. Invoked before each subsequent (non-first) request attempt. * *

Callers MUST wait for the {@code delay} returned by this call before making the next attempt. If the next attempt * fails, callers MUST re-call {@link #refreshRetryToken} before attempting another retry. This call invalidates the provided @@ -70,6 +93,29 @@ public interface RetryStrategy { */ RefreshRetryTokenResponse refreshRetryToken(RefreshRetryTokenRequest request); + /** + * Refresh a retry token asynchronously. Invoked before each subsequent (non-first) request attempt. + * + *

Callers MUST wait for the {@code delay} returned by this call before making the next attempt. If the next attempt + * fails, callers MUST re-call {@link #refreshRetryToken} before attempting another retry. This call invalidates the provided + * token, and returns a new one. Callers MUST use the new token. + * + *

If the attempt was successful, callers MUST call {@link #recordSuccess}. + * + *

The future is completed exceptionally with {@link NullPointerException} if a required parameter is not specified. + *

The future is completed exceptionally with {@link IllegalArgumentException} if the provided token was not issued by + * this strategy or the provided token was already used for a previous refresh or success call. + *

The future is completed exceptionally with {@link TokenAcquisitionFailedException} if a token cannot be acquired. + */ + default CompletableFuture refreshRetryTokenAsync(RefreshRetryTokenRequest request) { + try { + RefreshRetryTokenResponse response = refreshRetryToken(request); + return CompletableFuture.completedFuture(response); + } catch (Throwable t) { + return CompletableFutureUtils.failedFuture(t); + } + } + /** * Invoked after an attempt succeeds. * @@ -102,6 +148,10 @@ default boolean useClientDefaults() { */ Builder toBuilder(); + @Override + default void close() { + } + /** * Builder to create immutable instances of {@link RetryStrategy}. */ diff --git a/core/retries-spi/src/test/java/software/amazon/awssdk/retries/api/RetryStrategyTest.java b/core/retries-spi/src/test/java/software/amazon/awssdk/retries/api/RetryStrategyTest.java new file mode 100644 index 000000000000..3e419f1ab8aa --- /dev/null +++ b/core/retries-spi/src/test/java/software/amazon/awssdk/retries/api/RetryStrategyTest.java @@ -0,0 +1,61 @@ +/* + * 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.retries.api; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.Test; + +public class RetryStrategyTest { + @Test + void acquireInitialTokenAsync_syncThrows_reportedThroughFuture() { + RetryStrategy retryStrategy = mock(RetryStrategy.class); + + when(retryStrategy.acquireInitialTokenAsync(any(AcquireInitialTokenRequest.class))) + .thenCallRealMethod(); + + RuntimeException t = new RuntimeException("oops"); + when(retryStrategy.acquireInitialToken(any(AcquireInitialTokenRequest.class))) + .thenThrow(t); + + assertThatThrownBy(() -> retryStrategy.acquireInitialTokenAsync(AcquireInitialTokenRequest.create("test")).join()) + .hasRootCause(t); + } + + @Test + void refreshRetryTokenAsync_syncThrows_reportedThroughFuture() { + RetryStrategy retryStrategy = mock(RetryStrategy.class); + + when(retryStrategy.refreshRetryTokenAsync(any(RefreshRetryTokenRequest.class))) + .thenCallRealMethod(); + + RuntimeException t = new RuntimeException("oops"); + when(retryStrategy.refreshRetryToken(any(RefreshRetryTokenRequest.class))) + .thenThrow(t); + + RetryToken token = mock(RetryToken.class); + RefreshRetryTokenRequest request = RefreshRetryTokenRequest.builder() + .token(token) + .failure(new RuntimeException("failure")) + .build(); + + assertThatThrownBy(() -> retryStrategy.refreshRetryTokenAsync(request).join()) + .hasRootCause(t); + } +} diff --git a/core/retries/pom.xml b/core/retries/pom.xml index a11671fa42ae..c05814587b68 100644 --- a/core/retries/pom.xml +++ b/core/retries/pom.xml @@ -21,7 +21,7 @@ core software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -70,5 +70,10 @@ assertj-core test + + org.mockito + mockito-core + test + diff --git a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/BaseRetryStrategy.java b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/BaseRetryStrategy.java index dfda06093ab3..6c6551dc68e2 100644 --- a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/BaseRetryStrategy.java +++ b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/BaseRetryStrategy.java @@ -39,6 +39,7 @@ import software.amazon.awssdk.retries.internal.circuitbreaker.TokenBucket; import software.amazon.awssdk.retries.internal.circuitbreaker.TokenBucketStore; import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.ToString; import software.amazon.awssdk.utils.Validate; @@ -86,7 +87,7 @@ public abstract class BaseRetryStrategy implements DefaultAwareRetryStrategy { * @see RetryStrategy#acquireInitialToken(AcquireInitialTokenRequest) */ @Override - public final AcquireInitialTokenResponse acquireInitialToken(AcquireInitialTokenRequest request) { + public AcquireInitialTokenResponse acquireInitialToken(AcquireInitialTokenRequest request) { logAcquireInitialToken(request); DefaultRetryToken token = DefaultRetryToken.builder().scope(request.scope()).build(); return AcquireInitialTokenResponse.create(token, computeInitialBackoff(request)); @@ -98,7 +99,20 @@ public final AcquireInitialTokenResponse acquireInitialToken(AcquireInitialToken * @see RetryStrategy#refreshRetryToken(RefreshRetryTokenRequest) */ @Override - public final RefreshRetryTokenResponse refreshRetryToken(RefreshRetryTokenRequest request) { + public RefreshRetryTokenResponse refreshRetryToken(RefreshRetryTokenRequest request) { + Pair refreshedToken = refreshTokenOrThrow(request); + Duration backoff = computeBackoff(request, refreshedToken.left()); + + logRefreshTokenSuccess(refreshedToken.left(), refreshedToken.right(), backoff); + return RefreshRetryTokenResponseImpl.create(refreshedToken.left(), backoff); + } + + /** + * Attempt to refresh the token for a retry or throws {@link TokenAcquisitionFailedException} if unable to do so. + * + * @return A pair of the refreshed token and the successful acquire response from the token bucket. + */ + protected Pair refreshTokenOrThrow(RefreshRetryTokenRequest request) { DefaultRetryToken token = asDefaultRetryToken(request.token()); // Check if we meet the preconditions needed for retrying. These will throw if the expected condition is not meet. @@ -115,12 +129,8 @@ public final RefreshRetryTokenResponse refreshRetryToken(RefreshRetryTokenReques // All the conditions required to retry were meet, update the internal state before retrying. updateStateForRetry(request); - // Refresh the retry token and compute the backoff delay. - DefaultRetryToken refreshedToken = refreshToken(request, acquireResponse); - Duration backoff = computeBackoff(request, refreshedToken); - - logRefreshTokenSuccess(refreshedToken, acquireResponse, backoff); - return RefreshRetryTokenResponseImpl.create(refreshedToken, backoff); + // Refresh the retry token + return Pair.of(refreshToken(request, acquireResponse), acquireResponse); } /** @@ -335,7 +345,7 @@ private String acquisitionFailedMessage(AcquireResponse response) { response.maxCapacity()); } - private void logAcquireInitialToken(AcquireInitialTokenRequest request) { + protected void logAcquireInitialToken(AcquireInitialTokenRequest request) { // Request attempt 1 token acquired (backoff: 0ms, cost: 0, capacity: 500/500) TokenBucket tokenBucket = tokenBucketStore.tokenBucketForScope(request.scope()); log.debug(() -> String.format("Request attempt 1 token acquired " @@ -343,7 +353,7 @@ private void logAcquireInitialToken(AcquireInitialTokenRequest request) { tokenBucket.currentCapacity(), tokenBucket.maxCapacity())); } - private void logRefreshTokenSuccess(DefaultRetryToken token, AcquireResponse acquireResponse, Duration delay) { + protected void logRefreshTokenSuccess(DefaultRetryToken token, AcquireResponse acquireResponse, Duration delay) { log.debug(() -> String.format("Request attempt %d token acquired " + "(backoff: %dms, cost: %d, capacity: %d/%d)", token.attempt(), delay.toMillis(), diff --git a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAdaptiveRetryStrategy.java b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAdaptiveRetryStrategy.java index c52c7859526f..685bba2d5e46 100644 --- a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAdaptiveRetryStrategy.java +++ b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/DefaultAdaptiveRetryStrategy.java @@ -16,22 +16,27 @@ package software.amazon.awssdk.retries.internal; import java.time.Duration; +import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; import software.amazon.awssdk.annotations.SdkInternalApi; 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.BackoffStrategy; import software.amazon.awssdk.retries.api.RefreshRetryTokenRequest; +import software.amazon.awssdk.retries.api.RefreshRetryTokenResponse; +import software.amazon.awssdk.retries.internal.circuitbreaker.AcquireResponse; import software.amazon.awssdk.retries.internal.circuitbreaker.TokenBucketStore; import software.amazon.awssdk.retries.internal.ratelimiter.RateLimiterTokenBucket; import software.amazon.awssdk.retries.internal.ratelimiter.RateLimiterTokenBucketStore; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.Validate; @SdkInternalApi public final class DefaultAdaptiveRetryStrategy extends BaseRetryStrategy implements AdaptiveRetryStrategy { - private static final Logger LOG = Logger.loggerFor(DefaultAdaptiveRetryStrategy.class); private final RateLimiterTokenBucketStore rateLimiterTokenBucketStore; @@ -42,16 +47,53 @@ public final class DefaultAdaptiveRetryStrategy } @Override - protected Duration computeInitialBackoff(AcquireInitialTokenRequest request) { + public AcquireInitialTokenResponse acquireInitialToken(AcquireInitialTokenRequest request) { + return CompletableFutureUtils.joinLikeSync(acquireInitialTokenAsync(request)); + } + + @Override + public RefreshRetryTokenResponse refreshRetryToken(RefreshRetryTokenRequest request) { + return CompletableFutureUtils.joinLikeSync(refreshRetryTokenAsync(request)); + } + + @Override + public CompletableFuture acquireInitialTokenAsync(AcquireInitialTokenRequest request) { + logAcquireInitialToken(request); RateLimiterTokenBucket bucket = rateLimiterTokenBucketStore.tokenBucketForScope(request.scope()); - return bucket.tryAcquire().delay(); + CompletableFuture acquireResult = bucket.acquireAsync(); + + return acquireResult.thenApply(r -> { + DefaultRetryToken token = DefaultRetryToken.builder().scope(request.scope()).build(); + return AcquireInitialTokenResponse.create(token, Duration.ZERO); + }); } @Override - protected Duration computeBackoff(RefreshRetryTokenRequest request, DefaultRetryToken token) { - Duration backoff = super.computeBackoff(request, token); + public CompletableFuture refreshRetryTokenAsync(RefreshRetryTokenRequest request) { + DefaultRetryToken token = (DefaultRetryToken) request.token(); + Pair refreshResult; + try { + refreshResult = refreshTokenOrThrow(request); + } catch (Throwable t) { + return CompletableFutureUtils.failedFuture(t); + } + + DefaultRetryToken refreshedToken = refreshResult.left(); + AcquireResponse acquireResponse = refreshResult.right(); RateLimiterTokenBucket bucket = rateLimiterTokenBucketStore.tokenBucketForScope(token.scope()); - return backoff.plus(bucket.tryAcquire().delay()); + CompletableFuture acquireResult = bucket.acquireAsync(); + return acquireResult.thenApply(r -> { + // Note: This is the backoff imposed standard retry strategy, *not* the rate limiter. This must still be honored by + // the caller before sending the request. + Duration backoff = computeBackoff(request, refreshedToken); + logRefreshTokenSuccess(refreshedToken, acquireResponse, backoff); + return RefreshRetryTokenResponse.create(refreshedToken, backoff); + }); + } + + @Override + public void close() { + rateLimiterTokenBucketStore.close(); } @Override diff --git a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucket.java b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucket.java index 2d8743af9924..86a718f18906 100644 --- a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucket.java +++ b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucket.java @@ -16,42 +16,150 @@ package software.amazon.awssdk.retries.internal.ratelimiter; import java.time.Duration; -import java.util.concurrent.atomic.AtomicReference; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.function.Function; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.SdkAutoCloseable; /** * The {@link RateLimiterTokenBucket} keeps track of past throttling responses and adapts to slow down the send rate to adapt to - * the service. It does this by suggesting a delay amount as result of a {@link #tryAcquire()} call. Callers must update its - * internal state by calling {@link #updateRateAfterThrottling()} when getting a throttling response or - * {@link #updateRateAfterSuccess()} when getting successful response. + * the service. It does this by delaying the completion of the future returned by {@link #acquireAsync()} until the requested + * capacity is available. Callers must update its internal state by calling {@link #updateRateAfterThrottling()} when getting a + * throttling response or {@link #updateRateAfterSuccess()} when getting successful response. * - *

This class is thread-safe, its internal current state is kept in the inner class {@link PersistentState} which is stored - * using an {@link AtomicReference}. This class is converted to {@link TransientState} when the state needs to be mutated and - * converted back to a {@link PersistentState} and stored using {@link AtomicReference#compareAndSet(Object, Object)}. + *

This class is thread-safe. * *

The algorithm used is adapted from the network congestion avoidance algorithm * CUBIC. */ @SdkInternalApi -public class RateLimiterTokenBucket { - private final AtomicReference stateReference; +@ThreadSafe +public class RateLimiterTokenBucket implements SdkAutoCloseable { + // Thread used for capacity waiting and notifying. + private final ScheduledExecutorService scheduler; + + // Protect access to other members below + private final Object lock = new Object(); + private final RateLimiterClock clock; + // the collection of futures returned to threads currently waiting for capacity. + // Futures are completed in FIFO order. + // The size of this equal to the number of threads concurrently accessing this bucket. + private final Deque> waiting = new ArrayDeque<>(); + private PersistentState state; + private boolean open = true; + private boolean notifierRunning = false; - RateLimiterTokenBucket(RateLimiterClock clock) { + RateLimiterTokenBucket(RateLimiterClock clock, ScheduledExecutorService scheduler) { this.clock = clock; - this.stateReference = new AtomicReference<>(new PersistentState()); + this.scheduler = scheduler; + this.state = new PersistentState(); + } + + @Override + public void close() { + doClose(null); + } + + private void doClose(Throwable cause) { + synchronized (lock) { + open = false; + IllegalStateException closedException = new IllegalStateException("Rate limiter bucket is closed", cause); + while (true) { + CompletableFuture w = waiting.poll(); + if (w == null) { + break; + } + w.completeExceptionally(closedException); + } + } } /** - * Acquire tokens from the bucket. If the bucket contains enough capacity to satisfy the request, this method will return in - * {@link RateLimiterAcquireResponse#delay()} a {@link Duration#ZERO} value, otherwise it will return the amount of time the - * callers need to wait until enough tokens are refilled. + * Acquire a token from the bucket. + * + * @return A future that is completed when the requested amount is acquired from this bucket. */ - public RateLimiterAcquireResponse tryAcquire() { - StateUpdate update = updateState(ts -> ts.tokenBucketAcquire(clock, 1.0)); - return RateLimiterAcquireResponse.create(update.result); + public CompletableFuture acquireAsync() { + synchronized (lock) { + if (!open) { + return CompletableFutureUtils.failedFuture(new IllegalStateException("Rate limiter bucket is closed")); + } + + // fast path and avoid scheduling in the executor if throttling isn't enabled. + if (!state.enabled) { + return CompletableFuture.completedFuture(null); + } + + CompletableFuture future = new CompletableFuture<>(); + waiting.add(future); + if (!notifierRunning) { + notifierRunning = scheduleOrClose(this::doNotify, Duration.ZERO); + } + return future; + } + } + + + @SdkTestInternalApi + Deque> waiting() { + return waiting; + } + + @SdkTestInternalApi + boolean isClosed() { + return !open; + } + + private void doNotify() { + while (true) { + CompletableFuture w; + synchronized (lock) { + w = waiting.poll(); + if (w == null) { + notifierRunning = false; + return; + } + + TransientState.AcquireResult acquireResult = updateState(t -> t.tokenBucketAcquire(clock, 1.0)).result; + + // Not enough capacity. Try again later when enough time has + // passed to refill the bucket at the current rate. + if (!acquireResult.isSuccessful()) { + waiting.push(w); + notifierRunning = scheduleOrClose(this::doNotify, acquireResult.refillWait()); + return; + } + + } + // Acquire was successful, signal the waiting thread. + w.complete(null); + } + } + + private void schedule(Runnable command, Duration d) { + scheduler.schedule(command, d.toMillis(), TimeUnit.MILLISECONDS); + } + + /** + * @return true if schedule was successful, false otherwise. If the schedule failed, this bucket will be closed. + */ + private boolean scheduleOrClose(Runnable command, Duration d) { + try { + schedule(command, d); + return true; + } catch (Throwable t) { + doClose(t); + } + return false; } /** @@ -88,24 +196,15 @@ private StateUpdate consumeState(Consumer mutator) { } /** - * Converts the stored persistent state into a transient one and transforms it using the provided function. The provided - * function is expected to update the transient state in-place and return a value that will be returned to the caller in the - * {@link StateUpdate#result} field. The mutated transient value is converted back to a persistent one and stored in the - * atomic reference if no changes were made in-between. If another thread changes the value in-between, the operation is - * retried until succeeded. + * Converts the stored persistent state into a transient one and transforms it using the provided function. */ private StateUpdate updateState(Function mutator) { - PersistentState current; - PersistentState updated; - T result; - do { - current = stateReference.get(); - TransientState transientState = current.toTransient(); - result = mutator.apply(transientState); - updated = transientState.toPersistent(); - } while (!stateReference.compareAndSet(current, updated)); - - return new StateUpdate<>(updated, result); + synchronized (lock) { + TransientState transientState = state.toTransient(); + T result = mutator.apply(transientState); + state = transientState.toPersistent(); + return new StateUpdate<>(state, result); + } } static class StateUpdate { @@ -163,17 +262,38 @@ PersistentState toPersistent() { * a {@link Duration#ZERO} value, otherwise it will return the amount of time the callers need to wait until enough tokens * are refilled. */ - Duration tokenBucketAcquire(RateLimiterClock clock, double amount) { + AcquireResult tokenBucketAcquire(RateLimiterClock clock, double amount) { if (!this.enabled) { - return Duration.ZERO; + return new AcquireResult(true, Duration.ZERO); } refill(clock); - double waitTime = 0.0; if (this.currentCapacity < amount) { - waitTime = (amount - this.currentCapacity) / this.fillRate; + double diff = amount - currentCapacity; + double waitTime = diff / this.fillRate; + double waitTimeMs = waitTime * 1_000.0; + Duration duration = Duration.ofMillis((long) Math.ceil(waitTimeMs)); + return new AcquireResult(false, duration); } this.currentCapacity -= amount; - return Duration.ofNanos((long) (waitTime * 1_000_000_000.0)); + return new AcquireResult(true, Duration.ZERO); + } + + private static class AcquireResult { + final boolean successful; + final Duration refillWait; + + AcquireResult(boolean successful, Duration refillWait) { + this.successful = successful; + this.refillWait = refillWait; + } + + boolean isSuccessful() { + return successful; + } + + Duration refillWait() { + return refillWait; + } } /** diff --git a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStore.java b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStore.java index 303e6d61d7f5..a2a5f2f966ed 100644 --- a/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStore.java +++ b/core/retries/src/main/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStore.java @@ -15,8 +15,13 @@ package software.amazon.awssdk.retries.internal.ratelimiter; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.annotations.ToBuilderIgnoreField; +import software.amazon.awssdk.utils.SdkAutoCloseable; +import software.amazon.awssdk.utils.ThreadFactoryBuilder; import software.amazon.awssdk.utils.Validate; import software.amazon.awssdk.utils.builder.CopyableBuilder; import software.amazon.awssdk.utils.builder.ToCopyableBuilder; @@ -27,23 +32,59 @@ */ @SdkInternalApi public final class RateLimiterTokenBucketStore - implements ToCopyableBuilder { + implements ToCopyableBuilder, SdkAutoCloseable { private static final int MAX_ENTRIES = 128; + private static final String THREAD_NAME_PREFIX = "sdk-adaptive-rate-limiter-"; + private static final RateLimiterClock DEFAULT_CLOCK = new SystemClock(); private final LruCache scopeToTokenBucket; private final RateLimiterClock clock; + private final ScheduledExecutorService scheduler; + private final boolean closeScheduler; private RateLimiterTokenBucketStore(Builder builder) { - this.clock = Validate.paramNotNull(builder.clock, "clock"); - this.scopeToTokenBucket = LruCache.builder(x -> new RateLimiterTokenBucket(clock)) + this(builder.clock, + resolveScheduler(builder), + builder.scheduler == null); + } + + private RateLimiterTokenBucketStore(RateLimiterClock clock, ScheduledExecutorService scheduler, boolean closeScheduler) { + this.clock = Validate.paramNotNull(clock, "clock"); + this.scheduler = Validate.paramNotNull(scheduler, "scheduler"); + this.closeScheduler = closeScheduler; + this.scopeToTokenBucket = LruCache.builder( + x -> new RateLimiterTokenBucket(clock, scheduler)) .maxSize(MAX_ENTRIES) .build(); } + @Override + public void close() { + scopeToTokenBucket.evictAll(); + if (closeScheduler) { + scheduler.shutdownNow(); + } + } + public RateLimiterTokenBucket tokenBucketForScope(String scope) { return scopeToTokenBucket.get(scope); } + @SdkTestInternalApi + ScheduledExecutorService scheduler() { + return scheduler; + } + + private static ScheduledExecutorService resolveScheduler(Builder b) { + if (b.scheduler != null) { + return b.scheduler; + } + return Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder() + .daemonThreads(true) + .threadNamePrefix(THREAD_NAME_PREFIX) + .build()); + } + @Override @ToBuilderIgnoreField("scopeToTokenBucket") public Builder toBuilder() { @@ -56,6 +97,7 @@ public static RateLimiterTokenBucketStore.Builder builder() { public static class Builder implements CopyableBuilder { private RateLimiterClock clock; + private ScheduledExecutorService scheduler; Builder() { this.clock = DEFAULT_CLOCK; @@ -63,6 +105,7 @@ public static class Builder implements CopyableBuilderwill not be closed when {@link #close() closing} this bucket store. + * + * @return This object for method chaining. + */ + public Builder scheduler(ScheduledExecutorService scheduler) { + this.scheduler = scheduler; + return this; + } + @Override public RateLimiterTokenBucketStore build() { return new RateLimiterTokenBucketStore(this); diff --git a/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStoreTest.java b/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStoreTest.java new file mode 100644 index 000000000000..b915045e1b5a --- /dev/null +++ b/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketStoreTest.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.retries.internal.ratelimiter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledExecutorService; +import org.junit.jupiter.api.Test; + +public class RateLimiterTokenBucketStoreTest { + @Test + void close_schedulerProvided_schedulerNotClosed() { + ScheduledExecutorService scheduler = mock(ScheduledExecutorService.class); + RateLimiterTokenBucketStore store = RateLimiterTokenBucketStore.builder() + .clock(new SystemClock()) + .scheduler(scheduler) + .build(); + + store.close(); + + verify(scheduler, never()).shutdownNow(); + verify(scheduler, never()).shutdown(); + } + + @Test + void close_schedulerNotProvidedOnBuilder_schedulerClosed() { + RateLimiterTokenBucketStore store = RateLimiterTokenBucketStore.builder() + .clock(new SystemClock()) + .build(); + + store.close(); + + assertThat(store.scheduler().isShutdown()).isTrue(); + } + + @Test + void close_closesAllCacheEntries() { + int entries = 64; + List buckets = new ArrayList<>(entries); + + ScheduledExecutorService scheduler = mock(ScheduledExecutorService.class); + RateLimiterTokenBucketStore store = RateLimiterTokenBucketStore.builder() + .clock(new SystemClock()) + .scheduler(scheduler) + .build(); + + List> futures = new ArrayList<>(entries); + + for (int i = 0; i < entries; ++i) { + RateLimiterTokenBucket bucket = store.tokenBucketForScope(Integer.toString(i)); + buckets.add(bucket); + + // enable throttling so futures from acquireAsync get queued + bucket.updateRateAfterThrottling(); + futures.add(bucket.acquireAsync()); + } + + store.close(); + + // New acquires from the closed bucket should fail + assertThat(buckets).allSatisfy(b -> assertThatThrownBy(b.acquireAsync()::join) + .hasMessageContaining("Rate limiter bucket is closed")); + + // All pending futures should be failed + assertThat(futures).allSatisfy(cf -> assertThatThrownBy(cf::join) + .hasMessageContaining("Rate limiter bucket is closed")); + } +} diff --git a/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketTest.java b/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketTest.java index 14021ebde812..806826a20d07 100644 --- a/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketTest.java +++ b/core/retries/src/test/java/software/amazon/awssdk/retries/internal/ratelimiter/RateLimiterTokenBucketTest.java @@ -16,44 +16,206 @@ package software.amazon.awssdk.retries.internal.ratelimiter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.within; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.Collection; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class RateLimiterTokenBucketTest { - private static MutableClock clock = null; - private static RateLimiterTokenBucket tokenBucket = null; private static final double EPSILON = 0.0001; + private MutableClock clock = null; + private ScheduledExecutorService scheduler = null; + private RateLimiterTokenBucket tokenBucket = null; - @BeforeAll - static void setup() { + @BeforeEach + void setup() { clock = new MutableClock(); - tokenBucket = new RateLimiterTokenBucket(clock); + scheduler = mock(ScheduledExecutorService.class); + tokenBucket = new RateLimiterTokenBucket(clock, scheduler); } - @ParameterizedTest - @MethodSource("parameters") - void testCase(TestCase testCase) { + @Test + void acquireAsync_bucketClosed_futureCompletedExceptionally() { + tokenBucket.close(); + CompletableFuture f = tokenBucket.acquireAsync(); + assertThatThrownBy(f::join).satisfies(t -> { + Throwable cause = t.getCause(); + assertThat(cause).isExactlyInstanceOf(IllegalStateException.class); + assertThat(cause).hasMessage("Rate limiter bucket is closed"); + }); + } + + @Test + void acquireAsync_notEnabled_doesNotScheduleTask() { + CompletableFuture f = tokenBucket.acquireAsync(); + assertThat(f).isCompleted(); + verifyNoInteractions(scheduler); + } + + @Test + void acquireAsync_enabled_schedulesTask() { + tokenBucket.updateRateAfterThrottling(); + + tokenBucket.acquireAsync(); + verify(scheduler).schedule(any(Runnable.class), anyLong(), any(TimeUnit.class)); + } + + + @Test + void acquireAsync_scheduleFails_completesFutureExceptionally() { + tokenBucket.updateRateAfterThrottling(); + + doThrow(new RejectedExecutionException("no")).when(scheduler).schedule(any(Runnable.class), + anyLong(), + any(TimeUnit.class)); + + CompletableFuture f = tokenBucket.acquireAsync(); + assertThatThrownBy(f::join).satisfies(t -> { + Throwable cause = t.getCause(); + assertThat(cause).hasMessage("Rate limiter bucket is closed"); + }); + } + + @Test + void acquireAsync_scheduleFails_futureNotInWaitingDeque() { + tokenBucket.updateRateAfterThrottling(); + + doThrow(new RejectedExecutionException("no")).when(scheduler).schedule(any(Runnable.class), + anyLong(), + any(TimeUnit.class)); + + CompletableFuture f = tokenBucket.acquireAsync(); + assertThat(f).isCompletedExceptionally(); + assertThat(tokenBucket.waiting()).isEmpty(); + } + + @Test + void acquireAsync_scheduleFails_closesBucket() { + tokenBucket.updateRateAfterThrottling(); + + doThrow(new RejectedExecutionException("no")).when(scheduler).schedule(any(Runnable.class), + anyLong(), + any(TimeUnit.class)); + + CompletableFuture f = tokenBucket.acquireAsync(); + assertThat(f).isCompletedExceptionally(); + assertThat(tokenBucket.isClosed()).isTrue(); + } + + @Test + void close_completesAllPendingFutures() { + // enable throttling so futures actually get queued instead of being completed immediately + tokenBucket.updateRateAfterThrottling(); + + List> futures = IntStream.range(0, 10) + .mapToObj(i -> tokenBucket.acquireAsync()) + .collect(Collectors.toList()); + + tokenBucket.close(); + + assertThat(futures).allSatisfy(f -> { + assertThatThrownBy(f::join).satisfies(t -> { + Throwable cause = t.getCause(); + assertThat(cause).isExactlyInstanceOf(IllegalStateException.class); + assertThat(cause).hasMessage("Rate limiter bucket is closed"); + }); + }); + + assertThat(tokenBucket.waiting()).isEmpty(); + } + + @Test + void close_doesShutDownExecutor() { + tokenBucket.close(); + verifyNoInteractions(scheduler); + } + + @Test + void doNotify_scheduleRejected_failsFuture() { + tokenBucket.updateRateAfterThrottling(); + + // Empty bucket at default rate of 0.5 tokens per second should be 2seconds + when(scheduler.schedule(any(Runnable.class), eq(2000L), eq(TimeUnit.MILLISECONDS))) + .thenThrow(new RejectedExecutionException("no")); + + // 0L is the initial schedule from acquireAsync, capture the doNotify schedule and execute that. + when(scheduler.schedule(any(Runnable.class), eq(0L), any(TimeUnit.class))).thenAnswer(i -> { + Runnable r = i.getArgument(0); + r.run(); + return null; + }); + + tokenBucket.acquireAsync(); + assertThat(tokenBucket.isClosed()).isTrue(); + } + + @Test + void doNotify_scheduleRejected_closesBucket() { + tokenBucket.updateRateAfterThrottling(); + + // Empty bucket at default rate of 0.5 tokens per second should be 2seconds + when(scheduler.schedule(any(Runnable.class), eq(2000L), eq(TimeUnit.MILLISECONDS))) + .thenThrow(new RejectedExecutionException("no")); + + // 0L is the initial schedule from acquireAsync, capture the doNotify schedule and execute that. + when(scheduler.schedule(any(Runnable.class), eq(0L), any(TimeUnit.class))).thenAnswer(i -> { + Runnable r = i.getArgument(0); + r.run(); + return null; + }); + + CompletableFuture future = tokenBucket.acquireAsync(); + assertThatThrownBy(future::join).hasRootCauseInstanceOf(RejectedExecutionException.class); + assertThat(tokenBucket.isClosed()).isTrue(); + } + + @Test + void sendingRateEndToEndTest() { + for (TestCase sendingRateTestCase : sendingRateTestCases()) { + assertSendingRateTestCase(sendingRateTestCase); + } + } + + void assertSendingRateTestCase(TestCase testCase) { clock.setCurrent(testCase.givenTimestamp); RateLimiterUpdateResponse res; - tokenBucket.tryAcquire(); + if (testCase.throttleResponse) { res = tokenBucket.updateRateAfterThrottling(); } else { res = tokenBucket.updateRateAfterSuccess(); } double measuredTxRate = res.measuredTxRate(); - assertThat(measuredTxRate).isCloseTo(testCase.expectMeasuredTxRate, within(EPSILON)); + assertThat(measuredTxRate) + .as("%s: Measured TX rate", testCase) + .isCloseTo(testCase.expectMeasuredTxRate, within(EPSILON)); double fillRate = res.fillRate(); - assertThat(fillRate).isCloseTo(testCase.expectFillRate, within(EPSILON)); + assertThat(fillRate) + .as("%s: Fill rate", testCase) + .isCloseTo(testCase.expectFillRate, within(EPSILON)); } - - static Collection parameters() { + static Collection sendingRateTestCases() { + // Note: Test cases are not independent. Each case depends on the state of the bucket being correctly updated from the + // previous test. return Arrays.asList( new TestCase() .givenSuccessResponse() @@ -174,6 +336,15 @@ TestCase expectFillRate(double expectFillRate) { return this; } + @Override + public String toString() { + return "TestCase{" + + "throttleResponse=" + throttleResponse + + ", givenTimestamp=" + givenTimestamp + + ", expectMeasuredTxRate=" + expectMeasuredTxRate + + ", expectFillRate=" + expectFillRate + + '}'; + } } static class MutableClock implements RateLimiterClock { diff --git a/core/sdk-core/pom.xml b/core/sdk-core/pom.xml index 335db51f207f..8e3e0b803dd5 100644 --- a/core/sdk-core/pom.xml +++ b/core/sdk-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk core - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sdk-core AWS Java SDK :: SDK Core @@ -106,12 +106,6 @@ reactive-streams - - software.amazon.awssdk - apache-client - ${awsjavasdk.version} - test - org.junit.jupiter junit-jupiter @@ -193,11 +187,6 @@ ${awsjavasdk.version} test - - org.reactivestreams - reactive-streams-tck - test - com.google.jimfs jimfs @@ -218,12 +207,6 @@ hamcrest-core test - - software.amazon.awssdk - netty-nio-client - ${awsjavasdk.version} - test - io.reactivex.rxjava2 rxjava @@ -232,33 +215,6 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.version} - - - - junit - false - - - 1 - - - - org.apache.maven.surefire - surefire-junit-platform - ${maven.surefire.version} - - - org.apache.maven.surefire - surefire-testng - ${maven.surefire.version} - - - org.codehaus.mojo build-helper-maven-plugin @@ -294,6 +250,20 @@ + + com.github.siom79.japicmp + japicmp-maven-plugin + + + + + software.amazon.awssdk.core.spi.identity.AuthSchemeOptionsResolver#resolve(software.amazon.awssdk.core.SdkRequest) + + + + diff --git a/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/AmazonHttpClientSslHandshakeTimeoutTest.java b/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/AmazonHttpClientSslHandshakeTimeoutTest.java deleted file mode 100644 index 3b82be2be2c8..000000000000 --- a/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/AmazonHttpClientSslHandshakeTimeoutTest.java +++ /dev/null @@ -1,81 +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.http; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils.executionContext; -import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; - -import java.io.IOException; -import java.time.Duration; - -import org.junit.Test; - -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.retries.DefaultRetryStrategy; -import utils.HttpTestUtils; - -/** - * This test is to verify that the apache-httpclient library has fixed the bug where socket timeout configuration is - * incorrectly ignored during SSL handshake. This test is expected to hang (and fail after the junit timeout) if run - * against the problematic httpclient version (e.g. 4.3). - * - * @link https://issues.apache.org/jira/browse/HTTPCLIENT-1478 - */ -public class AmazonHttpClientSslHandshakeTimeoutTest extends UnresponsiveMockServerTestBase { - - private static final Duration CLIENT_SOCKET_TO = Duration.ofSeconds(1); - - @Test(timeout = 60 * 1000) - public void testSslHandshakeTimeout() { - AmazonSyncHttpClient httpClient = HttpTestUtils.testClientBuilder() - .retryStrategy(DefaultRetryStrategy.doNotRetry()) - .httpClient(ApacheHttpClient.builder() - .socketTimeout(CLIENT_SOCKET_TO) - .build()) - .build(); - - System.out.println("Sending request to localhost..."); - - try { - SdkHttpFullRequest request = server.configureHttpsEndpoint(SdkHttpFullRequest.builder()) - .method(SdkHttpMethod.GET) - .build(); - httpClient.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext(request)) - .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); - fail("Client-side socket read timeout is expected!"); - - } catch (SdkClientException e) { - e.printStackTrace(); - /** - * Http client catches the SocketTimeoutException and throws a - * ConnectTimeoutException. - * {@link DefaultHttpClientConnectionOperator#connect(ManagedHttpClientConnection, HttpHost, - * InetSocketAddress, int, SocketConfig, HttpContext)} - */ - assertThat(e).hasCauseInstanceOf(IOException.class); - } - } -} diff --git a/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/ConnectionPoolMaxConnectionsIntegrationTest.java b/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/ConnectionPoolMaxConnectionsIntegrationTest.java deleted file mode 100644 index 942b6c957820..000000000000 --- a/core/sdk-core/src/it/java/software/amazon/awssdk/core/http/ConnectionPoolMaxConnectionsIntegrationTest.java +++ /dev/null @@ -1,91 +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.http; - -import static software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils.executionContext; -import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; - -import java.time.Duration; - -import org.apache.http.conn.ConnectionPoolTimeoutException; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.core.http.server.MockServer; -import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.response.EmptySdkResponseHandler; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.retries.DefaultRetryStrategy; -import utils.HttpTestUtils; - -public class ConnectionPoolMaxConnectionsIntegrationTest { - - private static MockServer server; - - @BeforeClass - public static void setup() { - server = MockServer.createMockServer(MockServer.ServerBehavior.OVERLOADED); - server.startServer(); - } - - @AfterClass - public static void tearDown() { - if (server != null) { - server.stopServer(); - } - } - - @Test(timeout = 60 * 1000) - public void leasing_a_new_connection_fails_with_connection_pool_timeout() { - - AmazonSyncHttpClient httpClient = HttpTestUtils.testClientBuilder() - .retryStrategy(DefaultRetryStrategy.doNotRetry()) - .httpClient(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofMillis(100)) - .maxConnections(1) - .build()) - .build(); - - SdkHttpFullRequest request = server.configureHttpEndpoint(SdkHttpFullRequest.builder()) - .method(SdkHttpMethod.GET) - .build(); - - // Block the first connection in the pool with this request. - httpClient.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext(request)) - .execute(combinedSyncResponseHandler(new EmptySdkResponseHandler(), null)); - - try { - // A new connection will be leased here which would fail in - // ConnectionPoolTimeoutException. - httpClient.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext(request)) - .execute(combinedSyncResponseHandler(null, null)); - Assert.fail("Connection pool timeout exception is expected!"); - } catch (SdkClientException e) { - Assert.assertTrue(e.getCause() instanceof ConnectionPoolTimeoutException); - } - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/ClientEndpointProvider.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/ClientEndpointProvider.java index 500dd446af4d..572830b0c152 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/ClientEndpointProvider.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/ClientEndpointProvider.java @@ -19,6 +19,7 @@ import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.core.internal.StaticClientEndpointProvider; import software.amazon.awssdk.endpoints.EndpointProvider; +import software.amazon.awssdk.utils.FunctionalUtils; /** * Client endpoint providers are responsible for resolving client-level endpoints. {@link EndpointProvider}s are @@ -48,6 +49,20 @@ static ClientEndpointProvider create(URI uri, boolean isEndpointOverridden) { */ URI clientEndpoint(); + /** + * Returns the client endpoint as a string with the query and user-info components stripped, as the rules engine's + * {@code ParseURL} rejects a URI carrying query parameters. Returns {@code null} if the endpoint is not overridden. + */ + default String sanitizedEndpointString() { + if (!isEndpointOverridden()) { + return null; + } + URI endpoint = clientEndpoint(); + return FunctionalUtils.invokeSafely( + () -> new URI(endpoint.getScheme(), null, endpoint.getHost(), endpoint.getPort(), + endpoint.getPath(), null, endpoint.getFragment()).toString()); + } + /** * Returns true if this endpoint was specified as an override by the customer, or false if it was determined * automatically by the SDK. 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 db0ee4d67f8f..0da073035e64 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 @@ -218,6 +218,12 @@ public enum SdkSystemSetting implements SystemSetting { */ AWS_USE_FIPS_ENDPOINT("aws.useFipsEndpoint", null), + /** + * Defines whether endpoint URLs from environment variables, system properties, and the shared configuration file + * should be ignored. Endpoint URLs set programmatically via the client builder are not affected. + */ + AWS_IGNORE_CONFIGURED_ENDPOINT_URLS("aws.ignoreConfiguredEndpointUrls", null), + /** * Whether request compression is disabled for operations marked with the RequestCompression trait. The default value is * false, i.e., request compression is enabled. @@ -270,7 +276,17 @@ public enum SdkSystemSetting implements SystemSetting { * defaults including STANDARD as the default retry mode, reduced base backoff delays, differentiated token bucket * costs, and other v2.1 retry specification changes. When {@code false} (the default), the SDK uses v2.0 retry behavior. */ - AWS_NEW_RETRIES_2026("aws.newRetries2026", null); + AWS_NEW_RETRIES_2026("aws.newRetries2026", null), + + /** + * Configure whether a default read/write inactivity timeout is applied to HTTP clients that do not enforce one of their + * own (currently the AWS CRT-based clients). When {@code true}, such clients shut down a connection that transfers no + * bytes for the resolved timeout window. When {@code false} (the default), no default read/write timeout is applied. + * + *

This setting is not intended to be used by end users. It gates an interim rollout and is subject to removal in a + * future release. + */ + AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026("aws.enableDefaultSocketTimeout2026", null); private final String systemProperty; private final String defaultValue; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SplittingTransformerConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SplittingTransformerConfiguration.java index 766213195203..21b564983c33 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SplittingTransformerConfiguration.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SplittingTransformerConfiguration.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.core; import java.util.Objects; +import java.util.function.UnaryOperator; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.internal.async.SplittingTransformer; @@ -35,9 +36,11 @@ public final class SplittingTransformerConfiguration implements ToCopyableBuilde SplittingTransformerConfiguration> { private final Long bufferSizeInBytes; + private final UnaryOperator responseMapper; private SplittingTransformerConfiguration(DefaultBuilder builder) { this.bufferSizeInBytes = Validate.paramNotNull(builder.bufferSize, "bufferSize"); + this.responseMapper = builder.responseMapper; } /** @@ -54,6 +57,14 @@ public Long bufferSizeInBytes() { return bufferSizeInBytes; } + /** + * @return the response mapper applied to the first response before delivery to the upstream transformer, or null if + * not set. See {@link Builder#responseMapper(UnaryOperator)} for semantics. + */ + public UnaryOperator responseMapper() { + return responseMapper; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -65,12 +76,15 @@ public boolean equals(Object o) { SplittingTransformerConfiguration that = (SplittingTransformerConfiguration) o; - return Objects.equals(bufferSizeInBytes, that.bufferSizeInBytes); + return Objects.equals(bufferSizeInBytes, that.bufferSizeInBytes) + && Objects.equals(responseMapper, that.responseMapper); } @Override public int hashCode() { - return bufferSizeInBytes != null ? bufferSizeInBytes.hashCode() : 0; + int result = bufferSizeInBytes != null ? bufferSizeInBytes.hashCode() : 0; + result = 31 * result + (responseMapper != null ? responseMapper.hashCode() : 0); + return result; } @Override @@ -94,13 +108,29 @@ public interface Builder extends CopyableBuilderOnly applied by the default {@code split} implementation. A transformer that overrides {@code split} (such as a + * parallel, file-based one) may not read it, in which case it has no effect. + * + * @param responseMapper a function to transform the response before delivery, or null for no mapping + * @return This object for method chaining. + */ + Builder responseMapper(UnaryOperator responseMapper); } private static final class DefaultBuilder implements Builder { private Long bufferSize; + private UnaryOperator responseMapper; private DefaultBuilder(SplittingTransformerConfiguration configuration) { this.bufferSize = configuration.bufferSizeInBytes; + this.responseMapper = configuration.responseMapper; } private DefaultBuilder() { @@ -112,6 +142,12 @@ public Builder bufferSizeInBytes(Long bufferSize) { return this; } + @Override + public Builder responseMapper(UnaryOperator responseMapper) { + this.responseMapper = responseMapper; + return this; + } + @Override public SplittingTransformerConfiguration build() { return new SplittingTransformerConfiguration(this); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java index 36a2d7eb647c..d762dc15a809 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java @@ -29,6 +29,8 @@ import java.util.function.Consumer; import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; +import software.amazon.awssdk.annotations.SdkAdvancedApi; +import software.amazon.awssdk.annotations.SdkAdvancedApi.Usage; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.FileRequestBodyConfiguration; @@ -63,6 +65,15 @@ * @see ByteBuffersAsyncRequestBody */ @SdkPublicApi +@SdkAdvancedApi( + cautionWhen = Usage.IMPLEMENTED, + guidance = "This is a reactive-streams Publisher and must obey the reactive-streams specification. " + + "The SDK re-subscribes on each retry attempt, " + + "so to support retries, reproduce the full content on every subscribe; a body that cannot should fail the " + + "subscriber on a later subscribe rather than emit partial content.", + saferAlternative = "Prefer the AsyncRequestBody.fromFile/fromBytes/fromInputStream factories. If you must supply a " + + "custom Publisher, build it with an established reactive-streams library such as RxJava or Reactor rather " + + "than implementing Publisher by hand.") public interface AsyncRequestBody extends SdkPublisher { /** @@ -94,6 +105,16 @@ default String body() { * @param publisher Publisher of source data * @return Implementation of {@link AsyncRequestBody} that produces data send by the publisher */ + @SdkAdvancedApi( + cautionWhen = Usage.CALLED, + guidance = "The returned AsyncRequestBody passes each subscribe straight through to the supplied publisher, so " + + "the publisher must itself meet the AsyncRequestBody contract: obey the reactive-streams " + + "specification, and since the SDK re-subscribes on each " + + "retry attempt, reproduce the full content on every subscribe to support retries; a publisher that " + + "cannot should fail the subscriber on a later subscribe rather than emit partial content.", + saferAlternative = "Prefer the AsyncRequestBody.fromFile/fromBytes/fromInputStream factories, which do not " + + "require the caller to supply a contract-compliant publisher. If you must supply one, build it with an " + + "established reactive-streams library such as RxJava or Reactor rather than by hand.") static AsyncRequestBody fromPublisher(Publisher publisher) { return new AsyncRequestBody() { diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncResponseTransformer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncResponseTransformer.java index 4c27501e6340..70ff1e6aef50 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncResponseTransformer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncResponseTransformer.java @@ -23,6 +23,8 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkAdvancedApi; +import software.amazon.awssdk.annotations.SdkAdvancedApi.Usage; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.FileTransformerConfiguration; @@ -86,6 +88,15 @@ * @param Type this response handler produces. I.E. the type you are transforming the response into. */ @SdkPublicApi +@SdkAdvancedApi( + cautionWhen = Usage.IMPLEMENTED, + guidance = "prepare() is called on each request attempt; if the CompletableFuture it returned on a previous " + + "attempt has already completed, it must return a new instance so the result of a retry is not lost, and " + + "exceptionOccurred() should release any resources the attempt opened (for example an open file channel) " + + "so retries do not leak them. onStream() receives the response body as a reactive-streams Publisher that " + + "the implementation subscribes to, and that subscriber must comply with the reactive-streams " + + "specification; a subscriber that never requests data stalls the response.", + saferAlternative = "Prefer the AsyncResponseTransformer.toFile/toBytes/toBlockingInputStream factories.") public interface AsyncResponseTransformer { /** * Initial call to enable any setup required before the response is handled. @@ -138,6 +149,7 @@ default SplitResult split(SplittingTransformerConfiguration .builder() .upstreamResponseTransformer(this) .maximumBufferSizeInBytes(splitConfig.bufferSizeInBytes()) + .responseMapper(splitConfig.responseMapper()) .resultFuture(future) .build(); return AsyncResponseTransformer.SplitResult.builder() @@ -303,6 +315,14 @@ static AsyncResponseTransformer> * @param Pojo response type. * @return AsyncResponseTransformer instance. */ + @SdkAdvancedApi( + cautionWhen = Usage.CALLED, + guidance = "The returned ResponsePublisher is a reactive-streams Publisher you must subscribe to and drive: " + + "your subscriber must obey the reactive-streams specification and honor back-pressure. A subscriber " + + "that never requests data stalls the response, and requesting unbounded data can exhaust memory.", + saferAlternative = "Prefer the fully-managed AsyncResponseTransformer.toFile/toBytes factories, which do not " + + "hand you a publisher to drive. If you do consume the publisher, use an established reactive-streams " + + "library such as RxJava or Reactor rather than a hand-written Subscriber.") static AsyncResponseTransformer> toPublisher() { return new PublisherAsyncResponseTransformer<>(); } @@ -330,6 +350,14 @@ static AsyncResponseTransformer AsyncResponseTransformer> toPublisher(Duration timeout) { return new PublisherAsyncResponseTransformer<>(timeout); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/listener/AsyncRequestBodyListener.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/listener/AsyncRequestBodyListener.java index 8835d1a007ae..99989c9bb4d9 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/listener/AsyncRequestBodyListener.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/async/listener/AsyncRequestBodyListener.java @@ -67,6 +67,11 @@ public String contentType() { return delegate.contentType(); } + @Override + public String body() { + return delegate.body(); + } + @Override public SdkPublisher split(AsyncRequestBodySplitConfiguration splitConfiguration) { return delegate.split(splitConfiguration); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkAsyncClientBuilder.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkAsyncClientBuilder.java index cb02b440d49a..55fdb4c9d989 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkAsyncClientBuilder.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkAsyncClientBuilder.java @@ -68,6 +68,13 @@ default B asyncConfiguration(Consumer clientAs * customize the HTTP client as it benefits from service specific defaults. * *

+ * A new HTTP client instance is built from this builder for each service client it is supplied to, configured with that + * service's HTTP defaults. Supplying the same builder to multiple service clients therefore produces a separate, + * independently configured HTTP client instance (with its own connection pool) for each of them. To share a single HTTP + * client instance across service clients, pass a pre-built client to {@link #httpClient(SdkAsyncHttpClient)} instead. + *

+ * + *

* Clients created by the builder are managed by the SDK and will be closed when the service client is closed. *

* diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkSyncClientBuilder.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkSyncClientBuilder.java index 5bf6f8a7b483..bec5fc0e5c9a 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkSyncClientBuilder.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/builder/SdkSyncClientBuilder.java @@ -50,6 +50,13 @@ public interface SdkSyncClientBuilder, C> { * customize the HTTP client as it benefits from service-specific default configuration. * *

+ * A new HTTP client instance is built from this builder for each service client it is supplied to, configured with that + * service's HTTP defaults. Supplying the same builder to multiple service clients therefore produces a separate, + * independently configured HTTP client instance (with its own connection pool) for each of them. To share a single HTTP + * client instance across service clients, pass a pre-built client to {@link #httpClient(SdkHttpClient)} instead. + *

+ * + *

* Clients created by the builder are managed by the SDK and will be closed when the service client is closed. *

*/ diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java index 04c418c1b08d..7a79c4b60bfb 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/ClientOverrideConfiguration.java @@ -288,6 +288,9 @@ public Optional scheduledExecutorService() { * execution except for marshalling. This includes request handler execution, all HTTP requests including retries, * unmarshalling, etc. This value should always be positive, if present. * + *

Because this window is narrower than the API call as a whole, the reported + * {@link software.amazon.awssdk.core.metrics.CoreMetric#API_CALL_DURATION} metric can exceed this timeout. + * *

The api call timeout feature doesn't have strict guarantees on how quickly a request is aborted when the * timeout is breached. The typical case aborts the request within a few milliseconds but there may occasionally be * requests that don't get aborted until several seconds after the timer has been breached. Because of this, the client @@ -613,6 +616,9 @@ default Builder retryStrategy(Consumer> configurator * entire client execution except for marshalling. This includes request handler execution, all HTTP requests including * retries, unmarshalling, etc. This value should always be positive, if present. * + *

Because this window is narrower than the API call as a whole, the reported + * {@link software.amazon.awssdk.core.metrics.CoreMetric#API_CALL_DURATION} metric can exceed this timeout. + * *

The api call timeout feature doesn't have strict guarantees on how quickly a request is aborted when the * timeout is breached. The typical case aborts the request within a few milliseconds but there may occasionally be * requests that don't get aborted until several seconds after the timer has been breached. Because of this, the client diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.java index e37ba953211d..973fc0c97f1a 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkAdvancedAsyncClientOption.java @@ -18,6 +18,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; +import software.amazon.awssdk.annotations.SdkAdvancedApi; +import software.amazon.awssdk.annotations.SdkAdvancedApi.Usage; import software.amazon.awssdk.annotations.SdkPublicApi; /** @@ -52,6 +54,13 @@ public final class SdkAdvancedAsyncClientOption extends ClientOption { * within the I/O thread because it may block the I/O thread and cause deadlock, especially if you are sending * another SDK request in the {@link CompletableFuture} chain since the SDK may perform blocking calls in some cases. */ + @SdkAdvancedApi( + cautionWhen = Usage.CONFIGURED, + guidance = "An executor that does not dispatch to a separate thread (e.g. Runnable::run) runs the " + + "completion inline on the calling thread and can deadlock the client, especially when the " + + "future chain issues another SDK request. If you set a custom executor, verify it under your " + + "own load tests, including request chains that issue further SDK calls.", + saferAlternative = "Leave unset to use the SDK-managed per-client ThreadPoolExecutor.") public static final SdkAdvancedAsyncClientOption FUTURE_COMPLETION_EXECUTOR = new SdkAdvancedAsyncClientOption<>(Executor.class); 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 20ea0d01c3b9..199232a088b3 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 @@ -311,6 +311,13 @@ public final class SdkClientOption extends ClientOption { */ public static final SdkClientOption DEFAULT_NEW_RETRIES_2026 = new SdkClientOption<>(Boolean.class); + /** + * Option to specify the default for the {@code AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} feature gate for the SDK client. + * This option is not intended to be set by end users. It gates an interim rollout and is subject to removal in a future + * release. + */ + public static final SdkClientOption DEFAULT_ENABLE_SOCKET_TIMEOUT_2026 = new SdkClientOption<>(Boolean.class); + /** * Whether retries 2.1 behavior is enabled. */ diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/endpoint/EndpointResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/endpoint/EndpointResolver.java index c17b6f96d8e6..fb93e96a273d 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/endpoint/EndpointResolver.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/endpoint/EndpointResolver.java @@ -23,7 +23,6 @@ /** * Callback interface for resolving endpoints from the request and execution context. */ -@FunctionalInterface @SdkProtectedApi public interface EndpointResolver { /** diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026Resolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026Resolver.java new file mode 100644 index 000000000000..4a37c9a80ea7 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026Resolver.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.http; + +import java.util.Optional; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.core.SdkSystemSetting; + +/** + * Resolver for the {@link SdkSystemSetting#AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} that supports setting a fallback value if not + * defined in the environment or system properties. + */ +@SdkProtectedApi +public final class EnableDefaultSocketTimeout2026Resolver { + private Boolean defaultEnableSocketTimeout2026; + + /** + * The default value for {@code AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026} if not configured via + * {@link SdkSystemSetting#AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026}. + * + * @return This resolver for method chaining. + */ + public EnableDefaultSocketTimeout2026Resolver defaultEnableSocketTimeout2026(Boolean defaultEnableSocketTimeout2026) { + this.defaultEnableSocketTimeout2026 = defaultEnableSocketTimeout2026; + return this; + } + + /** + * Resolve whether a default read/write timeout is applied. + */ + public boolean resolve() { + Optional envConfig = SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.getBooleanValue(); + + if (envConfig.isPresent()) { + return envConfig.get(); + } + + if (defaultEnableSocketTimeout2026 != null) { + return defaultEnableSocketTimeout2026; + } + + return false; + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/auth/AuthSchemeResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/auth/AuthSchemeResolver.java index ac795a34c494..1b5d64324c61 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/auth/AuthSchemeResolver.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/http/auth/AuthSchemeResolver.java @@ -82,7 +82,7 @@ public static SelectedAuthScheme resolveAuthScheme( identityProviders = resolver.resolve(request, identityProviders, executionAttributes); } - List authOptions = optionsResolver.resolve(request); + List authOptions = optionsResolver.resolve(request, executionAttributes); return selectAuthScheme(authOptions, authSchemes, identityProviders, null); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.java index 7ade08249da2..f3e34d023c38 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/ExecutionInterceptor.java @@ -19,6 +19,8 @@ import java.nio.ByteBuffer; import java.util.Optional; import org.reactivestreams.Publisher; +import software.amazon.awssdk.annotations.SdkAdvancedApi; +import software.amazon.awssdk.annotations.SdkAdvancedApi.Usage; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; @@ -173,6 +175,10 @@ default void afterMarshalling(Context.AfterMarshalling context, ExecutionAttribu /** * Modify the {@link SdkHttpFullRequest} before it is sent to the service. * + *

Note: The HTTP request URL at this point may not reflect the final resolved endpoint. Endpoint + * resolution happens after all interceptors complete. To read the fully resolved endpoint URL, use + * {@link #beforeTransmission} instead. + * * @param context The current state of the execution, including the SDK and current HTTP request. * @param executionAttributes A mutable set of attributes scoped to one specific request/response cycle that can be used to * give data to future lifecycle methods. @@ -183,11 +189,32 @@ default SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, return context.httpRequest(); } + @SdkAdvancedApi( + cautionWhen = Usage.OVERRIDDEN, + guidance = "Replacing the request body from an interceptor is discouraged: the returned RequestBody becomes the " + + "content the SDK sends, and the request's Content-Length and content hash or checksum are derived from " + + "it, so a body whose content or length does not match what the operation expects corrupts the request " + + "or is rejected by the service. Return the body reported by context.requestBody() unless you have a " + + "specific reason to replace it.", + saferAlternative = "Return context.requestBody() unchanged. If you must supply a different body, build it with " + + "the RequestBody factories rather than a hand-written ContentStreamProvider.") default Optional modifyHttpContent(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { return context.requestBody(); } + @SdkAdvancedApi( + cautionWhen = Usage.OVERRIDDEN, + guidance = "Replacing the async request body from an interceptor is discouraged: the returned AsyncRequestBody " + + "becomes the content the SDK sends, and the request's Content-Length and content hash or checksum are " + + "derived from it, so a body whose content or length does not match what the operation expects corrupts " + + "the request or is rejected by the service. It must also comply with the reactive-streams " + + "specification; the SDK re-subscribes to it " + + "on each retry attempt, so to support retries it must reproduce the full content on every subscribe. " + + "Return the body reported by context.asyncRequestBody() unless you have a specific reason to replace " + + "it.", + saferAlternative = "Return context.asyncRequestBody() unchanged. If you must supply a different body, build it " + + "with the AsyncRequestBody factories or an established reactive-streams library.") default Optional modifyAsyncHttpContent(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { return context.asyncRequestBody(); 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 cbcaec2c9333..de6f16ed4d73 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 @@ -38,6 +38,7 @@ import software.amazon.awssdk.core.useragent.BusinessMetricCollection; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.endpoints.EndpointProvider; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.SdkHttpExecutionAttributes; import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeProvider; @@ -130,10 +131,22 @@ public final class SdkInternalExecutionAttribute extends SdkExecutionAttribute { /** * Whether the endpoint on the request is the result of Endpoint Discovery. + * + * @deprecated This attribute is specific to the endpoint discovery feature and should not be used to skip endpoint + * resolution; use {@link #SKIP_ENDPOINT_RESOLUTION} instead. */ + @Deprecated public static final ExecutionAttribute IS_DISCOVERED_ENDPOINT = new ExecutionAttribute<>("IsDiscoveredEndpoint"); + /** + * Whether endpoint resolution should be skipped for the current request. When set to {@code true}, the SDK will not + * invoke the endpoint provider and will use the endpoint already set on the request. This is used for pre-signed URL + * operations and other scenarios where the endpoint is already fully resolved. + */ + public static final ExecutionAttribute SKIP_ENDPOINT_RESOLUTION = + new ExecutionAttribute<>("SkipEndpointResolution"); + /** * The nano time that the current API call attempt began. */ @@ -200,11 +213,29 @@ public final class SdkInternalExecutionAttribute extends SdkExecutionAttribute { new ExecutionAttribute<>("EndpointResolver"); /** - * The HTTP request URI captured before modifyHttpRequest interceptors run. - * Used by EndpointResolutionStage to detect if a customer interceptor modified the URL. + * The HTTP request endpoint (scheme, host, port and path) captured before modifyHttpRequest interceptors run. + * Used by EndpointResolutionStage to detect if a customer interceptor modified the endpoint. + */ + public static final ExecutionAttribute HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY = + new ExecutionAttribute<>("HttpRequestEndpointBeforeModify"); + + /** + * The HTTP request URI captured before modifyHttpRequest interceptors run. Writing this replaces + * {@link #HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY} with the written URI's components. + * + * @deprecated Use {@link #HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY} instead. This is a view over that attribute, so the + * value recorded by the SDK carries only the scheme, host, port and path: the query string is absent, and the port + * is present even when it is the protocol's default. Reading it builds a {@link URI}, which + * {@link #HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY} lets you avoid. */ + @Deprecated public static final ExecutionAttribute HTTP_REQUEST_URI_BEFORE_MODIFY = - new ExecutionAttribute<>("HttpRequestUriBeforeModify"); + ExecutionAttribute.derivedBuilder("HttpRequestUriBeforeModify", + URI.class, + () -> HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY) + .readMapping(endpoint -> endpoint != null ? endpoint.toUri() : null) + .writeMapping((endpoint, uri) -> uri != null ? EndpointUrl.fromUri(uri) : null) + .build(); /** * The selected auth scheme for a request. diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/StaticClientEndpointProvider.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/StaticClientEndpointProvider.java index 40a9cd38f2c3..43be721c9110 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/StaticClientEndpointProvider.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/StaticClientEndpointProvider.java @@ -18,6 +18,7 @@ import java.net.URI; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.utils.FunctionalUtils; import software.amazon.awssdk.utils.ToString; import software.amazon.awssdk.utils.Validate; @@ -31,10 +32,48 @@ public class StaticClientEndpointProvider implements ClientEndpointProvider { private final URI clientEndpoint; private final boolean isEndpointOverridden; + /** + * A sanitized form of {@link #clientEndpoint} with the query and user-info components stripped, formatted as a + * string. This is the value that endpoint rules receive via the {@code SDK::Endpoint} built-in. Computed once at + * construction so that every call to {@code endpointBuiltIn()} returns the same {@link String} reference. + *

+ * {@code null} when {@link #isEndpointOverridden} is {@code false}. + */ + private final String sanitizedEndpointString; + public StaticClientEndpointProvider(URI clientEndpoint, boolean isEndpointOverridden) { this.clientEndpoint = Validate.paramNotNull(clientEndpoint, "clientEndpoint"); this.isEndpointOverridden = isEndpointOverridden; Validate.paramNotNull(clientEndpoint.getScheme(), "The URI scheme of endpointOverride"); + this.sanitizedEndpointString = isEndpointOverridden ? sanitize(clientEndpoint) : null; + } + + /** + * {@inheritDoc} + *

+ * Returns the same {@link String} reference on every call, because the value is computed once at construction. That + * removes a URI construction and its string conversion from every request that resolves an endpoint against an + * overridden client endpoint. + *

+ * {@code final} so that the cached value cannot be shadowed by a subclass whose overridden accessors the constructor + * did not see. + */ + @Override + public final String sanitizedEndpointString() { + return sanitizedEndpointString; + } + + /** + * Repeats {@link ClientEndpointProvider#sanitizedEndpointString()}'s transformation over the constructor's argument, + * rather than calling that default from the constructor, so no virtual method runs before this class is fully + * initialised. The two must agree, and + * {@code ClientEndpointProviderTest.sanitizedEndpointString_cachedFormMatchesRecomputedForm} is what holds them + * together. + */ + private static String sanitize(URI endpoint) { + return FunctionalUtils.invokeSafely( + () -> new URI(endpoint.getScheme(), null, endpoint.getHost(), endpoint.getPort(), + endpoint.getPath(), null, endpoint.getFragment()).toString()); } @Override diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncResponseTransformer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncResponseTransformer.java index e250eab650b0..3c94080f604c 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncResponseTransformer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncResponseTransformer.java @@ -72,7 +72,7 @@ public void exceptionOccurred(Throwable throwable) { public SplitResult> split(SplittingTransformerConfiguration splitConfig) { CompletableFuture> future = new CompletableFuture<>(); SdkPublisher> transformer = - new ByteArraySplittingTransformer<>(this, future); + new ByteArraySplittingTransformer<>(this, future, splitConfig.responseMapper()); return AsyncResponseTransformer.SplitResult.>builder() .publisher(transformer) .resultFuture(future) diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArraySplittingTransformer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArraySplittingTransformer.java index 2531f7f8166b..fa5761d01bd2 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArraySplittingTransformer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArraySplittingTransformer.java @@ -23,10 +23,12 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.UnaryOperator; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.core.exception.SdkClientException; @@ -84,12 +86,30 @@ public class ByteArraySplittingTransformer implements SdkPublisher buffers; + private final UnaryOperator responseMapper; + public ByteArraySplittingTransformer(AsyncResponseTransformer> upstreamResponseTransformer, CompletableFuture> resultFuture) { + this(upstreamResponseTransformer, resultFuture, UnaryOperator.identity()); + } + + public ByteArraySplittingTransformer(AsyncResponseTransformer> + upstreamResponseTransformer, + CompletableFuture> resultFuture, + UnaryOperator responseMapper) { this.upstreamResponseTransformer = upstreamResponseTransformer; this.resultFuture = resultFuture; this.buffers = new ConcurrentHashMap<>(); + this.responseMapper = responseMapper != null ? responseMapper : UnaryOperator.identity(); + } + + @SuppressWarnings("unchecked") + private ResponseT mapResponse(ResponseT response) { + if (!(response instanceof SdkResponse)) { + return response; + } + return (ResponseT) responseMapper.apply((SdkResponse) response); } @Override @@ -181,7 +201,7 @@ private void handleSubscriptionCancel() { CompletableFuture> upstreamPrepareFuture = upstreamResponseTransformer.prepare(); CompletableFutureUtils.forwardResultTo(upstreamPrepareFuture, resultFuture); - upstreamResponseTransformer.onResponse(responseT.get()); + upstreamResponseTransformer.onResponse(mapResponse(responseT.get())); int totalPartCount = nextPartNumber.get() - 1; if (buffers.size() != totalPartCount) { diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBody.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBody.java index e1f6d9e8cb05..af319e47164d 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBody.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBody.java @@ -31,12 +31,15 @@ import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncRequestBodySplitConfiguration; +import software.amazon.awssdk.core.async.CloseableAsyncRequestBody; +import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.core.exception.NonRetryableException; import software.amazon.awssdk.core.internal.util.Mimetype; import software.amazon.awssdk.core.internal.util.NoopSubscription; import software.amazon.awssdk.utils.Logger; -import software.amazon.awssdk.utils.SdkAutoCloseable; import software.amazon.awssdk.utils.Validate; +import software.amazon.awssdk.utils.async.SimplePublisher; /** * An implementation of {@link AsyncRequestBody} for providing data from the supplied {@link ByteBuffer} array. This is created @@ -57,6 +60,12 @@ *

  • Send error notifications to all active subscribers
  • *
  • Prevent new subscriptions
  • * + * + *

    Splitting:

    + * Because all data is already in memory, this implementation splits into independent + * {@code ByteBuffersAsyncRequestBody} parts backed by read-only slices of the same data rather than using + * {@link SplittingPublisher} making each part replayable. + * * @see AsyncRequestBody#fromBytes(byte[]) * @see AsyncRequestBody#fromBytesUnsafe(byte[]) * @see AsyncRequestBody#fromByteBuffer(ByteBuffer) @@ -66,7 +75,7 @@ * @see AsyncRequestBody#fromString(String) */ @SdkInternalApi -public final class ByteBuffersAsyncRequestBody implements AsyncRequestBody, SdkAutoCloseable { +public final class ByteBuffersAsyncRequestBody implements CloseableAsyncRequestBody { private static final Logger log = Logger.loggerFor(ByteBuffersAsyncRequestBody.class); private final String mimetype; @@ -123,6 +132,105 @@ public String body() { return BodyType.BYTES.getName(); } + /** + * {@inheritDoc} + * + *

    Behaves the same as {@link #splitCloseable(AsyncRequestBodySplitConfiguration)}; the emitted parts are + * closeable, even though they are exposed here as plain {@link AsyncRequestBody}s. + */ + @Override + public SdkPublisher split(AsyncRequestBodySplitConfiguration splitConfiguration) { + // The identity mapping only widens the element type. SdkPublisher is invariant, so the publisher returned by + // splitCloseable cannot be returned directly. + return splitCloseable(splitConfiguration).map(body -> body); + } + + /** + * {@inheritDoc} + * + *

    Each part is an independent, replayable {@code ByteBuffersAsyncRequestBody} backed by read-only slices of this + * body's data, so no data is copied and each part may be subscribed to more than once (i.e. it supports retries). + * Closing a part releases only that part's slices; it does not affect this body or any sibling part. + * + *

    {@link AsyncRequestBodySplitConfiguration#bufferSizeInBytes()} is not applicable here and is ignored, since all + * of the data is already buffered in memory. + */ + @Override + public SdkPublisher splitCloseable(AsyncRequestBodySplitConfiguration splitConfiguration) { + Validate.notNull(splitConfiguration, "splitConfiguration"); + long chunkSizeInBytes = splitConfiguration.chunkSizeInBytes() == null + ? AsyncRequestBodySplitConfiguration.defaultConfiguration().chunkSizeInBytes() + : splitConfiguration.chunkSizeInBytes(); + + SimplePublisher publisher = new SimplePublisher<>(); + + // Reading closed and snapshotting buffers must be atomic, otherwise a concurrent close() could + // split an already-emptied buffer list. Nothing is published while the lock is held. + List dataToSplit = null; + boolean alreadyClosed; + synchronized (lock) { + alreadyClosed = closed; + if (!alreadyClosed) { + dataToSplit = new ArrayList<>(buffers); + } + } + + if (alreadyClosed) { + publisher.error(NonRetryableException.create("AsyncRequestBody has been closed")); + return SdkPublisher.adapt(publisher); + } + + try { + sendParts(publisher, dataToSplit, chunkSizeInBytes); + publisher.complete(); + } catch (Throwable t) { + log.debug(() -> "Failed to split the in-memory request body", t); + publisher.error(t); + } + return SdkPublisher.adapt(publisher); + } + + /** + * Slices {@code dataToSplit} at {@code chunkSizeInBytes} boundaries and sends one part per chunk. The slices are + * read-only views over the existing data, so this does not copy the payload. A single empty part is sent if there is + * no data, mirroring the behavior of {@link SplittingPublisher} for an empty body. + */ + private void sendParts(SimplePublisher publisher, + List dataToSplit, + long chunkSizeInBytes) { + List currentPart = new ArrayList<>(); + long currentPartLength = 0; + boolean anyPartSent = false; + + for (ByteBuffer data : dataToSplit) { + // A read-only view (no underlying copy) + ByteBuffer remainingData = data.asReadOnlyBuffer(); + + while (remainingData.hasRemaining()) { + int lengthToRead = Math.toIntExact(Math.min(chunkSizeInBytes - currentPartLength, + remainingData.remaining())); + // No underlying copy, just a view on top of the already read-only buffer. + ByteBuffer slice = remainingData.duplicate(); + slice.limit(slice.position() + lengthToRead); + remainingData.position(remainingData.position() + lengthToRead); + + currentPart.add(slice); + currentPartLength += lengthToRead; + + if (currentPartLength == chunkSizeInBytes) { + publisher.send(new ByteBuffersAsyncRequestBody(mimetype, currentPartLength, currentPart)); + anyPartSent = true; + currentPart = new ArrayList<>(); + currentPartLength = 0; + } + } + } + + if (currentPartLength > 0 || !anyPartSent) { + publisher.send(new ByteBuffersAsyncRequestBody(mimetype, currentPartLength, currentPart)); + } + } + public static ByteBuffersAsyncRequestBody of(List buffers, long length) { return new ByteBuffersAsyncRequestBody(Mimetype.MIMETYPE_OCTET_STREAM, length, buffers); } 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 54fdd978c7e6..f1f9b17ffb1e 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 @@ -186,6 +186,11 @@ public String contentType() { return wrapped.contentType(); } + @Override + public String body() { + return wrapped.body(); + } + @Override public void subscribe(Subscriber s) { Validate.notNull(s, "Subscription MUST NOT be null."); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBody.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBody.java index 246bcb10578f..790ef09cce42 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBody.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBody.java @@ -70,6 +70,11 @@ public String contentType() { return wrapped.contentType(); } + @Override + public String body() { + return wrapped.body(); + } + private SdkPublisher> split(SdkPublisher source) { return subscriber -> source.subscribe(new SplittingSubscriber(subscriber)); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/EmittingSubscription.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/EmittingSubscription.java index 25f1a78705ca..efd16ed28c04 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/EmittingSubscription.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/EmittingSubscription.java @@ -35,7 +35,7 @@ public final class EmittingSubscription implements Subscription { private static final Logger log = Logger.loggerFor(EmittingSubscription.class); - private Subscriber downstreamSubscriber; + private final Subscriber downstreamSubscriber; private final AtomicBoolean emitting; private final AtomicLong outstandingDemand; private final Runnable onCancel; @@ -74,7 +74,6 @@ public void request(long n) { @Override public void cancel() { isCancelled.set(true); - downstreamSubscriber = null; onCancel.run(); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelper.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelper.java index 7de0add5613c..4a02a1b8b5b9 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelper.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelper.java @@ -196,5 +196,10 @@ private void startNextIfNeeded() { public Optional contentLength() { return fileAsyncRequestBody.contentLength(); } + + @Override + public String body() { + return fileAsyncRequestBody.body(); + } } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformer.java index c35d28c53601..752af9ea4c28 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformer.java @@ -139,6 +139,7 @@ private AsynchronousFileChannel createChannel(Path path) throws IOException { @Override public CompletableFuture prepare() { + fileChannel = null; cf = new CompletableFuture<>(); cf.whenComplete((r, t) -> { if (t != null && fileChannel != null) { @@ -169,14 +170,16 @@ public void onStream(SdkPublisher publisher) { @Override public void exceptionOccurred(Throwable throwable) { + AsynchronousFileChannel currentFileChannel = fileChannel; + fileChannel = null; try { - if (fileChannel != null) { + if (currentFileChannel != null) { runAndLogError(log.logger(), String.format("Failed to close the file %s, resource may be leaked", path), - () -> fileChannel.close()); + currentFileChannel::close); } } finally { - if (configuration.failureBehavior() == FailureBehavior.DELETE) { + if (currentFileChannel != null && configuration.failureBehavior() == FailureBehavior.DELETE) { runAndLogError(log.logger(), String.format("Failed to delete the file %s", path), () -> Files.deleteIfExists(path)); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerPublisher.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerPublisher.java index f6c215a45165..ba811809c536 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerPublisher.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerPublisher.java @@ -41,7 +41,7 @@ public class FileAsyncResponseTransformerPublisher private final Path path; private final FileTransformerConfiguration initialConfig; - private Subscriber subscriber; + private volatile Subscriber subscriber; private final AtomicLong transformerCount; @@ -70,9 +70,22 @@ private AsyncResponseTransformer createTransformer() { } private void onCancel() { + // Drop the subscriber reference on cancel, per Reactive Streams rule 3.13. Reads snapshot the volatile field and + // null-check it, so this clear cannot race into a NullPointerException. subscriber = null; } + /** + * Signals an error to the downstream subscriber if still present. Reads the volatile field once so a concurrent + * {@link #onCancel()} cannot cause a {@link NullPointerException}. + */ + private void signalError(Throwable e) { + Subscriber currentSubscriber = subscriber; + if (currentSubscriber != null) { + currentSubscriber.onError(e); + } + } + /** * This is the AsyncResponseTransformer that will be used for each individual requests. *

    @@ -107,13 +120,13 @@ public void onResponse(T response) { Optional contentLength = response.sdkHttpResponse().firstMatchingHeader("content-length"); long transformerCount = FileAsyncResponseTransformerPublisher.this.transformerCount.get(); // Error out if content range header is missing and this is not the initial request - if (subscriber != null && transformerCount > 0) { - subscriber.onError(new IllegalStateException("Content range header is missing")); + if (transformerCount > 0) { + signalError(new IllegalStateException("Content range header is missing")); return; } if (!contentLength.isPresent()) { - subscriber.onError(new IllegalStateException("Content length header is missing")); + signalError(new IllegalStateException("Content length header is missing")); return; } String totalLength = contentLength.get(); @@ -125,10 +138,7 @@ public void onResponse(T response) { String contentRange = contentRangeOpt.get(); Optional> contentRangePair = ContentRangeParser.range(contentRange); if (!contentRangePair.isPresent()) { - if (subscriber != null) { - IllegalStateException e = new IllegalStateException("Could not parse content range header " + contentRange); - handleError(e); - } + handleError(new IllegalStateException("Could not parse content range header " + contentRange)); return; } @@ -141,7 +151,7 @@ public void onResponse(T response) { } private void handleError(Throwable e) { - subscriber.onError(e); + signalError(e); future.completeExceptionally(e); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/SplittingTransformer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/SplittingTransformer.java index d4cf1c7a2356..0b94dd2f7c34 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/SplittingTransformer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/SplittingTransformer.java @@ -19,9 +19,11 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.util.function.UnaryOperator; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.SplittingTransformerConfiguration; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.SdkPublisher; @@ -112,16 +114,18 @@ public class SplittingTransformer implements SdkPublisher upstreamResponseTransformer, - Long maximumBufferSizeInBytes, - CompletableFuture resultFuture) { + private final UnaryOperator responseMapper; + + private SplittingTransformer(Builder builder) { this.upstreamResponseTransformer = Validate.paramNotNull( - upstreamResponseTransformer, "upstreamResponseTransformer"); - this.resultFuture = Validate.paramNotNull( - resultFuture, "resultFuture"); - Validate.notNull(maximumBufferSizeInBytes, "maximumBufferSizeInBytes"); + builder.upstreamResponseTransformer, "upstreamResponseTransformer"); + this.resultFuture = Validate.paramNotNull(builder.returnFuture, "resultFuture"); + Validate.notNull(builder.maximumBufferSize, "maximumBufferSizeInBytes"); this.maximumBufferInBytes = Validate.isPositive( - maximumBufferSizeInBytes, "maximumBufferSizeInBytes"); + builder.maximumBufferSize, "maximumBufferSizeInBytes"); + this.responseMapper = builder.responseMapper != null + ? builder.responseMapper + : UnaryOperator.identity(); this.resultFuture.whenComplete((r, e) -> { if (e == null) { @@ -133,6 +137,14 @@ private SplittingTransformer(AsyncResponseTransformer upstre }); } + @SuppressWarnings("unchecked") + private ResponseT mapResponse(ResponseT response) { + if (!(response instanceof SdkResponse)) { + return response; + } + return (ResponseT) responseMapper.apply((SdkResponse) response); + } + /** * @param downstreamSubscriber the {@link Subscriber} to the individual AsyncResponseTransformer */ @@ -296,7 +308,7 @@ public CompletableFuture prepare() { public void onResponse(ResponseT response) { if (onResponseCalled.compareAndSet(false, true)) { log.trace(() -> "calling onResponse on the upstream transformer"); - upstreamResponseTransformer.onResponse(response); + upstreamResponseTransformer.onResponse(mapResponse(response)); } this.response = response; } @@ -393,6 +405,7 @@ public static final class Builder { private Long maximumBufferSize; private CompletableFuture returnFuture; private AsyncResponseTransformer upstreamResponseTransformer; + private UnaryOperator responseMapper; private Builder() { } @@ -437,10 +450,13 @@ public Builder resultFuture(CompletableFuture retur return this; } + public Builder responseMapper(UnaryOperator responseMapper) { + this.responseMapper = responseMapper; + return this; + } + public SplittingTransformer build() { - return new SplittingTransformer<>(this.upstreamResponseTransformer, - this.maximumBufferSize, - this.returnFuture); + return new SplittingTransformer<>(this); } } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseAsyncClientHandler.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseAsyncClientHandler.java index 0c2f91a3a424..4e27f2400c18 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseAsyncClientHandler.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseAsyncClientHandler.java @@ -17,6 +17,7 @@ import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; +import java.time.Duration; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Function; @@ -50,6 +51,7 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.NoOpMetricCollector; import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Logger; @@ -70,7 +72,7 @@ protected BaseAsyncClientHandler(SdkClientConfiguration clientConfiguration, public CompletableFuture execute( ClientExecutionParams executionParams) { - return measureApiCallSuccess(executionParams, () -> { + return measureApiCall(executionParams, () -> { // Running beforeExecution interceptors and modifyRequest interceptors. ExecutionContext executionContext = invokeInterceptorsAndCreateExecutionContext(executionParams); @@ -86,7 +88,7 @@ public Complet ClientExecutionParams executionParams, AsyncResponseTransformer asyncResponseTransformer) { - return measureApiCallSuccess(executionParams, () -> { + return measureApiCall(executionParams, () -> { if (executionParams.getCombinedResponseHandler() != null) { // There is no support for catching errors in a body for streaming responses. Our codegen must never // attempt to do this. @@ -232,7 +234,10 @@ private Comple new AsyncAfterTransmissionInterceptorCallingResponseHandler<>(asyncResponseHandler, executionContext)); + // Captured because the requestBody branch above may reassign 'marshalled', leaving it not effectively final. + SdkHttpFullRequest requestForMetrics = marshalled; CompletableFuture exceptionTranslatedFuture = invokeFuture.handle((resp, err) -> { + reportServiceEndpointMetric(executionContext, requestForMetrics); if (err != null) { throw ThrowableUtils.failure(err); } @@ -288,27 +293,49 @@ private CompletableFuture invoke( .execute(responseHandler); } - private CompletableFuture measureApiCallSuccess(ClientExecutionParams executionParams, - Supplier> apiCall) { + /** + * Measure {@link CoreMetric#API_CALL_DURATION} and report {@link CoreMetric#API_CALL_SUCCESSFUL} for the whole API + * call. + * + *

    The window deliberately encloses everything the SDK does for the call, marshalling included, and closes when + * the returned future completes. Measuring inside the request pipeline is not an option: the pipeline's input is the + * already-marshalled request, so no arrangement of pipeline stages can enclose marshalling. Measuring here also + * keeps the window identical to the synchronous client's. + */ + private CompletableFuture measureApiCall(ClientExecutionParams executionParams, + Supplier> apiCall) { + MetricCollector metricCollector = executionParams.getMetricCollector(); + if (metricCollector == null || metricCollector instanceof NoOpMetricCollector) { + // Nothing will consume these metrics, so don't pay for the clock reads or the extra future. A null collector + // is treated the same as NoOp: when the params carry none, the collector that AwsExecutionContextBuilder + // substitutes into the ExecutionContext is never handed to a publisher, so anything reported to it is + // discarded. + try { + return apiCall.get(); + } catch (Exception e) { + return CompletableFutureUtils.failedFuture(e); + } + } + + long callStart = System.nanoTime(); try { CompletableFuture apiCallResult = apiCall.get(); CompletableFuture outputFuture = - apiCallResult.whenComplete((r, t) -> reportApiCallSuccess(executionParams, t == null)); + apiCallResult.whenComplete((r, t) -> reportApiCallMetrics(metricCollector, callStart, t == null)); // Preserve cancellations on the output future, by passing cancellations of the output future to the api call future. CompletableFutureUtils.forwardExceptionTo(outputFuture, apiCallResult); return outputFuture; } catch (Exception e) { - reportApiCallSuccess(executionParams, false); + reportApiCallMetrics(metricCollector, callStart, false); return CompletableFutureUtils.failedFuture(e); } } - private void reportApiCallSuccess(ClientExecutionParams executionParams, boolean value) { - MetricCollector metricCollector = executionParams.getMetricCollector(); - if (metricCollector != null) { - metricCollector.reportMetric(CoreMetric.API_CALL_SUCCESSFUL, value); - } + private void reportApiCallMetrics(MetricCollector metricCollector, long callStartNanoTime, boolean successful) { + long durationNanos = System.nanoTime() - callStartNanoTime; + metricCollector.reportMetric(CoreMetric.API_CALL_SUCCESSFUL, successful); + metricCollector.reportMetric(CoreMetric.API_CALL_DURATION, Duration.ofNanos(durationNanos)); } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java index 41cb4f6477dc..e89d2893a002 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseClientHandler.java @@ -41,6 +41,7 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; @@ -81,15 +82,39 @@ static InterceptorContext finalizeSdkHttpFu addHttpRequest(executionContext, request); runAfterMarshallingInterceptors(executionContext); - // Snapshot the HTTP request URI before modifyHttpRequest interceptors run. - // EndpointResolutionStage uses this to detect if a customer interceptor modified the URL. + // Snapshot the HTTP request endpoint before modifyHttpRequest interceptors run. + // EndpointResolutionStage uses this to detect if a customer interceptor modified the endpoint. + // + // Use the optimized EndpointUrl instead of an expensive URI to avoid the cost of parsing/re-parsing it. + // Query/EC2 protocols have the entire request payload in query params at this point which increases the time + // to build the URI in proportion to the size of the request. + SdkHttpRequest marshalledRequest = executionContext.interceptorContext().httpRequest(); executionContext.executionAttributes().putAttribute( - SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, - executionContext.interceptorContext().httpRequest().getUri()); + SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, + EndpointUrl.fromComponents(marshalledRequest.protocol(), + marshalledRequest.host(), + marshalledRequest.port(), + marshalledRequest.encodedPath())); return runModifyHttpRequestAndHttpContentInterceptors(executionContext); } + /** + * Report the {@link CoreMetric#SERVICE_ENDPOINT} metric for a completed request execution. + * + *

    This must run after the request pipeline, so that {@code EndpointResolutionStage} and the signer have applied + * their changes to the HTTP request held by the interceptor context. {@code fallbackRequest} is used only when the + * interceptor context does not hold a full request, which can happen when the execution failed before the pipeline + * updated it. + */ + static void reportServiceEndpointMetric(ExecutionContext executionContext, SdkHttpFullRequest fallbackRequest) { + SdkHttpRequest finalRequest = executionContext.interceptorContext().httpRequest(); + MetricUtils.collectServiceEndpointMetrics(executionContext.metricCollector(), + finalRequest instanceof SdkHttpFullRequest + ? (SdkHttpFullRequest) finalRequest + : fallbackRequest); + } + private static void runBeforeMarshallingInterceptors(ExecutionContext executionContext) { executionContext.interceptorChain().beforeMarshalling(executionContext.interceptorContext(), executionContext.executionAttributes()); @@ -103,6 +128,8 @@ private static SdkHttpFullRequest modifyEndpointHostIfNeeded(SdkHttpFullRequest ClientExecutionParams executionParams) { if (executionParams.discoveredEndpoint() != null) { URI discoveredEndpoint = executionParams.discoveredEndpoint(); + executionParams.putExecutionAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true); + // Keep deprecated attribute for cross-module compatibility with older generated service clients executionParams.putExecutionAttribute(SdkInternalExecutionAttribute.IS_DISCOVERED_ENDPOINT, true); return originalRequest.toBuilder().host(discoveredEndpoint.getHost()).port(discoveredEndpoint.getPort()).build(); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseSyncClientHandler.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseSyncClientHandler.java index 03ea0683397b..2a4d20f88ed3 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseSyncClientHandler.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/handler/BaseSyncClientHandler.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.core.internal.handler; +import java.time.Duration; import java.util.Optional; import java.util.function.Supplier; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -41,6 +42,7 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.NoOpMetricCollector; @SdkInternalApi public abstract class BaseSyncClientHandler extends BaseClientHandler implements SyncClientHandler { @@ -57,7 +59,7 @@ public ReturnT ClientExecutionParams executionParams, ResponseTransformer responseTransformer) { - return measureApiCallSuccess(executionParams, () -> { + return measureApiCall(executionParams, () -> { // Running beforeExecution interceptors and modifyRequest interceptors. ExecutionContext executionContext = invokeInterceptorsAndCreateExecutionContext(executionParams); @@ -71,7 +73,7 @@ public ReturnT public OutputT execute( ClientExecutionParams executionParams) { - return measureApiCallSuccess(executionParams, () -> { + return measureApiCall(executionParams, () -> { // Running beforeExecution interceptors and modifyRequest interceptors. ExecutionContext executionContext = invokeInterceptorsAndCreateExecutionContext(executionParams); @@ -170,28 +172,44 @@ private ReturnT doExecute( } SdkClientConfiguration clientConfiguration = resolveRequestConfiguration(executionParams); - return invoke(clientConfiguration, - marshalled, - inputT, - executionContext, - responseHandler); + try { + return invoke(clientConfiguration, + marshalled, + inputT, + executionContext, + responseHandler); + } finally { + reportServiceEndpointMetric(executionContext, marshalled); + } } - private T measureApiCallSuccess(ClientExecutionParams executionParams, Supplier thingToMeasureSuccessOf) { + /** + * Measure {@link CoreMetric#API_CALL_DURATION} and report {@link CoreMetric#API_CALL_SUCCESSFUL} for the whole API + * call. + * + *

    The window deliberately encloses everything the SDK does for the call, marshalling included. Measuring inside + * the request pipeline is not an option: the pipeline's input is the already-marshalled request, so no arrangement + * of pipeline stages can enclose marshalling. + */ + private T measureApiCall(ClientExecutionParams executionParams, Supplier apiCall) { + MetricCollector metricCollector = executionParams.getMetricCollector(); + if (metricCollector == null || metricCollector instanceof NoOpMetricCollector) { + // Nothing will consume these metrics, so don't pay for the clock reads. A null collector is treated the same + // as NoOp: when the params carry none, the collector that AwsExecutionContextBuilder substitutes into the + // ExecutionContext is never handed to a publisher, so anything reported to it is discarded. + return apiCall.get(); + } + + long callStart = System.nanoTime(); try { - T result = thingToMeasureSuccessOf.get(); - reportApiCallSuccess(executionParams, true); + T result = apiCall.get(); + metricCollector.reportMetric(CoreMetric.API_CALL_SUCCESSFUL, true); return result; } catch (Exception e) { - reportApiCallSuccess(executionParams, false); + metricCollector.reportMetric(CoreMetric.API_CALL_SUCCESSFUL, false); throw e; - } - } - - private void reportApiCallSuccess(ClientExecutionParams executionParams, boolean value) { - MetricCollector metricCollector = executionParams.getMetricCollector(); - if (metricCollector != null) { - metricCollector.reportMetric(CoreMetric.API_CALL_SUCCESSFUL, value); + } finally { + metricCollector.reportMetric(CoreMetric.API_CALL_DURATION, Duration.ofNanos(System.nanoTime() - callStart)); } } 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 5772db0555a3..049d1cc64d85 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 @@ -33,7 +33,6 @@ import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyUserAgentStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncApiCallAttemptMetricCollectionStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncApiCallMetricCollectionStage; 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; @@ -214,8 +213,8 @@ public CompletableFuture execute( .then(async(() -> new UnwrapResponseContainer<>())) .then(async(() -> new AfterExecutionInterceptorsStage<>())) .wrappedWith(AsyncExecutionFailureExceptionReportingStage::new) - .wrappedWith(AsyncApiCallTimeoutTrackingStage::new) - .wrappedWith(AsyncApiCallMetricCollectionStage::new)::build)::build) + // Note: API_CALL_DURATION is measured by BaseAsyncClientHandler + .wrappedWith(AsyncApiCallTimeoutTrackingStage::new)::build)::build) .build(httpClientDependencies) .execute(request, createRequestExecutionDependencies()); } catch (RuntimeException e) { 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 1996766372a4..53fc3c2e48a3 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 @@ -30,7 +30,6 @@ import software.amazon.awssdk.core.internal.http.pipeline.stages.AfterTransmissionExecutionInterceptorsStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyUserAgentStage; @@ -206,7 +205,7 @@ public OutputT execute(HttpResponseHandler> response .wrappedWith(RetryableStage::new)::build) .wrappedWith(StreamManagingStage::new) .wrappedWith(ApiCallTimeoutTrackingStage::new)::build) - .wrappedWith((deps, wrapped) -> new ApiCallMetricCollectionStage<>(wrapped)) + // Note: API_CALL_DURATION is measured by BaseSyncClientHandler .then(() -> new UnwrapResponseContainer<>()) .then(() -> new AfterExecutionInterceptorsStage<>()) .wrappedWith(ExecutionFailureExceptionReportingStage::new) diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisher.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisher.java index 0471c6199dc1..c918a8735ac2 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisher.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisher.java @@ -17,11 +17,17 @@ import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Optional; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.http.ContentStreamProvider; +import software.amazon.awssdk.http.Header; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.async.SdkHttpContentPublisher; import software.amazon.awssdk.utils.IoUtils; @@ -33,12 +39,27 @@ @SdkInternalApi public final class SimpleHttpContentPublisher implements SdkHttpContentPublisher { + private static final byte[] EMPTY_CONTENT = new byte[0]; + + /** + * Ceiling on how much is allocated up front from the {@code Content-Length} header. The header is normally exact, + * but it can be set by a request interceptor, and trusting an absurd value would turn a request that merely fails + * into an {@link OutOfMemoryError}. Bodies larger than this still read correctly, just via the growing path below. + */ + private static final int MAX_PRESIZED_ALLOCATION = 8 * 1024 * 1024; + + private static final int GROWING_READ_BUFFER_SIZE = 4 * 1024; + private final byte[] content; private final int length; public SimpleHttpContentPublisher(SdkHttpFullRequest request) { - this.content = request.contentStreamProvider().map(p -> invokeSafely(() -> IoUtils.toByteArray(p.newStream()))) - .orElseGet(() -> new byte[0]); + this(request, MAX_PRESIZED_ALLOCATION); + } + + @SdkTestInternalApi + SimpleHttpContentPublisher(SdkHttpFullRequest request, int maxPresizedAllocation) { + this.content = readContent(request, maxPresizedAllocation); this.length = content.length; } @@ -52,6 +73,106 @@ public void subscribe(Subscriber s) { s.onSubscribe(new SubscriptionImpl(s)); } + private static byte[] readContent(SdkHttpFullRequest request, int maxPresizedAllocation) { + ContentStreamProvider provider = request.contentStreamProvider().orElse(null); + if (provider == null) { + return EMPTY_CONTENT; + } + return invokeSafely(() -> readFully(provider.newStream(), presizeHint(request, maxPresizedAllocation))); + } + + /** + * Reads {@code stream} into an exactly-sized array. + * + *

    When the length is known up front this allocates the result array once and reads straight into it. That avoids + * the staging buffer, the doubling reallocations and the final defensive copy that + * {@link IoUtils#toByteArray(InputStream)} needs in order to handle an unknown length. + * + *

    The stream is deliberately not closed, matching the previous behavior: some + * {@link ContentStreamProvider} implementations (notably {@link ContentStreamProvider#fromInputStream(InputStream)}) + * hand back the same stream on every call and rely on mark/reset, so closing it here would break the next retry + * attempt. + * + * @param presizeHint expected length, or a negative number if unknown. + */ + private static byte[] readFully(InputStream stream, int presizeHint) throws IOException { + if (presizeHint < 0) { + return IoUtils.toByteArray(stream); + } + + byte[] buffer = new byte[presizeHint]; + int read = readUpTo(stream, buffer); + + if (read < presizeHint) { + // Stream was shorter than advertised. Trim rather than pad the body with trailing zeros. + byte[] trimmed = new byte[read]; + System.arraycopy(buffer, 0, trimmed, 0, read); + return trimmed; + } + + // Either the stream is longer than advertised, or it is longer than MAX_PRESIZED_ALLOCATION. Read the remainder + // instead of silently truncating the body. + int next = stream.read(); + if (next < 0) { + return buffer; + } + return readRemainder(stream, buffer, next); + } + + /** + * Fills {@code buffer} as far as the stream allows, returning the number of bytes read. + */ + private static int readUpTo(InputStream stream, byte[] buffer) throws IOException { + int read = 0; + while (read < buffer.length) { + int n = stream.read(buffer, read, buffer.length - read); + if (n < 0) { + break; + } + read += n; + } + return read; + } + + private static byte[] readRemainder(InputStream stream, byte[] alreadyRead, int nextByte) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(alreadyRead.length * 2); + out.write(alreadyRead, 0, alreadyRead.length); + out.write(nextByte); + + byte[] chunk = new byte[GROWING_READ_BUFFER_SIZE]; + int n; + while ((n = stream.read(chunk)) != -1) { + out.write(chunk, 0, n); + } + return out.toByteArray(); + } + + /** + * The marshallers and the body-rewriting pipeline stages set {@code Content-Length} for in-memory bodies, so this is + * normally present and exact. + * + * @return the length to pre-allocate, or a negative number if it could not be determined. + */ + private static int presizeHint(SdkHttpFullRequest request, int maxPresizedAllocation) { + return request.firstMatchingHeader(Header.CONTENT_LENGTH) + .map(contentLength -> parsePresizeHint(contentLength, maxPresizedAllocation)) + .orElse(-1); + } + + private static int parsePresizeHint(String contentLength, int maxPresizedAllocation) { + long parsed; + try { + parsed = Long.parseLong(contentLength); + } catch (NumberFormatException e) { + return -1; + } + + if (parsed < 0) { + return -1; + } + return (int) Math.min(parsed, maxPresizedAllocation); + } + private class SubscriptionImpl implements Subscription { private boolean running = true; private final Subscriber s; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmer.java new file mode 100644 index 000000000000..dfd12514da09 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmer.java @@ -0,0 +1,148 @@ +/* + * 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.loader; + +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import org.reactivestreams.Publisher; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.internal.http.async.SimpleHttpContentPublisher; +import software.amazon.awssdk.core.internal.warmup.RegionEndpointResolver; +import software.amazon.awssdk.core.internal.warmup.WarmUpDiscovery; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.http.async.SdkAsyncHttpService; +import software.amazon.awssdk.http.async.SimpleSubscriber; +import software.amazon.awssdk.utils.AttributeMap; +import software.amazon.awssdk.utils.IoUtils; +import software.amazon.awssdk.utils.Logger; + +/** + * Warms every async {@link SdkAsyncHttpService} on the classpath for CRaC warm-up: builds each client and sends a best-effort + * {@code GET} to the resolved STS endpoint, draining the reactive response body, so the HTTP/DNS/TLS/cert-chain code is + * JIT-compiled into the snapshot. + */ +@SdkInternalApi +public final class AsyncHttpClientWarmer implements HttpClientWarmer { + + private static final Logger log = Logger.loggerFor(AsyncHttpClientWarmer.class); + + private static final long WARM_UP_TIMEOUT_SECONDS = 5; + + private final Iterable services; + private final Supplier endpointProvider; + + @SdkTestInternalApi + AsyncHttpClientWarmer(Iterable services, Supplier endpointProvider) { + this.services = services; + this.endpointProvider = endpointProvider; + } + + /** + * Warms a single {@code service} against {@code endpointProvider}. + */ + @SdkTestInternalApi + public static AsyncHttpClientWarmer forService(Supplier endpointProvider, SdkAsyncHttpService service) { + return new AsyncHttpClientWarmer(Collections.singletonList(service), endpointProvider); + } + + public static AsyncHttpClientWarmer create() { + return new AsyncHttpClientWarmer(discoverServices(), () -> RegionEndpointResolver.create().endpoint()); + } + + /** + * Like {@link #create()}, but warms against {@code endpointProvider}. + */ + @SdkTestInternalApi + public static AsyncHttpClientWarmer create(Supplier endpointProvider) { + return new AsyncHttpClientWarmer(discoverServices(), endpointProvider); + } + + private static Iterable discoverServices() { + return () -> SdkServiceLoader.INSTANCE.loadServices(SdkAsyncHttpService.class); + } + + @Override + public void warmAll() { + URI endpoint = endpointProvider.get(); + String userAgent = HttpClientWarmer.warmUpUserAgent(); + WarmUpDiscovery.forEachDiscovered(services.iterator(), service -> { + SdkAsyncHttpClient client = service.createAsyncHttpClientFactory().buildWithDefaults(AttributeMap.empty()); + warmClient(client, endpoint, userAgent); + }); + } + + /** + * Sends the warm-up {@code GET} to {@code endpoint}, drains the response body, and closes the client. Best-effort: any + * failure or timeout is logged and swallowed. We block on the execute future (bounded) because the bundled async + * clients complete it only after the body is drained, so its completion implies the full path was exercised. + */ + private void warmClient(SdkAsyncHttpClient client, URI endpoint, String userAgent) { + try { + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(endpoint) + .putHeader(HEADER_USER_AGENT, userAgent) + .build(); + AsyncExecuteRequest request = AsyncExecuteRequest.builder() + .request(httpRequest) + .requestContentPublisher(new SimpleHttpContentPublisher(httpRequest)) + .responseHandler(new WarmUpResponseHandler()) + .build(); + client.execute(request).get(WARM_UP_TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.debug(() -> "Async HTTP client warm-up call was interrupted (ignored).", e); + } catch (Exception e) { + // Includes ExecutionException for a failed warm-up request; best-effort, so swallow. + log.debug(() -> "Async HTTP client warm-up call failed (ignored).", e); + } finally { + IoUtils.closeQuietlyV2(client, log); + } + } + + /** + * Subscribes a {@link SimpleSubscriber} to drain and discard the response body, exercising the body-read/TLS path. + * The subscription is required: some clients complete the execute future only once the body is consumed. + */ + private static final class WarmUpResponseHandler implements SdkAsyncHttpResponseHandler { + + @Override + public void onHeaders(SdkHttpResponse headers) { + // No-op: warm-up only needs the body drained, not the headers. + } + + @Override + public void onStream(Publisher stream) { + stream.subscribe(new SimpleSubscriber(byteBuffer -> { + // Discard the bytes; warm-up only needs the path exercised. + })); + } + + @Override + public void onError(Throwable error) { + // No-op: failure is surfaced via the execute future, which the caller blocks on. + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvoker.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvoker.java new file mode 100644 index 000000000000..89610b136283 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvoker.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.core.internal.http.loader; + +import java.util.Arrays; +import java.util.List; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; + +/** + * {@link HttpWarmupInvoker} that owns the set of {@link HttpClientWarmer}s and invokes each. + */ +@SdkInternalApi +public final class ClasspathHttpWarmupInvoker implements HttpWarmupInvoker { + + private final List warmers; + + @SdkTestInternalApi + ClasspathHttpWarmupInvoker(List warmers) { + this.warmers = warmers; + } + + /** + * @return an invoker over the HTTP-client warmers on the classpath. + */ + public static HttpWarmupInvoker create() { + return new ClasspathHttpWarmupInvoker( + Arrays.asList(SyncHttpClientWarmer.create(), AsyncHttpClientWarmer.create())); + } + + @Override + public void invokeAll() { + for (HttpClientWarmer warmer : warmers) { + warmer.warmAll(); + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpClientWarmer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpClientWarmer.java new file mode 100644 index 000000000000..9b8aedf3147b --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpClientWarmer.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.core.internal.http.loader; + +import static software.amazon.awssdk.core.internal.useragent.UserAgentConstant.FEATURE_METADATA; +import static software.amazon.awssdk.core.internal.useragent.UserAgentConstant.appendSpaceAndField; + +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.internal.useragent.SdkUserAgentBuilder; +import software.amazon.awssdk.core.util.SystemUserAgent; + +/** + * Warms the sync or async HTTP clients on the classpath for CRaC warm-up. + */ +@SdkInternalApi +public interface HttpClientWarmer { + + String HEADER_USER_AGENT = "User-Agent"; + + String WARM_UP_FEATURE_ID = "warmup"; + + /** + * Warms every HTTP client found on the classpath. Best-effort; never throws. + */ + void warmAll(); + + /** + * Builds the {@code User-Agent} header value for warm-up requests: the system user agent (SDK version, Java version, OS, + * etc.) plus the {@link #WARM_UP_FEATURE_ID} feature marker. + */ + static String warmUpUserAgent() { + StringBuilder uaString = + new StringBuilder(SdkUserAgentBuilder.buildSystemUserAgentString(SystemUserAgent.getOrCreate())); + appendSpaceAndField(uaString, FEATURE_METADATA, WARM_UP_FEATURE_ID); + return uaString.toString(); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpWarmupInvoker.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpWarmupInvoker.java new file mode 100644 index 000000000000..783ec2ca71e5 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/HttpWarmupInvoker.java @@ -0,0 +1,30 @@ +/* + * 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.loader; + +import software.amazon.awssdk.annotations.SdkInternalApi; + +/** + * Warms every HTTP client on the classpath for CRaC warm-up by invoking each {@link HttpClientWarmer}. + */ +@SdkInternalApi +public interface HttpWarmupInvoker { + + /** + * Invokes {@link HttpClientWarmer#warmAll()} on every warmer. Best-effort; never throws. + */ + void invokeAll(); +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmer.java new file mode 100644 index 000000000000..6c8f84e460dc --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmer.java @@ -0,0 +1,118 @@ +/* + * 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.loader; + +import java.net.URI; +import java.util.Collections; +import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.internal.warmup.RegionEndpointResolver; +import software.amazon.awssdk.core.internal.warmup.WarmUpDiscovery; +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.SdkHttpMethod; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.SdkHttpService; +import software.amazon.awssdk.utils.AttributeMap; +import software.amazon.awssdk.utils.IoUtils; +import software.amazon.awssdk.utils.Logger; + +/** + * Warms every sync {@link SdkHttpService} on the classpath for CRaC warm-up: builds each client and sends a best-effort + * {@code GET} to the resolved STS endpoint, draining the response body, so the HTTP/DNS/TLS/cert-chain code is JIT-compiled + * into the snapshot. + */ +@SdkInternalApi +public final class SyncHttpClientWarmer implements HttpClientWarmer { + + private static final Logger log = Logger.loggerFor(SyncHttpClientWarmer.class); + + private final Iterable services; + private final Supplier endpointProvider; + + @SdkTestInternalApi + SyncHttpClientWarmer(Iterable services, Supplier endpointProvider) { + this.services = services; + this.endpointProvider = endpointProvider; + } + + /** + * Warms a single {@code service} against {@code endpointProvider}. + */ + @SdkTestInternalApi + public static SyncHttpClientWarmer forService(Supplier endpointProvider, SdkHttpService service) { + return new SyncHttpClientWarmer(Collections.singletonList(service), endpointProvider); + } + + public static SyncHttpClientWarmer create() { + return new SyncHttpClientWarmer(discoverServices(), () -> RegionEndpointResolver.create().endpoint()); + } + + /** + * Like {@link #create()}, but warms against {@code endpointProvider}. + */ + @SdkTestInternalApi + public static SyncHttpClientWarmer create(Supplier endpointProvider) { + return new SyncHttpClientWarmer(discoverServices(), endpointProvider); + } + + private static Iterable discoverServices() { + return () -> SdkServiceLoader.INSTANCE.loadServices(SdkHttpService.class); + } + + @Override + public void warmAll() { + URI endpoint = endpointProvider.get(); + String userAgent = HttpClientWarmer.warmUpUserAgent(); + WarmUpDiscovery.forEachDiscovered(services.iterator(), service -> { + SdkHttpClient client = service.createHttpClientBuilder().buildWithDefaults(AttributeMap.empty()); + warmClient(client, endpoint, userAgent); + }); + } + + /** + * Sends the warm-up {@code GET} to {@code endpoint}, drains the response body, and closes the client. Best-effort: the + * goal is JIT compilation, not a successful request, so any failure is logged and swallowed. + */ + private void warmClient(SdkHttpClient client, URI endpoint, String userAgent) { + try { + SdkHttpRequest httpRequest = SdkHttpRequest.builder() + .method(SdkHttpMethod.GET) + .uri(endpoint) + .putHeader(HEADER_USER_AGENT, userAgent) + .build(); + HttpExecuteRequest request = HttpExecuteRequest.builder() + .request(httpRequest) + .build(); + ExecutableHttpRequest executableRequest = client.prepareRequest(request); + HttpExecuteResponse response = executableRequest.call(); + response.responseBody().ifPresent(body -> { + try { + IoUtils.drainInputStream(body); + } finally { + IoUtils.closeQuietlyV2(body, log); + } + }); + } catch (Exception e) { + log.debug(() -> "Sync HTTP client warm-up call failed (ignored).", e); + } finally { + IoUtils.closeQuietlyV2(client, log); + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/ApiCallMetricCollectionStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/ApiCallMetricCollectionStage.java deleted file mode 100644 index c7a6783fa7da..000000000000 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/ApiCallMetricCollectionStage.java +++ /dev/null @@ -1,62 +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.time.Duration; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.Response; -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.util.MetricUtils; -import software.amazon.awssdk.core.metrics.CoreMetric; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.metrics.MetricCollector; - -/** - * Wrapper pipeline that tracks the {@link CoreMetric#API_CALL_DURATION} metric. - */ -@SdkInternalApi -public class ApiCallMetricCollectionStage implements RequestToResponsePipeline { - private final RequestPipeline> wrapped; - - public ApiCallMetricCollectionStage(RequestPipeline> wrapped) { - this.wrapped = wrapped; - } - - @Override - public Response execute(SdkHttpFullRequest input, RequestExecutionContext context) throws Exception { - MetricCollector metricCollector = context.executionContext().metricCollector(); - - // Note: at this point, any exception, even a service exception, will - // be thrown from the wrapped pipeline so we can't use - // MetricUtil.measureDuration() - long callStart = System.nanoTime(); - try { - Response response = wrapped.execute(input, context); - return response; - } finally { - long d = System.nanoTime() - callStart; - metricCollector.reportMetric(CoreMetric.API_CALL_DURATION, Duration.ofNanos(d)); - // Collect SERVICE_ENDPOINT after pipeline execution so that EndpointResolutionStage - // has applied the resolved URL to the request. - SdkHttpFullRequest finalRequest = context.executionContext().interceptorContext().httpRequest() != null - ? (SdkHttpFullRequest) context.executionContext().interceptorContext().httpRequest() - : input; - MetricUtils.collectServiceEndpointMetrics(metricCollector, finalRequest); - } - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncApiCallMetricCollectionStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncApiCallMetricCollectionStage.java deleted file mode 100644 index e85a6f752aee..000000000000 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncApiCallMetricCollectionStage.java +++ /dev/null @@ -1,73 +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.time.Duration; -import java.util.concurrent.CompletableFuture; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.util.MetricUtils; -import software.amazon.awssdk.core.metrics.CoreMetric; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.metrics.MetricCollector; -import software.amazon.awssdk.utils.CompletableFutureUtils; - -/** - * Wrapper pipeline that tracks the {@link CoreMetric#API_CALL_DURATION} metric. - */ -@SdkInternalApi -public final class AsyncApiCallMetricCollectionStage implements RequestPipeline> { - private final RequestPipeline> wrapped; - - public AsyncApiCallMetricCollectionStage(RequestPipeline> wrapped) { - this.wrapped = wrapped; - } - - @Override - public CompletableFuture execute(SdkHttpFullRequest input, RequestExecutionContext context) throws Exception { - MetricCollector metricCollector = context.executionContext().metricCollector(); - - CompletableFuture future = new CompletableFuture<>(); - - long callStart = System.nanoTime(); - CompletableFuture executeFuture = wrapped.execute(input, context); - - executeFuture.whenComplete((r, t) -> { - long duration = System.nanoTime() - callStart; - metricCollector.reportMetric(CoreMetric.API_CALL_DURATION, Duration.ofNanos(duration)); - - // Collect SERVICE_ENDPOINT after pipeline execution so that EndpointResolutionStage - // has applied the resolved URL to the request. - SdkHttpFullRequest finalRequest = context.executionContext().interceptorContext().httpRequest() != null - ? (SdkHttpFullRequest) context.executionContext().interceptorContext().httpRequest() - : input; - MetricUtils.collectServiceEndpointMetrics(metricCollector, finalRequest); - - if (t != null) { - future.completeExceptionally(t); - } else { - future.complete(r); - } - }).exceptionally(t -> { - future.completeExceptionally(t); - return null; - }); - - return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); - } -} 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 15b81d30d75f..6d96569ffdb3 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 @@ -22,6 +22,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.Response; import software.amazon.awssdk.core.async.AsyncRequestBody; @@ -36,7 +37,6 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.Either; import software.amazon.awssdk.utils.Logger; /** @@ -90,14 +90,26 @@ public CompletableFuture> execute() { } 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); - } + Thread caller = Thread.currentThread(); + retryableStageHelper.acquireInitialTokenAsync().whenComplete((r, t) -> { + if (t != null) { + future.completeExceptionally(t); + return; + } + + if (!r.isZero()) { + retryableStageHelper.logBackingOff(r); + } + + // Avoid scheduling if there's no delay and we're still on the calling thread (e.g. not on a retry strategy + // owned thread such as the rate limiter + if (r.isZero() && Thread.currentThread().equals(caller)) { + attemptExecute(future); + } else { + scheduleOrFail(() -> attemptExecute(future), r.toMillis(), MILLISECONDS, future); + } + }); + } private void attemptExecute(CompletableFuture> future) { @@ -140,33 +152,42 @@ private void attemptExecute(CompletableFuture> future) { } public void maybeAttemptExecute(CompletableFuture> future) { - Either backoffDelay = retryableStageHelper.tryRefreshToken(suggestedDelay()); - - Optional acquireFailureDelay = backoffDelay.right(); - if (acquireFailureDelay.isPresent()) { - Duration delay = acquireFailureDelay.get(); - retryableStageHelper.logAcquireFailureBackingOff(delay); - SdkException disallowedException = retryableStageHelper.retryPolicyDisallowedRetryException(); - // Avoid needless scheduling if we won't wait - if (delay.isZero()) { - future.completeExceptionally(disallowedException); - } else { - scheduledExecutor.schedule(() -> future.completeExceptionally(disallowedException), - delay.toMillis(), MILLISECONDS); + retryableStageHelper.tryRefreshTokenAsync(suggestedDelay()).whenComplete((backoffDelay, err) -> { + if (err != null) { + future.completeExceptionally(err); + return; } - 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); - // get() is safe, Either requires left OR right to be present - Duration successDelay = backoffDelay.left().get(); - retryableStageHelper.logBackingOff(successDelay); - long totalDelayMillis = successDelay.toMillis(); - scheduledExecutor.schedule(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS); + try { + Optional acquireFailureDelay = backoffDelay.right(); + if (acquireFailureDelay.isPresent()) { + Duration delay = acquireFailureDelay.get(); + retryableStageHelper.logAcquireFailureBackingOff(delay); + SdkException disallowedException = retryableStageHelper.retryPolicyDisallowedRetryException(); + // Avoid needless scheduling if we won't wait + if (delay.isZero()) { + future.completeExceptionally(disallowedException); + } else { + scheduleOrFail(() -> future.completeExceptionally(disallowedException), delay.toMillis(), + MILLISECONDS, future); + } + 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); + + // get() is safe, Either requires left OR right to be present + Duration successDelay = backoffDelay.left().get(); + retryableStageHelper.logBackingOff(successDelay); + long totalDelayMillis = successDelay.toMillis(); + scheduleOrFail(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS, future); + } catch (Throwable t) { + future.completeExceptionally(t); + } + }); } private void maybeRetryExecute(CompletableFuture> future, Exception exception) { @@ -214,4 +235,15 @@ private boolean newRetries2026Enabled(RequestExecutionContext executionContext) .getOptionalAttribute(SdkInternalExecutionAttribute.NEW_RETRIES_2026_ENABLED) .orElse(false); } + + /** + * Schedule the runnable on the scheduled executor, failing the future if the schedule() call fails. + */ + private void scheduleOrFail(Runnable r, long delay, TimeUnit timeUnit, CompletableFuture future) { + try { + scheduledExecutor.schedule(r, delay, timeUnit); + } catch (Throwable t) { + future.completeExceptionally(t); + } + } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStage.java index 5156395c581f..16b78e7e3a35 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStage.java @@ -21,6 +21,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.async.AsyncRequestBody; @@ -38,6 +39,7 @@ import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; @@ -154,6 +156,19 @@ private static void updateAsyncRequestBodyInContexts(RequestExecutionContext con Publisher signedPayload = optionalPayload.get(); if (signedPayload instanceof AsyncRequestBody) { newAsyncRequestBody = (AsyncRequestBody) signedPayload; + } else if (signedPayload instanceof SdkHttpContentPublisher) { + SdkHttpContentPublisher contentPublisher = (SdkHttpContentPublisher) signedPayload; + newAsyncRequestBody = new AsyncRequestBody() { + @Override + public Optional contentLength() { + return contentPublisher.contentLength(); + } + + @Override + public void subscribe(Subscriber s) { + contentPublisher.subscribe(s); + } + }; } else { newAsyncRequestBody = AsyncRequestBody.fromPublisher(signedPayload); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStage.java index 831340b29d16..4c1f5d3b4f8d 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStage.java @@ -114,7 +114,7 @@ private List resolveAuthSchemeOptions(ExecutionAttributes exec if (resolver == null) { return null; } - return resolver.resolve(request); + return resolver.resolve(request, executionAttributes); } /** diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStage.java index 183ace09971c..5dca5af68377 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStage.java @@ -33,6 +33,7 @@ import software.amazon.awssdk.core.internal.http.pipeline.MutableRequestToRequestPipeline; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.utils.StringUtils; @@ -61,6 +62,10 @@ public SdkHttpFullRequest.Builder execute(SdkHttpFullRequest.Builder request, Re return request; } + if (Boolean.TRUE.equals(attrs.getAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION))) { + return request; + } + // Skip if endpoint was already resolved by an old service interceptor Endpoint existingEndpoint = attrs.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT); if (existingEndpoint != null) { @@ -98,27 +103,30 @@ public SdkHttpFullRequest.Builder execute(SdkHttpFullRequest.Builder request, Re ClientEndpointProvider clientEndpointProvider = attrs.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER); if (interceptorModifiedEndpoint(request, attrs)) { - applyResolvedPath(request, clientEndpointProvider.clientEndpoint(), endpoint.url()); + applyResolvedPath(request, clientEndpointProvider.clientEndpoint(), endpoint.endpointUrl()); return request; } - return setUri(request, clientEndpointProvider.clientEndpoint(), endpoint.url()); + return setUri(request, clientEndpointProvider.clientEndpoint(), endpoint.endpointUrl()); } /** - * Detects if an interceptor modified the HTTP request URL in modifyHttpRequest(). - * Compares the current request's host and scheme against the snapshot taken before interceptors ran. + * Detects if an interceptor modified the HTTP request endpoint in modifyHttpRequest(). + * Compares the current request's host, scheme and port against the snapshot taken before interceptors ran. */ private static boolean interceptorModifiedEndpoint(SdkHttpFullRequest.Builder request, ExecutionAttributes attrs) { - URI preModifyUri = attrs.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY); - if (preModifyUri == null) { + EndpointUrl preModifyEndpoint = + attrs.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY); + if (preModifyEndpoint == null) { return false; } String requestHost = request.host(); + if (requestHost == null) { + return false; + } Integer requestPort = request.port(); - return requestHost != null - && (!requestHost.equals(preModifyUri.getHost()) - || !String.valueOf(request.protocol()).equals(preModifyUri.getScheme()) - || (requestPort != null && requestPort != preModifyUri.getPort())); + return !requestHost.equals(preModifyEndpoint.host()) + || !String.valueOf(request.protocol()).equals(preModifyEndpoint.scheme()) + || (requestPort != null && requestPort != preModifyEndpoint.port()); } /** @@ -127,19 +135,19 @@ private static boolean interceptorModifiedEndpoint(SdkHttpFullRequest.Builder re */ private static SdkHttpFullRequest.Builder setUri(SdkHttpFullRequest.Builder request, URI clientEndpoint, - URI resolvedUri) { - applyResolvedPath(request, clientEndpoint, resolvedUri); - return request.protocol(resolvedUri.getScheme()) - .host(resolvedUri.getHost()) - .port(resolvedUri.getPort()); + EndpointUrl resolvedUrl) { + applyResolvedPath(request, clientEndpoint, resolvedUrl); + return request.protocol(resolvedUrl.scheme()) + .host(resolvedUrl.host()) + .port(resolvedUrl.port()); } private static void applyResolvedPath(SdkHttpFullRequest.Builder request, URI clientEndpoint, - URI resolvedUri) { + EndpointUrl resolvedUrl) { String clientEndpointPath = clientEndpoint.getRawPath(); String requestPath = request.encodedPath(); - String resolvedUriPath = resolvedUri.getRawPath(); + String resolvedUriPath = resolvedUrl.encodedPath(); if (!resolvedUriPath.equals(clientEndpointPath)) { request.encodedPath(combinePath(clientEndpointPath, requestPath, resolvedUriPath)); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStage.java index d9845304457f..b7512a00dc37 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStage.java @@ -18,6 +18,7 @@ import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SDK_HTTP_EXECUTION_ATTRIBUTES; import static software.amazon.awssdk.core.internal.http.timers.TimerUtils.resolveTimeoutInMillis; import static software.amazon.awssdk.http.Header.CONTENT_LENGTH; +import static software.amazon.awssdk.http.Header.TRANSFER_ENCODING; import java.nio.ByteBuffer; import java.time.Duration; @@ -246,6 +247,10 @@ private boolean shouldSetContentLength(SdkHttpFullRequest request, SdkHttpConten return false; } + if (request.firstMatchingHeader(TRANSFER_ENCODING).isPresent()) { + return false; + } + return Optional.ofNullable(requestProvider).flatMap(SdkHttpContentPublisher::contentLength).isPresent(); } 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 840df78367fd..5de053302cda 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 @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.Response; @@ -60,6 +61,7 @@ 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 static final String RETRY_TOKEN_SCOPE = "GLOBAL"; private final SdkHttpFullRequest request; private final boolean isLongPollingOperation; @@ -72,6 +74,7 @@ public final class RetryableStageHelper { private SdkHttpResponse lastResponse; private SdkException lastException; + public RetryableStageHelper(SdkHttpFullRequest request, RequestExecutionContext context, HttpClientDependencies dependencies) { @@ -106,14 +109,31 @@ public void startingAttempt() { * 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; + AcquireInitialTokenResponse result = doBlockAcquireInitialToken(); + context.executionAttributes().putAttribute(RETRY_TOKEN, result.token()); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, result.delay()); + return result.delay(); + } + + private AcquireInitialTokenResponse doBlockAcquireInitialToken() { + AcquireInitialTokenRequest acquireRequest = AcquireInitialTokenRequest.create(RETRY_TOKEN_SCOPE); + + return retryStrategy().acquireInitialToken(acquireRequest); + } + + public CompletableFuture acquireInitialTokenAsync() { + AcquireInitialTokenRequest acquireRequest = AcquireInitialTokenRequest.create(RETRY_TOKEN_SCOPE); + + return retryStrategy().acquireInitialTokenAsync(acquireRequest).whenComplete( + (result, t) -> { + if (t != null) { + return; + } + + context.executionAttributes().putAttribute(RETRY_TOKEN, result.token()); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, result.delay()); + }) + .thenApply(AcquireInitialTokenResponse::delay); } /** @@ -138,16 +158,12 @@ public void recordAttemptSucceeded() { * code should not retry. */ public Either tryRefreshToken(Duration suggestedDelay) { - RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); - RefreshRetryTokenResponse refreshResponse; + RetryToken retryToken; + Duration attemptDelay; try { - RefreshRetryTokenRequest refreshRequest = RefreshRetryTokenRequest.builder() - .failure(this.lastException) - .token(retryToken) - .isLongPolling(isLongPollingOperation) - .suggestedDelay(suggestedDelay) - .build(); - refreshResponse = retryStrategy().refreshRetryToken(refreshRequest); + RefreshRetryTokenResponse tryRefreshResult = doBlockingRefreshRetryToken(suggestedDelay); + attemptDelay = tryRefreshResult.delay(); + retryToken = tryRefreshResult.token(); } catch (TokenAcquisitionFailedException e) { context.executionAttributes().putAttribute(RETRY_TOKEN, e.token()); Optional acquireFailureDelay = e.delay(); @@ -158,12 +174,67 @@ public Either tryRefreshToken(Duration suggestedDelay) { } return Either.right(Duration.ZERO); } - Duration acquireSuccessDelay = refreshResponse.delay(); - context.executionAttributes().putAttribute(RETRY_TOKEN, refreshResponse.token()); + Duration acquireSuccessDelay = attemptDelay; + context.executionAttributes().putAttribute(RETRY_TOKEN, retryToken); context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, acquireSuccessDelay); return Either.left(acquireSuccessDelay); } + private RefreshRetryTokenResponse doBlockingRefreshRetryToken(Duration suggestedDelay) { + RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); + + RefreshRetryTokenRequest refreshRequest = RefreshRetryTokenRequest.builder() + .failure(this.lastException) + .token(retryToken) + .isLongPolling(isLongPollingOperation) + .suggestedDelay(suggestedDelay) + .build(); + + return retryStrategy().refreshRetryToken(refreshRequest); + } + + public CompletableFuture> tryRefreshTokenAsync(Duration suggestedDelay) { + CompletableFuture> cf = new CompletableFuture<>(); + + RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); + + RefreshRetryTokenRequest refreshRequest = RefreshRetryTokenRequest.builder() + .failure(this.lastException) + .token(retryToken) + .isLongPolling(isLongPollingOperation) + .suggestedDelay(suggestedDelay) + .build(); + + retryStrategy().refreshRetryTokenAsync(refreshRequest).whenComplete((r, t) -> { + if (t != null) { + Throwable cause = t instanceof CompletionException ? t.getCause() : t; + if (cause instanceof TokenAcquisitionFailedException) { + TokenAcquisitionFailedException e = (TokenAcquisitionFailedException) cause; + + context.executionAttributes().putAttribute(RETRY_TOKEN, e.token()); + Optional acquireFailureDelay = e.delay(); + if (acquireFailureDelay.isPresent()) { + Duration acquireDelay = acquireFailureDelay.get(); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, acquireDelay); + cf.complete(Either.right(acquireDelay)); + return; + } + cf.complete(Either.right(Duration.ZERO)); + } else { + cf.completeExceptionally(t); + } + return; + } + + Duration acquireSuccessDelay = r.delay(); + context.executionAttributes().putAttribute(RETRY_TOKEN, r.token()); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, acquireSuccessDelay); + cf.complete(Either.left(acquireSuccessDelay)); + }); + + return cf; + } + /** * Return the exception that should be thrown, because the retry strategy did not allow the request to be retried. */ diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java index 8849e3dbd78c..003d57e126c8 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java @@ -18,8 +18,6 @@ import static software.amazon.awssdk.core.http.HttpResponseHandler.X_AMZN_REQUEST_ID_HEADERS; import static software.amazon.awssdk.core.http.HttpResponseHandler.X_AMZ_ID_2_HEADER; -import java.net.URI; -import java.net.URISyntaxException; import java.time.Duration; import java.util.OptionalLong; import java.util.concurrent.Callable; @@ -27,7 +25,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; import software.amazon.awssdk.annotations.SdkProtectedApi; -import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; import software.amazon.awssdk.core.metrics.CoreMetric; @@ -38,6 +35,7 @@ import software.amazon.awssdk.metrics.NoOpMetricCollector; import software.amazon.awssdk.metrics.SdkMetric; import software.amazon.awssdk.utils.Pair; +import software.amazon.awssdk.utils.http.SdkHttpUtils; import software.amazon.awssdk.utils.uri.SdkUri; /** @@ -107,19 +105,17 @@ public static Pair measureDurationUnsafe(Callable c, long st /** * Collect the SERVICE_ENDPOINT metric for this request. + * + *

    Only the scheme, host and non-default port are used, so the endpoint string is assembled from the request's + * components directly reducing un-cached URI creations. */ public static void collectServiceEndpointMetrics(MetricCollector metricCollector, SdkHttpFullRequest httpRequest) { if (metricCollector != null && !(metricCollector instanceof NoOpMetricCollector) && httpRequest != null) { - // Only interested in the service endpoint so don't include any path, query, or fragment component - URI requestUri = httpRequest.getUri(); - try { - URI serviceEndpoint = SdkUri.getInstance().newUri( - requestUri.getScheme(), requestUri.getAuthority(), null, null, null); - metricCollector.reportMetric(CoreMetric.SERVICE_ENDPOINT, serviceEndpoint); - } catch (URISyntaxException e) { - // This should not happen since getUri() should return a valid URI - throw SdkClientException.create("Unable to collect SERVICE_ENDPOINT metric", e); - } + String protocol = httpRequest.protocol(); + int port = httpRequest.port(); + String portSuffix = SdkHttpUtils.isUsingStandardPort(protocol, port) ? "" : ":" + port; + metricCollector.reportMetric(CoreMetric.SERVICE_ENDPOINT, + SdkUri.getInstance().create(protocol + "://" + httpRequest.host() + portSuffix)); } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvoker.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvoker.java new file mode 100644 index 000000000000..e72998bc2fbf --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvoker.java @@ -0,0 +1,48 @@ +/* + * 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.warmup; + +import java.util.ServiceLoader; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * {@link WarmUpInvoker} implementation that uses {@link ServiceLoader} to find {@link SdkWarmUpProvider} + * implementations on the classpath and invokes {@code warmUp()} on every one of them. + */ +@SdkInternalApi +public final class ClasspathWarmUpInvoker implements WarmUpInvoker { + + private final WarmUpServiceLoader serviceLoader; + + @SdkTestInternalApi + ClasspathWarmUpInvoker(WarmUpServiceLoader serviceLoader) { + this.serviceLoader = serviceLoader; + } + + @Override + public void invokeAll() { + WarmUpDiscovery.forEachDiscovered(serviceLoader.loadProviders(), SdkWarmUpProvider::warmUp); + } + + /** + * @return ClasspathWarmUpInvoker that discovers {@link SdkWarmUpProvider}s from the classpath. + */ + public static WarmUpInvoker create() { + return new ClasspathWarmUpInvoker(WarmUpServiceLoader.INSTANCE); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolver.java new file mode 100644 index 000000000000..b40b6b83b672 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolver.java @@ -0,0 +1,77 @@ +/* + * 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.warmup; + +import java.net.URI; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.utils.HostnameValidator; +import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.StringUtils; + +/** + * Resolves the endpoint used by the CRaC HTTP-client warm-up. The warm-up targets a single predetermined service; that service + * is currently STS, so this builds the regional STS endpoint ({@code https://sts..amazonaws.com/}). + * + *

    The region is taken from {@link SdkSystemSetting#AWS_REGION} (the {@code aws.region} system property or {@code AWS_REGION} + * environment variable), falling back to {@value #DEFAULT_REGION} when it is unset or not a valid hostname component. This + * matches how the SDK resolves a region from system settings. + * + *

    Only system properties and environment variables are read. The full SDK region-resolution chain (IMDS, profile file) is + * avoided during warm-up because those add network or filesystem calls that may fail or time out. The endpoint host always + * uses the {@code amazonaws.com} suffix, which is incorrect for the China, GovCloud, and ISO partitions; in those partitions + * the warm-up request simply fails and is ignored, since it is best-effort. + */ +@SdkInternalApi +public final class RegionEndpointResolver { + + static final String DEFAULT_REGION = "us-east-1"; + + private static final Logger log = Logger.loggerFor(RegionEndpointResolver.class); + + private RegionEndpointResolver() { + } + + public static RegionEndpointResolver create() { + return new RegionEndpointResolver(); + } + + /** + * @return the regional STS endpoint URI for the resolved region; never null. + */ + public URI endpoint() { + return URI.create("https://sts." + resolveRegion() + ".amazonaws.com/"); + } + + private String resolveRegion() { + // trimToNull turns blank/empty into null so a blank AWS_REGION falls through to the default. + String awsRegion = SdkSystemSetting.AWS_REGION.getStringValue() + .map(StringUtils::trimToNull) + .orElse(null); + if (awsRegion == null) { + return DEFAULT_REGION; + } + // A real region is a hostname-compliant token. Reject anything else so it cannot alter the endpoint host, and fall + // back to the default so the best-effort warm-up still runs. + try { + HostnameValidator.validateHostnameCompliant(awsRegion, "region", "AWS_REGION"); + return awsRegion; + } catch (IllegalArgumentException e) { + log.debug(() -> "Configured region is not a valid hostname component; using " + DEFAULT_REGION + " for warm-up.", e); + return DEFAULT_REGION; + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvoker.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvoker.java new file mode 100644 index 000000000000..7c5269d5da22 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvoker.java @@ -0,0 +1,104 @@ +/* + * 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.warmup; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.utils.Logger; + +/** + * Warms only the service clients named by {@code SdkWarmUp.warmUp(Class...)}. Matches each requested client class name + * against the discovered {@link SdkWarmUpProvider}s' sync and async class names, then warms the matched client type only. + */ +@SdkInternalApi +public final class TargetedWarmUpInvoker { + + private static final Logger log = Logger.loggerFor(TargetedWarmUpInvoker.class); + + private final WarmUpServiceLoader serviceLoader; + + @SdkTestInternalApi + TargetedWarmUpInvoker(WarmUpServiceLoader serviceLoader) { + this.serviceLoader = serviceLoader; + } + + public static TargetedWarmUpInvoker create() { + return new TargetedWarmUpInvoker(WarmUpServiceLoader.INSTANCE); + } + + /** + * Warms the provider client type matching each requested client class name. An unmatched name is logged + * at warn and skipped, and a provider that fails does not stop the others. + * + * @param requestedClassNames the fully qualified sync or async client class names to warm. + * @return the matched client types and the names that warmed successfully. + */ + public TargetedWarmUpResult invoke(Collection requestedClassNames) { + Set matchedClientTypes = EnumSet.noneOf(ClientType.class); + Set warmedClientNames = new LinkedHashSet<>(); + if (requestedClassNames.isEmpty()) { + return new TargetedWarmUpResult(matchedClientTypes, warmedClientNames); + } + + List providers = loadProviders(); + for (String requested : requestedClassNames) { + boolean warmFailed = false; + Set matched = EnumSet.noneOf(ClientType.class); + for (SdkWarmUpProvider provider : providers) { + ClientType clientType = clientTypeFor(requested, provider); + if (clientType == null) { + continue; + } + matched.add(clientType); + if (!WarmUpDiscovery.runSafely(provider.getClass().getName(), + () -> provider.warmUpClient(clientType))) { + warmFailed = true; + } + } + if (matched.isEmpty()) { + log.warn(() -> "No warm-up provider matched client class " + requested + "; skipping."); + } else if (!warmFailed) { + warmedClientNames.add(requested); + } + matchedClientTypes.addAll(matched); + } + return new TargetedWarmUpResult(matchedClientTypes, warmedClientNames); + } + + private ClientType clientTypeFor(String requested, SdkWarmUpProvider provider) { + if (requested.equals(provider.syncClientClassName())) { + return ClientType.SYNC; + } + if (requested.equals(provider.asyncClientClassName())) { + return ClientType.ASYNC; + } + return null; + } + + private List loadProviders() { + List providers = new ArrayList<>(); + WarmUpDiscovery.forEachDiscovered(serviceLoader.loadProviders(), providers::add); + return providers; + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResult.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResult.java new file mode 100644 index 000000000000..aea2192ece26 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResult.java @@ -0,0 +1,78 @@ +/* + * 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.warmup; + +import java.util.Collections; +import java.util.Set; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.utils.ToString; + +/** + * Outcome of a {@link TargetedWarmUpInvoker} run: the client types that matched and the client names that warmed + * successfully. + */ +@SdkInternalApi +public final class TargetedWarmUpResult { + + private final Set matchedClientTypes; + private final Set warmedClientNames; + + TargetedWarmUpResult(Set matchedClientTypes, Set warmedClientNames) { + this.matchedClientTypes = Collections.unmodifiableSet(matchedClientTypes); + this.warmedClientNames = Collections.unmodifiableSet(warmedClientNames); + } + + public Set matchedClientTypes() { + return matchedClientTypes; + } + + public Set warmedClientNames() { + return warmedClientNames; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + TargetedWarmUpResult that = (TargetedWarmUpResult) o; + + if (!matchedClientTypes.equals(that.matchedClientTypes)) { + return false; + } + return warmedClientNames.equals(that.warmedClientNames); + } + + @Override + public int hashCode() { + int result = matchedClientTypes.hashCode(); + result = 31 * result + warmedClientNames.hashCode(); + return result; + } + + @Override + public String toString() { + return ToString.builder("TargetedWarmUpResult") + .add("matchedClientTypes", matchedClientTypes) + .add("warmedClientNames", warmedClientNames) + .build(); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpDiscovery.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpDiscovery.java new file mode 100644 index 000000000000..f275b1d0d360 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpDiscovery.java @@ -0,0 +1,78 @@ +/* + * 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.warmup; + +import java.util.Iterator; +import java.util.ServiceConfigurationError; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.utils.Logger; + +/** + * Shared best-effort helpers for the CRaC warm-up paths: {@link java.util.ServiceLoader} iteration and running a + * single warm-up task without letting its failure stop the others. + */ +@SdkInternalApi +public final class WarmUpDiscovery { + + private static final Logger log = Logger.loggerFor(WarmUpDiscovery.class); + + private WarmUpDiscovery() { + } + + /** + * Applies {@code action} to every discovered element, skipping (and logging at warn) any element that fails to load or + * whose action throws, so the rest still run. Logs at debug when nothing is discovered. + */ + public static void forEachDiscovered(Iterator iterator, Consumer action) { + boolean discoveredAny = false; + while (iterator.hasNext()) { + T element; + try { + element = iterator.next(); + } catch (ServiceConfigurationError e) { + // next() has already advanced past the bad element, so it is safe to continue to the next one. + log.warn(() -> "Skipping a warm-up task that could not be loaded.", e); + continue; + } + + discoveredAny = true; + T discovered = element; + runSafely(discovered.getClass().getName(), () -> action.accept(discovered)); + } + + if (!discoveredAny) { + log.debug(() -> "No warm-up tasks were discovered on the classpath."); + } + } + + /** + * Runs one warm-up {@code task}. Returns {@code true} if it completed. If it fails, logs at warn with + * {@code description} and returns {@code false}, so a sibling task still runs. + * + *

    Also catches {@link LinkageError}: a task can fail to link (missing dependency or native library) and that + * is an {@link Error}, not an {@link Exception}. Other errors still propagate. + */ + public static boolean runSafely(String description, Runnable task) { + try { + task.run(); + return true; + } catch (RuntimeException | LinkageError e) { + log.warn(() -> "Warm-up failed for " + description + " and was skipped.", e); + return false; + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpInvoker.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpInvoker.java new file mode 100644 index 000000000000..437c263fe7f6 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpInvoker.java @@ -0,0 +1,34 @@ +/* + * 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.warmup; + +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Discovers {@link SdkWarmUpProvider}s and invokes their warm-up behind the public {@code SdkWarmUp.warmUp()}. + * Mirrors the {@code SdkHttpServiceProvider} loader abstraction, except warm-up invokes every discovered + * provider rather than selecting one. + */ +@SdkInternalApi +public interface WarmUpInvoker { + + /** + * Invokes {@link SdkWarmUpProvider#warmUp()} on every discovered provider, containing per-provider failures + * so one failing provider does not stop the others. + */ + void invokeAll(); +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpServiceLoader.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpServiceLoader.java new file mode 100644 index 000000000000..7cdfce3d89ca --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmUpServiceLoader.java @@ -0,0 +1,36 @@ +/* + * 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.warmup; + +import java.util.Iterator; +import java.util.ServiceLoader; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.internal.util.ClassLoaderHelper; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Thin layer over {@link ServiceLoader} for {@link SdkWarmUpProvider}. + */ +@SdkInternalApi +class WarmUpServiceLoader { + + public static final WarmUpServiceLoader INSTANCE = new WarmUpServiceLoader(); + + Iterator loadProviders() { + return ServiceLoader.load(SdkWarmUpProvider.class, + ClassLoaderHelper.classLoader(WarmUpServiceLoader.class)).iterator(); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistry.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistry.java new file mode 100644 index 000000000000..38d5981241ec --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistry.java @@ -0,0 +1,55 @@ +/* + * 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.warmup; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.ThreadSafe; + +/** + * Tracks which service clients {@code SdkWarmUp.warmUp(Class...)} has already warmed, so each is warmed at most once per + * JVM. State is per-instance, so it is unit-testable with fresh instances; production uses a single long-lived instance. + */ +@ThreadSafe +@SdkInternalApi +public final class WarmedClientRegistry { + + private final Set warmed = ConcurrentHashMap.newKeySet(); + + /** + * Returns the not-yet-warmed subset of {@code clientClassNames}, in encounter order, ignoring nulls. Warm the + * returned names, then pass them to {@link #markWarmed(Collection)}. + */ + public Set selectUnwarmed(Collection clientClassNames) { + Set unwarmed = new LinkedHashSet<>(); + for (String name : clientClassNames) { + if (name != null && !warmed.contains(name)) { + unwarmed.add(name); + } + } + return unwarmed; + } + + /** + * Records the given names as warmed. Call only after warming completes, so a failed run is retried by a later call. + */ + public void markWarmed(Collection clientClassNames) { + warmed.addAll(clientClassNames); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistry.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistry.java new file mode 100644 index 000000000000..cb981e55274c --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistry.java @@ -0,0 +1,53 @@ +/* + * 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.warmup; + +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.core.ClientType; + +/** + * Tracks whether each HTTP client type has been warmed, so {@code SdkWarmUp.warmUp(Class...)} warms each at most once + * per JVM. Only {@link ClientType#SYNC} and {@link ClientType#ASYNC} are tracked. + */ +@ThreadSafe +@SdkInternalApi +public final class WarmedHttpClientTypeRegistry { + + private volatile boolean syncWarmed; + private volatile boolean asyncWarmed; + + public boolean isWarmed(ClientType clientType) { + if (clientType == ClientType.SYNC) { + return syncWarmed; + } + if (clientType == ClientType.ASYNC) { + return asyncWarmed; + } + return false; + } + + /** + * Mark only after warming completes, so a failed run is retried later. + */ + public void markWarmed(ClientType clientType) { + if (clientType == ClientType.SYNC) { + syncWarmed = true; + } else if (clientType == ClientType.ASYNC) { + asyncWarmed = true; + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java index d29274e28fa7..60939d869dd5 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java @@ -60,10 +60,22 @@ public final class CoreMetric { metric("ServiceEndpoint", URI.class, MetricLevel.ERROR); /** - * The duration of the API call. This includes all call attempts made. + * The duration of the API call. This includes all call attempts made and all interceptors. * - *

    {@code API_CALL_DURATION ~= CREDENTIALS_FETCH_DURATION + MARSHALLING_DURATION + SUM_ALL(BACKOFF_DELAY_DURATION) + - * SUM_ALL(SIGNING_DURATION) + SUM_ALL(SERVICE_CALL_DURATION) + SUM_ALL(UNMARSHALLING_DURATION)} + *

    For an asynchronous client the measurement ends when the returned + * {@link java.util.concurrent.CompletableFuture} completes, which for a streaming operation is when the response + * transformer completes. + * + *

    {@code API_CALL_DURATION ~= CREDENTIALS_FETCH_DURATION + MARSHALLING_DURATION + ENDPOINT_RESOLVE_DURATION + + * SUM_ALL(BACKOFF_DELAY_DURATION) + SUM_ALL(SIGNING_DURATION) + SUM_ALL(SERVICE_CALL_DURATION) + + * SUM_ALL(UNMARSHALLING_DURATION)} + * + *

    The relation is approximate because several steps inside the window have no metric of their own including + * request compression and checksum computation. + * + *

    This is not bounded by a configured + * {@link software.amazon.awssdk.core.client.config.ClientOverrideConfiguration.Builder#apiCallTimeout(Duration) + * apiCallTimeout}, which covers a narrower window that excludes marshalling and the interceptors. */ public static final SdkMetric API_CALL_DURATION = metric("ApiCallDuration", Duration.class, MetricLevel.INFO); diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/spi/identity/AuthSchemeOptionsResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/spi/identity/AuthSchemeOptionsResolver.java index 7a37d7c3dd6b..0dec086cea1c 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/spi/identity/AuthSchemeOptionsResolver.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/spi/identity/AuthSchemeOptionsResolver.java @@ -18,6 +18,7 @@ import java.util.List; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; /** @@ -26,14 +27,14 @@ * This allows auth scheme resolution to happen after interceptors have modified the request, * ensuring that any request modifications affecting auth scheme selection are respected. */ -@FunctionalInterface @SdkProtectedApi public interface AuthSchemeOptionsResolver { /** - * Resolves auth scheme options for the given request. + * Resolves auth scheme options for the given request and execution attributes. * * @param request The request (after interceptors have modified it) + * @param executionAttributes The execution attributes for the current request execution * @return List of auth scheme options in priority order */ - List resolve(SdkRequest request); + List resolve(SdkRequest request, ExecutionAttributes executionAttributes); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/waiters/WaiterOverrideConfiguration.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/waiters/WaiterOverrideConfiguration.java index 8c3bab41fa6c..7d3762f389ed 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/waiters/WaiterOverrideConfiguration.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/waiters/WaiterOverrideConfiguration.java @@ -176,6 +176,9 @@ public Builder backoffStrategyV2(BackoffStrategy backoffStrategy) { /** * Define the maximum number of attempts to try before transitioning the waiter to a failure state. * + *

    {@code maxAttempts} works alongside {@link #waitTimeout(Duration)}, which, when set, acts as an upper bound + * on the total wait time. The waiter transitions to a failure state as soon as either limit is reached. + * * @param maxAttempts The new maxAttempts value. * @return This object for method chaining. */ @@ -189,6 +192,16 @@ public Builder maxAttempts(Integer maxAttempts) { * timeout doesn't have strict guarantees on how quickly a request is aborted when the timeout is breached. The request * can timeout early if it is determined that the next retry will breach the max wait time. It's disabled by default. * + *

    When set, {@code waitTimeout} is an upper bound on the total wait time and works alongside + * {@link #maxAttempts(Integer)}, which caps the number of polling attempts (with a service-provided default). The + * waiter transitions to a failure state as soon as either limit is reached — the waiter may error out at the + * attempt limit before {@code waitTimeout} elapses. For example, if a service defines a default {@code maxAttempts=100} + * with a 6-second delay between polls, setting only {@code waitTimeout(Duration.ofMinutes(30))} still terminates the + * waiter at ~10 minutes because {@code maxAttempts} is reached first. + * + *

    To wait longer than the service-provided default, override {@link #maxAttempts(Integer)} to increase the number + * of polling attempts or {@link #backoffStrategyV2(BackoffStrategy)} to lengthen the delay between polls. + * * @param waitTimeout The new waitTimeout value. * @return This object for method chaining. */ diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUp.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUp.java new file mode 100644 index 000000000000..2b55d3ebaaee --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUp.java @@ -0,0 +1,148 @@ +/* + * 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.warmup; + +import java.util.LinkedHashSet; +import java.util.ServiceLoader; +import java.util.Set; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.core.internal.http.loader.AsyncHttpClientWarmer; +import software.amazon.awssdk.core.internal.http.loader.ClasspathHttpWarmupInvoker; +import software.amazon.awssdk.core.internal.http.loader.SyncHttpClientWarmer; +import software.amazon.awssdk.core.internal.warmup.ClasspathWarmUpInvoker; +import software.amazon.awssdk.core.internal.warmup.TargetedWarmUpInvoker; +import software.amazon.awssdk.core.internal.warmup.TargetedWarmUpResult; +import software.amazon.awssdk.core.internal.warmup.WarmedClientRegistry; +import software.amazon.awssdk.core.internal.warmup.WarmedHttpClientTypeRegistry; +import software.amazon.awssdk.utils.Logger; + +/** + * Entry point for warming up SDK service request paths before a Coordinated Restore at Checkpoint (CRaC) + * checkpoint. + * + *

    {@link #warmUp()} discovers every {@link SdkWarmUpProvider} registered on the classpath through {@link + * ServiceLoader} (via the {@code META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider} + * resource) and invokes {@link SdkWarmUpProvider#warmUp()} on each. + * + *

    Behavior contract: + *

      + *
    • Idempotent: {@code warmUp()} runs the warm-up at most once per JVM. Once a call completes + * successfully, later calls return immediately. If a call throws before completing, a later call retries. + * Concurrent callers block until the in-flight call finishes, then observe its result.
    • + *
    • Per-provider resilience: a single provider that throws from {@code warmUp()}, or that fails + * to load, does not prevent the remaining providers from running.
    • + *
    • Safe when empty: if no providers are registered, {@code warmUp()} is a no-op.
    • + *
    + * + *

    Call this once during application initialization, before a CRaC checkpoint is taken. + */ +@ThreadSafe +@SdkPublicApi +public final class SdkWarmUp { + + private static final Logger log = Logger.loggerFor(SdkWarmUp.class); + + private static final Object WARM_UP_LOCK = new Object(); + + private static volatile boolean warmedUp = false; + + // Tracks per-service work already done, keyed by service-client class name. + private static final WarmedClientRegistry WARMED_CLIENTS = new WarmedClientRegistry(); + + // Tracks the service-independent HTTP-layer warm-up, keyed by client type, so it runs at most once per type. + private static final WarmedHttpClientTypeRegistry WARMED_HTTP_CLIENT_TYPES = new WarmedHttpClientTypeRegistry(); + + private SdkWarmUp() { + } + + /** + * Discovers every {@link SdkWarmUpProvider} on the classpath and invokes {@link SdkWarmUpProvider#warmUp()} + * on each, honoring the idempotency, per-provider resilience, and empty-classpath behavior described on + * this class. Safe to call concurrently. + * + *

    This method and {@link #warmUp(Class[])} track warmed state independently: this method warms + * every provider and does not skip clients that were warmed by a targeted {@link #warmUp(Class[])} call. + */ + public static void warmUp() { + if (warmedUp) { + return; + } + synchronized (WARM_UP_LOCK) { + if (warmedUp) { + return; + } + // Set warmedUp only after invokeAll() succeeds, so a failed run leaves it false and a later call retries. + ClasspathWarmUpInvoker.create().invokeAll(); + ClasspathHttpWarmupInvoker.create().invokeAll(); + warmedUp = true; + } + } + + /** + * Warms up only the given service clients, warming the sync path for a sync client and the async path for an async + * client. A client already warmed by this method is skipped; a class matched by no provider, or whose warm-up + * fails, is logged at warn and retried on the next call. The HTTP clients on the classpath are warmed at most + * once across all calls to this method. Best-effort and safe to call concurrently. + * + *

    This method and {@link #warmUp()} track warmed state independently: this method does not skip + * clients that {@link #warmUp()} already warmed. + * + * @param clients the service client classes to warm up, for example {@code ServiceClient.class} or + * {@code ServiceAsyncClient.class}. + */ + @SafeVarargs + public static void warmUp(Class... clients) { + if (clients == null || clients.length == 0) { + log.debug(() -> "SdkWarmUp.warmUp(Class...) called with no clients; nothing to do."); + return; + } + + Set requested = new LinkedHashSet<>(); + for (Class client : clients) { + if (client != null) { + requested.add(client.getName()); + } + } + Set toWarmUp = WARMED_CLIENTS.selectUnwarmed(requested); + if (toWarmUp.isEmpty()) { + return; + } + + // Racing calls may double-warm the same client; warming is idempotent, so that is harmless. + TargetedWarmUpResult result = TargetedWarmUpInvoker.create().invoke(toWarmUp); + warmHttpClientsOnce(result.matchedClientTypes()); + + // Only successfully warmed names are recorded; unmatched or failed ones are retried on a later call. + WARMED_CLIENTS.markWarmed(result.warmedClientNames()); + } + + /** + * Warms the HTTP clients for the given client types, skipping types already warmed by an earlier call. + */ + private static void warmHttpClientsOnce(Set matchedClientTypes) { + if (matchedClientTypes.contains(ClientType.SYNC) && !WARMED_HTTP_CLIENT_TYPES.isWarmed(ClientType.SYNC)) { + SyncHttpClientWarmer.create().warmAll(); + WARMED_HTTP_CLIENT_TYPES.markWarmed(ClientType.SYNC); + } + if (matchedClientTypes.contains(ClientType.ASYNC) && !WARMED_HTTP_CLIENT_TYPES.isWarmed(ClientType.ASYNC)) { + AsyncHttpClientWarmer.create().warmAll(); + WARMED_HTTP_CLIENT_TYPES.markWarmed(ClientType.ASYNC); + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUpProvider.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUpProvider.java new file mode 100644 index 000000000000..478486ce3085 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/SdkWarmUpProvider.java @@ -0,0 +1,63 @@ +/* + * 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.warmup; + +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.internal.warmup.WarmUpDiscovery; + +/** + * Service Provider Interface for warming up an SDK service's request path before a Coordinated Restore at Checkpoint + * (CRaC) checkpoint. The SDK discovers implementations on the classpath with {@link java.util.ServiceLoader}. An + * implementation registers itself in the + * {@code META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider} resource. + * + *

    + * Implementations must be thread safe. + */ +@ThreadSafe +@SdkProtectedApi +public interface SdkWarmUpProvider { + + /** + * Exercises the service's request path so the Just-In-Time compiled code is captured in a CRaC snapshot. The sync + * and async clients are warmed independently: a failure warming one is logged at warn and does not stop the other. + */ + default void warmUp() { + WarmUpDiscovery.runSafely(syncClientClassName(), () -> warmUpClient(ClientType.SYNC)); + WarmUpDiscovery.runSafely(asyncClientClassName(), () -> warmUpClient(ClientType.ASYNC)); + } + + /** + * The fully qualified name of the sync service client this provider warms (for example + * {@code "software.amazon.awssdk.services.s3.S3Client"}), or {@code null} if the service has no sync client. + */ + String syncClientClassName(); + + /** + * The fully qualified name of the async service client this provider warms (for example + * {@code "software.amazon.awssdk.services.s3.S3AsyncClient"}), or {@code null} if the service has no async + * client. + */ + String asyncClientClassName(); + + /** + * Exercises only the request path of the given client type: {@link ClientType#SYNC} warms the sync client, + * {@link ClientType#ASYNC} the async client. Any other value is a no-op. + */ + void warmUpClient(ClientType clientType); +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClient.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClient.java new file mode 100644 index 000000000000..5931607f1af3 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClient.java @@ -0,0 +1,116 @@ +/* + * 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.warmup.http; + +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.Immutable; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.utils.async.SimplePublisher; +import software.amazon.awssdk.utils.builder.SdkBuilder; + +/** + * An {@link SdkAsyncHttpClient} that completes every request with caller-supplied response bytes without performing any + * network I/O. It is the async counterpart of {@link CannedResponseHttpClient}, used to warm the async request pipeline for a + * CRaC checkpoint. + * + *

    + * Each {@link #execute(AsyncExecuteRequest)} signals the configured status code, publishes the response bytes through a + * {@link SimplePublisher}, and returns an already-completed future. + */ +@SdkProtectedApi +@Immutable +@ThreadSafe +public final class CannedResponseAsyncHttpClient implements SdkAsyncHttpClient { + + private static final int DEFAULT_STATUS_CODE = 200; + private static final byte[] EMPTY_BODY = new byte[0]; + + private final byte[] responseBody; + private final int statusCode; + + private CannedResponseAsyncHttpClient(DefaultBuilder builder) { + this.responseBody = builder.responseBody == null ? EMPTY_BODY : builder.responseBody.clone(); + this.statusCode = builder.statusCode == null ? DEFAULT_STATUS_CODE : builder.statusCode; + } + + public static Builder builder() { + return new DefaultBuilder(); + } + + @Override + public CompletableFuture execute(AsyncExecuteRequest request) { + request.responseHandler().onHeaders(SdkHttpResponse.builder().statusCode(statusCode).build()); + + SimplePublisher bodyPublisher = new SimplePublisher<>(); + request.responseHandler().onStream(bodyPublisher); + if (responseBody.length > 0) { + bodyPublisher.send(ByteBuffer.wrap(responseBody)); + } + bodyPublisher.complete(); + + return CompletableFuture.completedFuture(null); + } + + @Override + public String clientName() { + return "CannedResponseAsync"; + } + + @Override + public void close() { + } + + public interface Builder extends SdkBuilder { + + /** + * The response body published by every {@link #execute(AsyncExecuteRequest)}. Optional; defaults to an empty body. + */ + Builder responseBody(byte[] responseBody); + + /** + * The HTTP status code signalled by every {@link #execute(AsyncExecuteRequest)}. Defaults to {@code 200}. + */ + Builder statusCode(int statusCode); + } + + private static final class DefaultBuilder implements Builder { + + private byte[] responseBody; + private Integer statusCode; + + @Override + public Builder responseBody(byte[] responseBody) { + this.responseBody = responseBody; + return this; + } + + @Override + public Builder statusCode(int statusCode) { + this.statusCode = statusCode; + return this; + } + + @Override + public CannedResponseAsyncHttpClient build() { + return new CannedResponseAsyncHttpClient(this); + } + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClient.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClient.java new file mode 100644 index 000000000000..26bc71359731 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClient.java @@ -0,0 +1,123 @@ +/* + * 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.warmup.http; + +import java.io.ByteArrayInputStream; +import software.amazon.awssdk.annotations.Immutable; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.http.AbortableInputStream; +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.SdkHttpResponse; +import software.amazon.awssdk.utils.builder.SdkBuilder; + +/** + * An {@link SdkHttpClient} that returns caller-supplied response bytes without performing any network I/O. + * + *

    + * Each {@link ExecutableHttpRequest#call()} returns the configured status code and a fresh stream over the response bytes. + */ +@SdkProtectedApi +@Immutable +@ThreadSafe +public final class CannedResponseHttpClient implements SdkHttpClient { + + private static final int DEFAULT_STATUS_CODE = 200; + private static final byte[] EMPTY_BODY = new byte[0]; + + private final byte[] responseBody; + private final int statusCode; + + private CannedResponseHttpClient(DefaultBuilder builder) { + this.responseBody = builder.responseBody == null ? EMPTY_BODY : builder.responseBody.clone(); + this.statusCode = builder.statusCode == null ? DEFAULT_STATUS_CODE : builder.statusCode; + } + + public static Builder builder() { + return new DefaultBuilder(); + } + + @Override + public ExecutableHttpRequest prepareRequest(HttpExecuteRequest request) { + return new CannedExecutableRequest(); + } + + @Override + public String clientName() { + return "CannedResponseSync"; + } + + @Override + public void close() { + } + + public interface Builder extends SdkBuilder { + + /** + * The response body returned by every {@link ExecutableHttpRequest#call()}. Optional; defaults to an empty body. + */ + Builder responseBody(byte[] responseBody); + + /** + * The HTTP status code returned by every {@link ExecutableHttpRequest#call()}. Defaults to {@code 200}. + */ + Builder statusCode(int statusCode); + } + + private static final class DefaultBuilder implements Builder { + + private byte[] responseBody; + private Integer statusCode; + + @Override + public Builder responseBody(byte[] responseBody) { + this.responseBody = responseBody; + return this; + } + + @Override + public Builder statusCode(int statusCode) { + this.statusCode = statusCode; + return this; + } + + @Override + public CannedResponseHttpClient build() { + return new CannedResponseHttpClient(this); + } + } + + private final class CannedExecutableRequest implements ExecutableHttpRequest { + + @Override + public HttpExecuteResponse call() { + AbortableInputStream body = AbortableInputStream.create(new ByteArrayInputStream(responseBody)); + return HttpExecuteResponse.builder() + .response(SdkHttpResponse.builder() + .statusCode(statusCode) + .build()) + .responseBody(body) + .build(); + } + + @Override + public void abort() { + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/ClientEndpointProviderTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/ClientEndpointProviderTest.java new file mode 100644 index 000000000000..43846d815357 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/ClientEndpointProviderTest.java @@ -0,0 +1,107 @@ +/* + * 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; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +/** + * Covers {@link ClientEndpointProvider#sanitizedEndpointString()}'s default implementation, which is the value generated + * endpoint resolvers receive as the {@code SDK::Endpoint} built-in. + * + *

    Every provider the SDK itself installs is a {@code StaticClientEndpointProvider}, which overrides the method with a + * value computed once at construction. The default therefore runs only for an external implementor, and it exists to be + * the single definition of the transformation that the overriding implementation caches. Both halves are asserted here: + * what the transformation does, and that the two forms agree. + */ +class ClientEndpointProviderTest { + /** + * A provider that leaves {@code sanitizedEndpointString()} to the interface, which is what an external implementor + * gets and what no SDK code path produces. + */ + private static ClientEndpointProvider defaultImplementation(URI uri, boolean isEndpointOverridden) { + return new ClientEndpointProvider() { + @Override + public URI clientEndpoint() { + return uri; + } + + @Override + public boolean isEndpointOverridden() { + return isEndpointOverridden; + } + }; + } + + @ParameterizedTest + @CsvSource({ + // Query parameters are rejected by the rules engine's ParseURL, which is why they are stripped. + "https://example.com/path?foo=bar, https://example.com/path", + "https://example.com?foo=bar, https://example.com", + "https://example.com/path?foo=bar&baz=qux, https://example.com/path", + // User-info is stripped for the same reason: it is not part of what the rules engine resolves against. + "https://user:pass@example.com/path, https://example.com/path", + "https://user@example.com, https://example.com", + "https://user:pass@example.com/path?foo=bar,https://example.com/path", + // Everything else survives untouched. + "https://example.com:8443/path, https://example.com:8443/path", + "http://example.com/path, http://example.com/path", + "https://example.com/path#frag, https://example.com/path#frag", + "https://example.com/a/b/c, https://example.com/a/b/c" + }) + void sanitizedEndpointString_stripsQueryAndUserInfo(String input, String expected) { + assertThat(defaultImplementation(URI.create(input), true).sanitizedEndpointString()).isEqualTo(expected); + } + + @Test + void sanitizedEndpointString_returnsNullWhenNotOverridden() { + URI uri = URI.create("https://example.com/path?foo=bar"); + + assertThat(defaultImplementation(uri, false).sanitizedEndpointString()).isNull(); + assertThat(ClientEndpointProvider.create(uri, false).sanitizedEndpointString()).isNull(); + } + + /** + * The claim that makes it safe for {@code StaticClientEndpointProvider} to compute this once at construction: the + * cached value and the recomputed one cannot disagree, because there is one definition of the transformation. + */ + @ParameterizedTest + @CsvSource({ + "https://example.com/path?foo=bar", + "https://user:pass@example.com/path?foo=bar", + "https://example.com:8443/path", + "https://example.com/path#frag", + "http://example.com" + }) + void sanitizedEndpointString_cachedFormMatchesRecomputedForm(String input) { + URI uri = URI.create(input); + + assertThat(ClientEndpointProvider.create(uri, true).sanitizedEndpointString()) + .isEqualTo(defaultImplementation(uri, true).sanitizedEndpointString()); + } + + @Test + void sanitizedEndpointString_overridingImplementationReturnsAStableReference() { + ClientEndpointProvider provider = ClientEndpointProvider.forEndpointOverride( + URI.create("https://example.com/path?foo=bar")); + + assertThat(provider.sanitizedEndpointString()).isSameAs(provider.sanitizedEndpointString()); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/listener/NotifyingAsyncRequestBodyTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/listener/NotifyingAsyncRequestBodyTest.java index 22ba94852e82..a0c40296c868 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/listener/NotifyingAsyncRequestBodyTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/listener/NotifyingAsyncRequestBodyTest.java @@ -15,16 +15,24 @@ package software.amazon.awssdk.core.async.listener; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.function.Consumer; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.reactivestreams.Subscriber; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncRequestBody.BodyType; import software.amazon.awssdk.core.async.AsyncRequestBodySplitConfiguration; public class NotifyingAsyncRequestBodyTest { @@ -55,6 +63,35 @@ public void contentType_delegatesCall() { verify(mockRequestBody).contentType(); } + @Test + public void body_delegatesCall() { + AsyncRequestBodyListener.NotifyingAsyncRequestBody notifying = + new AsyncRequestBodyListener.NotifyingAsyncRequestBody(mockRequestBody, mockListener); + + notifying.body(); + verify(mockRequestBody).body(); + } + + @Test + public void body_wrappingFileRequestBody_returnsFile() throws IOException { + FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); + Path path = fs.getPath("./test"); + Files.write(path, "Hello world".getBytes()); + + AsyncRequestBodyListener.NotifyingAsyncRequestBody notifying = + new AsyncRequestBodyListener.NotifyingAsyncRequestBody(AsyncRequestBody.fromFile(path), mockListener); + + assertThat(notifying.body()).isEqualTo(BodyType.FILE.getName()); + } + + @Test + public void body_wrappingBytesRequestBody_returnsBytes() { + AsyncRequestBodyListener.NotifyingAsyncRequestBody notifying = + new AsyncRequestBodyListener.NotifyingAsyncRequestBody(AsyncRequestBody.fromString("Hello world"), mockListener); + + assertThat(notifying.body()).isEqualTo(BodyType.BYTES.getName()); + } + @Test public void subscribe_delegatesCall() { AsyncRequestBodyListener.NotifyingAsyncRequestBody notifying = diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientMetricCollectorExceptionTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientMetricCollectorExceptionTest.java index 52de25b3063f..1362230e5aaa 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientMetricCollectorExceptionTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientMetricCollectorExceptionTest.java @@ -23,7 +23,6 @@ import static software.amazon.awssdk.core.internal.util.AsyncResponseHandlerTestUtils.noOpResponseHandler; import static utils.HttpTestUtils.testAsyncClientBuilder; -import java.time.Duration; import java.util.Collections; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -41,8 +40,8 @@ import software.amazon.awssdk.core.interceptor.ExecutionInterceptorChain; import software.amazon.awssdk.core.interceptor.InterceptorContext; import software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient; -import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.protocol.VoidSdkResponse; +import software.amazon.awssdk.http.HttpMetric; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.http.SdkHttpResponse; @@ -70,11 +69,16 @@ public class AsyncClientMetricCollectorExceptionTest { @Mock private SdkAsyncHttpClient asyncHttpClient; + /** + * This exercises the request pipeline directly rather than going through {@code BaseAsyncClientHandler}, so it + * throws from a metric that the pipeline itself reports. {@code API_CALL_DURATION} is reported by the client handler, + * above the pipeline, so it is not reachable from here. + */ @Test public void exceptionInReportMetricReportedInFuture() { when(metricCollector.createChild(any())).thenReturn(metricCollector); Exception exception = new RuntimeException(MESSAGE); - doThrow(exception).when(metricCollector).reportMetric(eq(CoreMetric.API_CALL_DURATION), any(Duration.class)); + doThrow(exception).when(metricCollector).reportMetric(eq(HttpMetric.HTTP_STATUS_CODE), any(Integer.class)); CompletableFuture responseFuture = makeRequest(); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientRetryStrategyExceptionTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientRetryStrategyExceptionTest.java index 983be14c8451..011df8916320 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientRetryStrategyExceptionTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/AsyncClientRetryStrategyExceptionTest.java @@ -61,6 +61,7 @@ public class AsyncClientRetryStrategyExceptionTest { public void exceptionInInitialTokenReportedInFuture() { Exception exception = new RuntimeException(MESSAGE); when(retryStrategy.acquireInitialToken(any())).thenThrow(exception); + when(retryStrategy.acquireInitialTokenAsync(any())).thenCallRealMethod(); CompletableFuture responseFuture = makeRequest(); @@ -73,8 +74,11 @@ public void exceptionInRefreshTokenReportedInFuture() { AcquireInitialTokenResponse.create(new RetryToken() { }, Duration.ZERO) ); + when(retryStrategy.acquireInitialTokenAsync(any())).thenCallRealMethod(); + Exception exception = new RuntimeException(MESSAGE); when(retryStrategy.refreshRetryToken(any())).thenThrow(exception); + when(retryStrategy.refreshRetryTokenAsync(any())).thenCallRealMethod(); CompletableFuture responseFuture = makeRequest(); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerSignerValidationTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerSignerValidationTest.java index b0c19a521895..e403d29fb8e4 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerSignerValidationTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerSignerValidationTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Arrays; @@ -26,6 +27,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -179,7 +181,6 @@ public void execute_requestHasHttpsEndpoint_usesBearerAuth_succeeds() throws Exc SdkAsyncClientHandler sdkAsyncClientHandler = new SdkAsyncClientHandler(testClientConfiguration()); CompletableFuture execute = sdkAsyncClientHandler.execute(executionParams()); - SdkAsyncHttpResponseHandler capturedHandler = executeRequestCaptor.getValue().responseHandler(); Map> headers = new HashMap<>(); headers.put("foo", Arrays.asList("bar")); @@ -227,10 +228,13 @@ private ClientExecutionParams executionParams() { } private SdkClientConfiguration testClientConfiguration() { + ScheduledExecutorService exec = mock(ScheduledExecutorService.class); + return HttpTestUtils.testClientConfiguration() .toBuilder() .option(SdkClientOption.ASYNC_HTTP_CLIENT, httpClient) .option(SdkAdvancedClientOption.SIGNER, signer) + .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, exec) .build(); } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerTest.java index 6482ab936fc2..ae11cc3c2256 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/AsyncClientHandlerTest.java @@ -18,15 +18,20 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import java.time.Duration; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Test; @@ -41,6 +46,7 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.exception.SdkServiceException; import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.core.runtime.transform.Marshaller; @@ -49,6 +55,7 @@ import software.amazon.awssdk.http.async.AsyncExecuteRequest; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.retries.DefaultRetryStrategy; import utils.HttpTestUtils; import utils.ValidSdkObjects; @@ -108,6 +115,36 @@ public void successfulExecutionCallsResponseHandler() throws Exception { assertThat(actualResponse.sdkHttpResponse().headers()).isEqualTo(headers); } + /** + * The handler reports {@code API_CALL_DURATION} and {@code API_CALL_SUCCESSFUL} from a {@code whenComplete} action on + * the future it returns, so a collector that throws must fail that future rather than be swallowed. + * + *

    Only assertable on the success path. When the source future has already failed and the {@code whenComplete} + * action throws, {@link CompletableFuture} keeps the source exception and discards the action's. The pipeline stage + * this reporting replaced behaved the same way, so that is a pre-existing limitation rather than a new one. + */ + @Test + public void metricCollectorThrowsOnSuccessfulExecution_exceptionReportedInFuture() throws Exception { + MetricCollector metricCollector = mock(MetricCollector.class); + when(metricCollector.createChild(any())).thenReturn(metricCollector); + RuntimeException exception = new RuntimeException("metric collector boom"); + doThrow(exception).when(metricCollector).reportMetric(eq(CoreMetric.API_CALL_DURATION), any(Duration.class)); + + ArgumentCaptor executeRequest = ArgumentCaptor.forClass(AsyncExecuteRequest.class); + + expectRetrievalFromMocks(); + when(httpClient.execute(executeRequest.capture())).thenReturn(httpClientFuture); + when(responseHandler.handle(any(), any())).thenReturn(VoidSdkResponse.builder().build()); + + CompletableFuture responseFuture = + asyncClientHandler.execute(clientExecutionParams().withMetricCollector(metricCollector)); + SdkAsyncHttpResponseHandler capturedHandler = executeRequest.getValue().responseHandler(); + capturedHandler.onHeaders(SdkHttpFullResponse.builder().statusCode(200).build()); + capturedHandler.onStream(new EmptyPublisher<>()); + + assertThatThrownBy(() -> responseFuture.get(1, TimeUnit.SECONDS)).hasRootCause(exception); + } + @Test public void failedExecutionCallsErrorResponseHandler() throws Exception { SdkServiceException exception = SdkServiceException.builder().message("Uh oh!").statusCode(500).build(); @@ -143,10 +180,12 @@ private ClientExecutionParams clientExecutionParams() { } public SdkClientConfiguration clientConfiguration() { + ScheduledExecutorService exec = mock(ScheduledExecutorService.class); return HttpTestUtils.testClientConfiguration().toBuilder() .option(SdkClientOption.ASYNC_HTTP_CLIENT, httpClient) .option(SdkClientOption.RETRY_POLICY, RetryPolicy.none()) .option(SdkClientOption.RETRY_STRATEGY, DefaultRetryStrategy.doNotRetry()) + .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, exec) .build(); } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/SyncClientHandlerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/SyncClientHandlerTest.java index efbc983e6b0e..0da6c741e2f4 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/SyncClientHandlerTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/client/handler/SyncClientHandlerTest.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.core.client.handler; +import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; @@ -22,6 +23,8 @@ import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; +import java.net.URI; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -41,14 +44,20 @@ import software.amazon.awssdk.core.exception.RetryableException; import software.amazon.awssdk.core.exception.SdkServiceException; import software.amazon.awssdk.core.http.HttpResponseHandler; +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.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.runtime.transform.Marshaller; import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.AbortableInputStream; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.ExecutableHttpRequest; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.retries.DefaultRetryStrategy; import utils.HttpTestUtils; @@ -189,6 +198,69 @@ private void mockSuccessfulApiCall() throws Exception { when(responseHandler.handle(any(), any())).thenReturn(VoidSdkResponse.builder().build()); } + /** + * The pre-modify snapshot must never encode the marshalled request's query parameters. For the query and ec2 + * protocols those parameters still hold the entire request payload when the snapshot is taken, so encoding them + * costs a full pass over the payload on every API call, and retaining them keeps the payload alive for the rest of + * the call. Guards the regression fixed in this change. + */ + @Test + public void snapshottedEndpoint_doesNotEncodeOrRetainQueryParameters() throws Exception { + SdkHttpFullRequest.Builder marshalled = + ValidSdkObjects.sdkHttpFullRequest(8080) + .encodedPath("/2015-03-31/functions/my-function/invocations") + .putRawQueryParameter("Qualifier", "prod"); + // A handful of payload-shaped parameters is enough: the assertion is that the query string is absent + // entirely, so any of these appearing in the snapshot is a failure. + for (int i = 0; i < 20; i++) { + marshalled.putRawQueryParameter("MetricData.member." + i + ".Value", "12345.6789"); + } + + List capturedEndpoint = new ArrayList<>(); + List capturedUri = new ArrayList<>(); + ExecutionInterceptor interceptor = new ExecutionInterceptor() { + @Override + public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes attrs) { + capturedEndpoint.add( + attrs.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY)); + capturedUri.add(attrs.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)); + return context.httpRequest(); + } + }; + + SdkSyncClientHandler handler = new SdkSyncClientHandler( + clientConfiguration().toBuilder() + .option(SdkClientOption.EXECUTION_INTERCEPTORS, singletonList(interceptor)) + .build()); + + when(marshaller.marshall(request)).thenReturn(marshalled.build()); + when(httpClient.prepareRequest(any())).thenReturn(httpClientCall); + when(httpClientCall.call()).thenReturn(HttpExecuteResponse.builder() + .response(SdkHttpResponse.builder() + .statusCode(200) + .build()) + .build()); + when(responseHandler.handle(any(), any())).thenReturn(VoidSdkResponse.builder().build()); + + handler.execute(clientExecutionParams()); + + // The endpoint snapshot holds components only; nothing references the query parameters. + assertThat(capturedEndpoint).hasSize(1); + assertThat(capturedEndpoint.get(0).host()).isEqualTo("localhost"); + assertThat(capturedEndpoint.get(0).encodedPath()).isEqualTo("/2015-03-31/functions/my-function/invocations"); + + // The deprecated URI view carries no query string, so the payload was never encoded. + URI uri = capturedUri.get(0); + assertThat(uri.getQuery()).isNull(); + assertThat(uri.toString()).isEqualTo("http://localhost:8080/2015-03-31/functions/my-function/invocations"); + + // The known consumer pattern: extract the path suffix following "/invocations". + String path = uri.toString(); + int idx = path.indexOf("/invocations"); + assertThat(idx).isGreaterThanOrEqualTo(0); + assertThat(path.substring(idx + "/invocations".length())).isEmpty(); + } + private void expectRetrievalFromMocks() { when(marshaller.marshall(request)).thenReturn(marshalledRequest); when(httpClient.prepareRequest(any())).thenReturn(httpClientCall); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientWireMockTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientWireMockTest.java deleted file mode 100644 index a43e20d74caa..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/AmazonHttpClientWireMockTest.java +++ /dev/null @@ -1,94 +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.http; - -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.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.matching; -import static com.github.tomakehurst.wiremock.client.WireMock.optionsRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; -import static software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils.executionContext; -import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; - -import org.junit.Before; -import org.junit.Test; -import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import utils.HttpTestUtils; -import utils.http.WireMockTestBase; - -public class AmazonHttpClientWireMockTest extends WireMockTestBase { - private static final String OPERATION = "/some-operation"; - private static final String HEADER = "Some-Header"; - private static final String CONFIG_HEADER_VALUE = "client config header value"; - private static final String REQUEST_HEADER_VALUE = "request header value"; - - @Before - public void setUp() { - stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse())); - } - - @Test - public void headersSpecifiedInClientConfigurationArePutOnRequest() { - SdkHttpFullRequest request = newGetRequest(OPERATION).build(); - - AmazonSyncHttpClient sut = createClient(HEADER, CONFIG_HEADER_VALUE); - sendRequest(request, sut); - - verify(getRequestedFor(urlPathEqualTo(OPERATION)).withHeader(HEADER, matching(CONFIG_HEADER_VALUE))); - } - - @Test - public void headersOnRequestsWinOverClientConfigurationHeaders() { - SdkHttpFullRequest request = newGetRequest(OPERATION) - .putHeader(HEADER, REQUEST_HEADER_VALUE) - .build(); - - AmazonSyncHttpClient sut = createClient(HEADER, CONFIG_HEADER_VALUE); - sendRequest(request, sut); - - verify(getRequestedFor(urlPathEqualTo(OPERATION)).withHeader(HEADER, matching(REQUEST_HEADER_VALUE))); - } - - @Test - public void canHandleOptionsRequest() { - SdkHttpFullRequest request = newRequest(OPERATION) - .method(SdkHttpMethod.OPTIONS) - .build(); - - AmazonSyncHttpClient sut = HttpTestUtils.testAmazonHttpClient(); - sendRequest(request, sut); - - verify(optionsRequestedFor(urlPathEqualTo(OPERATION))); - } - - private void sendRequest(SdkHttpFullRequest request, AmazonSyncHttpClient sut) { - sut.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext(request)) - .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); - } - - private AmazonSyncHttpClient createClient(String headerName, String headerValue) { - return HttpTestUtils.testClientBuilder().additionalHeader(headerName, headerValue).build(); - } -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java deleted file mode 100644 index c544254dfb38..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/ContentStreamProviderWireMockTest.java +++ /dev/null @@ -1,129 +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.http; - -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.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils.executionContext; -import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; -import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import org.junit.Test; -import software.amazon.awssdk.core.exception.SdkServiceException; -import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; -import software.amazon.awssdk.core.io.SdkFilterInputStream; -import software.amazon.awssdk.http.ContentStreamProvider; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import utils.HttpTestUtils; -import utils.http.WireMockTestBase; - -/** - * WireMock tests related to {@link ContentStreamProvider} usage. - */ -public class ContentStreamProviderWireMockTest extends WireMockTestBase { - private static final String OPERATION = "/some-operation"; - - @Test - public void closesAllCreatedInputStreamsFromProvider() { - stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse().withStatus(500))); - - TestContentStreamProvider provider = new TestContentStreamProvider(); - SdkHttpFullRequest request = newRequest(OPERATION) - .contentStreamProvider(provider) - .method(SdkHttpMethod.PUT) - .build(); - - AmazonSyncHttpClient testClient = HttpTestUtils.testAmazonHttpClient(); - try { - sendRequest(request, testClient); - fail("Should have thrown SdkServiceException"); - } catch (SdkServiceException ignored) { - } - - // The test client uses the default retry policy so there should be 4 - // total attempts and an equal number created streams - assertThat(provider.getCreatedStreams().size()).isEqualTo(4); - for (CloseTrackingInputStream is : provider.getCreatedStreams()) { - assertThat(is.isClosed()).isTrue(); - } - } - - private void sendRequest(SdkHttpFullRequest request, AmazonSyncHttpClient sut) { - sut.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext(request)) - .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); - } - - private static class TestContentStreamProvider implements ContentStreamProvider { - private static final byte[] CONTENT_BYTES = "Hello".getBytes(StandardCharsets.UTF_8); - private List createdStreams = new ArrayList<>(); - - @Override - public InputStream newStream() { - closeCurrentStream(); - CloseTrackingInputStream s = newContentStream(); - createdStreams.add(s); - return s; - } - - List getCreatedStreams() { - return createdStreams; - } - - private CloseTrackingInputStream newContentStream() { - return new CloseTrackingInputStream(new ByteArrayInputStream(CONTENT_BYTES)); - } - - private void closeCurrentStream() { - if (createdStreams.isEmpty()) { - return; - } - invokeSafely(() -> createdStreams.get(createdStreams.size() - 1).close()); - } - } - - private static class CloseTrackingInputStream extends SdkFilterInputStream { - private boolean isClosed = false; - - CloseTrackingInputStream(InputStream in) { - super(in); - } - - @Override - public void close() throws IOException { - super.close(); - isClosed = true; - } - - boolean isClosed() { - return isClosed; - } - } -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026ResolverTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026ResolverTest.java new file mode 100644 index 000000000000..cc1d2757d754 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/EnableDefaultSocketTimeout2026ResolverTest.java @@ -0,0 +1,121 @@ +/* + * 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.http; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +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 software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +public class EnableDefaultSocketTimeout2026ResolverTest { + private static String enableDefaultSocketTimeout2026Save; + + @BeforeAll + static void setup() { + enableDefaultSocketTimeout2026Save = System.getProperty(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property()); + } + + @AfterAll + static void teardown() { + if (enableDefaultSocketTimeout2026Save != null) { + System.setProperty(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property(), + enableDefaultSocketTimeout2026Save); + } else { + System.clearProperty(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property()); + } + } + + @BeforeEach + void methodSetup() { + System.clearProperty(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property()); + } + + @Test + void systemSetting_usesExpectedEnvironmentVariableAndSystemPropertyNames() { + assertThat(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.environmentVariable()) + .isEqualTo("AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026"); + assertThat(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property()) + .isEqualTo("aws.enableDefaultSocketTimeout2026"); + } + + @ParameterizedTest + @MethodSource("params") + void resolve_behavesCorrectly(TestParams params) { + EnvironmentVariableHelper.run((env) -> { + if (params.systemProperty != null) { + System.setProperty(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.property(), params.systemProperty); + } + + if (params.envVar != null) { + env.set(SdkSystemSetting.AWS_ENABLE_DEFAULT_SOCKET_TIMEOUT_2026.environmentVariable(), params.envVar); + } + + EnableDefaultSocketTimeout2026Resolver resolver = + new EnableDefaultSocketTimeout2026Resolver().defaultEnableSocketTimeout2026(params.defaultEnableSocketTimeout2026); + + assertThat(resolver.resolve()).isEqualTo(params.expected); + }); + } + + private static Stream params() { + return Stream.of( + // default + new TestParams().expected(false), + + // precedence testing + new TestParams().systemProperty("true").defaultEnableSocketTimeout2026(true).expected(true), + new TestParams().systemProperty("false").defaultEnableSocketTimeout2026(true).expected(false), + new TestParams().envVar("true").defaultEnableSocketTimeout2026(true).expected(true), + new TestParams().envVar("false").defaultEnableSocketTimeout2026(true).expected(false), + new TestParams().defaultEnableSocketTimeout2026(true).expected(true), + new TestParams().defaultEnableSocketTimeout2026(false).expected(false) + ); + } + + private static class TestParams { + private String systemProperty; + private String envVar; + private Boolean defaultEnableSocketTimeout2026; + private boolean expected; + + public TestParams systemProperty(String systemProperty) { + this.systemProperty = systemProperty; + return this; + } + + public TestParams envVar(String envVar) { + this.envVar = envVar; + return this; + } + + public TestParams defaultEnableSocketTimeout2026(Boolean defaultEnableSocketTimeout2026) { + this.defaultEnableSocketTimeout2026 = defaultEnableSocketTimeout2026; + return this; + } + + public TestParams expected(boolean expected) { + this.expected = expected; + return this; + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/MockServerTestBase.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/MockServerTestBase.java deleted file mode 100644 index b4b38e646c85..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/MockServerTestBase.java +++ /dev/null @@ -1,41 +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.http; - -import org.junit.After; -import org.junit.Before; -import software.amazon.awssdk.core.http.server.MockServer; - -public abstract class MockServerTestBase { - - protected MockServer server; - - @Before - public void setupBaseFixture() { - server = buildMockServer(); - server.startServer(); - } - - @After - public void tearDownBaseFixture() { - server.stopServer(); - } - - /** - * Implemented by test subclasses to build the correct type of {@link MockServer} - */ - protected abstract MockServer buildMockServer(); -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/SdkTransactionIdInHeaderTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/SdkTransactionIdInHeaderTest.java deleted file mode 100644 index e2977ccea4ba..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/SdkTransactionIdInHeaderTest.java +++ /dev/null @@ -1,79 +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.http; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.findAll; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; - -import com.github.tomakehurst.wiremock.verification.LoggedRequest; -import org.junit.Test; -import software.amazon.awssdk.core.exception.SdkServiceException; -import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage; -import software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import utils.HttpTestUtils; -import utils.http.WireMockTestBase; - -public class SdkTransactionIdInHeaderTest extends WireMockTestBase { - - private static final String RESOURCE_PATH = "/transaction-id/"; - - @Test - public void retriedRequest_HasSameTransactionIdForAllRetries() throws Exception { - stubFor(get(urlEqualTo(RESOURCE_PATH)).willReturn(aResponse().withStatus(500))); - executeRequest(); - assertTransactionIdIsUnchangedAcrossRetries(); - } - - private void assertTransactionIdIsUnchangedAcrossRetries() { - String previousTransactionId = null; - for (LoggedRequest request : findAll(getRequestedFor(urlEqualTo(RESOURCE_PATH)))) { - final String currentTransactionId = request.getHeader(ApplyTransactionIdStage.HEADER_SDK_TRANSACTION_ID); - // Transaction ID should always be set - assertNotNull(currentTransactionId); - // Transaction ID should be the same across retries - if (previousTransactionId != null) { - assertEquals(previousTransactionId, currentTransactionId); - } - previousTransactionId = currentTransactionId; - } - } - - private void executeRequest() throws Exception { - AmazonSyncHttpClient httpClient = HttpTestUtils.testAmazonHttpClient(); - try { - SdkHttpFullRequest request = newGetRequest(RESOURCE_PATH).build(); - httpClient.requestExecutionBuilder() - .request(request) - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(ClientExecutionAndRequestTimerTestUtils.executionContext(request)) - .execute(combinedSyncResponseHandler(null, stubErrorHandler())); - fail("Expected exception"); - } catch (SdkServiceException expected) { - // Ignored or expected. - } - } - -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/UnresponsiveMockServerTestBase.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/UnresponsiveMockServerTestBase.java deleted file mode 100644 index 5f8451bda352..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/UnresponsiveMockServerTestBase.java +++ /dev/null @@ -1,25 +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.http; - -import software.amazon.awssdk.core.http.server.MockServer; - -public abstract class UnresponsiveMockServerTestBase extends MockServerTestBase { - @Override - protected MockServer buildMockServer() { - return MockServer.createMockServer(MockServer.ServerBehavior.UNRESPONSIVE); - } -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/server/MockServer.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/server/MockServer.java deleted file mode 100644 index 6b9dfe538d52..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/http/server/MockServer.java +++ /dev/null @@ -1,271 +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.http.server; - -import java.io.DataOutputStream; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.net.URI; -import org.apache.http.Header; -import org.apache.http.HttpResponse; -import org.apache.http.ProtocolVersion; -import org.apache.http.entity.BasicHttpEntity; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.message.BasicStatusLine; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.utils.IoUtils; -import software.amazon.awssdk.utils.StringInputStream; - -/** - * MockServer implementation with several different configurable behaviors - */ -public class MockServer { - - private final ServerBehaviorStrategy serverBehaviorStrategy; - /** - * The server socket which the test service will listen to. - */ - private ServerSocket serverSocket; - private Thread listenerThread; - - public MockServer(final ServerBehaviorStrategy serverBehaviorStrategy) { - this.serverBehaviorStrategy = serverBehaviorStrategy; - } - - public static MockServer createMockServer(ServerBehavior serverBehavior) { - switch (serverBehavior) { - case UNRESPONSIVE: - return new MockServer(new UnresponsiveServerBehavior()); - case OVERLOADED: - return new MockServer(new OverloadedServerBehavior()); - default: - throw new IllegalArgumentException("Unsupported implementation for server issue: " + serverBehavior); - } - } - - public void startServer() { - try { - serverSocket = new ServerSocket(0); // auto-assign a port at localhost - System.out.println("Listening on port " + serverSocket.getLocalPort()); - } catch (IOException e) { - throw new RuntimeException("Unable to start the server socker.", e); - } - - listenerThread = new MockServerListenerThread(serverSocket, serverBehaviorStrategy); - listenerThread.setDaemon(true); - listenerThread.start(); - } - - public void stopServer() { - listenerThread.interrupt(); - try { - listenerThread.join(10 * 1000); - } catch (InterruptedException e1) { - System.err.println("The listener thread didn't terminate " + "after waiting for 10 seconds."); - } - - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) { - throw new RuntimeException("Unable to stop the server socket.", e); - } - } - } - - public int getPort() { - return serverSocket.getLocalPort(); - } - - public SdkHttpFullRequest.Builder configureHttpsEndpoint(SdkHttpFullRequest.Builder request) { - return request.uri(URI.create("https://localhost")) - .port(getPort()); - } - - public SdkHttpFullRequest.Builder configureHttpEndpoint(SdkHttpFullRequest.Builder request) { - return request.uri(URI.create("http://localhost")) - .port(getPort()); - } - - public enum ServerBehavior { - UNRESPONSIVE, - OVERLOADED, - DUMMY_RESPONSE; - } - - public interface ServerBehaviorStrategy { - void runServer(ServerSocket serverSocket); - } - - private static class MockServerListenerThread extends Thread { - /** The server socket which this thread listens and responds to. */ - private final ServerSocket serverSocket; - private final ServerBehaviorStrategy behaviorStrategy; - - public MockServerListenerThread(ServerSocket serverSocket, ServerBehaviorStrategy behaviorStrategy) { - super(behaviorStrategy.getClass().getName()); - this.serverSocket = serverSocket; - this.behaviorStrategy = behaviorStrategy; - setDaemon(true); - } - - @Override - public void run() { - this.behaviorStrategy.runServer(serverSocket); - } - } - - /** - * A daemon thread which runs a simple server that listens to a specific server socket. Whenever - * a connection is created, the server simply keeps holding the connection open while - * periodically writing data. The test client talking to this server is expected to timeout - * appropriately, instead of hanging and waiting for the response forever. - */ - public static class OverloadedServerBehavior implements ServerBehaviorStrategy { - - @Override - public void runServer(ServerSocket serverSocket) { - try { - while (true) { - Socket socket = null; - try { - socket = serverSocket.accept(); - try (DataOutputStream out = new DataOutputStream(socket.getOutputStream())) { - out.writeBytes("HTTP/1.1 200 OK\r\n"); - out.writeBytes("Content-Type: text/html\r\n"); - out.writeBytes("Content-Length: 500\r\n\r\n"); - out.writeBytes("

    Hello."); - while (true) { - Thread.sleep(1 * 1000); - out.writeBytes("Hi."); - } - } - } catch (SocketException se) { - // Ignored or expected. - } finally { - if (socket != null) { - socket.close(); - } - } - } - } catch (IOException e) { - throw new RuntimeException("Error when waiting for new socket connection.", e); - } catch (InterruptedException e) { - System.err.println("Socket listener thread interrupted. Terminating the thread..."); - return; - } - } - } - - /** - * A daemon thread which runs a simple server that listens to a specific server socket. Whenever - * a connection is created, the server simply keeps holding the connection open and no byte will - * be written to the socket. The test client talking to this server is expected to timeout - * appropriately, instead of hanging and waiting for the response forever. - */ - public static class UnresponsiveServerBehavior implements ServerBehaviorStrategy { - @Override - public void runServer(ServerSocket serverSocket) { - Socket socket = null; - try { - socket = serverSocket.accept(); - System.out.println("Socket created on port " + socket.getLocalPort()); - while (true) { - System.out.println("I don't want to talk."); - Thread.sleep(10 * 1000); - } - } catch (IOException e) { - throw new RuntimeException("Error when waiting for new socket connection.", e); - } catch (InterruptedException e) { - System.err.println("Socket listener thread interrupted. Terminating the thread..."); - return; - } finally { - try { - if (socket != null) { - socket.close(); - } - } catch (IOException e) { - throw new RuntimeException("Fail to close the socket", e); - } - } - } - } - - public static class DummyResponseServerBehavior implements ServerBehaviorStrategy { - - private final HttpResponse response; - private String content; - - public DummyResponseServerBehavior(HttpResponse response) { - this.response = response; - try { - this.content = IoUtils.toUtf8String(response.getEntity().getContent()); - } catch (Exception e) { - // Ignored or expected. - } - } - - public static DummyResponseServerBehavior build(int statusCode, String statusMessage, String content) { - HttpResponse response = new BasicHttpResponse( - new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), statusCode, statusMessage)); - setEntity(response, content); - response.addHeader("Content-Length", String.valueOf(content.getBytes().length)); - response.addHeader("Connection", "close"); - return new DummyResponseServerBehavior(response); - } - - private static void setEntity(HttpResponse response, String content) { - BasicHttpEntity entity = new BasicHttpEntity(); - entity.setContent(new StringInputStream(content)); - response.setEntity(entity); - } - - @Override - public void runServer(ServerSocket serverSocket) { - try { - while (true) { - Socket socket = null; - try { - socket = serverSocket.accept(); - try (DataOutputStream out = new DataOutputStream(socket.getOutputStream())) { - StringBuilder builder = new StringBuilder(); - builder.append(response.getStatusLine().toString() + "\r\n"); - for (Header header : response.getAllHeaders()) { - builder.append(header.getName() + ":" + header.getValue() + "\r\n"); - } - builder.append("\r\n"); - builder.append(content); - System.out.println(builder.toString()); - out.writeBytes(builder.toString()); - } - } catch (SocketException se) { - // Ignored or expected. - } finally { - if (socket != null) { - socket.close(); - } - } - } - } catch (IOException e) { - throw new RuntimeException("Error when waiting for new socket connection.", e); - } - } - - } - -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttributeTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttributeTest.java new file mode 100644 index 000000000000..e28475921630 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttributeTest.java @@ -0,0 +1,126 @@ +/* + * 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.interceptor; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.endpoints.EndpointUrl; + +/** + * Tests for the deprecated {@link SdkInternalExecutionAttribute#HTTP_REQUEST_URI_BEFORE_MODIFY}, which is a derived + * view over {@link SdkInternalExecutionAttribute#HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY}. + */ +class SdkInternalExecutionAttributeTest { + + private static final EndpointUrl ENDPOINT = + EndpointUrl.fromComponents("https", "lambda.us-east-1.amazonaws.com", 443, + "/2015-03-31/functions/my-function/invocations"); + + private ExecutionAttributes attributes; + + @BeforeEach + void setup() { + attributes = new ExecutionAttributes(); + } + + @Test + void httpRequestUriBeforeModify_noSnapshot_isNull() { + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)).isNull(); + } + + @Test + void httpRequestUriBeforeModify_rendersSnapshottedEndpoint() { + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)) + .isEqualTo(URI.create("https://lambda.us-east-1.amazonaws.com:443" + + "/2015-03-31/functions/my-function/invocations")); + } + + @Test + void httpRequestUriBeforeModify_neverCarriesQueryString() { + // The snapshot holds components only, so the query string is always absent. This is what keeps the query and + // ec2 protocols cheap: for those the raw query parameters are the entire request payload at this point. + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + URI uri = attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY); + + assertThat(uri.getQuery()).isNull(); + assertThat(uri.getRawPath()).isEqualTo("/2015-03-31/functions/my-function/invocations"); + } + + @Test + void httpRequestUriBeforeModify_repeatedReadsShareTheSameUri() { + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)) + .isSameAs(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)); + } + + @Test + void httpRequestUriBeforeModify_writeReplacesTheEndpoint() { + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, + URI.create("http://custom.example.com:8443/my-path")); + + EndpointUrl endpoint = + attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY); + assertThat(endpoint.scheme()).isEqualTo("http"); + assertThat(endpoint.host()).isEqualTo("custom.example.com"); + assertThat(endpoint.port()).isEqualTo(8443); + assertThat(endpoint.encodedPath()).isEqualTo("/my-path"); + } + + @Test + void httpRequestUriBeforeModify_writeRoundTripsExactly() { + // A written URI reads back unchanged, query string included, so a caller that sets this attribute sees + // precisely what it set. + URI written = URI.create("https://custom.example.com/my-path?Qualifier=prod"); + + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, written); + + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)) + .isEqualTo(written); + } + + @Test + void httpRequestUriBeforeModify_writeNull_clearsTheEndpoint() { + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, null); + + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY)).isNull(); + assertThat(attributes.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)).isNull(); + } + + @Test + void httpRequestEndpointBeforeModify_survivesCopy() { + attributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, ENDPOINT); + + // Copies duplicate the backing map rather than re-setting each attribute, so the read-only derived view must + // still resolve against the copy. + ExecutionAttributes copy = attributes.copy(); + + assertThat(copy.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY)) + .isSameAs(ENDPOINT); + assertThat(copy.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY)) + .isEqualTo(ENDPOINT.toUri()); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBodySplitTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBodySplitTest.java new file mode 100644 index 000000000000..d4e5717d1839 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ByteBuffersAsyncRequestBodySplitTest.java @@ -0,0 +1,373 @@ +/* + * 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.async; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.nio.ByteBuffer; +import java.nio.ReadOnlyBufferException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncRequestBodySplitConfiguration; +import software.amazon.awssdk.core.async.CloseableAsyncRequestBody; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.exception.NonRetryableException; +import software.amazon.awssdk.core.internal.util.Mimetype; + +/** + * Tests for {@link ByteBuffersAsyncRequestBody#split(AsyncRequestBodySplitConfiguration)} and + * {@link ByteBuffersAsyncRequestBody#splitCloseable(AsyncRequestBodySplitConfiguration)}. + * + *

    Because all of the data is already resident in memory, each split part must be independently replayable so that a + * failed part upload can be retried. + */ +class ByteBuffersAsyncRequestBodySplitTest { + + private static Stream splitTestCases() { + byte[] content = bytesOfLength(100); + return Stream.of( + Arguments.of("chunk size divides content evenly", buffers(content), 10L, 10), + Arguments.of("chunk size does not divide content evenly", buffers(content), 30L, 4), + Arguments.of("chunk size equal to content length", buffers(content), 100L, 1), + Arguments.of("chunk size larger than content length", buffers(content), 1000L, 1), + Arguments.of("chunk size of one byte", buffers(bytesOfLength(5)), 1L, 5), + // Each source buffer holds a distinct range of the content so that data assembled out of order is detected. + Arguments.of("multiple source buffers, chunk spans buffers", + Arrays.asList(ByteBuffer.wrap(Arrays.copyOfRange(content, 0, 10)), + ByteBuffer.wrap(Arrays.copyOfRange(content, 10, 20)), + ByteBuffer.wrap(Arrays.copyOfRange(content, 20, 30))), + 7L, 5), + Arguments.of("multiple source buffers, chunk smaller than each buffer", + Arrays.asList(ByteBuffer.wrap(Arrays.copyOfRange(content, 0, 10)), + ByteBuffer.wrap(Arrays.copyOfRange(content, 10, 20))), + 4L, 5), + Arguments.of("source buffers include an empty buffer", + Arrays.asList(ByteBuffer.wrap(Arrays.copyOfRange(content, 0, 5)), + ByteBuffer.wrap(new byte[0]), + ByteBuffer.wrap(Arrays.copyOfRange(content, 5, 10))), + 5L, 2) + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("splitTestCases") + void splitCloseable_splitsAtChunkBoundariesPreservingContent(String description, + List sourceBuffers, + long chunkSize, + int expectedNumParts) throws Exception { + byte[] expectedContent = concat(sourceBuffers); + ByteBuffersAsyncRequestBody body = ByteBuffersAsyncRequestBody.of(sourceBuffers, expectedContent.length); + + List parts = collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(chunkSize))); + + assertThat(parts).hasSize(expectedNumParts); + for (int i = 0; i < parts.size(); i++) { + long expectedPartLength = i == parts.size() - 1 + ? expectedContent.length - (i * chunkSize) + : chunkSize; + assertThat(parts.get(i).contentLength()).hasValue(expectedPartLength); + } + + assertThat(concatDrained(parts)).isEqualTo(expectedContent); + } + + @ParameterizedTest(name = "chunk size {0}") + @ValueSource(longs = {1L, 7L, 10L, 100L, 1000L}) + void splitCloseable_eachPartIsReplayable(long chunkSize) throws Exception { + byte[] content = bytesOfLength(100); + List parts = + collectParts(AsyncRequestBody.fromBytes(content).splitCloseable(c -> c.chunkSizeInBytes(chunkSize))); + + // Drain every part three times; each pass must reproduce the full content. The second and subsequent passes are + // what a retry of an individual part upload does. + for (int pass = 0; pass < 3; pass++) { + assertThat(concatDrained(parts)).as("pass %d", pass).isEqualTo(content); + } + } + + @Test + void splitCloseable_closingPart_doesNotAffectSiblingsOrSource() throws Exception { + byte[] content = bytesOfLength(30); + ByteBuffersAsyncRequestBody body = ByteBuffersAsyncRequestBody.from(content); + + List parts = collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(10L))); + assertThat(parts).hasSize(3); + + parts.get(1).close(); + + assertThat(drain(parts.get(0))).isEqualTo(Arrays.copyOfRange(content, 0, 10)); + assertThat(drain(parts.get(2))).isEqualTo(Arrays.copyOfRange(content, 20, 30)); + assertThat(drain(body)).isEqualTo(content); + + assertThatThrownBy(() -> drain(parts.get(1))) + .hasCauseInstanceOf(NonRetryableException.class) + .hasMessageContaining("AsyncRequestBody has been closed"); + } + + @Test + void splitCloseable_closingSource_doesNotAffectParts() throws Exception { + byte[] content = bytesOfLength(30); + ByteBuffersAsyncRequestBody body = ByteBuffersAsyncRequestBody.from(content); + + List parts = collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(10L))); + body.close(); + + assertThat(concatDrained(parts)).isEqualTo(content); + } + + @Test + void splitCloseable_whenSourceIsClosed_shouldError() { + ByteBuffersAsyncRequestBody body = ByteBuffersAsyncRequestBody.from(bytesOfLength(30)); + body.close(); + + assertThatThrownBy(() -> collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(10L)))) + .hasCauseInstanceOf(NonRetryableException.class) + .hasMessageContaining("AsyncRequestBody has been closed"); + } + + @Test + void splitCloseable_doesNotMutateSourceBuffers() throws Exception { + ByteBuffer first = ByteBuffer.wrap(bytesOfLength(20)); + ByteBuffer second = ByteBuffer.wrap(bytesOfLength(20)); + second.position(5); + int firstPosition = first.position(); + int secondPosition = second.position(); + + ByteBuffersAsyncRequestBody body = ByteBuffersAsyncRequestBody.of(first, second); + collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(7L))); + + assertThat(first.position()).isEqualTo(firstPosition); + assertThat(second.position()).isEqualTo(secondPosition); + } + + /** + * The parts view the source data rather than copying it, so a part must not be usable to mutate that data. Asserts + * on the slices the parts actually hold: asserting on the buffers delivered to a subscriber would prove nothing, + * since {@code ByteBuffersAsyncRequestBody} makes every published buffer read-only on the way out regardless. + */ + @Test + void splitCloseable_partSlicesAreReadOnly_soPartsCannotMutateSourceData() throws Exception { + // fromBytesUnsafe does not copy, so the parts slice the caller's array directly. + byte[] callerOwnedArray = bytesOfLength(20); + List parts = collectParts( + AsyncRequestBody.fromBytesUnsafe(callerOwnedArray).splitCloseable(c -> c.chunkSizeInBytes(10L))); + + assertThat(parts).hasSize(2); + for (CloseableAsyncRequestBody part : parts) { + List slices = ((ByteBuffersAsyncRequestBody) part).bufferedData(); + assertThat(slices).isNotEmpty().allMatch(ByteBuffer::isReadOnly); + for (ByteBuffer slice : slices) { + assertThatThrownBy(() -> slice.put(0, (byte) 99)).isInstanceOf(ReadOnlyBufferException.class); + } + } + + assertThat(callerOwnedArray).isEqualTo(bytesOfLength(20)); + } + + @Test + void splitCloseable_emptyBody_shouldEmitSingleEmptyPart() throws Exception { + List parts = + collectParts(AsyncRequestBody.empty().splitCloseable(c -> c.chunkSizeInBytes(10L))); + + assertThat(parts).hasSize(1); + assertThat(parts.get(0).contentLength()).hasValue(0L); + assertThat(drain(parts.get(0))).isEmpty(); + } + + @Test + void splitCloseable_propagatesContentType() throws Exception { + AsyncRequestBody body = AsyncRequestBody.fromString("hello world"); + assertThat(body.contentType()).isNotEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); + + List parts = collectParts(body.splitCloseable(c -> c.chunkSizeInBytes(4L))); + + assertThat(parts).isNotEmpty().allSatisfy(p -> assertThat(p.contentType()).isEqualTo(body.contentType())); + } + + @Test + void splitCloseable_propagatesBodyType() throws Exception { + List parts = + collectParts(AsyncRequestBody.fromBytes(bytesOfLength(20)).splitCloseable(c -> c.chunkSizeInBytes(10L))); + + assertThat(parts).allSatisfy(p -> assertThat(p.body()).isEqualTo(AsyncRequestBody.BodyType.BYTES.getName())); + } + + @Test + void splitCloseable_nullConfiguration_shouldThrow() { + AsyncRequestBodySplitConfiguration configuration = null; + assertThatThrownBy(() -> AsyncRequestBody.fromBytes(bytesOfLength(10)).splitCloseable(configuration)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("splitConfiguration"); + } + + @Test + void splitCloseable_noChunkSizeConfigured_shouldUseDefaultChunkSize() throws Exception { + long defaultChunkSize = AsyncRequestBodySplitConfiguration.defaultConfiguration().chunkSizeInBytes(); + byte[] content = bytesOfLength(Math.toIntExact(defaultChunkSize + 1)); + + List parts = collectParts( + AsyncRequestBody.fromBytes(content).splitCloseable(AsyncRequestBodySplitConfiguration.builder().build())); + + assertThat(parts).hasSize(2); + assertThat(parts.get(0).contentLength()).hasValue(defaultChunkSize); + assertThat(parts.get(1).contentLength()).hasValue(1L); + } + + @Test + @SuppressWarnings("deprecation") + void legacySplit_producesReplayableParts() throws Exception { + byte[] content = bytesOfLength(30); + SdkPublisher publisher = + AsyncRequestBody.fromBytes(content).split(c -> c.chunkSizeInBytes(10L)); + + List parts = new ArrayList<>(); + subscribeAndCollect(publisher, parts); + + assertThat(parts).hasSize(3); + assertThat(concatDrained(parts)).isEqualTo(content); + assertThat(concatDrained(parts)).isEqualTo(content); + } + + /** + * Content where each byte encodes its own offset, so that content assembled in the wrong order is detected. + */ + private static byte[] bytesOfLength(int length) { + byte[] bytes = new byte[length]; + for (int i = 0; i < length; i++) { + bytes[i] = (byte) (i % 256); + } + return bytes; + } + + private static List buffers(byte[] content) { + return Arrays.asList(ByteBuffer.wrap(content)); + } + + private static byte[] concat(List buffers) { + return concatBytes(buffers.stream() + .map(b -> { + ByteBuffer duplicate = b.duplicate(); + byte[] bytes = new byte[duplicate.remaining()]; + duplicate.get(bytes); + return bytes; + }) + .collect(Collectors.toList())); + } + + private static byte[] concatBytes(List chunks) { + int total = chunks.stream().mapToInt(c -> c.length).sum(); + byte[] result = new byte[total]; + int offset = 0; + for (byte[] chunk : chunks) { + System.arraycopy(chunk, 0, result, offset, chunk.length); + offset += chunk.length; + } + return result; + } + + private static byte[] concatDrained(List parts) throws Exception { + List drained = new ArrayList<>(); + for (AsyncRequestBody part : parts) { + drained.add(drain(part)); + } + return concatBytes(drained); + } + + private static List collectParts(SdkPublisher publisher) + throws Exception { + List parts = new ArrayList<>(); + subscribeAndCollect(publisher, parts); + return parts; + } + + private static void subscribeAndCollect(SdkPublisher publisher, List collected) throws Exception { + CompletableFuture completed = new CompletableFuture<>(); + publisher.subscribe(new Subscriber() { + @Override + public void onSubscribe(Subscription s) { + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(T part) { + collected.add(part); + } + + @Override + public void onError(Throwable t) { + completed.completeExceptionally(t); + } + + @Override + public void onComplete() { + completed.complete(null); + } + }); + completed.get(5, TimeUnit.SECONDS); + } + + private static byte[] drain(AsyncRequestBody body) throws Exception { + return concatBytes(drainToBuffers(body).stream() + .map(b -> { + byte[] bytes = new byte[b.remaining()]; + b.get(bytes); + return bytes; + }) + .collect(Collectors.toList())); + } + + private static List drainToBuffers(AsyncRequestBody body) throws Exception { + List received = new ArrayList<>(); + CompletableFuture completed = new CompletableFuture<>(); + body.subscribe(new Subscriber() { + @Override + public void onSubscribe(Subscription s) { + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + received.add(byteBuffer); + } + + @Override + public void onError(Throwable t) { + completed.completeExceptionally(t); + } + + @Override + public void onComplete() { + completed.complete(null); + } + }); + completed.get(5, TimeUnit.SECONDS); + return received; + } +} 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 c17d2c3fdaab..9840e4cf1ab7 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 @@ -35,12 +35,14 @@ import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; 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.async.AsyncRequestBody.BodyType; import software.amazon.awssdk.core.internal.util.Mimetype; import software.amazon.awssdk.http.async.SimpleSubscriber; import software.amazon.awssdk.http.auth.spi.signer.PayloadChecksumStore; @@ -165,6 +167,18 @@ public void onComplete() { assertThat(sb).hasToString(tc.expectedBody); } + private static Stream bodyTypeCases() { + return Stream.of( + Arguments.of("file source -> File", AsyncRequestBody.fromFile(path), BodyType.FILE), + Arguments.of("bytes source -> Bytes", AsyncRequestBody.fromString(testString), BodyType.BYTES)); + } + + @ParameterizedTest(name = "{index} {0}") + @MethodSource("bodyTypeCases") + public void body_forwardsWrappedBodyType(String description, AsyncRequestBody wrapped, BodyType expected) { + assertThat(checksumPublisher(wrapped).body()).isEqualTo(expected.getName()); + } + @Test public void constructor_asyncRequestBodyFromString_hasCorrectContentType() { AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBodyTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBodyTest.java index ffb15e282a13..30752ce3c479 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBodyTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/CompressionAsyncRequestBodyTest.java @@ -17,22 +17,32 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; import io.reactivex.Flowable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.ByteBuffer; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Optional; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; import java.util.zip.GZIPInputStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import org.reactivestreams.Subscriber; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncRequestBody.BodyType; import software.amazon.awssdk.core.internal.compression.Compressor; import software.amazon.awssdk.core.internal.compression.GzipCompressor; import software.amazon.awssdk.core.internal.util.Mimetype; @@ -126,6 +136,36 @@ public void onComplete() { assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); } + private static Stream bodyTypeCases() { + return Stream.of( + Arguments.of("file source -> File", AsyncRequestBody.fromFile(fileBody()), BodyType.FILE), + Arguments.of("bytes source -> Bytes", AsyncRequestBody.fromString("Hello world"), BodyType.BYTES)); + } + + @ParameterizedTest(name = "{index} {0}") + @MethodSource("bodyTypeCases") + public void body_forwardsUnderlyingBodyType(String description, AsyncRequestBody wrapped, BodyType expected) { + assertThat(compressionBody(wrapped).body()).isEqualTo(expected.getName()); + } + + private static CompressionAsyncRequestBody compressionBody(AsyncRequestBody wrapped) { + return CompressionAsyncRequestBody.builder() + .compressor(compressor) + .asyncRequestBody(wrapped) + .build(); + } + + private static Path fileBody() { + try { + FileSystem fs = Jimfs.newFileSystem(Configuration.unix()); + Path path = fs.getPath("./test"); + Files.write(path, "Hello world".getBytes()); + return path; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private static String createCompressibleStringOfGivenSize(int size) { ByteBuffer data = ByteBuffer.allocate(size); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/EmittingSubscriptionTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/EmittingSubscriptionTest.java new file mode 100644 index 000000000000..1d040476cf95 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/EmittingSubscriptionTest.java @@ -0,0 +1,148 @@ +/* + * 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.async; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; + +class EmittingSubscriptionTest { + + @Test + void request_withPositiveDemand_emitsOneItemPerRequested() { + RecordingSubscriber subscriber = new RecordingSubscriber(); + EmittingSubscription subscription = subscriptionFor(subscriber); + + subscription.request(3); + + assertThat(subscriber.onNextCount.get()).isEqualTo(3); + assertThat(subscriber.onError.get()).isNull(); + } + + @ParameterizedTest + @ValueSource(longs = {0L, -1L, Long.MIN_VALUE}) + void request_withNonPositiveDemand_signalsIllegalArgumentException(long demand) { + RecordingSubscriber subscriber = new RecordingSubscriber(); + EmittingSubscription subscription = subscriptionFor(subscriber); + + subscription.request(demand); + + assertThat(subscriber.onError.get()).isInstanceOf(IllegalArgumentException.class); + assertThat(subscriber.onNextCount.get()).isZero(); + } + + @Test + void cancel_thenRequest_emitsNothing() { + RecordingSubscriber subscriber = new RecordingSubscriber(); + EmittingSubscription subscription = subscriptionFor(subscriber); + + subscription.cancel(); + subscription.request(5); + + assertThat(subscriber.onNextCount.get()).isZero(); + assertThat(subscriber.onError.get()).isNull(); + } + + /** + * A {@code cancel()} concurrent with an in-flight emit loop must not throw. + */ + @Test + @Timeout(value = 30, unit = TimeUnit.SECONDS) + void cancel_concurrentWithEmit_neverThrowsNullPointerException() throws InterruptedException { + int rounds = 1_000; + // A large demand keeps the emit loop running long enough to overlap the cancel. + long demandPerRound = 10_000; + + for (int round = 0; round < rounds; round++) { + RecordingSubscriber subscriber = new RecordingSubscriber(); + EmittingSubscription subscription = subscriptionFor(subscriber); + + AtomicReference emitFailure = new AtomicReference<>(); + CountDownLatch startSignal = new CountDownLatch(1); + + Thread emitter = new Thread(() -> { + awaitQuietly(startSignal); + try { + subscription.request(demandPerRound); + } catch (Throwable t) { + emitFailure.set(t); + } + }); + Thread canceller = new Thread(() -> { + awaitQuietly(startSignal); + subscription.cancel(); + }); + + emitter.start(); + canceller.start(); + startSignal.countDown(); + emitter.join(); + canceller.join(); + + assertThat(emitFailure.get()) + .withFailMessage("cancel() racing the emit loop threw: %s", emitFailure.get()) + .isNull(); + } + } + + private static EmittingSubscription subscriptionFor(Subscriber subscriber) { + return EmittingSubscription.builder() + .downstreamSubscriber(subscriber) + .onCancel(() -> { }) + .supplier(Object::new) + .build(); + } + + private static void awaitQuietly(CountDownLatch latch) { + try { + latch.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private static final class RecordingSubscriber implements Subscriber { + private final AtomicInteger onNextCount = new AtomicInteger(); + private final AtomicReference onError = new AtomicReference<>(); + + @Override + public void onSubscribe(Subscription s) { + } + + @Override + public void onNext(Object item) { + onNextCount.incrementAndGet(); + } + + @Override + public void onError(Throwable t) { + onError.compareAndSet(null, t); + } + + @Override + public void onComplete() { + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelperTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelperTest.java index 514c549c3594..7244d71cd0a5 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelperTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBodySplitHelperTest.java @@ -19,9 +19,12 @@ import static software.amazon.awssdk.core.internal.async.SplittingPublisherTestUtils.verifyIndividualAsyncRequestBody; import java.io.IOException; +import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; @@ -29,8 +32,12 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.core.async.AsyncRequestBody.BodyType; import software.amazon.awssdk.core.async.AsyncRequestBodySplitConfiguration; import software.amazon.awssdk.testutils.RandomTempFile; @@ -85,6 +92,51 @@ public void split_differentChunkSize_shouldSplitCorrectly(int chunkSize) throws assertThat(maxConcurrency.get()).isLessThanOrEqualTo(expectedMaxConcurrency); } + @Test + public void split_fileRequestBody_partsReportFileBodyType() throws Exception { + FileAsyncRequestBody fileAsyncRequestBody = FileAsyncRequestBody.builder() + .path(testFile) + .chunkSizeInBytes(10) + .build(); + AsyncRequestBodySplitConfiguration config = + AsyncRequestBodySplitConfiguration.builder() + .chunkSizeInBytes((long) CHUNK_SIZE) + .bufferSizeInBytes(55L) + .build(); + FileAsyncRequestBodySplitHelper helper = new FileAsyncRequestBodySplitHelper(fileAsyncRequestBody, config); + + List bodyTypes = new CopyOnWriteArrayList<>(); + helper.split() + .subscribe(requestBody -> { + bodyTypes.add(requestBody.body()); + // Draining each part lets the buffer-limited publisher emit the next one. + requestBody.subscribe(new DrainingSubscriber()); + }) + .get(5, TimeUnit.SECONDS); + + assertThat(bodyTypes).isNotEmpty(); + assertThat(bodyTypes).containsOnly(BodyType.FILE.getName()); + } + + private static final class DrainingSubscriber implements Subscriber { + @Override + public void onSubscribe(Subscription subscription) { + subscription.request(Long.MAX_VALUE); + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + } + + @Override + public void onError(Throwable throwable) { + } + + @Override + public void onComplete() { + } + } + private static Runnable verifyConcurrentRequests(FileAsyncRequestBodySplitHelper helper, AtomicInteger maxConcurrency) { return () -> { int concurrency = helper.numAsyncRequestBodiesInFlight().get(); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerTest.java index 0464489b081f..81a8fa87de9e 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/FileAsyncResponseTransformerTest.java @@ -121,7 +121,8 @@ public void synchronousPublisher_shouldNotHang() throws Exception { @Test void noConfiguration_fileAlreadyExists_shouldThrowException() throws Exception { Path testPath = testFs.getPath("test_file.txt"); - Files.write(testPath, RandomStringUtils.random(1000).getBytes(StandardCharsets.UTF_8)); + String existingContent = RandomStringUtils.randomAlphanumeric(1000); + Files.write(testPath, existingContent.getBytes(StandardCharsets.UTF_8)); assertThat(testPath).exists(); String content = RandomStringUtils.randomAlphanumeric(30000); @@ -131,6 +132,7 @@ void noConfiguration_fileAlreadyExists_shouldThrowException() throws Exception { transformer.onResponse("foobar"); transformer.onStream(testPublisher(content)); assertThatThrownBy(() -> future.join()).hasRootCauseInstanceOf(FileAlreadyExistsException.class); + assertThat(testPath).hasContent(existingContent); } @Test @@ -186,6 +188,73 @@ void createOrAppendExisting_fileExists_shouldAppend() throws Exception { assertThat(testPath).hasContent(existingString + content); } + @ParameterizedTest + @MethodSource("deleteConfigurations") + void exceptionOccurred_beforeFileOpened_shouldPreserveExistingFile(FileTransformerConfiguration configuration) + throws Exception { + Path testPath = testFs.getPath("test_file.txt"); + String existingContent = RandomStringUtils.randomAlphanumeric(1000); + Files.write(testPath, existingContent.getBytes(StandardCharsets.UTF_8)); + + FileAsyncResponseTransformer transformer = new FileAsyncResponseTransformer<>(testPath, configuration); + CompletableFuture future = transformer.prepare(); + RuntimeException exception = new RuntimeException("oops"); + transformer.exceptionOccurred(exception); + + assertThat(future).failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCause(exception); + assertThat(testPath).hasContent(existingContent); + } + + @Test + void exceptionOccurred_beforeFileOpenedOnRetry_shouldPreserveExistingFile() throws Exception { + Path testPath = testFs.getPath("test_file.txt"); + FileAsyncResponseTransformer transformer = new FileAsyncResponseTransformer<>(testPath); + + stubException(transformer); + assertThat(testPath).doesNotExist(); + + String existingContent = RandomStringUtils.randomAlphanumeric(1000); + Files.write(testPath, existingContent.getBytes(StandardCharsets.UTF_8)); + CompletableFuture future = transformer.prepare(); + RuntimeException exception = new RuntimeException("oops"); + transformer.exceptionOccurred(exception); + + assertThat(future).failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCause(exception); + assertThat(testPath).hasContent(existingContent); + } + + @Test + void exceptionOccurred_afterFileOpened_shouldAllowRetry() throws Exception { + Path testPath = testFs.getPath("test_file.txt"); + FileAsyncResponseTransformer transformer = new FileAsyncResponseTransformer<>(testPath); + + stubException(transformer); + assertThat(testPath).doesNotExist(); + + String content = RandomStringUtils.randomAlphanumeric(1000); + stubSuccessfulStreaming(content, transformer); + assertThat(testPath).hasContent(content); + } + + @Test + void exceptionOccurred_calledTwice_shouldNotDeleteReplacement() throws Exception { + Path testPath = testFs.getPath("test_file.txt"); + FileAsyncResponseTransformer transformer = new FileAsyncResponseTransformer<>(testPath); + + stubException(transformer); + assertThat(testPath).doesNotExist(); + + String replacementContent = RandomStringUtils.randomAlphanumeric(1000); + Files.write(testPath, replacementContent.getBytes(StandardCharsets.UTF_8)); + transformer.exceptionOccurred(new RuntimeException("second callback")); + + assertThat(testPath).hasContent(replacementContent); + } + @ParameterizedTest @MethodSource("configurations") void exceptionOccurred_deleteFileBehavior(FileTransformerConfiguration configuration) throws Exception { @@ -203,6 +272,17 @@ void exceptionOccurred_deleteFileBehavior(FileTransformerConfiguration configura } } + private static List deleteConfigurations() { + List conf = new ArrayList<>(); + for (FileWriteOption fileWriteOption : FileWriteOption.values()) { + conf.add(FileTransformerConfiguration.builder() + .fileWriteOption(fileWriteOption) + .failureBehavior(DELETE) + .build()); + } + return conf; + } + private static List configurations() { List conf = new ArrayList<>(); conf.add(FileTransformerConfiguration.defaultCreateNew()); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisherTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisherTest.java new file mode 100644 index 000000000000..1ca4de38845f --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/async/SimpleHttpContentPublisherTest.java @@ -0,0 +1,421 @@ +/* + * 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.async; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.http.ContentStreamProvider; +import software.amazon.awssdk.http.Header; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; + +class SimpleHttpContentPublisherTest { + + private static final byte[] BODY = "The quick brown fox jumps over the lazy dog".getBytes(StandardCharsets.UTF_8); + + @Test + void contentLength_whenNoContentStreamProvider_isZero() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestBuilder().build()); + + assertThat(publisher.contentLength()).hasValue(0L); + } + + @Test + void subscribe_whenNoContentStreamProvider_publishesEmptyBuffer() { + CollectingSubscriber subscriber = drain(new SimpleHttpContentPublisher(requestBuilder().build())); + + assertThat(subscriber.content()).isEmpty(); + assertThat(subscriber.bufferCount()).isEqualTo(1); + } + + @Test + void subscribe_whenContentLengthMatchesBody_publishesFullBody() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + @Test + void subscribe_whenContentLengthHeaderAbsent_publishesFullBody() { + SdkHttpFullRequest request = requestBuilder().contentStreamProvider(() -> new ByteArrayInputStream(BODY)).build(); + + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(request); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * An unusable Content-Length must fall back to reading the stream rather than failing or truncating. + */ + @ParameterizedTest + @ValueSource(strings = {"", " ", "not-a-number", "-1", "12.5", "99999999999999999999999999"}) + void subscribe_whenContentLengthHeaderIsUnusable_publishesFullBody(String contentLength) { + SdkHttpFullRequest request = requestBuilder().contentStreamProvider(() -> new ByteArrayInputStream(BODY)) + .putHeader(Header.CONTENT_LENGTH, contentLength) + .build(); + + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(request); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + @Test + void subscribe_whenContentLengthIsZeroAndBodyEmpty_publishesEmptyBuffer() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(new byte[0], 0)); + + assertThat(publisher.contentLength()).hasValue(0L); + assertThat(drain(publisher).content()).isEmpty(); + } + + /** + * The pre-sized read has to loop, because an {@link InputStream} may return fewer bytes than asked for. + */ + @Test + void subscribe_whenStreamReturnsPartialReads_publishesFullBody() { + SdkHttpFullRequest request = + requestBuilder().contentStreamProvider(() -> new OneByteAtATimeInputStream(BODY)) + .putHeader(Header.CONTENT_LENGTH, Integer.toString(BODY.length)) + .build(); + + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(request); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * Content-Length larger than the stream: publish what is actually there rather than padding with trailing zeros. + */ + @Test + void subscribe_whenContentLengthLongerThanStream_publishesOnlyActualBytes() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length + 100)); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * Content-Length smaller than the stream: read the remainder rather than truncating the body. + */ + @Test + void subscribe_whenContentLengthShorterThanStream_publishesFullBody() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, 5)); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * A body larger than the pre-size ceiling still has to be published in full. + */ + @Test + void subscribe_whenBodyLargerThanPresizeCeiling_publishesFullBody() { + SimpleHttpContentPublisher publisher = + new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length), 8); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * The ceiling exists so that a bogus Content-Length cannot drive a huge allocation. The body still has to be + * published in full, and the reported length has to come from the body rather than the header. + */ + @Test + void subscribe_whenContentLengthFarExceedsPresizeCeiling_publishesFullBody() { + SimpleHttpContentPublisher publisher = + new SimpleHttpContentPublisher(requestWithBody(BODY, Integer.MAX_VALUE), 8); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * Same as above but through the production ceiling, so a {@code Content-Length} of ~2 GiB must not be allocated. + */ + @Test + void subscribe_whenContentLengthIsIntMaxValue_publishesFullBodyWithoutExhaustingMemory() { + SimpleHttpContentPublisher publisher = + new SimpleHttpContentPublisher(requestWithBody(BODY, Integer.MAX_VALUE)); + + assertThat(publisher.contentLength()).hasValue((long) BODY.length); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + @Test + void subscribe_whenSubscribedTwice_eachSubscriberReceivesFullBody() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + + assertThat(drain(publisher).content()).isEqualTo(BODY); + assertThat(drain(publisher).content()).isEqualTo(BODY); + } + + /** + * A retry constructs a new publisher from the same request. Both attempts must see identical bytes. + * + *

    Uses a stream that fails reads after {@code close()} and is exposed through + * {@link ContentStreamProvider#fromInputStream(InputStream)}, which hands back the same stream on every + * call and relies on mark/reset. Closing the stream while buffering would break the second attempt. + */ + @Test + void construct_whenProviderReusesStreamAcrossAttempts_bothAttemptsSeeSameBody() { + CloseAwareInputStream stream = new CloseAwareInputStream(BODY); + SdkHttpFullRequest request = requestBuilder().contentStreamProvider(ContentStreamProvider.fromInputStream(stream)) + .putHeader(Header.CONTENT_LENGTH, Integer.toString(BODY.length)) + .build(); + + byte[] firstAttempt = drain(new SimpleHttpContentPublisher(request)).content(); + byte[] secondAttempt = drain(new SimpleHttpContentPublisher(request)).content(); + + assertThat(firstAttempt).isEqualTo(BODY); + assertThat(secondAttempt).isEqualTo(BODY); + assertThat(stream.closeCount()).isZero(); + } + + @Test + void construct_whenContentLengthHeaderAbsent_doesNotCloseProviderStream() { + CloseAwareInputStream stream = new CloseAwareInputStream(BODY); + SdkHttpFullRequest request = requestBuilder().contentStreamProvider(() -> stream).build(); + + assertThat(drain(new SimpleHttpContentPublisher(request)).content()).isEqualTo(BODY); + assertThat(stream.closeCount()).isZero(); + } + + @Test + void request_whenDemandIsNotPositive_signalsError() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + CollectingSubscriber subscriber = new CollectingSubscriber(0); + publisher.subscribe(subscriber); + + subscriber.subscription().request(0); + + assertThat(subscriber.error()).isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Demand must be positive"); + assertThat(subscriber.bufferCount()).isZero(); + assertThat(subscriber.completed()).isFalse(); + } + + @Test + void request_whenCalledRepeatedly_publishesBodyOnce() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + CollectingSubscriber subscriber = new CollectingSubscriber(0); + publisher.subscribe(subscriber); + + subscriber.subscription().request(1); + subscriber.subscription().request(1); + subscriber.subscription().request(Long.MAX_VALUE); + + assertThat(subscriber.bufferCount()).isEqualTo(1); + assertThat(subscriber.content()).isEqualTo(BODY); + assertThat(subscriber.completeCount()).isEqualTo(1); + } + + @Test + void cancel_whenCancelledBeforeRequest_publishesNothing() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + CollectingSubscriber subscriber = new CollectingSubscriber(0); + publisher.subscribe(subscriber); + + subscriber.subscription().cancel(); + subscriber.subscription().request(Long.MAX_VALUE); + + assertThat(subscriber.bufferCount()).isZero(); + assertThat(subscriber.completed()).isFalse(); + assertThat(subscriber.error()).isNull(); + } + + /** + * The published buffer has to line up with what {@link SimpleHttpContentPublisher#contentLength()} advertises, since + * the HTTP clients use the two together to frame the request. + */ + @Test + void subscribe_whenBodyPublished_bufferRemainingMatchesContentLength() { + SimpleHttpContentPublisher publisher = new SimpleHttpContentPublisher(requestWithBody(BODY, BODY.length)); + + CollectingSubscriber subscriber = drain(publisher); + + assertThat(subscriber.totalRemaining()).isEqualTo(publisher.contentLength().get()); + } + + private static SdkHttpFullRequest.Builder requestBuilder() { + return SdkHttpFullRequest.builder() + .uri(URI.create("https://aws.amazon.com")) + .method(SdkHttpMethod.POST); + } + + private static SdkHttpFullRequest requestWithBody(byte[] body, long advertisedContentLength) { + return requestBuilder().contentStreamProvider(() -> new ByteArrayInputStream(body)) + .putHeader(Header.CONTENT_LENGTH, Long.toString(advertisedContentLength)) + .build(); + } + + private static CollectingSubscriber drain(SimpleHttpContentPublisher publisher) { + CollectingSubscriber subscriber = new CollectingSubscriber(Long.MAX_VALUE); + publisher.subscribe(subscriber); + assertThat(subscriber.error()).isNull(); + assertThat(subscriber.completed()).isTrue(); + return subscriber; + } + + private static final class CollectingSubscriber implements Subscriber { + private final long initialDemand; + private final List buffers = new ArrayList<>(); + private Subscription subscription; + private Throwable error; + private int completeCount; + private long totalRemaining; + + private CollectingSubscriber(long initialDemand) { + this.initialDemand = initialDemand; + } + + @Override + public void onSubscribe(Subscription s) { + this.subscription = s; + if (initialDemand > 0) { + s.request(initialDemand); + } + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + totalRemaining += byteBuffer.remaining(); + byte[] buffer = new byte[byteBuffer.remaining()]; + byteBuffer.get(buffer); + buffers.add(buffer); + } + + @Override + public void onError(Throwable t) { + this.error = t; + } + + @Override + public void onComplete() { + completeCount++; + } + + private Subscription subscription() { + return subscription; + } + + private Throwable error() { + return error; + } + + private boolean completed() { + return completeCount > 0; + } + + private int completeCount() { + return completeCount; + } + + private int bufferCount() { + return buffers.size(); + } + + private long totalRemaining() { + return totalRemaining; + } + + private byte[] content() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + buffers.forEach(b -> out.write(b, 0, b.length)); + return out.toByteArray(); + } + } + + /** + * Returns at most one byte per read, to exercise the pre-sized read loop. + */ + private static final class OneByteAtATimeInputStream extends FilterInputStream { + private OneByteAtATimeInputStream(byte[] content) { + super(new ByteArrayInputStream(content)); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + return super.read(b, off, Math.min(len, 1)); + } + } + + /** + * Models a real stream: reads fail once it has been closed. {@link ByteArrayInputStream} alone cannot catch an + * unwanted {@code close()} because its {@code close()} is a no-op. + */ + private static final class CloseAwareInputStream extends FilterInputStream { + private boolean closed; + private int closeCount; + + private CloseAwareInputStream(byte[] content) { + super(new ByteArrayInputStream(content)); + } + + @Override + public int read() throws IOException { + throwIfClosed(); + return super.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + throwIfClosed(); + return super.read(b, off, len); + } + + @Override + public synchronized void reset() throws IOException { + throwIfClosed(); + super.reset(); + } + + @Override + public void close() throws IOException { + closed = true; + closeCount++; + super.close(); + } + + private int closeCount() { + return closeCount; + } + + private void throwIfClosed() throws IOException { + if (closed) { + throw new IOException("Stream closed"); + } + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmerTest.java new file mode 100644 index 000000000000..484ddd2f1e39 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/AsyncHttpClientWarmerTest.java @@ -0,0 +1,257 @@ +/* + * 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.loader; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.http.async.SdkAsyncHttpService; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Unit tests for {@link AsyncHttpClientWarmer}. Every test drives the real {@link AsyncHttpClientWarmer#warmAll()} with an + * injected list of stub {@link SdkAsyncHttpService}s and a fixed endpoint. Stubbed clients drive the response handler so the + * drain path runs; most settle the execute future immediately, while a couple settle it after a delay or never to cover the + * blocking and timeout paths. + */ +class AsyncHttpClientWarmerTest { + + private static final URI ENDPOINT = URI.create("https://sts.us-east-1.amazonaws.com/"); + + @Test + void warmAll_whenResponseHasBody_drainsAndClosesIt() { + AtomicBoolean drained = new AtomicBoolean(false); + Publisher body = bodyPublisher(drained, ByteBuffer.wrap("denied".getBytes())); + SdkAsyncHttpClient client = stubClient(body); + + warmer(serviceFor(client)).warmAll(); + + assertThat(drained).isTrue(); // subscribed, drained to completion + verify(client).close(); + } + + @Test + void warmAll_whenInvoked_issuesGetToResolvedEndpoint() { + SdkAsyncHttpClient client = stubClient(emptyBody()); + ArgumentCaptor request = ArgumentCaptor.forClass(AsyncExecuteRequest.class); + + warmer(serviceFor(client)).warmAll(); + + verify(client).execute(request.capture()); + assertThat(request.getValue().request().method()).isEqualTo(SdkHttpMethod.GET); + assertThat(request.getValue().request().getUri()).isEqualTo(ENDPOINT); + } + + @Test + void warmAll_whenInvoked_addsWarmUpUserAgentHeader() { + SdkAsyncHttpClient client = stubClient(emptyBody()); + ArgumentCaptor request = ArgumentCaptor.forClass(AsyncExecuteRequest.class); + + warmer(serviceFor(client)).warmAll(); + + verify(client).execute(request.capture()); + assertThat(request.getValue().request().firstMatchingHeader("User-Agent")) + .hasValueSatisfying(userAgent -> assertThat(userAgent).contains("aws-sdk-java/2.").contains("ft/warmup")); + } + + @Test + void warmAll_whenRequestFails_swallowsAndStillClosesClient() { + SdkAsyncHttpClient client = mock(SdkAsyncHttpClient.class); + when(client.execute(any(AsyncExecuteRequest.class))).thenThrow(new RuntimeException("offline")); + + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + + verify(client).close(); + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromWarmer()) + .anyMatch(event -> event.getLevel() == Level.DEBUG + && event.getMessage().getFormattedMessage().contains("warm-up call failed (ignored)")); + } + } + + @Test + void warmAll_whenNoResponseBody_stillClosesClient() { + SdkAsyncHttpClient client = stubClient(emptyBody()); + + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + verify(client).close(); + } + + @Test + void warmAll_whenExecuteTakesLongerThanTimeout_timesOutSwallowsAndClosesClient() { + // execute() returns a future that never completes, so the bounded get() times out. + SdkAsyncHttpClient client = mock(SdkAsyncHttpClient.class); + when(client.execute(any(AsyncExecuteRequest.class))).thenReturn(new CompletableFuture<>()); + + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + + verify(client).close(); + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromWarmer()) + .anyMatch(event -> event.getLevel() == Level.DEBUG + && event.getMessage().getFormattedMessage().contains("warm-up call failed (ignored)")); + } + } + + @Test + void warmAll_whenStreamReadTakesLongerThanTimeout_timesOutSwallowsAndClosesClient() { + // The handler subscribes to a body that never finishes, so the execute future stays pending and get() times out. + SdkAsyncHttpClient client = mock(SdkAsyncHttpClient.class); + when(client.execute(any(AsyncExecuteRequest.class))).thenAnswer(invocation -> { + AsyncExecuteRequest request = invocation.getArgument(0); + request.responseHandler().onStream(neverEndingBody()); + return new CompletableFuture(); + }); + + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + + verify(client).close(); + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromWarmer()) + .anyMatch(event -> event.getLevel() == Level.DEBUG + && event.getMessage().getFormattedMessage().contains("warm-up call failed (ignored)")); + } + } + + @Test + void warmAll_whenMultipleServicesDiscovered_warmsEach() { + SdkAsyncHttpClient first = stubClient(emptyBody()); + SdkAsyncHttpClient second = stubClient(emptyBody()); + + warmer(serviceFor(first), serviceFor(second)).warmAll(); + + verify(first).execute(any(AsyncExecuteRequest.class)); + verify(second).execute(any(AsyncExecuteRequest.class)); + } + + @Test + void warmAll_whenOneServiceFailsToBuild_stillWarmsOthers() { + SdkAsyncHttpService failing = mock(SdkAsyncHttpService.class); + when(failing.createAsyncHttpClientFactory()).thenThrow(new RuntimeException("bad service")); + SdkAsyncHttpClient healthy = stubClient(emptyBody()); + + warmer(failing, serviceFor(healthy)).warmAll(); + + verify(healthy).execute(any(AsyncExecuteRequest.class)); + } + + @Test + void warmAll_whenNoServices_isNoOp() { + assertThatCode(() -> warmer().warmAll()).doesNotThrowAnyException(); + } + + private static AsyncHttpClientWarmer warmer(SdkAsyncHttpService... services) { + return new AsyncHttpClientWarmer(Arrays.asList(services), () -> ENDPOINT); + } + + private static Predicate loggedFromWarmer() { + return event -> AsyncHttpClientWarmer.class.getName().equals(event.getLoggerName()); + } + + /** A service whose builder yields the given client. */ + private static SdkAsyncHttpService serviceFor(SdkAsyncHttpClient client) { + SdkAsyncHttpClient.Builder builder = mock(SdkAsyncHttpClient.Builder.class); + when(builder.buildWithDefaults(any())).thenReturn(client); + + SdkAsyncHttpService service = mock(SdkAsyncHttpService.class); + when(service.createAsyncHttpClientFactory()).thenReturn(builder); + return service; + } + + /** + * A client whose {@code execute} drives the response handler with the given body and completes the returned future, so + * the warmer's drain path runs and its bounded wait settles immediately. + */ + private static SdkAsyncHttpClient stubClient(Publisher body) { + SdkAsyncHttpClient client = mock(SdkAsyncHttpClient.class); + when(client.execute(any(AsyncExecuteRequest.class))).thenAnswer(invocation -> { + AsyncExecuteRequest request = invocation.getArgument(0); + SdkAsyncHttpResponseHandler handler = request.responseHandler(); + handler.onHeaders(SdkHttpResponse.builder().statusCode(403).build()); + handler.onStream(body); + return CompletableFuture.completedFuture(null); + }); + return client; + } + + /** A publisher that delivers the given chunks then completes, flipping {@code drained} once the stream completes. */ + private static Publisher bodyPublisher(AtomicBoolean drained, ByteBuffer... chunks) { + return subscriber -> subscriber.onSubscribe(new Subscription() { + private boolean done; + + @Override + public void request(long n) { + if (done) { + return; + } + done = true; + for (ByteBuffer chunk : chunks) { + subscriber.onNext(chunk); + } + drained.set(true); + subscriber.onComplete(); + } + + @Override + public void cancel() { + done = true; + } + }); + } + + private static Publisher emptyBody() { + return bodyPublisher(new AtomicBoolean(false)); + } + + /** A publisher that subscribes but never signals onNext/onComplete/onError, so the stream read never finishes. */ + private static Publisher neverEndingBody() { + return subscriber -> subscriber.onSubscribe(new Subscription() { + @Override + public void request(long n) { + // No terminal signal: the read never completes. + } + + @Override + public void cancel() { + } + }); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvokerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvokerTest.java new file mode 100644 index 000000000000..7fd1240b8b73 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathHttpWarmupInvokerTest.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.internal.http.loader; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.Test; + +class ClasspathHttpWarmupInvokerTest { + + @Test + void invokeAll_whenMultipleWarmers_invokesEachOnce() { + CountingWarmer first = new CountingWarmer(); + CountingWarmer second = new CountingWarmer(); + + new ClasspathHttpWarmupInvoker(Arrays.asList(first, second)).invokeAll(); + + assertThat(first.invocations()).isEqualTo(1); + assertThat(second.invocations()).isEqualTo(1); + } + + @Test + void invokeAll_whenNoWarmers_isNoOp() { + assertThatCode(() -> new ClasspathHttpWarmupInvoker(Collections.emptyList()).invokeAll()) + .doesNotThrowAnyException(); + } + + private static final class CountingWarmer implements HttpClientWarmer { + private final AtomicInteger invocations = new AtomicInteger(); + + @Override + public void warmAll() { + invocations.incrementAndGet(); + } + + int invocations() { + return invocations.get(); + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathSdkHttpServiceProviderTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathSdkHttpServiceProviderTest.java index 03e25c388625..b39bfbc2b093 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathSdkHttpServiceProviderTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/ClasspathSdkHttpServiceProviderTest.java @@ -19,24 +19,34 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static software.amazon.awssdk.core.internal.http.loader.ClasspathSdkHttpServiceProvider.ASYNC_HTTP_SERVICES_PRIORITY; -import static software.amazon.awssdk.core.internal.http.loader.ClasspathSdkHttpServiceProvider.SYNC_HTTP_SERVICES_PRIORITY; import java.util.Arrays; import java.util.Iterator; +import java.util.Map; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpService; -import software.amazon.awssdk.http.apache.ApacheSdkHttpService; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.async.SdkAsyncHttpService; -import software.amazon.awssdk.http.nio.netty.NettySdkAsyncHttpService; +import software.amazon.awssdk.utils.ImmutableMap; @RunWith(MockitoJUnitRunner.class) public class ClasspathSdkHttpServiceProviderTest { + private static final Map TEST_SYNC_PRIORITY = + ImmutableMap.builder() + .put(HighPrioritySyncHttpService.class.getName(), 1) + .build(); + + private static final Map TEST_ASYNC_PRIORITY = + ImmutableMap.builder() + .put(HighPriorityAsyncHttpService.class.getName(), 1) + .build(); + @Mock private SdkServiceLoader serviceLoader; @@ -48,11 +58,11 @@ public class ClasspathSdkHttpServiceProviderTest { public void setup() { provider = new ClasspathSdkHttpServiceProvider<>(serviceLoader, SdkHttpService.class, - SYNC_HTTP_SERVICES_PRIORITY); + TEST_SYNC_PRIORITY); asyncProvider = new ClasspathSdkHttpServiceProvider<>(serviceLoader, SdkAsyncHttpService.class, - ASYNC_HTTP_SERVICES_PRIORITY); + TEST_ASYNC_PRIORITY); } @Test @@ -71,12 +81,12 @@ public void oneImplementationsFound_ReturnsFulfilledOptional() { @Test public void multipleSyncImplementationsFound_ReturnHighestPriority() { - ApacheSdkHttpService apacheSdkHttpService = new ApacheSdkHttpService(); + HighPrioritySyncHttpService highPrioritySyncHttpService = new HighPrioritySyncHttpService(); SdkHttpService mock = mock(SdkHttpService.class); when(serviceLoader.loadServices(SdkHttpService.class)) - .thenReturn(iteratorOf(mock, apacheSdkHttpService)); - assertThat(provider.loadService()).contains(apacheSdkHttpService); + .thenReturn(iteratorOf(mock, highPrioritySyncHttpService)); + assertThat(provider.loadService()).contains(highPrioritySyncHttpService); SdkHttpService mock1 = mock(SdkHttpService.class); SdkHttpService mock2 = mock(SdkHttpService.class); @@ -87,12 +97,12 @@ public void multipleSyncImplementationsFound_ReturnHighestPriority() { @Test public void multipleAsyncImplementationsFound_ReturnHighestPriority() { - NettySdkAsyncHttpService netty = new NettySdkAsyncHttpService(); + HighPriorityAsyncHttpService highPriorityAsyncHttpService = new HighPriorityAsyncHttpService(); SdkAsyncHttpService mock = mock(SdkAsyncHttpService.class); when(serviceLoader.loadServices(SdkAsyncHttpService.class)) - .thenReturn(iteratorOf(mock, netty)); - assertThat(asyncProvider.loadService()).contains(netty); + .thenReturn(iteratorOf(mock, highPriorityAsyncHttpService)); + assertThat(asyncProvider.loadService()).contains(highPriorityAsyncHttpService); SdkAsyncHttpService mock1 = mock(SdkAsyncHttpService.class); SdkAsyncHttpService mock2 = mock(SdkAsyncHttpService.class); @@ -105,4 +115,26 @@ public void multipleAsyncImplementationsFound_ReturnHighestPriority() { private final Iterator iteratorOf(T... items) { return Arrays.asList(items).iterator(); } + + /** + * Test-local sync HTTP service whose class name is registered in {@link #TEST_SYNC_PRIORITY}. The provider only ever + * inspects the class name, so the factory method is never invoked. + */ + private static final class HighPrioritySyncHttpService implements SdkHttpService { + @Override + public SdkHttpClient.Builder createHttpClientBuilder() { + throw new UnsupportedOperationException(); + } + } + + /** + * Test-local async HTTP service whose class name is registered in {@link #TEST_ASYNC_PRIORITY}. The provider only ever + * inspects the class name, so the factory method is never invoked. + */ + private static final class HighPriorityAsyncHttpService implements SdkAsyncHttpService { + @Override + public SdkAsyncHttpClient.Builder createAsyncHttpClientFactory() { + throw new UnsupportedOperationException(); + } + } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmerTest.java new file mode 100644 index 000000000000..228e98ba42ae --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/loader/SyncHttpClientWarmerTest.java @@ -0,0 +1,171 @@ +/* + * 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.loader; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.Arrays; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import software.amazon.awssdk.http.AbortableInputStream; +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.SdkHttpMethod; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.SdkHttpService; + +/** + * Unit tests for {@link SyncHttpClientWarmer}. Every test drives the real {@link SyncHttpClientWarmer#warmAll()} with an + * injected list of stub {@link SdkHttpService}s and a fixed endpoint. + */ +class SyncHttpClientWarmerTest { + + private static final URI ENDPOINT = URI.create("https://sts.us-east-1.amazonaws.com/"); + + @Test + void warmAll_whenResponseHasBody_drainsAndClosesIt() throws IOException { + InputStream body = spy(new ByteArrayInputStream("denied".getBytes())); + SdkHttpClient client = stubClient(respondingWith(403, body)); + + warmer(serviceFor(client)).warmAll(); + + verify(body, atLeastOnce()).read(); // drained to EOF + verify(body).close(); + verify(client).close(); + } + + @Test + void warmAll_whenInvoked_issuesGetToResolvedEndpoint() { + SdkHttpClient client = stubClient(respondingWith(403, emptyBody())); + ArgumentCaptor request = ArgumentCaptor.forClass(HttpExecuteRequest.class); + + warmer(serviceFor(client)).warmAll(); + + verify(client).prepareRequest(request.capture()); + assertThat(request.getValue().httpRequest().method()).isEqualTo(SdkHttpMethod.GET); + assertThat(request.getValue().httpRequest().getUri()).isEqualTo(ENDPOINT); + } + + @Test + void warmAll_whenInvoked_addsWarmUpUserAgentHeader() { + SdkHttpClient client = stubClient(respondingWith(403, emptyBody())); + ArgumentCaptor request = ArgumentCaptor.forClass(HttpExecuteRequest.class); + + warmer(serviceFor(client)).warmAll(); + + verify(client).prepareRequest(request.capture()); + assertThat(request.getValue().httpRequest().firstMatchingHeader("User-Agent")) + .hasValueSatisfying(userAgent -> assertThat(userAgent).contains("aws-sdk-java/2.").contains("ft/warmup")); + } + + @Test + void warmAll_whenRequestFails_swallowsAndStillClosesClient() throws IOException { + SdkHttpClient client = mock(SdkHttpClient.class); + ExecutableHttpRequest request = mock(ExecutableHttpRequest.class); + when(client.prepareRequest(any(HttpExecuteRequest.class))).thenReturn(request); + when(request.call()).thenThrow(new IOException("offline")); + + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + verify(client).close(); + } + + @Test + void warmAll_whenNoResponseBody_stillClosesClient() { + SdkHttpClient client = stubClient(respondingWith(403, null)); + + assertThatCode(() -> warmer(serviceFor(client)).warmAll()).doesNotThrowAnyException(); + verify(client).close(); + } + + @Test + void warmAll_whenMultipleServicesDiscovered_warmsEach() { + SdkHttpClient first = stubClient(respondingWith(403, emptyBody())); + SdkHttpClient second = stubClient(respondingWith(403, emptyBody())); + + warmer(serviceFor(first), serviceFor(second)).warmAll(); + + verify(first).prepareRequest(any(HttpExecuteRequest.class)); + verify(second).prepareRequest(any(HttpExecuteRequest.class)); + } + + @Test + void warmAll_whenOneServiceFailsToBuild_stillWarmsOthers() { + SdkHttpService failing = mock(SdkHttpService.class); + when(failing.createHttpClientBuilder()).thenThrow(new RuntimeException("bad service")); + SdkHttpClient healthy = stubClient(respondingWith(403, emptyBody())); + + warmer(failing, serviceFor(healthy)).warmAll(); + + verify(healthy).prepareRequest(any(HttpExecuteRequest.class)); + } + + @Test + void warmAll_whenNoServices_isNoOp() { + assertThatCode(() -> warmer().warmAll()).doesNotThrowAnyException(); + } + + private static SyncHttpClientWarmer warmer(SdkHttpService... services) { + return new SyncHttpClientWarmer(Arrays.asList(services), () -> ENDPOINT); + } + + /** A service whose builder yields the given client. */ + private static SdkHttpService serviceFor(SdkHttpClient client) { + SdkHttpClient.Builder builder = mock(SdkHttpClient.Builder.class); + when(builder.buildWithDefaults(any())).thenReturn(client); + + SdkHttpService service = mock(SdkHttpService.class); + when(service.createHttpClientBuilder()).thenReturn(builder); + return service; + } + + /** A client whose single request returns the given response. */ + private static SdkHttpClient stubClient(HttpExecuteResponse response) { + try { + ExecutableHttpRequest request = mock(ExecutableHttpRequest.class); + when(request.call()).thenReturn(response); + + SdkHttpClient client = mock(SdkHttpClient.class); + when(client.prepareRequest(any(HttpExecuteRequest.class))).thenReturn(request); + return client; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static HttpExecuteResponse respondingWith(int statusCode, InputStream body) { + return HttpExecuteResponse.builder() + .response(SdkHttpResponse.builder().statusCode(statusCode).build()) + .responseBody(body == null ? null : AbortableInputStream.create(body)) + .build(); + } + + private static InputStream emptyBody() { + return new ByteArrayInputStream(new byte[0]); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageTest.java index 827e1a7d1cef..659623108d13 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageTest.java @@ -18,8 +18,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import java.io.IOException; @@ -27,12 +30,16 @@ import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; +import java.util.concurrent.Phaser; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Assume; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; @@ -54,12 +61,14 @@ import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.retries.api.AcquireInitialTokenRequest; import software.amazon.awssdk.retries.api.AcquireInitialTokenResponse; 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; +import software.amazon.awssdk.utils.CompletableFutureUtils; public class AsyncRetryableStageTest extends BaseRetryableStageTest { private RetryStrategy mockRetryStrategy; @@ -89,7 +98,8 @@ void methodSetup() { when(mockAcquireInitialTokenResponse.token()).thenReturn(mockRetryToken); when(mockAcquireInitialTokenResponse.delay()).thenReturn(Duration.ZERO); - when(mockRetryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireInitialTokenResponse); + when(mockRetryStrategy.acquireInitialTokenAsync(any())) + .thenReturn(CompletableFuture.completedFuture(mockAcquireInitialTokenResponse)); mockDelegatePipeline = mock(RequestPipeline.class); } @@ -97,37 +107,9 @@ void methodSetup() { @ParameterizedTest @MethodSource("acquireDelayTestCases") void execute_acquireDelay_behavesCorrectly(AcquireDelayTestCase testCase) throws Exception { - SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_STRATEGY, mockRetryStrategy) - .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, - executorService) - .build(); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, executorService); - HttpClientDependencies deps = HttpClientDependencies.builder() - .clientConfiguration(clientConfig) - .build(); - - AsyncRetryableStage retryableStage = new AsyncRetryableStage<>(mock(TransformingAsyncResponseHandler.class), - deps, mockDelegatePipeline); - - SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .uri(URI.create("https://my-service.amazonaws.com")) - .build(); - - ExecutionAttributes execAttrs = ExecutionAttributes.builder() - .put(SdkInternalExecutionAttribute.NEW_RETRIES_2026_ENABLED, true) - .build(); - - ExecutionContext execCtx = ExecutionContext.builder() - .metricCollector(NoOpMetricCollector.create()) - .executionAttributes(execAttrs) - .build(); - - RequestExecutionContext ctx = RequestExecutionContext.builder() - .originalRequest(mock(SdkRequest.class)) - .executionContext(execCtx) - .build(); + RequestExecutionContext ctx = createRequestExecutionContext(true); SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder() .statusCode(502); @@ -141,21 +123,30 @@ void execute_acquireDelay_behavesCorrectly(AcquireDelayTestCase testCase) throws when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); if (testCase.isFailure()) { - when(mockRetryStrategy.refreshRetryToken(any())).thenThrow( - new TokenAcquisitionFailedException("Acquire failed", mockRetryToken, null, testCase.failureDelay()) + when(mockRetryStrategy.refreshRetryTokenAsync(any())).thenReturn( + CompletableFutureUtils.failedFuture(new TokenAcquisitionFailedException("Acquire failed", mockRetryToken, null, + testCase.failureDelay())) ); } else { // only retry once, otherwise we'll get into an infinite loop AtomicBoolean first = new AtomicBoolean(); - when(mockRetryStrategy.refreshRetryToken(any())).thenAnswer(i -> { + when(mockRetryStrategy.refreshRetryTokenAsync(any())).thenAnswer(i -> { if (first.compareAndSet(false, true)) { - return RefreshRetryTokenResponse.create(mockRetryToken, testCase.successDelay()); + return CompletableFuture.completedFuture(RefreshRetryTokenResponse.create(mockRetryToken, + testCase.successDelay())); } - throw new TokenAcquisitionFailedException("Acquire failed", mockRetryToken, null, Duration.ZERO); + return CompletableFutureUtils.failedFuture(new TokenAcquisitionFailedException("Acquire failed", + mockRetryToken, + null, + Duration.ZERO)); }); } long start = System.nanoTime(); + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); CompletableFuture> execute = retryableStage.execute(httpRequest, ctx); // exception thrown doesn't matter, just results in exception because we mock just enough... assertThatThrownBy(execute::join); @@ -171,38 +162,9 @@ void execute_acquireDelay_behavesCorrectly(AcquireDelayTestCase testCase) throws void execute_retryableException_treatsRetryAfterCorrectly(RetryAfterTestCase testCase) throws Exception { Assume.assumeTrue("Async v2.0 behavior doesn't look at Retry-After", testCase.isNewRetries2026Enabled()); - SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_STRATEGY, mockRetryStrategy) - .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, - executorService) - .build(); - - HttpClientDependencies deps = HttpClientDependencies.builder() - .clientConfiguration(clientConfig) - .build(); - - AsyncRetryableStage retryableStage = new AsyncRetryableStage<>(mock(TransformingAsyncResponseHandler.class), - deps, mockDelegatePipeline); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, executorService); - SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .uri(URI.create("https://my-service.amazonaws.com")) - .build(); - - ExecutionAttributes execAttrs = ExecutionAttributes.builder() - .put(SdkInternalExecutionAttribute.NEW_RETRIES_2026_ENABLED, - testCase.isNewRetries2026Enabled()) - .build(); - - ExecutionContext execCtx = ExecutionContext.builder() - .metricCollector(NoOpMetricCollector.create()) - .executionAttributes(execAttrs) - .build(); - - RequestExecutionContext ctx = RequestExecutionContext.builder() - .originalRequest(mock(SdkRequest.class)) - .executionContext(execCtx) - .build(); + RequestExecutionContext ctx = createRequestExecutionContext(testCase.isNewRetries2026Enabled()); SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder() .statusCode(502); @@ -223,13 +185,18 @@ void execute_retryableException_treatsRetryAfterCorrectly(RetryAfterTestCase tes when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + CompletableFuture> execute = retryableStage.execute(httpRequest, ctx); // exception thrown doesn't matter, just results in exception because we mock just enough... assertThatThrownBy(execute::join); ArgumentCaptor refreshRequestCaptor = ArgumentCaptor.forClass(RefreshRetryTokenRequest.class); - verify(mockRetryStrategy).refreshRetryToken(refreshRequestCaptor.capture()); + verify(mockRetryStrategy).refreshRetryTokenAsync(refreshRequestCaptor.capture()); RefreshRetryTokenRequest refreshRequest = refreshRequestCaptor.getValue(); @@ -239,38 +206,197 @@ void execute_retryableException_treatsRetryAfterCorrectly(RetryAfterTestCase tes @ParameterizedTest(name = "New Retries = {0}") @CsvSource({"true", "false"}) void execute_delegateThrows_noHttpResponse_uses0SuggestedDelay(boolean newRetries2026) throws Exception { - SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_STRATEGY, mockRetryStrategy) - .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, - executorService) - .build(); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, executorService); - HttpClientDependencies deps = HttpClientDependencies.builder() - .clientConfiguration(clientConfig) - .build(); + RequestExecutionContext ctx = createRequestExecutionContext(newRetries2026); + + CompletableFuture> future = new CompletableFuture<>(); + future.completeExceptionally(new IOException("connection")); + when(mockDelegatePipeline.execute(any(), any())).thenReturn(future); - AsyncRetryableStage retryableStage = new AsyncRetryableStage<>(mock(TransformingAsyncResponseHandler.class), - deps, mockDelegatePipeline); + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + + CompletableFuture> execute = retryableStage.execute(httpRequest, ctx); + // exception thrown doesn't matter, just results in exception because we mock just enough... + assertThatThrownBy(execute::join); + + ArgumentCaptor refreshRequestCaptor = ArgumentCaptor.forClass(RefreshRetryTokenRequest.class); + + verify(mockRetryStrategy).refreshRetryTokenAsync(refreshRequestCaptor.capture()); + + RefreshRetryTokenRequest refreshRequest = refreshRequestCaptor.getValue(); + + assertThat(refreshRequest.suggestedDelay().get()).isEqualTo(Duration.ZERO); + } + + @Test + void execute_isFirstAttempt_acquireInitialTokenCompleteSameThread_doesNotSchedule() throws Exception { + RequestExecutionContext ctx = createRequestExecutionContext(true); + + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder().statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + ScheduledExecutorService exec = mock(ScheduledExecutorService.class); + + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, exec); SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() .method(SdkHttpMethod.GET) .uri(URI.create("https://my-service.amazonaws.com")) .build(); - ExecutionAttributes execAttrs = ExecutionAttributes.builder() - .put(SdkInternalExecutionAttribute.NEW_RETRIES_2026_ENABLED, - newRetries2026) + CompletableFuture> executeFuture = retryableStage.execute(httpRequest, ctx); + + assertThatThrownBy(executeFuture::join); + + verifyNoInteractions(exec); + } + + @Test + void execute_isFirstAttempt_acquireInitialTokenCompleteSameDurationNonZero_schedules() throws Exception { + RequestExecutionContext ctx = createRequestExecutionContext(true); + + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder().statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + + Duration delay = Duration.ofMillis(1); + + AcquireInitialTokenResponse acquireTokenResponse = AcquireInitialTokenResponse.create(mock(RetryToken.class), delay); + when(mockRetryStrategy.acquireInitialTokenAsync(any(AcquireInitialTokenRequest.class))).thenReturn( + CompletableFuture.completedFuture(acquireTokenResponse)); + + ScheduledExecutorService mockExec = mock(ScheduledExecutorService.class); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExec); + + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) .build(); + Phaser phaser = new Phaser(2); - ExecutionContext execCtx = ExecutionContext.builder() - .metricCollector(NoOpMetricCollector.create()) - .executionAttributes(execAttrs) - .build(); + when(mockExec.schedule(any(Runnable.class), eq(1L), eq(TimeUnit.MILLISECONDS))).thenAnswer(i -> { + Runnable r = i.getArgument(0); + r.run(); + phaser.arrive(); + return null; + }); - RequestExecutionContext ctx = RequestExecutionContext.builder() - .originalRequest(mock(SdkRequest.class)) - .executionContext(execCtx) - .build(); + retryableStage.execute(httpRequest, ctx); + + phaser.arriveAndAwaitAdvance(); + + verify(mockExec).schedule(any(Runnable.class), eq(1L), eq(TimeUnit.MILLISECONDS)); + } + + @Test + void execute_isFirstAttempt_acquireInitialTokenCompleteSameThreadDurationNonZero_schedules() throws Exception { + RequestExecutionContext ctx = createRequestExecutionContext(true); + + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder().statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + + Duration delay = Duration.ofMillis(1); + + AcquireInitialTokenResponse acquireTokenResponse = AcquireInitialTokenResponse.create(mock(RetryToken.class), delay); + when(mockRetryStrategy.acquireInitialTokenAsync(any(AcquireInitialTokenRequest.class))).thenReturn( + CompletableFuture.completedFuture(acquireTokenResponse)); + + ScheduledExecutorService mockExec = mock(ScheduledExecutorService.class); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExec); + + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + Phaser phaser = new Phaser(2); + + when(mockExec.schedule(any(Runnable.class), eq(1L), eq(TimeUnit.MILLISECONDS))).thenAnswer(i -> { + Runnable r = i.getArgument(0); + r.run(); + phaser.arrive(); + return null; + }); + + retryableStage.execute(httpRequest, ctx); + + phaser.arriveAndAwaitAdvance(); + + verify(mockExec).schedule(any(Runnable.class), eq(1L), eq(TimeUnit.MILLISECONDS)); + } + + + @Test + void execute_isFirstAttempt_scheduleFails_completesExceptionally() throws Exception { + RequestExecutionContext ctx = createRequestExecutionContext(true); + + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder().statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + + Duration delay = Duration.ofMillis(1); + + AcquireInitialTokenResponse acquireTokenResponse = AcquireInitialTokenResponse.create(mock(RetryToken.class), delay); + when(mockRetryStrategy.acquireInitialTokenAsync(any(AcquireInitialTokenRequest.class))).thenReturn( + CompletableFuture.completedFuture(acquireTokenResponse)); + + ScheduledExecutorService mockExec = mock(ScheduledExecutorService.class); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExec); + + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + + when(mockExec.schedule(any(Runnable.class), eq(1L), eq(TimeUnit.MILLISECONDS))) + .thenThrow(new RejectedExecutionException("closed")); + + CompletableFuture> future = retryableStage.execute(httpRequest, ctx); + + assertThatThrownBy(future::join).hasRootCauseInstanceOf(RejectedExecutionException.class) + .hasRootCauseMessage("closed"); + } + + @Test + void execute_isRetryAttempt_scheduleFails_completesExceptionally() throws Exception { + ScheduledExecutorService mockExecutor = mock(ScheduledExecutorService.class); + + when(mockExecutor.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class))).thenThrow(new RejectedExecutionException("closed")); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExecutor); + + RequestExecutionContext ctx = createRequestExecutionContext(true); SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder() .statusCode(502); @@ -281,21 +407,147 @@ void execute_delegateThrows_noHttpResponse_uses0SuggestedDelay(boolean newRetrie .exception(SdkException.builder().build()) .build(); + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); - CompletableFuture> future = new CompletableFuture<>(); - future.completeExceptionally(new IOException("connection")); - when(mockDelegatePipeline.execute(any(), any())).thenReturn(future); + // only retry once, otherwise we'll get into an infinite loop + AtomicBoolean first = new AtomicBoolean(); + when(mockRetryStrategy.refreshRetryTokenAsync(any())).thenAnswer(i -> { + if (first.compareAndSet(false, true)) { + return CompletableFuture.completedFuture(RefreshRetryTokenResponse.create(mockRetryToken, Duration.ZERO)); + } + return CompletableFutureUtils.failedFuture(new TokenAcquisitionFailedException("Acquire failed", + mockRetryToken, + null, + Duration.ZERO)); + }); + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); CompletableFuture> execute = retryableStage.execute(httpRequest, ctx); - // exception thrown doesn't matter, just results in exception because we mock just enough... - assertThatThrownBy(execute::join); + assertThatThrownBy(execute::join).hasRootCauseInstanceOf(RejectedExecutionException.class).hasRootCauseMessage("closed"); + } - ArgumentCaptor refreshRequestCaptor = ArgumentCaptor.forClass(RefreshRetryTokenRequest.class); + @Test + void execute_retryDisallowed_delayNonZero_scheduleFails_completesExceptionally() throws Exception { + ScheduledExecutorService mockExecutor = mock(ScheduledExecutorService.class); - verify(mockRetryStrategy).refreshRetryToken(refreshRequestCaptor.capture()); + when(mockExecutor.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class))).thenThrow(new RejectedExecutionException("closed")); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExecutor); - RefreshRetryTokenRequest refreshRequest = refreshRequestCaptor.getValue(); + RequestExecutionContext ctx = createRequestExecutionContext(true); - assertThat(refreshRequest.suggestedDelay().get()).isEqualTo(Duration.ZERO); + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder() + .statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + // only retry once, otherwise we'll get into an infinite loop + AtomicBoolean first = new AtomicBoolean(); + when(mockRetryStrategy.refreshRetryTokenAsync(any())) + .thenAnswer(i -> + CompletableFutureUtils.failedFuture(new TokenAcquisitionFailedException("Acquire failed", + mockRetryToken, + null, + Duration.ofSeconds(1)))); + + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + CompletableFuture> execute = retryableStage.execute(httpRequest, ctx); + assertThatThrownBy(execute::join).hasRootCauseInstanceOf(RejectedExecutionException.class).hasRootCauseMessage("closed"); + } + + @Test + void execute_isFirstAttempt_acquireInitialTokenCompleteDifferentThread_schedules() throws Exception { + RequestExecutionContext ctx = createRequestExecutionContext(true); + + SdkHttpFullResponse.Builder httpResponse = SdkHttpFullResponse.builder().statusCode(502); + + Response response = Response.builder() + .httpResponse(httpResponse.build()) + .isSuccess(false) + .exception(SdkException.builder().build()) + .build(); + + when(mockDelegatePipeline.execute(any(), any())).thenReturn(CompletableFuture.completedFuture(response)); + + AcquireInitialTokenResponse acquireTokenResponse = AcquireInitialTokenResponse.create(mock(RetryToken.class), + Duration.ZERO); + + ScheduledExecutorService mockExec = mock(ScheduledExecutorService.class); + AsyncRetryableStage retryableStage = createRetryableStage(mockRetryStrategy, mockExec); + + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + + // wait for execution to "start" before completing the future + Phaser phaser = new Phaser(2); + + when(mockRetryStrategy.acquireInitialTokenAsync(any(AcquireInitialTokenRequest.class))) + .thenAnswer(i -> { + CompletableFuture future = new CompletableFuture<>(); + executorService.submit(() -> { + phaser.arriveAndAwaitAdvance(); + future.complete(acquireTokenResponse); + }); + return future; + }); + + when(mockExec.schedule(any(Runnable.class), eq(0L), eq(TimeUnit.MILLISECONDS))).thenAnswer(i -> { + Runnable r = i.getArgument(0); + r.run(); + return null; + }); + + CompletableFuture> executeFuture = retryableStage.execute(httpRequest, ctx); + + phaser.arrive(); + assertThatThrownBy(executeFuture::join); + + verify(mockExec).schedule(any(Runnable.class), eq(0L), eq(TimeUnit.MILLISECONDS)); + } + + private AsyncRetryableStage createRetryableStage(RetryStrategy retryStrategy, + ScheduledExecutorService scheduler) { + SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() + .option(SdkClientOption.RETRY_STRATEGY, retryStrategy) + .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, + scheduler) + .build(); + + HttpClientDependencies deps = HttpClientDependencies.builder() + .clientConfiguration(clientConfig) + .build(); + + return new AsyncRetryableStage<>(mock(TransformingAsyncResponseHandler.class), + deps, mockDelegatePipeline); + } + + private RequestExecutionContext createRequestExecutionContext(Boolean newRetries2026Enabled) { + ExecutionAttributes execAttrs = ExecutionAttributes.builder() + .put(SdkInternalExecutionAttribute.NEW_RETRIES_2026_ENABLED, + newRetries2026Enabled) + .build(); + + ExecutionContext execCtx = ExecutionContext.builder() + .metricCollector(NoOpMetricCollector.create()) + .executionAttributes(execAttrs) + .build(); + + return RequestExecutionContext.builder() + .originalRequest(mock(SdkRequest.class)) + .executionContext(execCtx) + .build(); } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStageTest.java index 02a74672db4b..649697b837c5 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncSigningStageTest.java @@ -33,6 +33,7 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.HashMap; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.junit.Before; import org.junit.Test; @@ -43,6 +44,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.async.AsyncRequestBody; @@ -58,6 +61,7 @@ import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; @@ -596,6 +600,50 @@ private RequestExecutionContext createContext(SelectedAuthScheme selec return context; } + @Test + public void execute_signerReturnsSdkHttpContentPublisher_preservesContentLength() throws Exception { + AsyncRequestBody asyncPayload = AsyncRequestBody.fromString("async request body"); + + SelectedAuthScheme selectedAuthScheme = new SelectedAuthScheme<>( + CompletableFuture.completedFuture(identity), + httpSigner, + AuthSchemeOption.builder() + .schemeId("my.auth#myAuth") + .build()); + RequestExecutionContext context = createContext(selectedAuthScheme, asyncPayload, null); + + SdkHttpRequest signedRequest = ValidSdkObjects.sdkHttpFullRequest().build(); + + SdkHttpContentPublisher contentPublisher = + new SdkHttpContentPublisher() { + @Override + public Optional contentLength() { + return Optional.of(42L); + } + + @Override + public void subscribe(Subscriber s) { + s.onSubscribe(new Subscription() { + @Override public void request(long n) { s.onComplete(); } + @Override public void cancel() { } + }); + } + }; + + when(httpSigner.signAsync(ArgumentMatchers.>any())) + .thenReturn( + CompletableFuture.completedFuture(AsyncSignedRequest.builder() + .request(signedRequest) + .payload(contentPublisher) + .build())); + + SdkHttpFullRequest request = ValidSdkObjects.sdkHttpFullRequest().build(); + stage.execute(request, context).join(); + + assertThat(context.requestProvider()).isNotNull(); + assertThat(context.requestProvider().contentLength()).hasValue(42L); + } + private interface TestAsyncRequestBodySigner extends Signer, AsyncRequestBodySigner { } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStageTest.java index 6ab7325a3093..6873b84d9020 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AuthSchemeResolutionStageTest.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -100,7 +101,7 @@ void execute_noResolver_returnsRequestUnchanged() throws Exception { void execute_resolverReturnsEmpty_returnsRequestUnchanged() throws Exception { executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> Collections.emptyList()); + (req, attrs) -> Collections.emptyList()); SdkHttpFullRequest.Builder result = stage.execute(httpRequestBuilder, context); @@ -126,7 +127,7 @@ void execute_resolverReceivesRequestFromInterceptorContext() throws Exception { .build(); AuthSchemeOptionsResolver resolver = mock(AuthSchemeOptionsResolver.class); - doReturn(createAuthOptions()).when(resolver).resolve(modifiedRequest); + doReturn(createAuthOptions()).when(resolver).resolve(eq(modifiedRequest), any(ExecutionAttributes.class)); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, resolver); @@ -135,7 +136,7 @@ void execute_resolverReceivesRequestFromInterceptorContext() throws Exception { stage.execute(httpRequestBuilder, context); // Verify resolver was called with the MODIFIED request, not originalRequest - verify(resolver).resolve(modifiedRequest); + verify(resolver).resolve(eq(modifiedRequest), any(ExecutionAttributes.class)); } @Test @@ -156,7 +157,7 @@ void execute_withRequestIdentityProviderResolver_callsUpdaterWithRequest() throw executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, authSchemes); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> createAuthOptions()); + (req, attrs) -> createAuthOptions()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, baseProviders); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDER_RESOLVER, resolver); @@ -169,7 +170,7 @@ void execute_withRequestIdentityProviderResolver_callsUpdaterWithRequest() throw void execute_withoutRequestIdentityProviderResolver_doesNotFail() throws Exception { executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> createAuthOptions()); + (req, attrs) -> createAuthOptions()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, createIdentityProviders()); // No IDENTITY_PROVIDER_RESOLVER set @@ -183,7 +184,7 @@ void execute_withoutRequestIdentityProviderResolver_doesNotFail() throws Excepti void execute_happyPath_setsSelectedAuthScheme() throws Exception { executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> createAuthOptions()); + (req, attrs) -> createAuthOptions()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, createIdentityProviders()); SdkHttpFullRequest.Builder result = stage.execute(httpRequestBuilder, context); @@ -240,7 +241,7 @@ void execute_authSchemeAlreadyResolved_skipsResolution() throws Exception { executionAttributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, alreadyResolved); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> createAuthOptions()); + (req, attrs) -> createAuthOptions()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, createIdentityProviders()); SdkHttpFullRequest.Builder result = stage.execute(httpRequestBuilder, context); @@ -262,7 +263,7 @@ void execute_authSchemeUnset_proceedsWithResolution() throws Exception { executionAttributes.putAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME, unsetPlaceholder); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, createAuthSchemes()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - (AuthSchemeOptionsResolver) req -> createAuthOptions()); + (req, attrs) -> createAuthOptions()); executionAttributes.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, createIdentityProviders()); stage.execute(httpRequestBuilder, context); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStageTest.java index d13717389c5f..34b591a937a1 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/EndpointResolutionStageTest.java @@ -34,6 +34,7 @@ import software.amazon.awssdk.core.internal.http.RequestExecutionContext; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.metrics.MetricCollector; @@ -196,8 +197,8 @@ void execute_interceptorModifiedHost_preservesCustomHostAndScheme() throws Excep .host("custom.example.com") .port(8080) .encodedPath("/my-operation"); - executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, - URI.create("https://myservice.amazonaws.com/my-operation")); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, + preModifyEndpoint("https", "myservice.amazonaws.com", "/my-operation")); executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, ClientEndpointProvider.forEndpointOverride(CLIENT_ENDPOINT)); @@ -222,8 +223,8 @@ void execute_interceptorModifiedHost_stillAppliesResolvedPath() throws Exception .host("example.com") .encodedPath("/my-key"); - executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_URI_BEFORE_MODIFY, - URI.create("https://s3.us-west-2.amazonaws.com/my-key")); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, + preModifyEndpoint("https", "s3.us-west-2.amazonaws.com", "/my-key")); executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, ClientEndpointProvider.forEndpointOverride(clientEndpoint)); @@ -235,6 +236,59 @@ void execute_interceptorModifiedHost_stillAppliesResolvedPath() throws Exception assertThat(result.encodedPath()).isEqualTo("/my-bucket/my-key"); } + @Test + void execute_explicitStandardPortUnmodified_appliesResolvedUrl() throws Exception { + // The snapshot always carries a resolved port, so an endpoint that explicitly specifies the protocol's + // standard port must not be mistaken for one an interceptor modified. + SdkHttpFullRequest.Builder request = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host(CLIENT_ENDPOINT.getHost()) + .port(443) + .encodedPath("/"); + Endpoint endpoint = Endpoint.builder().url(RESOLVED_ENDPOINT).build(); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, + preModifyEndpoint("https", CLIENT_ENDPOINT.getHost(), "/")); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(CLIENT_ENDPOINT)); + RequestExecutionContext context = createContext(); + + SdkHttpFullRequest.Builder result = stage.execute(request, context); + + assertThat(result.host()).isEqualTo("resolved.us-west-2.amazonaws.com"); + } + + @Test + void execute_interceptorModifiedPortOnly_preservesCustomPort() throws Exception { + SdkHttpFullRequest.Builder request = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host(CLIENT_ENDPOINT.getHost()) + .port(8443) + .encodedPath("/"); + Endpoint endpoint = Endpoint.builder().url(RESOLVED_ENDPOINT).build(); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY, + preModifyEndpoint("https", CLIENT_ENDPOINT.getHost(), "/")); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(CLIENT_ENDPOINT)); + RequestExecutionContext context = createContext(); + + SdkHttpFullRequest.Builder result = stage.execute(request, context); + + assertThat(result.host()).isEqualTo(CLIENT_ENDPOINT.getHost()); + assertThat(result.port()).isEqualTo(8443); + } + + /** + * Mirrors the snapshot {@code BaseClientHandler} records: endpoint components only, with the port resolved the + * way {@link software.amazon.awssdk.http.SdkHttpRequest#port()} resolves it. + */ + private static EndpointUrl preModifyEndpoint(String scheme, String host, String encodedPath) { + return EndpointUrl.fromComponents(scheme, host, "https".equals(scheme) ? 443 : 80, encodedPath); + } + private SdkHttpFullRequest.Builder defaultRequest() { return SdkHttpFullRequest.builder() .method(SdkHttpMethod.GET) @@ -273,4 +327,45 @@ void execute_endpointAlreadyResolved_skipsResolution() throws Exception { assertThat(result).isSameAs(request); assertThat(executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT)).isSameAs(preResolved); } + + @Test + void execute_resolvedEndpointWithPort_appliesPort() throws Exception { + Endpoint endpoint = Endpoint.builder().url(URI.create("https://resolved.amazonaws.com:8443/v2")).build(); + SdkHttpFullRequest.Builder request = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("myservice.amazonaws.com") + .encodedPath("/operation"); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(CLIENT_ENDPOINT)); + RequestExecutionContext context = createContext(); + + SdkHttpFullRequest.Builder result = stage.execute(request, context); + + assertThat(result.host()).isEqualTo("resolved.amazonaws.com"); + assertThat(result.port()).isEqualTo(8443); + assertThat(result.protocol()).isEqualTo("https"); + } + + @Test + void execute_resolvedPathWithEncodedCharacters_preservesEncoding() throws Exception { + URI clientEndpoint = URI.create("https://s3.amazonaws.com"); + Endpoint endpoint = Endpoint.builder() + .url(URI.create("https://s3.amazonaws.com/bucket%20name")) + .build(); + SdkHttpFullRequest.Builder request = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("s3.amazonaws.com") + .encodedPath("/key%2Fwith%2Fslashes"); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.ENDPOINT_RESOLVER, (req, attrs) -> endpoint); + executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(clientEndpoint)); + RequestExecutionContext context = createContext(); + + SdkHttpFullRequest.Builder result = stage.execute(request, context); + + assertThat(result.encodedPath()).isEqualTo("/bucket%20name/key%2Fwith%2Fslashes"); + } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStageTest.java index df8126db2343..96723fb76d8a 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/MakeAsyncHttpRequestStageTest.java @@ -46,6 +46,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.http.ExecutionContext; @@ -56,6 +57,7 @@ import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler; import software.amazon.awssdk.core.internal.http.timers.ClientExecutionAndRequestTimerTestUtils; import software.amazon.awssdk.core.internal.util.AsyncResponseHandlerTestUtils; +import software.amazon.awssdk.http.Header; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.async.AsyncExecuteRequest; @@ -237,6 +239,48 @@ public void execute_handlerFutureCompletedExceptionally_doesNotAttemptSynchronou } } + @Test + public void execute_requestHasTransferEncodingHeader_doesNotAddContentLength() { + stage = new MakeAsyncHttpRequestStage<>( + combinedAsyncResponseHandler(AsyncResponseHandlerTestUtils.noOpResponseHandler(), + AsyncResponseHandlerTestUtils.noOpResponseHandler()), + clientDependencies(null)); + + SdkHttpFullRequest sdkHttpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.POST) + .host("service.us-east-1.amazonaws.com") + .protocol("https") + .putHeader(Header.TRANSFER_ENCODING, "chunked") + .build(); + + AsyncRequestBody requestBody = AsyncRequestBody.fromString("hello world"); + + ExecutionContext executionContext = ExecutionContext.builder() + .executionAttributes(new ExecutionAttributes()) + .build(); + + RequestExecutionContext context = RequestExecutionContext.builder() + .originalRequest(ValidSdkObjects.sdkRequest()) + .executionContext(executionContext) + .requestProvider(requestBody) + .build(); + + CompletableFuture requestFuture = CompletableFuture.completedFuture(sdkHttpRequest); + + try { + stage.execute(requestFuture, context); + } catch (Exception e) { + // ignored, we only care about the request sent to the HTTP client + } finally { + ArgumentCaptor httpRequestCaptor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); + verify(sdkAsyncHttpClient).execute(httpRequestCaptor.capture()); + + SdkHttpFullRequest capturedRequest = (SdkHttpFullRequest) httpRequestCaptor.getValue().request(); + assertThat(capturedRequest.firstMatchingHeader(Header.CONTENT_LENGTH)).isNotPresent(); + assertThat(capturedRequest.firstMatchingHeader(Header.TRANSFER_ENCODING)).hasValue("chunked"); + } + } + private HttpClientDependencies clientDependencies(Duration timeout) { SdkClientConfiguration configuration = SdkClientConfiguration.builder() .option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR, Runnable::run) diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelperTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelperTest.java index 1febd989ebd3..9759ff75eb52 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelperTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelperTest.java @@ -23,7 +23,11 @@ import java.net.URI; import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -44,61 +48,44 @@ import software.amazon.awssdk.retries.api.RetryStrategy; import software.amazon.awssdk.retries.api.RetryToken; import software.amazon.awssdk.retries.api.TokenAcquisitionFailedException; +import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.Either; public class RetryableStageHelperTest { + private RetryStrategy mockRetryStrategy; + + @BeforeEach + void setup() { + mockRetryStrategy = mock(RetryStrategy.class); + } @ParameterizedTest(name = "IS_LONG_POLLING = {0}, expected = {1}") @MethodSource("longPollingValueTestParams") void tryRefreshToken_forwardsLongPollingAttrValue(Boolean attribute, boolean expected) { - SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .uri(URI.create("https://my-service.amazonaws.com")) - .build(); - ExecutionAttributes.Builder attributes = ExecutionAttributes.builder(); if (attribute != null) { attributes.put(SdkInternalExecutionAttribute.IS_LONG_POLLING, attribute); } - ExecutionContext executionContext = ExecutionContext.builder().executionAttributes(attributes.build()).build(); - - RequestExecutionContext requestExecutionContext = RequestExecutionContext.builder() - .originalRequest(mock(SdkRequest.class)) - .executionContext(executionContext) - .build(); - - RetryStrategy retryStrategy = mock(RetryStrategy.class); - - SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_STRATEGY, retryStrategy) - .build(); - - HttpClientDependencies dependencies = HttpClientDependencies.builder() - .clientConfiguration(clientConfig) - .build(); - - RetryableStageHelper helper = new RetryableStageHelper(httpRequest, - requestExecutionContext, - dependencies); + RetryableStageHelper helper = makeTestHelper(attributes.build()); AcquireInitialTokenResponse mockAcquireResponse = mock(AcquireInitialTokenResponse.class); RetryToken token = mock(RetryToken.class); when(mockAcquireResponse.token()).thenReturn(token); - when(retryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); + when(mockRetryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); RefreshRetryTokenResponse mockRefreshResponse = mock(RefreshRetryTokenResponse.class); when(mockRefreshResponse.delay()).thenReturn(Duration.ZERO); ArgumentCaptor refreshRequestCaptor = ArgumentCaptor.forClass(RefreshRetryTokenRequest.class); - when(retryStrategy.refreshRetryToken(any())).thenReturn(mockRefreshResponse); + when(mockRetryStrategy.refreshRetryToken(any())).thenReturn(mockRefreshResponse); helper.acquireInitialToken(); helper.setLastException(new RuntimeException()); helper.tryRefreshToken(Duration.ZERO); - verify(retryStrategy).refreshRetryToken(refreshRequestCaptor.capture()); + verify(mockRetryStrategy).refreshRetryToken(refreshRequestCaptor.capture()); assertThat(refreshRequestCaptor.getValue().isLongPolling()).isEqualTo(expected); } @@ -106,45 +93,19 @@ void tryRefreshToken_forwardsLongPollingAttrValue(Boolean attribute, boolean exp @ParameterizedTest(name = "delay on successful refresh = {0}, delay on failed refresh = {1}") @MethodSource("refreshBackoffTestParams") void tryRefreshToken_returnsCorrectBackoff(Duration successDelay, Duration failureDelay) { - SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .uri(URI.create("https://my-service.amazonaws.com")) - .build(); - - ExecutionAttributes.Builder attributes = ExecutionAttributes.builder(); - - ExecutionContext executionContext = ExecutionContext.builder().executionAttributes(attributes.build()).build(); - - RequestExecutionContext requestExecutionContext = RequestExecutionContext.builder() - .originalRequest(mock(SdkRequest.class)) - .executionContext(executionContext) - .build(); - - RetryStrategy retryStrategy = mock(RetryStrategy.class); - - SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_STRATEGY, retryStrategy) - .build(); - - HttpClientDependencies dependencies = HttpClientDependencies.builder() - .clientConfiguration(clientConfig) - .build(); - - RetryableStageHelper helper = new RetryableStageHelper(httpRequest, - requestExecutionContext, - dependencies); + RetryableStageHelper helper = makeTestHelper(ExecutionAttributes.builder().build()); AcquireInitialTokenResponse mockAcquireResponse = mock(AcquireInitialTokenResponse.class); RetryToken token = mock(RetryToken.class); when(mockAcquireResponse.token()).thenReturn(token); - when(retryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); + when(mockRetryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); if (successDelay != null) { RefreshRetryTokenResponse mockRefreshResponse = mock(RefreshRetryTokenResponse.class); when(mockRefreshResponse.delay()).thenReturn(successDelay); - when(retryStrategy.refreshRetryToken(any())).thenReturn(mockRefreshResponse); + when(mockRetryStrategy.refreshRetryToken(any())).thenReturn(mockRefreshResponse); } else { - when(retryStrategy.refreshRetryToken(any())).thenThrow( + when(mockRetryStrategy.refreshRetryToken(any())).thenThrow( new TokenAcquisitionFailedException("failed", token, null, failureDelay) ); } @@ -161,6 +122,89 @@ void tryRefreshToken_returnsCorrectBackoff(Duration successDelay, Duration failu } } + @Test + void tryRefreshTokenAsync_refreshThrowsAcquireFailure_wrappedInCompletionException_acquireFailureDurationReturned() { + RetryableStageHelper helper = makeTestHelper(ExecutionAttributes.builder().build()); + + Duration failureAcquireDuration = Duration.ofSeconds(1); + TokenAcquisitionFailedException acquireException = new TokenAcquisitionFailedException("could not acquire", + mock(RetryToken.class), null, + failureAcquireDuration); + + // This chaining is important to make sure whenComplete sees a CompletionException instead of the + // TokenAcquisitionFailedException directly + CompletableFuture future1 = CompletableFutureUtils.failedFuture(acquireException); + CompletableFuture toReturn = future1.thenApply(Function.identity()); + + when(mockRetryStrategy.refreshRetryTokenAsync(any(RefreshRetryTokenRequest.class))) + .thenReturn(toReturn); + + AcquireInitialTokenResponse mockAcquireResponse = mock(AcquireInitialTokenResponse.class); + RetryToken token = mock(RetryToken.class); + when(mockAcquireResponse.token()).thenReturn(token); + when(mockRetryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); + + helper.acquireInitialToken(); + + helper.setLastException(new RuntimeException()); + + assertThat(helper.tryRefreshTokenAsync(Duration.ZERO).join().right()).hasValue(failureAcquireDuration); + } + + @Test + void tryRefreshTokenAsync_refreshThrowsAcquireFailure__acquireFailureDurationReturned() { + RetryableStageHelper helper = makeTestHelper(ExecutionAttributes.builder().build()); + + Duration failureAcquireDuration = Duration.ofSeconds(1); + TokenAcquisitionFailedException acquireException = new TokenAcquisitionFailedException("could not acquire", + mock(RetryToken.class), null, + failureAcquireDuration); + + CompletableFuture future = CompletableFutureUtils.failedFuture(acquireException); + + when(mockRetryStrategy.refreshRetryTokenAsync(any(RefreshRetryTokenRequest.class))) + .thenReturn(future); + + AcquireInitialTokenResponse mockAcquireResponse = mock(AcquireInitialTokenResponse.class); + RetryToken token = mock(RetryToken.class); + when(mockAcquireResponse.token()).thenReturn(token); + when(mockRetryStrategy.acquireInitialToken(any())).thenReturn(mockAcquireResponse); + + helper.acquireInitialToken(); + + helper.setLastException(new RuntimeException()); + + assertThat(helper.tryRefreshTokenAsync(Duration.ZERO).join().right()).hasValue(failureAcquireDuration); + } + + RetryableStageHelper makeTestHelper(ExecutionAttributes executionAttributes) { + SdkHttpFullRequest httpRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .uri(URI.create("https://my-service.amazonaws.com")) + .build(); + + ExecutionContext executionContext = ExecutionContext.builder() + .executionAttributes(executionAttributes) + .build(); + + RequestExecutionContext requestExecutionContext = RequestExecutionContext.builder() + .originalRequest(mock(SdkRequest.class)) + .executionContext(executionContext) + .build(); + + RetryStrategy retryStrategy = mockRetryStrategy; + + SdkClientConfiguration clientConfig = SdkClientConfiguration.builder() + .option(SdkClientOption.RETRY_STRATEGY, retryStrategy) + .build(); + + HttpClientDependencies dependencies = HttpClientDependencies.builder() + .clientConfiguration(clientConfig) + .build(); + + return new RetryableStageHelper(httpRequest, requestExecutionContext, dependencies); + } + private static Stream longPollingValueTestParams() { return Stream.of( // Absent should default to false diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java index 8f1ce6a9f437..a04c0fcf1d9f 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/AsyncHttpClientApiCallTimeoutTests.java @@ -15,10 +15,6 @@ package software.amazon.awssdk.core.internal.http.timers; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.API_CALL_TIMEOUT; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.SLOW_REQUEST_HANDLER_TIMEOUT; @@ -27,16 +23,12 @@ import static software.amazon.awssdk.core.internal.util.AsyncResponseHandlerTestUtils.superSlowResponseHandler; import static utils.HttpTestUtils.testAsyncClientBuilder; -import com.github.tomakehurst.wiremock.junit.WireMockRule; import java.io.ByteArrayInputStream; -import java.time.Duration; import java.util.Arrays; import java.util.Collections; import java.util.concurrent.CompletableFuture; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import software.amazon.awssdk.core.exception.ApiCallAttemptTimeoutException; import software.amazon.awssdk.core.exception.ApiCallTimeoutException; import software.amazon.awssdk.core.exception.SdkServiceException; import software.amazon.awssdk.core.http.ExecutionContext; @@ -51,13 +43,11 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.retries.DefaultRetryStrategy; +import utils.StubSdkAsyncHttpClient; import utils.ValidSdkObjects; public class AsyncHttpClientApiCallTimeoutTests { - @Rule - public WireMockRule wireMock = new WireMockRule(0); - private AmazonAsyncHttpClient httpClient; @Before @@ -65,36 +55,44 @@ public void setup() { httpClient = testAsyncClientBuilder() .retryStrategy(DefaultRetryStrategy.doNotRetry()) .apiCallTimeout(API_CALL_TIMEOUT) + .asyncHttpClient(StubSdkAsyncHttpClient.create()) .build(); } @Test public void errorResponse_SlowErrorResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(500).withBody("{}"))); + AmazonAsyncHttpClient errorClient = testAsyncClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .apiCallTimeout(API_CALL_TIMEOUT) + .asyncHttpClient(StubSdkAsyncHttpClient.create(500)) + .build(); ExecutionContext executionContext = ClientExecutionAndRequestTimerTestUtils.executionContext(null); - CompletableFuture future = httpClient.requestExecutionBuilder() - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext) - .request(generateRequest()) - .execute(combinedAsyncResponseHandler(noOpResponseHandler(), - superSlowResponseHandler(API_CALL_TIMEOUT.toMillis()))); + CompletableFuture future = errorClient.requestExecutionBuilder() + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext) + .request(generateRequest()) + .execute(combinedAsyncResponseHandler(noOpResponseHandler(), + superSlowResponseHandler(API_CALL_TIMEOUT.toMillis()))); assertThatThrownBy(future::join).hasCauseInstanceOf(ApiCallTimeoutException.class); } @Test public void errorResponse_SlowAfterErrorRequestHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(500).withBody("{}"))); + AmazonAsyncHttpClient errorClient = testAsyncClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .apiCallTimeout(API_CALL_TIMEOUT) + .asyncHttpClient(StubSdkAsyncHttpClient.create(500)) + .build(); + ExecutionInterceptorChain interceptors = new ExecutionInterceptorChain( Collections.singletonList(new SlowExecutionInterceptor().onExecutionFailureWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT))); SdkHttpFullRequest request = generateRequest(); - InterceptorContext incerceptorContext = + InterceptorContext interceptorContext = InterceptorContext.builder() .request(NoopTestRequest.builder().build()) .httpRequest(request) @@ -104,25 +102,23 @@ public void errorResponse_SlowAfterErrorRequestHandler_ThrowsApiCallTimeoutExcep .signer(new NoOpSigner()) .interceptorChain(interceptors) .executionAttributes(new ExecutionAttributes()) - .interceptorContext(incerceptorContext) + .interceptorContext(interceptorContext) .metricCollector(MetricCollector.create("ApiCall")) .build(); CompletableFuture future = - httpClient.requestExecutionBuilder() - .originalRequest(NoopTestRequest.builder().build()) - .request(request) - .executionContext(executionContext) - .execute(combinedAsyncResponseHandler(noOpResponseHandler(), - noOpResponseHandler(SdkServiceException.builder().build()))); + errorClient.requestExecutionBuilder() + .originalRequest(NoopTestRequest.builder().build()) + .request(request) + .executionContext(executionContext) + .execute(combinedAsyncResponseHandler(noOpResponseHandler(), + noOpResponseHandler(SdkServiceException.builder().build()))); assertThatThrownBy(future::join).hasCauseInstanceOf(ApiCallTimeoutException.class); } @Test public void successfulResponse_SlowBeforeRequestRequestHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); ExecutionInterceptor interceptor = new SlowExecutionInterceptor().beforeTransmissionWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT); @@ -133,25 +129,10 @@ public void successfulResponse_SlowBeforeRequestRequestHandler_ThrowsApiCallTime @Test public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); CompletableFuture future = requestBuilder().execute(superSlowResponseHandler(API_CALL_TIMEOUT.toMillis())); assertThatThrownBy(future::join).hasCauseInstanceOf(ApiCallTimeoutException.class); } - @Test - public void slowApiAttempt_ThrowsApiCallAttemptTimeoutException() { - httpClient = testAsyncClientBuilder() - .apiCallTimeout(API_CALL_TIMEOUT) - .apiCallAttemptTimeout(Duration.ofMillis(1)) - .build(); - - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}").withFixedDelay(1_000))); - CompletableFuture future = requestBuilder().execute(noOpResponseHandler()); - assertThatThrownBy(future::join).hasCauseInstanceOf(ApiCallAttemptTimeoutException.class); - } - private AmazonAsyncHttpClient.RequestExecutionBuilder requestBuilder() { return httpClient.requestExecutionBuilder() .request(generateRequest()) @@ -160,7 +141,7 @@ private AmazonAsyncHttpClient.RequestExecutionBuilder requestBuilder() { } private SdkHttpFullRequest generateRequest() { - return ValidSdkObjects.sdkHttpFullRequest(wireMock.port()) + return ValidSdkObjects.sdkHttpFullRequest() .host("localhost") .contentStreamProvider(() -> new ByteArrayInputStream("test".getBytes())).build(); } @@ -170,7 +151,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler ExecutionInterceptorChain interceptors = new ExecutionInterceptorChain(Arrays.asList(requestHandlers)); - InterceptorContext incerceptorContext = + InterceptorContext interceptorContext = InterceptorContext.builder() .request(NoopTestRequest.builder().build()) .httpRequest(generateRequest()) @@ -179,7 +160,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler .signer(new NoOpSigner()) .interceptorChain(interceptors) .executionAttributes(new ExecutionAttributes()) - .interceptorContext(incerceptorContext) + .interceptorContext(interceptorContext) .metricCollector(MetricCollector.create("ApiCall")) .build(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/ClientExecutionAndRequestTimerTestUtils.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/ClientExecutionAndRequestTimerTestUtils.java index b4923e2b363e..64f271a6963b 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/ClientExecutionAndRequestTimerTestUtils.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/ClientExecutionAndRequestTimerTestUtils.java @@ -107,7 +107,7 @@ public static void execute(AmazonSyncHttpClient httpClient, SdkHttpFullRequest r } public static ExecutionContext executionContext(SdkHttpFullRequest request) { - InterceptorContext incerceptorContext = + InterceptorContext interceptorContext = InterceptorContext.builder() .request(NoopTestRequest.builder().build()) .httpRequest(request) @@ -116,7 +116,7 @@ public static ExecutionContext executionContext(SdkHttpFullRequest request) { .signer(new NoOpSigner()) .interceptorChain(new ExecutionInterceptorChain(Collections.emptyList())) .executionAttributes(new ExecutionAttributes()) - .interceptorContext(incerceptorContext) + .interceptorContext(interceptorContext) .metricCollector(MetricCollector.create("ApiCall")) .build(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallAttemptTimeoutTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallAttemptTimeoutTest.java index 2dcf349495a6..308eb660328e 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallAttemptTimeoutTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallAttemptTimeoutTest.java @@ -15,10 +15,6 @@ package software.amazon.awssdk.core.internal.http.timers; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.API_CALL_TIMEOUT; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.SLOW_REQUEST_HANDLER_TIMEOUT; @@ -27,11 +23,9 @@ import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.superSlowResponseHandler; import static utils.HttpTestUtils.testClientBuilder; -import com.github.tomakehurst.wiremock.junit.WireMockRule; import java.io.ByteArrayInputStream; import java.util.Arrays; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import software.amazon.awssdk.core.exception.ApiCallAttemptTimeoutException; import software.amazon.awssdk.core.http.ExecutionContext; @@ -46,14 +40,12 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.retries.DefaultRetryStrategy; +import utils.StubSdkHttpClient; import utils.ValidSdkObjects; public class HttpClientApiCallAttemptTimeoutTest { - @Rule - public WireMockRule wireMock = new WireMockRule(0); - private AmazonSyncHttpClient httpClient; @Before @@ -61,14 +53,12 @@ public void setup() { httpClient = testClientBuilder() .retryStrategy(DefaultRetryStrategy.doNotRetry()) .apiCallAttemptTimeout(API_CALL_TIMEOUT) + .httpClient(StubSdkHttpClient.create()) .build(); } @Test public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); - assertThatThrownBy(() -> requestBuilder().execute(combinedSyncResponseHandler( superSlowResponseHandler(API_CALL_TIMEOUT.toMillis()), null))) .isInstanceOf(ApiCallAttemptTimeoutException.class); @@ -76,24 +66,25 @@ public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException @Test public void errorResponse_SlowErrorResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(500).withBody("{}"))); + AmazonSyncHttpClient errorClient = testClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .apiCallAttemptTimeout(API_CALL_TIMEOUT) + .httpClient(StubSdkHttpClient.create(500)) + .build(); ExecutionContext executionContext = ClientExecutionAndRequestTimerTestUtils.executionContext(null); - assertThatThrownBy(() -> httpClient.requestExecutionBuilder() - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext) - .request(generateRequest()) - .execute(combinedSyncResponseHandler(null, - superSlowResponseHandler(API_CALL_TIMEOUT.toMillis())))) + assertThatThrownBy(() -> errorClient.requestExecutionBuilder() + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext) + .request(generateRequest()) + .execute(combinedSyncResponseHandler(null, + superSlowResponseHandler(API_CALL_TIMEOUT.toMillis())))) .isInstanceOf(ApiCallAttemptTimeoutException.class); } @Test public void successfulResponse_SlowBeforeTransmissionExecutionInterceptor_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); ExecutionInterceptor interceptor = new SlowExecutionInterceptor().beforeTransmissionWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT); @@ -104,8 +95,6 @@ public void successfulResponse_SlowBeforeTransmissionExecutionInterceptor_Throws @Test public void successfulResponse_SlowAfterResponseExecutionInterceptor_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); ExecutionInterceptor interceptor = new SlowExecutionInterceptor().afterTransmissionWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT); assertThatThrownBy(() -> requestBuilder().executionContext(withInterceptors(interceptor)) @@ -121,7 +110,7 @@ private AmazonSyncHttpClient.RequestExecutionBuilder requestBuilder() { } private SdkHttpFullRequest generateRequest() { - return ValidSdkObjects.sdkHttpFullRequest(wireMock.port()) + return ValidSdkObjects.sdkHttpFullRequest() .host("localhost") .contentStreamProvider(() -> new ByteArrayInputStream("test".getBytes())).build(); } @@ -131,7 +120,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler ExecutionInterceptorChain interceptors = new ExecutionInterceptorChain(Arrays.asList(requestHandlers)); - InterceptorContext incerceptorContext = + InterceptorContext interceptorContext = InterceptorContext.builder() .request(NoopTestRequest.builder().build()) .httpRequest(generateRequest()) @@ -140,7 +129,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler .signer(new NoOpSigner()) .interceptorChain(interceptors) .executionAttributes(new ExecutionAttributes()) - .interceptorContext(incerceptorContext) + .interceptorContext(interceptorContext) .metricCollector(MetricCollector.create("ApiCall")) .build(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallTimeoutTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallTimeoutTest.java index 9a610485a4d9..fb5a8d20a700 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallTimeoutTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/timers/HttpClientApiCallTimeoutTest.java @@ -15,10 +15,6 @@ package software.amazon.awssdk.core.internal.http.timers; -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.get; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.API_CALL_TIMEOUT; import static software.amazon.awssdk.core.internal.http.timers.TimeoutTestConstants.SLOW_REQUEST_HANDLER_TIMEOUT; @@ -27,11 +23,9 @@ import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.superSlowResponseHandler; import static utils.HttpTestUtils.testClientBuilder; -import com.github.tomakehurst.wiremock.junit.WireMockRule; import java.io.ByteArrayInputStream; import java.util.Arrays; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import software.amazon.awssdk.core.exception.ApiCallTimeoutException; import software.amazon.awssdk.core.http.ExecutionContext; @@ -46,14 +40,12 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.retries.DefaultRetryStrategy; +import utils.StubSdkHttpClient; import utils.ValidSdkObjects; public class HttpClientApiCallTimeoutTest { - @Rule - public WireMockRule wireMock = new WireMockRule(0); - private AmazonSyncHttpClient httpClient; @Before @@ -61,14 +53,12 @@ public void setup() { httpClient = testClientBuilder() .retryStrategy(DefaultRetryStrategy.doNotRetry()) .apiCallTimeout(API_CALL_TIMEOUT) + .httpClient(StubSdkHttpClient.create()) .build(); } @Test public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); - assertThatThrownBy(() -> requestBuilder().execute(combinedSyncResponseHandler( superSlowResponseHandler(API_CALL_TIMEOUT.toMillis() * 2), null))) .isInstanceOf(ApiCallTimeoutException.class); @@ -76,24 +66,25 @@ public void successfulResponse_SlowResponseHandler_ThrowsApiCallTimeoutException @Test public void errorResponse_SlowErrorResponseHandler_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(500).withBody("{}"))); + AmazonSyncHttpClient errorClient = testClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .apiCallTimeout(API_CALL_TIMEOUT) + .httpClient(StubSdkHttpClient.create(500)) + .build(); ExecutionContext executionContext = ClientExecutionAndRequestTimerTestUtils.executionContext(null); - assertThatThrownBy(() -> httpClient.requestExecutionBuilder() - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(executionContext) - .request(generateRequest()) - .execute(combinedSyncResponseHandler(noOpSyncResponseHandler(), - superSlowResponseHandler(API_CALL_TIMEOUT.toMillis())))) + assertThatThrownBy(() -> errorClient.requestExecutionBuilder() + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext) + .request(generateRequest()) + .execute(combinedSyncResponseHandler(noOpSyncResponseHandler(), + superSlowResponseHandler(API_CALL_TIMEOUT.toMillis())))) .isInstanceOf(ApiCallTimeoutException.class); } @Test public void successfulResponse_SlowBeforeTransmissionExecutionInterceptor_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); ExecutionInterceptor interceptor = new SlowExecutionInterceptor().beforeTransmissionWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT); @@ -104,8 +95,6 @@ public void successfulResponse_SlowBeforeTransmissionExecutionInterceptor_Throws @Test public void successfulResponse_SlowAfterResponseExecutionInterceptor_ThrowsApiCallTimeoutException() { - stubFor(get(anyUrl()) - .willReturn(aResponse().withStatus(200).withBody("{}"))); ExecutionInterceptor interceptor = new SlowExecutionInterceptor().afterTransmissionWaitInSeconds(SLOW_REQUEST_HANDLER_TIMEOUT); assertThatThrownBy(() -> requestBuilder().executionContext(withInterceptors(interceptor)) @@ -121,7 +110,7 @@ private AmazonSyncHttpClient.RequestExecutionBuilder requestBuilder() { } private SdkHttpFullRequest generateRequest() { - return ValidSdkObjects.sdkHttpFullRequest(wireMock.port()) + return ValidSdkObjects.sdkHttpFullRequest() .host("localhost") .contentStreamProvider(() -> new ByteArrayInputStream("test".getBytes())).build(); } @@ -131,7 +120,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler ExecutionInterceptorChain interceptors = new ExecutionInterceptorChain(Arrays.asList(requestHandlers)); - InterceptorContext incerceptorContext = + InterceptorContext interceptorContext = InterceptorContext.builder() .request(NoopTestRequest.builder().build()) .httpRequest(generateRequest()) @@ -140,7 +129,7 @@ private ExecutionContext withInterceptors(ExecutionInterceptor... requestHandler .signer(new NoOpSigner()) .interceptorChain(interceptors) .executionAttributes(new ExecutionAttributes()) - .interceptorContext(incerceptorContext) + .interceptorContext(interceptorContext) .metricCollector(MetricCollector.create("ApiCall")) .build(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/MetricUtilsTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/MetricUtilsTest.java index 1a150620e87e..0c76993312c1 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/MetricUtilsTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/MetricUtilsTest.java @@ -19,8 +19,10 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import java.io.IOException; +import java.net.URI; import java.time.Duration; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -31,8 +33,11 @@ import software.amazon.awssdk.core.http.HttpResponseHandler; import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.http.HttpMetric; +import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.NoOpMetricCollector; import software.amazon.awssdk.metrics.SdkMetric; import software.amazon.awssdk.utils.Pair; @@ -170,6 +175,113 @@ public void reportDuration_completableFuture_doesNotWrapException() { } } + @Test + public void collectServiceEndpointMetrics_when_standardHttpPort_omitsPort() { + MetricCollector mockCollector = mock(MetricCollector.class); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, requestBuilder("http", "example.amazonaws.com", 80).build()); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, URI.create("http://example.amazonaws.com")); + } + + @Test + public void collectServiceEndpointMetrics_when_standardHttpsPort_omitsPort() { + MetricCollector mockCollector = mock(MetricCollector.class); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, requestBuilder("https", "example.amazonaws.com", 443).build()); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, URI.create("https://example.amazonaws.com")); + } + + @Test + public void collectServiceEndpointMetrics_when_nonStandardPort_retainsPort() { + MetricCollector mockCollector = mock(MetricCollector.class); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, requestBuilder("http", "localhost", 8080).build()); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, URI.create("http://localhost:8080")); + } + + @Test + public void collectServiceEndpointMetrics_when_ipv6LiteralHost_reportsBracketedHost() { + MetricCollector mockCollector = mock(MetricCollector.class); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, requestBuilder("https", "[::1]", 8443).build()); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, URI.create("https://[::1]:8443")); + } + + @Test + public void collectServiceEndpointMetrics_when_requestHasPathAndQuery_reportsEndpointOnly() { + MetricCollector mockCollector = mock(MetricCollector.class); + + SdkHttpFullRequest request = requestBuilder("https", "example.amazonaws.com", 443) + .encodedPath("/some/resource/path") + .putRawQueryParameter("marker", "abc123") + .putRawQueryParameter("limit", "10") + .build(); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, request); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, URI.create("https://example.amazonaws.com")); + } + + @Test + public void collectServiceEndpointMetrics_when_accountIdHost_reportsEndpointOnly() { + MetricCollector mockCollector = mock(MetricCollector.class); + + // Account-id hosts route through the SdkUri cache. Assert the cached value is still the endpoint alone. + SdkHttpFullRequest request = requestBuilder("https", "123456789012.ddb.us-east-1.amazonaws.com", 443) + .encodedPath("/") + .build(); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, request); + + verify(mockCollector).reportMetric(CoreMetric.SERVICE_ENDPOINT, + URI.create("https://123456789012.ddb.us-east-1.amazonaws.com")); + } + + @Test + public void collectServiceEndpointMetrics_when_nullCollector_doesNothing() { + // A host that cannot be parsed proves the guard short-circuits before the URI is built. + MetricUtils.collectServiceEndpointMetrics(null, requestBuilder("http", "in valid host", 80).build()); + } + + @Test + public void collectServiceEndpointMetrics_when_noOpCollector_doesNothing() { + MetricUtils.collectServiceEndpointMetrics(NoOpMetricCollector.create(), + requestBuilder("http", "in valid host", 80).build()); + } + + @Test + public void collectServiceEndpointMetrics_when_nullRequest_doesNothing() { + MetricCollector mockCollector = mock(MetricCollector.class); + + MetricUtils.collectServiceEndpointMetrics(mockCollector, null); + + verifyNoMoreInteractions(mockCollector); + } + + @Test + public void collectServiceEndpointMetrics_when_hostIsUnparseable_throwsIllegalArgumentException() { + MetricCollector mockCollector = mock(MetricCollector.class); + SdkHttpFullRequest request = requestBuilder("http", "in valid host", 80).build(); + + // Documents the existing contract: an unparseable endpoint surfaces the IllegalArgumentException from URI + // parsing. The previous implementation reached the same outcome, because SdkHttpRequest#getUri() threw this + // before its URISyntaxException handler could run. + thrown.expect(IllegalArgumentException.class); + MetricUtils.collectServiceEndpointMetrics(mockCollector, request); + } + + private static SdkHttpFullRequest.Builder requestBuilder(String protocol, String host, int port) { + return SdkHttpFullRequest.builder() + .method(SdkHttpMethod.POST) + .protocol(protocol) + .host(host) + .port(port); + } + @Test public void collectHttpMetrics_collectsAllExpectedMetrics() { MetricCollector mockCollector = mock(MetricCollector.class); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvokerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvokerTest.java new file mode 100644 index 000000000000..b0c08e1a86db --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/ClasspathWarmUpInvokerTest.java @@ -0,0 +1,202 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.RegisteredWarmUpProvider; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Unit tests for {@link ClasspathWarmUpInvoker}. Most tests stub {@link WarmUpServiceLoader}; the "fails to load" + * tests use a real {@link ServiceLoader} over a temporary {@code META-INF/services} file. + */ +class ClasspathWarmUpInvokerTest { + + @Test + void invokeAll_invokesEveryProviderOnce() { + CountingProvider first = new CountingProvider(); + CountingProvider second = new CountingProvider(); + CountingProvider third = new CountingProvider(); + + invokerLoading(first, second, third).invokeAll(); + + assertThat(first.invocations()).isEqualTo(1); + assertThat(second.invocations()).isEqualTo(1); + assertThat(third.invocations()).isEqualTo(1); + } + + @Test + void invokeAll_whenOneProviderThrows_stillInvokesOthers() { + CountingProvider before = new CountingProvider(); + SdkWarmUpProvider throwing = throwingProvider(); + CountingProvider after = new CountingProvider(); + + WarmUpInvoker invoker = invokerLoading(before, throwing, after); + + assertThatCode(invoker::invokeAll).doesNotThrowAnyException(); + assertThat(before.invocations()).isEqualTo(1); + assertThat(after.invocations()).isEqualTo(1); + } + + @Test + void invokeAll_whenProviderFailsToLoad_stillInvokesOthers(@TempDir Path tempDir) throws IOException { + // Non-existent class then a real one: ServiceLoader must advance past the bad entry. It builds the + // instance itself, so we read the static counter on RegisteredWarmUpProvider. + RegisteredWarmUpProvider.INVOCATIONS.set(0); + WarmUpInvoker invoker = invokerLoading(createAndLoadTempServicesFile( + tempDir, "com.example.DoesNotExistProvider", RegisteredWarmUpProvider.class.getName())); + + assertThatCode(invoker::invokeAll).doesNotThrowAnyException(); + assertThat(RegisteredWarmUpProvider.INVOCATIONS.get()).isEqualTo(1); + } + + @Test + void invokeAll_whenNoProviders_isNoOp() { + WarmUpInvoker invoker = invokerLoading(Collections.emptyIterator()); + assertThatCode(invoker::invokeAll).doesNotThrowAnyException(); + } + + @Test + void invokeAll_whenProviderThrows_logsAtWarn() { + SdkWarmUpProvider throwing = throwingProvider(); + + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + invokerLoading(throwing).invokeAll(); + + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromInvoker()) + .anyMatch(event -> event.getLevel() == Level.WARN + && event.getMessage().getFormattedMessage().contains("Warm-up failed for")); + } + } + + @Test + void invokeAll_whenProviderFailsToLoad_logsAtWarn(@TempDir Path tempDir) throws IOException { + WarmUpInvoker invoker = invokerLoading(createAndLoadTempServicesFile(tempDir, "com.example.DoesNotExistProvider")); + + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + invoker.invokeAll(); + + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromInvoker()) + .anyMatch(event -> event.getLevel() == Level.WARN + && event.getMessage().getFormattedMessage().contains("could not be loaded")); + } + } + + @Test + void invokeAll_whenNoProviders_logsAtDebug() { + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + invokerLoading(Collections.emptyIterator()).invokeAll(); + + assertThat(logCaptor.loggedEvents()) + .filteredOn(loggedFromInvoker()) + .anyMatch(event -> event.getLevel() == Level.DEBUG + && event.getMessage().getFormattedMessage().contains("No warm-up tasks")); + } + } + + private static Predicate loggedFromInvoker() { + return event -> WarmUpDiscovery.class.getName().equals(event.getLoggerName()); + } + + private WarmUpInvoker invokerLoading(SdkWarmUpProvider... providers) { + return invokerLoading(Arrays.asList(providers).iterator()); + } + + private WarmUpInvoker invokerLoading(Iterator providers) { + WarmUpServiceLoader loader = new WarmUpServiceLoader() { + @Override + Iterator loadProviders() { + return providers; + } + }; + return new ClasspathWarmUpInvoker(loader); + } + + // Creates a temp META-INF/services file with the given class names and loads it through a real ServiceLoader. + private Iterator createAndLoadTempServicesFile(Path tempDir, String... providerClassNames) + throws IOException { + Path servicesDir = tempDir.resolve("META-INF/services"); + Files.createDirectories(servicesDir); + Path registration = servicesDir.resolve(SdkWarmUpProvider.class.getName()); + Files.write(registration, Arrays.asList(providerClassNames)); + + URLClassLoader classLoader = new URLClassLoader(new URL[] {tempDir.toUri().toURL()}, + getClass().getClassLoader()); + return ServiceLoader.load(SdkWarmUpProvider.class, classLoader).iterator(); + } + + /** + * Base class for test providers now that {@link SdkWarmUpProvider} + */ + private abstract static class TestProvider implements SdkWarmUpProvider { + @Override + public String syncClientClassName() { + return null; + } + + @Override + public String asyncClientClassName() { + return null; + } + + @Override + public void warmUpClient(ClientType clientType) { + } + } + + private static final class CountingProvider extends TestProvider { + private final AtomicInteger invocations = new AtomicInteger(); + + @Override + public void warmUp() { + invocations.incrementAndGet(); + } + + int invocations() { + return invocations.get(); + } + } + + private static SdkWarmUpProvider throwingProvider() { + return new TestProvider() { + @Override + public void warmUp() { + throw new RuntimeException("boom"); + } + }; + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolverTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolverTest.java new file mode 100644 index 000000000000..59089e20d8f4 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/RegionEndpointResolverTest.java @@ -0,0 +1,139 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.net.URI; +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.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +class RegionEndpointResolverTest { + + private static final String REGION_PROPERTY = "aws.region"; + private static final String AWS_REGION_ENV = "AWS_REGION"; + private static final String AWS_DEFAULT_REGION_ENV = "AWS_DEFAULT_REGION"; + + private static final EnvironmentVariableHelper ENV = new EnvironmentVariableHelper(); + + @BeforeEach + void clearSettings() { + clearRegionSettings(); + } + + @AfterEach + void restoreSettings() { + clearRegionSettings(); + } + + private void clearRegionSettings() { + ENV.reset(); + ENV.remove(AWS_REGION_ENV); + ENV.remove(AWS_DEFAULT_REGION_ENV); + System.clearProperty(REGION_PROPERTY); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("regionResolutionCases") + void endpoint_whenRegionConfigured_resolvesExpectedEndpoint(String description, String sysprop, String awsRegion, + String expectedRegion) { + applyRegionSettings(sysprop, awsRegion); + + assertThat(RegionEndpointResolver.create().endpoint()) + .isEqualTo(URI.create("https://sts." + expectedRegion + ".amazonaws.com/")); + } + + private static Stream regionResolutionCases() { + return Stream.of( + // description aws.region AWS_REGION expected + arguments("nothing set -> default region", null, null, "us-east-1"), + arguments("system property wins over AWS_REGION", "eu-west-1", "ap-south-1", "eu-west-1"), + arguments("AWS_REGION used when no system property", null, "ap-south-1", "ap-south-1"), + arguments("blank system property short-circuits AWS_REGION", " ", "ap-south-1", "us-east-1"), + arguments("blank AWS_REGION falls through to default", null, " ", "us-east-1"), + arguments("chosen value is trimmed", " eu-central-1 ", null, "eu-central-1") + ); + } + + @Test + void endpoint_whenOnlyAwsDefaultRegionSet_ignoresItAndUsesDefault() { + ENV.set(AWS_DEFAULT_REGION_ENV, "us-west-2"); + + assertThat(RegionEndpointResolver.create().endpoint()) + .isEqualTo(URI.create("https://sts.us-east-1.amazonaws.com/")); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("untrustedRegionCases") + void endpoint_whenRegionNotHostnameCompliant_fallsBackToDefault(String description, String region) { + System.setProperty(REGION_PROPERTY, region); + + URI endpoint = RegionEndpointResolver.create().endpoint(); + + // A non-compliant region cannot reach the host; it is rejected and the default region is used instead. + assertThat(endpoint).isEqualTo(URI.create("https://sts.us-east-1.amazonaws.com/")); + } + + private static Stream untrustedRegionCases() { + return Stream.of( + arguments("newline is rejected", "us-east-1\nfoo"), + arguments("carriage return is rejected", "us-east-1\rfoo"), + arguments("forward slash is rejected", "us-east-1/foo"), + arguments("space is rejected", "us-east-1 foo"), + arguments("at sign is rejected", "evil@host"), + arguments("hash is rejected", "host#fragment"), + arguments("dot is rejected", "sts.evil.com") + ); + } + + @Test + void endpoint_whenImdsUnreachable_resolvesWithoutCallingImds() { + // Point IMDS at a non-routable address. A resolver that (incorrectly) called IMDS would block here; + // the correct resolver ignores IMDS entirely and returns the default region immediately. + String savedImdsEndpoint = System.getProperty("aws.ec2MetadataServiceEndpoint"); + System.setProperty("aws.ec2MetadataServiceEndpoint", "http://10.255.255.1"); + try { + long startNanos = System.nanoTime(); + URI endpoint = RegionEndpointResolver.create().endpoint(); + long elapsedMillis = (System.nanoTime() - startNanos) / 1_000_000; + + assertThat(endpoint).isEqualTo(URI.create("https://sts.us-east-1.amazonaws.com/")); + assertThat(elapsedMillis).isLessThan(1_000L); + } finally { + if (savedImdsEndpoint != null) { + System.setProperty("aws.ec2MetadataServiceEndpoint", savedImdsEndpoint); + } else { + System.clearProperty("aws.ec2MetadataServiceEndpoint"); + } + } + } + + private static void applyRegionSettings(String sysprop, String awsRegion) { + if (sysprop != null) { + System.setProperty(REGION_PROPERTY, sysprop); + } + if (awsRegion != null) { + ENV.set(AWS_REGION_ENV, awsRegion); + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvokerTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvokerTest.java new file mode 100644 index 000000000000..58f75c42ad84 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpInvokerTest.java @@ -0,0 +1,207 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.Set; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.testutils.LogCaptor; + +class TargetedWarmUpInvokerTest { + + private static final String SERVICE1_SYNC = "software.amazon.awssdk.services.service1.Service1Client"; + private static final String SERVICE1_ASYNC = "software.amazon.awssdk.services.service1.Service1AsyncClient"; + private static final String SERVICE2_SYNC = "software.amazon.awssdk.services.service2.Service2Client"; + + @Test + void invoke_syncClassRequested_warmsSyncClientTypeOnly() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + + TargetedWarmUpResult result = invokerLoading(service1).invoke(Arrays.asList(SERVICE1_SYNC)); + + assertThat(service1.warmedTypes()).containsExactly(ClientType.SYNC); + assertThat(result.matchedClientTypes()).containsExactly(ClientType.SYNC); + assertThat(result.warmedClientNames()).containsExactly(SERVICE1_SYNC); + } + + @Test + void invoke_asyncClassRequested_warmsAsyncClientTypeOnly() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + + TargetedWarmUpResult result = invokerLoading(service1).invoke(Arrays.asList(SERVICE1_ASYNC)); + + assertThat(service1.warmedTypes()).containsExactly(ClientType.ASYNC); + assertThat(result.matchedClientTypes()).containsExactly(ClientType.ASYNC); + assertThat(result.warmedClientNames()).containsExactly(SERVICE1_ASYNC); + } + + @Test + void invoke_bothClassesRequested_warmsBothClientTypes() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + + TargetedWarmUpResult result = + invokerLoading(service1).invoke(Arrays.asList(SERVICE1_SYNC, SERVICE1_ASYNC)); + + assertThat(service1.warmedTypes()).containsExactlyInAnyOrder(ClientType.SYNC, ClientType.ASYNC); + assertThat(result.matchedClientTypes()).containsExactlyInAnyOrder(ClientType.SYNC, ClientType.ASYNC); + assertThat(result.warmedClientNames()).containsExactly(SERVICE1_SYNC, SERVICE1_ASYNC); + } + + @Test + void invoke_classAcrossTwoProviders_warmsOnlyTheMatchingProvider() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + RecordingProvider service2 = new RecordingProvider(SERVICE2_SYNC, null); + + invokerLoading(service1, service2).invoke(Arrays.asList(SERVICE2_SYNC)); + + assertThat(service1.warmedTypes()).isEmpty(); + assertThat(service2.warmedTypes()).containsExactly(ClientType.SYNC); + } + + @Test + void invoke_unmatchedClass_logsWarnAndDoesNotThrow() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + TargetedWarmUpResult result = + invokerLoading(service1).invoke(Arrays.asList("com.example.NotAClient")); + + assertThat(result.matchedClientTypes()).isEmpty(); + assertThat(result.warmedClientNames()).isEmpty(); + assertThat(service1.warmedTypes()).isEmpty(); + assertThat(logCaptor.loggedEvents()) + .anyMatch(event -> event.getLevel() == Level.WARN + && event.getMessage().getFormattedMessage().contains("com.example.NotAClient")); + } + } + + @Test + void invoke_whenProviderWarmUpThrows_stillReturnsMatchedClientType() { + SdkWarmUpProvider throwing = new TestProvider(SERVICE1_SYNC, SERVICE1_ASYNC) { + @Override + public void warmUpClient(ClientType clientType) { + throw new RuntimeException("boom"); + } + }; + + // A throwing warmUpClient must not stop the follow-on HTTP warm-up: the matched client type is still returned so + // the caller can narrow the HTTP warmers. + TargetedWarmUpResult result = invokerLoading(throwing).invoke(Arrays.asList(SERVICE1_SYNC)); + + assertThat(result.matchedClientTypes()).containsExactly(ClientType.SYNC); + } + + @Test + void invoke_whenProviderWarmUpThrows_doesNotReportClientWarmed() { + SdkWarmUpProvider throwing = new TestProvider(SERVICE1_SYNC, SERVICE1_ASYNC) { + @Override + public void warmUpClient(ClientType clientType) { + throw new RuntimeException("boom"); + } + }; + + TargetedWarmUpResult result = invokerLoading(throwing).invoke(Arrays.asList(SERVICE1_SYNC)); + + assertThat(result.warmedClientNames()).isEmpty(); + } + + @Test + void invoke_mixedSuccessAndFailure_reportsOnlySuccessfulClientWarmed() { + RecordingProvider healthy = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + SdkWarmUpProvider throwing = new TestProvider(SERVICE2_SYNC, null) { + @Override + public void warmUpClient(ClientType clientType) { + throw new RuntimeException("boom"); + } + }; + + TargetedWarmUpResult result = + invokerLoading(healthy, throwing).invoke(Arrays.asList(SERVICE1_SYNC, SERVICE2_SYNC)); + + assertThat(result.warmedClientNames()).containsExactly(SERVICE1_SYNC); + assertThat(result.matchedClientTypes()).containsExactly(ClientType.SYNC); + } + + @Test + void invoke_emptyRequest_isNoOp() { + RecordingProvider service1 = new RecordingProvider(SERVICE1_SYNC, SERVICE1_ASYNC); + + TargetedWarmUpResult result = invokerLoading(service1).invoke(Collections.emptyList()); + + assertThat(result.matchedClientTypes()).isEmpty(); + assertThat(result.warmedClientNames()).isEmpty(); + assertThat(service1.warmedTypes()).isEmpty(); + } + + private TargetedWarmUpInvoker invokerLoading(SdkWarmUpProvider... providers) { + WarmUpServiceLoader loader = new WarmUpServiceLoader() { + @Override + Iterator loadProviders() { + return Arrays.asList(providers).iterator(); + } + }; + return new TargetedWarmUpInvoker(loader); + } + + private static class TestProvider implements SdkWarmUpProvider { + private final String syncName; + private final String asyncName; + + TestProvider(String syncName, String asyncName) { + this.syncName = syncName; + this.asyncName = asyncName; + } + + @Override + public String syncClientClassName() { + return syncName; + } + + @Override + public String asyncClientClassName() { + return asyncName; + } + + @Override + public void warmUpClient(ClientType clientType) { + } + } + + private static final class RecordingProvider extends TestProvider { + private final Set warmed = EnumSet.noneOf(ClientType.class); + + RecordingProvider(String syncName, String asyncName) { + super(syncName, asyncName); + } + + @Override + public void warmUpClient(ClientType clientType) { + warmed.add(clientType); + } + + Set warmedTypes() { + return warmed; + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResultTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResultTest.java new file mode 100644 index 000000000000..02156f420242 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/TargetedWarmUpResultTest.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 software.amazon.awssdk.core.internal.warmup; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; + +public class TargetedWarmUpResultTest { + + @Test + public void equalsHashCode() { + EqualsVerifier.forClass(TargetedWarmUpResult.class) + .withNonnullFields("matchedClientTypes", "warmedClientNames") + .verify(); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistryTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistryTest.java new file mode 100644 index 000000000000..9eac3b88ff91 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedClientRegistryTest.java @@ -0,0 +1,91 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; + +/** + * Unit tests for {@link WarmedClientRegistry}. Each test uses a fresh instance, so the dedup state is isolated without + * any static reset hook or reflection. + */ +class WarmedClientRegistryTest { + + private static final String SERVICE1_SYNC = "software.amazon.awssdk.services.service1.Service1Client"; + private static final String SERVICE1_ASYNC = "software.amazon.awssdk.services.service1.Service1AsyncClient"; + + @Test + void selectUnwarmed_freshRegistry_returnsAllRequested() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + + assertThat(registry.selectUnwarmed(Arrays.asList(SERVICE1_SYNC, SERVICE1_ASYNC))) + .containsExactly(SERVICE1_SYNC, SERVICE1_ASYNC); + } + + @Test + void selectUnwarmed_afterMarkWarmed_skipsAlreadyWarmed() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + registry.markWarmed(Collections.singletonList(SERVICE1_SYNC)); + + assertThat(registry.selectUnwarmed(Arrays.asList(SERVICE1_SYNC, SERVICE1_ASYNC))) + .containsExactly(SERVICE1_ASYNC); + } + + @Test + void selectUnwarmed_allAlreadyWarmed_returnsEmpty() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + registry.markWarmed(Arrays.asList(SERVICE1_SYNC, SERVICE1_ASYNC)); + + assertThat(registry.selectUnwarmed(Arrays.asList(SERVICE1_SYNC, SERVICE1_ASYNC))).isEmpty(); + } + + @Test + void selectUnwarmed_preservesEncounterOrderAndDeduplicates() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + + assertThat(registry.selectUnwarmed(Arrays.asList(SERVICE1_ASYNC, SERVICE1_SYNC, SERVICE1_ASYNC))) + .containsExactly(SERVICE1_ASYNC, SERVICE1_SYNC); + } + + @Test + void selectUnwarmed_ignoresNullNames() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + + assertThat(registry.selectUnwarmed(Arrays.asList(SERVICE1_SYNC, null, SERVICE1_ASYNC))) + .containsExactly(SERVICE1_SYNC, SERVICE1_ASYNC); + } + + @Test + void selectUnwarmed_emptyInput_returnsEmpty() { + WarmedClientRegistry registry = new WarmedClientRegistry(); + + assertThat(registry.selectUnwarmed(Collections.emptyList())).isEmpty(); + } + + @Test + void separateInstances_doNotShareState() { + WarmedClientRegistry first = new WarmedClientRegistry(); + first.markWarmed(Collections.singletonList(SERVICE1_SYNC)); + + WarmedClientRegistry second = new WarmedClientRegistry(); + + assertThat(second.selectUnwarmed(Collections.singletonList(SERVICE1_SYNC))) + .containsExactly(SERVICE1_SYNC); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistryTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistryTest.java new file mode 100644 index 000000000000..d6eef0af335b --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/warmup/WarmedHttpClientTypeRegistryTest.java @@ -0,0 +1,64 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientType; + +/** + * Unit tests for {@link WarmedHttpClientTypeRegistry}. + */ +class WarmedHttpClientTypeRegistryTest { + + @Test + void isWarmed_freshRegistry_returnsFalseForAllTypes() { + WarmedHttpClientTypeRegistry registry = new WarmedHttpClientTypeRegistry(); + + assertThat(registry.isWarmed(ClientType.SYNC)).isFalse(); + assertThat(registry.isWarmed(ClientType.ASYNC)).isFalse(); + } + + @Test + void isWarmed_afterMarkingSync_asyncStaysUnwarmed() { + WarmedHttpClientTypeRegistry registry = new WarmedHttpClientTypeRegistry(); + registry.markWarmed(ClientType.SYNC); + + assertThat(registry.isWarmed(ClientType.SYNC)).isTrue(); + assertThat(registry.isWarmed(ClientType.ASYNC)).isFalse(); + } + + @Test + void isWarmed_afterMarkingBoth_returnsTrueForEach() { + WarmedHttpClientTypeRegistry registry = new WarmedHttpClientTypeRegistry(); + registry.markWarmed(ClientType.SYNC); + registry.markWarmed(ClientType.ASYNC); + + assertThat(registry.isWarmed(ClientType.SYNC)).isTrue(); + assertThat(registry.isWarmed(ClientType.ASYNC)).isTrue(); + } + + @Test + void unknownType_isNeverWarmedAndMarkingIsNoOp() { + WarmedHttpClientTypeRegistry registry = new WarmedHttpClientTypeRegistry(); + registry.markWarmed(ClientType.UNKNOWN); + + assertThat(registry.isWarmed(ClientType.UNKNOWN)).isFalse(); + assertThat(registry.isWarmed(ClientType.SYNC)).isFalse(); + assertThat(registry.isWarmed(ClientType.ASYNC)).isFalse(); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredAsyncClient.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredAsyncClient.java new file mode 100644 index 000000000000..f6164664af43 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredAsyncClient.java @@ -0,0 +1,24 @@ +/* + * 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.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client whose fully qualified name matches {@link RegisteredWarmUpProvider#asyncClientClassName()}. + */ +public interface RegisteredAsyncClient extends SdkClient { +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredSyncClient.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredSyncClient.java new file mode 100644 index 000000000000..81a3e51ea583 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredSyncClient.java @@ -0,0 +1,25 @@ +/* + * 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.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client whose fully qualified name matches {@link RegisteredWarmUpProvider#syncClientClassName()}, so + * {@code SdkWarmUp.warmUp(RegisteredSyncClient.class)} matches that provider's sync client type. + */ +public interface RegisteredSyncClient extends SdkClient { +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredWarmUpProvider.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredWarmUpProvider.java new file mode 100644 index 000000000000..2308c509278a --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/RegisteredWarmUpProvider.java @@ -0,0 +1,58 @@ +/* + * 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.warmup; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import software.amazon.awssdk.core.ClientType; + +/** + * Test-only {@link SdkWarmUpProvider} registered in test-scoped {@code META-INF/services} so a real {@link + * java.util.ServiceLoader} discovers and instantiates it by name. Both static fields are static because the loader + * builds its own instance. Must be public with a no-arg constructor for ServiceLoader. + * + *

    {@code INVOCATIONS} counts full {@link #warmUp()} calls; {@code WARMED_CLIENTS} records the client types passed to + * {@link #warmUpClient(ClientType)}, so a test can tell the targeted path from the full one. + */ +public final class RegisteredWarmUpProvider implements SdkWarmUpProvider { + + public static final AtomicInteger INVOCATIONS = new AtomicInteger(); + + public static final Set WARMED_CLIENTS = + Collections.synchronizedSet(EnumSet.noneOf(ClientType.class)); + + @Override + public void warmUp() { + INVOCATIONS.incrementAndGet(); + } + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.core.warmup.RegisteredSyncClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.core.warmup.RegisteredAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + WARMED_CLIENTS.add(clientType); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpProviderTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpProviderTest.java new file mode 100644 index 000000000000..49fd736b9c8b --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpProviderTest.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.core.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.util.ArrayList; +import java.util.List; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Tests the default {@link SdkWarmUpProvider#warmUp()} method, which warms the sync and async clients independently so + * a failure warming one does not stop the other. + */ +class SdkWarmUpProviderTest { + + @Test + void warmUp_warmsSyncThenAsync() { + RecordingProvider provider = new RecordingProvider(); + + provider.warmUp(); + + assertThat(provider.warmedTypes).containsExactly(ClientType.SYNC, ClientType.ASYNC); + } + + @Test + void warmUp_whenSyncFails_stillWarmsAsyncAndDoesNotThrow() { + RecordingProvider provider = new RecordingProvider() { + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + throw new RuntimeException("sync boom"); + } + super.warmUpClient(clientType); + } + }; + + assertThatCode(provider::warmUp).doesNotThrowAnyException(); + assertThat(provider.warmedTypes).containsExactly(ClientType.ASYNC); + } + + @Test + void warmUp_whenSyncFailsToLink_stillWarmsAsync() { + RecordingProvider provider = new RecordingProvider() { + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + throw new NoClassDefFoundError("missing signer"); + } + super.warmUpClient(clientType); + } + }; + + assertThatCode(provider::warmUp).doesNotThrowAnyException(); + assertThat(provider.warmedTypes).containsExactly(ClientType.ASYNC); + } + + @Test + void warmUp_whenClientFails_logsAtWarn() { + RecordingProvider provider = new RecordingProvider() { + @Override + public void warmUpClient(ClientType clientType) { + throw new RuntimeException("boom"); + } + }; + + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + provider.warmUp(); + + assertThat(logCaptor.loggedEvents()) + .anyMatch(event -> event.getLevel() == Level.WARN + && event.getMessage().getFormattedMessage().contains("Warm-up failed for")); + } + } + + private static class RecordingProvider implements SdkWarmUpProvider { + private final List warmedTypes = new ArrayList<>(); + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.services.example.ExampleClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.services.example.ExampleAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + warmedTypes.add(clientType); + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpTest.java new file mode 100644 index 000000000000..069272056d23 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/SdkWarmUpTest.java @@ -0,0 +1,138 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Tests the static {@link SdkWarmUp#warmUp()} entry point end to end through {@link java.util.ServiceLoader}, + * using a test-scoped {@code META-INF/services} registration of {@link RegisteredWarmUpProvider}. {@code warmUp()} + * runs at most once per JVM, so many concurrent calls must invoke the provider exactly once in total. + */ +class SdkWarmUpTest { + + private String savedRegionProperty; + + @BeforeEach + void setup() { + // Dummy region so warmUp()'s HTTP warm-up resolves a non-existent STS host and fails DNS immediately, keeping the test offline. + savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "warmup-unit-test"); + RegisteredWarmUpProvider.INVOCATIONS.set(0); + RegisteredWarmUpProvider.WARMED_CLIENTS.clear(); + } + + @AfterEach + void teardown() { + if (savedRegionProperty != null) { + System.setProperty("aws.region", savedRegionProperty); + } else { + System.clearProperty("aws.region"); + } + } + + @Test + void warmUp_concurrentCalls_invokeRegisteredProviderExactlyOnce() throws InterruptedException { + int threadCount = 16; + CountDownLatch start = new CountDownLatch(1); + CountDownLatch done = new CountDownLatch(threadCount); + List threads = new ArrayList<>(); + + for (int i = 0; i < threadCount; i++) { + Thread thread = new Thread(() -> { + try { + start.await(); + SdkWarmUp.warmUp(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } finally { + done.countDown(); + } + }); + threads.add(thread); + thread.start(); + } + + start.countDown(); + done.await(); + for (Thread thread : threads) { + thread.join(); + } + + assertThat(RegisteredWarmUpProvider.INVOCATIONS.get()).isEqualTo(1); + } + + @Test + void warmUp_withMatchingSyncClient_warmsSyncClientTypeThroughWarmUpClient() { + SdkWarmUp.warmUp(RegisteredSyncClient.class); + + // Targeted warm-up runs via warmUpClient() only; the full warmUp() path (counted by INVOCATIONS) must not run. + assertThat(RegisteredWarmUpProvider.INVOCATIONS.get()).isEqualTo(0); + assertThat(RegisteredWarmUpProvider.WARMED_CLIENTS).containsExactly(ClientType.SYNC); + } + + @Test + void warmUp_withMatchingAsyncClient_warmsAsyncClientTypeThroughWarmUpClient() { + SdkWarmUp.warmUp(RegisteredAsyncClient.class); + + assertThat(RegisteredWarmUpProvider.INVOCATIONS.get()).isEqualTo(0); + assertThat(RegisteredWarmUpProvider.WARMED_CLIENTS).containsExactly(ClientType.ASYNC); + } + + @Test + void warmUp_withUnmatchedClient_doesNotThrow() { + assertThatCode(() -> SdkWarmUp.warmUp(UnmatchedClient.class)).doesNotThrowAnyException(); + } + + @Test + void warmUp_withUnmatchedClient_warnsOnEveryCallAndIsRetried() { + // An unmatched client is not recorded as warmed, so every call warns and retries. + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + SdkWarmUp.warmUp(RetriedUnmatchedClient.class); + SdkWarmUp.warmUp(RetriedUnmatchedClient.class); + + long unmatchedWarns = logCaptor.loggedEvents().stream() + .filter(event -> event.getLevel() == Level.WARN + && event.getMessage().getFormattedMessage() + .contains(RetriedUnmatchedClient.class.getName())) + .count(); + assertThat(unmatchedWarns).isEqualTo(2); + } + } + + @Test + void warmUp_withEmptyArray_isNoOp() { + assertThatCode(() -> SdkWarmUp.warmUp(new Class[0])).doesNotThrowAnyException(); + } + + interface UnmatchedClient extends SdkClient { + } + + interface RetriedUnmatchedClient extends SdkClient { + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClientTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClientTest.java new file mode 100644 index 000000000000..a4a1c62057c4 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseAsyncHttpClientTest.java @@ -0,0 +1,143 @@ +/* + * 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.warmup.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.http.async.SimpleSubscriber; + +class CannedResponseAsyncHttpClientTest { + + private static final byte[] PAYLOAD = "{\"StringMember\":\"warmup\"}".getBytes(StandardCharsets.UTF_8); + + @Test + void execute_whenNoStatusGiven_signalsDefault200() { + CannedResponseAsyncHttpClient client = CannedResponseAsyncHttpClient.builder().responseBody(PAYLOAD).build(); + RecordingResponseHandler handler = new RecordingResponseHandler(); + + client.execute(requestWith(handler)).join(); + + assertThat(handler.headers.statusCode()).isEqualTo(200); + } + + @Test + void execute_whenStatusGiven_signalsConfiguredStatus() { + CannedResponseAsyncHttpClient client = + CannedResponseAsyncHttpClient.builder().responseBody(PAYLOAD).statusCode(500).build(); + RecordingResponseHandler handler = new RecordingResponseHandler(); + + client.execute(requestWith(handler)).join(); + + assertThat(handler.headers.statusCode()).isEqualTo(500); + } + + @Test + void execute_whenInvoked_streamsConfiguredBody() { + CannedResponseAsyncHttpClient client = CannedResponseAsyncHttpClient.builder().responseBody(PAYLOAD).build(); + RecordingResponseHandler handler = new RecordingResponseHandler(); + + client.execute(requestWith(handler)).join(); + + assertThat(handler.drainBody()).isEqualTo(PAYLOAD); + } + + @Test + void execute_whenNoBodyGiven_signalsDefault200AndEmptyBody() { + CannedResponseAsyncHttpClient client = CannedResponseAsyncHttpClient.builder().build(); + RecordingResponseHandler handler = new RecordingResponseHandler(); + + client.execute(requestWith(handler)).join(); + + assertThat(handler.headers.statusCode()).isEqualTo(200); + assertThat(handler.drainBody()).isEmpty(); + } + + @Test + void execute_whenInvoked_returnsCompletedFuture() { + CannedResponseAsyncHttpClient client = CannedResponseAsyncHttpClient.builder().responseBody(PAYLOAD).build(); + + CompletableFuture future = client.execute(requestWith(new RecordingResponseHandler())); + + assertThat(future).isCompleted(); + } + + @Test + void close_isSafeNoOp() { + CannedResponseAsyncHttpClient client = CannedResponseAsyncHttpClient.builder().build(); + + assertThatCode(client::close).doesNotThrowAnyException(); + } + + private static AsyncExecuteRequest requestWith(SdkAsyncHttpResponseHandler handler) { + return AsyncExecuteRequest.builder() + .responseHandler(handler) + .build(); + } + + private static final class RecordingResponseHandler implements SdkAsyncHttpResponseHandler { + + private SdkHttpResponse headers; + private Publisher stream; + + @Override + public void onHeaders(SdkHttpResponse headers) { + this.headers = headers; + } + + @Override + public void onStream(Publisher stream) { + this.stream = stream; + } + + @Override + public void onError(Throwable error) { + } + + private byte[] drainBody() { + ByteArrayOutputStream collected = new ByteArrayOutputStream(); + CompletableFuture done = new CompletableFuture<>(); + stream.subscribe(new SimpleSubscriber(byteBuffer -> { + byte[] chunk = new byte[byteBuffer.remaining()]; + byteBuffer.get(chunk); + collected.write(chunk, 0, chunk.length); + }) { + @Override + public void onComplete() { + super.onComplete(); + done.complete(null); + } + + @Override + public void onError(Throwable t) { + super.onError(t); + done.completeExceptionally(t); + } + }); + done.join(); + return collected.toByteArray(); + } + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClientTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClientTest.java new file mode 100644 index 000000000000..cfc7db2bad56 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/warmup/http/CannedResponseHttpClientTest.java @@ -0,0 +1,101 @@ +/* + * 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.warmup.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.ExecutableHttpRequest; +import software.amazon.awssdk.http.HttpExecuteRequest; +import software.amazon.awssdk.http.HttpExecuteResponse; +import software.amazon.awssdk.utils.IoUtils; +import utils.ValidSdkObjects; + +class CannedResponseHttpClientTest { + + private static final byte[] PAYLOAD = "{\"StringMember\":\"warmup\"}".getBytes(StandardCharsets.UTF_8); + + private static HttpExecuteRequest request() { + return HttpExecuteRequest.builder() + .request(ValidSdkObjects.sdkHttpFullRequest().build()) + .build(); + } + + private static byte[] readBody(HttpExecuteResponse response) throws IOException { + return IoUtils.toByteArray(response.responseBody().orElseThrow(() -> new AssertionError("expected a body"))); + } + + @Test + void call_whenNoStatusGiven_returnsDefault200() throws IOException { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().responseBody(PAYLOAD).build(); + + HttpExecuteResponse response = client.prepareRequest(request()).call(); + + assertThat(response.httpResponse().statusCode()).isEqualTo(200); + } + + @Test + void call_whenStatusGiven_returnsConfiguredStatus() throws IOException { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().responseBody(PAYLOAD).statusCode(404).build(); + + HttpExecuteResponse response = client.prepareRequest(request()).call(); + + assertThat(response.httpResponse().statusCode()).isEqualTo(404); + } + + @Test + void call_whenInvoked_returnsFullyDrainableBody() throws IOException { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().responseBody(PAYLOAD).build(); + + byte[] body = readBody(client.prepareRequest(request()).call()); + + assertThat(body).isEqualTo(PAYLOAD); + } + + @Test + void call_whenInvokedRepeatedly_eachCallGetsFreshReadableStream() throws IOException { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().responseBody(PAYLOAD).build(); + + byte[] first = readBody(client.prepareRequest(request()).call()); + byte[] second = readBody(client.prepareRequest(request()).call()); + + assertThat(first).isEqualTo(PAYLOAD); + assertThat(second).isEqualTo(PAYLOAD); + } + + @Test + void closeAndAbort_areSafeNoOps() { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().responseBody(PAYLOAD).build(); + ExecutableHttpRequest executableRequest = client.prepareRequest(request()); + + assertThatCode(executableRequest::abort).doesNotThrowAnyException(); + assertThatCode(client::close).doesNotThrowAnyException(); + } + + @Test + void call_whenNoBodyGiven_returnsDefault200AndEmptyBody() throws IOException { + CannedResponseHttpClient client = CannedResponseHttpClient.builder().build(); + + HttpExecuteResponse response = client.prepareRequest(request()).call(); + + assertThat(response.httpResponse().statusCode()).isEqualTo(200); + assertThat(readBody(response)).isEmpty(); + } + +} diff --git a/core/sdk-core/src/test/java/utils/HttpTestUtils.java b/core/sdk-core/src/test/java/utils/HttpTestUtils.java index 127584c67e5a..e809cb15d575 100644 --- a/core/sdk-core/src/test/java/utils/HttpTestUtils.java +++ b/core/sdk-core/src/test/java/utils/HttpTestUtils.java @@ -31,25 +31,19 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient; import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; -import software.amazon.awssdk.core.internal.http.loader.DefaultSdkAsyncHttpClientBuilder; -import software.amazon.awssdk.core.internal.http.loader.DefaultSdkHttpClientBuilder; import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; import software.amazon.awssdk.core.signer.NoOpSigner; import software.amazon.awssdk.http.SdkHttpClient; -import software.amazon.awssdk.http.SdkHttpConfigurationOption; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.retries.api.RetryStrategy; -import software.amazon.awssdk.utils.AttributeMap; public class HttpTestUtils { public static SdkHttpClient testSdkHttpClient() { - return new DefaultSdkHttpClientBuilder().buildWithDefaults( - AttributeMap.empty().merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); + return StubSdkHttpClient.create(); } public static SdkAsyncHttpClient testSdkAsyncHttpClient() { - return new DefaultSdkAsyncHttpClientBuilder().buildWithDefaults( - AttributeMap.empty().merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); + return StubSdkAsyncHttpClient.create(); } public static AmazonSyncHttpClient testAmazonHttpClient() { diff --git a/core/sdk-core/src/test/java/utils/StubSdkAsyncHttpClient.java b/core/sdk-core/src/test/java/utils/StubSdkAsyncHttpClient.java new file mode 100644 index 000000000000..09c8502b805e --- /dev/null +++ b/core/sdk-core/src/test/java/utils/StubSdkAsyncHttpClient.java @@ -0,0 +1,83 @@ +/* + * 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 utils; + +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.utils.async.SimplePublisher; + +/** + * A minimal in-memory {@link SdkAsyncHttpClient} for sdk-core tests that do not need a real transport: it immediately delivers + * a response with a configurable status code and an empty body to the response handler, without touching the network. Tests + * that induce a timeout via a slow response handler or interceptor only need the transport to respond promptly with the right + * status (200 vs 5xx) so the success or error path is selected. + */ +public final class StubSdkAsyncHttpClient implements SdkAsyncHttpClient { + + /** + * A small deliberate transport latency. The real async HTTP client talking to a WireMock server (which this stub + * replaced) always took some milliseconds to deliver a response. Tests that assert an API call timeout fires while a + * response handler sleeps for exactly the timeout duration depend on that latency to push the total elapsed time past + * the timeout, so the stub reproduces it rather than responding instantly. + */ + private static final long RESPONSE_LATENCY_MILLIS = 50; + + private final int statusCode; + + private StubSdkAsyncHttpClient(int statusCode) { + this.statusCode = statusCode; + } + + public static StubSdkAsyncHttpClient create() { + return new StubSdkAsyncHttpClient(200); + } + + public static StubSdkAsyncHttpClient create(int statusCode) { + return new StubSdkAsyncHttpClient(statusCode); + } + + @Override + public CompletableFuture execute(AsyncExecuteRequest request) { + SdkAsyncHttpResponseHandler responseHandler = request.responseHandler(); + simulateTransportLatency(); + responseHandler.onHeaders(SdkHttpResponse.builder().statusCode(statusCode).build()); + SimplePublisher bodyPublisher = new SimplePublisher<>(); + responseHandler.onStream(bodyPublisher); + bodyPublisher.complete(); + return CompletableFuture.completedFuture(null); + } + + @Override + public void close() { + } + + @Override + public String clientName() { + return "StubAsync"; + } + + private static void simulateTransportLatency() { + try { + Thread.sleep(RESPONSE_LATENCY_MILLIS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/core/sdk-core/src/test/java/utils/StubSdkHttpClient.java b/core/sdk-core/src/test/java/utils/StubSdkHttpClient.java new file mode 100644 index 000000000000..249731760f5f --- /dev/null +++ b/core/sdk-core/src/test/java/utils/StubSdkHttpClient.java @@ -0,0 +1,90 @@ +/* + * 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 utils; + +import java.io.ByteArrayInputStream; +import software.amazon.awssdk.http.AbortableInputStream; +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.SdkHttpResponse; + +/** + * A minimal in-memory {@link SdkHttpClient} for sdk-core tests that do not need a real transport: it immediately returns a + * response with a configurable status code and an empty body, without touching the network. Tests that induce a timeout via a + * slow response handler or interceptor only need the transport to return promptly with the right status (200 vs 5xx) so the + * success or error path is selected. + */ +public final class StubSdkHttpClient implements SdkHttpClient { + + /** + * A small deliberate transport latency. The real HTTP client talking to a WireMock server (which this stub replaced) + * always took some milliseconds to return a response. Tests that assert an API call timeout fires while a response + * handler sleeps for exactly the timeout duration depend on that latency to push the total elapsed time past the + * timeout, so the stub reproduces it rather than returning instantly. + */ + private static final long RESPONSE_LATENCY_MILLIS = 50; + + private final int statusCode; + + private StubSdkHttpClient(int statusCode) { + this.statusCode = statusCode; + } + + public static StubSdkHttpClient create() { + return new StubSdkHttpClient(200); + } + + public static StubSdkHttpClient create(int statusCode) { + return new StubSdkHttpClient(statusCode); + } + + @Override + public ExecutableHttpRequest prepareRequest(HttpExecuteRequest request) { + return new ExecutableHttpRequest() { + @Override + public HttpExecuteResponse call() { + simulateTransportLatency(); + return HttpExecuteResponse.builder() + .response(SdkHttpResponse.builder().statusCode(statusCode).build()) + .responseBody(AbortableInputStream.create(new ByteArrayInputStream(new byte[0]))) + .build(); + } + + @Override + public void abort() { + } + }; + } + + @Override + public void close() { + } + + @Override + public String clientName() { + return "Stub"; + } + + private static void simulateTransportLatency() { + try { + Thread.sleep(RESPONSE_LATENCY_MILLIS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/core/sdk-core/src/test/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider b/core/sdk-core/src/test/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider new file mode 100644 index 000000000000..fbd6137d5063 --- /dev/null +++ b/core/sdk-core/src/test/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider @@ -0,0 +1,15 @@ +# +# 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. +# +software.amazon.awssdk.core.warmup.RegisteredWarmUpProvider diff --git a/docs/design/core/presignedURL-Get/DecisionLog.md b/docs/design/core/presignedURL-Get/DecisionLog.md index afd5b033a00a..b37a7324ae1c 100644 --- a/docs/design/core/presignedURL-Get/DecisionLog.md +++ b/docs/design/core/presignedURL-Get/DecisionLog.md @@ -69,3 +69,8 @@ Initially considered separate discovery request (bytes=0-0) followed by download 1. **API Names**: Finalize `downloadWithPresignedUrl` and `downloadFileWithPresignedUrl` for Transfer Manager methods during Surface API Review later. 2. **Pause/Resume Support**: Decided not to support pause/resume capability for presigned URL downloads, maintaining consistency with AWS SDK for Java v1 which also lacks this feature for presigned URLs. + +## API Surface Area Review Decision: 05/28/2026 + +### Decision Addressed +Changed the return type of downloadFileWithPresignedUrl from FileDownload to a new PresignedFileDownload type. FileDownload exposes pause() which is not supported for presigned URL downloads — introducing PresignedFileDownload makes this a compile-time guarantee rather than a runtime UnsupportedOperationException. diff --git a/docs/design/core/presignedURL-Get/Design.md b/docs/design/core/presignedURL-Get/Design.md index d2cd1f691229..127e7653f396 100644 --- a/docs/design/core/presignedURL-Get/Design.md +++ b/docs/design/core/presignedURL-Get/Design.md @@ -39,7 +39,7 @@ AsyncPresignedUrlExtension presignExtension = s3Client.presignedUrlExtension(); // Create presigned URL request PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() .presignedUrl(presignedUrl) - .range("range=0-1024") + .range("bytes=0-1024") .build(); // Async usage @@ -72,7 +72,7 @@ CompletableFuture> response = multipartClient.presignedUrlExtension().getObject(request, AsyncResponseTransformer.toBytes()); ``` -The multipart implementation uses Range headers (e.g., `bytes=0-8388607`) instead of partNumber parameters to preserve presigned URL signatures. The first request downloads the initial part while discovering total object size from the Content-Range header. +The multipart implementation uses Range headers (e.g., `bytes=0-8388607`) instead of partNumber parameters to preserve presigned URL signatures. The first request downloads the initial part while discovering total object size from the Content-Range header. Subsequent parts include an `If-Match` header with the ETag captured from the first response to detect object mutation mid-download. Each part response is validated to ensure Content-Range alignment and Content-Length match expected values. ### AsyncPresignedUrlExtension Interface @@ -111,10 +111,11 @@ public final class PresignedUrlDownloadRequest private final URL presignedUrl; private final String range; + private final String ifMatch; - // Standard getters: presignedUrl(), range() + // Standard getters: presignedUrl(), range(), ifMatch() // Standard builder methods: builder(), toBuilder() - // Standard Builder class with presignedUrl(), range() setter methods + // Standard Builder class with presignedUrl(), range(), ifMatch() setter methods } ``` @@ -126,7 +127,7 @@ The S3TransferManager extends support for presigned URL downloads, providing hig ```java // File-based presigned URL download -FileDownload download = transferManager.downloadFileWithPresignedUrl( +PresignedFileDownload download = transferManager.downloadFileWithPresignedUrl( PresignedDownloadFileRequest.builder() .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() .presignedUrl(presignedUrl) diff --git a/http-client-spi/pom.xml b/http-client-spi/pom.xml index cfe36998bfbb..e777ae5120e6 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT http-client-spi AWS Java SDK :: HTTP Client Interface @@ -75,11 +75,6 @@ assertj-core test - - org.reactivestreams - reactive-streams-tck - test - nl.jqno.equalsverifier equalsverifier diff --git a/http-client-spi/src/main/java/software/amazon/awssdk/http/ContentStreamProvider.java b/http-client-spi/src/main/java/software/amazon/awssdk/http/ContentStreamProvider.java index 4ae96838d8b4..714a960a9262 100644 --- a/http-client-spi/src/main/java/software/amazon/awssdk/http/ContentStreamProvider.java +++ b/http-client-spi/src/main/java/software/amazon/awssdk/http/ContentStreamProvider.java @@ -24,6 +24,8 @@ import java.util.Arrays; import java.util.Map; import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkAdvancedApi; +import software.amazon.awssdk.annotations.SdkAdvancedApi.Usage; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.utils.IoUtils; @@ -41,6 +43,13 @@ */ @SdkPublicApi @FunctionalInterface +@SdkAdvancedApi( + cautionWhen = Usage.IMPLEMENTED, + guidance = "newStream() must return a stream positioned at the start of the content on every call, closing any " + + "previous stream it opened. A stale or unreset stream corrupts the request body and breaks retries, " + + "which re-read the content.", + saferAlternative = "Prefer the ContentStreamProvider.fromInputStream/fromByteArray/fromString factories, which " + + "handle reset correctly.") public interface ContentStreamProvider { /** * Create {@link ContentStreamProvider} from a byte array. This will copy the contents of the byte array. diff --git a/http-client-spi/src/main/java/software/amazon/awssdk/http/ProxyAuthScheme.java b/http-client-spi/src/main/java/software/amazon/awssdk/http/ProxyAuthScheme.java new file mode 100644 index 000000000000..d4857013b2c4 --- /dev/null +++ b/http-client-spi/src/main/java/software/amazon/awssdk/http/ProxyAuthScheme.java @@ -0,0 +1,52 @@ +/* + * 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.http; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * Supported auth schemes for authentication with a proxy. + */ +@SdkPublicApi +public enum ProxyAuthScheme { + /** + * Basic authentication, as defined by RFC 7617. Requires a + * username and password. + */ + BASIC("Basic"), + + /** + * Kerberos authentication, using SPNEGO as defined by + * RFC 4559. + *

    + * Credentials are read from the environment Kerberos ticket cache. The client never prompts for a password and never reads a + * keytab, so the environment must already hold a valid ticket-granting ticket, typically obtained by running + * {@code kinit} and verifiable with {@code klist}. The cache location follows the usual Kerberos conventions, including + * the {@code KRB5CCNAME} environment variable. Any username and password configured on the proxy are ignored. + */ + NEGOTIATE("Negotiate"), + ; + + private final String value; + + ProxyAuthScheme(String value) { + this.value = value; + } + + public String value() { + return value; + } +} diff --git a/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java b/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java index e9efa8b1814b..69487fb28129 100644 --- a/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java +++ b/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpConfigurationOption.java @@ -41,6 +41,16 @@ public final class SdkHttpConfigurationOption extends AttributeMap.Key { public static final SdkHttpConfigurationOption WRITE_TIMEOUT = new SdkHttpConfigurationOption<>("WriteTimeout", Duration.class); + /** + * SDK-internal. A fallback read/write timeout that is honored only by HTTP client implementations which do not + * enforce a read/write timeout of their own (currently the AWS CRT-based clients); implementations that already + * apply one, such as the Apache and Netty clients, ignore it. Unlike {@link #READ_TIMEOUT}/{@link #WRITE_TIMEOUT}, + * which carry a caller-configured socket timeout, this value is resolved by the SDK and is not intended to be set by + * end users. {@link Duration#ZERO} means no timeout is applied (the service is fully exempt, or the rollout gate is off). + */ + public static final SdkHttpConfigurationOption SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT = + new SdkHttpConfigurationOption<>("SdkInternalFallbackReadWriteTimeout", Duration.class); + /** * Timeout for establishing a connection to a remote service. */ diff --git a/http-clients/apache-client/pom.xml b/http-clients/apache-client/pom.xml index 482d7a3330c7..54fe8f07f157 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apache-client diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java index 6013c07bdaa8..04c1076176c8 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheHttpClient.java @@ -101,8 +101,13 @@ *

    See software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient for an alternative implementation.

    * *

    This can be created via {@link #builder()}

    + * + * @deprecated Apache 4.x is in maintenance mode. Users are encouraged to switch to the + * Apache 5 HTTP Client + * which is feature compatible with this client. */ @SdkPublicApi +@Deprecated public final class ApacheHttpClient implements SdkHttpClient { public static final String CLIENT_NAME = "Apache"; @@ -345,6 +350,9 @@ public String clientName() { * .socketTimeout(Duration.ofSeconds(10)) * .build(); * + * @deprecated Apache 4.x is in maintenance mode. Users are encouraged to switch to the + * Apache 5 HTTP Client + * which is feature compatible with this client. */ public interface Builder extends SdkHttpClient.Builder { diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheSdkHttpService.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheSdkHttpService.java index 8ada6d4fc835..f9605120f244 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheSdkHttpService.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ApacheSdkHttpService.java @@ -21,8 +21,13 @@ /** * Service binding for the Apache implementation. + * + * @deprecated Apache 4.x is in maintenance mode. Users are encouraged to switch to the + * Apache 5 HTTP Client + * which is feature compatible with this client. */ @SdkPublicApi +@Deprecated public class ApacheSdkHttpService implements SdkHttpService { @Override public SdkHttpClient.Builder createHttpClientBuilder() { diff --git a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java index c5e24a9e7e11..ab83d254d3fe 100644 --- a/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java +++ b/http-clients/apache-client/src/main/java/software/amazon/awssdk/http/apache/ProxyConfiguration.java @@ -32,8 +32,13 @@ /** * Configuration that defines how to communicate via an HTTP or HTTPS proxy. + * + * @deprecated Apache 4.x is in maintenance mode. Users are encouraged to switch to the + * Apache 5 HTTP Client + * which is feature compatible with this client. */ @SdkPublicApi +@Deprecated public final class ProxyConfiguration implements ToCopyableBuilder { private final URI endpoint; private final String username; @@ -259,11 +264,18 @@ public interface Builder extends CopyableBuilder { /** * Configure the hosts that the client is allowed to access without going through the proxy. + *

    Entries supplied here are treated as exact host names (e.g. {@code example.com}) or CIDR ranges for IP addresses + * (e.g. {@code 10.0.0.0/8}). Wildcard patterns such as {@code *.example.com} or a bare {@code *} are not supported for + * entries supplied here; to use wildcards, configure them through the {@code http.nonProxyHosts} system property or the + * {@code NO_PROXY} environment variable instead. */ Builder nonProxyHosts(Set nonProxyHosts); /** * Add a host that the client is allowed to access without going through the proxy. + *

    The host is treated as an exact host name or CIDR range; wildcard patterns are not supported for entries supplied + * here. See {@link #nonProxyHosts(Set)} for details on wildcard support through the system property or environment + * variable. * * @see ProxyConfiguration#nonProxyHosts() */ @@ -281,6 +293,11 @@ public interface Builder extends CopyableBuilder { * are not provided during building the {@link ProxyConfiguration} object. To disable this behavior, set this value to * "false".It is important to note that when this property is set to "true," all proxy settings will exclusively originate * from system properties, and no partial settings will be obtained from EnvironmentVariableValues. + *

    Pipe-separated host names in the {@code http.nonProxyHosts} system property indicate multiple hosts to exclude + * from proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com|b.com"} and + * {@code "a.com | b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). */ Builder useSystemPropertyValues(Boolean useSystemPropertyValues); @@ -293,7 +310,10 @@ public interface Builder extends CopyableBuilder { * proxy settings will exclusively originate from environment variableValues, and no partial settings will be obtained * from SystemPropertyValues. *

    Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from - * proxy settings. + * proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and + * {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). * * @param useEnvironmentVariableValues The option whether to use environment variable values. * @return This object for method chaining. diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheConnectionPoolMaxConnectionsTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheConnectionPoolMaxConnectionsTest.java new file mode 100644 index 000000000000..a0011ce57686 --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheConnectionPoolMaxConnectionsTest.java @@ -0,0 +1,37 @@ +/* + * 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.http.apache; + +import java.time.Duration; +import org.apache.http.conn.ConnectionPoolTimeoutException; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientConnectionPoolTestSuite; + +public class ApacheConnectionPoolMaxConnectionsTest extends SdkHttpClientConnectionPoolTestSuite { + + @Override + protected SdkHttpClient createSdkHttpClient(int maxConnections, Duration connectionTimeout) { + return ApacheHttpClient.builder() + .connectionTimeout(connectionTimeout) + .maxConnections(maxConnections) + .build(); + } + + @Override + protected Class expectedPoolTimeoutCause() { + return ConnectionPoolTimeoutException.class; + } +} diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSdkPipelineBehaviorTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSdkPipelineBehaviorTest.java new file mode 100644 index 000000000000..833483813962 --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSdkPipelineBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.apache; + +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSdkPipelineBehaviorTestSuite; + +public class ApacheHttpClientSdkPipelineBehaviorTest extends SdkHttpClientSdkPipelineBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + return ApacheHttpClient.builder().build(); + } +} diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSslHandshakeTimeoutTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSslHandshakeTimeoutTest.java new file mode 100644 index 000000000000..3285c1998785 --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheHttpClientSslHandshakeTimeoutTest.java @@ -0,0 +1,30 @@ +/* + * 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.http.apache; + +import java.time.Duration; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeTimeoutTestSuite; + +public class ApacheHttpClientSslHandshakeTimeoutTest extends SdkHttpClientSslHandshakeTimeoutTestSuite { + + @Override + protected SdkHttpClient createSdkHttpClient(Duration socketTimeout) { + return ApacheHttpClient.builder() + .socketTimeout(socketTimeout) + .build(); + } +} diff --git a/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheSslHandshakeBehaviorTest.java b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheSslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..4e0b979db02f --- /dev/null +++ b/http-clients/apache-client/src/test/java/software/amazon/awssdk/http/apache/ApacheSslHandshakeBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.apache; + +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeBehaviorTestSuite; + +public class ApacheSslHandshakeBehaviorTest extends SdkHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + return ApacheHttpClient.builder().build(); + } +} diff --git a/http-clients/apache5-client/pom.xml b/http-clients/apache5-client/pom.xml index 6f428128ca7c..68efbe615e47 100644 --- a/http-clients/apache5-client/pom.xml +++ b/http-clients/apache5-client/pom.xml @@ -21,7 +21,7 @@ http-clients software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apache5-client diff --git a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/ProxyConfiguration.java b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/ProxyConfiguration.java index 14c655c2557b..61ad3805468d 100644 --- a/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/ProxyConfiguration.java +++ b/http-clients/apache5-client/src/main/java/software/amazon/awssdk/http/apache5/ProxyConfiguration.java @@ -259,11 +259,18 @@ public interface Builder extends CopyableBuilder { /** * Configure the hosts that the client is allowed to access without going through the proxy. + *

    Entries supplied here are treated as exact host names (e.g. {@code example.com}) or CIDR ranges for IP addresses + * (e.g. {@code 10.0.0.0/8}). Wildcard patterns such as {@code *.example.com} or a bare {@code *} are not supported for + * entries supplied here; to use wildcards, configure them through the {@code http.nonProxyHosts} system property or the + * {@code NO_PROXY} environment variable instead. */ Builder nonProxyHosts(Set nonProxyHosts); /** * Add a host that the client is allowed to access without going through the proxy. + *

    The host is treated as an exact host name or CIDR range; wildcard patterns are not supported for entries supplied + * here. See {@link #nonProxyHosts(Set)} for details on wildcard support through the system property or environment + * variable. * * @see ProxyConfiguration#nonProxyHosts() */ @@ -281,6 +288,11 @@ public interface Builder extends CopyableBuilder { * are not provided during building the {@link ProxyConfiguration} object. To disable this behavior, set this value to * "false".It is important to note that when this property is set to "true," all proxy settings will exclusively originate * from system properties, and no partial settings will be obtained from EnvironmentVariableValues. + *

    Pipe-separated host names in the {@code http.nonProxyHosts} system property indicate multiple hosts to exclude + * from proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com|b.com"} and + * {@code "a.com | b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). */ Builder useSystemPropertyValues(Boolean useSystemPropertyValues); @@ -293,7 +305,10 @@ public interface Builder extends CopyableBuilder { * proxy settings will exclusively originate from environment variableValues, and no partial settings will be obtained * from SystemPropertyValues. *

    Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from - * proxy settings. + * proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and + * {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). * * @param useEnvironmentVariableValues The option whether to use environment variable values. * @return This object for method chaining. diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ConnectionPoolMaxConnectionsTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ConnectionPoolMaxConnectionsTest.java new file mode 100644 index 000000000000..c6442201c4af --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5ConnectionPoolMaxConnectionsTest.java @@ -0,0 +1,37 @@ +/* + * 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.http.apache5; + +import java.time.Duration; +import org.apache.hc.core5.http.ConnectionRequestTimeoutException; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientConnectionPoolTestSuite; + +public class Apache5ConnectionPoolMaxConnectionsTest extends SdkHttpClientConnectionPoolTestSuite { + + @Override + protected SdkHttpClient createSdkHttpClient(int maxConnections, Duration connectionTimeout) { + return Apache5HttpClient.builder() + .connectionTimeout(connectionTimeout) + .maxConnections(maxConnections) + .build(); + } + + @Override + protected Class expectedPoolTimeoutCause() { + return ConnectionRequestTimeoutException.class; + } +} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSdkPipelineBehaviorTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSdkPipelineBehaviorTest.java new file mode 100644 index 000000000000..3a9d9c951316 --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSdkPipelineBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.apache5; + +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSdkPipelineBehaviorTestSuite; + +public class Apache5HttpClientSdkPipelineBehaviorTest extends SdkHttpClientSdkPipelineBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + return Apache5HttpClient.builder().build(); + } +} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSslHandshakeTimeoutTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSslHandshakeTimeoutTest.java new file mode 100644 index 000000000000..055e7f850ad5 --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5HttpClientSslHandshakeTimeoutTest.java @@ -0,0 +1,30 @@ +/* + * 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.http.apache5; + +import java.time.Duration; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeTimeoutTestSuite; + +public class Apache5HttpClientSslHandshakeTimeoutTest extends SdkHttpClientSslHandshakeTimeoutTestSuite { + + @Override + protected SdkHttpClient createSdkHttpClient(Duration socketTimeout) { + return Apache5HttpClient.builder() + .socketTimeout(socketTimeout) + .build(); + } +} diff --git a/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5SslHandshakeBehaviorTest.java b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5SslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..cfa80a7491b9 --- /dev/null +++ b/http-clients/apache5-client/src/test/java/software/amazon/awssdk/http/apache5/Apache5SslHandshakeBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.apache5; + +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeBehaviorTestSuite; + +public class Apache5SslHandshakeBehaviorTest extends SdkHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + return Apache5HttpClient.builder().build(); + } +} diff --git a/http-clients/aws-crt-client/pom.xml b/http-clients/aws-crt-client/pom.xml index 7b6b90aaced0..c6afdb6af215 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -112,11 +112,6 @@ assertj-core test - - org.reactivestreams - reactive-streams-tck - test - org.apache.logging.log4j log4j-api @@ -213,6 +208,17 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + + true + + + diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java index 852c2f566293..79a150eabab8 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java @@ -129,6 +129,26 @@ public interface Builder extends SdkAsyncHttpClient.BuilderBy default (when this is not set), the client shares a single, process-wide event-loop group sized to + * {@code Runtime.getRuntime().availableProcessors()}, shared with every other CRT client in the JVM. When this value is + * set, the client instead creates and owns a private event-loop group of the given size; that group is shut down when + * this client is closed and is not shared with any other client. + * + *

    This is an advanced tuning and isolation control, and each client configured with an explicit size consumes that + * many additional IO threads. Oversizing wastes threads and adds context-switching and memory overhead without improving + * throughput; undersizing can leave the client's IO as a bottleneck and underutilize available cores. The best value + * depends on your workload and hardware, so benchmark your own application before changing it from the default. An + * excessively high value relative to the number of available processors is logged as a warning. + * + * @param numEventLoopThreads the number of event-loop threads; must be greater than 1, or {@code null} to use the shared + * default. + * @return The builder for method chaining. + */ + AwsCrtAsyncHttpClient.Builder numEventLoopThreads(Integer numEventLoopThreads); + /** * Sets the http proxy configuration to use for this client. * @param proxyConfiguration The http proxy configuration to use @@ -145,17 +165,21 @@ public interface Builder extends SdkAsyncHttpClient.Builder proxyConfigurationBuilderConsumer); /** - * Configure the health checks for all connections established by this client. + * Configure the health checks for all connections established by this client. This is the CRT client's knob for a + * read/write inactivity timeout: a connection whose throughput stays below + * {@link ConnectionHealthConfiguration#minimumThroughputInBps()} for + * {@link ConnectionHealthConfiguration#minimumThroughputTimeout()} is considered unhealthy and shut down, failing the + * in-flight request with a retryable {@code IOException}. * - *

    - * You can set a throughput threshold for a connection to be considered healthy. - * If a connection falls below this threshold ({@link ConnectionHealthConfiguration#minimumThroughputInBps() - * }) for the configurable amount - * of time ({@link ConnectionHealthConfiguration#minimumThroughputTimeout()}), - * then the connection is considered unhealthy and will be shut down. + *

    To set a read/write inactivity timeout, use {@code minimumThroughputInBps(1L)} with + * {@code minimumThroughputTimeout(yourDuration)}: any byte moved in either direction resets the window, so the connection + * is shut down only after {@code yourDuration} elapses with no bytes transferred. The timeout has whole-second + * granularity and must be at least two seconds. * - *

    - * Disabled by default. + *

    When this client is created and managed by an AWS SDK service client, a default read/write inactivity timeout + * may be applied automatically, resolved per service by the SDK. When this client is built directly and supplied to a + * service client, or used standalone, no automatic default is applied; monitoring is enabled only by an explicit + * configuration set here, which always takes precedence over any SDK-applied default. * * @param healthChecksConfiguration The health checks config to use * @return The builder of the method chaining. @@ -194,6 +218,17 @@ AwsCrtAsyncHttpClient.Builder connectionHealthConfiguration(ConsumerBy default, it's 10 seconds. + * + * @param tlsNegotiationTimeout the timeout duration; must be positive + * @return this builder for method chaining. + */ + AwsCrtAsyncHttpClient.Builder tlsNegotiationTimeout(Duration tlsNegotiationTimeout); + /** * Configure whether to enable {@code tcpKeepAlive} and relevant configuration for all connections established by this * client. @@ -248,6 +283,28 @@ AwsCrtAsyncHttpClient.Builder tcpKeepAliveConfiguration(ConsumerIf not set, the platform + CRT default is used (equivalent to + * {@link TlsVersion#SYSTEM_DEFAULT}). + * + *

    This option is mutually exclusive with {@link #postQuantumTlsEnabled(Boolean) + * postQuantumTlsEnabled(false)}. Attempting to set both will cause client construction + * to fail with an {@link IllegalStateException}. + * + *

    macOS: the default CRT TLS backend on macOS (Apple Secure Transport) does not + * support TLS 1.3. To use {@link TlsVersion#TLS_1_3} on macOS you must set the environment + * variable {@code AWS_CRT_USE_NON_FIPS_TLS_13} to any non-empty value at process startup so + * the CRT selects its s2n-tls backend. See {@link TlsVersion} for details. + * + * @param minTlsVersion the minimum acceptable TLS version; {@code null} clears + * the value and reverts to the platform default + * @return this builder for method chaining + */ + AwsCrtAsyncHttpClient.Builder minTlsVersion(TlsVersion minTlsVersion); } /** @@ -267,6 +324,7 @@ public Builder protocol(Protocol protocol) { @Override public SdkAsyncHttpClient build() { return new AwsCrtAsyncHttpClient(this, getAttributeMap().build() + .merge(AwsCrtHttpClientBase.AWS_CRT_HTTP_DEFAULTS) .merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); } @@ -274,6 +332,7 @@ public SdkAsyncHttpClient build() { public SdkAsyncHttpClient buildWithDefaults(AttributeMap serviceDefaults) { return new AwsCrtAsyncHttpClient(this, getAttributeMap().build() .merge(serviceDefaults) + .merge(AwsCrtHttpClientBase.AWS_CRT_HTTP_DEFAULTS) .merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); } diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClient.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClient.java index b2511f1c28ed..9fe64121b2ca 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClient.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClient.java @@ -56,12 +56,16 @@ public final class AwsCrtHttpClient extends AwsCrtHttpClientBase implements SdkHttpClient { private AwsCrtHttpClient(DefaultBuilder builder, AttributeMap config) { - super(builder, config); - if (this.protocol == Protocol.HTTP2) { + super(builder, validateProtocol(config)); + } + + private static AttributeMap validateProtocol(AttributeMap config) { + if (config.get(SdkHttpConfigurationOption.PROTOCOL) == Protocol.HTTP2) { throw new UnsupportedOperationException( "HTTP/2 is not supported for sync HTTP clients. Either use HTTP/1.1 (the default) or use an async " + "HTTP client (e.g., AwsCrtAsyncHttpClient)."); } + return config; } public static AwsCrtHttpClient.Builder builder() { @@ -181,6 +185,26 @@ public interface Builder extends SdkHttpClient.Builder */ AwsCrtHttpClient.Builder readBufferSizeInBytes(Long readBufferSize); + /** + * Configure the number of event-loop (IO) threads in this client's event-loop group. + * + *

    By default (when this is not set), the client shares a single, process-wide event-loop group sized to + * {@code Runtime.getRuntime().availableProcessors()}, shared with every other CRT client in the JVM. When this value is + * set, the client instead creates and owns a private event-loop group of the given size; that group is shut down when + * this client is closed and is not shared with any other client. + * + *

    This is an advanced tuning and isolation control, and each client configured with an explicit size consumes that + * many additional IO threads. Oversizing wastes threads and adds context-switching and memory overhead without improving + * throughput; undersizing can leave the client's IO as a bottleneck and underutilize available cores. The best value + * depends on your workload and hardware, so benchmark your own application before changing it from the default. An + * excessively high value relative to the number of available processors is logged as a warning. + * + * @param numEventLoopThreads the number of event-loop threads; must be greater than 1, or {@code null} to use the shared + * default. + * @return The builder for method chaining. + */ + AwsCrtHttpClient.Builder numEventLoopThreads(Integer numEventLoopThreads); + /** * Sets the http proxy configuration to use for this client. * @param proxyConfiguration The http proxy configuration to use @@ -197,17 +221,21 @@ public interface Builder extends SdkHttpClient.Builder AwsCrtHttpClient.Builder proxyConfiguration(Consumer proxyConfigurationBuilderConsumer); /** - * Configure the health checks for all connections established by this client. + * Configure the health checks for all connections established by this client. This is the CRT client's knob for a + * read/write inactivity timeout: a connection whose throughput stays below + * {@link ConnectionHealthConfiguration#minimumThroughputInBps()} for + * {@link ConnectionHealthConfiguration#minimumThroughputTimeout()} is considered unhealthy and shut down, failing the + * in-flight request with a retryable {@code IOException}. * - *

    - * You can set a throughput threshold for a connection to be considered healthy. - * If a connection falls below this threshold ({@link ConnectionHealthConfiguration#minimumThroughputInBps() - * }) for the configurable amount - * of time ({@link ConnectionHealthConfiguration#minimumThroughputTimeout()}), - * then the connection is considered unhealthy and will be shut down. + *

    To set a read/write inactivity timeout, use {@code minimumThroughputInBps(1L)} with + * {@code minimumThroughputTimeout(yourDuration)}: any byte moved in either direction resets the window, so the connection + * is shut down only after {@code yourDuration} elapses with no bytes transferred. The timeout has whole-second + * granularity and must be at least two seconds. * - *

    - * Disabled by default. + *

    When this client is created and managed by an AWS SDK service client, a default read/write inactivity timeout + * may be applied automatically, resolved per service by the SDK. When this client is built directly and supplied to a + * service client, or used standalone, no automatic default is applied; monitoring is enabled only by an explicit + * configuration set here, which always takes precedence over any SDK-applied default. * * @param healthChecksConfiguration The health checks config to use * @return The builder of the method chaining. @@ -246,6 +274,17 @@ AwsCrtHttpClient.Builder connectionHealthConfiguration(ConsumerBy default, it's 10 seconds. + * + * @param tlsNegotiationTimeout the timeout duration; must be positive + * @return this builder for method chaining. + */ + AwsCrtHttpClient.Builder tlsNegotiationTimeout(Duration tlsNegotiationTimeout); + /** * Configure whether to enable {@code tcpKeepAlive} and relevant configuration for all connections established by this * client. @@ -292,6 +331,28 @@ AwsCrtHttpClient.Builder tcpKeepAliveConfiguration(ConsumerIf not set, the platform + CRT default is used (equivalent to + * {@link TlsVersion#SYSTEM_DEFAULT}). + * + *

    This option is mutually exclusive with {@link #postQuantumTlsEnabled(Boolean) + * postQuantumTlsEnabled(false)}. Attempting to set both will cause client construction + * to fail with an {@link IllegalStateException}. + * + *

    macOS: the default CRT TLS backend on macOS (Apple Secure Transport) does not + * support TLS 1.3. To use {@link TlsVersion#TLS_1_3} on macOS you must set the environment + * variable {@code AWS_CRT_USE_NON_FIPS_TLS_13} to any non-empty value at process startup so + * the CRT selects its s2n-tls backend. See {@link TlsVersion} for details. + * + * @param minTlsVersion the minimum acceptable TLS version; {@code null} clears + * the value and reverts to the platform default + * @return this builder for method chaining + */ + AwsCrtHttpClient.Builder minTlsVersion(TlsVersion minTlsVersion); } /** @@ -305,6 +366,7 @@ private static final class DefaultBuilder @Override public AwsCrtHttpClient build() { return new AwsCrtHttpClient(this, getAttributeMap().build() + .merge(AwsCrtHttpClientBase.AWS_CRT_HTTP_DEFAULTS) .merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); } @@ -312,6 +374,7 @@ public AwsCrtHttpClient build() { public AwsCrtHttpClient buildWithDefaults(AttributeMap serviceDefaults) { return new AwsCrtHttpClient(this, getAttributeMap().build() .merge(serviceDefaults) + .merge(AwsCrtHttpClientBase.AWS_CRT_HTTP_DEFAULTS) .merge(SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS)); } } diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientBase.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientBase.java index 50689d2236d5..703a196dd102 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientBase.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientBase.java @@ -15,18 +15,22 @@ package software.amazon.awssdk.http.crt; -import static software.amazon.awssdk.crtcore.CrtConfigurationUtils.resolveHttpMonitoringOptions; import static software.amazon.awssdk.crtcore.CrtConfigurationUtils.resolveProxy; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL; import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.buildSocketOptions; +import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.buildTlsConnectionOptions; import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.resolveCipherPreference; +import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.resolveMinTlsVersion; +import static software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils.resolveMonitoringOptions; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import java.net.URI; +import java.time.Duration; import java.util.LinkedList; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.crt.CrtResource; import software.amazon.awssdk.crt.http.Http2StreamManagerOptions; import software.amazon.awssdk.crt.http.HttpClientConnectionManagerOptions; @@ -36,7 +40,9 @@ import software.amazon.awssdk.crt.http.HttpStreamManagerOptions; import software.amazon.awssdk.crt.http.HttpVersion; import software.amazon.awssdk.crt.io.ClientBootstrap; +import software.amazon.awssdk.crt.io.EventLoopGroup; import software.amazon.awssdk.crt.io.SocketOptions; +import software.amazon.awssdk.crt.io.TlsConnectionOptions; import software.amazon.awssdk.crt.io.TlsContext; import software.amazon.awssdk.crt.io.TlsContextOptions; import software.amazon.awssdk.http.Protocol; @@ -54,11 +60,23 @@ */ @SdkProtectedApi abstract class AwsCrtHttpClientBase implements SdkAutoCloseable { + // TLS_NEGOTIATION_TIMEOUT diverges from the SDK global default (5s) for backwards compatibility: + // the underlying CRT has always applied a 10s handshake timeout, so adopting the 5s global would silently tighten the + // effective handshake timeout for existing CRT customers. + static final AttributeMap AWS_CRT_HTTP_DEFAULTS = + AttributeMap.builder() + .put(SdkHttpConfigurationOption.TLS_NEGOTIATION_TIMEOUT, Duration.ofSeconds(10)) + .build(); + private static final Logger log = Logger.loggerFor(AwsCrtHttpClientBase.class); private static final String AWS_COMMON_RUNTIME = "AwsCommonRuntime"; private static final long DEFAULT_STREAM_WINDOW_SIZE = 16L * 1024L * 1024L; // 16 MB + // Heuristic threshold (not an API contract) for warning about likely-accidental oversizing of the per-client + // event-loop group. A value at or above this multiple of the available processors is almost certainly unintended. + private static final int NUM_EVENT_LOOP_THREADS_WARN_MULTIPLIER = 4; + protected final long readBufferSize; protected final Protocol protocol; private final Map connectionPools = new ConcurrentHashMap<>(); @@ -72,36 +90,81 @@ abstract class AwsCrtHttpClientBase implements SdkAutoCloseable { private final int maxStreamsPerEndpoint; private final long connectionAcquisitionTimeout; private final TlsContextOptions tlsContextOptions; + private final Duration tlsNegotiationTimeout; private boolean isClosed = false; AwsCrtHttpClientBase(AwsCrtClientBuilderBase builder, AttributeMap config) { - ClientBootstrap clientBootstrap = new ClientBootstrap(null, null); - SocketOptions clientSocketOptions = buildSocketOptions(builder.getTcpKeepAliveConfiguration(), - config.get(SdkHttpConfigurationOption.CONNECTION_TIMEOUT)); - TlsContextOptions clientTlsContextOptions = - TlsContextOptions.createDefaultClient() - .withCipherPreference(resolveCipherPreference(builder.getPostQuantumTlsEnabled())) - .withVerifyPeer(!config.get(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES)); - this.protocol = config.get(PROTOCOL); - if (protocol == Protocol.HTTP2) { - clientTlsContextOptions = clientTlsContextOptions.withAlpnList("h2"); + // These native resources are created before being registered as owned, and each creation can throw + // (e.g. CrtRuntimeException). Because close() is never invoked on a client that failed to construct, any + // already-created resource must be released here if a later step throws - otherwise the private EventLoopGroup + // (and its OS threads) and the other native handles would leak. + EventLoopGroup eventLoopGroup = null; + ClientBootstrap clientBootstrap = null; + SocketOptions clientSocketOptions = null; + TlsContextOptions clientTlsContextOptions = null; + TlsContext clientTlsContext = null; + try { + Integer numEventLoopThreads = builder.getNumEventLoopThreads(); + if (numEventLoopThreads != null) { + warnIfNumEventLoopThreadsIsExcessive(numEventLoopThreads); + eventLoopGroup = new EventLoopGroup(numEventLoopThreads); + } + clientBootstrap = new ClientBootstrap(eventLoopGroup, null); + clientSocketOptions = buildSocketOptions(builder.getTcpKeepAliveConfiguration(), + config.get(SdkHttpConfigurationOption.CONNECTION_TIMEOUT)); + clientTlsContextOptions = + TlsContextOptions.createDefaultClient() + .withCipherPreference(resolveCipherPreference(builder.getPostQuantumTlsEnabled())) + .withMinimumTlsVersion(resolveMinTlsVersion(builder.getMinTlsVersion())) + .withVerifyPeer(!config.get(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES)); + this.protocol = config.get(PROTOCOL); + if (protocol == Protocol.HTTP2) { + clientTlsContextOptions = clientTlsContextOptions.withAlpnList("h2"); + } + + this.tlsContextOptions = registerOwnedResource(clientTlsContextOptions); + clientTlsContext = new TlsContext(clientTlsContextOptions); + + // The bootstrap holds a native reference to its event-loop group, so the group is registered before (and thus + // closed after) the bootstrap to keep CRT teardown ordering correct. A null group leaves the shared static + // default group untouched. + registerOwnedResource(eventLoopGroup); + this.bootstrap = registerOwnedResource(clientBootstrap); + this.socketOptions = registerOwnedResource(clientSocketOptions); + this.tlsContext = registerOwnedResource(clientTlsContext); + this.tlsNegotiationTimeout = config.get(SdkHttpConfigurationOption.TLS_NEGOTIATION_TIMEOUT); + this.readBufferSize = builder.getReadBufferSizeInBytes() == null ? + DEFAULT_STREAM_WINDOW_SIZE : builder.getReadBufferSizeInBytes(); + this.maxStreamsPerEndpoint = config.get(SdkHttpConfigurationOption.MAX_CONNECTIONS); + this.monitoringOptions = resolveMonitoringOptions( + builder.getConnectionHealthConfiguration(), + config.get(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT)); + this.maxConnectionIdleInMilliseconds = config.get(SdkHttpConfigurationOption.CONNECTION_MAX_IDLE_TIMEOUT).toMillis(); + this.connectionAcquisitionTimeout = config.get(SdkHttpConfigurationOption.CONNECTION_ACQUIRE_TIMEOUT).toMillis(); + this.proxyOptions = resolveProxy(builder.getProxyConfiguration(), tlsContext).orElse(null); + } catch (RuntimeException e) { + // Release in reverse dependency order: the TlsContext wraps its options, and the bootstrap holds a + // reference to the event-loop group, so those wrappers are closed before what they depend on. + IoUtils.closeQuietly(clientTlsContext, log.logger()); + IoUtils.closeQuietly(clientTlsContextOptions, log.logger()); + IoUtils.closeQuietly(clientSocketOptions, log.logger()); + IoUtils.closeQuietly(clientBootstrap, log.logger()); + IoUtils.closeQuietly(eventLoopGroup, log.logger()); + throw e; } + } - this.tlsContextOptions = registerOwnedResource(clientTlsContextOptions); - TlsContext clientTlsContext = new TlsContext(clientTlsContextOptions); - - this.bootstrap = registerOwnedResource(clientBootstrap); - this.socketOptions = registerOwnedResource(clientSocketOptions); - this.tlsContext = registerOwnedResource(clientTlsContext); - this.readBufferSize = builder.getReadBufferSizeInBytes() == null ? - DEFAULT_STREAM_WINDOW_SIZE : builder.getReadBufferSizeInBytes(); - this.maxStreamsPerEndpoint = config.get(SdkHttpConfigurationOption.MAX_CONNECTIONS); - this.monitoringOptions = - resolveHttpMonitoringOptions(builder.getConnectionHealthConfiguration()) - .orElse(null); - this.maxConnectionIdleInMilliseconds = config.get(SdkHttpConfigurationOption.CONNECTION_MAX_IDLE_TIMEOUT).toMillis(); - this.connectionAcquisitionTimeout = config.get(SdkHttpConfigurationOption.CONNECTION_ACQUIRE_TIMEOUT).toMillis(); - this.proxyOptions = resolveProxy(builder.getProxyConfiguration(), tlsContext).orElse(null); + private static void warnIfNumEventLoopThreadsIsExcessive(int numEventLoopThreads) { + int availableProcessors = Math.max(1, Runtime.getRuntime().availableProcessors()); + if (numEventLoopThreads >= NUM_EVENT_LOOP_THREADS_WARN_MULTIPLIER * availableProcessors) { + log.warn(() -> String.format( + "numEventLoopThreads is set to %d, which is unusually high relative to the %d available processor(s). " + + "Each client configured with numEventLoopThreads gets its own private event-loop group, so a high count " + + "multiplied across multiple clients can lead to thread explosion, excessive context-switching, and increased " + + "memory use without improving throughput. Consider benchmarking your workload to confirm this value is " + + "necessary.", + numEventLoopThreads, availableProcessors)); + } } /** @@ -122,18 +185,27 @@ String clientName() { return AWS_COMMON_RUNTIME; } + @SdkTestInternalApi + Duration resolvedTlsNegotiationTimeout() { + return tlsNegotiationTimeout; + } + private HttpStreamManager createConnectionPool(URI uri) { log.debug(() -> String.format("Creating ConnectionPool for: URI:%s, MaxConns: %d, MaxStreams: %d", uri, maxStreamsPerEndpoint, maxStreamsPerEndpoint)); boolean isHttps = "https".equalsIgnoreCase(uri.getScheme()); - TlsContext poolTlsContext = isHttps ? tlsContext : null; + TlsConnectionOptions poolTlsConnectionOptions = null; + if (isHttps) { + poolTlsConnectionOptions = registerOwnedResource( + buildTlsConnectionOptions(tlsContext, tlsNegotiationTimeout, uri.getHost())); + } HttpClientConnectionManagerOptions h1Options = new HttpClientConnectionManagerOptions() .withClientBootstrap(bootstrap) .withSocketOptions(socketOptions) - .withTlsContext(poolTlsContext) + .withTlsConnectionOptions(poolTlsConnectionOptions) .withUri(uri) .withWindowSize(readBufferSize) .withMaxConnections(maxStreamsPerEndpoint) diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/ProxyConfiguration.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/ProxyConfiguration.java index 6e6cd85dd775..da0f58d7d849 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/ProxyConfiguration.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/ProxyConfiguration.java @@ -135,14 +135,25 @@ public interface Builder extends CrtProxyConfiguration.Builder, CopyableBuilder< Builder useEnvironmentVariableValues(Boolean useEnvironmentVariableValues); /** - * Configure the hosts that the client is allowed to access without going through the proxy. + * Configure the hosts that the client is allowed to access without going through the proxy. Each entry accepts the + * same forms as the {@code http.nonProxyHosts} system property: an exact host name such as {@code example.com}, a host + * name with a leading {@code *} wildcard such as {@code *.example.com}, a single {@code *} matching all hosts, or an + * IP range in CIDR notation such as {@code 10.0.0.0/8}. Both {@code example.com} and {@code *.example.com} match + * {@code example.com} and its subdomains. Entries must not carry surrounding whitespace; a leading or trailing space + * is treated as part of the host and prevents matching (for example the space in a comma-space + * {@code no_proxy=a.com, *.foo.com} value). */ @Override Builder nonProxyHosts(Set nonProxyHosts); /** - * Add a host that the client is allowed to access without going through the proxy. + * Add a host that the client is allowed to access without going through the proxy. The entry accepts the same forms + * as the {@code http.nonProxyHosts} system property: an exact host name such as {@code example.com}, a host name with + * a leading {@code *} wildcard such as {@code *.example.com}, a single {@code *} matching all hosts, or an IP range in + * CIDR notation such as {@code 10.0.0.0/8}. Both {@code example.com} and {@code *.example.com} match + * {@code example.com} and its subdomains. The entry must not carry surrounding whitespace; a leading or trailing space + * is treated as part of the host and prevents matching. */ @Override Builder addNonProxyHost(String nonProxyHost); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/TlsVersion.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/TlsVersion.java new file mode 100644 index 000000000000..e08e58b43224 --- /dev/null +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/TlsVersion.java @@ -0,0 +1,43 @@ +/* + * 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.http.crt; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * A TLS protocol version that {@link AwsCrtHttpClient} and {@link AwsCrtAsyncHttpClient} uses. + * + *

    Mac-Only TLS Behavior: the default CRT TLS backend on macOS (Apple Secure Transport) does not + * support TLS 1.3. To use {@link TlsVersion#TLS_1_3} on macOS you must set the environment variable + * {@code AWS_CRT_USE_NON_FIPS_TLS_13} to any non-empty value at process startup so the CRT selects its s2n-tls backend. See + * Mac-Only TLS Behavior for more details. + * + * @see AwsCrtHttpClient.Builder#minTlsVersion(TlsVersion) + * @see AwsCrtAsyncHttpClient.Builder#minTlsVersion(TlsVersion) + */ +@SdkPublicApi +public enum TlsVersion { + + /** + * TLS 1.3. + */ + TLS_1_3, + + /** + * The underlying OS/platform + CRT TLS default. + */ + SYSTEM_DEFAULT +} diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtClientBuilderBase.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtClientBuilderBase.java index b459c7eddb1b..eff0e8a6d874 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtClientBuilderBase.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtClientBuilderBase.java @@ -22,6 +22,7 @@ import software.amazon.awssdk.http.crt.ConnectionHealthConfiguration; import software.amazon.awssdk.http.crt.ProxyConfiguration; import software.amazon.awssdk.http.crt.TcpKeepAliveConfiguration; +import software.amazon.awssdk.http.crt.TlsVersion; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.Validate; @@ -33,6 +34,8 @@ public class AwsCrtClientBuilderBase { private ConnectionHealthConfiguration connectionHealthConfiguration; private TcpKeepAliveConfiguration tcpKeepAliveConfiguration; private Boolean postQuantumTlsEnabled; + private TlsVersion minTlsVersion; + private Integer numEventLoopThreads; protected AwsCrtClientBuilderBase() { } @@ -61,6 +64,17 @@ public Long getReadBufferSizeInBytes() { return this.readBufferSize; } + public BuilderT numEventLoopThreads(Integer numEventLoopThreads) { + Validate.isTrue(numEventLoopThreads == null || numEventLoopThreads > 1, + "numEventLoopThreads must be greater than 1"); + this.numEventLoopThreads = numEventLoopThreads; + return thisBuilder(); + } + + public Integer getNumEventLoopThreads() { + return this.numEventLoopThreads; + } + public BuilderT proxyConfiguration(ProxyConfiguration proxyConfiguration) { this.proxyConfiguration = proxyConfiguration; @@ -106,6 +120,16 @@ public BuilderT connectionAcquisitionTimeout(Duration connectionAcquisitionTimeo return thisBuilder(); } + public BuilderT tlsNegotiationTimeout(Duration tlsNegotiationTimeout) { + Validate.isPositive(tlsNegotiationTimeout, "tlsNegotiationTimeout"); + standardOptions.put(SdkHttpConfigurationOption.TLS_NEGOTIATION_TIMEOUT, tlsNegotiationTimeout); + return thisBuilder(); + } + + public void setTlsNegotiationTimeout(Duration tlsNegotiationTimeout) { + tlsNegotiationTimeout(tlsNegotiationTimeout); + } + public BuilderT tcpKeepAliveConfiguration(TcpKeepAliveConfiguration tcpKeepAliveConfiguration) { this.tcpKeepAliveConfiguration = tcpKeepAliveConfiguration; return thisBuilder(); @@ -132,6 +156,15 @@ public Boolean getPostQuantumTlsEnabled() { return this.postQuantumTlsEnabled; } + public BuilderT minTlsVersion(TlsVersion minTlsVersion) { + this.minTlsVersion = minTlsVersion; + return thisBuilder(); + } + + public TlsVersion getMinTlsVersion() { + return this.minTlsVersion; + } + public BuilderT proxyConfiguration(Consumer proxyConfigurationBuilderConsumer) { ProxyConfiguration.Builder builder = ProxyConfiguration.builder(); proxyConfigurationBuilderConsumer.accept(builder); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtils.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtils.java index 0c48ff65b8f0..ce03372ae257 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtils.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtils.java @@ -18,9 +18,16 @@ import java.time.Duration; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.crt.http.HttpMonitoringOptions; import software.amazon.awssdk.crt.io.SocketOptions; import software.amazon.awssdk.crt.io.TlsCipherPreference; +import software.amazon.awssdk.crt.io.TlsConnectionOptions; +import software.amazon.awssdk.crt.io.TlsContext; +import software.amazon.awssdk.crt.io.TlsContextOptions; +import software.amazon.awssdk.crtcore.CrtConfigurationUtils; +import software.amazon.awssdk.http.crt.ConnectionHealthConfiguration; import software.amazon.awssdk.http.crt.TcpKeepAliveConfiguration; +import software.amazon.awssdk.http.crt.TlsVersion; import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.NumericUtils; @@ -28,9 +35,49 @@ public final class AwsCrtConfigurationUtils { private static final Logger log = Logger.loggerFor(AwsCrtConfigurationUtils.class); + // CRT rejects a throughput-failure interval below two seconds (HttpMonitoringOptions). + private static final int MIN_MONITORING_FAILURE_INTERVAL_SECONDS = 2; + private AwsCrtConfigurationUtils() { } + /** + * Resolves the throughput monitor that enforces a connection's read/write inactivity timeout, highest precedence first: + *

      + *
    1. an explicit {@link ConnectionHealthConfiguration} always wins;
    2. + *
    3. otherwise the SDK-resolved {@code fallbackTimeout}: {@link Duration#ZERO} applies nothing, a positive value is + * mapped.
    4. + *
    + * The fallback is only ever supplied to an SDK-managed client. + */ + public static HttpMonitoringOptions resolveMonitoringOptions(ConnectionHealthConfiguration healthConfiguration, + Duration fallbackTimeout) { + if (healthConfiguration != null) { + return CrtConfigurationUtils.resolveHttpMonitoringOptions(healthConfiguration).orElse(null); + } + + if (fallbackTimeout == null || fallbackTimeout.isZero()) { + return null; + } + return mapReadWriteTimeout(fallbackTimeout); + } + + /** + * Maps a read/write inactivity timeout onto the CRT throughput monitor that enforces it: a minimum throughput of one byte + * per second measured over a failure interval of {@code readWriteTimeout}. Because the threshold is a single byte, any byte + * moved while a stream is pending resets the interval, so the connection is shut down only after {@code readWriteTimeout} of + * continuous zero-byte progress. The interval has whole-second granularity, and CRT rejects an interval below two seconds, so + * a shorter timeout is raised to that floor. + */ + public static HttpMonitoringOptions mapReadWriteTimeout(Duration readWriteTimeout) { + HttpMonitoringOptions httpMonitoringOptions = new HttpMonitoringOptions(); + httpMonitoringOptions.setMinThroughputBytesPerSecond(1); + int seconds = Math.max(MIN_MONITORING_FAILURE_INTERVAL_SECONDS, + NumericUtils.saturatedCast(readWriteTimeout.getSeconds())); + httpMonitoringOptions.setAllowableThroughputFailureIntervalSeconds(seconds); + return httpMonitoringOptions; + } + public static SocketOptions buildSocketOptions(TcpKeepAliveConfiguration tcpKeepAliveConfiguration, Duration connectionTimeout) { SocketOptions clientSocketOptions = new SocketOptions(); @@ -53,6 +100,18 @@ public static SocketOptions buildSocketOptions(TcpKeepAliveConfiguration tcpKeep return clientSocketOptions; } + public static TlsConnectionOptions buildTlsConnectionOptions(TlsContext tlsContext, Duration tlsNegotiationTimeout, + String serverName) { + TlsConnectionOptions tlsConnectionOptions = new TlsConnectionOptions(tlsContext); + if (tlsNegotiationTimeout != null) { + tlsConnectionOptions.withTimeoutMs(NumericUtils.saturatedCast(tlsNegotiationTimeout.toMillis())); + } + if (serverName != null) { + tlsConnectionOptions.withServerName(serverName); + } + return tlsConnectionOptions; + } + public static TlsCipherPreference resolveCipherPreference(Boolean postQuantumTlsEnabled) { // As of v0.39.3, aws-crt-java prefers PQ by default, so only return the non-PQ-default policy // below if the caller explicitly disables PQ by passing in false. @@ -66,4 +125,21 @@ public static TlsCipherPreference resolveCipherPreference(Boolean postQuantumTls return TlsCipherPreference.TLS_CIPHER_SYSTEM_DEFAULT; } + /** + * Translate the SDK-owned {@link TlsVersion} into the CRT-native {@link TlsContextOptions.TlsVersions} + */ + public static TlsContextOptions.TlsVersions resolveMinTlsVersion(TlsVersion minTlsVersion) { + if (minTlsVersion == null) { + return TlsContextOptions.TlsVersions.TLS_VER_SYS_DEFAULTS; + } + switch (minTlsVersion) { + case TLS_1_3: + return TlsContextOptions.TlsVersions.TLSv1_3; + case SYSTEM_DEFAULT: + return TlsContextOptions.TlsVersions.TLS_VER_SYS_DEFAULTS; + default: + throw new IllegalArgumentException("Unsupported minTlsVersion: " + minTlsVersion); + } + } + } diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutor.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutor.java index 00761c769dea..78c212cc6b34 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutor.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutor.java @@ -63,12 +63,13 @@ private void doExecute(CrtAsyncRequestContext executionContext, acquireStartTime = System.nanoTime(); } - HttpRequestBase crtRequest = toAsyncCrtRequest(executionContext); HttpStreamManager streamManager = executionContext.streamManager(); CrtResponseAdapter crtResponseHandler = CrtResponseAdapter.toCrtResponseHandler(requestFuture, asyncRequest.responseHandler()); + HttpRequestBase crtRequest = toAsyncCrtRequest(executionContext, crtResponseHandler::failRequest); + CompletableFuture streamFuture = streamManager.acquireStream(crtRequest, crtResponseHandler); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutor.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutor.java index 87c786cb23fd..b135888653e2 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutor.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutor.java @@ -58,7 +58,7 @@ private void doExecute(CrtRequestContext executionContext, CompletableFuture streamFuture = diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtUtils.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtUtils.java index 8e1650c56057..a3c16f3f1387 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtUtils.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/CrtUtils.java @@ -94,11 +94,15 @@ public static Throwable wrapCrtException(Throwable throwable) { int httpErrorCode = httpException.getErrorCode(); if (httpErrorCode == CRT_TLS_NEGOTIATION_ERROR_CODE) { - return new SSLHandshakeException(httpException.getMessage()); + SSLHandshakeException sslHandshakeException = new SSLHandshakeException(httpException.getMessage()); + sslHandshakeException.initCause(httpException); + return sslHandshakeException; } if (httpErrorCode == CRT_SOCKET_TIMEOUT) { - return new ConnectException(httpException.getMessage()); + ConnectException connectException = new ConnectException(httpException.getMessage()); + connectException.initCause(httpException); + return connectException; } return wrapWithIoExceptionIfRetryable((HttpException) throwable); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapter.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapter.java index 8672d80b0d1b..79ff633b3a77 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapter.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapter.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.http.HttpHeader; import software.amazon.awssdk.crt.http.HttpRequest; @@ -36,7 +37,7 @@ public final class CrtRequestAdapter { private CrtRequestAdapter() { } - public static HttpRequestBase toAsyncCrtRequest(CrtAsyncRequestContext request) { + public static HttpRequestBase toAsyncCrtRequest(CrtAsyncRequestContext request, Consumer onBodyError) { AsyncExecuteRequest sdkExecuteRequest = request.sdkRequest(); SdkHttpRequest sdkRequest = sdkExecuteRequest.request(); @@ -51,7 +52,8 @@ public static HttpRequestBase toAsyncCrtRequest(CrtAsyncRequestContext request) .orElse(""); String path = encodedPath + encodedQueryString; CrtRequestBodyAdapter crtRequestBodyAdapter = new CrtRequestBodyAdapter(sdkExecuteRequest.requestContentPublisher(), - request.readBufferSize()); + request.readBufferSize(), + onBodyError); HttpHeader[] crtHeaderArray = asArray(createAsyncHttpHeaderList(sdkRequest.getUri(), sdkExecuteRequest, request.protocol())); return new HttpRequest(method, @@ -60,7 +62,7 @@ public static HttpRequestBase toAsyncCrtRequest(CrtAsyncRequestContext request) crtRequestBodyAdapter); } - public static HttpRequest toCrtRequest(CrtRequestContext request) { + public static HttpRequest toCrtRequest(CrtRequestContext request, Consumer onBodyError) { HttpExecuteRequest sdkExecuteRequest = request.sdkRequest(); SdkHttpRequest sdkRequest = sdkExecuteRequest.httpRequest(); @@ -82,7 +84,7 @@ public static HttpRequest toCrtRequest(CrtRequestContext request) { .map(provider -> new HttpRequest(method, finalEncodedPath, crtHeaderArray, - new CrtRequestInputStreamAdapter(provider))) + new CrtRequestInputStreamAdapter(provider, onBodyError))) .orElse(new HttpRequest(method, finalEncodedPath, crtHeaderArray, null)); @@ -108,9 +110,11 @@ private static List createAsyncHttpHeaderList(URI uri, AsyncExecuteR crtHeaderList.add(new HttpHeader(Header.CONNECTION, Header.KEEP_ALIVE_VALUE)); } - // Set Content-Length if needed + // Set Content-Length if needed, but never alongside Transfer-Encoding. RFC 7230 forbids sending both Optional contentLength = sdkExecuteRequest.requestContentPublisher().contentLength(); - if (!sdkRequest.firstMatchingHeader(Header.CONTENT_LENGTH).isPresent() && contentLength.isPresent()) { + if (!sdkRequest.firstMatchingHeader(Header.CONTENT_LENGTH).isPresent() + && !sdkRequest.firstMatchingHeader(Header.TRANSFER_ENCODING).isPresent() + && contentLength.isPresent()) { crtHeaderList.add(new HttpHeader(Header.CONTENT_LENGTH, Long.toString(contentLength.get()))); } @@ -135,8 +139,6 @@ private static List createHttpHeaderList(URI uri, HttpExecuteRequest crtHeaderList.add(new HttpHeader(Header.CONNECTION, Header.KEEP_ALIVE_VALUE)); } - // We assume content length was set by the caller if a stream was present, so don't set it here. - // Add the rest of the Headers sdkRequest.forEachHeader((key, value) -> value.stream().map(val -> new HttpHeader(key, val)).forEach(crtHeaderList::add)); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapter.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapter.java index 6fa64d8a011d..abe8182b78b2 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapter.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapter.java @@ -17,6 +17,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.http.HttpRequestBodyStream; import software.amazon.awssdk.http.async.SdkHttpContentPublisher; @@ -27,11 +28,14 @@ final class CrtRequestBodyAdapter implements HttpRequestBodyStream { private final SdkHttpContentPublisher requestPublisher; private final ByteBufferStoringSubscriber requestBodySubscriber; + private final Consumer onBodyError; private final AtomicBoolean subscribed = new AtomicBoolean(false); + private final AtomicBoolean errorSignaled = new AtomicBoolean(false); - CrtRequestBodyAdapter(SdkHttpContentPublisher requestPublisher, long readLimit) { + CrtRequestBodyAdapter(SdkHttpContentPublisher requestPublisher, long readLimit, Consumer onBodyError) { this.requestPublisher = requestPublisher; this.requestBodySubscriber = new ByteBufferStoringSubscriber(readLimit); + this.onBodyError = onBodyError; } @Override @@ -40,7 +44,16 @@ public boolean sendRequestBody(ByteBuffer bodyBytesOut) { requestPublisher.subscribe(requestBodySubscriber); } - return requestBodySubscriber.transferTo(bodyBytesOut) == TransferResult.END_OF_STREAM; + try { + return requestBodySubscriber.transferTo(bodyBytesOut) == TransferResult.END_OF_STREAM; + } catch (RuntimeException e) { + // This is a native JNI upcall: an escaping exception is printed to stderr and discarded by CRT (#6715). + // Fail the request with the original publisher error instead of letting it propagate. + if (errorSignaled.compareAndSet(false, true)) { + onBodyError.accept(e); + } + return false; + } } @Override diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapter.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapter.java index 68f418b9e1df..bc3c55f58d46 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapter.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapter.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.http.HttpRequestBodyStream; import software.amazon.awssdk.http.ContentStreamProvider; @@ -29,11 +31,14 @@ final class CrtRequestInputStreamAdapter implements HttpRequestBodyStream { private static final int READ_BUFFER_SIZE = 16 * 1024; private final ContentStreamProvider provider; + private final Consumer onBodyError; + private final AtomicBoolean errorSignaled = new AtomicBoolean(false); private volatile InputStream providerStream; private final byte[] readBuffer = new byte[READ_BUFFER_SIZE]; - CrtRequestInputStreamAdapter(ContentStreamProvider provider) { + CrtRequestInputStreamAdapter(ContentStreamProvider provider, Consumer onBodyError) { this.provider = provider; + this.onBodyError = onBodyError; } @Override @@ -51,8 +56,11 @@ public boolean sendRequestBody(ByteBuffer bodyBytesOut) { if (read > 0) { bodyBytesOut.put(readBuffer, 0, read); } - } catch (IOException ioe) { - throw new RuntimeException(ioe); + } catch (IOException | RuntimeException e) { + // This is a native JNI call: an escaping exception is printed to stderr and discarded by CRT (#6715). + // Fail the request with the original error instead of letting it propagate. + signalError(e); + return false; } return read < 0; @@ -62,13 +70,20 @@ public boolean sendRequestBody(ByteBuffer bodyBytesOut) { public boolean resetPosition() { try { createNewStream(); - } catch (IOException ioe) { - throw new RuntimeException(ioe); + } catch (IOException | RuntimeException e) { + signalError(e); + return false; } return true; } + private void signalError(Throwable error) { + if (errorSignaled.compareAndSet(false, true)) { + onBodyError.accept(error); + } + } + private void createNewStream() throws IOException { if (providerStream != null) { providerStream.close(); diff --git a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java index 814b827ad055..a3265e6481fe 100644 --- a/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java +++ b/http-clients/aws-crt-client/src/main/java/software/amazon/awssdk/http/crt/internal/response/CrtResponseAdapter.java @@ -19,6 +19,7 @@ import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.crt.CRT; @@ -49,6 +50,11 @@ public final class CrtResponseAdapter implements HttpStreamBaseResponseHandler { private final SdkHttpResponse.Builder responseBuilder; private final ResponseHandlerHelper responseHandlerHelper; + // Guards the single terminal responseHandler.onError. A request-body error (failRequest) completes the future, + // which triggers closeConnection -> cancel -> a cancel-derived onResponseComplete; this guard stops that from + // notifying onError a second time. See #6715. + private final AtomicBoolean onErrorInvoked = new AtomicBoolean(false); + private CrtResponseAdapter(CompletableFuture completionFuture, SdkAsyncHttpResponseHandler responseHandler) { this(completionFuture, responseHandler, new SimplePublisher<>()); @@ -133,12 +139,25 @@ private void onFailedResponseComplete(HttpException error) { responseHandlerHelper.closeConnection(); } + /** + * Fail the request from outside the CRT response callbacks (e.g. a request-body read error): deliver the error to + * the response handler and complete the request future. Completing the future triggers the executor's + * connection-eviction which cancels the stream; the cancel-derived {@code onResponseComplete} is suppressed by the + * one-shot guard in {@link #callResponseHandlerOnError}, so the handler is notified exactly once. See #6715. + */ + public void failRequest(Throwable error) { + failResponseHandlerAndFuture(error); + } + private void failResponseHandlerAndFuture(Throwable error) { callResponseHandlerOnError(error); completionFuture.completeExceptionally(error); } private void callResponseHandlerOnError(Throwable error) { + if (!onErrorInvoked.compareAndSet(false, true)) { + return; + } try { responseHandler.onError(error); } catch (RuntimeException e) { diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientLongRunningRequestTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientLongRunningRequestTest.java index 17c8f1f37c8a..5a0a4b9d7ec1 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientLongRunningRequestTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientLongRunningRequestTest.java @@ -15,9 +15,21 @@ package software.amazon.awssdk.http.crt; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.CONFIGURED_TIMEOUT; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.assertFailsWithIoExceptionWithinTimeBound; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.stubLongPolling; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.stubStreamingWithPauses; + +import java.net.URI; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import software.amazon.awssdk.crt.Log; +import software.amazon.awssdk.http.HttpTestUtils; import software.amazon.awssdk.http.SdkAsyncHttpClientLongRunningRequestTestSuite; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.utils.AttributeMap; @@ -34,15 +46,47 @@ protected SdkAsyncHttpClient createSdkAsyncHttpClient(AttributeMap config) { return AwsCrtAsyncHttpClient.builder().buildWithDefaults(config); } - // Empty test; the CRT async client does not currently enforce READ_TIMEOUT. Delete this - // override when connection health monitoring is re-added. + // The CRT client enforces a read/write inactivity timeout through SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT rather than + // READ_TIMEOUT (which it ignores), so these two suite cases are re-implemented to configure that option. A stalled or + // paused response then trips the CRT throughput monitor (AWS_ERROR_HTTP_CHANNEL_THROUGHPUT_FAILURE, a retryable + // IOException) and fails the request within the bound instead of hanging. + @Test @Override public void executeWhenReadTimeoutAndServerDelaysResponseFailsWithinTimeoutBound() { + stubLongPolling(mockServer); + SdkAsyncHttpClient client = createSdkAsyncHttpClient(fallbackTimeoutConfig()); + try { + assertFailsWithIoExceptionWithinTimeBound(sendRequest(client), CONFIGURED_TIMEOUT); + } finally { + client.close(); + } } - // Empty test; the CRT async client does not currently enforce READ_TIMEOUT. Delete this - // override when connection health monitoring is re-added. + @Test @Override public void executeWhenReadTimeoutAndStreamingResponsePausesFailsWithinTimeoutBound() { + stubStreamingWithPauses(mockServer); + SdkAsyncHttpClient client = createSdkAsyncHttpClient(fallbackTimeoutConfig()); + try { + assertFailsWithIoExceptionWithinTimeBound(sendRequest(client), CONFIGURED_TIMEOUT); + } finally { + client.close(); + } + } + + private static AttributeMap fallbackTimeoutConfig() { + return AttributeMap.builder() + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, CONFIGURED_TIMEOUT) + .build(); + } + + private CompletableFuture sendRequest(SdkAsyncHttpClient client) { + URI uri = URI.create("http://localhost:" + mockServer.getPort()); + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(uri) + .method(SdkHttpMethod.GET) + .putHeader("Host", uri.getHost()) + .build(); + return HttpTestUtils.sendRequest(client, request); } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientTest.java new file mode 100644 index 000000000000..db0b668c004c --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientTest.java @@ -0,0 +1,119 @@ +/* + * 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.http.crt; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.time.Duration; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.crt.io.TlsCipherPreference; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.utils.AttributeMap; + +class AwsCrtAsyncHttpClientTest extends AwsCrtHttpClientTestBase { + + @ParameterizedTest(name = "{0}") + @MethodSource("invalidTlsNegotiationTimeouts") + void tlsNegotiationTimeout_invalidDuration_shouldThrowException(String description, Duration input, + String expectedMessageFragment) { + assertThatThrownBy(() -> AwsCrtAsyncHttpClient.builder().tlsNegotiationTimeout(input).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(expectedMessageFragment); + } + + @ParameterizedTest(name = "[async] {0}") + @MethodSource("resolutionMatrix") + void asyncBuilder_resolvedTlsNegotiationTimeout_matchesPathBPrecedence(String description, Duration customer, + Duration serviceDefault, Duration expected) { + AwsCrtAsyncHttpClient.Builder builder = AwsCrtAsyncHttpClient.builder(); + if (customer != null) { + builder.tlsNegotiationTimeout(customer); + } + + try (SdkAsyncHttpClient client = buildAsync(builder, serviceDefault)) { + assertThat(((AwsCrtAsyncHttpClient) client).resolvedTlsNegotiationTimeout()).isEqualTo(expected); + } + } + + @Test + void asyncBuilder_buildWithDefaults_serviceDefaultsLacksTlsNegotiationTimeout_resolvesToCrtDefault10s() { + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().buildWithDefaults(AttributeMap.empty())) { + assertThat(((AwsCrtAsyncHttpClient) client).resolvedTlsNegotiationTimeout()).isEqualTo(CRT_DEFAULT); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("minTlsVersionInputs") + void asyncBuilder_minTlsVersion_buildSucceeds(String description, Consumer configure) { + assertThatCode(() -> { + AwsCrtAsyncHttpClient.Builder builder = AwsCrtAsyncHttpClient.builder(); + configure.accept(builder); + builder.build().close(); + }).doesNotThrowAnyException(); + } + + @Test + void asyncBuilder_postQuantumTrueWithMinTls13_buildSucceeds() { + assertThatCode(() -> AwsCrtAsyncHttpClient.builder() + .postQuantumTlsEnabled(true) + .minTlsVersion(TlsVersion.TLS_1_3) + .build() + .close()) + .doesNotThrowAnyException(); + } + + // CRT enforces mutual exclusivity between a non-default cipher preference and a non-default minimum TLS version + // (aws-crt-java TlsContextOptions#getNativeHandle throws IllegalStateException). This surfaces only on platforms + // where TLS_CIPHER_NON_PQ_DEFAULT is supported; elsewhere resolveCipherPreference(false) falls back to + // TLS_CIPHER_SYSTEM_DEFAULT (see AwsCrtConfigurationUtils) and CRT accepts the combination. + @Test + void asyncBuilder_postQuantumFalseWithMinTls13_failsWhenCrtEnforcesMutualExclusivity() { + assumeTrue(TlsCipherPreference.TLS_CIPHER_NON_PQ_DEFAULT.isSupported()); + assertThatThrownBy(() -> AwsCrtAsyncHttpClient.builder() + .postQuantumTlsEnabled(false) + .minTlsVersion(TlsVersion.TLS_1_3) + .build()) + .isInstanceOf(IllegalStateException.class); + } + + static Stream minTlsVersionInputs() { + return Stream.of( + Arguments.of("unset -> build succeeds", + (Consumer) b -> { }), + Arguments.of("SYSTEM_DEFAULT -> build succeeds", + (Consumer) b -> b.minTlsVersion(TlsVersion.SYSTEM_DEFAULT)), + Arguments.of("TLS_1_3 -> build succeeds", + (Consumer) b -> b.minTlsVersion(TlsVersion.TLS_1_3)), + Arguments.of("TLS_1_3 then null -> build succeeds", + (Consumer) b -> + b.minTlsVersion(TlsVersion.TLS_1_3).minTlsVersion(null)) + ); + } + + private static SdkAsyncHttpClient buildAsync(AwsCrtAsyncHttpClient.Builder builder, Duration serviceDefault) { + return serviceDefault == null + ? builder.build() + : builder.buildWithDefaults(serviceDefaultsMap(serviceDefault)); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientWireMockTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientWireMockTest.java index 2efa2e56e9f2..fc17eb57d820 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientWireMockTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtAsyncHttpClientWireMockTest.java @@ -17,58 +17,76 @@ 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.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.http.HttpTestUtils.createProvider; -import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL; import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.createRequest; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.liveEventLoopGroups; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.newEventLoopGroups; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.waitForEventLoopGroupsReleased; -import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import java.net.URI; +import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; import software.amazon.awssdk.crt.CrtResource; import software.amazon.awssdk.crt.Log; import software.amazon.awssdk.http.HttpMetric; -import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.RecordingResponseHandler; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.async.AsyncExecuteRequest; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.testutils.LogCaptor; import software.amazon.awssdk.utils.AttributeMap; public class AwsCrtAsyncHttpClientWireMockTest { - @Rule - public WireMockRule mockServer = new WireMockRule(wireMockConfig() - .dynamicPort()); + @RegisterExtension + static WireMockExtension mockServer = WireMockExtension.newInstance() + .options(wireMockConfig().dynamicPort().dynamicHttpsPort()) + .build(); - @BeforeClass + @BeforeAll public static void setup() { System.setProperty("aws.crt.debugnative", "true"); Log.initLoggingToStdout(Log.LogLevel.Warn); } @Test - public void closeClient_reuse_throwException() { + public void closeClient_reuse_throwException(WireMockRuntimeInfo wm) { SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.create(); client.close(); - assertThatThrownBy(() -> makeSimpleRequest(client)).hasMessageContaining("is closed"); + assertThatThrownBy(() -> makeSimpleRequest(client, wm)).hasMessageContaining("is closed"); } @Test - public void sendRequest_withCollector_shouldCollectMetrics() throws Exception { + public void sendRequest_withCollector_shouldCollectMetrics(WireMockRuntimeInfo wm) throws Exception { try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().maxConcurrency(10).build()) { - RecordingResponseHandler recorder = makeSimpleRequest(client); + RecordingResponseHandler recorder = makeSimpleRequest(client, wm); MetricCollection metrics = recorder.collector().collect(); assertThat(metrics.metricValues(HttpMetric.HTTP_CLIENT_NAME)).containsExactly("AwsCommonRuntime"); @@ -80,25 +98,185 @@ public void sendRequest_withCollector_shouldCollectMetrics() throws Exception { } @Test - public void sharedEventLoopGroup_closeOneClient_shouldNotAffectOtherClients() throws Exception { + public void sharedEventLoopGroup_closeOneClient_shouldNotAffectOtherClients(WireMockRuntimeInfo wm) throws Exception { try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.create()) { - makeSimpleRequest(client); + makeSimpleRequest(client, wm); } try (SdkAsyncHttpClient anotherClient = AwsCrtAsyncHttpClient.create()) { - makeSimpleRequest(anotherClient); + makeSimpleRequest(anotherClient, wm); } } + @Test + public void tlsNegotiationTimeout_customValue_clientStartsSuccessfully(WireMockRuntimeInfo wm) throws Exception { + AttributeMap defaults = AttributeMap.builder().put(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES, true).build(); + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder() + .tlsNegotiationTimeout(Duration.ofSeconds(3)) + .buildWithDefaults(defaults)) { + makeSimpleHttpsRequest(client, wm); + } + } + + @ParameterizedTest + @ValueSource(ints = {0, -1, 1}) + public void numEventLoopThreads_notGreaterThanOne_shouldThrowException(int value) { + assertThatThrownBy(() -> AwsCrtAsyncHttpClient.builder().numEventLoopThreads(value)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("numEventLoopThreads must be greater than 1"); + } + + @Test + public void numEventLoopThreads_null_shouldBeAccepted() { + assertThatCode(() -> AwsCrtAsyncHttpClient.builder().numEventLoopThreads(null)) + .doesNotThrowAnyException(); + } + + @Test + public void defaultBuilder_sharesStaticDefaultEventLoopGroup() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.create(); + SdkAsyncHttpClient anotherClient = AwsCrtAsyncHttpClient.create()) { + assertThat(newEventLoopGroups(before)).isEmpty(); + } + } + + @Test + public void numEventLoopThreads_createsPrivateGroupsNotShared() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().numEventLoopThreads(2).build(); + SdkAsyncHttpClient anotherClient = AwsCrtAsyncHttpClient.builder().numEventLoopThreads(2).build()) { + assertThat(newEventLoopGroups(before)).hasSize(2); + } + } + + @Test + public void numEventLoopThreads_executesRequest(WireMockRuntimeInfo wm) throws Exception { + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().numEventLoopThreads(2).build()) { + RecordingResponseHandler recorder = makeSimpleRequest(client, wm); + assertThat(recorder.responses().get(0).statusCode()).isEqualTo(200); + } + } + + @Test + public void numEventLoopThreads_closeReleasesPrivateGroup() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().numEventLoopThreads(2).build(); + Set privateGroup = newEventLoopGroups(before); + assertThat(privateGroup).hasSize(1); + + client.close(); + + assertThat(waitForEventLoopGroupsReleased(privateGroup, Duration.ofSeconds(30))) + .as("private event-loop group should be released on close") + .isTrue(); + } + + @ParameterizedTest + @CsvSource({"4, true", "1, false"}) + public void numEventLoopThreads_warnsOnlyWhenExcessive(int multipleOfProcessors, boolean expectWarning) { + int processors = Math.max(1, Runtime.getRuntime().availableProcessors()); + int size = Math.max(2, multipleOfProcessors * processors); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN); + SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder().numEventLoopThreads(size).build()) { + if (expectWarning) { + assertThat(logCaptor.loggedEvents()).anySatisfy(event -> { + assertThat(event.getLevel()).isEqualTo(Level.WARN); + assertThat(event.getMessage().getFormattedMessage()) + .contains("numEventLoopThreads") + .contains("private event-loop group"); + }); + } else { + assertThat(logCaptor.loggedEvents()).noneSatisfy(event -> + assertThat(event.getMessage().getFormattedMessage()).contains("numEventLoopThreads")); + } + } + } + + @Test + public void requestBodyPublisherError_completesFutureWithOriginalError(WireMockRuntimeInfo wm) { + mockServer.stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withStatus(200))); + IllegalArgumentException bodyError = new IllegalArgumentException("test error"); + + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.create()) { + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost:" + wm.getHttpPort())) + .method(SdkHttpMethod.PUT) + .encodedPath("/") + .putHeader("Host", "localhost") + .putHeader("Content-Length", "16") + .build(); + + CompletableFuture executeFuture = + client.execute(AsyncExecuteRequest.builder() + .request(request) + .requestContentPublisher(erroringPublisher(bodyError, 16)) + .responseHandler(new RecordingResponseHandler()) + .build()); + + assertThatThrownBy(() -> executeFuture.get(5, TimeUnit.SECONDS)) + .hasCauseReference(bodyError); + } + } + + private static SdkHttpContentPublisher erroringPublisher(Throwable error, long contentLength) { + return new SdkHttpContentPublisher() { + @Override + public Optional contentLength() { + return Optional.of(contentLength); + } + + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new Subscription() { + @Override + public void request(long n) { + subscriber.onError(error); + } + + @Override + public void cancel() { + } + }); + } + }; + } + + private void warmUpStaticDefaultEventLoopGroup() { + // A default client and a private-group client both lazily create the shared static default group (via the host + // resolver), so create it up front to keep the before/after group diff stable. + AwsCrtAsyncHttpClient.create().close(); + } + + private RecordingResponseHandler makeSimpleHttpsRequest(SdkAsyncHttpClient client, WireMockRuntimeInfo wm) throws Exception { + String body = randomAlphabetic(10); + URI uri = URI.create("https://localhost:" + wm.getHttpsPort()); + mockServer.stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withBody(body))); + SdkHttpRequest request = createRequest(uri); + RecordingResponseHandler recorder = new RecordingResponseHandler(); + client.execute(AsyncExecuteRequest.builder() + .request(request) + .requestContentPublisher(createProvider("")) + .responseHandler(recorder) + .build()); + recorder.completeFuture().get(5, TimeUnit.SECONDS); + return recorder; + } + /** * Make a simple async request and wait for it to finish. * * @param client Client to make request with. */ - private RecordingResponseHandler makeSimpleRequest(SdkAsyncHttpClient client) throws Exception { + private RecordingResponseHandler makeSimpleRequest(SdkAsyncHttpClient client, WireMockRuntimeInfo wm) throws Exception { String body = randomAlphabetic(10); - URI uri = URI.create("http://localhost:" + mockServer.port()); - stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withBody(body))); + URI uri = URI.create("http://localhost:" + wm.getHttpPort()); + mockServer.stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withBody(body))); SdkHttpRequest request = createRequest(uri); RecordingResponseHandler recorder = new RecordingResponseHandler(); client.execute(AsyncExecuteRequest.builder() diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientLongRunningRequestTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientLongRunningRequestTest.java index e51ca3aa7e16..3b6049403abc 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientLongRunningRequestTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientLongRunningRequestTest.java @@ -15,10 +15,27 @@ package software.amazon.awssdk.http.crt; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.CONFIGURED_TIMEOUT; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.assertFailsWithIoExceptionWithinTimeBound; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.stubLongPolling; +import static software.amazon.awssdk.http.LongRunningRequestTestSupport.stubStreamingWithPauses; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import software.amazon.awssdk.crt.Log; +import software.amazon.awssdk.http.HttpExecuteRequest; +import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpClientLongRunningRequestTestSuite; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.utils.AttributeMap; public class AwsCrtHttpClientLongRunningRequestTest extends SdkHttpClientLongRunningRequestTestSuite { @@ -34,15 +51,77 @@ protected SdkHttpClient createSdkHttpClient(AttributeMap config) { return AwsCrtHttpClient.builder().buildWithDefaults(config); } - // Empty test; the CRT sync client does not currently enforce READ_TIMEOUT. Delete this - // override when connection health monitoring is re-added. + // The CRT client enforces a read/write inactivity timeout through SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT rather than + // READ_TIMEOUT (which it ignores), so these two suite cases are re-implemented to configure that option. A stalled or + // paused response then trips the CRT throughput monitor (AWS_ERROR_HTTP_CHANNEL_THROUGHPUT_FAILURE, a retryable + // IOException) and fails the request within the bound instead of hanging. + @Test @Override public void executeWhenReadTimeoutAndServerDelaysResponseFailsWithinTimeoutBound() { + stubLongPolling(mockServer); + SdkHttpClient client = createSdkHttpClient(fallbackTimeoutConfig()); + try { + assertFailsWithIoExceptionWithinTimeBound(executeAsync(client), CONFIGURED_TIMEOUT); + } finally { + client.close(); + } } - // Empty test; the CRT sync client does not currently enforce READ_TIMEOUT. Delete this - // override when connection health monitoring is re-added. + @Test @Override public void executeWhenReadTimeoutAndStreamingResponsePausesFailsWithinTimeoutBound() { + stubStreamingWithPauses(mockServer); + SdkHttpClient client = createSdkHttpClient(fallbackTimeoutConfig()); + try { + assertFailsWithIoExceptionWithinTimeBound(executeAsync(client), CONFIGURED_TIMEOUT); + } finally { + client.close(); + } + } + + private static AttributeMap fallbackTimeoutConfig() { + return AttributeMap.builder() + .put(SdkHttpConfigurationOption.SDK_INTERNAL_FALLBACK_READ_WRITE_TIMEOUT, CONFIGURED_TIMEOUT) + .build(); + } + + private CompletableFuture executeAsync(SdkHttpClient client) { + return CompletableFuture.supplyAsync(() -> { + executeRequest(client); + return null; + }); + } + + private void executeRequest(SdkHttpClient client) { + URI uri = URI.create("http://localhost:" + mockServer.getPort()); + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(uri) + .method(SdkHttpMethod.POST) + .putHeader("Host", uri.getHost()) + .putHeader("Content-Length", "4") + .contentStreamProvider(() -> new ByteArrayInputStream( + "Body".getBytes(StandardCharsets.UTF_8))) + .build(); + try { + HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() + .request(request) + .contentStreamProvider( + request.contentStreamProvider() + .orElse(null)) + .build()) + .call(); + response.responseBody().ifPresent(body -> { + try { + while (body.read() != -1) { + // drain body so mid-body timeouts surface + } + body.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTest.java index d4284e640555..040d1307afdb 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTest.java @@ -15,42 +15,24 @@ package software.amazon.awssdk.http.crt; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES; - +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.time.Duration; -import org.junit.Test; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; - -import software.amazon.awssdk.crt.CrtResource; -import software.amazon.awssdk.crt.Log; +import java.util.function.Consumer; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.crt.io.TlsCipherPreference; import software.amazon.awssdk.http.SdkHttpClient; -import software.amazon.awssdk.http.SdkHttpClientTestSuite; import software.amazon.awssdk.utils.AttributeMap; -/** - * Testing the scenario where h1 server sends 5xx errors. - */ -public class AwsCrtHttpClientTest extends SdkHttpClientTestSuite { - - @BeforeAll - public static void beforeAll() { - System.setProperty("aws.crt.debugnative", "true"); - Log.initLoggingToStdout(Log.LogLevel.Warn); - } - /** - * default value of connectionAcquisitionTimeout of 10 will fail validatesHttpsCertificateIssuer() test - * */ - @Override - protected SdkHttpClient createSdkHttpClient(SdkHttpClientOptions options) { - boolean trustAllCerts = options.trustAll(); - return AwsCrtHttpClient.builder() - .connectionAcquisitionTimeout(Duration.ofSeconds(40)) - .buildWithDefaults(AttributeMap.builder().put(TRUST_ALL_CERTIFICATES, trustAllCerts).build()); - } +public class AwsCrtHttpClientTest extends AwsCrtHttpClientTestBase { @Test public void negativeConnectionAcquisitionTimeout_shouldFail() { @@ -62,13 +44,87 @@ public void negativeConnectionAcquisitionTimeout_shouldFail() { }).hasMessage("connectionAcquisitionTimeout must be positive"); } - // Empty test; behavior not supported when using custom factory - @Override - public void testCustomTlsTrustManagerAndTrustAllFails() { + @ParameterizedTest(name = "{0}") + @MethodSource("invalidTlsNegotiationTimeouts") + void tlsNegotiationTimeout_invalidDuration_shouldThrowException(String description, Duration input, + String expectedMessageFragment) { + assertThatThrownBy(() -> AwsCrtHttpClient.builder().tlsNegotiationTimeout(input).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining(expectedMessageFragment); + } + + @Test + void syncBuilder_buildWithDefaults_serviceDefaultsLacksTlsNegotiationTimeout_resolvesToCrtDefault10s() { + try (SdkHttpClient client = AwsCrtHttpClient.builder().buildWithDefaults(AttributeMap.empty())) { + assertThat(((AwsCrtHttpClient) client).resolvedTlsNegotiationTimeout()).isEqualTo(CRT_DEFAULT); + } + } + + + @ParameterizedTest(name = "[sync] {0}") + @MethodSource("resolutionMatrix") + void syncBuilder_resolvedTlsNegotiationTimeout_matchesPathBPrecedence(String description, Duration customer, + Duration serviceDefault, Duration expected) { + AwsCrtHttpClient.Builder builder = AwsCrtHttpClient.builder(); + if (customer != null) { + builder.tlsNegotiationTimeout(customer); + } + + try (SdkHttpClient client = buildSync(builder, serviceDefault)) { + assertThat(((AwsCrtHttpClient) client).resolvedTlsNegotiationTimeout()).isEqualTo(expected); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("minTlsVersionInputs") + void syncBuilder_minTlsVersion_buildSucceeds(String description, Consumer configure) { + assertThatCode(() -> { + AwsCrtHttpClient.Builder builder = AwsCrtHttpClient.builder(); + configure.accept(builder); + builder.build().close(); + }).doesNotThrowAnyException(); + } + + @Test + void syncBuilder_postQuantumTrueWithMinTls13_buildSucceeds() { + assertThatCode(() -> AwsCrtHttpClient.builder() + .postQuantumTlsEnabled(true) + .minTlsVersion(TlsVersion.TLS_1_3) + .build() + .close()) + .doesNotThrowAnyException(); + } + + // CRT enforces mutual exclusivity between a non-default cipher preference and a non-default minimum TLS version + // (aws-crt-java TlsContextOptions#getNativeHandle throws IllegalStateException). This surfaces only on platforms + // where TLS_CIPHER_NON_PQ_DEFAULT is supported; elsewhere resolveCipherPreference(false) falls back to + // TLS_CIPHER_SYSTEM_DEFAULT (see AwsCrtConfigurationUtils) and CRT accepts the combination. + @Test + void syncBuilder_postQuantumFalseWithMinTls13_failsWhenCrtEnforcesMutualExclusivity() { + assumeTrue(TlsCipherPreference.TLS_CIPHER_NON_PQ_DEFAULT.isSupported()); + assertThatThrownBy(() -> AwsCrtHttpClient.builder() + .postQuantumTlsEnabled(false) + .minTlsVersion(TlsVersion.TLS_1_3) + .build()) + .isInstanceOf(IllegalStateException.class); + } + + static Stream minTlsVersionInputs() { + return Stream.of( + Arguments.of("unset -> build succeeds", + (Consumer) b -> { }), + Arguments.of("SYSTEM_DEFAULT -> build succeeds", + (Consumer) b -> b.minTlsVersion(TlsVersion.SYSTEM_DEFAULT)), + Arguments.of("TLS_1_3 -> build succeeds", + (Consumer) b -> b.minTlsVersion(TlsVersion.TLS_1_3)), + Arguments.of("TLS_1_3 then null -> build succeeds", + (Consumer) b -> b.minTlsVersion(TlsVersion.TLS_1_3).minTlsVersion(null)) + ); } - // Empty test; behavior not supported when using custom factory - @Override - public void testCustomTlsTrustManager() { + private static SdkHttpClient buildSync(AwsCrtHttpClient.Builder builder, Duration serviceDefault) { + return serviceDefault == null + ? builder.build() + : builder.buildWithDefaults(serviceDefaultsMap(serviceDefault)); } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTestBase.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTestBase.java new file mode 100644 index 000000000000..b3daf18578a8 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientTestBase.java @@ -0,0 +1,58 @@ +/* + * 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.http.crt; + +import java.time.Duration; +import java.util.stream.Stream; +import org.junit.jupiter.params.provider.Arguments; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.utils.AttributeMap; + + +public class AwsCrtHttpClientTestBase { + static final Duration CRT_DEFAULT = Duration.ofSeconds(10); + static final Duration CUSTOMER = Duration.ofSeconds(3); + static final Duration SERVICE_DEFAULT = Duration.ofSeconds(7); + + static Stream invalidTlsNegotiationTimeouts() { + return Stream.of( + Arguments.of("null duration -> rejected by paramNotNull", null, "tlsNegotiationTimeout"), + Arguments.of("zero duration -> rejected by isPositive", Duration.ZERO, "must be positive"), + Arguments.of("negative duration -> rejected by isPositive", Duration.ofSeconds(-1), "must be positive") + ); + } + + + static Stream resolutionMatrix() { + return Stream.of( + Arguments.of("customer unset, no service default -> CRT default (10s) beats GLOBAL (5s)", + null, null, CRT_DEFAULT), + Arguments.of("customer unset, service default 7s -> service default beats CRT default", + null, SERVICE_DEFAULT, SERVICE_DEFAULT), + Arguments.of("customer set 3s, no service default -> customer wins", + CUSTOMER, null, CUSTOMER), + Arguments.of("customer set 3s, service default 7s -> customer beats service default", + CUSTOMER, SERVICE_DEFAULT, CUSTOMER) + ); + } + + + static AttributeMap serviceDefaultsMap(Duration tlsNegotiationTimeout) { + return AttributeMap.builder() + .put(SdkHttpConfigurationOption.TLS_NEGOTIATION_TIMEOUT, tlsNegotiationTimeout) + .build(); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientWireMockTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientWireMockTest.java index ce5d778f06a1..e67f8965a28b 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientWireMockTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtHttpClientWireMockTest.java @@ -20,22 +20,32 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static java.util.Collections.emptyMap; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.PROTOCOL; +import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES; import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.createRequest; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.liveEventLoopGroups; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.newEventLoopGroups; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.waitForEventLoopGroupsReleased; import com.github.tomakehurst.wiremock.junit.WireMockRule; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; import java.net.URI; +import java.time.Duration; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import org.apache.logging.log4j.Level; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; import software.amazon.awssdk.crt.CrtResource; import software.amazon.awssdk.crt.Log; @@ -45,15 +55,16 @@ import software.amazon.awssdk.http.HttpMetric; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientTestSuite; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.metrics.MetricCollection; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.testutils.LogCaptor; import software.amazon.awssdk.utils.AttributeMap; -public class AwsCrtHttpClientWireMockTest { - @Rule - public WireMockRule mockServer = new WireMockRule(wireMockConfig() - .dynamicPort()); +public class AwsCrtHttpClientWireMockTest extends SdkHttpClientTestSuite { private static ScheduledExecutorService executorService; @@ -86,6 +97,123 @@ public void invalidProtocol_shouldThrowException() { .isInstanceOf(UnsupportedOperationException.class); } + @Test + public void numEventLoopThreads_zero_shouldThrowException() { + assertThatThrownBy(() -> AwsCrtHttpClient.builder().numEventLoopThreads(0)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("numEventLoopThreads must be greater than 1"); + } + + @Test + public void numEventLoopThreads_negative_shouldThrowException() { + assertThatThrownBy(() -> AwsCrtHttpClient.builder().numEventLoopThreads(-1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("numEventLoopThreads must be greater than 1"); + } + + @Test + public void numEventLoopThreads_one_shouldThrowException() { + assertThatThrownBy(() -> AwsCrtHttpClient.builder().numEventLoopThreads(1)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("numEventLoopThreads must be greater than 1"); + } + + @Test + public void numEventLoopThreads_null_shouldBeAccepted() { + assertThatCode(() -> AwsCrtHttpClient.builder().numEventLoopThreads(null)) + .doesNotThrowAnyException(); + } + + @Test + public void defaultBuilder_sharesStaticDefaultEventLoopGroup() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + + try (SdkHttpClient client = AwsCrtHttpClient.create(); + SdkHttpClient anotherClient = AwsCrtHttpClient.create()) { + assertThat(newEventLoopGroups(before)).isEmpty(); + } + } + + @Test + public void numEventLoopThreads_createsPrivateGroupsNotShared() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + + try (SdkHttpClient client = AwsCrtHttpClient.builder().numEventLoopThreads(2).build(); + SdkHttpClient anotherClient = AwsCrtHttpClient.builder().numEventLoopThreads(2).build()) { + assertThat(newEventLoopGroups(before)).hasSize(2); + } + } + + @Test + public void numEventLoopThreads_executesRequest() throws Exception { + try (SdkHttpClient client = AwsCrtHttpClient.builder().numEventLoopThreads(2).build()) { + HttpExecuteResponse response = makeSimpleRequest(client, null); + assertThat(response.httpResponse().statusCode()).isEqualTo(200); + } + } + + @Test + public void numEventLoopThreads_closeReleasesPrivateGroup() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + SdkHttpClient client = AwsCrtHttpClient.builder().numEventLoopThreads(2).build(); + Set privateGroup = newEventLoopGroups(before); + assertThat(privateGroup).hasSize(1); + + client.close(); + + assertThat(waitForEventLoopGroupsReleased(privateGroup, Duration.ofSeconds(30))) + .as("private event-loop group should be released on close") + .isTrue(); + } + + @Test + public void numEventLoopThreads_excessivelyHigh_logsWarning() { + int excessive = 4 * Math.max(1, Runtime.getRuntime().availableProcessors()); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN); + SdkHttpClient client = AwsCrtHttpClient.builder().numEventLoopThreads(excessive).build()) { + assertThat(logCaptor.loggedEvents()).anySatisfy(event -> { + assertThat(event.getLevel()).isEqualTo(Level.WARN); + assertThat(event.getMessage().getFormattedMessage()) + .contains("numEventLoopThreads") + .contains("private event-loop group"); + }); + } + } + + @Test + public void numEventLoopThreads_normalValue_doesNotLogWarning() { + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN); + SdkHttpClient client = AwsCrtHttpClient.builder().numEventLoopThreads(2).build()) { + assertThat(logCaptor.loggedEvents()).noneSatisfy(event -> + assertThat(event.getMessage().getFormattedMessage()).contains("numEventLoopThreads")); + } + } + + @Test + public void http2WithNumEventLoopThreads_throwsAndDoesNotLeakPrivateGroup() { + warmUpStaticDefaultEventLoopGroup(); + Set before = liveEventLoopGroups(); + AttributeMap attributeMap = AttributeMap.builder() + .put(PROTOCOL, Protocol.HTTP2) + .build(); + + assertThatThrownBy(() -> AwsCrtHttpClient.builder().numEventLoopThreads(2).buildWithDefaults(attributeMap)) + .isInstanceOf(UnsupportedOperationException.class); + + assertThat(newEventLoopGroups(before)) + .as("HTTP/2 rejection must not leave a private event-loop group behind") + .isEmpty(); + } + + private void warmUpStaticDefaultEventLoopGroup() { + // A default client and a private-group client both lazily create the shared static default group (via the host + // resolver), so create it up front to keep the before/after group diff stable. + AwsCrtHttpClient.create().close(); + } + @Test public void sendRequest_withCollector_shouldCollectMetrics() throws Exception { @@ -113,6 +241,26 @@ public void sharedEventLoopGroup_closeOneClient_shouldNotAffectOtherClients() th } } + @Test + public void tlsNegotiationTimeout_customValue_clientStartsSuccessfully() throws Exception { + AttributeMap defaults = AttributeMap.builder().put(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES, true).build(); + try (SdkHttpClient client = AwsCrtHttpClient.builder() + .tlsNegotiationTimeout(Duration.ofSeconds(3)) + .buildWithDefaults(defaults)) { + String body = randomAlphabetic(10); + URI uri = URI.create("https://localhost:" + mockServer.httpsPort()); + stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withBody(body))); + SdkHttpRequest request = createRequest(uri); + + HttpExecuteRequest.Builder executeRequestBuilder = HttpExecuteRequest.builder(); + executeRequestBuilder.request(request) + .contentStreamProvider(() -> new ByteArrayInputStream(new byte[0])); + ExecutableHttpRequest executableRequest = client.prepareRequest(executeRequestBuilder.build()); + HttpExecuteResponse response = executableRequest.call(); + assertThat(response.httpResponse().statusCode()).isEqualTo(200); + } + } + @Test public void abortRequest_shouldFailTheExceptionWithIOException() throws Exception { try (SdkHttpClient client = AwsCrtHttpClient.create()) { @@ -133,6 +281,54 @@ public void abortRequest_shouldFailTheExceptionWithIOException() throws Exceptio } } + @Test + public void call_requestBodyStreamThrows_surfacesOriginalIoException() throws Exception { + try (SdkHttpClient client = AwsCrtHttpClient.create()) { + URI uri = URI.create("http://localhost:" + mockServer.port()); + stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withStatus(200))); + SdkHttpRequest request = createRequest(uri, "/", new byte[] {1, 2, 3, 4, 5}, SdkHttpMethod.PUT, emptyMap()); + + HttpExecuteRequest.Builder executeRequestBuilder = HttpExecuteRequest.builder(); + executeRequestBuilder.request(request) + .contentStreamProvider(() -> new InputStream() { + @Override + public int read() throws IOException { + throw new IOException("boom"); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + throw new IOException("boom"); + } + }); + ExecutableHttpRequest executableRequest = client.prepareRequest(executeRequestBuilder.build()); + + assertThatThrownBy(executableRequest::call) + .isInstanceOf(IOException.class) + .hasMessageContaining("boom"); + } + } + + @Test + public void call_requestBodyProviderThrowsUncheckedIoException_surfacesOriginalError() throws Exception { + try (SdkHttpClient client = AwsCrtHttpClient.create()) { + URI uri = URI.create("http://localhost:" + mockServer.port()); + stubFor(any(urlPathEqualTo("/")).willReturn(aResponse().withStatus(200))); + SdkHttpRequest request = createRequest(uri, "/", new byte[] {1, 2, 3, 4, 5}, SdkHttpMethod.PUT, emptyMap()); + + HttpExecuteRequest.Builder executeRequestBuilder = HttpExecuteRequest.builder(); + executeRequestBuilder.request(request) + .contentStreamProvider(() -> { + throw new UncheckedIOException(new IOException("boom")); + }); + ExecutableHttpRequest executableRequest = client.prepareRequest(executeRequestBuilder.build()); + + assertThatThrownBy(executableRequest::call) + .hasRootCauseInstanceOf(IOException.class) + .hasRootCauseMessage("boom"); + } + } + /** * Make a simple request and wait for it to finish. * @@ -151,4 +347,25 @@ private HttpExecuteResponse makeSimpleRequest(SdkHttpClient client, MetricCollec ExecutableHttpRequest executableRequest = client.prepareRequest(executeRequestBuilder.build()); return executableRequest.call(); } + + /** + * default value of connectionAcquisitionTimeout of 10 will fail validatesHttpsCertificateIssuer() test + * */ + @Override + protected SdkHttpClient createSdkHttpClient(SdkHttpClientOptions options) { + boolean trustAllCerts = options.trustAll(); + return AwsCrtHttpClient.builder() + .connectionAcquisitionTimeout(Duration.ofSeconds(40)) + .buildWithDefaults(AttributeMap.builder().put(TRUST_ALL_CERTIFICATES, trustAllCerts).build()); + } + + // Empty test; behavior not supported when using custom factory + @Override + public void testCustomTlsTrustManagerAndTrustAllFails() { + } + + // Empty test; behavior not supported when using custom factory + @Override + public void testCustomTlsTrustManager() { + } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtTlsHandshakeTimeoutTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtTlsHandshakeTimeoutTest.java new file mode 100644 index 000000000000..0dc33938e43a --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/AwsCrtTlsHandshakeTimeoutTest.java @@ -0,0 +1,237 @@ +/* + * 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.http.crt; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.http.HttpTestUtils.createProvider; +import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES; +import static software.amazon.awssdk.http.crt.CrtHttpClientTestUtils.createRequest; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +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.crt.Log; +import software.amazon.awssdk.crt.http.HttpException; +import software.amazon.awssdk.http.ExecutableHttpRequest; +import software.amazon.awssdk.http.HttpExecuteRequest; +import software.amazon.awssdk.http.RecordingResponseHandler; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.utils.AttributeMap; + +/** + * Functional test that exercises the CRT runtime's TLS-handshake-timeout machinery end-to-end. Stands up a raw + * {@link ServerSocket} (NOT an {@code SSLServerSocket}) on loopback that accepts the TCP connection, drains a + * little of the ClientHello into a discard buffer, and never writes a ServerHello. The CRT TLS-negotiation timer + * fires before the connectionTimeout, completing the request future exceptionally. + */ +class AwsCrtTlsHandshakeTimeoutTest { + + private static final Duration CONNECTION_TIMEOUT = Duration.ofSeconds(15); + private static final Duration ASSERTION_UPPER_BOUND = Duration.ofSeconds(10); + + private TlsStallingServer stallingServer; + + @BeforeAll + static void beforeAll() { + System.setProperty("aws.crt.debugnative", "true"); + Log.initLoggingToStdout(Log.LogLevel.Warn); + } + + @BeforeEach + void setUp() throws IOException { + stallingServer = new TlsStallingServer(); + stallingServer.start(); + } + + @AfterEach + void tearDown() { + if (stallingServer != null) { + stallingServer.stop(); + } + } + + @Test + void asyncClient_serverWithholdsServerHello_failsWithTlsNegotiationTimeoutDrivenByConfiguredValue() throws Exception { + Duration configuredTimeout = Duration.ofSeconds(3); + Duration elapsedFloor = Duration.ofMillis(1500); + + AttributeMap defaults = AttributeMap.builder().put(TRUST_ALL_CERTIFICATES, true).build(); + try (SdkAsyncHttpClient client = AwsCrtAsyncHttpClient.builder() + .tlsNegotiationTimeout(configuredTimeout) + .connectionTimeout(CONNECTION_TIMEOUT) + .buildWithDefaults(defaults)) { + + URI uri = URI.create("https://localhost:" + stallingServer.port()); + SdkHttpRequest request = createRequest(uri); + RecordingResponseHandler recorder = new RecordingResponseHandler(); + + long start = System.nanoTime(); + client.execute(AsyncExecuteRequest.builder() + .request(request) + .requestContentPublisher(createProvider("")) + .responseHandler(recorder) + .build()); + + assertCompletedWithTlsNegotiationTimeout(recorder.completeFuture(), ASSERTION_UPPER_BOUND); + Duration elapsed = Duration.ofNanos(System.nanoTime() - start); + assertThat(elapsed).as("configured timeout %s should drive the deadline (elapsed=%s)", configuredTimeout, elapsed) + .isGreaterThanOrEqualTo(elapsedFloor); + } + } + + @Test + void syncClient_serverWithholdsServerHello_failsWithTlsNegotiationTimeoutDrivenByConfiguredValue() { + Duration configuredTimeout = Duration.ofSeconds(3); + Duration elapsedFloor = Duration.ofMillis(1500); + + AttributeMap defaults = AttributeMap.builder().put(TRUST_ALL_CERTIFICATES, true).build(); + try (SdkHttpClient client = AwsCrtHttpClient.builder() + .tlsNegotiationTimeout(configuredTimeout) + .connectionTimeout(CONNECTION_TIMEOUT) + .buildWithDefaults(defaults)) { + + URI uri = URI.create("https://localhost:" + stallingServer.port()); + SdkHttpRequest request = createRequest(uri); + HttpExecuteRequest httpExecuteRequest = HttpExecuteRequest.builder() + .request(request) + .contentStreamProvider(() -> new ByteArrayInputStream(new byte[0])) + .build(); + ExecutableHttpRequest executableRequest = client.prepareRequest(httpExecuteRequest); + + long start = System.nanoTime(); + assertThatThrownBy(executableRequest::call) + .isInstanceOf(IOException.class) + .hasCauseInstanceOf(HttpException.class) + .hasMessageContaining("tls negotiation timeout"); + Duration elapsed = Duration.ofNanos(System.nanoTime() - start); + assertThat(elapsed).as("configured timeout %s should drive the deadline (elapsed=%s)", configuredTimeout, elapsed) + .isBetween(elapsedFloor, ASSERTION_UPPER_BOUND); + } + } + + private static void assertCompletedWithTlsNegotiationTimeout(CompletableFuture future, Duration upperBound) throws Exception { + try { + future.get(upperBound.toMillis(), TimeUnit.MILLISECONDS); + throw new AssertionError("Expected TLS-negotiation-timeout failure but the future completed successfully"); + } catch (TimeoutException e) { + future.cancel(true); + throw new AssertionError("Future did not complete within " + upperBound + " - the TLS-handshake-timeout timer " + + "did not fire (or the SDK did not surface it).", e); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + assertThat(cause).isInstanceOf(IOException.class); + assertThat(cause).hasCauseInstanceOf(HttpException.class); + assertThat(cause).hasMessageContaining("tls negotiation timeout"); + } + } + + /** + * Raw {@link ServerSocket} on loopback that accepts TCP connections and never completes the TLS handshake. + * For each accepted client, a short-lived reader drains up to one buffer's worth of bytes (typically the + * ClientHello) so the kernel send buffer doesn't back-pressure the client into a write block, then the socket + * is held open until {@link #stop()} closes the listener. The client's TLS handshake timer fires while waiting + * for a ServerHello that never arrives. + */ + private static final class TlsStallingServer { + private ServerSocket serverSocket; + private Thread listenerThread; + private volatile boolean running; + + void start() throws IOException { + serverSocket = new ServerSocket(0, 50, InetAddress.getLoopbackAddress()); + running = true; + listenerThread = new Thread(this::acceptLoop, "AwsCrtTlsHandshakeTimeoutTest-StallingServer"); + listenerThread.setDaemon(true); + listenerThread.start(); + } + + int port() { + return serverSocket.getLocalPort(); + } + + void stop() { + running = false; + try { + serverSocket.close(); + } catch (IOException ignored) { + // best-effort + } + if (listenerThread != null) { + listenerThread.interrupt(); + try { + listenerThread.join(TimeUnit.SECONDS.toMillis(2)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + + private void acceptLoop() { + while (running && !Thread.currentThread().isInterrupted()) { + Socket client; + try { + client = serverSocket.accept(); + } catch (IOException e) { + return; + } + Thread worker = new Thread(() -> drainAndStall(client), + "AwsCrtTlsHandshakeTimeoutTest-StallingClient"); + worker.setDaemon(true); + worker.start(); + } + } + + private void drainAndStall(Socket client) { + try (InputStream in = client.getInputStream()) { + byte[] discard = new byte[4096]; + client.setSoTimeout(200); + try { + in.read(discard); + } catch (IOException ignored) { + // expected: read times out or the client side closes when the TLS-negotiation timer fires. + } + while (running) { + Thread.sleep(50); + } + } catch (IOException | InterruptedException ignored) { + // teardown path + } finally { + try { + client.close(); + } catch (IOException ignored) { + // best-effort + } + } + } + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtAsyncSslHandshakeBehaviorTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtAsyncSslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..2666ea96d406 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtAsyncSslHandshakeBehaviorTest.java @@ -0,0 +1,31 @@ +/* + * 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.http.crt; + +import java.time.Duration; +import software.amazon.awssdk.http.SdkAsyncHttpClientSslHandshakeBehaviorTestSuite; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; + +public class CrtAsyncSslHandshakeBehaviorTest extends SdkAsyncHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkAsyncHttpClient createSdkAsyncHttpClient() { + // CRT negotiates TLS during connection acquisition; the default 10s acquisition timeout can + // expire first and surface an acquisition-timeout exception instead of SSLHandshakeException. + return AwsCrtAsyncHttpClient.builder() + .connectionAcquisitionTimeout(Duration.ofSeconds(30)) + .build(); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtHttpClientTestUtils.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtHttpClientTestUtils.java index d564afd596b8..f09510f20475 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtHttpClientTestUtils.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtHttpClientTestUtils.java @@ -1,8 +1,25 @@ +/* + * 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.http.crt; import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; +import software.amazon.awssdk.crt.CrtResource; +import software.amazon.awssdk.crt.io.EventLoopGroup; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpResponse; @@ -10,7 +27,11 @@ import java.net.URI; import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; @@ -18,6 +39,59 @@ public class CrtHttpClientTestUtils { + private static final String EVENT_LOOP_GROUP = EventLoopGroup.class.getCanonicalName(); + + /** + * The {@link EventLoopGroup} native resources created since {@code before} was captured, by identity. Groups are only ever + * created synchronously while a client is constructed, so the difference is the exact set of groups the client under test + * created, immune to groups from other tests still draining asynchronously in the reused fork. Relies on + * {@code aws.crt.debugnative} being set. + */ + static Set newEventLoopGroups(Set before) { + Set created = liveEventLoopGroups(); + created.removeAll(before); + return created; + } + + static Set liveEventLoopGroups() { + Set groups = Collections.newSetFromMap(new IdentityHashMap<>()); + CrtResource.collectNativeResource(resource -> { + if (EVENT_LOOP_GROUP.equals(resource.canonicalName)) { + groups.add(resource.getWrapper()); + } + }); + return groups; + } + + /** + * Blocks until none of {@code groups} are in the live event-loop-group set, or the timeout elapses. Event-loop groups are + * released asynchronously (the bootstrap holds a native reference that drops on its own shutdown callback), so a released + * group leaves the live set shortly after {@code close()}. Unlike {@code CrtResource.waitForNoResources()}, this only waits + * on the specific groups passed in, so it does not tear down shared static defaults or depend on other tests' resources + * having drained. + * + * @return {@code true} if all groups were released before the timeout. + */ + static boolean waitForEventLoopGroupsReleased(Set groups, Duration timeout) { + long deadline = System.nanoTime() + timeout.toNanos(); + while (System.nanoTime() < deadline) { + Set stillLive = liveEventLoopGroups(); + stillLive.retainAll(groups); + if (stillLive.isEmpty()) { + return true; + } + try { + Thread.sleep(50); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return false; + } + } + Set stillLive = liveEventLoopGroups(); + stillLive.retainAll(groups); + return stillLive.isEmpty(); + } + static Subscriber createDummySubscriber() { return new Subscriber() { @Override diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtNonProxyHostsWildcardWarningTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtNonProxyHostsWildcardWarningTest.java new file mode 100644 index 000000000000..4426efef6ac3 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtNonProxyHostsWildcardWarningTest.java @@ -0,0 +1,196 @@ +/* + * 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.http.crt; + +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 java.util.Collections.emptyMap; +import static java.util.stream.Collectors.toSet; +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.LogEvent; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.reactivestreams.Subscriber; +import software.amazon.awssdk.crt.io.EventLoopGroup; +import software.amazon.awssdk.crt.io.HostResolver; +import software.amazon.awssdk.http.SdkHttpMethod; +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.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; +import software.amazon.awssdk.testutils.LogCaptor; + +/** + * Verifies that a nonProxyHosts entry with an unsupported wildcard placement is logged at WARN by the CRT client, from all + * three input sources, while the supported forms are not. + */ +class CrtNonProxyHostsWildcardWarningTest { + + private static final String WARN_PREFIX = "Unsupported wildcard in nonProxyHosts entry"; + + private final EnvironmentVariableHelper environmentVariableHelper = new EnvironmentVariableHelper(); + private SdkAsyncHttpClient client; + + @AfterEach + public void teardown() { + environmentVariableHelper.reset(); + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("http.nonProxyHosts"); + if (client != null) { + client.close(); + } + EventLoopGroup.closeStaticDefault(); + HostResolver.closeStaticDefault(); + } + + @ParameterizedTest(name = "builder \"{0}\" warns") + @ValueSource(strings = {"192.168.*", "internal*", "in*ternal", "*foo.com"}) + void unsupportedWildcard_builder_logsWarnOnce(String entry) { + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(1234) + .nonProxyHosts(single(entry)) + .build()) + .build(); + assertWarnedOnceFor(logCaptor, entry); + } + } + + @ParameterizedTest(name = "http.nonProxyHosts \"{0}\" warns") + @ValueSource(strings = {"192.168.*", "internal*", "in*ternal", "*foo.com"}) + void unsupportedWildcard_systemProperty_logsWarnOnce(String entry) { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", "1234"); + System.setProperty("http.nonProxyHosts", entry); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + assertWarnedOnceFor(logCaptor, entry); + } + } + + @ParameterizedTest(name = "no_proxy \"{0}\" warns") + @ValueSource(strings = {"192.168.*", "internal*", "in*ternal", "*foo.com"}) + void unsupportedWildcard_environmentVariable_logsWarnOnce(String entry) { + environmentVariableHelper.set("http_proxy", "http://localhost:1234"); + environmentVariableHelper.set("no_proxy", entry); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .useSystemPropertyValues(false) + .build()) + .build(); + assertWarnedOnceFor(logCaptor, entry); + } + } + + @ParameterizedTest(name = "supported \"{0}\" does not warn") + @ValueSource(strings = {"example.com", "*.internal.example.com", "*", "10.0.0.0/8"}) + void supportedForm_builder_doesNotWarn(String entry) { + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(1234) + .nonProxyHosts(single(entry)) + .build()) + .build(); + assertThat(warnRecords(logCaptor)).isEmpty(); + } + } + + @Test + void unsupportedWildcard_multipleRequests_warnsExactlyOnce() throws Exception { + WireMockServer mockServer = new WireMockServer(new WireMockConfiguration().dynamicPort()); + mockServer.start(); + mockServer.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withBody("hello"))); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(mockServer.port()) + .nonProxyHosts(single("192.168.*")) + .build()) + .build(); + + sendRequest(URI.create("http://localhost:" + mockServer.port())); + sendRequest(URI.create("http://localhost:" + mockServer.port())); + + assertWarnedOnceFor(logCaptor, "192.168.*"); + } finally { + mockServer.stop(); + } + } + + private static Set single(String entry) { + return Stream.of(entry).collect(toSet()); + } + + private static List warnRecords(LogCaptor logCaptor) { + return logCaptor.loggedEvents().stream() + .filter(e -> e.getMessage().getFormattedMessage().contains(WARN_PREFIX)) + .collect(Collectors.toList()); + } + + private static void assertWarnedOnceFor(LogCaptor logCaptor, String entry) { + assertThat(warnRecords(logCaptor)) + .singleElement() + .satisfies(event -> { + assertThat(event.getLevel()).isEqualTo(Level.WARN); + assertThat(event.getMessage().getFormattedMessage()).contains(WARN_PREFIX + " '" + entry + "'"); + }); + } + + private void sendRequest(URI uri) throws Exception { + CompletableFuture streamReceived = new CompletableFuture<>(); + AtomicReference response = new AtomicReference<>(null); + AtomicReference error = new AtomicReference<>(null); + Subscriber subscriber = CrtHttpClientTestUtils.createDummySubscriber(); + SdkAsyncHttpResponseHandler handler = + CrtHttpClientTestUtils.createTestResponseHandler(response, streamReceived, error, subscriber); + SdkHttpRequest request = CrtHttpClientTestUtils.createRequest(uri, "/", null, SdkHttpMethod.GET, emptyMap()); + + client.execute(AsyncExecuteRequest.builder() + .request(request) + .responseHandler(handler) + .requestContentPublisher(new EmptyPublisher()) + .build()) + .exceptionally(t -> null) + .get(60, TimeUnit.SECONDS); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtProxyWireMockTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtProxyWireMockTest.java new file mode 100644 index 000000000000..84a82584369b --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtProxyWireMockTest.java @@ -0,0 +1,267 @@ +/* + * 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.http.crt; + +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.anyRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static java.util.Collections.emptyMap; +import static java.util.stream.Collectors.toSet; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +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.ValueSource; +import org.reactivestreams.Subscriber; +import software.amazon.awssdk.crt.io.EventLoopGroup; +import software.amazon.awssdk.crt.io.HostResolver; +import software.amazon.awssdk.http.SdkHttpMethod; +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.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Verifies that a wildcard {@code http.nonProxyHosts} entry keeps matching hosts OFF the proxy on the CRT client. The routing + * decision is observed via the mock proxy's request journal, so the destination host does not need to resolve. + */ +class CrtProxyWireMockTest { + private SdkAsyncHttpClient client; + + private final WireMockServer mockProxy = new WireMockServer(new WireMockConfiguration().dynamicPort()); + private final WireMockServer mockServer = new WireMockServer(new WireMockConfiguration().dynamicPort()); + + @BeforeEach + public void setup() { + mockProxy.start(); + mockServer.start(); + mockProxy.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withBody("hello"))); + mockServer.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withBody("hello"))); + } + + @AfterEach + public void teardown() { + System.clearProperty("http.proxyHost"); + System.clearProperty("http.proxyPort"); + System.clearProperty("http.nonProxyHosts"); + mockServer.stop(); + mockProxy.stop(); + if (client != null) { + client.close(); + } + EventLoopGroup.closeStaticDefault(); + HostResolver.closeStaticDefault(); + } + + @Test + void suffixWildcardNonProxyHost_systemProperty_bypassesProxy() throws Exception { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(mockProxy.port())); + System.setProperty("http.nonProxyHosts", "*.internal.example.com"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + + sendRequest(URI.create("http://api.internal.example.com")); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + } + + @Test + void suffixWildcardNonProxyHost_rootDomainHost_bypassesProxy() throws Exception { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(mockProxy.port())); + System.setProperty("http.nonProxyHosts", "*.internal.example.com"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + + sendRequest(URI.create("http://internal.example.com")); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + } + + @Test + void exactHostNonProxyHost_systemProperty_bypassesProxy() throws Exception { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(mockProxy.port())); + System.setProperty("http.nonProxyHosts", "api.internal.example.com"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + + sendRequest(URI.create("http://api.internal.example.com")); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + } + + @Test + void nonMatchingHost_withSuffixWildcardNonProxyHost_isProxied() throws Exception { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(mockProxy.port())); + System.setProperty("http.nonProxyHosts", "*.internal.example.com"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + + sendRequest(URI.create("http://api.external.example.com")); + + mockProxy.verify(1, anyRequestedFor(anyUrl())); + } + + @Test + void suffixWildcardNonProxyHost_environmentVariable_bypassesProxy() throws Exception { + EnvironmentVariableHelper environmentVariableHelper = new EnvironmentVariableHelper(); + try { + environmentVariableHelper.set("http_proxy", "http://localhost:" + mockProxy.port()); + environmentVariableHelper.set("no_proxy", "*.internal.example.com"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .useSystemPropertyValues(false) + .build()) + .build(); + + sendRequest(URI.create("http://api.internal.example.com")); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + } finally { + environmentVariableHelper.reset(); + } + } + + // Both the comma and comma-space no_proxy spellings must route the same: the wildcard entry (*.foo.com) bypasses + // sub.foo.com, and the second entry (a.com) - which carries a leading space in the comma-space form - bypasses a.com + // after the CRT-side whitespace trim. + @ParameterizedTest(name = "no_proxy=\"{0}\"") + @ValueSource(strings = {"*.foo.com,a.com", "*.foo.com, a.com"}) + void commaSeparatedNonProxyHosts_environmentVariable_bypassesProxy(String noProxy) throws Exception { + EnvironmentVariableHelper environmentVariableHelper = new EnvironmentVariableHelper(); + try { + environmentVariableHelper.set("http_proxy", "http://localhost:" + mockProxy.port()); + environmentVariableHelper.set("no_proxy", noProxy); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .useSystemPropertyValues(false) + .build()) + .build(); + + sendRequest(URI.create("http://sub.foo.com")); + sendRequest(URI.create("http://a.com")); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + } finally { + environmentVariableHelper.reset(); + } + } + + @Test + void bareWildcardNonProxyHost_systemProperty_reachesServerDirectly() throws Exception { + System.setProperty("http.proxyHost", "localhost"); + System.setProperty("http.proxyPort", Integer.toString(mockProxy.port())); + System.setProperty("http.nonProxyHosts", "*"); + + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder().build()) + .build(); + + sendRequest(URI.create("http://localhost:" + mockServer.port())); + + mockProxy.verify(0, anyRequestedFor(anyUrl())); + mockServer.verify(1, anyRequestedFor(anyUrl())); + } + + @Test + void nonLeadingWildcardNonProxyHost_hostPrefix_isProxied() throws Exception { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(mockProxy.port()) + .nonProxyHosts(Stream.of("internal*").collect(toSet())) + .build()) + .build(); + + sendRequest(URI.create("http://internalservice.example.com")); + + mockProxy.verify(1, anyRequestedFor(anyUrl())); + } + + @Test + void nonLeadingWildcardNonProxyHost_ipPrefix_isProxied() throws Exception { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(mockProxy.port()) + .nonProxyHosts(Stream.of("192.168.*").collect(toSet())) + .build()) + .build(); + + sendRequest(URI.create("http://192.168.1.1")); + + mockProxy.verify(1, anyRequestedFor(anyUrl())); + } + + @Test + void nonLeadingWildcardNonProxyHost_notReinterpretedAsSuffixWildcard_apexProxied() throws Exception { + client = AwsCrtAsyncHttpClient.builder() + .proxyConfiguration(ProxyConfiguration.builder() + .host("localhost") + .port(mockProxy.port()) + .nonProxyHosts(Stream.of("*foo.com").collect(toSet())) + .build()) + .build(); + + sendRequest(URI.create("http://foo.com")); + + mockProxy.verify(1, anyRequestedFor(anyUrl())); + } + + private void sendRequest(URI uri) throws Exception { + CompletableFuture streamReceived = new CompletableFuture<>(); + AtomicReference response = new AtomicReference<>(null); + AtomicReference error = new AtomicReference<>(null); + Subscriber subscriber = CrtHttpClientTestUtils.createDummySubscriber(); + SdkAsyncHttpResponseHandler handler = + CrtHttpClientTestUtils.createTestResponseHandler(response, streamReceived, error, subscriber); + SdkHttpRequest request = CrtHttpClientTestUtils.createRequest(uri, "/", null, SdkHttpMethod.GET, emptyMap()); + + client.execute(AsyncExecuteRequest.builder() + .request(request) + .responseHandler(handler) + .requestContentPublisher(new EmptyPublisher()) + .build()) + .exceptionally(t -> null) + .get(60, TimeUnit.SECONDS); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtSslHandshakeBehaviorTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtSslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..c797c227dcab --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/CrtSslHandshakeBehaviorTest.java @@ -0,0 +1,31 @@ +/* + * 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.http.crt; + +import java.time.Duration; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeBehaviorTestSuite; + +public class CrtSslHandshakeBehaviorTest extends SdkHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + // CRT negotiates TLS during connection acquisition; the default 10s acquisition timeout can + // expire first and surface an acquisition-timeout exception instead of SSLHandshakeException. + return AwsCrtHttpClient.builder() + .connectionAcquisitionTimeout(Duration.ofSeconds(30)) + .build(); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/H2BehaviorTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/H2BehaviorTest.java index 8a8ec2415982..6e3ba8d56559 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/H2BehaviorTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/H2BehaviorTest.java @@ -49,6 +49,7 @@ import io.netty.handler.ssl.SslProvider; import io.netty.handler.ssl.SupportedCipherSuiteFilter; import io.netty.handler.ssl.util.SelfSignedCertificate; +import java.time.Duration; import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -85,12 +86,26 @@ public void teardown() throws InterruptedException { crt = null; } + @Test public void sendH2Request_overTls() throws Exception { CompletableFuture request = sendGetRequest(server.port(), crt); request.join(); } + @Test + public void buildH2HttpsClient_withCustomTlsNegotiationTimeout_doesNotNpeAndRequestSucceeds() throws Exception { + try (SdkAsyncHttpClient h2Client = AwsCrtAsyncHttpClient.builder() + .tlsNegotiationTimeout(Duration.ofSeconds(3)) + .buildWithDefaults(AttributeMap.builder() + .put(TRUST_ALL_CERTIFICATES, true) + .put(PROTOCOL, Protocol.HTTP2) + .build())) { + CompletableFuture request = sendGetRequest(server.port(), h2Client); + request.join(); + } + } + @Test public void sendH2Request_overPlaintext_usesPriorKnowledge() throws Exception { H2Server h2cServer = new H2Server(false); diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtilsTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtilsTest.java index 7e414e50bcc0..1ca5ad6d1173 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtilsTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/AwsCrtConfigurationUtilsTest.java @@ -21,17 +21,22 @@ import java.time.Duration; import java.util.stream.Stream; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.crt.http.HttpMonitoringOptions; import software.amazon.awssdk.crt.io.SocketOptions; import software.amazon.awssdk.crt.io.TlsCipherPreference; +import software.amazon.awssdk.crt.io.TlsContextOptions; import software.amazon.awssdk.http.SdkHttpConfigurationOption; +import software.amazon.awssdk.http.crt.ConnectionHealthConfiguration; import software.amazon.awssdk.http.crt.TcpKeepAliveConfiguration; +import software.amazon.awssdk.http.crt.TlsVersion; import software.amazon.awssdk.utils.AttributeMap; class AwsCrtConfigurationUtilsTest { + @ParameterizedTest @MethodSource("cipherPreferences") void resolveCipherPreference_shouldResolveCorrectly(Boolean postQuantumTlsEnabled, @@ -99,6 +104,84 @@ private static Stream tcpKeepAliveConfiguration() { ); } + @Test + void resolveMinTlsVersion_null_returnsSystemDefaults() { + assertThat(AwsCrtConfigurationUtils.resolveMinTlsVersion(null)) + .isEqualTo(TlsContextOptions.TlsVersions.TLS_VER_SYS_DEFAULTS); + } + + @Test + void resolveMinTlsVersion_systemDefault_returnsSystemDefaults() { + assertThat(AwsCrtConfigurationUtils.resolveMinTlsVersion(TlsVersion.SYSTEM_DEFAULT)) + .isEqualTo(TlsContextOptions.TlsVersions.TLS_VER_SYS_DEFAULTS); + } + + @Test + void resolveMinTlsVersion_tls13_returnsTLSv1_3() { + assertThat(AwsCrtConfigurationUtils.resolveMinTlsVersion(TlsVersion.TLS_1_3)) + .isEqualTo(TlsContextOptions.TlsVersions.TLSv1_3); + } + + @ParameterizedTest(name = "{0} inactivity timeout -> {1}s failure interval") + @MethodSource("readWriteTimeoutMappings") + void mapReadWriteTimeout_mapsToOneBytePerSecondMonitor(Duration readWriteTimeout, int expectedIntervalSeconds) { + HttpMonitoringOptions options = AwsCrtConfigurationUtils.mapReadWriteTimeout(readWriteTimeout); + assertThat(options.getMinThroughputBytesPerSecond()).isEqualTo(1L); + assertThat(options.getAllowableThroughputFailureIntervalSeconds()).isEqualTo(expectedIntervalSeconds); + } + + private static Stream readWriteTimeoutMappings() { + return Stream.of( + Arguments.of(Duration.ofMinutes(5), 300), + Arguments.of(Duration.ofMinutes(15), 900), + Arguments.of(Duration.ofSeconds(2), 2), + Arguments.of(Duration.ofSeconds(1), 2), + Arguments.of(Duration.ZERO, 2), + Arguments.of(Duration.ofMillis(2999), 2), + Arguments.of(Duration.ofMillis(3999), 3) + ); + } + + @Test + void resolveMonitoringOptions_explicitConnectionHealthConfiguration_winsOverFallback() { + HttpMonitoringOptions options = AwsCrtConfigurationUtils.resolveMonitoringOptions(healthConfiguration(), + Duration.ofMinutes(15)); + assertThat(options.getMinThroughputBytesPerSecond()).isEqualTo(500L); + assertThat(options.getAllowableThroughputFailureIntervalSeconds()).isEqualTo(10); + } + + @Test + void resolveMonitoringOptions_explicitConnectionHealthConfigurationWithoutFallback_usesExplicitConfig() { + HttpMonitoringOptions options = AwsCrtConfigurationUtils.resolveMonitoringOptions(healthConfiguration(), null); + assertThat(options.getMinThroughputBytesPerSecond()).isEqualTo(500L); + assertThat(options.getAllowableThroughputFailureIntervalSeconds()).isEqualTo(10); + } + + @Test + void resolveMonitoringOptions_fallbackZero_appliesNothing() { + assertThat(AwsCrtConfigurationUtils.resolveMonitoringOptions(null, Duration.ZERO)).isNull(); + } + + @Test + void resolveMonitoringOptions_fallbackPositive_mapped() { + HttpMonitoringOptions options = AwsCrtConfigurationUtils.resolveMonitoringOptions(null, Duration.ofMinutes(15)); + assertThat(options.getMinThroughputBytesPerSecond()).isEqualTo(1L); + assertThat(options.getAllowableThroughputFailureIntervalSeconds()).isEqualTo(900); + } + + @Test + void resolveMonitoringOptions_fallbackAbsent_appliesNothing() { + assertThat(AwsCrtConfigurationUtils.resolveMonitoringOptions(null, null)).isNull(); + } + + private static ConnectionHealthConfiguration healthConfiguration() { + return ConnectionHealthConfiguration.builder() + .minimumThroughputInBps(500L) + .minimumThroughputTimeout(Duration.ofSeconds(10)) + .build(); + } + + private static Stream defaultConnectionHealthConfigurationCases() { return Stream.of( Arguments.of(Duration.ofSeconds(30), Duration.ofSeconds(30), 30), diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutorTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutorTest.java index 89d5e2fb2f65..0c3c99267fdd 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutorTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtAsyncRequestExecutorTest.java @@ -184,7 +184,9 @@ public void execute_httpException_mapsToCorrectException(Entry executeFuture = requestExecutor.execute(context); - assertThatThrownBy(executeFuture::join).hasCauseInstanceOf(expectedExceptionClass); + assertThatThrownBy(executeFuture::join).hasCauseInstanceOf(expectedExceptionClass) + .hasCauseInstanceOf(IOException.class) + .hasRootCause(exception); } @Test diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutorTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutorTest.java index 456000ac1150..b1374d050304 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutorTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtRequestExecutorTest.java @@ -134,7 +134,9 @@ public void execute_httpException_mapsToCorrectException(Entry executeFuture = requestExecutor.execute(context); - assertThatThrownBy(executeFuture::join).hasCauseInstanceOf(expectedExceptionClass); + assertThatThrownBy(executeFuture::join).hasCauseInstanceOf(expectedExceptionClass) + .hasCauseInstanceOf(IOException.class) + .hasRootCause(exception); } @Test diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtResponseHandlerTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtResponseHandlerTest.java index e1caaeb021a9..3dbc08035c6b 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtResponseHandlerTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtResponseHandlerTest.java @@ -16,6 +16,9 @@ package software.amazon.awssdk.http.crt.internal; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.nio.ByteBuffer; @@ -73,6 +76,22 @@ void onResponseComplete_publisherCancelled_closesStream() { verify(httpStream).close(); } + @Test + void failRequest_thenCancelDerivedComplete_invokesOnErrorOnceWithOriginalError() { + SdkAsyncHttpResponseHandler responseHandler = spy(new TestAsyncHttpResponseHandler()); + CrtResponseAdapter adapter = CrtResponseAdapter.toCrtResponseHandler(requestFuture, responseHandler); + adapter.onAcquireStream(httpStream); + + RuntimeException original = new RuntimeException("test error"); + adapter.failRequest(original); + + // closeConnection's cancel later surfaces as a cancel-derived onResponseComplete; it must not re-notify onError. + adapter.onResponseComplete(httpStream, 1); + + verify(responseHandler, times(1)).onError(any()); + assertThatThrownBy(() -> requestFuture.join()).hasCause(original); + } + private static class TestAsyncHttpResponseHandler implements SdkAsyncHttpResponseHandler { @Override diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtUtilsTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtUtilsTest.java index 5cee0bb4770a..c9c43f238941 100644 --- a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtUtilsTest.java +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/CrtUtilsTest.java @@ -18,6 +18,9 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.net.ConnectException; +import javax.net.ssl.SSLHandshakeException; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import software.amazon.awssdk.crt.http.HttpException; @@ -70,4 +73,37 @@ public void wrapWithIoExceptionIfRetryable_nonRetryableCode_returnsHttpException assertThat(result).isSameAs(httpException); } + + /** + * TLS negotiation failures must chain the original {@link HttpException} (with its CRT error code) + * as cause, so callers can differentiate transient from persistent failures. + */ + @Test + public void wrapCrtException_tlsNegotiationError_wrapsInSslHandshakeExceptionWithCause() { + HttpException httpException = new HttpException(CrtUtils.CRT_TLS_NEGOTIATION_ERROR_CODE); + + Throwable result = CrtUtils.wrapCrtException(httpException); + + assertThat(result).isInstanceOf(SSLHandshakeException.class) + .hasMessage(httpException.getMessage()) + .hasCause(httpException); + assertThat(((HttpException) result.getCause()).getErrorCode()) + .isEqualTo(CrtUtils.CRT_TLS_NEGOTIATION_ERROR_CODE); + } + + /** + * Socket timeouts must chain the original {@link HttpException} as cause. + */ + @Test + public void wrapCrtException_socketTimeout_wrapsInConnectExceptionWithCause() { + HttpException httpException = new HttpException(CrtUtils.CRT_SOCKET_TIMEOUT); + + Throwable result = CrtUtils.wrapCrtException(httpException); + + assertThat(result).isInstanceOf(ConnectException.class) + .hasMessage(httpException.getMessage()) + .hasCause(httpException); + assertThat(((HttpException) result.getCause()).getErrorCode()) + .isEqualTo(CrtUtils.CRT_SOCKET_TIMEOUT); + } } diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapterTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapterTest.java new file mode 100644 index 000000000000..5073b68a9a39 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestAdapterTest.java @@ -0,0 +1,115 @@ +/* + * 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.http.crt.internal.request; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.http.HttpTestUtils.createProvider; + +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.crt.http.HttpHeader; +import software.amazon.awssdk.crt.http.HttpRequestBase; +import software.amazon.awssdk.http.Header; +import software.amazon.awssdk.http.HttpExecuteRequest; +import software.amazon.awssdk.http.Protocol; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; +import software.amazon.awssdk.http.crt.internal.CrtAsyncRequestContext; +import software.amazon.awssdk.http.crt.internal.CrtRequestContext; + +public class CrtRequestAdapterTest { + + @Test + public void toAsyncCrtRequest_transferEncodingPresent_doesNotAddContentLength() { + SdkHttpFullRequest sdkRequest = requestBuilder().putHeader(Header.TRANSFER_ENCODING, "chunked").build(); + SdkHttpContentPublisher publisher = createProvider("content-with-known-length"); + + HttpRequestBase crtRequest = toAsyncCrtRequest(sdkRequest, publisher); + + assertThat(headerNames(crtRequest)).contains(Header.TRANSFER_ENCODING) + .doesNotContain(Header.CONTENT_LENGTH); + } + + @Test + public void toAsyncCrtRequest_noTransferEncoding_addsContentLengthFromPublisher() { + SdkHttpFullRequest sdkRequest = requestBuilder().build(); + SdkHttpContentPublisher publisher = createProvider("content-with-known-length"); + + HttpRequestBase crtRequest = toAsyncCrtRequest(sdkRequest, publisher); + + assertThat(headerNames(crtRequest)).contains(Header.CONTENT_LENGTH) + .doesNotContain(Header.TRANSFER_ENCODING); + } + + @Test + public void toCrtRequest_transferEncodingPresent_doesNotAddContentLength() { + SdkHttpFullRequest sdkRequest = requestBuilder().putHeader(Header.TRANSFER_ENCODING, "chunked").build(); + + HttpRequestBase crtRequest = toCrtRequest(sdkRequest); + + assertThat(headerNames(crtRequest)).contains(Header.TRANSFER_ENCODING) + .doesNotContain(Header.CONTENT_LENGTH); + } + + @Test + public void toCrtRequest_contentLengthOnRequest_isPreserved() { + SdkHttpFullRequest sdkRequest = requestBuilder().putHeader(Header.CONTENT_LENGTH, "42").build(); + + HttpRequestBase crtRequest = toCrtRequest(sdkRequest); + + assertThat(headerNames(crtRequest)).contains(Header.CONTENT_LENGTH) + .doesNotContain(Header.TRANSFER_ENCODING); + } + + private static SdkHttpFullRequest.Builder requestBuilder() { + return SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost:8080")) + .method(SdkHttpMethod.POST) + .encodedPath("/"); + } + + private static HttpRequestBase toAsyncCrtRequest(SdkHttpFullRequest sdkRequest, SdkHttpContentPublisher publisher) { + AsyncExecuteRequest asyncRequest = AsyncExecuteRequest.builder() + .request(sdkRequest) + .requestContentPublisher(publisher) + .build(); + CrtAsyncRequestContext context = CrtAsyncRequestContext.builder() + .request(asyncRequest) + .readBufferSize(2000) + .protocol(Protocol.HTTP1_1) + .build(); + return CrtRequestAdapter.toAsyncCrtRequest(context, t -> { }); + } + + private static HttpRequestBase toCrtRequest(SdkHttpFullRequest sdkRequest) { + HttpExecuteRequest executeRequest = HttpExecuteRequest.builder() + .request(sdkRequest) + .build(); + CrtRequestContext context = CrtRequestContext.builder() + .request(executeRequest) + .readBufferSize(2000) + .build(); + return CrtRequestAdapter.toCrtRequest(context, t -> { }); + } + + private static List headerNames(HttpRequestBase crtRequest) { + return crtRequest.getHeaders().stream().map(HttpHeader::getName).collect(Collectors.toList()); + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapterTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapterTest.java new file mode 100644 index 000000000000..1952558c3aa2 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestBodyAdapterTest.java @@ -0,0 +1,92 @@ +/* + * 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.http.crt.internal.request; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.http.async.SdkHttpContentPublisher; + +class CrtRequestBodyAdapterTest { + + @Test + void sendRequestBody_publisherThrows_signalsErrorWithoutThrowing() { + AtomicReference signaled = new AtomicReference<>(); + CrtRequestBodyAdapter adapter = + new CrtRequestBodyAdapter(erroringPublisher(new RuntimeException("Something wrong happened")), 16, signaled::set); + + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); + + assertThat(signaled.get()).isInstanceOf(RuntimeException.class) + .hasMessageContaining("Something wrong happened"); + } + + @Test + void sendRequestBody_publisherThrowsCheckedException_signalsWrappedError() { + AtomicReference signaled = new AtomicReference<>(); + CrtRequestBodyAdapter adapter = + new CrtRequestBodyAdapter(erroringPublisher(new IOException("Some I/O error happened")), 16, signaled::set); + + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); + + assertThat(signaled.get()).isInstanceOf(UncheckedIOException.class) + .hasCauseInstanceOf(IOException.class); + } + + @Test + void sendRequestBody_calledAgainAfterError_signalsErrorOnlyOnce() { + AtomicInteger signalCount = new AtomicInteger(0); + CrtRequestBodyAdapter adapter = + new CrtRequestBodyAdapter(erroringPublisher(new RuntimeException("boom")), 16, t -> signalCount.incrementAndGet()); + + adapter.sendRequestBody(ByteBuffer.allocate(16)); + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); + + assertThat(signalCount.get()).isEqualTo(1); + } + + private static SdkHttpContentPublisher erroringPublisher(Throwable error) { + return new SdkHttpContentPublisher() { + @Override + public Optional contentLength() { + return Optional.of(0L); + } + + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new Subscription() { + @Override + public void request(long n) { + subscriber.onError(error); + } + + @Override + public void cancel() { + } + }); + } + }; + } +} diff --git a/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapterTest.java b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapterTest.java new file mode 100644 index 000000000000..2572c091ce17 --- /dev/null +++ b/http-clients/aws-crt-client/src/test/java/software/amazon/awssdk/http/crt/internal/request/CrtRequestInputStreamAdapterTest.java @@ -0,0 +1,120 @@ +/* + * 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.http.crt.internal.request; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.ContentStreamProvider; + +class CrtRequestInputStreamAdapterTest { + + @Test + void sendRequestBody_streamReadThrows_signalsOriginalErrorAndReturnsFalse() { + IOException error = new IOException("boom"); + AtomicReference signaled = new AtomicReference<>(); + CrtRequestInputStreamAdapter adapter = + new CrtRequestInputStreamAdapter(readErroringProvider(error), signaled::set); + + assertThat(adapter.sendRequestBody(ByteBuffer.allocate(16))).isFalse(); + + assertThat(signaled.get()).isSameAs(error); + } + + @Test + void sendRequestBody_newStreamThrowsUncheckedIoException_signalsOriginalErrorAndReturnsFalse() { + UncheckedIOException error = new UncheckedIOException(new IOException("boom")); + AtomicReference signaled = new AtomicReference<>(); + CrtRequestInputStreamAdapter adapter = + new CrtRequestInputStreamAdapter(() -> { throw error; }, signaled::set); + + assertThat(adapter.sendRequestBody(ByteBuffer.allocate(16))).isFalse(); + + assertThat(signaled.get()).isSameAs(error); + } + + @Test + void sendRequestBody_newStreamReturnsNull_signalsNpeAndReturnsFalse() { + AtomicReference signaled = new AtomicReference<>(); + CrtRequestInputStreamAdapter adapter = + new CrtRequestInputStreamAdapter(() -> null, signaled::set); + + assertThat(adapter.sendRequestBody(ByteBuffer.allocate(16))).isFalse(); + + assertThat(signaled.get()).isInstanceOf(NullPointerException.class); + } + + @Test + void resetPosition_closingPreviousStreamThrows_signalsOriginalErrorAndReturnsFalse() { + IOException error = new IOException("cannot reset"); + AtomicReference signaled = new AtomicReference<>(); + CrtRequestInputStreamAdapter adapter = + new CrtRequestInputStreamAdapter(closeErroringProvider(error), signaled::set); + + assertThat(adapter.resetPosition()).isTrue(); + assertThat(adapter.resetPosition()).isFalse(); + + assertThat(signaled.get()).isSameAs(error); + } + + @Test + void sendRequestBody_calledAgainAfterError_signalsErrorOnlyOnce() { + AtomicInteger signalCount = new AtomicInteger(0); + CrtRequestInputStreamAdapter adapter = + new CrtRequestInputStreamAdapter(readErroringProvider(new IOException("boom")), + t -> signalCount.incrementAndGet()); + + adapter.sendRequestBody(ByteBuffer.allocate(16)); + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); + + assertThat(signalCount.get()).isEqualTo(1); + } + + private static ContentStreamProvider readErroringProvider(IOException error) { + return () -> new InputStream() { + @Override + public int read() throws IOException { + throw error; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + throw error; + } + }; + } + + private static ContentStreamProvider closeErroringProvider(IOException error) { + return () -> new InputStream() { + @Override + public int read() { + return -1; + } + + @Override + public void close() throws IOException { + throw error; + } + }; + } +} diff --git a/http-clients/netty-nio-client/pom.xml b/http-clients/netty-nio-client/pom.xml index 6c563b6e2cfb..5fec7097da63 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -147,11 +147,6 @@ assertj-core test - - org.reactivestreams - reactive-streams-tck - test - org.apache.logging.log4j log4j-api @@ -238,6 +233,21 @@ jetty-util test + + org.apache.kerby + kerb-simplekdc + test + + + org.apache.kerby + kerb-client + test + + + org.apache.kerby + kerb-core + test + @@ -254,33 +264,6 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven.surefire.version} - - - - junit - false - - - 1 - - - - org.apache.maven.surefire - surefire-junit-platform - ${maven.surefire.version} - - - org.apache.maven.surefire - surefire-testng - ${maven.surefire.version} - - - org.apache.maven.plugins maven-jar-plugin diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java index 2c422fceb2b4..5c0b6c54b8a6 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/ProxyConfiguration.java @@ -19,6 +19,8 @@ import java.util.HashSet; import java.util.Set; import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.http.ProxyAuthScheme; +import software.amazon.awssdk.http.nio.netty.internal.utils.NettyClientLogger; import software.amazon.awssdk.utils.ProxyConfigProvider; import software.amazon.awssdk.utils.ProxyEnvironmentSetting; import software.amazon.awssdk.utils.ProxySystemSetting; @@ -34,6 +36,8 @@ */ @SdkPublicApi public final class ProxyConfiguration implements ToCopyableBuilder { + private static final NettyClientLogger log = NettyClientLogger.getLogger(ProxyConfiguration.class); + private final Boolean useSystemPropertyValues; private final Boolean useEnvironmentVariablesValues; private final String scheme; @@ -41,6 +45,7 @@ public final class ProxyConfiguration implements ToCopyableBuilder nonProxyHosts; private ProxyConfiguration(BuilderImpl builder) { @@ -56,7 +61,32 @@ private ProxyConfiguration(BuilderImpl builder) { this.port = resolvePort(builder, proxyConfigProvider); this.username = resolveUserName(builder, proxyConfigProvider); this.password = resolvePassword(builder, proxyConfigProvider); + this.proxyAuthScheme = builder.proxyAuthScheme; this.nonProxyHosts = resolveNonProxyHosts(builder, proxyConfigProvider); + validateProxyAuthConfig(proxyAuthScheme, username, password); + warnOnIgnoredCredentials(builder); + } + + private static void validateProxyAuthConfig(ProxyAuthScheme proxyAuthScheme, String username, String password) { + if (proxyAuthScheme == ProxyAuthScheme.BASIC + && (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))) { + throw new IllegalArgumentException("username and password must be configured when using BASIC proxy auth"); + } + } + + /** + * NEGOTIATE reads its credentials from the Kerberos ticket cache, so a username and password are dead configuration. Warn + * rather than fail, and only when they were set directly on this builder: values resolved from system properties or + * environment variables may not be under the caller's control, and warning about those would be noise. + */ + private static void warnOnIgnoredCredentials(BuilderImpl builder) { + if (builder.proxyAuthScheme == ProxyAuthScheme.NEGOTIATE + && (builder.username != null || builder.password != null)) { + log.warn(null, () -> "A proxy username and/or password was configured alongside the " + + ProxyAuthScheme.NEGOTIATE + " proxy auth scheme, and will be ignored. " + + ProxyAuthScheme.NEGOTIATE + " authenticates using the Kerberos ticket cache. Configure " + + ProxyAuthScheme.BASIC + " to authenticate with a username and password instead."); + } } private static Set resolveNonProxyHosts(BuilderImpl builder, ProxyConfigProvider proxyConfigProvider) { @@ -151,6 +181,13 @@ public Set nonProxyHosts() { return Collections.unmodifiableSet(nonProxyHosts != null ? nonProxyHosts : Collections.emptySet()); } + /** + * @return The auth scheme to use to authenticate with the proxy. + */ + public ProxyAuthScheme proxyAuthScheme() { + return proxyAuthScheme; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -183,6 +220,10 @@ public boolean equals(Object o) { return false; } + if (proxyAuthScheme != null ? !proxyAuthScheme.equals(that.proxyAuthScheme) : that.proxyAuthScheme != null) { + return false; + } + return nonProxyHosts.equals(that.nonProxyHosts); } @@ -195,6 +236,7 @@ public int hashCode() { result = 31 * result + nonProxyHosts.hashCode(); result = 31 * result + (username != null ? username.hashCode() : 0); result = 31 * result + (password != null ? password.hashCode() : 0); + result = 31 * result + (proxyAuthScheme != null ? proxyAuthScheme.hashCode() : 0); return result; } @@ -235,14 +277,37 @@ public interface Builder extends CopyableBuilder { Builder scheme(String scheme); /** - * Set the set of hosts that should not be proxied. Any request whose host portion matches any of the patterns - * given in the set will be sent to the remote host directly instead of through the proxy. + * Set the set of hosts that should not be proxied. Any request whose host portion matches one of these entries will be + * sent to the remote host directly instead of through the proxy. + *

    Entries supplied here are treated as exact host names (e.g. {@code example.com}) or CIDR ranges for IP addresses + * (e.g. {@code 10.0.0.0/8}). Wildcard patterns such as {@code *.example.com} or a bare {@code *} are not supported for + * entries supplied here; to use wildcards, configure them through the {@code http.nonProxyHosts} system property or the + * {@code NO_PROXY} environment variable instead. * * @param nonProxyHosts The set of hosts that should not be proxied. * @return This object for method chaining. */ Builder nonProxyHosts(Set nonProxyHosts); + /** + * Configure the auth scheme to use to authenticate with the proxy. + *

    + * If unset and {@link #username(String)} and {@link #password(String)} are set, the client will + * assume {@link ProxyAuthScheme#BASIC} auth. + *

    + * If set to {@link ProxyAuthScheme#BASIC}, {@link #username(String)} and {@link #password(String)} must also be + * configured (directly, or resolved from system properties or environment variables), otherwise + * {@link Builder#build()} throws {@link IllegalArgumentException}. + *

    + * If set to {@link ProxyAuthScheme#NEGOTIATE}, credentials come from the Kerberos ticket cache rather than from this + * configuration, and any configured username and password are ignored. See {@link ProxyAuthScheme#NEGOTIATE} for the + * environment it requires and for how a missing or expired ticket surfaces. + * + * @param proxyAuthScheme The auth scheme. + * @return This object for method chaining. + */ + Builder proxyAuthScheme(ProxyAuthScheme proxyAuthScheme); + /** * Set the username used to authenticate with the proxy username. * @@ -265,6 +330,11 @@ public interface Builder extends CopyableBuilder { * options are not provided during building the {@link ProxyConfiguration} object. To disable this behaviour, set this * value to false.It is important to note that when this property is set to "true," all proxy settings will exclusively * be obtained from System Property Values, and no partial settings will be obtained from Environment Variable Values. + *

    Pipe-separated host names in the {@code http.nonProxyHosts} system property indicate multiple hosts to exclude + * from proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com|b.com"} and + * {@code "a.com | b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). * * @param useSystemPropertyValues The option whether to use system property values * @return This object for method chaining. @@ -280,7 +350,10 @@ public interface Builder extends CopyableBuilder { * proxy settings will exclusively originate from Environment Variable Values, and no partial settings will be obtained * from System Property Values. *

    Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from - * proxy settings. + * proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and + * {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). * * @param useEnvironmentVariablesValues The option whether to use environment variable values * @return This object for method chaining. @@ -293,6 +366,7 @@ private static final class BuilderImpl implements Builder { private String scheme = "http"; private String host; private int port = 0; + private ProxyAuthScheme proxyAuthScheme; private String username; private String password; private Set nonProxyHosts; @@ -310,6 +384,7 @@ private BuilderImpl(ProxyConfiguration proxyConfiguration) { this.port = proxyConfiguration.port; this.nonProxyHosts = proxyConfiguration.nonProxyHosts != null ? new HashSet<>(proxyConfiguration.nonProxyHosts) : null; + this.proxyAuthScheme = proxyConfiguration.proxyAuthScheme; this.username = proxyConfiguration.username; this.password = proxyConfiguration.password; } @@ -342,6 +417,12 @@ public Builder nonProxyHosts(Set nonProxyHosts) { return this; } + @Override + public Builder proxyAuthScheme(ProxyAuthScheme proxyAuthScheme) { + this.proxyAuthScheme = proxyAuthScheme; + return this; + } + @Override public Builder username(String username) { this.username = username; diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java index ff5c87e57038..f13b5381e3b1 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMap.java @@ -32,18 +32,25 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import javax.security.auth.login.Configuration; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.ProtocolNegotiation; +import software.amazon.awssdk.http.ProxyAuthScheme; import software.amazon.awssdk.http.nio.netty.ProxyConfiguration; import software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup; import software.amazon.awssdk.http.nio.netty.internal.http2.HttpOrHttp2ChannelPool; import software.amazon.awssdk.http.nio.netty.internal.utils.NettyClientLogger; +import software.amazon.awssdk.utils.StringUtils; +import software.amazon.awssdk.utils.ThreadFactoryBuilder; /** * Implementation of {@link SdkChannelPoolMap} that awaits channel pools to be closed upon closing. @@ -87,6 +94,10 @@ public void channelCreated(Channel ch) throws Exception { private final SslContextProvider sslContextProvider; private final Boolean useNonBlockingDnsResolver; + private final Configuration negotiateAuthConfig; + private final ProxyAuthGenerator proxyAuthGenerator; + private final ExecutorService proxyAuthExecutor; + private AwaitCloseChannelPoolMap(Builder builder, Function createBootStrapProvider) { this.configuration = builder.configuration; this.protocol = builder.protocol; @@ -99,6 +110,11 @@ private AwaitCloseChannelPoolMap(Builder builder, Function "Closing channel pools"); @@ -168,6 +235,10 @@ public void close() { Collection channelPools = pools().values(); super.close(); + if (proxyAuthExecutor != null) { + proxyAuthExecutor.shutdownNow(); + } + try { CompletableFuture.allOf(channelPools.stream() .map(pool -> pool.underlyingSimpleChannelPool().closeFuture()) @@ -293,6 +364,9 @@ public static class Builder { private ProxyConfiguration proxyConfiguration; private Boolean useNonBlockingDnsResolver; + // testing only + private Configuration negotiateAuthConfig; + private Builder() { } @@ -351,6 +425,12 @@ public Builder useNonBlockingDnsResolver(Boolean useNonBlockingDnsResolver) { return this; } + @SdkTestInternalApi + public Builder negotiateAuthConfig(Configuration negotiateAuthConfig) { + this.negotiateAuthConfig = negotiateAuthConfig; + return this; + } + public AwaitCloseChannelPoolMap build() { return new AwaitCloseChannelPoolMap(this); } diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGenerator.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGenerator.java new file mode 100644 index 000000000000..44a80ab34a4e --- /dev/null +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGenerator.java @@ -0,0 +1,52 @@ +/* + * 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.http.nio.netty.internal; + +import io.netty.util.CharsetUtil; +import java.net.URI; +import java.util.Base64; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.ProxyAuthScheme; +import software.amazon.awssdk.utils.Validate; + +/** + * Auth param generator for Basic proxy authentication. + *

    + * See https://datatracker.ietf.org/doc/html/rfc7617. + */ +@SdkInternalApi +public class BasicProxyAuthGenerator implements ProxyAuthGenerator { + private final String username; + private final String password; + + public BasicProxyAuthGenerator(String username, String password) { + this.username = Validate.notEmpty(username, "username must not be empty"); + this.password = Validate.notEmpty(password, "password must not be empty"); + } + + @Override + public ProxyAuthScheme scheme() { + return ProxyAuthScheme.BASIC; + } + + @Override + public CompletableFuture generateAuthParams(URI proxyEndpoint) { + // Purely local and cheap, so this completes inline rather than hopping to another thread. + String authToken = String.format("%s:%s", this.username, this.password); + return CompletableFuture.completedFuture(Base64.getEncoder().encodeToString(authToken.getBytes(CharsetUtil.UTF_8))); + } +} diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java index cc53ed4da46a..0dafa642d6e4 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPool.java @@ -49,41 +49,30 @@ public class Http1TunnelConnectionPool implements ChannelPool { private final ChannelPool delegate; private final SslContext sslContext; private final URI proxyAddress; - private final String proxyUser; - private final String proxyPassword; + private final ProxyAuthGenerator proxyAuthGenerator; private final URI remoteAddress; private final ChannelPoolHandler handler; private final InitHandlerSupplier initHandlerSupplier; private final NettyConfiguration nettyConfiguration; public Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, - URI proxyAddress, String proxyUsername, String proxyPassword, + URI proxyAddress, ProxyAuthGenerator proxyAuthGenerator, URI remoteAddress, ChannelPoolHandler handler, NettyConfiguration nettyConfiguration) { this(eventLoop, delegate, sslContext, - proxyAddress, proxyUsername, proxyPassword, remoteAddress, handler, + proxyAddress, proxyAuthGenerator, remoteAddress, handler, ProxyTunnelInitHandler::new, nettyConfiguration); } - public Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, - URI proxyAddress, URI remoteAddress, ChannelPoolHandler handler, - NettyConfiguration nettyConfiguration) { - this(eventLoop, delegate, sslContext, - proxyAddress, null, null, remoteAddress, handler, - ProxyTunnelInitHandler::new, nettyConfiguration); - - } - @SdkTestInternalApi Http1TunnelConnectionPool(EventLoop eventLoop, ChannelPool delegate, SslContext sslContext, - URI proxyAddress, String proxyUser, String proxyPassword, URI remoteAddress, + URI proxyAddress, ProxyAuthGenerator proxyAuthGenerator, URI remoteAddress, ChannelPoolHandler handler, InitHandlerSupplier initHandlerSupplier, NettyConfiguration nettyConfiguration) { this.eventLoop = eventLoop; this.delegate = delegate; this.sslContext = sslContext; this.proxyAddress = proxyAddress; - this.proxyUser = proxyUser; - this.proxyPassword = proxyPassword; + this.proxyAuthGenerator = proxyAuthGenerator; this.remoteAddress = remoteAddress; this.handler = handler; this.initHandlerSupplier = initHandlerSupplier; @@ -138,7 +127,7 @@ private void setupChannel(Channel ch, Promise acquirePromise) { if (sslHandler != null) { ch.pipeline().addLast(sslHandler); } - ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, proxyUser, proxyPassword, remoteAddress, + ch.pipeline().addLast(initHandlerSupplier.newInitHandler(delegate, proxyAddress, proxyAuthGenerator, remoteAddress, tunnelEstablishedPromise)); tunnelEstablishedPromise.addListener((Future f) -> { if (f.isSuccess()) { @@ -180,7 +169,10 @@ private static boolean isTunnelEstablished(Channel ch) { @SdkTestInternalApi @FunctionalInterface interface InitHandlerSupplier { - ChannelHandler newInitHandler(ChannelPool sourcePool, String proxyUsername, String proxyPassword, URI remoteAddress, + ChannelHandler newInitHandler(ChannelPool sourcePool, + URI proxyAddress, + ProxyAuthGenerator authGenerator, + URI remoteAddress, Promise tunnelInitFuture); } } diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGenerator.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGenerator.java new file mode 100644 index 000000000000..b2f5bff08d54 --- /dev/null +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGenerator.java @@ -0,0 +1,155 @@ +/* + * 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.http.nio.netty.internal; + +import java.net.URI; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import javax.security.auth.Subject; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSException; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.ProxyAuthScheme; +import software.amazon.awssdk.utils.BinaryUtils; +import software.amazon.awssdk.utils.Validate; + +/** + * Auth generator for Kerberos. This does not login/authentication to Kerberos. It expects the ticket cache to be present and + * simply reads that to generate the token. + */ +@SdkInternalApi +public class NegotiateProxyAuthGenerator implements ProxyAuthGenerator { + // SPNEGO pseudo-mechanism OID. Lets the proxy negotiate Kerberos over HTTP "Negotiate". + // See https://www.ietf.org/rfc/rfc4178.txt for more info + private static final String OID = "1.3.6.1.5.5.2"; + private static final String SERVICE_NAME = "HTTP"; + private final Configuration config; + private final Executor executor; + + /** + * @param config The JAAS configuration to log in with, or null to use the default ticket-cache-only configuration. + * @param executor Executor to run the blocking Kerberos work on. Must not be a Netty event loop; see + * {@link #generateAuthParams(URI)}. Its lifecycle is owned by the caller. + */ + public NegotiateProxyAuthGenerator(Configuration config, Executor executor) { + if (config != null) { + this.config = config; + } else { + this.config = createDefaultConfig(); + } + this.executor = Validate.paramNotNull(executor, "executor"); + } + + @Override + public ProxyAuthScheme scheme() { + return ProxyAuthScheme.NEGOTIATE; + } + + @Override + public CompletableFuture generateAuthParams(URI proxyEndpoint) { + // Must not run on the caller's thread: the caller is a Netty event loop thread, and the work below reads the ticket + // cache from disk and may make a blocking TGS request to the KDC. Blocking the loop would stall every other channel + // assigned to it. + return CompletableFuture.supplyAsync(() -> generateAuthParamsBlocking(proxyEndpoint), executor); + } + + private String generateAuthParamsBlocking(URI proxyEndpoint) { + try { + Subject subject = getSubject(); + + byte[] token = Subject.doAs(subject, (PrivilegedExceptionAction) () -> { + GSSContext ctx = createGssContext(getManager(), proxyEndpoint); + try { + return ctx.initSecContext(new byte[0], 0, 0); + } finally { + ctx.dispose(); + } + }); + + return BinaryUtils.toBase64(token); + } catch (PrivilegedActionException e) { + throw new RuntimeException(String.format("Unable to generate SPNEGO token for Negotiate proxy authentication " + + "with '%s@%s'. This can happen when a service ticket for the proxy " + + "cannot be obtained from the KDC, e.g. because the ticket-granting " + + "ticket has expired (renew with 'kinit') or the proxy host does not " + + "match its Kerberos service principal name.", + SERVICE_NAME, proxyEndpoint.getHost()), e); + } + } + + private Subject getSubject() { + try { + LoginContext loginContext = new LoginContext("dummy", null, null, config); + loginContext.login(); + return loginContext.getSubject(); + } catch (LoginException e) { + throw new RuntimeException("Unable to perform Kerberos login for Negotiate proxy authentication. This " + + "typically means the Kerberos ticket cache is missing, expired, or not readable. " + + "Ensure a valid ticket-granting ticket exists (e.g., by running 'kinit'), and that " + + "the cache is at the expected location (see the KRB5CCNAME environment variable). " + + "Verify with 'klist'.", e); + } + } + + private GSSContext createGssContext(GSSManager manager, URI endpoint) { + try { + String name = String.format("%s@%s", SERVICE_NAME, endpoint.getHost()); + GSSName serverName = manager.createName(name, GSSName.NT_HOSTBASED_SERVICE); + Oid spnegoOid = new Oid(OID); + return manager.createContext(serverName, spnegoOid, null, + GSSContext.DEFAULT_LIFETIME); + } catch (GSSException e) { + throw new RuntimeException("Unable to create GSSContext", e); + } + } + + private static GSSManager getManager() { + return GSSManager.getInstance(); + } + + /** + * Create a generic {@link Configuration} that instructs the Kerberos login module to simply look in the ticket cache, and + * not to prompt for passwords. + *

    + * See javadoc for {@code com.sun.security.auth.module.Krb5LoginModule} for additional info on the configuration options. + */ + private static Configuration createDefaultConfig() { + return new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + Map opts = new HashMap<>(); + opts.put("useTicketCache", "true"); + opts.put("doNotPrompt", "true"); + return new AppConfigurationEntry[] { + new AppConfigurationEntry( + "com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, opts) + }; + } + }; + } +} diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyAuthGenerator.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyAuthGenerator.java new file mode 100644 index 000000000000..901338bd7eb3 --- /dev/null +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyAuthGenerator.java @@ -0,0 +1,41 @@ +/* + * 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.http.nio.netty.internal; + +import java.net.URI; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.http.ProxyAuthScheme; + +/** + * Generates the auth params for an {@code Authorization} HTTP header. + */ +@SdkInternalApi +public interface ProxyAuthGenerator { + /** + * The name of the auth scheme this generator supports. + */ + ProxyAuthScheme scheme(); + + /** + * Generate the auth params for this request. + *

    + * This is asynchronous because generating the params may block - Kerberos, for example, may need to read the ticket cache + * from disk and contact the KDC. Implementations that block MUST complete the returned future from a thread other than the + * caller's; the caller is a Netty event loop thread, and blocking it would stall every other channel assigned to that loop. + */ + CompletableFuture generateAuthParams(URI proxyEndpoint); +} diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java index e6f309afbad3..db1be11492e3 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandler.java @@ -28,11 +28,11 @@ import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpVersion; -import io.netty.util.CharsetUtil; import io.netty.util.concurrent.Promise; import java.io.IOException; import java.net.URI; -import java.util.Base64; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.function.Supplier; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; @@ -47,37 +47,105 @@ public final class ProxyTunnelInitHandler extends ChannelDuplexHandler { public static final NettyClientLogger log = NettyClientLogger.getLogger(ProxyTunnelInitHandler.class); private final ChannelPool sourcePool; - private final String username; - private final String password; + private final URI proxyAddress; + private final ProxyAuthGenerator authGenerator; private final URI remoteHost; private final Promise initPromise; private final Supplier httpCodecSupplier; public ProxyTunnelInitHandler(ChannelPool sourcePool, String proxyUsername, String proxyPassword, URI remoteHost, Promise initPromise) { - this(sourcePool, proxyUsername, proxyPassword, remoteHost, initPromise, HttpClientCodec::new); + this(sourcePool, null, proxyUsername, proxyPassword, remoteHost, initPromise, HttpClientCodec::new); } public ProxyTunnelInitHandler(ChannelPool sourcePool, URI remoteHost, Promise initPromise) { - this(sourcePool, null, null, remoteHost, initPromise, HttpClientCodec::new); + this(sourcePool, null, null, null, remoteHost, initPromise, HttpClientCodec::new); } @SdkTestInternalApi - public ProxyTunnelInitHandler(ChannelPool sourcePool, String prosyUsername, String proxyPassword, + public ProxyTunnelInitHandler(ChannelPool sourcePool, URI proxyAddress, String proxyUsername, String proxyPassword, URI remoteHost, Promise initPromise, Supplier httpCodecSupplier) { this.sourcePool = sourcePool; + this.proxyAddress = proxyAddress; this.remoteHost = remoteHost; this.initPromise = initPromise; - this.username = prosyUsername; - this.password = proxyPassword; + if (!StringUtils.isBlank(proxyUsername) && !StringUtils.isBlank(proxyPassword)) { + this.authGenerator = new BasicProxyAuthGenerator(proxyUsername, proxyPassword); + } else { + this.authGenerator = null; + } this.httpCodecSupplier = httpCodecSupplier; } + public ProxyTunnelInitHandler(ChannelPool sourcePool, URI proxyAddress, ProxyAuthGenerator authGenerator, + URI remoteHost, Promise initPromise, Supplier httpCodecSupplier) { + this.sourcePool = sourcePool; + this.proxyAddress = proxyAddress; + this.remoteHost = remoteHost; + this.initPromise = initPromise; + this.authGenerator = authGenerator; + this.httpCodecSupplier = httpCodecSupplier; + } + + public ProxyTunnelInitHandler(ChannelPool sourcePool, URI proxyAddress, ProxyAuthGenerator authGenerator, + URI remoteHost, Promise initPromise) { + this(sourcePool, proxyAddress, authGenerator, remoteHost, initPromise, HttpClientCodec::new); + } + @Override public void handlerAdded(ChannelHandlerContext ctx) { ChannelPipeline pipeline = ctx.pipeline(); pipeline.addBefore(ctx.name(), null, httpCodecSupplier.get()); - HttpRequest connectRequest = connectRequest(); + + if (authGenerator == null) { + sendConnectRequest(ctx, null); + return; + } + + CompletableFuture authParams; + try { + authParams = authGenerator.generateAuthParams(proxyAddress); + } catch (Throwable t) { + handleConnectRequestFailure(ctx, t); + return; + } + + // Basic auth completes inline, so only pay for a thread hop when the generator is actually asynchronous. When it is, + // the future completes on another thread, so hop back to the event loop before touching the channel or this + // handler's state. + boolean completesInline = authParams.isDone(); + authParams.whenComplete((params, error) -> { + if (completesInline) { + sendConnectRequestWithAuth(ctx, params, error); + } else { + ctx.executor().execute(() -> sendConnectRequestWithAuth(ctx, params, error)); + } + }); + } + + private void sendConnectRequestWithAuth(ChannelHandlerContext ctx, String authParams, Throwable error) { + // The channel may have gone away while we were waiting; whoever completed the promise has already cleaned up. + if (initPromise.isDone()) { + return; + } + + if (error != null) { + handleConnectRequestFailure(ctx, unwrap(error)); + return; + } + + sendConnectRequest(ctx, String.format("%s %s", authGenerator.scheme().value(), authParams)); + } + + private void sendConnectRequest(ChannelHandlerContext ctx, String proxyAuthorization) { + HttpRequest connectRequest; + try { + connectRequest = connectRequest(proxyAuthorization); + } catch (Throwable t) { + handleConnectRequestFailure(ctx, t); + return; + } + ctx.channel().writeAndFlush(connectRequest).addListener(f -> { if (!f.isSuccess()) { handleConnectRequestFailure(ctx, f.cause()); @@ -85,6 +153,10 @@ public void handlerAdded(ChannelHandlerContext ctx) { }); } + private static Throwable unwrap(Throwable t) { + return t instanceof CompletionException && t.getCause() != null ? t.getCause() : t; + } + @Override public void handlerRemoved(ChannelHandlerContext ctx) { if (ctx.pipeline().get(HttpClientCodec.class) != null) { @@ -145,16 +217,14 @@ private void closeAndRelease(ChannelHandlerContext ctx) { sourcePool.release(ctx.channel()); } - private HttpRequest connectRequest() { + private HttpRequest connectRequest(String proxyAuthorization) { String uri = getUri(); HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.CONNECT, uri, Unpooled.EMPTY_BUFFER); request.headers().add(HttpHeaderNames.HOST, uri); - if (!StringUtils.isEmpty(this.username) && !StringUtils.isEmpty(this.password)) { - String authToken = String.format("%s:%s", this.username, this.password); - String authB64 = Base64.getEncoder().encodeToString(authToken.getBytes(CharsetUtil.UTF_8)); - request.headers().add(HttpHeaderNames.PROXY_AUTHORIZATION, String.format("Basic %s", authB64)); + if (proxyAuthorization != null) { + request.headers().add(HttpHeaderNames.PROXY_AUTHORIZATION, proxyAuthorization); } return request; diff --git a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerSubscriber.java b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerSubscriber.java index 81e2a648a145..28c0f2933046 100644 --- a/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerSubscriber.java +++ b/http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerSubscriber.java @@ -154,7 +154,12 @@ private void verifyRegisteredWithRightExecutor(ChannelHandlerContext ctx) { @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { - maybeRequestMore(); + // Only request demand once RUNNING. A writability change can arrive while the subscription is still pending + // (the Expect: 100-continue deferral window, where the subscribe is held back until the server answers), when + // maybeRequestMore() would dereference a null subscription. See #7271. + if (state == HandlerSubscriber.State.RUNNING) { + maybeRequestMore(); + } ctx.fireChannelWritabilityChanged(); } diff --git a/http-clients/netty-nio-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/netty-nio-client/native-image.properties b/http-clients/netty-nio-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/netty-nio-client/native-image.properties index 1c7d1b66ae00..1e43c501d3bb 100644 --- a/http-clients/netty-nio-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/netty-nio-client/native-image.properties +++ b/http-clients/netty-nio-client/src/main/resources/META-INF/native-image/software.amazon.awssdk/netty-nio-client/native-image.properties @@ -12,6 +12,8 @@ # express or implied. See the License for the specific language governing # permissions and limitations under the License. # +# Needed because native-maven-plugin's metadata repository excludes netty's own +# '--initialize-at-build-time=io.netty', leaving jctools queues to fail at run time. Args=--allow-incomplete-classpath \ --initialize-at-run-time=io.netty.internal.tcnative.SSL,\ io.netty.internal.tcnative.CertificateVerifier,\ @@ -19,4 +21,5 @@ Args=--allow-incomplete-classpath \ io.netty.internal.tcnative.SSLPrivateKeyMethod,\ io.netty.handler.ssl.OpenSslPrivateKeyMethod,\ io.netty.handler.ssl.ReferenceCountedOpenSslEngine,\ - io.netty.handler.ssl.OpenSslAsyncPrivateKeyMethod + io.netty.handler.ssl.OpenSslAsyncPrivateKeyMethod \ + --initialize-at-build-time=io.netty.util.internal.shaded.org.jctools diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/BaseMockServer.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/BaseMockServer.java index f7dff4a55e99..9095f1a97be8 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/BaseMockServer.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/BaseMockServer.java @@ -15,8 +15,6 @@ package software.amazon.awssdk.http.nio.netty; -import java.io.IOException; -import java.net.ServerSocket; import java.net.URI; public class BaseMockServer { @@ -24,11 +22,6 @@ public class BaseMockServer { protected int httpPort; protected int httpsPort; - public BaseMockServer() throws IOException { - httpPort = getUnusedPort(); - httpsPort = getUnusedPort(); - } - public URI getHttpUri() { return URI.create(String.format("http://localhost:%s", httpPort)); } @@ -36,11 +29,4 @@ public URI getHttpUri() { public URI getHttpsUri() { return URI.create(String.format("https://localhost:%s", httpsPort)); } - - public static int getUnusedPort() throws IOException { - try (ServerSocket socket = new ServerSocket(0)) { - socket.setReuseAddress(true); - return socket.getLocalPort(); - } - } } diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/MockH2Server.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/MockH2Server.java index 4c34c3bc55de..863086547f14 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/MockH2Server.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/MockH2Server.java @@ -44,25 +44,25 @@ */ public class MockH2Server extends BaseMockServer { private final Server server; + private final ServerConnector httpConnector; + private final ServerConnector http2Connector; + private final HttpConfiguration httpConfiguration; public MockH2Server(boolean usingAlpn) throws IOException { server = new Server(); - ServerConnector connector = new ServerConnector(server); - connector.setPort(httpPort); // HTTP Configuration - HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration = new HttpConfiguration(); httpConfiguration.setSecureScheme("https"); - httpConfiguration.setSecurePort(httpsPort); httpConfiguration.setSendXPoweredBy(true); httpConfiguration.setSendServerVersion(true); - // HTTP Connector - ServerConnector http = new ServerConnector(server, - new HttpConnectionFactory(httpConfiguration), - new HTTP2CServerConnectionFactory(httpConfiguration)); - http.setPort(httpPort); - server.addConnector(http); + // HTTP Connector, port 0 makes the kernel assign a free port atomically at bind time + httpConnector = new ServerConnector(server, + new HttpConnectionFactory(httpConfiguration), + new HTTP2CServerConnectionFactory(httpConfiguration)); + httpConnector.setPort(0); + server.addConnector(httpConnector); // HTTPS Configuration @@ -86,7 +86,6 @@ public MockH2Server(boolean usingAlpn) throws IOException { // SSL Connection Factory SslConnectionFactory ssl; - ServerConnector http2Connector; if (usingAlpn) { ssl = new SslConnectionFactory(sslContextFactory, "alpn"); @@ -98,7 +97,7 @@ public MockH2Server(boolean usingAlpn) throws IOException { http2Connector = new ServerConnector(server, ssl, h2, new HttpConnectionFactory(https)); } - http2Connector.setPort(httpsPort); + http2Connector.setPort(0); server.addConnector(http2Connector); ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); @@ -108,6 +107,9 @@ public MockH2Server(boolean usingAlpn) throws IOException { public void start() throws Exception { server.start(); + httpPort = httpConnector.getLocalPort(); + httpsPort = http2Connector.getLocalPort(); + httpConfiguration.setSecurePort(httpsPort); } public void stop() throws Exception { diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClientApiCallAttemptTimeoutTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClientApiCallAttemptTimeoutTest.java new file mode 100644 index 000000000000..e941d80b3e7a --- /dev/null +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClientApiCallAttemptTimeoutTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.nio.netty; + +import software.amazon.awssdk.http.SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; + +public class NettyNioAsyncHttpClientApiCallAttemptTimeoutTest extends SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite { + @Override + protected SdkAsyncHttpClient createSdkAsyncHttpClient() { + return NettyNioAsyncHttpClient.builder().build(); + } +} diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettySslHandshakeBehaviorTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettySslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..9140a6edf92f --- /dev/null +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettySslHandshakeBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.nio.netty; + +import software.amazon.awssdk.http.SdkAsyncHttpClientSslHandshakeBehaviorTestSuite; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; + +public class NettySslHandshakeBehaviorTest extends SdkAsyncHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkAsyncHttpClient createSdkAsyncHttpClient() { + return NettyNioAsyncHttpClient.builder().build(); + } +} diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java index 06d57c1aa7d2..57f9ec44483a 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyConfigurationTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.http.nio.netty; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -23,9 +24,12 @@ import java.util.Random; import java.util.Set; import java.util.stream.Stream; +import org.apache.logging.log4j.Level; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.ProxyAuthScheme; +import software.amazon.awssdk.testutils.LogCaptor; /** * Tests for {@link ProxyConfiguration}. @@ -147,6 +151,100 @@ void setNonProxyHostsToNull_createsEmptySet() { assertThat(cfg.nonProxyHosts()).isEmpty(); } + @Test + void build_basicAuthSchemeWithoutCredentials_throws() { + ProxyConfiguration.Builder builder = ProxyConfiguration.builder() + .host("localhost") + .port(8888) + .proxyAuthScheme(ProxyAuthScheme.BASIC); + + assertThatThrownBy(builder::build) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("username and password must be configured"); + } + + @Test + void build_basicAuthSchemeWithoutPassword_throws() { + ProxyConfiguration.Builder builder = ProxyConfiguration.builder() + .host("localhost") + .port(8888) + .proxyAuthScheme(ProxyAuthScheme.BASIC) + .username("user"); + + assertThatThrownBy(builder::build) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("username and password must be configured"); + } + + @Test + void build_basicAuthSchemeWithCredentials_doesNotThrow() { + ProxyConfiguration cfg = ProxyConfiguration.builder() + .host("localhost") + .port(8888) + .proxyAuthScheme(ProxyAuthScheme.BASIC) + .username("user") + .password("pass") + .build(); + + assertThat(cfg.proxyAuthScheme()).isEqualTo(ProxyAuthScheme.BASIC); + } + + @Test + void build_basicAuthSchemeWithSystemPropertyCredentials_doesNotThrow() { + setHttpProxyProperties(); + + ProxyConfiguration cfg = ProxyConfiguration.builder() + .proxyAuthScheme(ProxyAuthScheme.BASIC) + .build(); + + assertThat(cfg.username()).isEqualTo(TEST_USER); + assertThat(cfg.password()).isEqualTo(TEST_PASSWORD); + } + + @Test + void build_negotiateAuthSchemeWithoutCredentials_doesNotThrow() { + ProxyConfiguration cfg = ProxyConfiguration.builder() + .host("localhost") + .port(8888) + .proxyAuthScheme(ProxyAuthScheme.NEGOTIATE) + .build(); + + assertThat(cfg.proxyAuthScheme()).isEqualTo(ProxyAuthScheme.NEGOTIATE); + } + + @Test + void build_negotiateAuthSchemeWithCredentials_warnsAndKeepsBuilding() { + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + ProxyConfiguration cfg = ProxyConfiguration.builder() + .host("localhost") + .port(8888) + .proxyAuthScheme(ProxyAuthScheme.NEGOTIATE) + .username(TEST_USER) + .password(TEST_PASSWORD) + .build(); + + assertThat(cfg.proxyAuthScheme()).isEqualTo(ProxyAuthScheme.NEGOTIATE); + assertThat(logCaptor.loggedEvents()).singleElement() + .satisfies(event -> assertThat(event.getMessage().getFormattedMessage()) + .contains("NEGOTIATE") + .contains("will be ignored")); + } + } + + @Test + void build_negotiateAuthSchemeWithSystemPropertyCredentials_doesNotWarn() { + setHttpProxyProperties(); + + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + ProxyConfiguration.builder() + .proxyAuthScheme(ProxyAuthScheme.NEGOTIATE) + .build(); + + // Credentials the caller did not set here are not their mistake to fix, so warning about them would be noise. + assertThat(logCaptor.loggedEvents()).isEmpty(); + } + } + @Test void toBuilderModified_doesNotModifySource() { ProxyConfiguration original = allPropertiesSetConfig(); @@ -185,7 +283,11 @@ private void setRandomValue(Object o, Method setter) throws InvocationTargetExce setter.invoke(o, randomSet()); } else if (Boolean.class.equals(paramClass)) { setter.invoke(o, RNG.nextBoolean()); - } else { + } else if (ProxyAuthScheme.class.equals(paramClass)) { + ProxyAuthScheme authScheme = ProxyAuthScheme.values()[RNG.nextInt(ProxyAuthScheme.values().length)]; + setter.invoke(o, authScheme); + } + else { throw new RuntimeException("Don't know how create random value for type " + paramClass); } } diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyWireMockTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyWireMockTest.java index 438d65e1f9fc..75ab4de383cf 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyWireMockTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/ProxyWireMockTest.java @@ -37,11 +37,14 @@ import software.amazon.awssdk.http.async.AsyncExecuteRequest; import software.amazon.awssdk.http.async.SdkAsyncHttpClient; import software.amazon.awssdk.http.async.SdkAsyncHttpResponseHandler; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; /** * Tests for HTTP proxy functionality in the Netty client. */ public class ProxyWireMockTest { + private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper(); + private static SdkAsyncHttpClient client; private static ProxyConfiguration proxyCfg; @@ -79,6 +82,7 @@ public void methodTeardown() { client.close(); } client = null; + ENVIRONMENT_VARIABLE_HELPER.reset(); } @Test(expected = IOException.class) @@ -150,6 +154,32 @@ public void proxyConfigured_hostInNonProxySet_nonBlockingDns_doesNotConnect() { assertThat(responseHandler.fullResponseAsString()).isEqualTo("hello"); } + @Test + public void proxyConfigured_hostInCommaSpaceNoProxyEnv_doesNotConnect() { + ENVIRONMENT_VARIABLE_HELPER.set("no_proxy", "example.com, localhost"); + + RecordingResponseHandler responseHandler = new RecordingResponseHandler(); + AsyncExecuteRequest req = AsyncExecuteRequest.builder() + .request(testSdkRequest()) + .responseHandler(responseHandler) + .requestContentPublisher(new EmptyPublisher()) + .build(); + + ProxyConfiguration cfg = ProxyConfiguration.builder() + .host("localhost") + .port(mockProxy.port()) + .build(); + + client = NettyNioAsyncHttpClient.builder() + .proxyConfiguration(cfg) + .build(); + + client.execute(req).join(); + + responseHandler.completeFuture.join(); + assertThat(responseHandler.fullResponseAsString()).isEqualTo("hello"); + } + private SdkHttpFullRequest testSdkRequest() { return SdkHttpFullRequest.builder() .method(SdkHttpMethod.GET) diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java index a1d4b9781f35..8838e230329e 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/AwaitCloseChannelPoolMapTest.java @@ -23,45 +23,83 @@ import static software.amazon.awssdk.http.SdkHttpConfigurationOption.GLOBAL_HTTP_DEFAULTS; import static software.amazon.awssdk.http.SdkHttpConfigurationOption.TLS_KEY_MANAGERS_PROVIDER; -import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.WireMockServer; import io.netty.channel.Channel; import io.netty.channel.pool.ChannelPool; import io.netty.handler.ssl.SslProvider; -import io.netty.util.CharsetUtil; import io.netty.util.concurrent.Future; +import java.net.InetSocketAddress; +import java.net.Socket; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; -import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; import org.apache.commons.lang3.RandomStringUtils; -import org.junit.After; -import org.junit.Rule; -import org.junit.Test; +import org.apache.kerby.kerberos.kerb.client.KrbClient; +import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer; +import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mockito; import software.amazon.awssdk.http.Protocol; import software.amazon.awssdk.http.ProtocolNegotiation; import software.amazon.awssdk.http.TlsKeyManagersProvider; +import software.amazon.awssdk.http.ProxyAuthScheme; import software.amazon.awssdk.http.nio.netty.ProxyConfiguration; import software.amazon.awssdk.http.nio.netty.RecordingNetworkTrafficListener; import software.amazon.awssdk.http.nio.netty.SdkEventLoopGroup; import software.amazon.awssdk.utils.AttributeMap; public class AwaitCloseChannelPoolMapTest { + private static final String KRB5_PROP = "java.security.krb5.conf"; + private static final RecordingNetworkTrafficListener recorder = new RecordingNetworkTrafficListener(); - private final RecordingNetworkTrafficListener recorder = new RecordingNetworkTrafficListener(); + private static WireMockServer mockProxy; + + private static Path tempDir; + private static Path keytabFile; + private static Path ccacheFile; + private static int port; + + private static SimpleKdcServer kdc; + private static String krb5PropSave; + + private static Configuration negotiateAuthConfig; private AwaitCloseChannelPoolMap channelPoolMap; - @Rule - public WireMockRule mockProxy = new WireMockRule(wireMockConfig() - .dynamicPort() - .networkTrafficListener(recorder)); + @BeforeAll + public static void setup() throws Exception { + mockProxy = new WireMockServer(wireMockConfig().dynamicPort().networkTrafficListener(recorder)); + mockProxy.start(); + + setupMockKerberos(); + } + + @AfterAll + public static void teardown() throws Exception { + if (krb5PropSave != null) { + System.setProperty(KRB5_PROP, krb5PropSave); + } else { + System.clearProperty(KRB5_PROP); + } + mockProxy.stop(); + kdc.stop(); + } - @After + @AfterEach public void methodTeardown() { if (channelPoolMap != null) { channelPoolMap.close(); @@ -71,6 +109,56 @@ public void methodTeardown() { recorder.reset(); } + private static void setupMockKerberos() throws Exception { + tempDir = Files.createTempDirectory(null); + keytabFile = tempDir.resolve("keytab"); + ccacheFile = tempDir.resolve("ccache"); + + try (Socket freePort = new Socket()) { + freePort.setReuseAddress(true); + freePort.bind(new InetSocketAddress(0)); + port = freePort.getLocalPort(); + + kdc = new SimpleKdcServer(); + kdc.setKdcRealm("EXAMPLE.COM"); + kdc.setKdcHost("localhost"); + kdc.setWorkDir(tempDir.toFile()); + kdc.setKdcTcpPort(port); + kdc.setAllowUdp(false); + kdc.init(); + + krb5PropSave = System.getProperty(KRB5_PROP); + + System.setProperty(KRB5_PROP, tempDir.resolve("krb5.conf").toAbsolutePath().toString()); + kdc.start(); + + kdc.createPrincipal("alice@EXAMPLE.COM", "alicePassword"); + kdc.createAndExportPrincipals(keytabFile.toFile(), "HTTP/localhost@EXAMPLE.COM"); + + // initialize the ticket cache + KrbClient krbClient = kdc.getKrbClient(); + TgtTicket tgt = krbClient.requestTgt("alice@EXAMPLE.COM", "alicePassword"); + krbClient.storeTicket(tgt, ccacheFile.toFile()); + + // Override config so we look at the testing cache instead of the real system cache + negotiateAuthConfig = new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + Map opts = new HashMap<>(); + opts.put("useTicketCache", "true"); + opts.put("ticketCache", ccacheFile.toAbsolutePath().toString()); + opts.put("refreshKrb5Config", "true"); + opts.put("doNotPrompt", "true"); + return new AppConfigurationEntry[] { + new AppConfigurationEntry( + "com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, opts) + }; + } + }; + } + } + @Test public void close_underlyingPoolsShouldBeClosed() { channelPoolMap = AwaitCloseChannelPoolMap.builder() @@ -216,13 +304,16 @@ public void usingProxy_noSchemeGiven_defaultsToHttp() { assertThat(requests).contains("CONNECT some-awesome-service:443"); } - @Test - public void usingProxy_withAuth() { + @ParameterizedTest + @MethodSource("proxyAuthTestParams") + public void usingProxy_authHeaderCorrect(ProxyAuthScheme authScheme, String username, String password, + String proxyAuthHeader) { ProxyConfiguration proxyConfiguration = ProxyConfiguration.builder() .host("localhost") .port(mockProxy.port()) - .username("myuser") - .password("mypassword") + .proxyAuthScheme(authScheme) + .username(username) + .password(password) .build(); channelPoolMap = AwaitCloseChannelPoolMap.builder() @@ -233,6 +324,7 @@ public void usingProxy_withAuth() { .protocol(Protocol.HTTP1_1) .maxStreams(100) .sslProvider(SslProvider.OPENSSL) + .negotiateAuthConfig(negotiateAuthConfig) .build(); SimpleChannelPoolAwareChannelPool simpleChannelPoolAwareChannelPool = channelPoolMap.newPool( @@ -244,9 +336,11 @@ public void usingProxy_withAuth() { assertThat(requests).contains("CONNECT some-awesome-service:443"); - String authB64 = Base64.getEncoder().encodeToString("myuser:mypassword".getBytes(CharsetUtil.UTF_8)); - String authHeaderValue = String.format("Basic %s", authB64); - assertThat(requests).contains(String.format("proxy-authorization: %s", authHeaderValue)); + if (proxyAuthHeader == null) { + assertThat(requests).doesNotContain("proxy-authorization:"); + } else { + assertThat(requests).contains(String.format("proxy-authorization: %s", proxyAuthHeader)); + } } @Test @@ -309,4 +403,14 @@ public void releaseChannel_autoReadEnabled() { assertThat(channel.config().isAutoRead()).isTrue(); } + private static Stream proxyAuthTestParams() { + return Stream.of( + Arguments.of(null, null, null, null), + Arguments.of(null, "user", "pass", "Basic dXNlcjpwYXNz"), + Arguments.of(ProxyAuthScheme.BASIC, "user", "pass", "Basic dXNlcjpwYXNz"), + Arguments.of(ProxyAuthScheme.NEGOTIATE, null, null, "Negotiate YII"), + Arguments.of(ProxyAuthScheme.NEGOTIATE, "user", "pass", "Negotiate YII") + + ); + } } diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGeneratorTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGeneratorTest.java new file mode 100644 index 000000000000..99ea7397bd94 --- /dev/null +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/BasicProxyAuthGeneratorTest.java @@ -0,0 +1,69 @@ +/* + * 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.http.nio.netty.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.http.ProxyAuthScheme; + +public class BasicProxyAuthGeneratorTest { + private static final String USERNAME = "user"; + private static final String PASSWORD = "pass"; + + private final BasicProxyAuthGenerator authGenerator = new BasicProxyAuthGenerator(USERNAME, PASSWORD); + + @ParameterizedTest(name = "username = {0}, password = {1}, expected error = {2}") + @MethodSource("invalidCtorParams") + void ctor_paramsInvalid_throws(String username, String password, String errorMessage) { + assertThatThrownBy(() -> new BasicProxyAuthGenerator(username, password)) + .hasMessageContaining(errorMessage); + } + + @Test + void scheme_returnsCorrectValue() { + assertThat(authGenerator.scheme()).isEqualTo(ProxyAuthScheme.BASIC); + } + + @Test + void generateAuthParams_generatedCorrectly() { + String expected = Base64.getEncoder() + .encodeToString(String.format("%s:%s", USERNAME, PASSWORD) + .getBytes(StandardCharsets.UTF_8)); + + assertThat(authGenerator.generateAuthParams(URI.create("http://amazon.com")).join()).isEqualTo(expected); + } + + private static Stream invalidCtorParams() { + return Stream.of( + Arguments.of(null, null, "username"), + Arguments.of("", "", "username"), + Arguments.of(null, PASSWORD, "username"), + Arguments.of("", PASSWORD, "username"), + Arguments.of(USERNAME, null, "password"), + Arguments.of(USERNAME, "", "password") + + ); + } +} diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java index d43b404f3f5f..b06eee6eaadc 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/Http1TunnelConnectionPoolTest.java @@ -42,6 +42,8 @@ import io.netty.util.concurrent.Promise; import java.io.IOException; import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; import java.util.concurrent.CountDownLatch; import javax.net.ssl.SSLEngine; @@ -73,6 +75,8 @@ public class Http1TunnelConnectionPoolTest { private static final String PROXY_PASSWORD = "mypassword"; + private static final ProxyAuthGenerator basicAuth = new BasicProxyAuthGenerator(PROXY_USER, PROXY_PASSWORD); + @Mock private ChannelPool delegatePool; @@ -115,7 +119,7 @@ public static void teardown() { @Test public void tunnelAlreadyEstablished_doesNotAddInitHandler() { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, configuration); when(mockAttr.get()).thenReturn(true); @@ -127,7 +131,7 @@ public void tunnelAlreadyEstablished_doesNotAddInitHandler() { @Test(timeout = 1000) public void tunnelNotEstablished_addsInitHandler() throws InterruptedException { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, configuration); when(mockAttr.get()).thenReturn(false); @@ -149,7 +153,7 @@ public void tunnelInitFails_acquireFutureFails() { }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS,null, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); + HTTP_PROXY_ADDRESS,null, REMOTE_ADDRESS, mockHandler, supplier, configuration); Future acquireFuture = tunnelPool.acquire(); @@ -164,7 +168,7 @@ public void tunnelInitSucceeds_acquireFutureSucceeds() { }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); Future acquireFuture = tunnelPool.acquire(); @@ -174,7 +178,7 @@ public void tunnelInitSucceeds_acquireFutureSucceeds() { @Test public void acquireFromDelegatePoolFails_failsFuture() { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, configuration); when(delegatePool.acquire(any(Promise.class))).thenReturn(GROUP.next().newFailedFuture(new IOException("boom"))); @@ -197,7 +201,7 @@ public void sslContextProvided_andProxyUsingHttps_addsSslHandler() { }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, mockSslCtx, - HTTPS_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); + HTTPS_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); tunnelPool.acquire().awaitUninterruptibly(); @@ -218,7 +222,7 @@ public void sslContextProvided_andProxyNotUsingHttps_doesNotAddSslHandler() { }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, mockSslCtx, - HTTP_PROXY_ADDRESS, null, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, supplier, configuration); tunnelPool.acquire().awaitUninterruptibly(); @@ -231,7 +235,7 @@ public void sslContextProvided_andProxyNotUsingHttps_doesNotAddSslHandler() { @Test public void release_releasedToDelegatePool() { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS,null, REMOTE_ADDRESS, mockHandler, configuration); tunnelPool.release(mockChannel); verify(delegatePool).release(eq(mockChannel), any(Promise.class)); } @@ -239,7 +243,7 @@ public void release_releasedToDelegatePool() { @Test public void release_withGivenPromise_releasedToDelegatePool() { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, configuration); Promise mockPromise = mock(Promise.class); tunnelPool.release(mockChannel, mockPromise); verify(delegatePool).release(eq(mockChannel), eq(mockPromise)); @@ -248,7 +252,7 @@ public void release_withGivenPromise_releasedToDelegatePool() { @Test public void close_closesDelegatePool() { Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, REMOTE_ADDRESS, mockHandler, configuration); + HTTP_PROXY_ADDRESS, null, REMOTE_ADDRESS, mockHandler, configuration); tunnelPool.close(); verify(delegatePool).close(); } @@ -257,42 +261,33 @@ public void close_closesDelegatePool() { public void proxyAuthProvided_addInitHandler_withAuth(){ TestInitHandlerData data = new TestInitHandlerData(); - Http1TunnelConnectionPool.InitHandlerSupplier supplier = (srcPool, proxyUser, proxyPassword, remoteAddr, initFuture) -> { + Http1TunnelConnectionPool.InitHandlerSupplier supplier = + (srcPool, proxyEndpoint, proxyAuthGenerator, remoteAddr, initFuture) -> { initFuture.setSuccess(mockChannel); - data.proxyUser(proxyUser); - data.proxyPassword(proxyPassword); + data.authHeader = proxyAuthGenerator.generateAuthParams(proxyEndpoint).join(); return mock(ChannelHandler.class); }; Http1TunnelConnectionPool tunnelPool = new Http1TunnelConnectionPool(GROUP.next(), delegatePool, null, - HTTP_PROXY_ADDRESS, PROXY_USER, PROXY_PASSWORD, REMOTE_ADDRESS, mockHandler, supplier, configuration); + HTTP_PROXY_ADDRESS, basicAuth, REMOTE_ADDRESS, mockHandler, supplier, configuration); tunnelPool.acquire().awaitUninterruptibly(); - assertThat(data.proxyUser()).isEqualTo(PROXY_USER); - assertThat(data.proxyPassword()).isEqualTo(PROXY_PASSWORD); - + String expectedAuthHeader = Base64.getEncoder().encodeToString((PROXY_USER + ":" + PROXY_PASSWORD) + .getBytes(StandardCharsets.UTF_8)); + assertThat(data.authHeader()).isEqualTo(expectedAuthHeader); } private static class TestInitHandlerData { - private String proxyUser; - private String proxyPassword; - - public void proxyUser(String proxyUser) { - this.proxyUser = proxyUser; - } - - public String proxyUser() { - return this.proxyUser; - } + private String authHeader; - public void proxyPassword(String proxyPassword) { - this.proxyPassword = proxyPassword; + public void authHeader(String authHeader) { + this.authHeader = authHeader; } - public String proxyPassword(){ - return this.proxyPassword; + public String authHeader() { + return authHeader; } } diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGeneratorTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGeneratorTest.java new file mode 100644 index 000000000000..97f2c3c2f4e1 --- /dev/null +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/NegotiateProxyAuthGeneratorTest.java @@ -0,0 +1,186 @@ +/* + * 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.http.nio.netty.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicReference; +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; +import org.apache.kerby.kerberos.kerb.KrbException; +import org.apache.kerby.kerberos.kerb.client.KrbClient; +import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer; +import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.testutils.FileUtils; + +public class NegotiateProxyAuthGeneratorTest { + private static final String KRB5_PROP = "java.security.krb5.conf"; + private static final String EXECUTOR_THREAD_NAME = "test-proxy-auth"; + private static final ExecutorService executor = + Executors.newSingleThreadExecutor(r -> new Thread(r, EXECUTOR_THREAD_NAME)); + private static Path tempDir; + private static Path keytabFile; + private static Path ccacheFile; + private static int port; + + private static SimpleKdcServer kdc; + private static String krb5PropSave; + + private static Configuration config; + + @BeforeAll + static void setup() throws IOException, KrbException { + tempDir = Files.createTempDirectory(null); + keytabFile = tempDir.resolve("keytab"); + ccacheFile = tempDir.resolve("ccache"); + + try (Socket freePort = new Socket()) { + freePort.setReuseAddress(true); + freePort.bind(new InetSocketAddress(0)); + port = freePort.getLocalPort(); + + kdc = new SimpleKdcServer(); + kdc.setKdcRealm("EXAMPLE.COM"); + kdc.setKdcHost("localhost"); + kdc.setWorkDir(tempDir.toFile()); + kdc.setKdcTcpPort(port); + kdc.setAllowUdp(false); + kdc.init(); + + krb5PropSave = System.getProperty(KRB5_PROP); + + System.setProperty(KRB5_PROP, tempDir.resolve("krb5.conf").toAbsolutePath().toString()); + + kdc.start(); + + kdc.createPrincipal("alice@EXAMPLE.COM", "alicePassword"); + kdc.createAndExportPrincipals(keytabFile.toFile(), "HTTP/localhost@EXAMPLE.COM"); + + // initialize the ticket cache + KrbClient krbClient = kdc.getKrbClient(); + TgtTicket tgt = krbClient.requestTgt("alice@EXAMPLE.COM", "alicePassword"); + krbClient.storeTicket(tgt, ccacheFile.toFile()); + + // Override config so we look at the testing cache instead of the real system cache + config = new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + Map opts = new HashMap<>(); + opts.put("useTicketCache", "true"); + opts.put("ticketCache", ccacheFile.toAbsolutePath().toString()); + opts.put("doNotPrompt", "true"); + opts.put("refreshKrb5Config", "true"); + return new AppConfigurationEntry[] { + new AppConfigurationEntry( + "com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, opts) + }; + } + }; + } + + } + + @AfterAll + static void teardown() throws KrbException { + executor.shutdownNow(); + if (krb5PropSave != null) { + System.setProperty(KRB5_PROP, krb5PropSave); + } else { + System.clearProperty(KRB5_PROP); + } + kdc.stop(); + FileUtils.cleanUpTestDirectory(tempDir); + } + + @Test + void generateAuthParams_configValid_successfullyGeneratesToken() { + NegotiateProxyAuthGenerator authGenerator = new NegotiateProxyAuthGenerator(config, executor); + + URI proxyEndpoint = URI.create("https://localhost:8192"); + + assertThat(authGenerator.generateAuthParams(proxyEndpoint).join()).startsWith("YII"); + } + + @Test + void generateAuthParams_ticketCacheMissing_failsWithActionableMessage() { + Configuration missingCacheConfig = new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + Map opts = new HashMap<>(); + opts.put("useTicketCache", "true"); + opts.put("ticketCache", tempDir.resolve("nonexistent-cache").toAbsolutePath().toString()); + opts.put("doNotPrompt", "true"); + opts.put("refreshKrb5Config", "true"); + return new AppConfigurationEntry[] { + new AppConfigurationEntry( + "com.sun.security.auth.module.Krb5LoginModule", + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, opts) + }; + } + }; + + NegotiateProxyAuthGenerator authGenerator = new NegotiateProxyAuthGenerator(missingCacheConfig, executor); + + assertThatThrownBy(() -> authGenerator.generateAuthParams(URI.create("https://localhost:8192")).join()) + .isInstanceOf(CompletionException.class) + .hasCauseInstanceOf(RuntimeException.class) + .hasMessageContaining("kinit") + .hasMessageContaining("ticket cache"); + } + + @Test + void generateAuthParams_runsOnSuppliedExecutor() { + AtomicReference loginThread = new AtomicReference<>(); + Configuration recordingConfig = new Configuration() { + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + loginThread.set(Thread.currentThread()); + return config.getAppConfigurationEntry(name); + } + }; + + new NegotiateProxyAuthGenerator(recordingConfig, executor).generateAuthParams(URI.create("https://localhost:8192")) + .join(); + + // The blocking Kerberos work must never run on the caller's thread, which in production is a Netty event loop. + assertThat(loginThread.get()).isNotSameAs(Thread.currentThread()); + assertThat(loginThread.get().getName()).isEqualTo(EXECUTOR_THREAD_NAME); + } + + @Test + void constructor_nullExecutor_throws() { + assertThatThrownBy(() -> new NegotiateProxyAuthGenerator(config, null)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("executor"); + } + +} diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java index 9836a953bda9..8bc20a165b25 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/ProxyTunnelInitHandlerTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.http.nio.netty.internal; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -41,10 +42,12 @@ import io.netty.handler.ssl.SslCloseCompletionEvent; import io.netty.handler.ssl.SslHandler; import io.netty.util.CharsetUtil; +import io.netty.util.concurrent.EventExecutor; import io.netty.util.concurrent.Promise; import java.io.IOException; import java.net.URI; import java.util.Base64; +import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import org.junit.AfterClass; import org.junit.Before; @@ -53,6 +56,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.http.ProxyAuthScheme; /** * Unit tests for {@link ProxyTunnelInitHandler}. @@ -95,7 +99,8 @@ public void addedToPipeline_addsCodec() { Supplier codecSupplier = () -> codec; when(mockCtx.name()).thenReturn("foo"); - ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, null, null, REMOTE_HOST, null, codecSupplier); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, null, null, null, REMOTE_HOST, null, + codecSupplier); handler.handlerAdded(mockCtx); verify(mockPipeline).addBefore(eq("foo"), eq(null), eq(codec)); @@ -202,7 +207,7 @@ public void handlerRemoved_removesCodec() { } @Test - public void handledAdded_writesRequest_withoutAuth() { + public void handlerAdded_writesRequest_withoutAuth() { Promise promise = GROUP.next().newPromise(); ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, REMOTE_HOST, promise); handler.handlerAdded(mockCtx); @@ -219,7 +224,7 @@ public void handledAdded_writesRequest_withoutAuth() { } @Test - public void handledAdded_writesRequest_withAuth() { + public void handlerAdded_writesRequest_withAuth() { Promise promise = GROUP.next().newPromise(); ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, PROXY_USER, PROXY_PASSWORD, REMOTE_HOST, promise); handler.handlerAdded(mockCtx); @@ -238,6 +243,71 @@ public void handledAdded_writesRequest_withAuth() { assertThat(requestCaptor.getValue()).isEqualTo(expectedRequest); } + @Test + public void handlerAdded_authParamsGeneratorThrows_failsFuture() { + ProxyAuthGenerator authGenerator = mock(ProxyAuthGenerator.class); + when(authGenerator.generateAuthParams(any(URI.class))).thenThrow(new RuntimeException("auth generator error")); + + Promise promise = GROUP.next().newPromise(); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, URI.create("https://amazon.com"), + authGenerator, + REMOTE_HOST, + promise); + handler.handlerAdded(mockCtx); + + assertThatThrownBy(promise::get).hasMessageContaining("Unable to send CONNECT request to proxy") + .hasRootCauseMessage("auth generator error"); + } + + @Test + public void handlerAdded_authParamsCompleteAsynchronously_writesRequestOnceParamsAvailable() throws Exception { + CompletableFuture authParams = new CompletableFuture<>(); + ProxyAuthGenerator authGenerator = mock(ProxyAuthGenerator.class); + when(authGenerator.scheme()).thenReturn(ProxyAuthScheme.NEGOTIATE); + when(authGenerator.generateAuthParams(any(URI.class))).thenReturn(authParams); + + EventExecutor executor = GROUP.next(); + when(mockCtx.executor()).thenReturn(executor); + + Promise promise = GROUP.next().newPromise(); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, URI.create("https://proxy.com"), + authGenerator, REMOTE_HOST, promise); + handler.handlerAdded(mockCtx); + + // The calling thread must not have waited for the auth params, so nothing is written yet. + verify(mockChannel, never()).writeAndFlush(any()); + + authParams.complete("token"); + // Drain the executor so the queued continuation has run. + executor.submit(() -> { }).get(); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpRequest.class); + verify(mockChannel).writeAndFlush(requestCaptor.capture()); + assertThat(requestCaptor.getValue().headers().get(HttpHeaderNames.PROXY_AUTHORIZATION)).isEqualTo("Negotiate token"); + } + + @Test + public void handlerAdded_authParamsFailAsynchronously_failsFuture() throws Exception { + CompletableFuture authParams = new CompletableFuture<>(); + ProxyAuthGenerator authGenerator = mock(ProxyAuthGenerator.class); + when(authGenerator.generateAuthParams(any(URI.class))).thenReturn(authParams); + + EventExecutor executor = GROUP.next(); + when(mockCtx.executor()).thenReturn(executor); + + Promise promise = GROUP.next().newPromise(); + ProxyTunnelInitHandler handler = new ProxyTunnelInitHandler(mockChannelPool, URI.create("https://proxy.com"), + authGenerator, REMOTE_HOST, promise); + handler.handlerAdded(mockCtx); + + authParams.completeExceptionally(new RuntimeException("auth generator error")); + executor.submit(() -> { }).get(); + + verify(mockChannel, never()).writeAndFlush(any()); + assertThatThrownBy(promise::get).hasMessageContaining("Unable to send CONNECT request to proxy") + .hasRootCauseMessage("auth generator error"); + } + private void successResponse(ProxyTunnelInitHandler handler) { DefaultHttpResponse resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); handler.channelRead(mockCtx, resp); diff --git a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerPublisherVerificationTest.java b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerPublisherVerificationTest.java index 06199aaa58ca..ca9bd0a2d833 100644 --- a/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerPublisherVerificationTest.java +++ b/http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/internal/nrs/HandlerPublisherVerificationTest.java @@ -57,7 +57,7 @@ public class HandlerPublisherVerificationTest extends PublisherVerification#7271: when a request carries + * {@code Expect: 100-continue}, {@link HttpStreamsClientHandler} defers subscribing the {@link HandlerSubscriber} to the + * body until the server answers {@code 100 Continue}. A {@code channelWritabilityChanged} event fired during that window + * used to dereference the still-null subscription and throw. + */ +public class HandlerSubscriberExpectContinueTest { + + private EmbeddedChannel channel; + private ExceptionCapturingHandler exceptionCapture; + + @BeforeEach + public void setup() { + channel = new EmbeddedChannel(new HttpStreamsClientHandler()); + exceptionCapture = new ExceptionCapturingHandler(); + channel.pipeline().addLast(exceptionCapture); + } + + @AfterEach + public void teardown() { + channel.finishAndReleaseAll(); + } + + @Test + public void channelWritabilityChanged_whenSubscriptionPending_doesNotRouteExceptionToPipeline() { + writeExpectContinueRequest(new SingleChunkPublisher("body")); + + channel.pipeline().fireChannelWritabilityChanged(); + + assertThat(exceptionCapture.captured()).isNull(); + } + + @Test + public void channelWritabilityChanged_whenSubscriptionPending_bodyStreamsAfter100Continue() { + SingleChunkPublisher body = new SingleChunkPublisher("body"); + writeExpectContinueRequest(body); + + channel.pipeline().fireChannelWritabilityChanged(); + deliver100Continue(); + + assertThat(body.subscribed()).isTrue(); + assertThat(streamedBody()).isEqualTo("body"); + assertThat(exceptionCapture.captured()).isNull(); + } + + private void writeExpectContinueRequest(Publisher body) { + DefaultStreamedHttpRequest request = + new DefaultStreamedHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.PUT, "/", body); + HttpUtil.set100ContinueExpected(request, true); + channel.writeOutbound(request); + } + + private void deliver100Continue() { + HttpResponse continueResponse = + new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE); + channel.writeInbound(continueResponse); + channel.runPendingTasks(); + } + + private String streamedBody() { + StringBuilder body = new StringBuilder(); + Object msg; + while ((msg = channel.readOutbound()) != null) { + if (msg instanceof HttpContent) { + body.append(((HttpContent) msg).content().toString(UTF_8)); + } + } + return body.toString(); + } + + private static final class ExceptionCapturingHandler extends ChannelInboundHandlerAdapter { + private final AtomicReference captured = new AtomicReference<>(); + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + captured.compareAndSet(null, cause); + } + + Throwable captured() { + return captured.get(); + } + } + + private static final class SingleChunkPublisher implements Publisher { + private final byte[] payload; + private final AtomicBoolean subscribed = new AtomicBoolean(false); + + private SingleChunkPublisher(String payload) { + this.payload = payload.getBytes(UTF_8); + } + + boolean subscribed() { + return subscribed.get(); + } + + @Override + public void subscribe(Subscriber subscriber) { + subscribed.set(true); + subscriber.onSubscribe(new Subscription() { + private boolean delivered; + + @Override + public void request(long n) { + if (n <= 0 || delivered) { + return; + } + delivered = true; + ByteBuf buf = Unpooled.wrappedBuffer(payload); + subscriber.onNext(new DefaultHttpContent(buf)); + subscriber.onComplete(); + } + + @Override + public void cancel() { + delivered = true; + } + }); + } + } +} diff --git a/http-clients/pom.xml b/http-clients/pom.xml index dbfca0245666..8494e0d0378a 100644 --- a/http-clients/pom.xml +++ b/http-clients/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/http-clients/url-connection-client/pom.xml b/http-clients/url-connection-client/pom.xml index 02b1c5c2e126..5f4c999ee0c7 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/ProxyConfiguration.java b/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/ProxyConfiguration.java index 8ca88eb36320..db1b91ffdcab 100644 --- a/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/ProxyConfiguration.java +++ b/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/ProxyConfiguration.java @@ -219,11 +219,18 @@ public interface Builder extends CopyableBuilder { /** * Configure the hosts that the client is allowed to access without going through the proxy. + *

    Entries supplied here are treated as exact host names (e.g. {@code example.com}) or CIDR ranges for IP addresses + * (e.g. {@code 10.0.0.0/8}). Wildcard patterns such as {@code *.example.com} or a bare {@code *} are not supported for + * entries supplied here; to use wildcards, configure them through the {@code http.nonProxyHosts} system property or the + * {@code NO_PROXY} environment variable instead. */ Builder nonProxyHosts(Set nonProxyHosts); /** * Add a host that the client is allowed to access without going through the proxy. + *

    The host is treated as an exact host name or CIDR range; wildcard patterns are not supported for entries supplied + * here. See {@link #nonProxyHosts(Set)} for details on wildcard support through the system property or environment + * variable. * * @see ProxyConfiguration#nonProxyHosts() */ @@ -236,6 +243,11 @@ public interface Builder extends CopyableBuilder { * are not provided during building the {@link ProxyConfiguration} object. To disable this behavior, set this value to * "false".It is important to note that when this property is set to "true," all proxy settings will exclusively originate * from system properties, and no partial settings will be obtained from EnvironmentVariableValues + *

    Pipe-separated host names in the {@code http.nonProxyHosts} system property indicate multiple hosts to exclude + * from proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com|b.com"} and + * {@code "a.com | b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). */ Builder useSystemPropertyValues(Boolean useSystemPropertyValues); @@ -246,7 +258,10 @@ public interface Builder extends CopyableBuilder { * value to "false".It is important to note that when this property is set to "true," all proxy settings will exclusively * originate from environment variableValues, and no partial settings will be obtained from SystemPropertyValues. *

    Comma-separated host names in the NO_PROXY environment variable indicate multiple hosts to exclude from - * proxy settings. + * proxy settings. Surrounding empty spaces around each host name are trimmed, so both {@code "a.com,b.com"} and + * {@code "a.com, b.com"} are accepted. Each entry may be an exact host name (e.g. {@code example.com}), a + * leading-wildcard suffix (e.g. {@code *.example.com}, which matches {@code example.com} and its subdomains), + * a single {@code *} (which matches all hosts), or a CIDR range for IP addresses (e.g. {@code 10.0.0.0/8}). * * @param useEnvironmentVariablesValues The option whether to use environment variable values * @return This object for method chaining. diff --git a/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.java b/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.java index 6537ec24753a..87009f29d999 100644 --- a/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.java +++ b/http-clients/url-connection-client/src/main/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClient.java @@ -28,6 +28,7 @@ import java.io.UncheckedIOException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; +import java.net.ProtocolException; import java.net.Proxy; import java.net.URI; import java.nio.charset.StandardCharsets; @@ -42,7 +43,6 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; -import java.util.function.Supplier; import java.util.stream.Collectors; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; @@ -318,23 +318,23 @@ public HttpExecuteResponse call() throws IOException { return HttpExecuteResponse.builder() .response(SdkHttpResponse.builder() - .statusCode(responseCode) - .statusText(connection.getResponseMessage()) - // TODO: Don't ignore abort? - .headers(extractHeaders(connection)) - .build()) + .statusCode(responseCode) + .statusText(connection.getResponseMessage()) + // TODO: Don't ignore abort? + .headers(extractHeaders(connection)) + .build()) .responseBody(responseBody) .build(); } - private Optional tryGetOutputStream() { - return getAndHandle100Bug(() -> invokeSafely(connection::getOutputStream), false); + private Optional tryGetOutputStream() throws IOException { + return getAndHandle100Bug(connection::getOutputStream, false); } - private Optional tryGetInputStream() { + private Optional tryGetInputStream() throws IOException { return responseHasNoContent() ? Optional.empty() - : getAndHandle100Bug(() -> invokeSafely(connection::getInputStream), true); + : getAndHandle100Bug(connection::getInputStream, true); } private Optional tryGetErrorStream() { @@ -361,16 +361,13 @@ private Optional tryGetErrorStream() { * non-failure cases (2xx, 3xx) or log and return the response without the payload for failure cases (4xx or 5xx) * . * + *

    + * Convert stream-accessor NPEs to checked {@link IOException}s so the retry policy can evaluate them. */ - private Optional getAndHandle100Bug(Supplier supplier, boolean failOn100Bug) { + private Optional getAndHandle100Bug(IoSupplier supplier, boolean failOn100Bug) throws IOException { try { return Optional.ofNullable(supplier.get()); - } catch (RuntimeException e) { - if (e.getCause() instanceof NullPointerException) { - throw new UncheckedIOException(new IOException( - "Unexpected NullPointerException when calling HttpURLConnection", e)); - } - + } catch (ProtocolException e) { if (!exceptionCausedBy100HandlingBug(e)) { throw e; } @@ -385,18 +382,44 @@ private Optional getAndHandle100Bug(Supplier supplier, boolean failOn1 return Optional.empty(); } - int responseCode = invokeSafely(connection::getResponseCode); + int responseCode = getResponseCodeSafely(connection); String message = "Unable to read response payload, because service returned response code " + responseCode + " to an Expect: 100-continue request. Using another HTTP client " + "implementation (e.g. Apache) removes this limitation."; throw new UncheckedIOException(new IOException(message, e)); + } catch (RuntimeException e) { + if (isNpeOrDirectlyWrapsNpe(e)) { + throw logAndConvertNpe(e); + } + throw e; } } - private boolean exceptionCausedBy100HandlingBug(RuntimeException e) { + /** + * Matches the bare and directly wrapped NPE forms emitted by HttpURLConnection stream accessors. + */ + private static boolean isNpeOrDirectlyWrapsNpe(RuntimeException e) { + return e instanceof NullPointerException || e.getCause() instanceof NullPointerException; + } + + private IOException logAndConvertNpe(RuntimeException e) { + log.debug(() -> "Converting NPE from HttpURLConnection implementation " + + connection.getClass().getName() + " to IOException for retry evaluation", e); + return new IOException("Unexpected NullPointerException when calling HttpURLConnection", e); + } + + private boolean exceptionCausedBy100HandlingBug(ProtocolException e) { return requestWasExpect100Continue() && e.getMessage() != null && - e.getMessage().startsWith("java.net.ProtocolException: Server rejected operation"); + e.getMessage().startsWith("Server rejected operation"); + } + + /** + * Supplies a value without converting checked {@link IOException}s to runtime exceptions. + */ + @FunctionalInterface + private interface IoSupplier { + T get() throws IOException; } private Boolean requestWasExpect100Continue() { @@ -406,11 +429,11 @@ private Boolean requestWasExpect100Continue() { .orElse(false); } - private boolean responseHasNoContent() { + private boolean responseHasNoContent() throws IOException { // We cannot account for chunked encoded responses, because we only have access to headers and response code here, // so we assume chunked encoded responses DO have content. if (responseHasNoContent == null) { - responseHasNoContent = responseNeverHasPayload(invokeSafely(connection::getResponseCode)) || + responseHasNoContent = responseNeverHasPayload(getResponseCodeSafely(connection)) || Objects.equals(connection.getHeaderField("Content-Length"), "0") || Objects.equals(connection.getRequestMethod(), "HEAD"); } @@ -422,13 +445,9 @@ private boolean responseNeverHasPayload(int responseCode) { } /** - * {@link sun.net.www.protocol.http.HttpURLConnection#getInputStream0()} has been observed to intermittently throw - * {@link NullPointerException}s for reasons that still require further investigation, but are assumed to be due to a - * bug in the JDK. Propagating such NPEs is confusing for users and are not subject to being retried on by the default - * retry policy configuration, so instead we bias towards propagating these as {@link IOException}s. - *

    - * TODO: Determine precise root cause of intermittent NPEs, submit JDK bug report if applicable, and consider applying - * this behavior only on unpatched JVM runtime versions. + * Converts NPEs from {@link HttpURLConnection#getResponseCode()} to checked {@link IOException}s so the retry + * policy can evaluate them. These NPEs can occur when + * {@link HttpURLConnection#disconnect()} races with response access. */ private static int getResponseCodeSafely(HttpURLConnection connection) throws IOException { Validate.paramNotNull(connection, "connection"); diff --git a/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientRetryTest.java b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientRetryTest.java new file mode 100644 index 000000000000..5483a4dd22cc --- /dev/null +++ b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientRetryTest.java @@ -0,0 +1,227 @@ +/* + * 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.http.urlconnection; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; +import static utils.HttpTestUtils.executionContext; +import static utils.HttpTestUtils.testClientConfiguration; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URL; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; +import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; +import software.amazon.awssdk.core.retry.RetryPolicy; +import software.amazon.awssdk.core.retry.backoff.BackoffStrategy; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; + +public class UrlConnectionHttpClientRetryTest { + @Test + void execute_whenOutputStreamThrowsBareNpe_retriesRequest() { + verifyOutputStreamFailureIsRetried(() -> { + throw new NullPointerException("this.http is null"); + }); + } + + @Test + void execute_whenOutputStreamThrowsWrappedNpe_retriesRequest() { + verifyOutputStreamFailureIsRetried(() -> { + throw new RuntimeException(new NullPointerException("this.http is null")); + }); + } + + @Test + void execute_whenOutputStreamThrowsIOException_retriesRequest() { + verifyOutputStreamFailureIsRetried(() -> { + throw new IOException("connection closed"); + }); + } + + @Test + void execute_whenInputStreamThrowsBareNpe_retriesRequest() { + AtomicInteger attempts = new AtomicInteger(); + SdkHttpClient transport = UrlConnectionHttpClient.create(uri -> new StubHttpURLConnection(toUrl(uri)) { + @Override + public InputStream getInputStream() { + if (attempts.incrementAndGet() == 1) { + throw new NullPointerException("this.http is null"); + } + return new ByteArrayInputStream(new byte[0]); + } + + // Ensure responseHasNoContent() proceeds to getInputStream(). + @Override + public String getHeaderField(String name) { + return null; + } + }); + + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost/test")) + .method(SdkHttpMethod.GET) + .build(); + verifyFailureIsRetried(transport, request, attempts); + } + + @Test + void execute_whenResponseCodeCheckBeforeInputStreamThrowsIOException_retriesRequest() { + AtomicInteger attempts = new AtomicInteger(); + AtomicInteger responseCodeCalls = new AtomicInteger(); + SdkHttpClient transport = UrlConnectionHttpClient.create(uri -> { + attempts.incrementAndGet(); + return new StubHttpURLConnection(toUrl(uri)) { + @Override + public int getResponseCode() throws IOException { + if (responseCodeCalls.incrementAndGet() == 2) { + throw new IOException("connection closed"); + } + return HTTP_OK; + } + }; + }); + + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost/test")) + .method(SdkHttpMethod.GET) + .build(); + verifyFailureIsRetried(transport, request, attempts); + } + + private void verifyOutputStreamFailureIsRetried(IoRunnable firstAttemptFailure) { + AtomicInteger attempts = new AtomicInteger(); + SdkHttpClient transport = UrlConnectionHttpClient.create(uri -> new StubHttpURLConnection(toUrl(uri)) { + @Override + public OutputStream getOutputStream() throws IOException { + if (attempts.incrementAndGet() == 1) { + firstAttemptFailure.run(); + } + return super.getOutputStream(); + } + }); + + SdkHttpFullRequest request = SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost/test")) + .method(SdkHttpMethod.PUT) + .putHeader("Content-Length", "1") + .contentStreamProvider(() -> new ByteArrayInputStream(new byte[1])) + .build(); + verifyFailureIsRetried(transport, request, attempts); + } + + private void verifyFailureIsRetried(SdkHttpClient transport, + SdkHttpFullRequest request, + AtomicInteger attempts) { + RetryPolicy retryPolicy = RetryPolicy.builder() + .numRetries(1) + .backoffStrategy(BackoffStrategy.none()) + .throttlingBackoffStrategy(BackoffStrategy.none()) + .build(); + AmazonSyncHttpClient client = new AmazonSyncHttpClient( + testClientConfiguration().toBuilder() + .option(SdkClientOption.SYNC_HTTP_CLIENT, transport) + .option(SdkClientOption.RETRY_POLICY, retryPolicy) + .build()); + try { + client.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); + } finally { + client.close(); + } + + assertThat(attempts.get()).isEqualTo(2); + } + + private static URL toUrl(URI uri) { + try { + return uri.toURL(); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + @FunctionalInterface + private interface IoRunnable { + void run() throws IOException; + } + + private static class StubHttpURLConnection extends HttpURLConnection { + private StubHttpURLConnection(URL url) { + super(url); + } + + @Override + public void connect() { + connected = true; + } + + @Override + public void disconnect() { + connected = false; + } + + @Override + public boolean usingProxy() { + return false; + } + + @Override + public OutputStream getOutputStream() throws IOException { + return new ByteArrayOutputStream(); + } + + @Override + public InputStream getInputStream() { + return null; + } + + @Override + public int getResponseCode() throws IOException { + return HTTP_OK; + } + + @Override + public String getResponseMessage() { + return "OK"; + } + + @Override + public String getHeaderField(String name) { + return "Content-Length".equals(name) ? "0" : null; + } + + @Override + public Map> getHeaderFields() { + return Collections.emptyMap(); + } + } +} diff --git a/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientWithCustomCreateWireMockTest.java b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientWithCustomCreateWireMockTest.java index 55b4410c6f36..d658370821f5 100644 --- a/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientWithCustomCreateWireMockTest.java +++ b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionHttpClientWithCustomCreateWireMockTest.java @@ -14,14 +14,14 @@ */ package software.amazon.awssdk.http.urlconnection; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import static software.amazon.awssdk.utils.FunctionalUtils.safeFunction; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.UncheckedIOException; import java.net.HttpURLConnection; import java.net.ProtocolException; import java.net.URL; @@ -29,10 +29,12 @@ import java.util.List; import java.util.Map; import java.util.function.Function; +import org.apache.logging.log4j.Level; import org.junit.Ignore; import org.junit.Test; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.SdkHttpClientTestSuite; +import software.amazon.awssdk.testutils.LogCaptor; public final class UrlConnectionHttpClientWithCustomCreateWireMockTest extends SdkHttpClientTestSuite { @@ -100,7 +102,9 @@ public OutputStream getOutputStream() { }); assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) - .isInstanceOf(UncheckedIOException.class); + .isInstanceOf(IOException.class) + .hasMessage("Unexpected NullPointerException when calling HttpURLConnection") + .hasCauseInstanceOf(RuntimeException.class); } @Test @@ -113,7 +117,118 @@ public InputStream getInputStream() { }); assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) - .isInstanceOf(UncheckedIOException.class); + .isInstanceOf(IOException.class) + .hasMessage("Unexpected NullPointerException when calling HttpURLConnection") + .hasCauseInstanceOf(RuntimeException.class); + } + + @Test + public void testGetOutputStreamBareNpeIsWrappedAsIo() throws Exception { + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public OutputStream getOutputStream() { + throw new NullPointerException("this.http is null"); + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) + .isInstanceOf(IOException.class) + .hasMessage("Unexpected NullPointerException when calling HttpURLConnection") + .hasCauseInstanceOf(NullPointerException.class); + } + + @Test + public void testGetInputStreamBareNpeIsWrappedAsIo() throws Exception { + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public InputStream getInputStream() { + throw new NullPointerException("this.http is null"); + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) + .isInstanceOf(IOException.class) + .hasMessage("Unexpected NullPointerException when calling HttpURLConnection") + .hasCauseInstanceOf(NullPointerException.class); + } + + @Test + public void testGetOutputStreamStacklessNpeIsWrappedAsIo() throws Exception { + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public OutputStream getOutputStream() { + throw stacklessNpe(); + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) + .isInstanceOf(IOException.class) + .hasCauseInstanceOf(NullPointerException.class); + } + + @Test + public void testGetOutputStreamUnrelatedNpeIsWrappedAsIo() throws Exception { + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public OutputStream getOutputStream() { + throw new NullPointerException("custom connection failure"); + } + }); + + try (LogCaptor logCaptor = LogCaptor.create(Level.DEBUG)) { + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)) + .isInstanceOf(IOException.class) + .hasCauseInstanceOf(NullPointerException.class); + assertThat(logCaptor.loggedEvents()).anySatisfy(logEvent -> + assertThat(logEvent.getMessage().getFormattedMessage()) + .contains("Converting NPE from HttpURLConnection implementation") + .contains("to IOException for retry evaluation")); + } + } + + @Test + public void testGetOutputStreamNonNpeRuntimeExceptionIsNotWrapped() throws Exception { + RuntimeException expected = new IllegalStateException("custom connection failure"); + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public OutputStream getOutputStream() { + throw expected; + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)).isSameAs(expected); + } + + @Test + public void testGetOutputStreamIOExceptionRemainsChecked() throws Exception { + IOException expected = new IOException("connection closed"); + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public OutputStream getOutputStream() throws IOException { + throw expected; + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)).isSameAs(expected); + } + + @Test + public void testGetInputStreamIOExceptionRemainsChecked() throws Exception { + IOException expected = new IOException("connection closed"); + connectionInterceptor = safeFunction(connection -> new DelegateHttpURLConnection(connection) { + @Override + public InputStream getInputStream() throws IOException { + throw expected; + } + }); + + assertThatThrownBy(() -> testForResponseCode(HttpURLConnection.HTTP_OK)).isSameAs(expected); + } + + private static NullPointerException stacklessNpe() { + NullPointerException result = new NullPointerException(); + result.setStackTrace(new StackTraceElement[0]); + return result; } private class DelegateHttpURLConnection extends HttpURLConnection { diff --git a/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionSslHandshakeBehaviorTest.java b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionSslHandshakeBehaviorTest.java new file mode 100644 index 000000000000..13ee6c728f97 --- /dev/null +++ b/http-clients/url-connection-client/src/test/java/software/amazon/awssdk/http/urlconnection/UrlConnectionSslHandshakeBehaviorTest.java @@ -0,0 +1,26 @@ +/* + * 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.http.urlconnection; + +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpClientSslHandshakeBehaviorTestSuite; + +public class UrlConnectionSslHandshakeBehaviorTest extends SdkHttpClientSslHandshakeBehaviorTestSuite { + @Override + protected SdkHttpClient createSdkHttpClient() { + return UrlConnectionHttpClient.builder().build(); + } +} diff --git a/metric-publishers/cloudwatch-metric-publisher/pom.xml b/metric-publishers/cloudwatch-metric-publisher/pom.xml index 709a607ce9d4..6732f0d9d21a 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudwatch-metric-publisher diff --git a/metric-publishers/emf-metric-logging-publisher/pom.xml b/metric-publishers/emf-metric-logging-publisher/pom.xml index 67a6b7d384f8..7a04241dad29 100644 --- a/metric-publishers/emf-metric-logging-publisher/pom.xml +++ b/metric-publishers/emf-metric-logging-publisher/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk metric-publishers - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT emf-metric-logging-publisher diff --git a/metric-publishers/pom.xml b/metric-publishers/pom.xml index 3971372c9808..6b0b388883e2 100644 --- a/metric-publishers/pom.xml +++ b/metric-publishers/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT metric-publishers diff --git a/pom.xml b/pom.xml index 739c750d6a16..e1672a6947af 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pom AWS Java SDK :: Parent The Amazon Web Services SDK for Java provides Java APIs @@ -74,6 +74,7 @@ third-party v2-migration test/http-client-tests + test/warmup-tests test/protocol-tests test/protocol-tests-core test/service-test-utils @@ -88,9 +89,8 @@ test/sdk-native-image-test test/s3-benchmarks test/auth-tests - test/region-testing test/ruleset-testing-core - test/old-client-version-compatibility-test + test/service-client-backward-compat-test test/bundle-logging-bridge-binding-test test/v2-migration-tests test/bundle-shading-tests @@ -104,11 +104,11 @@ ${project.version} - 2.47.4 - 2.47.3 - 2.21.4 - 2.21.5 - 2.21.4 + 2.55.4 + 2.55.3 + 2.21.7 + 2.21.6 + 2.21.7 2.21 1.0.1 3.14.0 @@ -119,7 +119,7 @@ 3.15.1 - 4.1.135.Final + 4.1.138.Final 3.4.6 1.3 UTF-8 @@ -131,7 +131,7 @@ 3.1.5 1.17.1 1.37 - 0.46.1 + 0.48.4 5.10.3 @@ -144,7 +144,7 @@ 1.1 7.1.0 2.6 - 2.0.78.Final + 2.0.84.Final 1.25.0 1.0.392 1.0.16.RELEASE @@ -152,6 +152,7 @@ 1.17.5 1.3.0 1.5.4 + 2.0.3 3.1.2 @@ -189,7 +190,7 @@ 1.8 4.5.13 4.4.16 - 5.6.2 + 5.6.4 5.4.3 1.0.4 @@ -213,6 +214,15 @@ + + + + org.reactivestreams + reactive-streams-tck + ${reactive-streams.version} + test + @@ -302,6 +312,13 @@ **/*TestCase.java ${skip.unit.tests} + + + + junit + false + + @@ -310,6 +327,11 @@ surefire-junit-platform ${maven.surefire.version} + + org.apache.maven.surefire + surefire-testng + ${maven.surefire.version} + @@ -646,7 +668,6 @@ *.internal.* software.amazon.awssdk.thirdparty.* software.amazon.awssdk.regions.* - software.amazon.awssdk.core.client.handler.ClientExecutionParams true diff --git a/release-scripts/pom.xml b/release-scripts/pom.xml index b2093b2ec5af..2065f959171f 100644 --- a/release-scripts/pom.xml +++ b/release-scripts/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml release-scripts @@ -83,5 +83,15 @@ log4j-slf4j-impl runtime + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + diff --git a/release-scripts/src/main/java/software/amazon/awssdk/release/UpdateServiceMain.java b/release-scripts/src/main/java/software/amazon/awssdk/release/UpdateServiceMain.java index cc55cd880f92..a8f427cafeb3 100644 --- a/release-scripts/src/main/java/software/amazon/awssdk/release/UpdateServiceMain.java +++ b/release-scripts/src/main/java/software/amazon/awssdk/release/UpdateServiceMain.java @@ -36,8 +36,14 @@ --service-module-name service-module-name --service-json /path/to/service-2.json [--paginators-json /path/to/paginators-1.json - --waiters-json /path/to/waiters-2.json]" + --waiters-json /path/to/waiters-2.json + --endpoint-rule-set-json /path/to/endpoint-rule-set.json + --endpoint-tests-json /path/to/endpoint-tests.json + --endpoint-bdd-json /path/to/endpoint-bdd-1.json]" * + * + *

    The endpoint model is either the BDD model or the rule set, never both: when {@code --endpoint-bdd-json} names an + * existing file it is copied and {@code --endpoint-rule-set-json} is ignored, otherwise the rule set is copied. */ public class UpdateServiceMain extends Cli { private static final Logger log = Logger.loggerFor(UpdateServiceMain.class); @@ -49,8 +55,12 @@ private UpdateServiceMain() { requiredOption("service-json", "The service-2.json file for the service."), optionalOption("paginators-json", "The paginators-1.json file for the service."), optionalOption("waiters-json", "The waiters-2.json file for the service."), - optionalOption("endpoint-rule-set-json", "The endpoint-rule-set.json file for the service."), - optionalOption("endpoint-tests-json", "The endpoint-tests.json file for the service.")); + optionalOption("endpoint-rule-set-json", "The endpoint-rule-set.json file for the service. Ignored when " + + "endpoint-bdd-json is given and points at an existing file."), + optionalOption("endpoint-tests-json", "The endpoint-tests.json file for the service."), + optionalOption("endpoint-bdd-json", "The endpoint-bdd-1.json file for the service. When present it is " + + "the endpoint model used for the service, and " + + "endpoint-rule-set-json is ignored.")); } public static void main(String[] args) { @@ -71,6 +81,7 @@ private static class ServiceUpdater { private final Path waitersJson; private final Path endpointRuleSetJson; private final Path endpointTestsJson; + private final Path endpointBddJson; private ServiceUpdater(CommandLine commandLine) { this.mavenProjectRoot = Paths.get(commandLine.getOptionValue("maven-project-root").trim()); @@ -81,6 +92,7 @@ private ServiceUpdater(CommandLine commandLine) { this.waitersJson = optionalPath(commandLine.getOptionValue("waiters-json")); this.endpointRuleSetJson = optionalPath(commandLine.getOptionValue("endpoint-rule-set-json")); this.endpointTestsJson = optionalPath(commandLine.getOptionValue("endpoint-tests-json")); + this.endpointBddJson = optionalPath(commandLine.getOptionValue("endpoint-bdd-json")); } private Path optionalPath(String path) { @@ -99,10 +111,34 @@ public void run() throws Exception { copyFile(serviceJson, codegenFileLocation.resolve("service-2.json")); copyFile(paginatorsJson, codegenFileLocation.resolve("paginators-1.json")); copyFile(waitersJson, codegenFileLocation.resolve("waiters-2.json")); - copyFile(endpointRuleSetJson, codegenFileLocation.resolve("endpoint-rule-set.json")); + copyEndpointModel(codegenFileLocation); copyFile(endpointTestsJson, codegenFileLocation.resolve("endpoint-tests.json")); } + /** + * Copies whichever endpoint model drives codegen for this service. A BDD model supersedes the rule set, so + * when one is available it is copied and {@code endpoint-rule-set-json} is ignored; otherwise the rule set is + * copied as before. + */ + private void copyEndpointModel(Path codegenFileLocation) throws IOException { + if (endpointBddJson != null && Files.isRegularFile(endpointBddJson)) { + log.info(() -> "Using endpoint BDD model " + endpointBddJson + " for " + serviceModuleName + + "; ignoring endpoint-rule-set-json."); + copyFile(endpointBddJson, codegenFileLocation.resolve("endpoint-bdd-1.json")); + return; + } + + if (endpointRuleSetJson == null) { + log.info(() -> "No endpoint BDD model available for " + serviceModuleName + + " and endpoint-rule-set-json is not set; leaving the endpoint model unchanged."); + return; + } + + log.info(() -> "No endpoint BDD model available for " + serviceModuleName + + "; using endpoint rule set " + endpointRuleSetJson + "."); + copyFile(endpointRuleSetJson, codegenFileLocation.resolve("endpoint-rule-set.json")); + } + private Path codegenFileLocation(String serviceModuleName, String serviceId) { Path codegenPath = mavenProjectRoot.resolve("services") diff --git a/release-scripts/src/test/java/software/amazon/awssdk/release/UpdateServiceMainTest.java b/release-scripts/src/test/java/software/amazon/awssdk/release/UpdateServiceMainTest.java new file mode 100644 index 000000000000..7cd3e3f237c8 --- /dev/null +++ b/release-scripts/src/test/java/software/amazon/awssdk/release/UpdateServiceMainTest.java @@ -0,0 +1,282 @@ +/* + * 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.release; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +/** + * Covers how {@link UpdateServiceMain} copies model files into a service's {@code codegen-resources} directory, and in + * particular which of the two endpoint models it copies. + * + *

    A BDD model supersedes the rule set: when {@code --endpoint-bdd-json} names an existing file, that file is the + * endpoint model for the service and {@code --endpoint-rule-set-json} is ignored. Only when no BDD model is available + * does the rule set get copied. + * + *

    Driven through {@code main} rather than by calling the copy helper directly, so the option registration and the + * destination path are covered too. An unregistered option would leave the argument silently ignored, which no test of + * the helper alone would catch. + */ +class UpdateServiceMainTest { + + @Test + void endpointBddJson_available_isCopiedEvenWhenNotAlreadyPresent(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.run(); + + assertThat(fixture.destination("endpoint-bdd-1.json")).hasContent(Fixture.BDD_CONTENT); + } + + @Test + void endpointBddJson_available_overwritesAStaleModel(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + fixture.writeDestination("endpoint-bdd-1.json", "{\"stale\": true}"); + + fixture.run(); + + assertThat(fixture.destination("endpoint-bdd-1.json")).hasContent(Fixture.BDD_CONTENT); + } + + /** + * The rule set is ignored rather than refreshed when a BDD model wins, so a checked-in rule set is left exactly as + * it was instead of being updated from the release. + */ + @Test + void endpointBddJson_available_leavesTheRuleSetAlone(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + fixture.writeDestination("endpoint-rule-set.json", "{\"untouched\": true}"); + + fixture.run(); + + assertThat(fixture.destination("endpoint-rule-set.json")).hasContent("{\"untouched\": true}"); + } + + @Test + void endpointBddJson_available_doesNotCreateARuleSet(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.run(); + + assertThat(fixture.destination("endpoint-rule-set.json")) + .as("the rule set is ignored when a BDD model is available") + .doesNotExist(); + } + + @Test + void endpointBddJson_argumentOmitted_copiesTheRuleSet(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.withoutEndpointBddArgument().run(); + + assertThat(fixture.destination("endpoint-rule-set.json")).hasContent(Fixture.RULE_SET_CONTENT); + assertThat(fixture.destination("endpoint-bdd-1.json")).doesNotExist(); + } + + /** + * Upstream does not publish a BDD model for every service, so the argument can point at a path that was never + * written. That falls back to the rule set rather than failing or leaving the service without an endpoint model. + */ + @Test + void endpointBddJson_sourceMissing_copiesTheRuleSet(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.withMissingEndpointBddSource().run(); + + assertThat(fixture.destination("endpoint-rule-set.json")).hasContent(Fixture.RULE_SET_CONTENT); + assertThat(fixture.destination("endpoint-bdd-1.json")).doesNotExist(); + } + + /** + * The BDD copy is on the source, not the destination, so omitting the argument leaves an existing model alone + * rather than deleting or emptying it. + */ + @Test + void endpointBddJson_argumentOmitted_leavesAnExistingModelAlone(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + fixture.writeDestination("endpoint-bdd-1.json", "{\"kept\": true}"); + + fixture.withoutEndpointBddArgument().run(); + + assertThat(fixture.destination("endpoint-bdd-1.json")).hasContent("{\"kept\": true}"); + } + + @Test + void bothEndpointModelArgumentsOmitted_isNotAnError(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.withoutEndpointBddArgument().withoutEndpointRuleSetArgument().run(); + + assertThat(fixture.destination("service-2.json")).hasContent(Fixture.SERVICE_CONTENT); + assertThat(fixture.destination("endpoint-bdd-1.json")).doesNotExist(); + assertThat(fixture.destination("endpoint-rule-set.json")).doesNotExist(); + } + + /** + * The other model files keep their unconditional behaviour. A service legitimately gains waiters or endpoint tests + * for the first time, and those must land on the release that carries them. + */ + @Test + void otherModelFiles_areCopiedEvenWhenNotAlreadyPresent(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp); + + fixture.run(); + + assertThat(fixture.destination("service-2.json")).hasContent(Fixture.SERVICE_CONTENT); + assertThat(fixture.destination("paginators-1.json")).exists(); + assertThat(fixture.destination("waiters-2.json")).exists(); + assertThat(fixture.destination("endpoint-tests.json")).exists(); + } + + /** + * Endpoint tests are copied regardless of which endpoint model was chosen; they are not part of the BDD/rule set + * decision. + */ + @Test + void endpointTestsJson_isCopiedWithEitherEndpointModel(@TempDir Path tmp) throws Exception { + Fixture withBdd = new Fixture(tmp.resolve("bdd")); + Fixture withRuleSet = new Fixture(tmp.resolve("ruleSet")); + + withBdd.run(); + withRuleSet.withoutEndpointBddArgument().run(); + + assertThat(withBdd.destination("endpoint-tests.json")).exists(); + assertThat(withRuleSet.destination("endpoint-tests.json")).exists(); + } + + /** + * DynamoDB's models live in a nested directory, so this checks the endpoint model lands in the same resolved + * destination the other files use rather than the module root. + */ + @Test + void endpointBddJson_isCopiedToTheResolvedNestedDestination(@TempDir Path tmp) throws Exception { + Fixture fixture = new Fixture(tmp, "dynamodb", "DynamoDB", "dynamodb"); + + fixture.run(); + + assertThat(fixture.destination("endpoint-bdd-1.json")).hasContent(Fixture.BDD_CONTENT); + assertThat(tmp.resolve("project/services/dynamodb/src/main/resources/codegen-resources/endpoint-bdd-1.json")) + .as("the nested service must not also get a copy at the module root") + .doesNotExist(); + } + + private static final class Fixture { + private static final String BDD_CONTENT = "{\"version\": \"1.0\", \"nodes\": \"AAAA\"}"; + private static final String RULE_SET_CONTENT = "{\"version\": \"1.0\"}"; + private static final String SERVICE_CONTENT = "{\"metadata\": {}}"; + + private final Path projectRoot; + private final Path sourceDir; + private final Path destinationDir; + private final String serviceModuleName; + private final String serviceId; + private boolean includeEndpointBddArgument = true; + private boolean includeEndpointRuleSetArgument = true; + private String endpointBddSourceName = "endpoint-bdd-1.json"; + + private Fixture(Path tmp) throws IOException { + this(tmp, "myservice", "MyService", null); + } + + private Fixture(Path tmp, String serviceModuleName, String serviceId, String nestedDir) throws IOException { + this.projectRoot = tmp.resolve("project"); + this.sourceDir = tmp.resolve("source"); + this.serviceModuleName = serviceModuleName; + this.serviceId = serviceId; + + Path codegenResources = projectRoot.resolve("services") + .resolve(serviceModuleName) + .resolve("src") + .resolve("main") + .resolve("resources") + .resolve("codegen-resources"); + this.destinationDir = nestedDir == null ? codegenResources : codegenResources.resolve(nestedDir); + Files.createDirectories(destinationDir); + Files.createDirectories(sourceDir); + + write(sourceDir.resolve("service-2.json"), SERVICE_CONTENT); + write(sourceDir.resolve("paginators-1.json"), "{\"pagination\": {}}"); + write(sourceDir.resolve("waiters-2.json"), "{\"waiters\": {}}"); + write(sourceDir.resolve("endpoint-rule-set.json"), RULE_SET_CONTENT); + write(sourceDir.resolve("endpoint-tests.json"), "{\"testCases\": []}"); + write(sourceDir.resolve("endpoint-bdd-1.json"), BDD_CONTENT); + } + + private Fixture withoutEndpointBddArgument() { + this.includeEndpointBddArgument = false; + return this; + } + + private Fixture withoutEndpointRuleSetArgument() { + this.includeEndpointRuleSetArgument = false; + return this; + } + + private Fixture withMissingEndpointBddSource() { + this.endpointBddSourceName = "no-such-endpoint-bdd-1.json"; + return this; + } + + private void writeDestination(String name, String content) throws IOException { + write(destinationDir.resolve(name), content); + } + + private Path destination(String name) { + return destinationDir.resolve(name); + } + + private void run() { + List args = new ArrayList<>(); + args.add("--maven-project-root"); + args.add(projectRoot.toString()); + args.add("--service-module-name"); + args.add(serviceModuleName); + args.add("--service-id"); + args.add(serviceId); + args.add("--service-json"); + args.add(sourceDir.resolve("service-2.json").toString()); + args.add("--paginators-json"); + args.add(sourceDir.resolve("paginators-1.json").toString()); + args.add("--waiters-json"); + args.add(sourceDir.resolve("waiters-2.json").toString()); + args.add("--endpoint-tests-json"); + args.add(sourceDir.resolve("endpoint-tests.json").toString()); + if (includeEndpointRuleSetArgument) { + args.add("--endpoint-rule-set-json"); + args.add(sourceDir.resolve("endpoint-rule-set.json").toString()); + } + if (includeEndpointBddArgument) { + args.add("--endpoint-bdd-json"); + args.add(sourceDir.resolve(endpointBddSourceName).toString()); + } + + UpdateServiceMain.main(args.toArray(new String[0])); + } + + private static void write(Path path, String content) throws IOException { + Files.createDirectories(path.getParent()); + Files.write(path, content.getBytes(UTF_8)); + } + } +} diff --git a/scripts/changelog/writer.py b/scripts/changelog/writer.py index ef714a81b021..7babff7bc96c 100644 --- a/scripts/changelog/writer.py +++ b/scripts/changelog/writer.py @@ -14,6 +14,8 @@ class ChangelogWriter(object): - ... - ### __Bugfixes__ - ... + - ### __Performance Improvements__ + - ... - ### __Deprecations__ - ... """ @@ -28,6 +30,7 @@ def write_changes(self, changes): self.write_category_header(s) self.write_items_for_category(s, self.features, "Features") self.write_items_for_category(s, self.bugfixes, "Bugfixes") + self.write_items_for_category(s, self.perf_improvements, "Performance Improvements") self.write_items_for_category(s, self.deprecations, "Deprecations") self.write_items_for_category(s, self.removals, "Removals") self.write_items_for_category(s, self.documentations, "Documentations") @@ -57,6 +60,7 @@ def process_changes(self, changes): def reset_maps(self): self.features = {} self.bugfixes = {} + self.perf_improvements = {} self.deprecations = {} self.removals = {} self.documentations = {} @@ -113,6 +117,8 @@ def get_map_for_type(self, t): return self.features elif t == 'bugfix': return self.bugfixes + elif t == 'perf-improvement': + return self.perf_improvements elif t == 'deprecation': return self.deprecations elif t == 'removal': diff --git a/scripts/new-change b/scripts/new-change index 093a9edafaea..39de0d12f435 100755 --- a/scripts/new-change +++ b/scripts/new-change @@ -16,7 +16,8 @@ To generate a new changelog entry:: This will open up a file in your editor (via the ``EDITOR`` env var). You'll see this template:: - # Type should be one of: feature, bugfix, deprecation, removal, documentation + # Type should be one of: feature, bugfix, perf-improvement, deprecation, + # removal, documentation type: {change_type} # The marketing name of the service this change applies to @@ -52,8 +53,10 @@ CHANGES_DIR = os.path.join( '.changes' ) CHANGE_PARTS = ['type', 'category', 'description'] +VALID_CHANGE_TYPES = ['feature', 'bugfix', 'perf-improvement', 'deprecation', + 'removal', 'documentation'] TEMPLATE = """\ -# Type should be one of: feature, bugfix, deprecation, removal, documentation +# Type should be one of: {valid_types} type: {change_type} # The marketing name of the service this change applies to @@ -107,6 +110,7 @@ def all_values_provided(args): def get_values_from_editor(args): with tempfile.NamedTemporaryFile('w') as f: contents = TEMPLATE.format( + valid_types=', '.join(VALID_CHANGE_TYPES), change_type=args.change_type, category=args.category, description=args.description, @@ -189,9 +193,8 @@ def parse_filled_in_contents(contents): continue if 'type' not in parsed and line.startswith('type:'): t = line[len('type:'):].strip() - if t not in ['feature', 'bugfix', 'deprecation', 'removal', - 'documentation']: - raise Exception("Unsupported category %s" % t) + if t not in VALID_CHANGE_TYPES: + raise Exception("Unsupported type %s" % t) parsed['type'] = t elif 'category' not in parsed and line.startswith('category:'): parsed['category'] = line[len('category:'):].strip() @@ -211,8 +214,7 @@ def parse_filled_in_contents(contents): def main(): parser = argparse.ArgumentParser() parser.add_argument('-t', '--type', dest='change_type', - default='', choices=('bugfix', 'feature', - 'deprecation', 'documentation')) + default='', choices=VALID_CHANGE_TYPES) parser.add_argument('-c', '--category', dest='category', default='') parser.add_argument('-u', '--contributor', dest='contributor', diff --git a/services-custom/dynamodb-enhanced/pom.xml b/services-custom/dynamodb-enhanced/pom.xml index 3fd9b2889505..09616cd2fd2b 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dynamodb-enhanced AWS Java SDK :: DynamoDB :: Enhanced Client diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/AsyncSearchVectorsIntegrationTest.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/AsyncSearchVectorsIntegrationTest.java new file mode 100644 index 000000000000..9606237f5ad9 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/AsyncSearchVectorsIntegrationTest.java @@ -0,0 +1,169 @@ +/* + * 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.enhanced.dynamodb; + +import java.util.List; +import java.util.function.Consumer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorRecord; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class AsyncSearchVectorsIntegrationTest extends SearchVectorsIntegrationTestBase { + + private static final String TABLE_NAME = SHARED_ASYNC_TABLE_NAME; + private DynamoDbAsyncClient asyncClient; + private DynamoDbEnhancedAsyncClient enhancedAsyncClient; + private DynamoDbAsyncTable mappedTable; + + @BeforeAll + void setup() { + asyncClient = createAsyncSearchVectorsClient(); + enhancedAsyncClient = DynamoDbEnhancedAsyncClient + .builder().dynamoDbClient(asyncClient).build(); + mappedTable = enhancedAsyncClient.table( + TABLE_NAME, VECTOR_TABLE_SCHEMA); + + prepareAsyncSharedTable( + asyncClient, + TABLE_NAME, + () -> mappedTable.createTable(createTableRequest()).join(), + () -> testRecords().forEach(r -> mappedTable.putItem(r).join()), + () -> mappedTable.vectorIndex(COSINE_INDEX) + .searchVectorsWithResponse(sharedTableSearchReadyRequest()).join() + .results()); + prepareDedicatedIntegrationTablesOnce(); + } + + @AfterAll + void teardown() { + asyncClient.close(); + } + + @Override + protected String sharedTableName() { + return TABLE_NAME; + } + + @Override + protected DescribeTableResponse describeTable(String tableName) { + return asyncClient.describeTable(r -> r.tableName(tableName)).join(); + } + + @Override + protected List> executeSearch(String index, SearchVectorsEnhancedRequest request) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(request).join().results(); + } + + @Override + protected void executePut(VectorRecord record) { + mappedTable.putItem(record).join(); + } + + @Override + protected void executeDelete(Key key) { + mappedTable.deleteItem(key).join(); + } + + @Override + protected List> executeSearchDocument(String index, + SearchVectorsEnhancedRequest request, + DocumentTableSchema schema) { + DynamoDbAsyncTable docTable = enhancedAsyncClient.table(TABLE_NAME, schema); + return docTable.vectorIndex(index).searchVectorsWithResponse(request).join().results(); + } + + @Override + protected SearchVectorsEnhancedResponse executeSearchWithResponse(String index, + SearchVectorsEnhancedRequest request) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(request).join(); + } + + @Override + protected List> executeSearchWithBuilder( + String index, Consumer builder) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(builder).join().results(); + } + + @Override + protected SearchVectorsEnhancedResponse executeSearchWithResponseBuilder( + String index, Consumer builder) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(builder).join(); + } + + @Override + protected void executeTempTableCreate(String tempTableName, + TableSchema schema, + CreateTableEnhancedRequest request) { + enhancedAsyncClient.table(tempTableName, schema).createTable(request).join(); + asyncClient.waiter().waitUntilTableExists(r -> r.tableName(tempTableName)).join(); + } + + @Override + protected void createAndWaitForDedicatedTable(String tableName, + StaticTableSchema schema, + List indexes) { + DynamoDbAsyncTable table = enhancedAsyncClient.table(tableName, schema); + table.createTable(CreateTableEnhancedRequest.builder().vectorIndexes(indexes).build()).join(); + asyncClient.waiter().waitUntilTableExists(r -> r.tableName(tableName)).join(); + } + + @Override + protected void deleteDedicatedTable(String tableName) { + asyncClient.deleteTable(r -> r.tableName(tableName)).join(); + } + + @Override + protected void dedicatedPutItem(String tableName, + StaticTableSchema schema, + VectorRecord record) { + enhancedAsyncClient.table(tableName, schema).putItem(record).join(); + } + + @Override + protected VectorRecord dedicatedGetItem(String tableName, + StaticTableSchema schema, + Key key) { + return enhancedAsyncClient.table(tableName, schema).getItem(key).join(); + } + + @Override + protected List> dedicatedSearch(String tableName, + StaticTableSchema schema, + String indexName, + SearchVectorsEnhancedRequest request) { + return enhancedAsyncClient.table(tableName, schema).vectorIndex(indexName) + .searchVectorsWithResponse(request).join().results(); + } + + @Override + protected SearchVectorsResponse executeLowLevelSearchVectors(SearchVectorsRequest request) { + return asyncClient.searchVectors(request).join(); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysImmutableSchemaIntegrationTest.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysImmutableSchemaIntegrationTest.java index 36f2f3a9690e..505baca2cca6 100644 --- a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysImmutableSchemaIntegrationTest.java +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysImmutableSchemaIntegrationTest.java @@ -30,6 +30,7 @@ import java.time.Instant; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -67,12 +68,32 @@ public static void teardown() { } } + private static final List GSI_NAMES = Arrays.asList("gsi1", "gsi2", "gsi3"); + private static void waitForGsiConsistency() { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + int expectedCount = COMPOSITE_RECORDS.size(); + for (String gsiName : GSI_NAMES) { + waitForGsiPropagation(gsiName, expectedCount); + } + } + + private static void waitForGsiPropagation(String gsiName, int expectedCount) { + for (int attempt = 0; attempt < 20; attempt++) { + int count = dynamoDbClient.scan(r -> r.tableName(mappedTable.tableName()) + .indexName(gsiName) + .limit(expectedCount + 1)) + .items().size(); + if (count >= expectedCount) { + return; + } + try { + Thread.sleep(Math.min(500L << Math.min(attempt, 3), 2_000L)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } } + throw new AssertionError("GSI propagation timed out for " + gsiName); } private static final java.util.List COMPOSITE_RECORDS = Arrays.asList( diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysIntegrationTestBase.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysIntegrationTestBase.java index 3e3a2c70211c..f284d529189b 100644 --- a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysIntegrationTestBase.java +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/QueryGSICompositeKeysIntegrationTestBase.java @@ -30,6 +30,7 @@ import java.time.Instant; import java.util.Arrays; import java.util.Iterator; +import java.util.List; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import software.amazon.awssdk.enhanced.dynamodb.model.CompositeKeyRecord; @@ -84,12 +85,32 @@ protected static void insertRecords() { COMPOSITE_RECORDS.forEach(record -> mappedTable.putItem(r -> r.item(record))); } + private static final List GSI_NAMES = Arrays.asList("gsi1", "gsi2", "gsi3", "gsi4", "gsi5", "gsi6"); + protected static void waitForGsiConsistency() { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); + int expectedCount = COMPOSITE_RECORDS.size(); + for (String gsiName : GSI_NAMES) { + waitForGsiPropagation(gsiName, expectedCount); + } + } + + private static void waitForGsiPropagation(String gsiName, int expectedCount) { + for (int attempt = 0; attempt < 20; attempt++) { + int count = dynamoDbClient.scan(r -> r.tableName(mappedTable.tableName()) + .indexName(gsiName) + .limit(expectedCount + 1)) + .items().size(); + if (count >= expectedCount) { + return; + } + try { + Thread.sleep(Math.min(500L << Math.min(attempt, 3), 2_000L)); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } } + throw new AssertionError("GSI propagation timed out for " + gsiName); } private static CompositeKeyRecord createRecord(String id, String sort, String pk1, Integer pk2, String pk3, diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsBeanSchemaIntegrationTest.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsBeanSchemaIntegrationTest.java new file mode 100644 index 000000000000..c77389e318d0 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsBeanSchemaIntegrationTest.java @@ -0,0 +1,835 @@ +/* + * 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.enhanced.dynamodb; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.InlineFilterOnlyVectorRecordBean; +import software.amazon.awssdk.enhanced.dynamodb.model.InlineFilterOnlyVectorRecordImmutable; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorRecordBean; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorRecordImmutable; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.IndexStatus; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.VectorIndexDescription; + +/** + * Integration tests verifying that bean and immutable annotation-driven vector index schemas produce correct tables at DynamoDB + * and support end-to-end search operations. + * + *

    These tests complement the existing {@link SearchVectorsIntegrationTestBase} suite, which + * exercises the {@code StaticTableSchema} path exclusively. The focus here is: + *

      + *
    • No-arg {@code createTable()} derives vector indexes from annotation metadata
    • + *
    • {@code describeTable()} returns correct vector index configuration
    • + *
    • Put + search round-trip works through the annotation path
    • + *
    + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class SearchVectorsBeanSchemaIntegrationTest extends DynamoDbEnhancedIntegrationTestBase { + + private static final String COSINE_INDEX = "cosine-index"; + private static final String FILTER_ONLY_INDEX = "filter-only-index"; + + private static final String BEAN_SHARED_SYNC_TABLE = "JavaTests-SearchVectors-Bean-Shared-Sync"; + private static final String BEAN_SHARED_ASYNC_TABLE = "JavaTests-SearchVectors-Bean-Shared-Async"; + private static final String BEAN_INLINE_FILTER_TABLE = "JavaTests-SearchVectors-Bean-FilterOnly"; + + private static final int QUICK_SEARCH_RETRY_ATTEMPTS = 3; + private static final int TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS = 20; + private static final int VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS = 30; + private static final int TABLE_DELETION_WAIT_ATTEMPTS = 30; + + private static final ConcurrentHashMap SHARED_TABLE_SETUP_LOCKS = new ConcurrentHashMap<>(); + private static final Set SEARCH_READY_TABLES = ConcurrentHashMap.newKeySet(); + private static volatile boolean beanMetadataVerified; + private static volatile boolean inlineFilterMetadataVerified; + + private static final float[] QUERY_VECTOR = {0.95f, 0.05f, 0.0f, 0.0f}; + private static final float[] EXACT_MATCH_VECTOR = {1.0f, 0.0f, 0.0f, 0.0f}; + private static final float[] ORTHOGONAL_VECTOR = {0.0f, 1.0f, 0.0f, 0.0f}; + + private static final TableSchema BEAN_SCHEMA = + BeanTableSchema.create(VectorRecordBean.class); + private static final TableSchema IMMUTABLE_SCHEMA = + ImmutableTableSchema.create(VectorRecordImmutable.class); + private static final TableSchema INLINE_FILTER_ONLY_BEAN_SCHEMA = + BeanTableSchema.create(InlineFilterOnlyVectorRecordBean.class); + private static final TableSchema INLINE_FILTER_ONLY_IMMUTABLE_SCHEMA = + ImmutableTableSchema.create(InlineFilterOnlyVectorRecordImmutable.class); + + private DynamoDbClient dynamoDbClient; + private DynamoDbEnhancedClient enhancedClient; + private DynamoDbAsyncClient asyncClient; + private DynamoDbEnhancedAsyncClient enhancedAsyncClient; + + private DynamoDbTable beanSyncTable; + private DynamoDbTable immutableSyncTable; + private DynamoDbTable inlineFilterBeanTable; + private DynamoDbTable inlineFilterImmutableTable; + private DynamoDbAsyncTable beanAsyncTable; + + @BeforeAll + void setup() { + dynamoDbClient = createDynamoDbClient(); + enhancedClient = DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build(); + asyncClient = createAsyncDynamoDbClient(); + enhancedAsyncClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(asyncClient).build(); + + beanSyncTable = enhancedClient.table(BEAN_SHARED_SYNC_TABLE, BEAN_SCHEMA); + immutableSyncTable = enhancedClient.table(BEAN_SHARED_SYNC_TABLE, IMMUTABLE_SCHEMA); + inlineFilterBeanTable = enhancedClient.table(BEAN_INLINE_FILTER_TABLE, INLINE_FILTER_ONLY_BEAN_SCHEMA); + inlineFilterImmutableTable = enhancedClient.table(BEAN_INLINE_FILTER_TABLE, INLINE_FILTER_ONLY_IMMUTABLE_SCHEMA); + beanAsyncTable = enhancedAsyncClient.table(BEAN_SHARED_ASYNC_TABLE, BEAN_SCHEMA); + + prepareSyncSharedBeanTable(); + prepareAsyncSharedBeanTable(); + prepareInlineFilterOnlyTable(); + } + + @AfterAll + void teardown() { + try { + asyncClient.close(); + } finally { + dynamoDbClient.close(); + } + } + + private void prepareSyncSharedBeanTable() { + prepareSyncSharedTable( + dynamoDbClient, + BEAN_SHARED_SYNC_TABLE, + () -> beanSyncTable.createTable(), + () -> beanSyncSeedRecords().forEach(beanSyncTable::putItem), + () -> beanSyncTable.vectorIndex(COSINE_INDEX) + .searchVectorsWithResponse(beanScienceSearchRequest()) + .results()); + } + + private void prepareAsyncSharedBeanTable() { + prepareAsyncSharedTable( + asyncClient, + BEAN_SHARED_ASYNC_TABLE, + () -> beanAsyncTable.createTable().join(), + () -> beanAsyncSeedRecords().forEach(record -> beanAsyncTable.putItem(record).join()), + () -> beanAsyncTable.vectorIndex(COSINE_INDEX) + .searchVectorsWithResponse(beanScienceSearchRequest()).join() + .results()); + } + + private void prepareInlineFilterOnlyTable() { + synchronized (sharedTableSetupLock(BEAN_INLINE_FILTER_TABLE)) { + if (SEARCH_READY_TABLES.contains(BEAN_INLINE_FILTER_TABLE)) { + return; + } + + Supplier>> search = + () -> inlineFilterBeanTable.vectorIndex(FILTER_ONLY_INDEX) + .searchVectorsWithResponse(inlineFilterScienceSearchRequest()) + .results(); + + if (sharedTableConfigured(dynamoDbClient, BEAN_INLINE_FILTER_TABLE)) { + if (!awaitSearchResultCount(search, 1, QUICK_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + SEARCH_READY_TABLES.add(BEAN_INLINE_FILTER_TABLE); + return; + } + inlineFilterSeedRecords().forEach(inlineFilterBeanTable::putItem); + if (!awaitSearchResultCount(search, 1, QUICK_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + SEARCH_READY_TABLES.add(BEAN_INLINE_FILTER_TABLE); + return; + } + recreateSyncSharedTable(dynamoDbClient, BEAN_INLINE_FILTER_TABLE, + () -> inlineFilterBeanTable.createTable()); + } else { + inlineFilterBeanTable.createTable(); + dynamoDbClient.waiter().waitUntilTableExists(r -> r.tableName(BEAN_INLINE_FILTER_TABLE)); + } + + waitForVectorIndexesActive(dynamoDbClient, BEAN_INLINE_FILTER_TABLE, 1); + inlineFilterSeedRecords().forEach(inlineFilterBeanTable::putItem); + awaitTableSearchReady(search, 1); + SEARCH_READY_TABLES.add(BEAN_INLINE_FILTER_TABLE); + } + } + + private static void prepareSyncSharedTable(DynamoDbClient client, + String tableName, + Runnable createTable, + Runnable seedTable, + Supplier>> search) { + synchronized (sharedTableSetupLock(tableName)) { + prepareSharedTable( + () -> sharedTableConfigured(client, tableName), + () -> recreateSyncSharedTable(client, tableName, createTable), + () -> waitForVectorIndexesActive(client, tableName, 1), + seedTable, + search); + SEARCH_READY_TABLES.add(tableName); + } + } + + private static void prepareAsyncSharedTable(DynamoDbAsyncClient client, + String tableName, + Runnable createTable, + Runnable seedTable, + Supplier>> search) { + synchronized (sharedTableSetupLock(tableName)) { + prepareSharedTable( + () -> sharedTableConfigured(client, tableName), + () -> recreateAsyncSharedTable(client, tableName, createTable), + () -> waitForVectorIndexesActive(client, tableName, 1), + seedTable, + search); + SEARCH_READY_TABLES.add(tableName); + } + } + + private static Object sharedTableSetupLock(String tableName) { + return SHARED_TABLE_SETUP_LOCKS.computeIfAbsent(tableName, ignored -> new Object()); + } + + private static void prepareSharedTable(Supplier tableConfigured, + Runnable recreateTable, + Runnable waitForIndexes, + Runnable seedTable, + Supplier>> search) { + if (tableConfigured.get()) { + if (!awaitSearchResultCount(search, 1, QUICK_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + return; + } + seedTable.run(); + if (!awaitSearchResultCount(search, 1, QUICK_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + return; + } + recreateTable.run(); + waitForIndexes.run(); + seedTable.run(); + awaitTableSearchReady(search, 1); + return; + } + + recreateTable.run(); + waitForIndexes.run(); + seedTable.run(); + awaitTableSearchReady(search, 1); + } + + private static boolean sharedTableConfigured(DynamoDbClient client, String tableName) { + if (!tableExists(client, tableName)) { + return false; + } + List indexes = + client.describeTable(r -> r.tableName(tableName)).table().vectorIndexes(); + return vectorIndexesActive(indexes, 1); + } + + private static boolean sharedTableConfigured(DynamoDbAsyncClient client, String tableName) { + if (!tableExists(client, tableName)) { + return false; + } + List indexes = + client.describeTable(r -> r.tableName(tableName)).join().table().vectorIndexes(); + return vectorIndexesActive(indexes, 1); + } + + private static void recreateSyncSharedTable(DynamoDbClient client, String tableName, Runnable createTable) { + if (tableExists(client, tableName)) { + client.deleteTable(r -> r.tableName(tableName)); + waitUntilTableNotExists(client, tableName); + } + createTable.run(); + client.waiter().waitUntilTableExists(r -> r.tableName(tableName)); + } + + private static void recreateAsyncSharedTable(DynamoDbAsyncClient client, String tableName, Runnable createTable) { + if (tableExists(client, tableName)) { + client.deleteTable(r -> r.tableName(tableName)).join(); + waitUntilTableNotExists(client, tableName); + } + createTable.run(); + client.waiter().waitUntilTableExists(r -> r.tableName(tableName)).join(); + } + + private static void waitUntilTableNotExists(DynamoDbClient client, String tableName) { + for (int attempt = 0; attempt < TABLE_DELETION_WAIT_ATTEMPTS; attempt++) { + if (!tableExists(client, tableName)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Timed out waiting for table deletion: " + tableName); + } + + private static void waitUntilTableNotExists(DynamoDbAsyncClient client, String tableName) { + for (int attempt = 0; attempt < TABLE_DELETION_WAIT_ATTEMPTS; attempt++) { + if (!tableExists(client, tableName)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Timed out waiting for table deletion: " + tableName); + } + + private static void awaitTableSearchReady(Supplier>> search, + int expectedCount) { + if (awaitSearchResultCount(search, expectedCount, TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS).size() < expectedCount) { + throw new AssertionError("Timed out waiting for table search results after seeding"); + } + } + + private static boolean tableExists(DynamoDbClient client, String name) { + try { + client.describeTable(r -> r.tableName(name)); + return true; + } catch (ResourceNotFoundException e) { + return false; + } + } + + private static boolean tableExists(DynamoDbAsyncClient client, String name) { + try { + client.describeTable(r -> r.tableName(name)).join(); + return true; + } catch (CompletionException e) { + if (e.getCause() instanceof ResourceNotFoundException) { + return false; + } + throw e; + } + } + + private static List beanSyncSeedRecords() { + return Arrays.asList( + beanRecord("articles", "exact-match", "science", "Exact match article", EXACT_MATCH_VECTOR), + beanRecord("articles", "orthogonal", "science", "Orthogonal article", ORTHOGONAL_VECTOR), + beanRecord("articles", "science-item", "science", "A science article", EXACT_MATCH_VECTOR), + beanRecord("articles", "art-item", "art", "An art article", EXACT_MATCH_VECTOR), + beanRecord("articles", "response-test", "science", "Response test", EXACT_MATCH_VECTOR)); + } + + private static List beanAsyncSeedRecords() { + return Arrays.asList( + beanRecord("articles", "async-exact-match", "science", "Async exact match", EXACT_MATCH_VECTOR), + beanRecord("articles", "async-orthogonal", "science", "Async orthogonal", ORTHOGONAL_VECTOR)); + } + + private static List inlineFilterSeedRecords() { + InlineFilterOnlyVectorRecordBean scienceItem = new InlineFilterOnlyVectorRecordBean(); + scienceItem.setPk("articles"); + scienceItem.setSk("science-item"); + scienceItem.setCategory("science"); + scienceItem.setEmbedding(toFloatList(EXACT_MATCH_VECTOR)); + + InlineFilterOnlyVectorRecordBean artItem = new InlineFilterOnlyVectorRecordBean(); + artItem.setPk("articles"); + artItem.setSk("art-item"); + artItem.setCategory("art"); + artItem.setEmbedding(toFloatList(EXACT_MATCH_VECTOR)); + + InlineFilterOnlyVectorRecordBean scienceReview = new InlineFilterOnlyVectorRecordBean(); + scienceReview.setPk("reviews"); + scienceReview.setSk("science-review"); + scienceReview.setCategory("science"); + scienceReview.setEmbedding(toFloatList(ORTHOGONAL_VECTOR)); + + InlineFilterOnlyVectorRecordBean reviewArtItem = new InlineFilterOnlyVectorRecordBean(); + reviewArtItem.setPk("reviews"); + reviewArtItem.setSk("art-item"); + reviewArtItem.setCategory("art"); + reviewArtItem.setEmbedding(toFloatList(EXACT_MATCH_VECTOR)); + + return Arrays.asList(scienceItem, artItem, scienceReview, reviewArtItem); + } + + private static VectorRecordBean beanRecord(String pk, + String sk, + String category, + String description, + float[] embedding) { + VectorRecordBean record = new VectorRecordBean(); + record.setPk(pk); + record.setSk(sk); + record.setCategory(category); + record.setDescription(description); + record.setEmbedding(toFloatList(embedding)); + return record; + } + + private static SearchVectorsEnhancedRequest beanScienceSearchRequest() { + return SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition("science")) + .build(); + } + + private static SearchVectorsEnhancedRequest inlineFilterScienceSearchRequest() { + return SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(inlineFilterOnlyCondition("science")) + .build(); + } + + private static Expression hashCondition(String categoryValue) { + return Expression.builder() + .expression("#cat = :catval") + .putExpressionName("#cat", "category") + .putExpressionValue(":catval", AttributeValue.builder().s(categoryValue).build()) + .build(); + } + + private static Expression hashAndFilterCondition(String categoryValue, String descriptionValue) { + return Expression.builder() + .expression("#cat = :catval AND #desc = :descval") + .putExpressionName("#cat", "category") + .putExpressionName("#desc", "description") + .putExpressionValue(":catval", AttributeValue.builder().s(categoryValue).build()) + .putExpressionValue(":descval", AttributeValue.builder().s(descriptionValue).build()) + .build(); + } + + private static Expression inlineFilterOnlyCondition(String categoryValue) { + return Expression.builder() + .expression("#cat = :catval") + .putExpressionName("#cat", "category") + .putExpressionValue(":catval", AttributeValue.builder().s(categoryValue).build()) + .build(); + } + + private static List toFloatList(float[] array) { + List list = new ArrayList<>(array.length); + for (float f : array) { + list.add(f); + } + return list; + } + + private static void waitForVectorIndexesActive(DynamoDbClient client, String tableName, int expectedCount) { + for (int attempt = 0; attempt < VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS; attempt++) { + DescribeTableResponse response = client.describeTable(r -> r.tableName(tableName)); + if (vectorIndexesActive(response, expectedCount)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Vector index(es) on table " + tableName + " did not become ACTIVE within " + + VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS + " attempts"); + } + + private static void waitForVectorIndexesActive(DynamoDbAsyncClient client, String tableName, int expectedCount) { + for (int attempt = 0; attempt < VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS; attempt++) { + DescribeTableResponse response = client.describeTable(r -> r.tableName(tableName)).join(); + if (vectorIndexesActive(response, expectedCount)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Vector index(es) on table " + tableName + " did not become ACTIVE within " + + VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS + " attempts"); + } + + private static boolean vectorIndexesActive(DescribeTableResponse response, int expectedCount) { + List indexes = response.table().vectorIndexes(); + return indexes != null + && indexes.size() == expectedCount + && indexes.stream().allMatch(i -> i.indexStatus() == IndexStatus.ACTIVE); + } + + private static boolean vectorIndexesActive(List indexes, int expectedCount) { + return indexes != null + && indexes.size() == expectedCount + && indexes.stream().allMatch(i -> i.indexStatus() == IndexStatus.ACTIVE); + } + + private static List> awaitSearchResultCount( + Supplier>> search, int expectedCount, int maxAttempts) { + List> results = search.get(); + for (int attempt = 0; results.size() < expectedCount && attempt < maxAttempts; attempt++) { + sleepBetweenRetries(attempt); + results = search.get(); + } + return results; + } + + private static void sleepBetweenRetries(int attempt) { + try { + long delay = Math.min(50L << Math.min(attempt, 4), 1_000L); + Thread.sleep(delay); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + + private static void assertBeanScoreOrdering(List> results, + String betterMatchSk, + String worseMatchSk) { + SearchResultItem betterMatch = findBeanResultBySk(results, betterMatchSk); + SearchResultItem worseMatch = findBeanResultBySk(results, worseMatchSk); + assertThat(betterMatch.score()).isLessThanOrEqualTo(worseMatch.score()); + } + + private static SearchResultItem findBeanResultBySk( + List> results, String sortKey) { + return results.stream() + .filter(r -> sortKey.equals(r.item().getSk())) + .findFirst() + .orElseThrow(() -> new AssertionError("Missing search result for sk: " + sortKey)); + } + + private static void assertImmutableScoreOrdering(List> results, + String betterMatchSk, + String worseMatchSk) { + SearchResultItem betterMatch = findImmutableResultBySk(results, betterMatchSk); + SearchResultItem worseMatch = findImmutableResultBySk(results, worseMatchSk); + assertThat(betterMatch.score()).isLessThanOrEqualTo(worseMatch.score()); + } + + private static SearchResultItem findImmutableResultBySk( + List> results, String sortKey) { + return results.stream() + .filter(r -> sortKey.equals(r.item().sk())) + .findFirst() + .orElseThrow(() -> new AssertionError("Missing search result for sk: " + sortKey)); + } + + private List> searchBeanVectors(SearchVectorsEnhancedRequest request) { + if (SEARCH_READY_TABLES.contains(BEAN_SHARED_SYNC_TABLE)) { + return beanSyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request) + .results(); + } + return awaitSearchResultCount( + () -> beanSyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).results(), + 1, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS); + } + + private List> searchImmutableVectors(SearchVectorsEnhancedRequest request) { + if (SEARCH_READY_TABLES.contains(BEAN_SHARED_SYNC_TABLE)) { + return immutableSyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).results(); + } + return awaitSearchResultCount( + () -> immutableSyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).results(), + 1, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS); + } + + private List> searchInlineFilterBeanVectors( + SearchVectorsEnhancedRequest request) { + if (SEARCH_READY_TABLES.contains(BEAN_INLINE_FILTER_TABLE)) { + return inlineFilterBeanTable.vectorIndex(FILTER_ONLY_INDEX).searchVectorsWithResponse(request).results(); + } + return awaitSearchResultCount( + () -> inlineFilterBeanTable.vectorIndex(FILTER_ONLY_INDEX).searchVectorsWithResponse(request).results(), + 1, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS); + } + + private List> searchInlineFilterImmutableVectors( + SearchVectorsEnhancedRequest request) { + if (SEARCH_READY_TABLES.contains(BEAN_INLINE_FILTER_TABLE)) { + return inlineFilterImmutableTable.vectorIndex(FILTER_ONLY_INDEX).searchVectorsWithResponse(request).results(); + } + return awaitSearchResultCount( + () -> inlineFilterImmutableTable.vectorIndex(FILTER_ONLY_INDEX).searchVectorsWithResponse(request).results(), + 1, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS); + } + + private List> searchAsyncBeanVectors(SearchVectorsEnhancedRequest request) { + if (SEARCH_READY_TABLES.contains(BEAN_SHARED_ASYNC_TABLE)) { + return beanAsyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).join().results(); + } + return awaitSearchResultCount( + () -> beanAsyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).join().results(), + 1, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS); + } + + private void verifyBeanVectorIndexMetadataOnce() { + if (!beanMetadataVerified) { + DescribeTableResponse response = dynamoDbClient.describeTable(r -> r.tableName(BEAN_SHARED_SYNC_TABLE)); + assertThat(response.table().tableStatusAsString()).isEqualTo("ACTIVE"); + assertVectorIndexMetadata(response); + beanMetadataVerified = true; + } + } + + private void verifyInlineFilterVectorIndexMetadataOnce() { + if (!inlineFilterMetadataVerified) { + DescribeTableResponse response = dynamoDbClient.describeTable(r -> r.tableName(BEAN_INLINE_FILTER_TABLE)); + assertThat(response.table().tableStatusAsString()).isEqualTo("ACTIVE"); + assertInlineFilterOnlyVectorIndexMetadata(response); + inlineFilterMetadataVerified = true; + } + } + + private static void assertVectorIndexMetadata(DescribeTableResponse response) { + List vectorIndexes = response.table().vectorIndexes(); + assertThat(vectorIndexes).hasSize(1); + + VectorIndexDescription index = vectorIndexes.get(0); + assertThat(index.indexName()).isEqualTo(COSINE_INDEX); + assertThat(index.distanceFunction()).hasToString("COSINE"); + assertThat(index.dimensions()).isEqualTo(4); + assertThat(index.vectorAttribute().attributeName()).isEqualTo("embedding"); + assertThat(index.searchSchema()) + .hasSize(2) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("category"); + assertThat(e.searchSchemaElementType()).hasToString("HASH"); + }) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("description"); + assertThat(e.searchSchemaElementType()).hasToString("INLINE_FILTER"); + }); + } + + private static void assertInlineFilterOnlyVectorIndexMetadata(DescribeTableResponse response) { + List vectorIndexes = response.table().vectorIndexes(); + assertThat(vectorIndexes).hasSize(1); + + VectorIndexDescription index = vectorIndexes.get(0); + assertThat(index.indexName()).isEqualTo(FILTER_ONLY_INDEX); + assertThat(index.distanceFunction()).hasToString("COSINE"); + assertThat(index.dimensions()).isEqualTo(4); + assertThat(index.vectorAttribute().attributeName()).isEqualTo("embedding"); + assertThat(index.searchSchema()) + .hasSize(1) + .allSatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("category"); + assertThat(e.searchSchemaElementType()).hasToString("INLINE_FILTER"); + }); + } + + // Bean schema tests + + @Test + void noArgCreateTable_fromBeanAnnotations_createsCorrectVectorIndex() { + verifyBeanVectorIndexMetadataOnce(); + } + + @Test + void putAndSearch_withBeanSchema_returnsOrderedResults() { + SearchVectorsEnhancedRequest request = beanScienceSearchRequest(); + + List> results = searchBeanVectors(request); + + assertThat(results).hasSizeGreaterThanOrEqualTo(2); + assertBeanScoreOrdering(results, "exact-match", "orthogonal"); + } + + @Test + void searchWithHashAndInlineFilter_withBeanSchema_filtersCorrectly() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression( + hashAndFilterCondition("science", + "A science article")) + .build(); + + List> results = searchBeanVectors(request); + + assertThat(results).hasSize(1); + assertThat(results.get(0).item().getSk()).isEqualTo("science-item"); + assertThat(results.get(0).item().getDescription()).isEqualTo("A science article"); + } + + @Test + void vectorIndexHandle_fromBeanTable_supportsSearchWithResponse() { + SearchVectorsEnhancedRequest request = beanScienceSearchRequest(); + + List> results = + beanSyncTable.vectorIndex(COSINE_INDEX).searchVectorsWithResponse(request).results(); + + assertThat(results.stream().map(r -> r.item().getSk())).contains("response-test"); + } + + // Immutable schema tests + + @Test + void noArgCreateTable_fromImmutableAnnotations_createsCorrectVectorIndex() { + verifyBeanVectorIndexMetadataOnce(); + } + + @Test + void putAndSearch_withImmutableSchema_returnsOrderedResults() { + SearchVectorsEnhancedRequest request = beanScienceSearchRequest(); + + List> results = searchImmutableVectors(request); + + assertThat(results).hasSizeGreaterThanOrEqualTo(2); + assertImmutableScoreOrdering(results, "exact-match", "orthogonal"); + } + + @Test + void searchWithHashAndInlineFilter_withImmutableSchema_filtersCorrectly() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression( + hashAndFilterCondition("science", + "A science article")) + .build(); + + List> results = searchImmutableVectors(request); + + assertThat(results).hasSize(1); + assertThat(results.get(0).item().sk()).isEqualTo("science-item"); + assertThat(results.get(0).item().description()).isEqualTo("A science article"); + } + + // Inline filter only schema tests + + @Test + void noArgCreateTable_fromBeanAnnotations_createsInlineFilterOnlyVectorIndex() { + verifyInlineFilterVectorIndexMetadataOnce(); + } + + @Test + void noArgCreateTable_fromImmutableAnnotations_createsInlineFilterOnlyVectorIndex() { + verifyInlineFilterVectorIndexMetadataOnce(); + } + + @Test + void putAndSearch_withBeanSchema_inlineFilterOnly_returnsResults() { + SearchVectorsEnhancedRequest request = inlineFilterScienceSearchRequest(); + + List> results = + searchInlineFilterBeanVectors(request); + + assertThat(results).hasSize(2); + assertThat(results.stream().map(r -> r.item().getSk())) + .containsExactlyInAnyOrder("science-item", "science-review"); + assertThat(results).allMatch(r -> "science".equals(r.item().getCategory())); + } + + @Test + void putAndSearch_withImmutableSchema_inlineFilterOnly_returnsResults() { + SearchVectorsEnhancedRequest request = inlineFilterScienceSearchRequest(); + + List> results = + searchInlineFilterImmutableVectors(request); + + assertThat(results).hasSize(2); + assertThat(results.stream().map(r -> r.item().sk())) + .containsExactlyInAnyOrder("science-item", "science-review"); + assertThat(results).allMatch(r -> "science".equals(r.item().category())); + } + + @Test + void searchWithInlineFilterCondition_withoutHashKey_returnsResultsAcrossPartitions() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression( + inlineFilterOnlyCondition("science")) + .build(); + + List> results = + searchInlineFilterBeanVectors(request); + + assertThat(results).hasSize(2); + assertThat(results.stream().map(r -> r.item().getPk()).collect(Collectors.toSet())) + .containsExactlyInAnyOrder("articles", "reviews"); + } + + // Async annotated schema tests + + @Test + void noArgCreateTable_asyncBeanSchema_createsCorrectVectorIndex() { + DescribeTableResponse response = asyncClient.describeTable(r -> r.tableName(BEAN_SHARED_ASYNC_TABLE)).join(); + assertThat(response.table().tableStatusAsString()).isEqualTo("ACTIVE"); + assertVectorIndexMetadata(response); + } + + @Test + void putAndSearch_asyncBeanSchema_returnsResults() { + SearchVectorsEnhancedRequest request = beanScienceSearchRequest(); + + List> results = searchAsyncBeanVectors(request); + + assertThat(results).hasSizeGreaterThanOrEqualTo(2); + assertBeanScoreOrdering(results, "async-exact-match", "async-orthogonal"); + } + + // Schema metadata consistency tests + + @Test + void beanAndImmutableSchemas_produceEquivalentVectorIndexMetadata() { + Collection beanMetadata = BEAN_SCHEMA.tableMetadata().vectorIndices(); + Collection immutableMetadata = IMMUTABLE_SCHEMA.tableMetadata().vectorIndices(); + + assertThat(beanMetadata).hasSize(1); + assertThat(immutableMetadata).hasSize(1); + + VectorIndexMetadata beanIndex = beanMetadata.iterator().next(); + VectorIndexMetadata immutableIndex = immutableMetadata.iterator().next(); + + assertThat(beanIndex.indexName()).isEqualTo(immutableIndex.indexName()).isEqualTo(COSINE_INDEX); + assertThat(beanIndex.vectorAttributeName()).isEqualTo(immutableIndex.vectorAttributeName()).isEqualTo("embedding"); + assertThat(beanIndex.dimensions()).isEqualTo(immutableIndex.dimensions()).isEqualTo(4); + assertThat(beanIndex.distanceFunction()).isEqualTo(immutableIndex.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(beanIndex.searchSchemaElements()).hasSameSizeAs(immutableIndex.searchSchemaElements()); + } + + @Test + void beanSchema_vectorIndexNotInSecondaryIndices() { + assertThat(BEAN_SCHEMA.tableMetadata().indices().stream() + .filter(i -> COSINE_INDEX.equals(i.name())) + .findAny()).isEmpty(); + + assertThat(BEAN_SCHEMA.tableMetadata().vectorIndices().stream() + .filter(vi -> COSINE_INDEX.equals(vi.indexName())) + .findAny()).isPresent(); + } + + @Test + void immutableSchema_vectorIndexNotInSecondaryIndices() { + assertThat(IMMUTABLE_SCHEMA.tableMetadata().indices().stream() + .filter(i -> COSINE_INDEX.equals(i.name())) + .findAny()).isEmpty(); + + assertThat(IMMUTABLE_SCHEMA.tableMetadata().vectorIndices().stream() + .filter(vi -> COSINE_INDEX.equals(vi.indexName())) + .findAny()).isPresent(); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTest.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTest.java new file mode 100644 index 000000000000..c66fe98fb8e8 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTest.java @@ -0,0 +1,168 @@ +/* + * 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.enhanced.dynamodb; + +import java.util.List; +import java.util.function.Consumer; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorRecord; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class SearchVectorsIntegrationTest extends SearchVectorsIntegrationTestBase { + + private static final String TABLE_NAME = SHARED_SYNC_TABLE_NAME; + private DynamoDbClient dynamoDbClient; + private DynamoDbEnhancedClient enhancedClient; + private DynamoDbTable mappedTable; + + @BeforeAll + void setup() { + dynamoDbClient = createSearchVectorsClient(); + enhancedClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(dynamoDbClient).build(); + mappedTable = enhancedClient.table( + TABLE_NAME, VECTOR_TABLE_SCHEMA); + + prepareSyncSharedTable( + dynamoDbClient, + TABLE_NAME, + () -> mappedTable.createTable(createTableRequest()), + () -> testRecords().forEach(mappedTable::putItem), + () -> mappedTable.vectorIndex(COSINE_INDEX) + .searchVectorsWithResponse(sharedTableSearchReadyRequest()) + .results()); + prepareDedicatedIntegrationTablesOnce(); + } + + @AfterAll + void teardown() { + dynamoDbClient.close(); + } + + @Override + protected String sharedTableName() { + return TABLE_NAME; + } + + @Override + protected DescribeTableResponse describeTable(String tableName) { + return dynamoDbClient.describeTable(r -> r.tableName(tableName)); + } + + @Override + protected List> executeSearch(String index, SearchVectorsEnhancedRequest request) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(request).results(); + } + + @Override + protected void executePut(VectorRecord record) { + mappedTable.putItem(record); + } + + @Override + protected void executeDelete(Key key) { + mappedTable.deleteItem(key); + } + + @Override + protected List> executeSearchDocument(String index, + SearchVectorsEnhancedRequest request, + DocumentTableSchema schema) { + DynamoDbTable docTable = enhancedClient.table(TABLE_NAME, schema); + return docTable.vectorIndex(index).searchVectorsWithResponse(request).results(); + } + + @Override + protected SearchVectorsEnhancedResponse executeSearchWithResponse(String index, + SearchVectorsEnhancedRequest request) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(request); + } + + @Override + protected List> executeSearchWithBuilder( + String index, Consumer builder) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(builder).results(); + } + + @Override + protected SearchVectorsEnhancedResponse executeSearchWithResponseBuilder( + String index, Consumer builder) { + return mappedTable.vectorIndex(index).searchVectorsWithResponse(builder); + } + + @Override + protected void executeTempTableCreate(String tempTableName, + TableSchema schema, + CreateTableEnhancedRequest request) { + enhancedClient.table(tempTableName, schema).createTable(request); + dynamoDbClient.waiter().waitUntilTableExists(r -> r.tableName(tempTableName)); + } + + @Override + protected void createAndWaitForDedicatedTable(String tableName, + StaticTableSchema schema, + List indexes) { + DynamoDbTable table = enhancedClient.table(tableName, schema); + table.createTable(CreateTableEnhancedRequest.builder().vectorIndexes(indexes).build()); + dynamoDbClient.waiter().waitUntilTableExists(r -> r.tableName(tableName)); + } + + @Override + protected void deleteDedicatedTable(String tableName) { + dynamoDbClient.deleteTable(r -> r.tableName(tableName)); + } + + @Override + protected void dedicatedPutItem(String tableName, + StaticTableSchema schema, + VectorRecord record) { + enhancedClient.table(tableName, schema).putItem(record); + } + + @Override + protected VectorRecord dedicatedGetItem(String tableName, + StaticTableSchema schema, + Key key) { + return enhancedClient.table(tableName, schema).getItem(key); + } + + @Override + protected List> dedicatedSearch(String tableName, + StaticTableSchema schema, + String indexName, + SearchVectorsEnhancedRequest request) { + return enhancedClient.table(tableName, schema).vectorIndex(indexName).searchVectorsWithResponse(request).results(); + } + + @Override + protected SearchVectorsResponse executeLowLevelSearchVectors(SearchVectorsRequest request) { + return dynamoDbClient.searchVectors(request); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTestBase.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTestBase.java new file mode 100644 index 000000000000..dc801f89b577 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/SearchVectorsIntegrationTestBase.java @@ -0,0 +1,2685 @@ +/* + * 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.enhanced.dynamodb; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.within; +import static software.amazon.awssdk.enhanced.dynamodb.TableMetadata.primaryIndexName; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.HASH; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.INLINE_FILTER; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import software.amazon.awssdk.enhanced.dynamodb.converters.document.CustomAttributeForDocumentConverterProvider; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorCreateTableLimitRecord; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorRecord; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; +import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; +import software.amazon.awssdk.services.dynamodb.model.IndexStatus; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; +import software.amazon.awssdk.services.dynamodb.model.VectorIndexDescription; + +public abstract class SearchVectorsIntegrationTestBase extends DynamoDbEnhancedIntegrationTestBase { + + + protected static final String COSINE_INDEX = "cosine-index"; + protected static final String DOT_PRODUCT_INDEX = "dot-product-index"; + protected static final String EUCLIDEAN_INDEX = "euclidean-index"; + protected static final String TABLE_WIDE_INDEX = "table-wide-index"; + + protected static final String SHARED_SYNC_TABLE_NAME = + "JavaTests-SearchVectors-Shared-Sync"; + protected static final String SHARED_ASYNC_TABLE_NAME = + "JavaTests-SearchVectors-Shared-Async"; + protected static final String NOHASH_TABLE_NAME = + "JavaTests-SearchVectors-NoHash"; + protected static final String DIMENSION_TABLE_PREFIX = + "JavaTests-SearchVectors-Dim"; + protected static final String FILTER_ONLY_TABLE_NAME = + "JavaTests-SearchVectors-FilterOnly"; + + private static final int DEFAULT_SEARCH_RETRY_ATTEMPTS = 15; + private static final int QUICK_SEARCH_RETRY_ATTEMPTS = 3; + private static final int TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS = 20; + private static final int VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS = 30; + private static final int TABLE_DELETION_WAIT_ATTEMPTS = 30; + + private static final ConcurrentHashMap SHARED_TABLE_SETUP_LOCKS = new ConcurrentHashMap<>(); + private static final Set PREPARED_TABLES = ConcurrentHashMap.newKeySet(); + private static final Set SEARCH_READY_TABLES = ConcurrentHashMap.newKeySet(); + private static final Object DEDICATED_TABLE_PREP_LOCK = new Object(); + private static volatile boolean dedicatedTablesPrepared; + + protected static final float[] EXACT_MATCH_VECTOR = {1.0f, 0.0f, 0.0f, 0.0f}; + protected static final float[] NEAR_MATCH_VECTOR = {0.9f, 0.1f, 0.0f, 0.0f}; + protected static final float[] ORTHOGONAL_1_VECTOR = {0.0f, 1.0f, 0.0f, 0.0f}; + protected static final float[] ORTHOGONAL_2_VECTOR = {0.0f, 0.0f, 1.0f, 0.0f}; + protected static final float[] DIFF_PARTITION_VECTOR = {0.5f, 0.5f, 0.5f, 0.5f}; + protected static final float[] QUERY_VECTOR = {0.95f, 0.05f, 0.0f, 0.0f}; + protected static final float[] ALTERNATE_QUERY_VECTOR = {0.0f, 1.0f, 0.0f, 0.0f}; + protected static final float[] DOT_PRODUCT_QUERY_VECTOR = {1.0f, 0.0f, 0.0f, 0.0f}; + + protected static final List VECTOR_INDEX_DEFINITIONS = Arrays.asList( + EnhancedVectorIndex.builder() + .indexName(COSINE_INDEX) + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType(INLINE_FILTER)) + .build(), + + EnhancedVectorIndex.builder() + .indexName(DOT_PRODUCT_INDEX) + .vectorAttributeName("embeddingDot") + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.KEYS_ONLY)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(), + + EnhancedVectorIndex.builder() + .indexName(EUCLIDEAN_INDEX) + .vectorAttributeName("embeddingEuclidean") + .distanceFunction(DistanceFunction.EUCLIDEAN) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes("category")) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build() + ); + + protected static final StaticTableSchema VECTOR_TABLE_SCHEMA = + StaticTableSchema.builder(VectorRecord.class) + .newItemSupplier(VectorRecord::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(VectorRecord::getPk) + .setter(VectorRecord::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(VectorRecord::getSk) + .setter(VectorRecord::setSk) + .tags(primarySortKey())) + .addAttribute(String.class, a -> a.name("category") + .getter(VectorRecord::getCategory) + .setter(VectorRecord::setCategory)) + .addAttribute(String.class, a -> a.name("description") + .getter(VectorRecord::getDescription) + .setter(VectorRecord::setDescription)) + .addAttribute(EnhancedType.listOf(Float.class), a -> a.name("embeddingCosine") + .getter(VectorRecord::getEmbeddingCosine) + .setter(VectorRecord::setEmbeddingCosine)) + .addAttribute(EnhancedType.listOf(Float.class), a -> a.name("embeddingDot") + .getter(VectorRecord::getEmbeddingDot) + .setter(VectorRecord::setEmbeddingDot)) + .addAttribute(EnhancedType.listOf(Float.class), a -> a.name("embeddingEuclidean") + .getter(VectorRecord::getEmbeddingEuclidean) + .setter(VectorRecord::setEmbeddingEuclidean)) + .tags(StaticAttributeTags.vectorIndexes(VECTOR_INDEX_DEFINITIONS)) + .build(); + + private static final Map DOCUMENT_SCHEMA_CACHE = new HashMap<>(); + + protected abstract String sharedTableName(); + + protected abstract DescribeTableResponse describeTable(String tableName); + + protected abstract List> executeSearch(String index, SearchVectorsEnhancedRequest req); + + protected abstract void executePut(VectorRecord record); + + protected abstract void executeDelete(Key key); + + protected abstract List> executeSearchDocument(String index, + SearchVectorsEnhancedRequest req, + DocumentTableSchema schema); + + protected abstract SearchVectorsEnhancedResponse executeSearchWithResponse(String index, + SearchVectorsEnhancedRequest req); + + protected abstract List> executeSearchWithBuilder( + String index, Consumer builder); + + protected abstract SearchVectorsEnhancedResponse executeSearchWithResponseBuilder( + String index, Consumer builder); + + protected abstract void executeTempTableCreate(String tempTableName, + TableSchema schema, + CreateTableEnhancedRequest request); + + protected abstract void createAndWaitForDedicatedTable(String tableName, + StaticTableSchema schema, + List indexes); + + protected abstract void deleteDedicatedTable(String tableName); + + protected abstract void dedicatedPutItem(String tableName, + StaticTableSchema schema, + VectorRecord record); + + protected abstract VectorRecord dedicatedGetItem(String tableName, + StaticTableSchema schema, + Key key); + + protected abstract List> dedicatedSearch(String tableName, + StaticTableSchema schema, + String indexName, + SearchVectorsEnhancedRequest request); + + protected abstract SearchVectorsResponse executeLowLevelSearchVectors(SearchVectorsRequest request); + + protected interface DedicatedTableContext { + String tableName(); + + void putItem(VectorRecord record); + + VectorRecord getItem(Key key); + + List> search(String indexName, SearchVectorsEnhancedRequest request); + + DescribeTableResponse describeTable(); + } + + protected static String createSearchVectorsTableName() { + return "JavaTests-" + UUID.randomUUID() + "-SearchVectorsTable"; + } + + protected static CreateTableEnhancedRequest createTableRequest() { + return CreateTableEnhancedRequest.builder() + .vectorIndexes(VECTOR_INDEX_DEFINITIONS) + .build(); + } + + protected static List testRecords() { + List records = new ArrayList<>(); + records.add(testRecord("articles", "exact-match", "science", + "Exact match article", EXACT_MATCH_VECTOR)); + records.add(testRecord("articles", "near-match", "science", + "Near match article", NEAR_MATCH_VECTOR)); + records.add(testRecord("articles", "orthogonal-1", "art", + "Orthogonal article one", ORTHOGONAL_1_VECTOR)); + records.add(testRecord("articles", "orthogonal-2", "art", + "Orthogonal article two", ORTHOGONAL_2_VECTOR)); + records.add(testRecord("reviews", "diff-partition", "general", + "Different partition review", DIFF_PARTITION_VECTOR)); + + records.add(testRecord("articles-extended", "article-history", "history", + "History article", seededNormalizedVector(4, 11))); + records.add(testRecord("articles-extended", "article-sports", "sports", + "Sports article", seededNormalizedVector(4, 12))); + records.add(testRecord("articles-extended", "article-tech", "tech", + "Technology article", seededNormalizedVector(4, 13))); + + records.add(testRecord("reviews", "review-positive", "positive", + "Positive review", seededNormalizedVector(4, 21))); + records.add(testRecord("reviews", "review-neutral", "neutral", + "Neutral review", seededNormalizedVector(4, 22))); + records.add(testRecord("reviews", "review-negative", "negative", + "Negative review", seededNormalizedVector(4, 23))); + records.add(testRecord("reviews", "review-tech", "tech", + "Tech review", seededNormalizedVector(4, 24))); + records.add(testRecord("reviews", "review-general", "general", + "General review", seededNormalizedVector(4, 25))); + + records.add(testRecord("products", "product-laptop", "electronics", + "Laptop", seededNormalizedVector(4, 31))); + records.add(testRecord("products", "product-phone", "electronics", + "Phone", seededNormalizedVector(4, 32))); + records.add(testRecord("products", "product-sofa", "home", + "Sofa", seededNormalizedVector(4, 33))); + records.add(testRecord("products", "product-lamp", "home", + "Lamp", seededNormalizedVector(4, 34))); + records.add(testRecord("products", "product-cooler", "outdoor", + "Cooler", seededNormalizedVector(4, 35))); + records.add(testRecord("products", "product-backpack", "outdoor", + "Backpack", seededNormalizedVector(4, 36))); + records.add(testRecord("products", "product-novel", "books", + "Novel", seededNormalizedVector(4, 37))); + records.add(testRecord("products", "product-textbook", "books", + "Textbook", seededNormalizedVector(4, 38))); + return records; + } + + protected static void setEmbeddingForIndex(VectorRecord record, String indexName, float[] embedding) { + setEmbeddingForIndex(record, indexName, toFloatList(embedding)); + } + + protected static void setEmbeddingForIndex(VectorRecord record, String indexName, List embedding) { + if (COSINE_INDEX.equals(indexName)) { + record.setEmbeddingCosine(embedding); + } else if (DOT_PRODUCT_INDEX.equals(indexName)) { + record.setEmbeddingDot(embedding); + } else if (EUCLIDEAN_INDEX.equals(indexName)) { + record.setEmbeddingEuclidean(embedding); + } else if (TABLE_WIDE_INDEX.equals(indexName) || indexName.startsWith("vector-index-")) { + record.setEmbeddingCosine(embedding); + } else { + throw new IllegalArgumentException("Unsupported index name for embedding assignment: " + indexName); + } + } + + protected static List embeddingForIndex(VectorRecord record, EnhancedVectorIndex index) { + String embeddingAttribute = index.vectorAttributeName(); + if ("embeddingDot".equals(embeddingAttribute)) { + return record.getEmbeddingDot(); + } + if ("embeddingEuclidean".equals(embeddingAttribute)) { + return record.getEmbeddingEuclidean(); + } + return record.getEmbeddingCosine(); + } + + protected static void assertEmbeddingMatches(VectorRecord record, + EnhancedVectorIndex index, + float[] expectedEmbedding) { + List embedding = embeddingForIndex(record, index); + assertThat(embedding).hasSize(expectedEmbedding.length); + IntStream.range(0, expectedEmbedding.length).forEach(i -> { + // DynamoDB may slightly change float values on read-back, so compare with a small tolerance. + assertThat(embedding.get(i)).isCloseTo(expectedEmbedding[i], within(0.00001f)); + }); + } + + protected static DocumentTableSchema documentSchema(boolean withCustomConverterProvider) { + return DOCUMENT_SCHEMA_CACHE.computeIfAbsent(withCustomConverterProvider, custom -> { + DocumentTableSchema.Builder builder = DocumentTableSchema + .builder() + .addIndexPartitionKey(primaryIndexName(), "pk", AttributeValueType.S) + .addIndexSortKey(primaryIndexName(), "sk", AttributeValueType.S) + .vectorIndexes(VECTOR_INDEX_DEFINITIONS); + if (custom) { + builder.attributeConverterProviders( + CustomAttributeForDocumentConverterProvider.create(), + DefaultAttributeConverterProvider.create()); + } + return builder.build(); + }); + } + + protected List> searchVectorsDocument(String index, + SearchVectorsEnhancedRequest request) { + return searchVectorsDocument(index, request, false); + } + + protected List> searchVectorsDocument(String index, + SearchVectorsEnhancedRequest request, + boolean withCustomConverter) { + if (isSharedTableSearchReady()) { + return executeSearchDocument(index, request, documentSchema(withCustomConverter)); + } + return awaitNonEmptySearchResults( + () -> executeSearchDocument(index, request, documentSchema(withCustomConverter))); + } + + protected boolean isSharedTableSearchReady() { + return SEARCH_READY_TABLES.contains(sharedTableName()); + } + + protected void withDedicatedTable( + StaticTableSchema schema, + List indexes, + Consumer test) { + String tableName = createSearchVectorsTableName(); + try { + createAndWaitForDedicatedTable( + tableName, schema, indexes); + waitForVectorIndexesActive( + tableName, indexes.size()); + test.accept(new DedicatedTableContext() { + @Override + public String tableName() { + return tableName; + } + + @Override + public void putItem(VectorRecord record) { + dedicatedPutItem(tableName, schema, record); + } + + @Override + public VectorRecord getItem(Key key) { + return dedicatedGetItem(tableName, schema, key); + } + + @Override + public List> search(String indexName, SearchVectorsEnhancedRequest request) { + return dedicatedSearch(tableName, schema, indexName, request); + } + + @Override + public DescribeTableResponse describeTable() { + return SearchVectorsIntegrationTestBase.this.describeTable(tableName); + } + }); + } finally { + deleteDedicatedTable(tableName); + } + } + + protected static EnhancedVectorIndex vectorIndexWithDimensions(int dims) { + return EnhancedVectorIndex.builder() + .indexName("vector-index-" + dims) + .vectorAttributeName("embedding") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(dims) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(); + } + + protected static StaticTableSchema tableSchemaForVectorIndex(EnhancedVectorIndex index) { + StaticTableSchema.Builder builder = + StaticTableSchema.builder(VectorRecord.class) + .newItemSupplier(VectorRecord::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(VectorRecord::getPk) + .setter(VectorRecord::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(VectorRecord::getSk) + .setter(VectorRecord::setSk) + .tags(primarySortKey())) + .addAttribute(String.class, a -> a.name("category") + .getter(VectorRecord::getCategory) + .setter(VectorRecord::setCategory)) + .addAttribute(String.class, a -> a.name("description") + .getter(VectorRecord::getDescription) + .setter(VectorRecord::setDescription)); + + String embeddingAttribute = index.vectorAttributeName(); + builder.addAttribute(EnhancedType.listOf(Float.class), a -> { + a.name(embeddingAttribute); + if ("embeddingDot".equals(embeddingAttribute)) { + a.getter(VectorRecord::getEmbeddingDot).setter(VectorRecord::setEmbeddingDot); + } else if ("embeddingEuclidean".equals(embeddingAttribute)) { + a.getter(VectorRecord::getEmbeddingEuclidean).setter(VectorRecord::setEmbeddingEuclidean); + } else { + a.getter(VectorRecord::getEmbeddingCosine).setter(VectorRecord::setEmbeddingCosine); + } + }); + + return builder.tags(StaticAttributeTags.vectorIndexes(Collections.singletonList(index))).build(); + } + + protected static EnhancedVectorIndex tableWideVectorIndex() { + return EnhancedVectorIndex.builder() + .indexName(TABLE_WIDE_INDEX) + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .build(); + } + + protected static StaticTableSchema createTableLimitTestSchema() { + StaticTableSchema.Builder builder = + StaticTableSchema.builder(VectorCreateTableLimitRecord.class) + .newItemSupplier(VectorCreateTableLimitRecord::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(VectorCreateTableLimitRecord::getPk) + .setter(VectorCreateTableLimitRecord::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(VectorCreateTableLimitRecord::getSk) + .setter(VectorCreateTableLimitRecord::setSk) + .tags(primarySortKey())) + .addAttribute(EnhancedType.listOf(Float.class), + a -> a.name("embeddingCosine") + .getter(VectorCreateTableLimitRecord::getEmbeddingCosine) + .setter(VectorCreateTableLimitRecord::setEmbeddingCosine)); + IntStream.range(0, 19).forEach(i -> { + int index = i; + builder.addAttribute(String.class, a -> a.name("filter" + index) + .getter(r -> r.getFilterAttribute(index)) + .setter((r, v) -> r.setFilterAttribute(index, v))); + }); + IntStream.range(0, 21).forEach(i -> { + int index = i; + builder.addAttribute(String.class, a -> a.name("proj" + index) + .getter(r -> r.getProjectionAttribute(index)) + .setter((r, v) -> r.setProjectionAttribute(index, v))); + }); + return builder.build(); + } + + protected static EnhancedVectorIndex buildVectorIndexWithInlineFilters(int inlineFilterCount) { + EnhancedVectorIndex.Builder builder = EnhancedVectorIndex.builder() + .indexName("inline-filter-limit-index") + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)); + IntStream.range(0, inlineFilterCount) + .forEach(i -> builder.addSearchSchemaElement(b -> b.attributeName("filter" + i) + .searchSchemaElementType(INLINE_FILTER))); + return builder.build(); + } + + protected static EnhancedVectorIndex buildVectorIndexWithProjectedAttributes(int projectedAttributeCount) { + List projectedNames = IntStream.range(0, projectedAttributeCount) + .mapToObj(i -> "proj" + i) + .collect(Collectors.toList()); + return EnhancedVectorIndex.builder() + .indexName("projection-limit-index") + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.INCLUDE) + .nonKeyAttributes(projectedNames)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(); + } + + protected static float[] generateNormalizedVector(int dimensions) { + return seededNormalizedVector(dimensions, 1); + } + + protected static boolean tableExists(DynamoDbClient client, String name) { + try { + client.describeTable(r -> r.tableName(name)); + return true; + } catch (ResourceNotFoundException e) { + return false; + } + } + + protected static boolean tableExists(DynamoDbAsyncClient client, String name) { + try { + client.describeTable(r -> r.tableName(name)).join(); + return true; + } catch (CompletionException e) { + if (e.getCause() instanceof ResourceNotFoundException) { + return false; + } + throw e; + } + } + + protected boolean tableExistsCheck(String tableName) { + try { + describeTable(tableName); + return true; + } catch (ResourceNotFoundException e) { + return false; + } catch (CompletionException e) { + if (e.getCause() instanceof ResourceNotFoundException) { + return false; + } + throw e; + } + } + + protected void waitForVectorIndexesActive(String tableName, int expectedCount) { + for (int attempt = 0; attempt < VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS; attempt++) { + List indexes = describeTable(tableName).table().vectorIndexes(); + if (vectorIndexesActive(indexes, expectedCount)) { + return; + } + sleepBetweenRetries(attempt); + } + throw vectorIndexWaitTimeout(tableName, expectedCount); + } + + protected static void waitForVectorIndexesActive(DynamoDbClient client, + String tableName, + int expectedCount) { + for (int attempt = 0; attempt < VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS; attempt++) { + List indexes = + client.describeTable(r -> r.tableName(tableName)).table().vectorIndexes(); + if (vectorIndexesActive(indexes, expectedCount)) { + return; + } + sleepBetweenRetries(attempt); + } + throw vectorIndexWaitTimeout(tableName, expectedCount); + } + + protected static void waitForVectorIndexesActive(DynamoDbAsyncClient client, + String tableName, + int expectedCount) { + for (int attempt = 0; attempt < VECTOR_INDEX_ACTIVE_WAIT_ATTEMPTS; attempt++) { + List indexes = + client.describeTable(r -> r.tableName(tableName)).join().table().vectorIndexes(); + if (vectorIndexesActive(indexes, expectedCount)) { + return; + } + sleepBetweenRetries(attempt); + } + throw vectorIndexWaitTimeout(tableName, expectedCount); + } + + private static boolean vectorIndexesActive(List indexes, int expectedCount) { + return indexes.size() == expectedCount + && indexes.stream().allMatch(i -> i.indexStatus() == IndexStatus.ACTIVE); + } + + private static AssertionError vectorIndexWaitTimeout(String tableName, int expectedCount) { + return new AssertionError("Timed out waiting for " + expectedCount + + " active vector indexes on table: " + tableName); + } + + protected static SearchVectorsEnhancedRequest sharedTableSearchReadyRequest() { + return baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + } + + protected static void prepareSyncSharedTable(DynamoDbClient client, + String tableName, + Runnable createTable, + Runnable seedTable, + Supplier>> search) { + synchronized (sharedTableSetupLock(tableName)) { + prepareSharedTable( + () -> sharedTableConfigured(client, tableName), + () -> recreateSyncSharedTable(client, tableName, createTable), + () -> waitForVectorIndexesActive(client, tableName, VECTOR_INDEX_DEFINITIONS.size()), + seedTable, + search); + SEARCH_READY_TABLES.add(tableName); + } + } + + protected static void prepareAsyncSharedTable(DynamoDbAsyncClient client, + String tableName, + Runnable createTable, + Runnable seedTable, + Supplier>> search) { + synchronized (sharedTableSetupLock(tableName)) { + prepareSharedTable( + () -> sharedTableConfigured(client, tableName), + () -> recreateAsyncSharedTable(client, tableName, createTable), + () -> waitForVectorIndexesActive(client, tableName, VECTOR_INDEX_DEFINITIONS.size()), + seedTable, + search); + SEARCH_READY_TABLES.add(tableName); + } + } + + private static Object sharedTableSetupLock(String tableName) { + return SHARED_TABLE_SETUP_LOCKS.computeIfAbsent(tableName, ignored -> new Object()); + } + + private static void prepareSharedTable(Supplier tableConfigured, + Runnable recreateTable, + Runnable waitForIndexes, + Runnable seedTable, + Supplier>> search) { + if (tableConfigured.get() + && !awaitSearchResultCount(search, 1, QUICK_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + return; + } + + if (!tableConfigured.get()) { + recreateTable.run(); + waitForIndexes.run(); + seedTable.run(); + awaitTableSearchReady(search, 1); + return; + } + + waitForIndexes.run(); + seedTable.run(); + if (!awaitSearchResultCount(search, 1, TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS).isEmpty()) { + return; + } + + recreateTable.run(); + waitForIndexes.run(); + seedTable.run(); + awaitTableSearchReady(search, 1); + } + + private static boolean sharedTableConfigured(DynamoDbClient client, String tableName) { + if (!tableExists(client, tableName)) { + return false; + } + List indexes = + client.describeTable(r -> r.tableName(tableName)).table().vectorIndexes(); + return vectorIndexesActive(indexes, VECTOR_INDEX_DEFINITIONS.size()); + } + + private static boolean sharedTableConfigured(DynamoDbAsyncClient client, String tableName) { + if (!tableExists(client, tableName)) { + return false; + } + List indexes = + client.describeTable(r -> r.tableName(tableName)).join().table().vectorIndexes(); + return vectorIndexesActive(indexes, VECTOR_INDEX_DEFINITIONS.size()); + } + + private static void recreateSyncSharedTable(DynamoDbClient client, String tableName, Runnable createTable) { + if (tableExists(client, tableName)) { + client.deleteTable(r -> r.tableName(tableName)); + waitUntilTableNotExists(client, tableName); + } + createTable.run(); + client.waiter().waitUntilTableExists(r -> r.tableName(tableName)); + } + + private static void recreateAsyncSharedTable(DynamoDbAsyncClient client, String tableName, Runnable createTable) { + if (tableExists(client, tableName)) { + client.deleteTable(r -> r.tableName(tableName)).join(); + waitUntilTableNotExists(client, tableName); + } + createTable.run(); + client.waiter().waitUntilTableExists(r -> r.tableName(tableName)).join(); + } + + private static void waitUntilTableNotExists(DynamoDbClient client, String tableName) { + for (int attempt = 0; attempt < TABLE_DELETION_WAIT_ATTEMPTS; attempt++) { + if (!tableExists(client, tableName)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Timed out waiting for table deletion: " + tableName); + } + + private static void waitUntilTableNotExists(DynamoDbAsyncClient client, String tableName) { + for (int attempt = 0; attempt < TABLE_DELETION_WAIT_ATTEMPTS; attempt++) { + if (!tableExists(client, tableName)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Timed out waiting for table deletion: " + tableName); + } + + private static void awaitTableSearchReady(Supplier>> search, + int expectedCount) { + if (awaitSearchResultCount(search, expectedCount, TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS).size() < expectedCount) { + throw new AssertionError("Timed out waiting for table search results after seeding"); + } + } + + protected void prepareDedicatedIntegrationTablesOnce() { + synchronized (DEDICATED_TABLE_PREP_LOCK) { + if (dedicatedTablesPrepared) { + return; + } + for (int dimensions : new int[] {128, 512, 1024}) { + prepareDimensionTable(dimensions); + } + prepareNoHashTable(); + dedicatedTablesPrepared = true; + } + } + + protected static String dimensionTableName(int dimensions) { + return DIMENSION_TABLE_PREFIX + dimensions; + } + + protected void prepareDimensionTable(int dimensions) { + String tableName = dimensionTableName(dimensions); + String prepKey = "dimension:" + tableName; + if (PREPARED_TABLES.contains(prepKey)) { + return; + } + + EnhancedVectorIndex index = vectorIndexWithDimensions(dimensions); + StaticTableSchema schema = tableSchemaForVectorIndex(index); + + if (tableExistsCheck(tableName)) { + waitForVectorIndexesActive(tableName, 1); + seedDimensionTable(tableName, schema, index, dimensions); + if (dimensionTableSearchReady(tableName, schema, index, dimensions)) { + PREPARED_TABLES.add(prepKey); + return; + } + deleteDedicatedTable(tableName); + waitUntilDedicatedTableNotExists(tableName); + } + + createAndWaitForDedicatedTable(tableName, schema, Collections.singletonList(index)); + waitForVectorIndexesActive(tableName, 1); + seedDimensionTable(tableName, schema, index, dimensions); + awaitDimensionTableSearchReady(tableName, schema, index, dimensions); + PREPARED_TABLES.add(prepKey); + } + + private void seedDimensionTable(String tableName, + StaticTableSchema schema, + EnhancedVectorIndex index, + int dimensions) { + float[] matchingVector = generateNormalizedVector(dimensions); + float[] otherVector = seededNormalizedVector(dimensions, 2); + String matchingSk = "item-" + dimensions; + String otherSk = "other-" + dimensions; + + VectorRecord matchingRecord = new VectorRecord() + .setPk("dimension-test") + .setSk(matchingSk) + .setCategory("test") + .setDescription("Dimension test item"); + setEmbeddingForIndex(matchingRecord, index.indexName(), matchingVector); + + VectorRecord otherRecord = new VectorRecord() + .setPk("dimension-test") + .setSk(otherSk) + .setCategory("other") + .setDescription("Other dimension test item"); + setEmbeddingForIndex(otherRecord, index.indexName(), otherVector); + + dedicatedPutItem(tableName, schema, matchingRecord); + dedicatedPutItem(tableName, schema, otherRecord); + + Key matchKey = Key.builder() + .partitionValue("dimension-test") + .sortValue(matchingSk).build(); + assertEmbeddingMatches(dedicatedGetItem(tableName, schema, matchKey), index, matchingVector); + + Key otherKey = Key.builder() + .partitionValue("dimension-test") + .sortValue(otherSk).build(); + assertEmbeddingMatches(dedicatedGetItem(tableName, schema, otherKey), index, otherVector); + } + + private SearchVectorsEnhancedRequest dimensionSearchRequest(int dimensions) { + return SearchVectorsEnhancedRequest.builder() + .searchVector(generateNormalizedVector(dimensions)) + .topK(2) + .searchConditionExpression(hashCondition("dimension-test")) + .build(); + } + + private boolean dimensionTableSearchReady(String tableName, + StaticTableSchema schema, + EnhancedVectorIndex index, + int dimensions) { + return awaitSearchResultCount( + () -> dedicatedSearch(tableName, schema, index.indexName(), dimensionSearchRequest(dimensions)), + 2, + TABLE_WARMUP_SEARCH_RETRY_ATTEMPTS).size() == 2; + } + + private void awaitDimensionTableSearchReady(String tableName, + StaticTableSchema schema, + EnhancedVectorIndex index, + int dimensions) { + if (!dimensionTableSearchReady(tableName, schema, index, dimensions)) { + throw new AssertionError("Timed out waiting for dimension table search results: " + tableName); + } + } + + protected void prepareNoHashTable() { + if (PREPARED_TABLES.contains(NOHASH_TABLE_NAME)) { + return; + } + + EnhancedVectorIndex noHashIndex = tableWideVectorIndex(); + StaticTableSchema noHashSchema = tableSchemaForVectorIndex(noHashIndex); + SearchVectorsEnhancedRequest warmupRequest = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .build(); + Supplier>> warmupSearch = + () -> dedicatedSearch(NOHASH_TABLE_NAME, noHashSchema, TABLE_WIDE_INDEX, warmupRequest); + + if (tableExistsCheck(NOHASH_TABLE_NAME) + && awaitSearchResultCount(warmupSearch, 2, QUICK_SEARCH_RETRY_ATTEMPTS).size() == 2) { + PREPARED_TABLES.add(NOHASH_TABLE_NAME); + return; + } + + if (!tableExistsCheck(NOHASH_TABLE_NAME)) { + createAndWaitForDedicatedTable( + NOHASH_TABLE_NAME, noHashSchema, Collections.singletonList(noHashIndex)); + waitForVectorIndexesActive(NOHASH_TABLE_NAME, 1); + } + + dedicatedPutItem(NOHASH_TABLE_NAME, noHashSchema, + testRecord("articles", "wide-articles", "science", "Wide articles item", QUERY_VECTOR)); + dedicatedPutItem(NOHASH_TABLE_NAME, noHashSchema, + testRecord("reviews", "wide-reviews", "general", "Wide reviews item", QUERY_VECTOR)); + awaitTableSearchReady(warmupSearch, 2); + PREPARED_TABLES.add(NOHASH_TABLE_NAME); + } + + protected void waitUntilDedicatedTableNotExists(String tableName) { + for (int attempt = 0; attempt < TABLE_DELETION_WAIT_ATTEMPTS; attempt++) { + if (!tableExistsCheck(tableName)) { + return; + } + sleepBetweenRetries(attempt); + } + throw new AssertionError("Timed out waiting for table deletion: " + tableName); + } + + protected static DynamoDbClient createSearchVectorsClient() { + return createDynamoDbClient(); + } + + protected static DynamoDbAsyncClient createAsyncSearchVectorsClient() { + return createAsyncDynamoDbClient(); + } + + protected static List toFloatList(float[] array) { + List list = new ArrayList<>(array.length); + for (float f : array) { + list.add(f); + } + return list; + } + + protected static List toSearchVectorAttributeValues(float[] searchVector) { + List result = new ArrayList<>(searchVector.length); + for (float value : searchVector) { + result.add(AttributeValue.builder().n(Float.toString(value)).build()); + } + return result; + } + + protected static SearchVectorsEnhancedRequest.Builder baseSearchRequest() { + return SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5); + } + + protected static Expression hashCondition(String pkValue) { + return Expression.builder() + .expression("#pk = :pkval") + .putExpressionName("#pk", "pk") + .putExpressionValue(":pkval", AttributeValue.builder().s(pkValue).build()) + .build(); + } + + protected static Expression hashAndFilterCondition(String pkValue, String categoryValue) { + return Expression.builder() + .expression("#pk = :pkval AND #cat = :catval") + .putExpressionName("#pk", "pk") + .putExpressionName("#cat", "category") + .putExpressionValue(":pkval", AttributeValue.builder().s(pkValue).build()) + .putExpressionValue(":catval", AttributeValue.builder().s(categoryValue).build()) + .build(); + } + + protected static Expression inlineFilterOnlyCondition(String categoryValue) { + return Expression.builder() + .expression("#cat = :catval") + .putExpressionName("#cat", "category") + .putExpressionValue(":catval", AttributeValue.builder().s(categoryValue).build()) + .build(); + } + + protected static void assertThrowsContaining(ThrowingCallable callable, + Class exceptionType, + String messageSubstring) { + assertThatThrownBy(callable) + .satisfies(thrown -> { + Throwable cause = thrown instanceof CompletionException ? thrown.getCause() : thrown; + assertThat(cause).isInstanceOf(exceptionType) + .hasMessageContaining(messageSubstring); + }); + } + + protected void failsAtService(ThrowingCallable callable) { + assertThatThrownBy(callable) + .satisfies(thrown -> { + Throwable cause = thrown instanceof CompletionException ? thrown.getCause() : thrown; + assertThat(cause).isInstanceOf(DynamoDbException.class); + }); + } + + protected List> searchVectors(String indexName, SearchVectorsEnhancedRequest request) { + if (isSharedTableSearchReady()) { + return executeSearch(indexName, request); + } + return awaitNonEmptySearchResults(() -> executeSearch(indexName, request)); + } + + protected SearchVectorsEnhancedResponse searchVectorsWithResponse(String indexName, + SearchVectorsEnhancedRequest request) { + SearchVectorsEnhancedResponse response = executeSearchWithResponse(indexName, request); + if (isSharedTableSearchReady() || !response.results().isEmpty()) { + return response; + } + for (int attempt = 0; response.results().isEmpty() && attempt < DEFAULT_SEARCH_RETRY_ATTEMPTS; attempt++) { + sleepBetweenRetries(attempt); + response = executeSearchWithResponse(indexName, request); + } + return response; + } + + protected SearchVectorsEnhancedResponse searchVectorsWithResponse( + String indexName, Consumer builder) { + SearchVectorsEnhancedResponse response = executeSearchWithResponseBuilder(indexName, builder); + if (isSharedTableSearchReady() || !response.results().isEmpty()) { + return response; + } + for (int attempt = 0; response.results().isEmpty() && attempt < DEFAULT_SEARCH_RETRY_ATTEMPTS; attempt++) { + sleepBetweenRetries(attempt); + response = executeSearchWithResponseBuilder(indexName, builder); + } + return response; + } + + protected static List> awaitNonEmptySearchResults( + Supplier>> search) { + return awaitSearchResultCount(search, 1); + } + + protected static List> awaitSearchResultCount( + Supplier>> search, int expectedCount) { + return awaitSearchResultCount(search, expectedCount, DEFAULT_SEARCH_RETRY_ATTEMPTS); + } + + protected static List> awaitSearchResultCount( + Supplier>> search, + int expectedCount, + int maxAttempts) { + List> results = search.get(); + for (int attempt = 0; results.size() < expectedCount && attempt < maxAttempts; attempt++) { + sleepBetweenRetries(attempt); + results = search.get(); + } + return results; + } + + // Uses exponential backoff with a maximum delay of 1 second between retries. + private static void sleepBetweenRetries(int attempt) { + try { + long delay = Math.min(50L << Math.min(attempt, 4), 1_000L); + Thread.sleep(delay); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } + } + + protected List> searchVectorsUntilContains( + String indexName, + SearchVectorsEnhancedRequest request, + String expectedSortKey) { + List> results = + executeSearch(indexName, request); + for (int attempt = 0; attempt < DEFAULT_SEARCH_RETRY_ATTEMPTS; attempt++) { + boolean found = results.stream() + .anyMatch(r -> r.item() != null + && expectedSortKey.equals( + r.item().getSk())); + if (found) { + return results; + } + sleepBetweenRetries(attempt); + results = executeSearch(indexName, request); + } + return results; + } + + protected List> searchVectorsUntilAbsent( + String indexName, + SearchVectorsEnhancedRequest request, + String absentSortKey) { + List> results = + executeSearch(indexName, request); + for (int attempt = 0; attempt < DEFAULT_SEARCH_RETRY_ATTEMPTS; attempt++) { + boolean found = results.stream() + .anyMatch(r -> r.item() != null + && absentSortKey.equals( + r.item().getSk())); + if (!found) { + return results; + } + sleepBetweenRetries(attempt); + results = executeSearch(indexName, request); + } + return results; + } + + protected static double scoreFor(List> results, String sortKey) { + return results.stream() + .filter(r -> sortKey.equals(r.item().getSk())) + .findFirst() + .map(SearchResultItem::score) + .orElseThrow(() -> new AssertionError("No result with sort key: " + sortKey)); + } + + protected static void assertScoresOrderedByRelevance(List> results, + DistanceFunction distanceFunction) { + assertThat(results) + .extracting(SearchResultItem::score) + .isSortedAccordingTo(relevanceScoreComparator(distanceFunction)); + } + + protected static void assertMoreRelevantThan(List> results, + DistanceFunction distanceFunction, + String moreRelevantSortKey, + String lessRelevantSortKey) { + double moreRelevantScore = scoreFor(results, moreRelevantSortKey); + double lessRelevantScore = scoreFor(results, lessRelevantSortKey); + + if (distanceFunction == DistanceFunction.DOT_PRODUCT) { + assertThat(moreRelevantScore) + .as("Dot product score for '%s' should be >= score for '%s'", + moreRelevantSortKey, lessRelevantSortKey) + .isGreaterThanOrEqualTo(lessRelevantScore); + } else { + assertThat(moreRelevantScore) + .as("%s score for '%s' should be <= score for '%s'", + distanceFunction, moreRelevantSortKey, lessRelevantSortKey) + .isLessThanOrEqualTo(lessRelevantScore); + } + } + + protected static void assertArticlesCosineSearchResults(List> results) { + assertThat(results).hasSize(4); + assertThat(results.stream().map(r -> r.item().getSk()).collect(Collectors.toList())) + .containsExactlyInAnyOrder("exact-match", "near-match", "orthogonal-1", "orthogonal-2"); + results.forEach(r -> assertThat(r.item().getPk()).isEqualTo("articles")); + + assertScoresOrderedByRelevance(results, DistanceFunction.COSINE); + assertThat(results.stream().map(r -> r.item().getSk()).limit(2).collect(Collectors.toList())) + .containsExactlyInAnyOrder("exact-match", "near-match"); + assertThat(results.stream().map(r -> r.item().getSk()).skip(2).collect(Collectors.toList())) + .containsExactlyInAnyOrder("orthogonal-1", "orthogonal-2"); + assertMoreRelevantThan(results, DistanceFunction.COSINE, "exact-match", "orthogonal-1"); + assertMoreRelevantThan(results, DistanceFunction.COSINE, "near-match", "orthogonal-2"); + } + + protected static void assertProjectedAttributes(VectorRecord vectorRecord, + boolean expectCategory, + boolean expectDescription) { + assertThat(vectorRecord.getPk()).isNotNull(); + assertThat(vectorRecord.getSk()).isNotNull(); + + if (expectCategory) { + assertThat(vectorRecord.getCategory()).isNotNull(); + } else { + assertThat(vectorRecord.getCategory()).isNull(); + } + if (expectDescription) { + assertThat(vectorRecord.getDescription()).isNotNull(); + } else { + assertThat(vectorRecord.getDescription()).isNull(); + } + } + + private static VectorRecord testRecord(String pk, String sk, String category, String description, float[] vector) { + return new VectorRecord() + .setPk(pk) + .setSk(sk) + .setCategory(category) + .setDescription(description) + .setEmbeddingCosine(toFloatList(vector)) + .setEmbeddingDot(toFloatList(vector)) + .setEmbeddingEuclidean(toFloatList(vector)); + } + + private static float[] seededNormalizedVector(int dimensions, int seed) { + float[] vector = new float[dimensions]; + vector[Math.floorMod(seed, dimensions)] = 1.0f; + return vector; + } + + private static Comparator relevanceScoreComparator(DistanceFunction distanceFunction) { + switch (distanceFunction) { + case DOT_PRODUCT: + return Comparator.reverseOrder(); + case COSINE: + case EUCLIDEAN: + return Comparator.naturalOrder(); + default: + throw new IllegalArgumentException("Unsupported distance function: " + distanceFunction); + } + } + + @Nested + class TableSetupTests { + + @Test + void createTable_withVectorIndexes_succeeds() { + DescribeTableResponse response = describeTable(sharedTableName()); + assertThat(response.table().tableStatus().toString()).hasToString("ACTIVE"); + assertThat(response.table().tableName()).isEqualTo(sharedTableName()); + } + + @Test + void describeTable_exposesVectorIndexMetadata() { + DescribeTableResponse response = describeTable(sharedTableName()); + List vectorIndexes = response.table().vectorIndexes(); + assertThat(vectorIndexes) + .hasSize(3) + .anySatisfy(index -> { + assertThat(index.indexName()).isEqualTo(COSINE_INDEX); + assertThat(index.distanceFunction()).hasToString("COSINE"); + assertThat(index.dimensions()).isEqualTo(4); + assertThat(index.vectorAttribute().attributeName()).isEqualTo("embeddingCosine"); + assertThat(index.searchSchema()) + .hasSize(2) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("pk"); + assertThat(e.searchSchemaElementType()).hasToString("HASH"); + }) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("category"); + assertThat(e.searchSchemaElementType()).hasToString("INLINE_FILTER"); + }); + }) + .anySatisfy(index -> { + assertThat(index.indexName()).isEqualTo(DOT_PRODUCT_INDEX); + assertThat(index.distanceFunction()).hasToString("DOT_PRODUCT"); + assertThat(index.dimensions()).isEqualTo(4); + assertThat(index.vectorAttribute().attributeName()).isEqualTo("embeddingDot"); + assertThat(index.searchSchema()) + .hasSize(1) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("pk"); + assertThat(e.searchSchemaElementType()).hasToString("HASH"); + }); + }) + .anySatisfy(index -> { + assertThat(index.indexName()).isEqualTo(EUCLIDEAN_INDEX); + assertThat(index.distanceFunction()).hasToString("EUCLIDEAN"); + assertThat(index.dimensions()).isEqualTo(4); + assertThat(index.vectorAttribute().attributeName()).isEqualTo("embeddingEuclidean"); + assertThat(index.searchSchema()) + .hasSize(1) + .anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("pk"); + assertThat(e.searchSchemaElementType()).hasToString("HASH"); + }); + }); + } + } + + @Nested + class SearchHappyPathTests { + + @Test + void searchVectors_cosine_resultsOrderedByRelevance() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + assertScoresOrderedByRelevance(results, DistanceFunction.COSINE); + } + + @Test + void searchVectors_dotProduct_resultsOrderedByRelevance() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(DOT_PRODUCT_INDEX, request); + + assertThat(results).isNotEmpty(); + assertScoresOrderedByRelevance(results, DistanceFunction.DOT_PRODUCT); + } + + @Test + void searchVectors_euclidean_resultsOrderedByRelevance() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(EUCLIDEAN_INDEX, request); + + assertThat(results).isNotEmpty(); + assertScoresOrderedByRelevance(results, DistanceFunction.EUCLIDEAN); + } + + @Test + void searchVectors_scoresAreNonNegative() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertThat(r.score()).isGreaterThanOrEqualTo(0.0)); + } + + @Test + void searchVectors_identicalVector_bestScore() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest + .builder() + .searchVector(EXACT_MATCH_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + assertThat(results.get(0).item().getSk()).isEqualTo("exact-match"); + } + + @Test + void searchVectors_returnsTypedItemsWithScores() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item()).isNotNull(); + assertThat(r.item().getPk()).isNotNull(); + assertThat(r.item().getSk()).isNotNull(); + }); + } + + @Test + void searchVectors_projectionAll_returnsAllAttributes() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertProjectedAttributes(r.item(), true, true)); + } + + @Test + void searchVectors_projectionKeysOnly_returnsOnlyKeys() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(DOT_PRODUCT_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertProjectedAttributes(r.item(), false, false)); + } + + @Test + void searchVectors_projectionInclude_returnsKeysAndCategory() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(EUCLIDEAN_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertProjectedAttributes(r.item(), true, false)); + } + + @Test + void searchVectors_withProjectionExpression() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .attributesToProject("pk", "category") + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item().getPk()).isNotNull(); + assertThat(r.item().getCategory()).isNotNull(); + assertThat(r.item().getDescription()).isNull(); + }); + } + + @Test + void searchVectorsWithResponse_returnsConsumedCapacity() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build(); + + SearchVectorsEnhancedResponse response = + searchVectorsWithResponse(COSINE_INDEX, request); + + assertArticlesCosineSearchResults(response.results()); + assertThat(response.consumedCapacity()).isNotNull(); + } + + @Test + void searchVectorsWithResponse_returnConsumedCapacityIndexes_returnsVectorCapacity() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .returnConsumedCapacity(ReturnConsumedCapacity.INDEXES) + .build(); + + SearchVectorsEnhancedResponse response = + searchVectorsWithResponse(COSINE_INDEX, request); + + assertArticlesCosineSearchResults(response.results()); + assertThat(response.consumedCapacity()).isNotNull(); + assertThat(response.consumedCapacity().vectorSearchRequestBytes()).isNotNull(); + } + + @Test + void searchVectorsWithResponse_noCapacityRequested_returnsNull() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + SearchVectorsEnhancedResponse response = + searchVectorsWithResponse(COSINE_INDEX, request); + + assertArticlesCosineSearchResults(response.results()); + assertThat(response.consumedCapacity()).isNull(); + } + + @Test + void searchVectors_withHashCondition() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertThat(r.item().getPk()).isEqualTo("articles")); + } + + @Test + void searchVectors_withHashAndInlineFilter() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashAndFilterCondition("articles", "science")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item().getPk()).isEqualTo("articles"); + assertThat(r.item().getCategory()).isEqualTo("science"); + }); + } + + @Test + void searchVectors_withTopK() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .topK(1) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).hasSize(1); + } + + @Test + void searchVectors_withBuilderConsumer_returnsOrderedCosineResults() { + Consumer requestBuilder = + b -> b.searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition("articles")); + + List> results = + awaitNonEmptySearchResults(() -> executeSearchWithBuilder(COSINE_INDEX, requestBuilder)); + + assertArticlesCosineSearchResults(results); + } + + @Test + void searchVectorsWithResponse_withBuilderConsumer_returnsOrderedCosineResults() { + SearchVectorsEnhancedResponse response = + searchVectorsWithResponse(COSINE_INDEX, + b -> b.searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition("articles"))); + + assertArticlesCosineSearchResults(response.results()); + } + + @Test + void searchVectors_emptyResults() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("nonexistent-partition")) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isEmpty(); + } + + @Test + void searchVectors_twoQueryVectorsOnCosineIndex_topResultSortKeyDiffers() { + SearchVectorsEnhancedRequest primaryQuery = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + SearchVectorsEnhancedRequest alternateQuery = SearchVectorsEnhancedRequest.builder() + .searchVector(ALTERNATE_QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + List> primaryResults = searchVectors(COSINE_INDEX, primaryQuery); + List> alternateResults = searchVectors(COSINE_INDEX, alternateQuery); + + assertThat(primaryResults).isNotEmpty(); + assertThat(alternateResults).isNotEmpty(); + assertThat(primaryResults.get(0).item().getSk()) + .isNotEqualTo(alternateResults.get(0).item().getSk()); + } + + @Test + void searchVectors_dotProductIndex_resultsOrderedByScoreDescending() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(DOT_PRODUCT_QUERY_VECTOR) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + List> results = searchVectors(DOT_PRODUCT_INDEX, request); + + assertThat(results).isNotEmpty(); + assertThat(results) + .extracting(SearchResultItem::score) + .isSortedAccordingTo(Comparator.reverseOrder()); + assertThat(results.get(0).item().getSk()).isEqualTo("exact-match"); + } + + @Test + void searchVectors_euclideanIndex_zeroQueryVector_nearestItemRanksFirst() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {0.0f, 0.0f, 0.0f, 0.0f}) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + List> results = searchVectors(EUCLIDEAN_INDEX, request); + + assertThat(results).isNotEmpty(); + assertThat(results.get(0).item().getSk()).isEqualTo("near-match"); + } + + @Test + void searchVectors_sameQueryVectorAcrossIndexes_returnsSameSortKeySet() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + Set cosineSortKeys = searchVectors(COSINE_INDEX, request).stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toSet()); + Set dotSortKeys = searchVectors(DOT_PRODUCT_INDEX, request).stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toSet()); + Set euclideanSortKeys = searchVectors(EUCLIDEAN_INDEX, request).stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toSet()); + + assertThat(cosineSortKeys).isEqualTo(dotSortKeys).isEqualTo(euclideanSortKeys); + } + + @Test + void searchVectors_sameItemAcrossIndexes_cosineScoresBounded_dotScoresUnbounded() { + VectorRecord amplifiedRecord = new VectorRecord() + .setPk("articles") + .setSk("dot-unbounded-item") + .setCategory("science") + .setDescription("Amplified dot embedding") + .setEmbeddingDot(toFloatList(new float[] {3.0f, 0.0f, 0.0f, 0.0f})); + executePut(amplifiedRecord); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(DOT_PRODUCT_QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + double cosineScore = scoreFor( + searchVectors(COSINE_INDEX, request), + "exact-match"); + List> + dotResults = + searchVectorsUntilContains( + DOT_PRODUCT_INDEX, request, + "dot-unbounded-item"); + double dotScore = scoreFor( + dotResults, "dot-unbounded-item"); + + assertThat(cosineScore).isBetween(0.0, 1.0); + assertThat(dotScore).isGreaterThan(1.0); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("dot-unbounded-item") + .build()); + } + } + + @Test + void searchVectors_emptyAttributesToProject_usesIndexLevelProjection() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> cosineResults = searchVectors(COSINE_INDEX, request); + List> dotResults = searchVectors(DOT_PRODUCT_INDEX, request); + List> euclideanResults = searchVectors(EUCLIDEAN_INDEX, request); + + assertThat(cosineResults).isNotEmpty(); + assertThat(dotResults).isNotEmpty(); + assertThat(euclideanResults).isNotEmpty(); + cosineResults.forEach(r -> assertProjectedAttributes(r.item(), true, true)); + dotResults.forEach(r -> assertProjectedAttributes(r.item(), false, false)); + euclideanResults.forEach(r -> assertProjectedAttributes(r.item(), true, false)); + } + + @Test + void searchVectors_topK100WithFourMatchingItems_returnsFourResults() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .topK(100) + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).hasSize(4); + } + + @Test + void searchVectors_topKNotSet_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "missing field `TopK`"); + } + } + + @Nested + class WritePathTests { + + @Test + void writePath_validVectorPersistedAndSearchable() { + VectorRecord newRecord = new VectorRecord() + .setPk("articles").setSk("write-test-item").setCategory("science") + .setDescription("Write path test") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingDot(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(newRecord); + + SearchVectorsEnhancedRequest request = + SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition("articles")) + .build(); + + try { + List> + results = searchVectorsUntilContains( + COSINE_INDEX, request, + "write-test-item"); + List sks = results.stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sks).contains("write-test-item"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("write-test-item") + .build()); + } + } + + @Test + void writePath_updateVectorThenSearch_cosineEmbeddingOnlyUpdated_rankingReflectsNewVector() { + VectorRecord vectorRecord = new VectorRecord() + .setPk("articles") + .setSk("update-test-item") + .setCategory("science") + .setDescription("Update path test") + .setEmbeddingCosine(toFloatList(ORTHOGONAL_2_VECTOR)) + .setEmbeddingDot(toFloatList(ORTHOGONAL_2_VECTOR)) + .setEmbeddingEuclidean(toFloatList(ORTHOGONAL_2_VECTOR)); + executePut(vectorRecord); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + vectorRecord.setEmbeddingCosine( + toFloatList(QUERY_VECTOR)); + executePut(vectorRecord); + + List sortKeys = + searchVectorsUntilContains( + COSINE_INDEX, request, + "update-test-item") + .stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys) + .contains("update-test-item"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("update-test-item") + .build()); + } + } + + @Test + void writePath_cosineEmbeddingOnlySet_itemAppearsInCosineIndexResults() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("cosine-only-item") + .setCategory("science") + .setDescription("Cosine embedding only"); + setEmbeddingForIndex(record, COSINE_INDEX, QUERY_VECTOR); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + List sortKeys = + searchVectorsUntilContains( + COSINE_INDEX, request, + "cosine-only-item") + .stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys) + .contains("cosine-only-item"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("cosine-only-item") + .build()); + } + } + + @Test + void writePath_dotEmbeddingAbsent_itemAbsentFromDotProductIndexResults() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("no-dot-item") + .setCategory("science") + .setDescription("Missing dot embedding") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + List sortKeys = searchVectors(DOT_PRODUCT_INDEX, request).stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys).doesNotContain("no-dot-item"); + } finally { + executeDelete(Key.builder().partitionValue("articles").sortValue("no-dot-item").build()); + } + } + + @Test + void writePath_deleteItem_itemAbsentFromSearchResults() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("delete-test-item") + .setCategory("science") + .setDescription("Delete path test") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingDot(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + searchVectorsUntilContains(COSINE_INDEX, request, "delete-test-item"); + + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("delete-test-item") + .build()); + + List sortKeys = searchVectorsUntilAbsent( + COSINE_INDEX, request, "delete-test-item") + .stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys).doesNotContain("delete-test-item"); + } + + @Test + void writePath_updateClearsEmbedding_itemAbsentFromSearchResults() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("clear-embedding-item") + .setCategory("science") + .setDescription("Clear embedding test") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingDot(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + searchVectorsUntilContains(COSINE_INDEX, request, "clear-embedding-item"); + + record.setEmbeddingCosine(null); + record.setEmbeddingDot(null); + record.setEmbeddingEuclidean(null); + executePut(record); + + List sortKeys = searchVectorsUntilAbsent( + COSINE_INDEX, request, "clear-embedding-item") + .stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys).doesNotContain("clear-embedding-item"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("clear-embedding-item") + .build()); + } + } + + @Test + void writePath_updateNonVectorFieldsOnly_itemStillSearchable() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("metadata-update-item") + .setCategory("science") + .setDescription("Original description") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingDot(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + searchVectorsUntilContains(COSINE_INDEX, request, "metadata-update-item"); + + record.setDescription("Updated description only"); + executePut(record); + + // Retry until the updated description is visible in search results, + // not just until the item exists (it may return stale data). + SearchResultItem result = null; + for (int attempt = 0; attempt < DEFAULT_SEARCH_RETRY_ATTEMPTS; attempt++) { + List> results = + executeSearch(COSINE_INDEX, request); + result = results.stream() + .filter(r -> "metadata-update-item".equals(r.item().getSk())) + .findFirst() + .orElse(null); + if (result != null && "Updated description only".equals(result.item().getDescription())) { + break; + } + sleepBetweenRetries(attempt); + } + assertThat(result).isNotNull(); + assertThat(result.item().getDescription()) + .isEqualTo("Updated description only"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("metadata-update-item") + .build()); + } + } + + @Test + void writePath_missingInlineFilterAttribute_itemSearchableWithHashOnlyCondition() { + VectorRecord record = new VectorRecord() + .setPk("articles") + .setSk("no-category-item") + .setDescription("Missing inline filter attribute") + .setEmbeddingCosine(toFloatList(QUERY_VECTOR)) + .setEmbeddingDot(toFloatList(QUERY_VECTOR)) + .setEmbeddingEuclidean(toFloatList(QUERY_VECTOR)); + executePut(record); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + try { + List sortKeys = + searchVectorsUntilContains( + COSINE_INDEX, request, "no-category-item") + .stream() + .map(r -> r.item().getSk()) + .collect(Collectors.toList()); + assertThat(sortKeys).contains("no-category-item"); + } finally { + executeDelete(Key.builder() + .partitionValue("articles") + .sortValue("no-category-item") + .build()); + } + } + } + + @Nested + class DocumentApiTests { + + @Test + void searchVectors_documentApi_returnsEnhancedDocuments() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectorsDocument(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + assertThat(results.get(0).item().getString("pk")).isNotNull(); + } + + @Test + void searchVectors_documentApi_scoresPresent() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectorsDocument(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertThat(r.score()).isGreaterThanOrEqualTo(0.0)); + } + + @Test + void searchVectors_documentApi_projectionBehavior() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .attributesToProject("pk", "category") + .build(); + + List> results = searchVectorsDocument(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item().getString("pk")).isNotNull(); + assertThat(r.item().getString("description")).isNull(); + }); + } + + @Test + void searchVectors_documentApi_withCondition() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> results = searchVectorsDocument(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> assertThat(r.item().getString("pk")).isEqualTo("articles")); + } + + @Test + void searchVectors_documentApi_withoutCustomConverterProvider_returnsProjectedAttributes() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .attributesToProject("pk", "category") + .build(); + + List> results = + searchVectorsDocument(COSINE_INDEX, request, false); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item().getString("pk")).isEqualTo("articles"); + assertThat(r.item().getString("category")).isNotNull(); + }); + } + + @Test + void searchVectors_documentApi_withCustomConverterProvider_searchSucceedsAndConverterApplied() { + EnhancedDocument docWithInteger = EnhancedDocument.builder() + .putNumber("testInteger", 7) + .build(); + Map mapped = documentSchema(true).itemToMap(docWithInteger, true); + assertThat(mapped.get("testInteger").n()).isEqualTo("17"); + + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + List> defaultResults = + searchVectorsDocument(COSINE_INDEX, request, false); + List> customResults = + searchVectorsDocument(COSINE_INDEX, request, true); + + assertThat(customResults).isNotEmpty(); + assertThat(customResults.stream().map(r -> r.item().getString("sk")).collect(Collectors.toList())) + .containsExactlyElementsOf(defaultResults.stream() + .map(r -> r.item().getString("sk")) + .collect(Collectors.toList())); + } + + @Test + void searchVectors_documentApi_minimalSchemaBuilder_matchesDefaultProviderBehavior() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + DocumentTableSchema minimalSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(primaryIndexName(), "pk", + AttributeValueType.S) + .addIndexSortKey(primaryIndexName(), "sk", + AttributeValueType.S) + .vectorIndexes(VECTOR_INDEX_DEFINITIONS) + .build(); + + List> defaultResults = + searchVectorsDocument(COSINE_INDEX, request, false); + List> minimalResults = + awaitNonEmptySearchResults( + () -> executeSearchDocument(COSINE_INDEX, request, minimalSchema)); + + assertThat(minimalResults.stream().map(r -> r.item().getString("sk")).collect(Collectors.toList())) + .containsExactlyElementsOf(defaultResults.stream() + .map(r -> r.item().getString("sk")) + .collect(Collectors.toList())); + } + } + + @Nested + @TestInstance(TestInstance.Lifecycle.PER_CLASS) + class NoHashSchemaTests { + private final EnhancedVectorIndex noHashIndex = + tableWideVectorIndex(); + private final StaticTableSchema noHashSchema = + tableSchemaForVectorIndex(noHashIndex); + + @Test + void createTable_vectorIndexWithoutSearchSchema_describeTableOmitsSearchSchema() { + DescribeTableResponse response = + describeTable(NOHASH_TABLE_NAME); + assertThat(response.table().vectorIndexes()) + .hasSize(1); + assertThat(response.table().vectorIndexes() + .get(0).searchSchema()).isEmpty(); + } + + @Test + void searchVectors_tableWideIndex_withoutHashCondition_returnsResultsFromAllPartitions() { + SearchVectorsEnhancedRequest request = + SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(10) + .build(); + + List> results = + awaitSearchResultCount( + () -> dedicatedSearch( + NOHASH_TABLE_NAME, noHashSchema, + TABLE_WIDE_INDEX, request), + 2); + + Set partitionKeys = results.stream() + .map(r -> r.item().getPk()) + .collect(Collectors.toSet()); + + assertThat(partitionKeys) + .containsExactlyInAnyOrder( + "articles", "reviews"); + } + + @Test + void searchVectors_tableWideIndex_withHashCondition_failsAtService() { + SearchVectorsEnhancedRequest request = + SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression( + hashCondition("articles")) + .build(); + + failsAtService( + () -> dedicatedSearch( + NOHASH_TABLE_NAME, noHashSchema, + TABLE_WIDE_INDEX, request)); + } + } + + @Nested + class DimensionVariantTests { + + @Test + void searchVectors_128DimensionIndex_putAndSearch_returnsMatchingItemWithScore() { + verifyDimensionRoundTrip(128); + } + + @Test + void searchVectors_512DimensionIndex_putAndSearch_returnsMatchingItemWithScore() { + verifyDimensionRoundTrip(512); + } + + @Test + void searchVectors_1024DimensionIndex_putAndSearch_returnsMatchingItemWithScore() { + verifyDimensionRoundTrip(1024); + } + + @Test + void searchVectors_4096DimensionIndex_putAndSearch_returnsMatchingItemWithScore() { + prepareDimensionTable(4096); + verifyDimensionRoundTrip(4096); + } + + private void verifyDimensionRoundTrip(int dimensions) { + String tableName = dimensionTableName(dimensions); + EnhancedVectorIndex index = + vectorIndexWithDimensions(dimensions); + StaticTableSchema schema = + tableSchemaForVectorIndex(index); + float[] matchingVector = + generateNormalizedVector(dimensions); + String matchingSk = "item-" + dimensions; + String otherSk = "other-" + dimensions; + + VectorIndexDescription indexDescription = + describeTable(tableName).table().vectorIndexes().get(0); + assertThat(indexDescription.indexName()) + .isEqualTo(index.indexName()); + assertThat(indexDescription.dimensions()) + .isEqualTo(dimensions); + assertThat(indexDescription.distanceFunction()) + .hasToString("COSINE"); + assertThat(indexDescription + .vectorAttribute().attributeName()) + .isEqualTo("embedding"); + assertThat(indexDescription.searchSchema()) + .hasSize(1) + .anySatisfy(element -> { + assertThat(element.attributeName()) + .isEqualTo("pk"); + assertThat(element + .searchSchemaElementType()) + .hasToString("HASH"); + }); + + SearchVectorsEnhancedRequest request = + SearchVectorsEnhancedRequest.builder() + .searchVector(matchingVector) + .topK(2) + .searchConditionExpression( + hashCondition("dimension-test")) + .build(); + + List> results = + awaitSearchResultCount( + () -> dedicatedSearch( + tableName, schema, + index.indexName(), request), + 2, + DEFAULT_SEARCH_RETRY_ATTEMPTS); + + assertThat(results).hasSize(2); + + VectorRecord retrievedMatch = + results.get(0).item(); + assertThat(retrievedMatch.getPk()) + .isEqualTo("dimension-test"); + assertThat(retrievedMatch.getSk()) + .isEqualTo(matchingSk); + assertThat(retrievedMatch.getCategory()) + .isEqualTo("test"); + assertThat(retrievedMatch.getDescription()) + .isEqualTo("Dimension test item"); + + VectorRecord retrievedOther = + results.get(1).item(); + assertThat(retrievedOther.getSk()) + .isEqualTo(otherSk); + assertThat(retrievedOther.getCategory()) + .isEqualTo("other"); + assertThat(retrievedOther.getDescription()) + .isEqualTo("Other dimension test item"); + + assertScoresOrderedByRelevance( + results, DistanceFunction.COSINE); + assertMoreRelevantThan( + results, DistanceFunction.COSINE, + matchingSk, otherSk); + } + } + + @Nested + class CreateTableLimitTests { + + @Test + void createTable_tooManyVectorIndexes_failsAtService() { + List sixIndexes = + IntStream.range(0, 6) + .mapToObj(i -> EnhancedVectorIndex.builder() + .indexName("vector-index-" + i) + .vectorAttributeName("embedding-" + i) + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b + .attributeName("pk") + .searchSchemaElementType(HASH)) + .build() + ).collect(Collectors.toList()); + CreateTableEnhancedRequest request = CreateTableEnhancedRequest.builder() + .vectorIndexes(sixIndexes) + .build(); + String tempTableName = createSearchVectorsTableName(); + + assertThrowsContaining(() -> executeTempTableCreate(tempTableName, VECTOR_TABLE_SCHEMA, request), + DynamoDbException.class, + "One or more parameter values were invalid: " + + "VectorIndex count exceeds the per-table limit of 5"); + } + + @Test + void createTable_dimensionsExceedsLimit_failsAtService() { + CreateTableEnhancedRequest request = + CreateTableEnhancedRequest.builder() + .vectorIndexes( + EnhancedVectorIndex.builder() + .indexName("big-dims-index") + .vectorAttributeName("embedding") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(5000) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build()) + .build(); + String tempTableName = createSearchVectorsTableName(); + + assertThrowsContaining(() -> executeTempTableCreate(tempTableName, VECTOR_TABLE_SCHEMA, request), + DynamoDbException.class, + "One or more parameter values were invalid: " + + "Number of dimensions must be between 1 and 4096 inclusive."); + } + + @Test + void createTable_tooManyInlineFilters_failsAtService() { + EnhancedVectorIndex vectorIndex = buildVectorIndexWithInlineFilters(19); + CreateTableEnhancedRequest request = CreateTableEnhancedRequest.builder() + .vectorIndexes(vectorIndex) + .build(); + String tempTableName = createSearchVectorsTableName(); + + assertThrowsContaining(() -> executeTempTableCreate(tempTableName, + createTableLimitTestSchema(), + request), + DynamoDbException.class, + "One or more parameter values were invalid: Value '19' at 'SearchSchema' failed" + + " to satisfy constraint: Member must have INLINE_FILTER count less than or equal to 18"); + } + + @Test + void createTable_duplicateVectorIndexNames_failsAtService() { + EnhancedVectorIndex firstIndex = EnhancedVectorIndex.builder() + .indexName("duplicate-index") + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(); + EnhancedVectorIndex secondIndex = EnhancedVectorIndex.builder() + .indexName("duplicate-index") + .vectorAttributeName("embeddingDot") + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .dimensions(4) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(); + CreateTableEnhancedRequest request = CreateTableEnhancedRequest.builder() + .vectorIndexes(firstIndex, secondIndex) + .build(); + String tempTableName = createSearchVectorsTableName(); + + assertThrowsContaining(() -> executeTempTableCreate(tempTableName, VECTOR_TABLE_SCHEMA, request), + DynamoDbException.class, + "One or more parameter values were invalid: " + + "Duplicate index name: duplicate-index"); + } + + @Test + void createTable_tooManyProjectedAttributes_failsAtService() { + EnhancedVectorIndex vectorIndex = buildVectorIndexWithProjectedAttributes(21); + CreateTableEnhancedRequest request = CreateTableEnhancedRequest.builder() + .vectorIndexes(vectorIndex) + .build(); + String tempTableName = createSearchVectorsTableName(); + + assertThrowsContaining(() -> executeTempTableCreate(tempTableName, + createTableLimitTestSchema(), + request), + DynamoDbException.class, + "1 validation error detected: Value '[proj0, proj1, proj2, proj3, proj4, " + + "proj5, proj6, proj7, proj8, proj9, proj10, proj11, proj12, proj13, proj14, proj15, proj16, " + + "proj17, proj18, proj19, proj20]' at 'vectorIndexes.1.member.projection.nonKeyAttributes' " + + "failed to satisfy constraint: Member must have length less than or equal to 20"); + } + } + + @Nested + class LowLevelClientSmokeTests { + + @Test + void searchVectors_lowLevelClient_returnsResults() { + SearchVectorsRequest request = SearchVectorsRequest.builder() + .tableName(sharedTableName()) + .indexName(COSINE_INDEX) + .searchVector(toSearchVectorAttributeValues(QUERY_VECTOR)) + .topK(5) + .searchConditionExpression("#pk = :pkval") + .expressionAttributeNames( + Collections.singletonMap("#pk", "pk")) + .expressionAttributeValues( + Collections.singletonMap( + ":pkval", + AttributeValue.builder().s("articles").build())) + .build(); + + SearchVectorsResponse response = executeLowLevelSearchVectors(request); + + assertThat(response.searchResults()).isNotEmpty(); + assertThat(response.searchResults().get(0).score()).isNotNull(); + assertThat(response.searchResults().get(0).item().get("pk").s()) + .isEqualTo("articles"); + } + } + + @Nested + class NegativeTests { + + @Test + void searchVectors_emptySearchVector_failsAtService() { + SearchVectorsEnhancedRequest request = + SearchVectorsEnhancedRequest.builder() + .searchVector(new float[0]) + .topK(5) + .searchConditionExpression(hashCondition("articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "1 validation error detected: Value at 'SearchVector' failed to satisfy constraint: " + + "Member must have length greater than or equal to 1"); + } + + @Test + void searchVectors_nullSearchVector_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "missing field `SearchVector`"); + } + + @Test + void searchVectors_topKZero_failsAtService() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .topK(0).build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "validation error detected: Value at 'TopK' failed to satisfy constraint: " + + "Member must have value greater than or equal to 1"); + } + + @Test + void searchVectors_topKNegative_failsAtService() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .topK(-1).build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "1 validation error detected: Value at 'TopK' failed to satisfy constraint: " + + "Member must have value greater than or equal to 1"); + } + + @Test + void searchVectors_topKExceedsLimit_failsAtService() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .topK(101).build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "Provided TopK value '101' is out of valid range. " + + "The value must be between 1 and 100 inclusive"); + } + + @Test + void searchVectors_wrongDimensionCount_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 0.0f, 0.0f}) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "Input search vector dimension 3 does not match vector index dimension 4"); + } + + @Test + void writePath_invalidDimensionCount_failsAtService() { + VectorRecord badRecord = new VectorRecord() + .setPk("articles") + .setSk("bad-dims") + .setCategory("science") + .setDescription("Bad dimensions") + .setEmbeddingCosine(toFloatList(new float[] {1.0f, 0.0f, 0.0f})) + .setEmbeddingDot(toFloatList(new float[] {1.0f, 0.0f, 0.0f})) + .setEmbeddingEuclidean(toFloatList(new float[] {1.0f, 0.0f, 0.0f})); + + assertThrowsContaining(() -> executePut(badRecord), + DynamoDbException.class, + "Invalid size for parameter embeddingCosine, Expected: 4, Actual: 3"); + } + + @Test + void searchVectors_nonExistentIndex_failsAtService() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .build(); + + assertThrowsContaining(() -> searchVectors("no-such-index", request), + IllegalArgumentException.class, + "Attempt to execute an operation that requires a vector index without " + + "defining the index in the table metadata. Index name: no-such-index"); + } + + @Test + void searchVectors_missingHashCondition_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .build(); + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "SearchConditionExpression must be provided when SearchSchema has a HASH key"); + } + + @Test + void searchVectors_searchVectorContainsNaN_throwsIllegalArgumentExceptionBeforeServiceCall() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, Float.NaN, 0.0f + , 0.0f}) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + IllegalArgumentException.class, + "NaN is not supported by the default converters."); + } + + @Test + void searchVectors_searchVectorContainsInfinity_throwsIllegalArgumentExceptionBeforeServiceCall() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, + Float.POSITIVE_INFINITY, 0.0f, 0.0f}) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + IllegalArgumentException.class, + "Infinite numbers are not supported by the default converters."); + } + + @Test + void writePath_embeddingContainsNaN_throwsIllegalArgumentExceptionBeforeServiceCall() { + VectorRecord badRecord = new VectorRecord() + .setPk("articles") + .setSk("nan-embedding") + .setCategory("science") + .setDescription("NaN embedding") + .setEmbeddingCosine(toFloatList(new float[] {1.0f, Float.NaN, 0.0f, 0.0f})); + + assertThrowsContaining(() -> executePut(badRecord), + IllegalArgumentException.class, + "NaN is not supported by the default converters."); + } + + @Test + void writePath_embeddingContainsInfinity_throwsIllegalArgumentExceptionBeforeServiceCall() { + VectorRecord badRecord = new VectorRecord() + .setPk("articles") + .setSk("infinity-embedding") + .setCategory("science") + .setDescription("Infinity embedding") + .setEmbeddingCosine(toFloatList(new float[] {1.0f, Float.POSITIVE_INFINITY, 0.0f, 0.0f})); + + assertThrowsContaining(() -> executePut(badRecord), + IllegalArgumentException.class, + "Infinite numbers are not supported by the default converters."); + } + + @Test + void searchVectors_inlineFilterExpressionWithoutHashCondition_failsAtService() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(inlineFilterOnlyCondition("science")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "SearchConditionExpression must have all HASH attributes" + + " in configured SearchSchema"); + } + + @Test + void searchVectors_malformedSearchConditionExpression_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(Expression.builder() + .expression("#pk === :pkval") + .putExpressionName("#pk", "pk") + .putExpressionValue(":pkval", AttributeValue.builder().s("articles").build()) + .build()) + .build(); + + failsAtService(() -> searchVectors(COSINE_INDEX, request)); + } + + @Test + void searchVectors_emptySearchConditionExpression_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(QUERY_VECTOR) + .topK(5) + .searchConditionExpression(Expression.builder().expression("").build()) + .build(); + + failsAtService(() -> searchVectors(COSINE_INDEX, request)); + } + + @Test + void searchVectors_documentApi_projectNonExistentAttribute_returnsNullForMissingField() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .attributesToProject("pk", "nonExistentAttribute") + .build(); + + List> results = searchVectorsDocument(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item()).isNotNull(); + assertThat(r.item().getString("pk")).isEqualTo("articles"); + assertThat(r.item().getString("nonExistentAttribute")).isNull(); + }); + } + + @Test + void searchVectors_projectionExpressionLeadingDot_returnsResultsWithNullItems() { + SearchVectorsEnhancedRequest request = baseSearchRequest() + .searchConditionExpression(hashCondition("articles")) + .attributesToProject(".pk") + .build(); + + List> results = searchVectors(COSINE_INDEX, request); + + assertThat(results).isNotEmpty(); + results.forEach(r -> { + assertThat(r.item()).isNull(); + assertThat(r.score()).isGreaterThanOrEqualTo(0.0); + }); + } + + @Test + void searchVectors_queryVectorLongerThanIndexDimensions_failsAtService() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f}) + .topK(5) + .searchConditionExpression(hashCondition( + "articles")) + .build(); + + assertThrowsContaining(() -> searchVectors(COSINE_INDEX, request), + DynamoDbException.class, + "Input search vector dimension 6 does not match vector index dimension 4"); + } + + @Test + void createTable_searchSchemaWithInlineFilterOnly_noHashElement_succeeds() { + EnhancedVectorIndex filterOnlyIndex = + EnhancedVectorIndex.builder() + .indexName("filter-only-index") + .vectorAttributeName("embeddingCosine") + .distanceFunction(DistanceFunction.COSINE) + .dimensions(4) + .projection(p -> p.projectionType( + ProjectionType.ALL)) + .addSearchSchemaElement( + b -> b.attributeName("category") + .searchSchemaElementType( + INLINE_FILTER)) + .build(); + CreateTableEnhancedRequest request = + CreateTableEnhancedRequest.builder() + .vectorIndexes(filterOnlyIndex) + .build(); + + if (!tableExistsCheck(FILTER_ONLY_TABLE_NAME)) { + executeTempTableCreate( + FILTER_ONLY_TABLE_NAME, + VECTOR_TABLE_SCHEMA, request); + } + DescribeTableResponse response = + describeTable(FILTER_ONLY_TABLE_NAME); + assertThat(response.table().vectorIndexes()) + .hasSize(1); + assertThat(response.table().vectorIndexes() + .get(0).indexName()) + .isEqualTo("filter-only-index"); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordBean.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordBean.java new file mode 100644 index 000000000000..8c9f4a732899 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordBean.java @@ -0,0 +1,91 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; + +/** + * Annotated bean with a vector index that defines only an INLINE_FILTER search schema element (no HASH key). + */ +@DynamoDbBean +public class InlineFilterOnlyVectorRecordBean { + private String pk; + private String sk; + private String category; + private List embedding; + + @DynamoDbPartitionKey + public String getPk() { + return pk; + } + + public void setPk(String pk) { + this.pk = pk; + } + + @DynamoDbSortKey + public String getSk() { + return sk; + } + + public void setSk(String sk) { + this.sk = sk; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"filter-only-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbVectorAttribute(indexName = "filter-only-index", dimensions = 4, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InlineFilterOnlyVectorRecordBean that = (InlineFilterOnlyVectorRecordBean) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(category, that.category) + && Objects.equals(embedding, that.embedding); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, category, embedding); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordImmutable.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordImmutable.java new file mode 100644 index 000000000000..332568b3999a --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/InlineFilterOnlyVectorRecordImmutable.java @@ -0,0 +1,120 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; + +/** + * Immutable equivalent of {@link InlineFilterOnlyVectorRecordBean} for end-to-end annotation testing. + */ +@DynamoDbImmutable(builder = InlineFilterOnlyVectorRecordImmutable.Builder.class) +public class InlineFilterOnlyVectorRecordImmutable { + private final String pk; + private final String sk; + private final String category; + private final List embedding; + + private InlineFilterOnlyVectorRecordImmutable(Builder b) { + this.pk = b.pk; + this.sk = b.sk; + this.category = b.category; + this.embedding = b.embedding; + } + + @DynamoDbPartitionKey + public String pk() { + return pk; + } + + @DynamoDbSortKey + public String sk() { + return sk; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"filter-only-index"}) + public String category() { + return category; + } + + @DynamoDbVectorAttribute(indexName = "filter-only-index", dimensions = 4, distanceFunction = DistanceFunction.COSINE) + public List embedding() { + return embedding; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + InlineFilterOnlyVectorRecordImmutable that = (InlineFilterOnlyVectorRecordImmutable) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(category, that.category) + && Objects.equals(embedding, that.embedding); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, category, embedding); + } + + public static final class Builder { + private String pk; + private String sk; + private String category; + private List embedding; + + private Builder() { + } + + public Builder pk(String pk) { + this.pk = pk; + return this; + } + + public Builder sk(String sk) { + this.sk = sk; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder embedding(List embedding) { + this.embedding = embedding; + return this; + } + + public InlineFilterOnlyVectorRecordImmutable build() { + return new InlineFilterOnlyVectorRecordImmutable(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorCreateTableLimitRecord.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorCreateTableLimitRecord.java new file mode 100644 index 000000000000..63cccffedb5a --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorCreateTableLimitRecord.java @@ -0,0 +1,94 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; + +/** + * IT-only record for createTable limit validation tests requiring many indexed attributes. + */ +public class VectorCreateTableLimitRecord { + private String pk; + private String sk; + private List embeddingCosine; + private final String[] filterAttributes = new String[19]; + private final String[] projectionAttributes = new String[21]; + + public String getPk() { + return pk; + } + + public VectorCreateTableLimitRecord setPk(String pk) { + this.pk = pk; + return this; + } + + public String getSk() { + return sk; + } + + public VectorCreateTableLimitRecord setSk(String sk) { + this.sk = sk; + return this; + } + + public List getEmbeddingCosine() { + return embeddingCosine; + } + + public VectorCreateTableLimitRecord setEmbeddingCosine(List embeddingCosine) { + this.embeddingCosine = embeddingCosine; + return this; + } + + public String getFilterAttribute(int index) { + return filterAttributes[index]; + } + + public VectorCreateTableLimitRecord setFilterAttribute(int index, String value) { + filterAttributes[index] = value; + return this; + } + + public String getProjectionAttribute(int index) { + return projectionAttributes[index]; + } + + public VectorCreateTableLimitRecord setProjectionAttribute(int index, String value) { + projectionAttributes[index] = value; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorCreateTableLimitRecord that = (VectorCreateTableLimitRecord) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(embeddingCosine, that.embeddingCosine); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, embeddingCosine); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecord.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecord.java new file mode 100644 index 000000000000..a9ed361ce189 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecord.java @@ -0,0 +1,115 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; + +public class VectorRecord { + private String pk; + private String sk; + private String category; + private String description; + private List embeddingCosine; + private List embeddingDot; + private List embeddingEuclidean; + + public String getPk() { + return pk; + } + + public VectorRecord setPk(String pk) { + this.pk = pk; + return this; + } + + public String getSk() { + return sk; + } + + public VectorRecord setSk(String sk) { + this.sk = sk; + return this; + } + + public String getCategory() { + return category; + } + + public VectorRecord setCategory(String category) { + this.category = category; + return this; + } + + public String getDescription() { + return description; + } + + public VectorRecord setDescription(String description) { + this.description = description; + return this; + } + + public List getEmbeddingCosine() { + return embeddingCosine; + } + + public VectorRecord setEmbeddingCosine(List embeddingCosine) { + this.embeddingCosine = embeddingCosine; + return this; + } + + public List getEmbeddingDot() { + return embeddingDot; + } + + public VectorRecord setEmbeddingDot(List embeddingDot) { + this.embeddingDot = embeddingDot; + return this; + } + + public List getEmbeddingEuclidean() { + return embeddingEuclidean; + } + + public VectorRecord setEmbeddingEuclidean(List embeddingEuclidean) { + this.embeddingEuclidean = embeddingEuclidean; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorRecord that = (VectorRecord) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(category, that.category) + && Objects.equals(description, that.description) + && Objects.equals(embeddingCosine, that.embeddingCosine) + && Objects.equals(embeddingDot, that.embeddingDot) + && Objects.equals(embeddingEuclidean, that.embeddingEuclidean); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, category, description, embeddingCosine, embeddingDot, embeddingEuclidean); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordBean.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordBean.java new file mode 100644 index 000000000000..42cb73c093b8 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordBean.java @@ -0,0 +1,104 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; + +/** + * Annotated bean equivalent of {@link VectorRecord} for testing the bean-annotation-driven vector index path end-to-end. Uses a + * single cosine vector index with HASH and INLINE_FILTER search schema elements. + */ +@DynamoDbBean +public class VectorRecordBean { + private String pk; + private String sk; + private String category; + private String description; + private List embedding; + + @DynamoDbPartitionKey + public String getPk() { + return pk; + } + + public void setPk(String pk) { + this.pk = pk; + } + + @DynamoDbSortKey + public String getSk() { + return sk; + } + + public void setSk(String sk) { + this.sk = sk; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"cosine-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"cosine-index"}) + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @DynamoDbVectorAttribute(indexName = "cosine-index", dimensions = 4, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorRecordBean that = (VectorRecordBean) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(category, that.category) + && Objects.equals(description, that.description) + && Objects.equals(embedding, that.embedding); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, category, description, embedding); + } +} diff --git a/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordImmutable.java b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordImmutable.java new file mode 100644 index 000000000000..dc4bee40d0b1 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/it/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorRecordImmutable.java @@ -0,0 +1,135 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; + +/** + * Immutable equivalent of {@link VectorRecordBean} for testing the immutable-annotation-driven vector index path end-to-end. + */ +@DynamoDbImmutable(builder = VectorRecordImmutable.Builder.class) +public class VectorRecordImmutable { + private final String pk; + private final String sk; + private final String category; + private final String description; + private final List embedding; + + private VectorRecordImmutable(Builder b) { + this.pk = b.pk; + this.sk = b.sk; + this.category = b.category; + this.description = b.description; + this.embedding = b.embedding; + } + + @DynamoDbPartitionKey + public String pk() { + return pk; + } + + @DynamoDbSortKey + public String sk() { + return sk; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"cosine-index"}) + public String category() { + return category; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"cosine-index"}) + public String description() { + return description; + } + + @DynamoDbVectorAttribute(indexName = "cosine-index", dimensions = 4, distanceFunction = DistanceFunction.COSINE) + public List embedding() { + return embedding; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorRecordImmutable that = (VectorRecordImmutable) o; + return Objects.equals(pk, that.pk) + && Objects.equals(sk, that.sk) + && Objects.equals(category, that.category) + && Objects.equals(description, that.description) + && Objects.equals(embedding, that.embedding); + } + + @Override + public int hashCode() { + return Objects.hash(pk, sk, category, description, embedding); + } + + public static final class Builder { + private String pk; + private String sk; + private String category; + private String description; + private List embedding; + + private Builder() { + } + + public Builder pk(String pk) { + this.pk = pk; + return this; + } + + public Builder sk(String sk) { + this.sk = sk; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder description(String description) { + this.description = description; + return this; + } + + public Builder embedding(List embedding) { + this.embedding = embedding; + return this; + } + + public VectorRecordImmutable build() { + return new VectorRecordImmutable(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.java index e193fe681df8..abffb850c0a6 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncTable.java @@ -61,6 +61,17 @@ public interface DynamoDbAsyncTable extends MappedTableResource { */ DynamoDbAsyncIndex index(String indexName); + /** + * Returns a mapped vector index that can be used to execute vector search commands against a vector index belonging to the + * table being mapped by this object. + * + * @param indexName The name of the vector index to build the command interface for. + * @return A {@link DynamoDbAsyncVectorIndex} object that can be used to execute vector search commands against. + */ + default DynamoDbAsyncVectorIndex vectorIndex(String indexName) { + throw new UnsupportedOperationException(); + } + /** * Creates a new table in DynamoDb with the name and schema already defined for this DynamoDbTable * together with additional parameters specified in the supplied request object, {@link CreateTableEnhancedRequest}. diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncVectorIndex.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncVectorIndex.java new file mode 100644 index 000000000000..77bc08ed6fc5 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbAsyncVectorIndex.java @@ -0,0 +1,86 @@ +/* + * 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.enhanced.dynamodb; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; + +/** + * Asynchronous interface for running vector search commands against a specific DynamoDb vector index linked to a mapped table. + *

    + * By default, all command methods throw an {@link UnsupportedOperationException} to prevent interface extensions from breaking + * implementing classes. + * + * @param The type of the modelled object. + */ +@SdkPublicApi +@ThreadSafe +public interface DynamoDbAsyncVectorIndex { + + /** + * Executes a vector similarity search against this vector index and returns the full enhanced response. + * + * @param request A {@link SearchVectorsEnhancedRequest} defining the search parameters. + * @return A {@link CompletableFuture} of {@link SearchVectorsEnhancedResponse}. + */ + default CompletableFuture> searchVectorsWithResponse( + SearchVectorsEnhancedRequest request) { + throw new UnsupportedOperationException(); + } + + /** + * Executes a vector similarity search against this vector index and returns the full enhanced response. + * + * @param requestConsumer A {@link Consumer} of {@link SearchVectorsEnhancedRequest.Builder}. + * @return A {@link CompletableFuture} of {@link SearchVectorsEnhancedResponse}. + */ + default CompletableFuture> searchVectorsWithResponse( + Consumer requestConsumer) { + throw new UnsupportedOperationException(); + } + + /** + * Gets the {@link DynamoDbEnhancedClientExtension} associated with this mapped resource. + * + * @return The {@link DynamoDbEnhancedClientExtension} associated with this mapped resource. + */ + DynamoDbEnhancedClientExtension mapperExtension(); + + /** + * Gets the {@link TableSchema} object that this mapped vector index was built with. + * + * @return The {@link TableSchema} object for this mapped vector index. + */ + TableSchema tableSchema(); + + /** + * Gets the physical table name that operations performed by this object will be executed against. + * + * @return The physical table name. + */ + String tableName(); + + /** + * Gets the physical vector index name that operations performed by this object will be executed against. + * + * @return The physical vector index name. + */ + String indexName(); +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.java index 6e94e6726c2f..f32f96a5a48b 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbTable.java @@ -61,6 +61,17 @@ public interface DynamoDbTable extends MappedTableResource { */ DynamoDbIndex index(String indexName); + /** + * Returns a mapped vector index that can be used to execute vector search commands against a vector index belonging to the + * table being mapped by this object. + * + * @param indexName The name of the vector index to build the command interface for. + * @return A {@link DynamoDbVectorIndex} object that can be used to execute vector search commands against. + */ + default DynamoDbVectorIndex vectorIndex(String indexName) { + throw new UnsupportedOperationException(); + } + /** * Creates a new table in DynamoDb with the name and schema already defined for this DynamoDbTable * together with additional parameters specified in the supplied request object, {@link CreateTableEnhancedRequest}. diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbVectorIndex.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbVectorIndex.java new file mode 100644 index 000000000000..3c1d8db2688d --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/DynamoDbVectorIndex.java @@ -0,0 +1,84 @@ +/* + * 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.enhanced.dynamodb; + +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; + +/** + * Synchronous interface for running vector search commands against a specific DynamoDb vector index linked to a mapped table. + *

    + * By default, all command methods throw an {@link UnsupportedOperationException} to prevent interface extensions from breaking + * implementing classes. + * + * @param The type of the modelled object. + */ +@SdkPublicApi +@ThreadSafe +public interface DynamoDbVectorIndex { + + /** + * Executes a vector similarity search against this vector index and returns the full enhanced response. + * + * @param request A {@link SearchVectorsEnhancedRequest} defining the search parameters. + * @return A {@link SearchVectorsEnhancedResponse} containing results and vector capacity metadata. + */ + default SearchVectorsEnhancedResponse searchVectorsWithResponse(SearchVectorsEnhancedRequest request) { + throw new UnsupportedOperationException(); + } + + /** + * Executes a vector similarity search against this vector index and returns the full enhanced response. + * + * @param requestConsumer A {@link Consumer} of {@link SearchVectorsEnhancedRequest.Builder}. + * @return A {@link SearchVectorsEnhancedResponse} containing results and vector capacity metadata. + */ + default SearchVectorsEnhancedResponse searchVectorsWithResponse( + Consumer requestConsumer) { + throw new UnsupportedOperationException(); + } + + /** + * Gets the {@link DynamoDbEnhancedClientExtension} associated with this mapped resource. + * + * @return The {@link DynamoDbEnhancedClientExtension} associated with this mapped resource. + */ + DynamoDbEnhancedClientExtension mapperExtension(); + + /** + * Gets the {@link TableSchema} object that this mapped vector index was built with. + * + * @return The {@link TableSchema} object for this mapped vector index. + */ + TableSchema tableSchema(); + + /** + * Gets the physical table name that operations performed by this object will be executed against. + * + * @return The physical table name. + */ + String tableName(); + + /** + * Gets the physical vector index name that operations performed by this object will be executed against. + * + * @return The physical vector index name. + */ + String indexName(); +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.java index 8cebb16ae68e..ae0f3e205222 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/TableMetadata.java @@ -22,6 +22,7 @@ import java.util.Optional; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; /** @@ -129,6 +130,16 @@ default Optional indexSortKey(String indexName) { */ Collection indices(); + /** + * Returns metadata about all the known vector indexes for this table. Vector indexes are distinct from global and local + * secondary indexes and are not included in {@link #indices()}. + * + * @return A collection of {@link VectorIndexMetadata} containing information about the vector indexes. + */ + default Collection vectorIndices() { + return Collections.emptyList(); + } + /** * Returns all custom metadata for this table. These entries are used by extensions to the library, therefore the * value type of each metadata object stored in the map is not known and is provided as {@link Object}. diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.java index 17b54da8cffd..d5ebc0fc2d6f 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchema.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import java.util.stream.Collectors; import software.amazon.awssdk.annotations.NotThreadSafe; import software.amazon.awssdk.annotations.SdkPublicApi; @@ -39,6 +40,7 @@ import software.amazon.awssdk.enhanced.dynamodb.internal.document.DefaultEnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @@ -206,6 +208,42 @@ public Builder addIndexSortKey(String indexName, String attributeName, Attribute return this; } + /** + * Adds one or more vector indexes to the table metadata. Vector indexes are distinct from global and local secondary + * indexes. + * + * @param vectorIndexes the vector index definitions to add + */ + public Builder vectorIndexes(EnhancedVectorIndex... vectorIndexes) { + for (EnhancedVectorIndex vectorIndex : vectorIndexes) { + staticTableMetaDataBuilder.addVectorIndex(vectorIndex); + } + return this; + } + + /** + * Adds one or more vector indexes to the table metadata. Vector indexes are distinct from global and local secondary + * indexes. + * + * @param vectorIndexes the vector index definitions to add + */ + public Builder vectorIndexes(List vectorIndexes) { + vectorIndexes.forEach(staticTableMetaDataBuilder::addVectorIndex); + return this; + } + + /** + * Adds a vector index to the table metadata using a builder consumer. Vector indexes are distinct from global and local + * secondary indexes. + * + * @param vectorIndex a consumer that configures the vector index builder + */ + public Builder vectorIndex(Consumer vectorIndex) { + EnhancedVectorIndex.Builder builder = EnhancedVectorIndex.builder(); + vectorIndex.accept(builder); + return vectorIndexes(builder.build()); + } + /** * Specifies the {@link AttributeConverterProvider}s to use with the table schema. The list of attribute converter * providers must provide {@link AttributeConverter}s for Custom types. The attribute converter providers will be loaded diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedTimestampRecordExtension.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedTimestampRecordExtension.java index 14628e4aa3b9..11f982ae5b7b 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedTimestampRecordExtension.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/extensions/AutoGeneratedTimestampRecordExtension.java @@ -318,7 +318,14 @@ private void processFlattenedNestedAttributes( } for (String attrName : customMetadataObject) { - AttributeConverter converter = schema.converterForAttribute(attrName); + AttributeConverter converter; + try { + converter = schema.converterForAttribute(attrName); + } catch (UnsupportedOperationException e) { + // Some custom/third-party TableSchema implementations don't support converterForAttribute. + // In that case, skip timestamp insertion for this attribute instead of failing the write. + continue; + } if (converter != null) { insertTimestampInItemToTransform(updatedItems, reconstructCompositeKey(path, attrName), @@ -390,7 +397,13 @@ private Map applyAutoGeneratedTimestampsToMap( boolean mapCopied = false; for (String key : customMetadataObject) { - AttributeConverter converter = nestedSchema.converterForAttribute(key); + AttributeConverter converter; + try { + converter = nestedSchema.converterForAttribute(key); + } catch (UnsupportedOperationException e) { + // Nested schema can't resolve converters: skip timestamp insertion for this attribute. + continue; + } if (converter != null) { if (!mapCopied) { updatedNestedMap = new HashMap<>(nestedMap); diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtils.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtils.java new file mode 100644 index 000000000000..abb0a9e1bf13 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtils.java @@ -0,0 +1,66 @@ +/* + * 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.enhanced.dynamodb.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.internal.converter.attribute.FloatAttributeConverter; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +/** + * Utilities for marshalling search vectors to the low-level DynamoDB API. + */ +@SdkInternalApi +public final class SearchVectorUtils { + private static final FloatAttributeConverter FLOAT_CONVERTER = FloatAttributeConverter.create(); + + private SearchVectorUtils() { + } + + /** + * Converts a {@code float[]} embedding into the {@code List} shape expected by + * {@code SearchVectorsRequest.searchVector()}. + */ + public static List toSearchVector(float[] searchVector) { + if (searchVector == null) { + return null; + } + + List result = new ArrayList<>(searchVector.length); + for (float value : searchVector) { + result.add(FLOAT_CONVERTER.transformFrom(value)); + } + return Collections.unmodifiableList(result); + } + + /** + * Converts a {@code List} embedding into the {@code List} shape expected by + * {@code SearchVectorsRequest.searchVector()}. + */ + public static List toSearchVector(List searchVector) { + if (searchVector == null) { + return null; + } + + List result = new ArrayList<>(searchVector.size()); + for (Float value : searchVector) { + result.add(FLOAT_CONVERTER.transformFrom(value)); + } + return Collections.unmodifiableList(result); + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndices.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndices.java new file mode 100644 index 000000000000..daa6e3290c51 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndices.java @@ -0,0 +1,65 @@ +/* + * 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.enhanced.dynamodb.internal; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; +import software.amazon.awssdk.utils.CollectionUtils; + +/** + * Converts {@link VectorIndexMetadata} instances from table metadata into {@link EnhancedVectorIndex} instances for use in table + * creation operations. This mirrors the pattern used by {@link TableIndices} for secondary indexes. + */ +@SdkInternalApi +public final class TableVectorIndices { + private final List vectorIndexMetadataList; + + public TableVectorIndices(List vectorIndexMetadataList) { + this.vectorIndexMetadataList = vectorIndexMetadataList; + } + + public List enhancedVectorIndices() { + if (CollectionUtils.isNullOrEmpty(vectorIndexMetadataList)) { + return Collections.emptyList(); + } + + return Collections.unmodifiableList( + vectorIndexMetadataList.stream() + .map(TableVectorIndices::toEnhancedVectorIndex) + .collect(Collectors.toList())); + } + + private static EnhancedVectorIndex toEnhancedVectorIndex(VectorIndexMetadata metadata) { + EnhancedVectorIndex.Builder builder = EnhancedVectorIndex.builder() + .indexName(metadata.indexName()) + .vectorAttributeName(metadata.vectorAttributeName()) + .dimensions(metadata.dimensions()) + .distanceFunction(metadata.distanceFunction()) + .projection(metadata.projection()); + + List schemaElements = metadata.searchSchemaElements(); + if (!CollectionUtils.isNullOrEmpty(schemaElements)) { + builder.searchSchemaElements(schemaElements); + } + + return builder.build(); + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtils.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtils.java new file mode 100644 index 000000000000..4cc82238e4bc --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtils.java @@ -0,0 +1,100 @@ +/* + * 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.enhanced.dynamodb.internal; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.VectorDistanceFunction; +import software.amazon.awssdk.services.dynamodb.model.VectorIndex; +import software.amazon.awssdk.utils.CollectionUtils; + +/** + * Maps enhanced vector index models to low-level DynamoDB create-table types. + */ +@SdkInternalApi +public final class VectorIndexUtils { + private VectorIndexUtils() { + } + + public static VectorIndex toVectorIndex(EnhancedVectorIndex enhancedVectorIndex) { + VectorIndex.Builder builder = + VectorIndex.builder() + .indexName(enhancedVectorIndex.indexName()) + .vectorAttribute(b -> b.attributeName(enhancedVectorIndex.vectorAttributeName())) + .dimensions((long) enhancedVectorIndex.dimensions()) + .distanceFunction(toVectorDistanceFunction(enhancedVectorIndex.distanceFunction())) + .projection(resolveProjection(enhancedVectorIndex.projection())); + + List searchSchema = + toSearchSchema(enhancedVectorIndex); + if (!searchSchema.isEmpty()) { + builder.searchSchema(searchSchema); + } + + return builder.build(); + } + + private static Projection resolveProjection(Projection projection) { + if (projection != null) { + return projection; + } + return Projection.builder().projectionType(ProjectionType.ALL).build(); + } + + private static VectorDistanceFunction toVectorDistanceFunction(DistanceFunction distanceFunction) { + if (distanceFunction == null) { + return null; + } + return VectorDistanceFunction.fromValue(distanceFunction.name()); + } + + private static List toSearchSchema( + EnhancedVectorIndex enhancedVectorIndex) { + if (CollectionUtils.isNullOrEmpty(enhancedVectorIndex.searchSchemaElements())) { + return Collections.emptyList(); + } + + return enhancedVectorIndex.searchSchemaElements().stream() + .map(VectorIndexUtils::toSdkSearchSchemaElement) + .collect(Collectors.toList()); + } + + private static software.amazon.awssdk.services.dynamodb.model.SearchSchemaElement toSdkSearchSchemaElement( + SearchSchemaElement element) { + return software.amazon.awssdk.services.dynamodb.model.SearchSchemaElement.builder() + .attributeName(element.attributeName()) + .searchSchemaElementType( + toSdkSearchSchemaElementType(element.searchSchemaElementType())) + .build(); + } + + private static software.amazon.awssdk.services.dynamodb.model.SearchSchemaElementType toSdkSearchSchemaElementType( + SearchSchemaElementType searchSchemaElementType) { + if (searchSchemaElementType == null) { + return null; + } + return software.amazon.awssdk.services.dynamodb.model.SearchSchemaElementType.fromValue( + searchSchemaElementType.name()); + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTable.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTable.java index cd281dec3d24..f065bae49baa 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTable.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTable.java @@ -27,6 +27,7 @@ import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.TableIndices; +import software.amazon.awssdk.enhanced.dynamodb.internal.TableVectorIndices; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.CreateTableOperation; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DeleteItemOperation; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DeleteTableOperation; @@ -100,6 +101,29 @@ public DefaultDynamoDbAsyncIndex index(String indexName) { return new DefaultDynamoDbAsyncIndex<>(dynamoDbClient, extension, tableSchema, tableName, indexName); } + @Override + public DefaultDynamoDbAsyncVectorIndex vectorIndex(String indexName) { + validateVectorIndexExists(indexName); + + return new DefaultDynamoDbAsyncVectorIndex<>(dynamoDbClient, + extension, + tableSchema, + tableName, + indexName); + } + + private void validateVectorIndexExists(String indexName) { + boolean exists = tableSchema.tableMetadata() + .vectorIndices() + .stream() + .anyMatch(vectorIndex -> vectorIndex.indexName().equals(indexName)); + if (!exists) { + throw new IllegalArgumentException("Attempt to execute an operation that requires a vector index " + + "without defining the index in the table metadata. Index name: " + + indexName); + } + } + @Override public CompletableFuture createTable(CreateTableEnhancedRequest request) { TableOperation operation = CreateTableOperation.create(request); @@ -117,10 +141,12 @@ public CompletableFuture createTable(Consumer createTable() { TableIndices indices = new TableIndices(new ArrayList<>(tableSchema.tableMetadata().indices())); + TableVectorIndices vectorIndices = new TableVectorIndices(new ArrayList<>(tableSchema.tableMetadata().vectorIndices())); return createTable(CreateTableEnhancedRequest.builder() .localSecondaryIndices(indices.localSecondaryIndices()) .globalSecondaryIndices(indices.globalSecondaryIndices()) + .vectorIndexes(vectorIndices.enhancedVectorIndices()) .build()); } diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndex.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndex.java new file mode 100644 index 000000000000..2eecb19d029e --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndex.java @@ -0,0 +1,119 @@ +/* + * 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.enhanced.dynamodb.internal.client; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.internal.operations.SearchVectorsOperation; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; + +@SdkInternalApi +public final class DefaultDynamoDbAsyncVectorIndex implements DynamoDbAsyncVectorIndex { + private final DynamoDbAsyncClient dynamoDbClient; + private final DynamoDbEnhancedClientExtension extension; + private final TableSchema tableSchema; + private final String tableName; + private final String indexName; + + DefaultDynamoDbAsyncVectorIndex(DynamoDbAsyncClient dynamoDbClient, + DynamoDbEnhancedClientExtension extension, + TableSchema tableSchema, + String tableName, + String indexName) { + this.dynamoDbClient = dynamoDbClient; + this.extension = extension; + this.tableSchema = tableSchema; + this.tableName = tableName; + this.indexName = indexName; + } + + @Override + public CompletableFuture> searchVectorsWithResponse( + SearchVectorsEnhancedRequest request) { + SearchVectorsOperation operation = SearchVectorsOperation.create(request); + return operation.executeOnVectorIndexAsync(tableSchema, tableName, indexName, extension, dynamoDbClient); + } + + @Override + public CompletableFuture> searchVectorsWithResponse( + Consumer requestConsumer) { + SearchVectorsEnhancedRequest.Builder builder = SearchVectorsEnhancedRequest.builder(); + requestConsumer.accept(builder); + return searchVectorsWithResponse(builder.build()); + } + + @Override + public DynamoDbEnhancedClientExtension mapperExtension() { + return extension; + } + + @Override + public TableSchema tableSchema() { + return tableSchema; + } + + @Override + public String tableName() { + return tableName; + } + + @Override + public String indexName() { + return indexName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultDynamoDbAsyncVectorIndex that = (DefaultDynamoDbAsyncVectorIndex) o; + + if (dynamoDbClient != null ? !dynamoDbClient.equals(that.dynamoDbClient) : that.dynamoDbClient != null) { + return false; + } + if (extension != null ? !extension.equals(that.extension) : that.extension != null) { + return false; + } + if (tableSchema != null ? !tableSchema.equals(that.tableSchema) : that.tableSchema != null) { + return false; + } + if (tableName != null ? !tableName.equals(that.tableName) : that.tableName != null) { + return false; + } + return indexName != null ? indexName.equals(that.indexName) : that.indexName == null; + } + + @Override + public int hashCode() { + int result = dynamoDbClient != null ? dynamoDbClient.hashCode() : 0; + result = 31 * result + (extension != null ? extension.hashCode() : 0); + result = 31 * result + (tableSchema != null ? tableSchema.hashCode() : 0); + result = 31 * result + (tableName != null ? tableName.hashCode() : 0); + result = 31 * result + (indexName != null ? indexName.hashCode() : 0); + return result; + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTable.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTable.java index 31ce811b3483..91563bc4c079 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTable.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTable.java @@ -26,6 +26,7 @@ import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.TableIndices; +import software.amazon.awssdk.enhanced.dynamodb.internal.TableVectorIndices; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.CreateTableOperation; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DeleteItemOperation; import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DeleteTableOperation; @@ -103,6 +104,29 @@ public DefaultDynamoDbIndex index(String indexName) { indexName); } + @Override + public DefaultDynamoDbVectorIndex vectorIndex(String indexName) { + validateVectorIndexExists(indexName); + + return new DefaultDynamoDbVectorIndex<>(dynamoDbClient, + extension, + tableSchema, + tableName, + indexName); + } + + private void validateVectorIndexExists(String indexName) { + boolean exists = tableSchema.tableMetadata() + .vectorIndices() + .stream() + .anyMatch(vectorIndex -> vectorIndex.indexName().equals(indexName)); + if (!exists) { + throw new IllegalArgumentException("Attempt to execute an operation that requires a vector index " + + "without defining the index in the table metadata. Index name: " + + indexName); + } + } + @Override public void createTable(CreateTableEnhancedRequest request) { TableOperation operation = CreateTableOperation.create(request); @@ -119,10 +143,12 @@ public void createTable(Consumer requestCons @Override public void createTable() { TableIndices indices = new TableIndices(new ArrayList<>(tableSchema.tableMetadata().indices())); + TableVectorIndices vectorIndices = new TableVectorIndices(new ArrayList<>(tableSchema.tableMetadata().vectorIndices())); createTable(CreateTableEnhancedRequest.builder() .localSecondaryIndices(indices.localSecondaryIndices()) .globalSecondaryIndices(indices.globalSecondaryIndices()) + .vectorIndexes(vectorIndices.enhancedVectorIndices()) .build()); } diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndex.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndex.java new file mode 100644 index 000000000000..b86cb8517f5b --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndex.java @@ -0,0 +1,117 @@ +/* + * 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.enhanced.dynamodb.internal.client; + +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.internal.operations.SearchVectorsOperation; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +@SdkInternalApi +public final class DefaultDynamoDbVectorIndex implements DynamoDbVectorIndex { + private final DynamoDbClient dynamoDbClient; + private final DynamoDbEnhancedClientExtension extension; + private final TableSchema tableSchema; + private final String tableName; + private final String indexName; + + DefaultDynamoDbVectorIndex(DynamoDbClient dynamoDbClient, + DynamoDbEnhancedClientExtension extension, + TableSchema tableSchema, + String tableName, + String indexName) { + this.dynamoDbClient = dynamoDbClient; + this.extension = extension; + this.tableSchema = tableSchema; + this.tableName = tableName; + this.indexName = indexName; + } + + @Override + public SearchVectorsEnhancedResponse searchVectorsWithResponse(SearchVectorsEnhancedRequest request) { + SearchVectorsOperation operation = SearchVectorsOperation.create(request); + return operation.executeOnVectorIndex(tableSchema, tableName, indexName, extension, dynamoDbClient); + } + + @Override + public SearchVectorsEnhancedResponse searchVectorsWithResponse( + Consumer requestConsumer) { + SearchVectorsEnhancedRequest.Builder builder = SearchVectorsEnhancedRequest.builder(); + requestConsumer.accept(builder); + return searchVectorsWithResponse(builder.build()); + } + + @Override + public DynamoDbEnhancedClientExtension mapperExtension() { + return extension; + } + + @Override + public TableSchema tableSchema() { + return tableSchema; + } + + @Override + public String tableName() { + return tableName; + } + + @Override + public String indexName() { + return indexName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultDynamoDbVectorIndex that = (DefaultDynamoDbVectorIndex) o; + + if (dynamoDbClient != null ? !dynamoDbClient.equals(that.dynamoDbClient) : that.dynamoDbClient != null) { + return false; + } + if (extension != null ? !extension.equals(that.extension) : that.extension != null) { + return false; + } + if (tableSchema != null ? !tableSchema.equals(that.tableSchema) : that.tableSchema != null) { + return false; + } + if (tableName != null ? !tableName.equals(that.tableName) : that.tableName != null) { + return false; + } + return indexName != null ? indexName.equals(that.indexName) : that.indexName == null; + } + + @Override + public int hashCode() { + int result = dynamoDbClient != null ? dynamoDbClient.hashCode() : 0; + result = 31 * result + (extension != null ? extension.hashCode() : 0); + result = 31 * result + (tableSchema != null ? tableSchema.hashCode() : 0); + result = 31 * result + (tableName != null ? tableName.hashCode() : 0); + result = 31 * result + (indexName != null ? indexName.hashCode() : 0); + return result; + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/mapper/BeanTableSchemaAttributeTags.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/mapper/BeanTableSchemaAttributeTags.java index 3b0132ded2df..1c8199d801f2 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/mapper/BeanTableSchemaAttributeTags.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/mapper/BeanTableSchemaAttributeTags.java @@ -23,10 +23,13 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.BeanTableSchemaAttributeTag; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbUpdateBehavior; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; /** * Static provider class for core {@link BeanTableSchema} attribute tags. Each of the implemented annotations has a @@ -62,4 +65,18 @@ public static StaticAttributeTag attributeTagFor(DynamoDbUpdateBehavior annotati public static StaticAttributeTag attributeTagFor(DynamoDbAtomicCounter annotation) { return StaticAttributeTags.atomicCounter(annotation.delta(), annotation.startValue()); } + + public static StaticAttributeTag attributeTagFor(DynamoDbSearchVectorsHashKey annotation) { + return StaticAttributeTags.searchVectorsHashKey(Arrays.asList(annotation.indexNames())); + } + + public static StaticAttributeTag attributeTagFor(DynamoDbSearchVectorsInlineFilterKey annotation) { + return StaticAttributeTags.searchVectorsInlineFilterKey(Arrays.asList(annotation.indexNames())); + } + + public static StaticAttributeTag attributeTagFor(DynamoDbVectorAttribute annotation) { + return StaticAttributeTags.vectorAttribute(annotation.indexName(), + annotation.dimensions(), + annotation.distanceFunction()); + } } \ No newline at end of file diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperation.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperation.java index 487d4b7c7b15..55ea6c0a802a 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperation.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperation.java @@ -20,15 +20,19 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; import software.amazon.awssdk.enhanced.dynamodb.OperationContext; import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.internal.VectorIndexUtils; import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; @@ -40,6 +44,8 @@ import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; import software.amazon.awssdk.services.dynamodb.model.KeyType; import software.amazon.awssdk.services.dynamodb.model.LocalSecondaryIndex; +import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; +import software.amazon.awssdk.services.dynamodb.model.VectorIndex; @SdkInternalApi public class CreateTableOperation implements TableOperation { @@ -79,6 +85,7 @@ public CreateTableRequest generateRequest(TableSchema tableSchema, List sdkGlobalSecondaryIndices = buildGlobalSecondaryIndices(tableSchema, dedupedIndexKeys); List sdkLocalSecondaryIndices = buildLocalSecondaryIndices(tableSchema, dedupedIndexKeys, primaryPartitionKeys); + List sdkVectorIndices = buildVectorIndexes(dedupedIndexKeys); List attributeDefinitions = buildAttributeDefinitions(dedupedIndexKeys, tableSchema); @@ -91,6 +98,7 @@ public CreateTableRequest generateRequest(TableSchema tableSchema, .keySchema(generateKeySchema(primaryPartitionKeys, primarySortKeys)) .globalSecondaryIndexes(sdkGlobalSecondaryIndices) .localSecondaryIndexes(sdkLocalSecondaryIndices) + .vectorIndexes(sdkVectorIndices) .attributeDefinitions(attributeDefinitions) .billingMode(billingMode) .provisionedThroughput(this.request.provisionedThroughput()) @@ -174,6 +182,18 @@ private List buildLocalSecondaryIndices( }).collect(Collectors.toList()); } + private List buildVectorIndexes(Set dedupedIndexKeys) { + if (!hasIndices(this.request.vectorIndexes())) { + return null; + } + + return this.request.vectorIndexes().stream().map(vectorIndex -> { + vectorIndex.searchSchemaElements() + .forEach(element -> dedupedIndexKeys.add(element.attributeName())); + return VectorIndexUtils.toVectorIndex(vectorIndex); + }).collect(Collectors.toList()); + } + private void validateLsiConstraints(List primaryPartitionKeys, List lsiPartitionKeys, List lsiSortKeys, String indexName) { if (lsiPartitionKeys.size() != 1) { @@ -194,17 +214,50 @@ private List buildAttributeDefinitions(Set dedupedI return dedupedIndexKeys.stream() .map(attribute -> AttributeDefinition.builder() .attributeName(attribute) - .attributeType(tableSchema.tableMetadata() - .scalarAttributeType(attribute) - .orElseThrow(() -> - new IllegalArgumentException( - String.format( - "Could not map key attribute '%s' to a valid scalar type", - attribute)))) + .attributeType(resolveScalarAttributeType(attribute, tableSchema)) .build()) .collect(Collectors.toList()); } + private ScalarAttributeType resolveScalarAttributeType(String attribute, TableSchema tableSchema) { + try { + Optional scalarType = tableSchema.tableMetadata().scalarAttributeType(attribute); + if (scalarType.isPresent()) { + return scalarType.get(); + } + } catch (IllegalArgumentException ignored) { + // Not a key attribute; resolve from the attribute converter instead. + } + + AttributeConverter converter = attributeConverter(tableSchema, attribute); + if (converter != null) { + ScalarAttributeType scalarType = converter.attributeValueType().scalarAttributeType(); + if (scalarType != null) { + return scalarType; + } + throw new IllegalArgumentException( + String.format("Attribute '%s' must be defined in the table schema as a scalar type " + + "(S, N, or B); found: %s.", attribute, converter.attributeValueType())); + } + + if (EnhancedDocument.class.equals(tableSchema.itemType().rawClass())) { + return ScalarAttributeType.S; + } + + throw new IllegalArgumentException( + String.format("Attribute '%s' must be defined in the table schema as a scalar type " + + "(S, N, or B); found: UNDEFINED.", attribute)); + } + + private static AttributeConverter attributeConverter(TableSchema tableSchema, String attribute) { + try { + return tableSchema.converterForAttribute(attribute); + } catch (UnsupportedOperationException ignored) { + // TableSchema implementations that do not support converterForAttribute (e.g. DocumentTableSchema) + return null; + } + } + private boolean hasIndices(Collection indices) { return indices != null && !indices.isEmpty(); } diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationName.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationName.java index cc3fec48e084..60afd9b7c6ba 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationName.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationName.java @@ -30,6 +30,7 @@ public enum OperationName { QUERY("Query"), PUT_ITEM("PutItem"), SCAN("Scan"), + SEARCH_VECTORS("SearchVectors"), TRANSACT_GET_ITEMS("TransactGetItems"), TRANSACT_WRITE_ITEMS("TransactWriteItems"), UPDATE_ITEM("UpdateItem"); diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperation.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperation.java new file mode 100644 index 000000000000..4bb216dedb3f --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperation.java @@ -0,0 +1,169 @@ +/* + * 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.enhanced.dynamodb.internal.operations; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Function; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.OperationContext; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.internal.EnhancedClientUtils; +import software.amazon.awssdk.enhanced.dynamodb.internal.ProjectionExpression; +import software.amazon.awssdk.enhanced.dynamodb.internal.SearchVectorUtils; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; +import software.amazon.awssdk.utils.CollectionUtils; + +@SdkInternalApi +public class SearchVectorsOperation implements VectorIndexOperation> { + + private final SearchVectorsEnhancedRequest request; + + private SearchVectorsOperation(SearchVectorsEnhancedRequest request) { + this.request = request; + } + + public static SearchVectorsOperation create(SearchVectorsEnhancedRequest request) { + return new SearchVectorsOperation<>(request); + } + + @Override + public OperationName operationName() { + return OperationName.SEARCH_VECTORS; + } + + /** + * Builds the low-level {@link SearchVectorsRequest}. + * + * @throws IllegalArgumentException if {@code context.indexName()} is the primary index + * ({@link TableMetadata#primaryIndexName()}) — message: + * {@code "SearchVectors cannot be executed against a primary index. A vector index name is + * required."} + * @throws IllegalArgumentException if {@code context.indexName()} is a GSI or LSI + */ + @Override + public SearchVectorsRequest generateRequest(TableSchema tableSchema, + OperationContext context, + DynamoDbEnhancedClientExtension extension) { + if (TableMetadata.primaryIndexName().equals(context.indexName())) { + throw new IllegalArgumentException( + "SearchVectors cannot be executed against a primary index. A vector index name is required."); + } + + boolean isSecondaryIndex = tableSchema.tableMetadata() + .indices() + .stream() + .anyMatch(index -> index.name().equals(context.indexName())); + if (isSecondaryIndex) { + throw new IllegalArgumentException("SearchVectors cannot be executed against a secondary index."); + } + + Map expressionValues = null; + Map expressionNames = null; + + if (request.searchConditionExpression() != null) { + expressionValues = request.searchConditionExpression().expressionValues(); + expressionNames = request.searchConditionExpression().expressionNames(); + } + + String projectionExpressionAsString = null; + if (request.nestedAttributesToProject() != null) { + ProjectionExpression attributesToProject = ProjectionExpression.create(request.nestedAttributesToProject()); + projectionExpressionAsString = attributesToProject.projectionExpressionAsString().orElse(null); + expressionNames = Expression.joinNames(expressionNames, attributesToProject.expressionAttributeNames()); + } + + SearchVectorsRequest.Builder searchVectorsRequest = + SearchVectorsRequest.builder() + .tableName(context.tableName()) + .indexName(context.indexName()) + .searchVector(SearchVectorUtils.toSearchVector( + request.searchVector())) + .returnConsumedCapacity(request.returnConsumedCapacityAsString()); + + if (request.topK() != null) { + searchVectorsRequest.topK(request.topK()); + } + + if (request.searchConditionExpression() != null) { + searchVectorsRequest.searchConditionExpression(request.searchConditionExpression().expression()); + searchVectorsRequest.expressionAttributeValues(expressionValues); + } + + if (expressionNames != null) { + searchVectorsRequest.expressionAttributeNames(expressionNames); + } + + if (projectionExpressionAsString != null) { + searchVectorsRequest.projectionExpression(projectionExpressionAsString); + } + + return searchVectorsRequest.build(); + } + + @Override + public SearchVectorsEnhancedResponse transformResponse(SearchVectorsResponse response, + TableSchema tableSchema, + OperationContext context, + DynamoDbEnhancedClientExtension extension) { + List> results; + if (CollectionUtils.isNullOrEmpty(response.searchResults())) { + results = Collections.emptyList(); + } else { + results = response.searchResults() + .stream() + .map(searchResult -> SearchResultItem.builder() + .item(EnhancedClientUtils.readAndTransformSingleItem( + searchResult.item(), + tableSchema, + context, + extension)) + .score(searchResult.score()) + .build()) + .collect(Collectors.toList()); + } + + return SearchVectorsEnhancedResponse.builder() + .results(results) + .consumedCapacity(response.consumedCapacity()) + .build(); + } + + @Override + public Function serviceCall(DynamoDbClient dynamoDbClient) { + return dynamoDbClient::searchVectors; + } + + @Override + public Function> asyncServiceCall( + DynamoDbAsyncClient dynamoDbAsyncClient) { + return dynamoDbAsyncClient::searchVectors; + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/VectorIndexOperation.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/VectorIndexOperation.java new file mode 100644 index 000000000000..633d518f268b --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/VectorIndexOperation.java @@ -0,0 +1,56 @@ +/* + * 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.enhanced.dynamodb.internal.operations; + +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.OperationContext; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * Interface for a single operation that can be executed against a vector index of a mapped database table. + */ +@SdkInternalApi +public interface VectorIndexOperation + extends CommonOperation { + + /** + * Executes this operation synchronously against a vector index. + */ + default ResultT executeOnVectorIndex(TableSchema tableSchema, + String tableName, + String vectorIndexName, + DynamoDbEnhancedClientExtension extension, + DynamoDbClient dynamoDbClient) { + OperationContext context = DefaultOperationContext.create(tableName, vectorIndexName); + return execute(tableSchema, context, extension, dynamoDbClient); + } + + /** + * Executes this operation asynchronously against a vector index. + */ + default CompletableFuture executeOnVectorIndexAsync(TableSchema tableSchema, + String tableName, + String vectorIndexName, + DynamoDbEnhancedClientExtension extension, + DynamoDbAsyncClient dynamoDbAsyncClient) { + OperationContext context = DefaultOperationContext.create(tableName, vectorIndexName); + return executeAsync(tableSchema, context, extension, dynamoDbAsyncClient); + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticAttributeTags.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticAttributeTags.java index 186cf1b2c107..6db66247e874 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticAttributeTags.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticAttributeTags.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.enhanced.dynamodb.mapper; import java.util.Collection; +import java.util.Collections; import java.util.function.BiConsumer; import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkPublicApi; @@ -24,6 +25,8 @@ import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.internal.extensions.AtomicCounterTag; import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.UpdateBehaviorTag; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; /** * Common implementations of {@link StaticAttributeTag}. These tags can be used to mark your attributes as having certain @@ -199,6 +202,84 @@ public static StaticAttributeTag atomicCounter() { return AtomicCounterTag.create(); } + /** + * Marks an attribute as a HASH partition key in the search schema for the specified vector index. + * + * @param indexName the name of the vector index + */ + public static StaticAttributeTag searchVectorsHashKey(String indexName) { + return searchVectorsHashKey(Collections.singletonList(indexName)); + } + + /** + * Marks an attribute as a HASH partition key in the search schema for multiple vector indexes. + * + * @param indexNames the names of the vector indexes + */ + public static StaticAttributeTag searchVectorsHashKey(Collection indexNames) { + return (attributeName, attributeValueType) -> + metadata -> indexNames.forEach( + indexName -> metadata.addSearchVectorsHashKey(indexName, attributeName)); + } + + /** + * Marks an attribute as an INLINE_FILTER element in the search schema for the specified vector index. + * + * @param indexName the name of the vector index + */ + public static StaticAttributeTag searchVectorsInlineFilterKey(String indexName) { + return searchVectorsInlineFilterKey(Collections.singletonList(indexName)); + } + + /** + * Marks an attribute as an INLINE_FILTER element in the search schema for multiple vector indexes. + * + * @param indexNames the names of the vector indexes + */ + public static StaticAttributeTag searchVectorsInlineFilterKey(Collection indexNames) { + return (attributeName, attributeValueType) -> + metadata -> indexNames.forEach( + indexName -> metadata.addSearchVectorsInlineFilterKey(indexName, attributeName)); + } + + /** + * Marks an attribute as the vector embedding attribute for the specified vector index, setting its dimensions and distance + * function. + * + * @param indexName the name of the vector index + * @param dimensions the number of vector dimensions + * @param distanceFunction the distance function for similarity search + */ + public static StaticAttributeTag vectorAttribute(String indexName, int dimensions, + DistanceFunction distanceFunction) { + return (attributeName, attributeValueType) -> + metadata -> metadata.setVectorAttribute(indexName, attributeName, dimensions, distanceFunction); + } + + /** + * Associates one or more vector indexes with a {@link StaticTableSchema}. Vector indexes are distinct from global and local + * secondary indexes. + * + * @param vectorIndexes the vector index definitions to associate with the table + */ + public static StaticTableTag vectorIndexes(EnhancedVectorIndex... vectorIndexes) { + return () -> metadata -> { + for (EnhancedVectorIndex vectorIndex : vectorIndexes) { + metadata.addVectorIndex(vectorIndex); + } + }; + } + + /** + * Associates one or more vector indexes with a {@link StaticTableSchema}. Vector indexes are distinct from global and local + * secondary indexes. + * + * @param vectorIndexes the vector index definitions to associate with the table + */ + public static StaticTableTag vectorIndexes(Collection vectorIndexes) { + return () -> metadata -> vectorIndexes.forEach(metadata::addVectorIndex); + } + private static class KeyAttributeTag implements StaticAttributeTag { private final BiConsumer tableMetadataKeySetter; diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadata.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadata.java index 4f4b972e45d7..49d1fb73045b 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadata.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadata.java @@ -35,6 +35,11 @@ import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.StaticIndexMetadata; import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.StaticKeyAttributeMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; /** @@ -48,6 +53,7 @@ public final class StaticTableMetadata implements TableMetadata { private final Map customMetadata; private final Map indexByNameMap; private final Map keyAttributes; + private final List vectorIndices; private final ConcurrentHashMap> partitionKeyCache = new ConcurrentHashMap<>(); private final ConcurrentHashMap> sortKeyCache = new ConcurrentHashMap<>(); @@ -57,6 +63,7 @@ private StaticTableMetadata(Builder builder) { builder.indexBuilders.forEach((key, value) -> indices.put(key, value.name(key).build())); this.indexByNameMap = Collections.unmodifiableMap(indices); this.keyAttributes = Collections.unmodifiableMap(builder.keyAttributes); + this.vectorIndices = Collections.unmodifiableList(builder.buildFinalVectorIndices()); } /** @@ -174,6 +181,11 @@ public Collection indices() { return indexByNameMap.values(); } + @Override + public Collection vectorIndices() { + return vectorIndices; + } + @Override public Map customMetadata() { return this.customMetadata; @@ -237,7 +249,10 @@ public boolean equals(Object o) { if (indexByNameMap != null ? ! indexByNameMap.equals(that.indexByNameMap) : that.indexByNameMap != null) { return false; } - return keyAttributes != null ? keyAttributes.equals(that.keyAttributes) : that.keyAttributes == null; + if (keyAttributes != null ? !keyAttributes.equals(that.keyAttributes) : that.keyAttributes != null) { + return false; + } + return vectorIndices != null ? vectorIndices.equals(that.vectorIndices) : that.vectorIndices == null; } @Override @@ -245,6 +260,7 @@ public int hashCode() { int result = customMetadata != null ? customMetadata.hashCode() : 0; result = 31 * result + (indexByNameMap != null ? indexByNameMap.hashCode() : 0); result = 31 * result + (keyAttributes != null ? keyAttributes.hashCode() : 0); + result = 31 * result + (vectorIndices != null ? vectorIndices.hashCode() : 0); return result; } @@ -256,6 +272,8 @@ public static class Builder { private final Map customMetadata = new LinkedHashMap<>(); private final Map indexBuilders = new LinkedHashMap<>(); private final Map keyAttributes = new LinkedHashMap<>(); + private final Map vectorIndices = new LinkedHashMap<>(); + private final Map incrementalVectorIndices = new LinkedHashMap<>(); private Builder() { indexBuilders.put(TableMetadata.primaryIndexName(), StaticIndexMetadata.builder()); @@ -407,6 +425,107 @@ public Builder markAttributeAsKey(String attributeName, AttributeValueType attri return this; } + /** + * Adds a HASH element to the SearchSchema for the named vector index. The vector index metadata is built incrementally + * from annotations and finalized at {@link #build()} time. + * + * @param indexName the name of the vector index + * @param attributeName the attribute to use as the HASH partition key in the search schema + */ + public Builder addSearchVectorsHashKey(String indexName, String attributeName) { + getOrCreateIncrementalVectorIndex(indexName) + .addSearchSchemaElement(SearchSchemaElement.builder() + .attributeName(attributeName) + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build()); + return this; + } + + /** + * Adds an INLINE_FILTER element to the SearchSchema for the named vector index. The vector index metadata is built + * incrementally from annotations and finalized at {@link #build()} time. + * + * @param indexName the name of the vector index + * @param attributeName the attribute to use as an inline filter in the search schema + */ + public Builder addSearchVectorsInlineFilterKey(String indexName, String attributeName) { + getOrCreateIncrementalVectorIndex(indexName) + .addSearchSchemaElement(SearchSchemaElement.builder() + .attributeName(attributeName) + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build()); + return this; + } + + /** + * Sets the vector attribute, dimensions, and distance function for the named vector index. The vector index metadata is + * built incrementally from annotations and finalized at {@link #build()} time. + * + * @param indexName the name of the vector index + * @param attributeName the attribute that stores the vector embedding + * @param dimensions the number of vector dimensions + * @param distanceFunction the distance function for similarity search + */ + public Builder setVectorAttribute(String indexName, String attributeName, + int dimensions, DistanceFunction distanceFunction) { + VectorIndexMetadata.Builder builder = getOrCreateIncrementalVectorIndex(indexName); + + if (builder.vectorAttributeName() != null) { + throw new IllegalArgumentException( + "Attempt to set a vector attribute for a vector index that already has one. " + + "Vector index name: " + indexName); + } + + builder.vectorAttributeName(attributeName) + .dimensions(dimensions) + .distanceFunction(distanceFunction); + return this; + } + + private VectorIndexMetadata.Builder getOrCreateIncrementalVectorIndex(String indexName) { + return incrementalVectorIndices.computeIfAbsent(indexName, + k -> VectorIndexMetadata.builder().indexName(k)); + } + + private List buildFinalVectorIndices() { + Map merged = new LinkedHashMap<>(vectorIndices); + incrementalVectorIndices.forEach((name, builder) -> { + if (merged.containsKey(name)) { + throw new IllegalArgumentException( + "Vector index '" + name + "' is defined both programmatically and via annotations."); + } + merged.put(name, builder.build()); + }); + return new ArrayList<>(merged.values()); + } + + /** + * Adds metadata for a vector index on this table. Vector indexes are distinct from global and local secondary indexes and + * must not be registered through {@link #addIndexPartitionKey(String, String, AttributeValueType)}. + * + * @param vectorIndex the vector index metadata to add + * @throws IllegalArgumentException if a vector index with the same name has already been added + */ + public Builder addVectorIndex(VectorIndexMetadata vectorIndex) { + if (vectorIndices.containsKey(vectorIndex.indexName())) { + throw new IllegalArgumentException("Attempt to add a vector index that has already been added. " + + "Vector index name: " + vectorIndex.indexName()); + } + + vectorIndices.put(vectorIndex.indexName(), vectorIndex); + return this; + } + + /** + * Adds metadata for a vector index on this table. + * + * @param enhancedVectorIndex the enhanced vector index definition to add + * @throws IllegalArgumentException if a vector index with the same name has already been added + */ + public Builder addVectorIndex(EnhancedVectorIndex enhancedVectorIndex) { + return addVectorIndex(VectorIndexMetadata.fromEnhancedVectorIndex(enhancedVectorIndex)); + } + /** * Package-private method to merge the contents of a constructed {@link TableMetadata} into this builder. */ @@ -430,9 +549,32 @@ Builder mergeWith(TableMetadata other) { other.customMetadata().forEach(this::mergeCustomMetaDataObject); other.keyAttributes().forEach(keyAttribute -> markAttributeAsKey(keyAttribute.name(), keyAttribute.attributeValueType())); + other.vectorIndices().forEach(this::mergeVectorIndex); return this; } + private void mergeVectorIndex(VectorIndexMetadata vi) { + if (vectorIndices.containsKey(vi.indexName())) { + throw new IllegalArgumentException("Attempt to add a vector index that has already been added. " + + "Vector index name: " + vi.indexName()); + } + VectorIndexMetadata.Builder builder = getOrCreateIncrementalVectorIndex(vi.indexName()); + if (vi.vectorAttributeName() != null) { + if (builder.vectorAttributeName() != null) { + throw new IllegalArgumentException( + "Attempt to set a vector attribute for a vector index that already has one. " + + "Vector index name: " + vi.indexName()); + } + builder.vectorAttributeName(vi.vectorAttributeName()) + .dimensions(vi.dimensions()) + .distanceFunction(vi.distanceFunction()); + } + if (vi.projection() != null) { + builder.projection(vi.projection()); + } + vi.searchSchemaElements().forEach(builder::addSearchSchemaElement); + } + private void mergeCustomMetaDataObject(String key, Object object) { if (object instanceof Collection) { this.addCustomMetadataObject(key, (Collection) object); diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsHashKey.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsHashKey.java new file mode 100644 index 000000000000..3e47ffe3ce91 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsHashKey.java @@ -0,0 +1,59 @@ +/* + * 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.enhanced.dynamodb.mapper.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.BeanTableSchemaAttributeTags; + +/** + * Denotes a HASH partition key in the SearchSchema for one or more vector indexes. The annotated attribute will be used as the + * partition key for scoping vector searches via {@code SearchConditionExpression}. + * + *

    Each vector index requires exactly one HASH element in its SearchSchema. Only the equality ({@code =}) operator is + * supported for HASH attributes in {@code SearchConditionExpression}. + * + *

    You must specify at least one index name. The index names must match those specified in corresponding + * {@link DynamoDbVectorAttribute} annotations. + * + *

    Example usage: + *

    {@code
    + * @DynamoDbBean
    + * public class Product {
    + *     @DynamoDbSearchVectorsHashKey(indexNames = {"product-embedding-index"})
    + *     public String getCategory() { return category; }
    + *
    + *     @DynamoDbVectorAttribute(
    + *         indexName = "product-embedding-index",
    + *         dimensions = 1536,
    + *         distanceFunction = DistanceFunction.COSINE)
    + *     public List getProductEmbedding() { return productEmbedding; }
    + * }
    + * }
    + */ +@SdkPublicApi +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@BeanTableSchemaAttributeTag(BeanTableSchemaAttributeTags.class) +public @interface DynamoDbSearchVectorsHashKey { + /** + * The names of one or more vector indexes that this HASH key should participate in. + */ + String[] indexNames(); +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsInlineFilterKey.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsInlineFilterKey.java new file mode 100644 index 000000000000..50a3979abd43 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbSearchVectorsInlineFilterKey.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.enhanced.dynamodb.mapper.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.BeanTableSchemaAttributeTags; + +/** + * Denotes an INLINE_FILTER attribute in the SearchSchema for one or more vector indexes. Inline filter attributes are applied as + * pre-filters before vector search and can be used in {@code SearchConditionExpression}. + * + *

    Only the equality ({@code =}) operator is supported for inline filter attributes. Up to 18 inline filters + * can be defined per vector index. + * + *

    You must specify at least one index name. The index names must match those specified in corresponding + * {@link DynamoDbVectorAttribute} annotations. + * + *

    Example usage: + *

    {@code
    + * @DynamoDbBean
    + * public class Product {
    + *     @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"product-embedding-index"})
    + *     public String getColor() { return color; }
    + *
    + *     @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"product-embedding-index"})
    + *     public String getSize() { return size; }
    + *
    + *     @DynamoDbVectorAttribute(
    + *         indexName = "product-embedding-index",
    + *         dimensions = 1536,
    + *         distanceFunction = DistanceFunction.COSINE)
    + *     public List getProductEmbedding() { return productEmbedding; }
    + * }
    + * }
    + */ +@SdkPublicApi +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@BeanTableSchemaAttributeTag(BeanTableSchemaAttributeTags.class) +public @interface DynamoDbSearchVectorsInlineFilterKey { + /** + * The names of one or more vector indexes that this inline filter key should participate in. + */ + String[] indexNames(); +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbVectorAttribute.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbVectorAttribute.java new file mode 100644 index 000000000000..eec415677343 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/mapper/annotations/DynamoDbVectorAttribute.java @@ -0,0 +1,70 @@ +/* + * 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.enhanced.dynamodb.mapper.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.BeanTableSchemaAttributeTags; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; + +/** + * Marks an attribute as the vector embedding for a named vector index. The annotated getter should return a {@code List} + * representing the vector embedding. + * + *

    Each vector index requires exactly one attribute annotated with {@code @DynamoDbVectorAttribute}. Multiple + * vector indexes on the same bean require separate annotated attributes, each with a distinct {@code indexName}. + * + *

    Example usage: + *

    {@code
    + * @DynamoDbBean
    + * public class Product {
    + *     @DynamoDbVectorAttribute(
    + *         indexName = "product-embedding-index",
    + *         dimensions = 1536,
    + *         distanceFunction = DistanceFunction.COSINE)
    + *     public List productEmbedding() { return productEmbedding; }
    + * }
    + * }
    + * + *

    Vector indexes defined via annotations default to {@code ProjectionType.ALL}. For {@code KEYS_ONLY} or + * {@code INCLUDE} projections, use the programmatic {@link CreateTableEnhancedRequest#vectorIndexes()} API with explicit + * {@link EnhancedVectorIndex} definitions. + */ +@SdkPublicApi +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@BeanTableSchemaAttributeTag(BeanTableSchemaAttributeTags.class) +public @interface DynamoDbVectorAttribute { + /** + * The name of the vector index this embedding attribute belongs to. + */ + String indexName(); + + /** + * The number of dimensions in the vector embedding. + */ + int dimensions(); + + /** + * The distance function used for similarity search on this index. + */ + DistanceFunction distanceFunction(); +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.java index 1848e6d19487..d322be6c5e74 100644 --- a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.java +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequest.java @@ -42,12 +42,14 @@ public final class CreateTableEnhancedRequest { private final StreamSpecification streamSpecification; private final Collection localSecondaryIndices; private final Collection globalSecondaryIndices; + private final Collection vectorIndexes; private CreateTableEnhancedRequest(Builder builder) { this.provisionedThroughput = builder.provisionedThroughput; this.streamSpecification = builder.streamSpecification; this.localSecondaryIndices = builder.localSecondaryIndices; this.globalSecondaryIndices = builder.globalSecondaryIndices; + this.vectorIndexes = builder.vectorIndexes; } /** @@ -64,7 +66,8 @@ public Builder toBuilder() { return builder().provisionedThroughput(provisionedThroughput) .streamSpecification(streamSpecification) .localSecondaryIndices(localSecondaryIndices) - .globalSecondaryIndices(globalSecondaryIndices); + .globalSecondaryIndices(globalSecondaryIndices) + .vectorIndexes(vectorIndexes); } /** @@ -95,6 +98,13 @@ public Collection globalSecondaryIndices() { return globalSecondaryIndices; } + /** + * Returns the vector indexes set on this request object, or null if none have been set. + */ + public Collection vectorIndexes() { + return vectorIndexes; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -106,20 +116,23 @@ public boolean equals(Object o) { CreateTableEnhancedRequest that = (CreateTableEnhancedRequest) o; - if (provisionedThroughput != null ? ! provisionedThroughput.equals(that.provisionedThroughput) : + if (provisionedThroughput != null ? !provisionedThroughput.equals(that.provisionedThroughput) : that.provisionedThroughput != null) { return false; } - if (streamSpecification != null ? ! streamSpecification.equals(that.streamSpecification) : + if (streamSpecification != null ? !streamSpecification.equals(that.streamSpecification) : that.streamSpecification != null) { return false; } - if (localSecondaryIndices != null ? ! localSecondaryIndices.equals(that.localSecondaryIndices) : + if (localSecondaryIndices != null ? !localSecondaryIndices.equals(that.localSecondaryIndices) : that.localSecondaryIndices != null) { return false; } - return globalSecondaryIndices != null ? globalSecondaryIndices.equals(that.globalSecondaryIndices) : - that.globalSecondaryIndices == null; + if (globalSecondaryIndices != null ? !globalSecondaryIndices.equals(that.globalSecondaryIndices) : + that.globalSecondaryIndices != null) { + return false; + } + return vectorIndexes != null ? vectorIndexes.equals(that.vectorIndexes) : that.vectorIndexes == null; } @Override @@ -128,6 +141,7 @@ public int hashCode() { result = 31 * result + (streamSpecification != null ? streamSpecification.hashCode() : 0); result = 31 * result + (localSecondaryIndices != null ? localSecondaryIndices.hashCode() : 0); result = 31 * result + (globalSecondaryIndices != null ? globalSecondaryIndices.hashCode() : 0); + result = 31 * result + (vectorIndexes != null ? vectorIndexes.hashCode() : 0); return result; } @@ -140,13 +154,13 @@ public static final class Builder { private StreamSpecification streamSpecification; private Collection localSecondaryIndices; private Collection globalSecondaryIndices; + private Collection vectorIndexes; private Builder() { } /** - * Sets the provisioned throughput for this table. Use this parameter to set the table's - * read and write capacity units. + * Sets the provisioned throughput for this table. Use this parameter to set the table's read and write capacity units. *

    * See the DynamoDb documentation for more information on default throughput values. */ @@ -255,6 +269,40 @@ public final Builder globalSecondaryIndices(Consumer + * See {@link EnhancedVectorIndex} for more information on creating and using a vector index. + */ + public Builder vectorIndexes(Collection vectorIndexes) { + this.vectorIndexes = vectorIndexes; + return this; + } + + /** + * Defines a vector index for this table. + *

    + * See {@link EnhancedVectorIndex} for more information on creating and using a vector index. + */ + public Builder vectorIndexes(EnhancedVectorIndex... vectorIndexes) { + this.vectorIndexes = Arrays.asList(vectorIndexes); + return this; + } + + /** + * This is a convenience method for {@link #vectorIndexes(Collection)} that creates instances of the + * {@link EnhancedVectorIndex.Builder} for you, avoiding the need to create them manually via + * {@link EnhancedVectorIndex#builder()}. + */ + @SafeVarargs + public final Builder vectorIndexes(Consumer... vectorIndexes) { + return vectorIndexes(Stream.of(vectorIndexes).map(vectorIndex -> { + EnhancedVectorIndex.Builder builder = EnhancedVectorIndex.builder(); + vectorIndex.accept(builder); + return builder.build(); + }).collect(Collectors.toList())); + } + public CreateTableEnhancedRequest build() { return new CreateTableEnhancedRequest(this); } diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/DistanceFunction.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/DistanceFunction.java new file mode 100644 index 000000000000..b9157c91ceb1 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/DistanceFunction.java @@ -0,0 +1,30 @@ +/* + * 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.enhanced.dynamodb.model; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * Distance function used for vector similarity search on a vector index. + * + * @see EnhancedVectorIndex#distanceFunction() + */ +@SdkPublicApi +public enum DistanceFunction { + COSINE, + DOT_PRODUCT, + EUCLIDEAN +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndex.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndex.java new file mode 100644 index 000000000000..923df61a11e1 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndex.java @@ -0,0 +1,216 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.services.dynamodb.model.Projection; + +/** + * Enhanced model representation of a vector index on a DynamoDb table. This is optionally used with the {@code createTable} + * operation in the enhanced client. + *

    + * Vector indexes are distinct from global and local secondary indexes; they define vector search configuration including + * embedding dimensions, distance function, and search schema elements. + */ +@SdkPublicApi +@ThreadSafe +public final class EnhancedVectorIndex { + private final String indexName; + private final String vectorAttributeName; + private final int dimensions; + private final DistanceFunction distanceFunction; + private final Projection projection; + private final List searchSchemaElements; + + private EnhancedVectorIndex(Builder builder) { + this.indexName = builder.indexName; + this.vectorAttributeName = builder.vectorAttributeName; + this.dimensions = builder.dimensions; + this.distanceFunction = builder.distanceFunction; + this.projection = builder.projection; + if (builder.searchSchemaElements == null) { + this.searchSchemaElements = Collections.emptyList(); + } else { + this.searchSchemaElements = Collections.unmodifiableList(new ArrayList<>(builder.searchSchemaElements)); + } + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().indexName(indexName) + .vectorAttributeName(vectorAttributeName) + .dimensions(dimensions) + .distanceFunction(distanceFunction) + .projection(projection) + .searchSchemaElements(searchSchemaElements); + } + + /** + * The name of the vector index. + */ + public String indexName() { + return indexName; + } + + /** + * The name of the table attribute that stores the vector embedding for this index. + */ + public String vectorAttributeName() { + return vectorAttributeName; + } + + /** + * The number of dimensions in the vector embedding. + */ + public int dimensions() { + return dimensions; + } + + /** + * The distance function used for similarity search on this index. + */ + public DistanceFunction distanceFunction() { + return distanceFunction; + } + + /** + * The attribute projection setting for this vector index. + */ + public Projection projection() { + return projection; + } + + /** + * The search schema elements for this vector index, including the hash attribute and optional inline filters. + */ + public List searchSchemaElements() { + return searchSchemaElements; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + EnhancedVectorIndex that = (EnhancedVectorIndex) o; + return dimensions == that.dimensions + && Objects.equals(indexName, that.indexName) + && Objects.equals(vectorAttributeName, that.vectorAttributeName) + && distanceFunction == that.distanceFunction + && Objects.equals(projection, that.projection) + && Objects.equals(searchSchemaElements, that.searchSchemaElements); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(indexName); + result = 31 * result + Objects.hashCode(vectorAttributeName); + result = 31 * result + Objects.hashCode(dimensions); + result = 31 * result + Objects.hashCode(distanceFunction); + result = 31 * result + Objects.hashCode(projection); + result = 31 * result + Objects.hashCode(searchSchemaElements); + return result; + } + + /** + * A builder for {@link EnhancedVectorIndex}. + */ + @NotThreadSafe + public static final class Builder { + private String indexName; + private String vectorAttributeName; + private int dimensions; + private DistanceFunction distanceFunction; + private Projection projection; + private List searchSchemaElements; + + private Builder() { + } + + public Builder indexName(String indexName) { + this.indexName = indexName; + return this; + } + + public Builder vectorAttributeName(String vectorAttributeName) { + this.vectorAttributeName = vectorAttributeName; + return this; + } + + public Builder dimensions(int dimensions) { + this.dimensions = dimensions; + return this; + } + + public Builder distanceFunction(DistanceFunction distanceFunction) { + this.distanceFunction = distanceFunction; + return this; + } + + public Builder projection(Projection projection) { + this.projection = projection; + return this; + } + + public Builder projection(Consumer projection) { + Projection.Builder builder = Projection.builder(); + projection.accept(builder); + return projection(builder.build()); + } + + public Builder searchSchemaElements(List searchSchemaElements) { + this.searchSchemaElements = searchSchemaElements; + return this; + } + + public Builder searchSchemaElements(SearchSchemaElement... searchSchemaElements) { + this.searchSchemaElements = new ArrayList<>(); + Collections.addAll(this.searchSchemaElements, searchSchemaElements); + return this; + } + + public Builder addSearchSchemaElement(SearchSchemaElement searchSchemaElement) { + if (this.searchSchemaElements == null) { + this.searchSchemaElements = new ArrayList<>(); + } + this.searchSchemaElements.add(searchSchemaElement); + return this; + } + + public Builder addSearchSchemaElement(Consumer searchSchemaElement) { + SearchSchemaElement.Builder builder = SearchSchemaElement.builder(); + searchSchemaElement.accept(builder); + return addSearchSchemaElement(builder.build()); + } + + public EnhancedVectorIndex build() { + return new EnhancedVectorIndex(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItem.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItem.java new file mode 100644 index 000000000000..78b3c68a64db --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItem.java @@ -0,0 +1,103 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.Objects; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; + +/** + * A single vector search hit containing a mapped item and its similarity score. + * + * @param The type of the mapped item. + */ +@SdkPublicApi +@ThreadSafe +public final class SearchResultItem { + private final T item; + private final Double score; + + private SearchResultItem(Builder builder) { + this.item = builder.item; + this.score = builder.score; + } + + public static Builder builder() { + return new Builder<>(); + } + + /** + * The mapped item returned by the search operation. + */ + public T item() { + return item; + } + + /** + * The similarity score for this item, as returned by the service. + */ + public Double score() { + return score; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SearchResultItem that = (SearchResultItem) o; + return Objects.equals(score, that.score) && Objects.equals(item, that.item); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(item); + result = 31 * result + Objects.hashCode(score); + return result; + } + + /** + * A builder for {@link SearchResultItem}. + * + * @param The type of the mapped item. + */ + @NotThreadSafe + public static final class Builder { + private T item; + private Double score; + + private Builder() { + } + + public Builder item(T item) { + this.item = item; + return this; + } + + public Builder score(Double score) { + this.score = score; + return this; + } + + public SearchResultItem build() { + return new SearchResultItem<>(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElement.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElement.java new file mode 100644 index 000000000000..9315541ce099 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElement.java @@ -0,0 +1,106 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.Objects; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; + +/** + * Enhanced model representation of one element in a vector index search schema. Used with {@link EnhancedVectorIndex} when + * creating a table that includes vector indexes. + */ +@SdkPublicApi +@ThreadSafe +public final class SearchSchemaElement { + private final String attributeName; + private final SearchSchemaElementType searchSchemaElementType; + + private SearchSchemaElement(Builder builder) { + this.attributeName = builder.attributeName; + this.searchSchemaElementType = builder.searchSchemaElementType; + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().attributeName(attributeName) + .searchSchemaElementType(searchSchemaElementType); + } + + /** + * The name of the table attribute referenced by this search schema element. + */ + public String attributeName() { + return attributeName; + } + + /** + * Whether this element is a hash key for vector search or an inline filter attribute. + */ + public SearchSchemaElementType searchSchemaElementType() { + return searchSchemaElementType; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SearchSchemaElement that = (SearchSchemaElement) o; + return Objects.equals(attributeName, that.attributeName) + && searchSchemaElementType == that.searchSchemaElementType; + } + + @Override + public int hashCode() { + int result = Objects.hashCode(attributeName); + result = 31 * result + Objects.hashCode(searchSchemaElementType); + return result; + } + + /** + * A builder for {@link SearchSchemaElement}. + */ + @NotThreadSafe + public static final class Builder { + private String attributeName; + private SearchSchemaElementType searchSchemaElementType; + + private Builder() { + } + + public Builder attributeName(String attributeName) { + this.attributeName = attributeName; + return this; + } + + public Builder searchSchemaElementType(SearchSchemaElementType searchSchemaElementType) { + this.searchSchemaElementType = searchSchemaElementType; + return this; + } + + public SearchSchemaElement build() { + return new SearchSchemaElement(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementType.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementType.java new file mode 100644 index 000000000000..b5d95719581c --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementType.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 software.amazon.awssdk.enhanced.dynamodb.model; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * Type of search schema element on a vector index. + * + * @see SearchSchemaElement#searchSchemaElementType() + */ +@SdkPublicApi +public enum SearchSchemaElementType { + HASH, + INLINE_FILTER +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequest.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequest.java new file mode 100644 index 000000000000..91caede9f7a2 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequest.java @@ -0,0 +1,309 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.utils.Validate; + +/** + * Defines parameters used when performing a vector search via {@code table.vectorIndex(name).searchVectorsWithResponse(...)}. + *

    + * The vector index name is bound on the vector index handle and is not part of this request. All parameters are optional; the + * service validates required fields such as {@link #searchVector()}. + */ +@SdkPublicApi +@ThreadSafe +public final class SearchVectorsEnhancedRequest { + private final float[] searchVector; + private final Integer topK; + private final Expression searchConditionExpression; + private final List attributesToProject; + private final String returnConsumedCapacity; + + private SearchVectorsEnhancedRequest(Builder builder) { + this.searchVector = builder.searchVector == null ? null : builder.searchVector.clone(); + this.topK = builder.topK; + this.searchConditionExpression = builder.searchConditionExpression; + this.returnConsumedCapacity = builder.returnConsumedCapacity; + if (builder.attributesToProject == null) { + this.attributesToProject = null; + } else { + this.attributesToProject = Collections.unmodifiableList(new ArrayList<>(builder.attributesToProject)); + } + } + + public static Builder builder() { + return new Builder(); + } + + public Builder toBuilder() { + return builder().searchVector(searchVector) + .topK(topK) + .searchConditionExpression(searchConditionExpression) + .returnConsumedCapacity(returnConsumedCapacity) + .addNestedAttributesToProject(attributesToProject); + } + + /** + * The query embedding used for similarity search. Must match the dimensionality of the target vector index. + */ + public float[] searchVector() { + return searchVector == null ? null : searchVector.clone(); + } + + /** + * The maximum number of similar items to return. + */ + public Integer topK() { + return topK; + } + + /** + * Filter expression applied together with vector similarity, including the required HASH attribute condition when configured + * on the index. + */ + public Expression searchConditionExpression() { + return searchConditionExpression; + } + + /** + * Returns the list of projected attributes on this request object, or null if no projection is specified. Nested attributes + * are represented using the '.' separator. Example : foo.bar is represented as "foo.bar" which is indistinguishable from a + * non-nested attribute with the name "foo.bar". Use {@link #nestedAttributesToProject} if you have a use-case that requires + * discrimination between these two cases. + */ + public List attributesToProject() { + return attributesToProject != null ? attributesToProject.stream() + .map(item -> String.join(".", item.elements())) + .collect(Collectors.toList()) : null; + } + + /** + * Returns the list of projected attribute names, in the form of {@link NestedAttributeName} objects, for this request object, + * or null if no projection is specified. + * + * @see NestedAttributeName + */ + public List nestedAttributesToProject() { + return attributesToProject; + } + + /** + * Whether to return the capacity consumed by this operation. + * + * @see software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest#returnConsumedCapacity() + */ + public ReturnConsumedCapacity returnConsumedCapacity() { + return ReturnConsumedCapacity.fromValue(returnConsumedCapacity); + } + + /** + * Whether to return the capacity consumed by this operation. + *

    + * Similar to {@link #returnConsumedCapacity()} but return the value as a string. This is useful in situations where the value + * is not defined in {@link ReturnConsumedCapacity}. + */ + public String returnConsumedCapacityAsString() { + return returnConsumedCapacity; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SearchVectorsEnhancedRequest that = (SearchVectorsEnhancedRequest) o; + return Arrays.equals(searchVector, that.searchVector) + && Objects.equals(topK, that.topK) + && Objects.equals(searchConditionExpression, that.searchConditionExpression) + && Objects.equals(attributesToProject, that.attributesToProject) + && Objects.equals(returnConsumedCapacity, that.returnConsumedCapacity); + } + + @Override + public int hashCode() { + int result = Arrays.hashCode(searchVector); + result = 31 * result + Objects.hashCode(topK); + result = 31 * result + Objects.hashCode(searchConditionExpression); + result = 31 * result + Objects.hashCode(attributesToProject); + result = 31 * result + Objects.hashCode(returnConsumedCapacity); + return result; + } + + /** + * A builder for {@link SearchVectorsEnhancedRequest}. + */ + @NotThreadSafe + public static final class Builder { + private float[] searchVector; + private Integer topK; + private Expression searchConditionExpression; + private List attributesToProject; + private String returnConsumedCapacity; + + private Builder() { + } + + /** + * Sets the query embedding as a {@code float[]} (canonical representation). + */ + public Builder searchVector(float[] searchVector) { + this.searchVector = searchVector; + return this; + } + + /** + * Sets the query embedding from a list of {@link Float} values. + */ + public Builder searchVector(List searchVector) { + if (searchVector == null) { + this.searchVector = null; + return this; + } + float[] values = new float[searchVector.size()]; + for (int i = 0; i < searchVector.size(); i++) { + values[i] = searchVector.get(i); + } + this.searchVector = values; + return this; + } + + public Builder topK(Integer topK) { + this.topK = topK; + return this; + } + + public Builder topK(int topK) { + this.topK = topK; + return this; + } + + public Builder searchConditionExpression(Expression searchConditionExpression) { + this.searchConditionExpression = searchConditionExpression; + return this; + } + + /** + * Sets a collection of attribute names to be retrieved from the database. These attributes can include scalars, sets, or + * elements of a JSON document. + *

    + * If no attribute names are specified, then all attributes will be returned. If any of the requested attributes are not + * found, they will not appear in the result. + *

    If there are nested attributes, use any of the addNestedAttributesToProject methods, such as + * {@link #addNestedAttributesToProject(NestedAttributeName...)}. + * + * @param attributesToProject A collection of the attributes names to be retrieved from the database. + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Builder attributesToProject(Collection attributesToProject) { + if (this.attributesToProject != null) { + this.attributesToProject.clear(); + } + if (attributesToProject != null) { + addNestedAttributesToProject(new ArrayList<>(attributesToProject) + .stream() + .map(NestedAttributeName::create) + .collect(Collectors.toList())); + } + return this; + } + + /** + * Sets one or more attribute names to be retrieved from the database. These attributes can include scalars, sets, or + * elements of a JSON document. + *

    + * If no attribute names are specified, then all attributes will be returned. If any of the requested attributes are not + * found, they will not appear in the result. + *

    If there are nested attributes, use any of the addNestedAttributesToProject methods, such as + * {@link #addNestedAttributesToProject(NestedAttributeName...)}. + * + * @param attributesToProject One or more attributes names to be retrieved from the database. + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Builder attributesToProject(String... attributesToProject) { + return attributesToProject(Arrays.asList(attributesToProject)); + } + + /** + * Adds a single attribute name to be retrieved from the database. The attribute can include scalars, sets, or elements of + * a JSON document. + *

    If there are nested attributes, use any of the addNestedAttributesToProject methods, such as + * {@link #addNestedAttributesToProject(NestedAttributeName...)}. + * + * @param attributeToProject An additional single attribute name to be retrieved from the database. + * @return Returns a reference to this object so that method calls can be chained together. + */ + public Builder addAttributeToProject(String attributeToProject) { + if (attributeToProject != null) { + addNestedAttributesToProject(NestedAttributeName.create(attributeToProject)); + } + return this; + } + + public Builder addNestedAttributeToProject(NestedAttributeName nestedAttributeName) { + if (nestedAttributeName != null) { + addNestedAttributesToProject(Arrays.asList(nestedAttributeName)); + } + return this; + } + + public Builder addNestedAttributesToProject(NestedAttributeName... nestedAttributeNames) { + return addNestedAttributesToProject(Arrays.asList(nestedAttributeNames)); + } + + public Builder addNestedAttributesToProject(Collection nestedAttributeNames) { + if (nestedAttributeNames != null) { + Validate.noNullElements(nestedAttributeNames, + "nestedAttributeNames list must not contain null elements"); + if (attributesToProject == null) { + this.attributesToProject = new ArrayList<>(nestedAttributeNames); + } else { + this.attributesToProject.addAll(nestedAttributeNames); + } + } + return this; + } + + public Builder returnConsumedCapacity(ReturnConsumedCapacity returnConsumedCapacity) { + this.returnConsumedCapacity = returnConsumedCapacity == null ? null : returnConsumedCapacity.toString(); + return this; + } + + public Builder returnConsumedCapacity(String returnConsumedCapacity) { + this.returnConsumedCapacity = returnConsumedCapacity; + return this; + } + + public SearchVectorsEnhancedRequest build() { + return new SearchVectorsEnhancedRequest(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponse.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponse.java new file mode 100644 index 000000000000..02f0c840d45d --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponse.java @@ -0,0 +1,121 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.services.dynamodb.model.VectorCapacity; + +/** + * Response from a vector search when using {@code searchVectorsWithResponse} on a vector index handle. + * + * @param The type of the mapped items in the search results. + */ +@SdkPublicApi +@ThreadSafe +public final class SearchVectorsEnhancedResponse { + private final List> results; + private final VectorCapacity consumedCapacity; + + private SearchVectorsEnhancedResponse(Builder builder) { + if (builder.results == null) { + this.results = Collections.emptyList(); + } else { + this.results = Collections.unmodifiableList(new ArrayList<>(builder.results)); + } + this.consumedCapacity = builder.consumedCapacity; + } + + public static Builder builder() { + return new Builder<>(); + } + + /** + * The search hits, each containing a mapped item and similarity score. + */ + public List> results() { + return results; + } + + /** + * Vector search capacity consumed by the operation, when returned by the service. + * + * @see software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse#consumedCapacity() for more information. + */ + public VectorCapacity consumedCapacity() { + return consumedCapacity; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SearchVectorsEnhancedResponse that = (SearchVectorsEnhancedResponse) o; + return Objects.equals(results, that.results) && Objects.equals(consumedCapacity, that.consumedCapacity); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(results); + result = 31 * result + Objects.hashCode(consumedCapacity); + return result; + } + + /** + * A builder for {@link SearchVectorsEnhancedResponse}. + * + * @param The type of the mapped items in the search results. + */ + @NotThreadSafe + public static final class Builder { + private List> results; + private VectorCapacity consumedCapacity; + + private Builder() { + } + + public Builder results(List> results) { + this.results = results; + return this; + } + + public Builder addResult(SearchResultItem result) { + if (this.results == null) { + this.results = new ArrayList<>(); + } + this.results.add(result); + return this; + } + + public Builder consumedCapacity(VectorCapacity consumedCapacity) { + this.consumedCapacity = consumedCapacity; + return this; + } + + public SearchVectorsEnhancedResponse build() { + return new SearchVectorsEnhancedResponse<>(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadata.java b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadata.java new file mode 100644 index 000000000000..3ce9ba44fb10 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/main/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadata.java @@ -0,0 +1,215 @@ +/* + * 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.enhanced.dynamodb.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.services.dynamodb.model.Projection; + +/** + * Read-only metadata describing a vector index on a mapped table. Used when resolving {@code table.vectorIndex(indexName)} + * handles and for programmatic table schema definitions. + */ +@SdkPublicApi +@ThreadSafe +public final class VectorIndexMetadata { + private final String indexName; + private final String vectorAttributeName; + private final int dimensions; + private final DistanceFunction distanceFunction; + private final Projection projection; + private final List searchSchemaElements; + + private VectorIndexMetadata(Builder builder) { + this.indexName = builder.indexName; + this.vectorAttributeName = builder.vectorAttributeName; + this.dimensions = builder.dimensions; + this.distanceFunction = builder.distanceFunction; + this.projection = builder.projection; + if (builder.searchSchemaElements == null) { + this.searchSchemaElements = Collections.emptyList(); + } else { + this.searchSchemaElements = Collections.unmodifiableList(new ArrayList<>(builder.searchSchemaElements)); + } + } + + public static Builder builder() { + return new Builder(); + } + + /** + * Creates a {@link VectorIndexMetadata} from an {@link EnhancedVectorIndex}. + */ + public static VectorIndexMetadata fromEnhancedVectorIndex(EnhancedVectorIndex enhancedVectorIndex) { + return builder().indexName(enhancedVectorIndex.indexName()) + .vectorAttributeName(enhancedVectorIndex.vectorAttributeName()) + .dimensions(enhancedVectorIndex.dimensions()) + .distanceFunction(enhancedVectorIndex.distanceFunction()) + .projection(enhancedVectorIndex.projection()) + .searchSchemaElements(enhancedVectorIndex.searchSchemaElements()) + .build(); + } + + public Builder toBuilder() { + return builder().indexName(indexName) + .vectorAttributeName(vectorAttributeName) + .dimensions(dimensions) + .distanceFunction(distanceFunction) + .projection(projection) + .searchSchemaElements(searchSchemaElements); + } + + /** + * The name of the vector index. + */ + public String indexName() { + return indexName; + } + + /** + * The name of the table attribute that stores the vector embedding for this index. + */ + public String vectorAttributeName() { + return vectorAttributeName; + } + + /** + * The number of dimensions in the vector embedding. + */ + public int dimensions() { + return dimensions; + } + + /** + * The distance function used for similarity search on this index. + */ + public DistanceFunction distanceFunction() { + return distanceFunction; + } + + /** + * The attribute projection setting for this vector index. + */ + public Projection projection() { + return projection; + } + + /** + * The search schema elements for this vector index. + */ + public List searchSchemaElements() { + return searchSchemaElements; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorIndexMetadata that = (VectorIndexMetadata) o; + return dimensions == that.dimensions + && Objects.equals(indexName, that.indexName) + && Objects.equals(vectorAttributeName, that.vectorAttributeName) + && distanceFunction == that.distanceFunction + && Objects.equals(projection, that.projection) + && Objects.equals(searchSchemaElements, that.searchSchemaElements); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(indexName); + result = 31 * result + Objects.hashCode(vectorAttributeName); + result = 31 * result + Objects.hashCode(dimensions); + result = 31 * result + Objects.hashCode(distanceFunction); + result = 31 * result + Objects.hashCode(projection); + result = 31 * result + Objects.hashCode(searchSchemaElements); + return result; + } + + /** + * A builder for {@link VectorIndexMetadata}. + */ + @NotThreadSafe + public static final class Builder { + private String indexName; + private String vectorAttributeName; + private int dimensions; + private DistanceFunction distanceFunction; + private Projection projection; + private List searchSchemaElements; + + private Builder() { + } + + public Builder indexName(String indexName) { + this.indexName = indexName; + return this; + } + + public Builder vectorAttributeName(String vectorAttributeName) { + this.vectorAttributeName = vectorAttributeName; + return this; + } + + public String vectorAttributeName() { + return vectorAttributeName; + } + + public Builder dimensions(int dimensions) { + this.dimensions = dimensions; + return this; + } + + public Builder distanceFunction(DistanceFunction distanceFunction) { + this.distanceFunction = distanceFunction; + return this; + } + + public Builder projection(Projection projection) { + this.projection = projection; + return this; + } + + public Builder searchSchemaElements(List searchSchemaElements) { + this.searchSchemaElements = searchSchemaElements; + return this; + } + + /** + * Adds a single search schema element to this vector index definition. Elements are accumulated incrementally when + * building vector index metadata from annotations. + */ + public Builder addSearchSchemaElement(SearchSchemaElement element) { + if (this.searchSchemaElements == null) { + this.searchSchemaElements = new ArrayList<>(); + } + this.searchSchemaElements.add(element); + return this; + } + + public VectorIndexMetadata build() { + return new VectorIndexMetadata(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultMethodsUnsupportedOperationTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultMethodsUnsupportedOperationTest.java index 2e04f9bd1871..53e08955a472 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultMethodsUnsupportedOperationTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/DefaultMethodsUnsupportedOperationTest.java @@ -55,7 +55,7 @@ Stream testDefaultMethodsThrowUnsupportedOperation() { .stream() .flatMap(this::createTestsForInterface) .collect(toList()); - assertEquals(102, dynamicTestList.size()); + assertEquals(108, dynamicTestList.size()); return dynamicTestList.stream(); } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchemaTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchemaTest.java index 79e26f3b6b72..a5aab3d156f6 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchemaTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/document/DocumentTableSchemaTest.java @@ -37,11 +37,16 @@ import software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider; import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; +import software.amazon.awssdk.enhanced.dynamodb.IndexMetadata; import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.converters.document.CustomAttributeForDocumentConverterProvider; import software.amazon.awssdk.enhanced.dynamodb.converters.document.CustomClassForDocumentAPI; import software.amazon.awssdk.enhanced.dynamodb.internal.converter.ChainConverterProvider; import software.amazon.awssdk.enhanced.dynamodb.internal.mapper.StaticKeyAttributeMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; class DocumentTableSchemaTest { @@ -249,6 +254,35 @@ void validate_DocumentTableSchemaItemToMapWithFilter(TestData testData) { )).isEqualTo(filteredAttributeValueMap); } + @Test + void vectorIndexMetadata_storedSeparatelyFromGsiAndLsiIndices() { + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.COSINE) + .addSearchSchemaElement(b -> b.attributeName("id") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .build(); + + DocumentTableSchema documentTableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "id", + AttributeValueType.S) + .vectorIndexes(vectorIndex) + .build(); + + TableMetadata metadata = documentTableSchema.tableMetadata(); + + assertThat(metadata.vectorIndices()) + .hasSize(1) + .containsExactly(VectorIndexMetadata.fromEnhancedVectorIndex(vectorIndex)); + assertThat(metadata.indices()) + .extracting(IndexMetadata::name) + .doesNotContain("embeddings-index"); + } + @Test void validate_DocumentTableSchema_WithCustomIntegerAttributeProvider() { EnhancedDocument numberDocument = EnhancedDocument.builder() diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/ExtensionSpiContractTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/ExtensionSpiContractTest.java new file mode 100644 index 000000000000..219e9de30a8f --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/extensions/ExtensionSpiContractTest.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.enhanced.dynamodb.extensions; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +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.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.internal.extensions.DefaultDynamoDbExtensionContext; +import software.amazon.awssdk.enhanced.dynamodb.internal.operations.DefaultOperationContext; +import software.amazon.awssdk.enhanced.dynamodb.internal.operations.OperationName; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +public class ExtensionSpiContractTest { + + private static final String TABLE_NAME = "extension-spi-contract-table"; + + private static final TableSchema TABLE_SCHEMA = StaticTableSchema.builder(NoExtensionItem.class) + .newItemSupplier(NoExtensionItem::new) + .addAttribute(String.class, + a -> a.name("id") + .getter(NoExtensionItem::getId) + .setter(NoExtensionItem::setId) + .tags(primaryPartitionKey())) + .build(); + + private static final TableMetadata TABLE_METADATA = TABLE_SCHEMA.tableMetadata(); + + private static final List WRITE_OPERATIONS = Arrays.asList( + OperationName.PUT_ITEM, + OperationName.UPDATE_ITEM, + OperationName.BATCH_WRITE_ITEM, + OperationName.TRANSACT_WRITE_ITEMS + ); + + private static Stream extensionAndOperations() { + List> extensionSuppliers = Arrays.asList( + AutoGeneratedTimestampRecordExtension::create, + AutoGeneratedUuidExtension::create, + () -> AtomicCounterExtension.builder().build(), + () -> VersionedRecordExtension.builder().build() + ); + + return extensionSuppliers.stream() + .flatMap(supplier -> WRITE_OPERATIONS.stream() + .map(operation -> Arguments.of(supplier.get(), + operation))); + } + + @ParameterizedTest(name = "{0} with {1}") + @MethodSource("extensionAndOperations") + public void beforeWrite_noOptionalCapabilities_returnsNoOpAndDoesNotMutateItems( + DynamoDbEnhancedClientExtension extension, + OperationName operationName) { + + Map items = new HashMap<>(); + items.put("id", AttributeValue.builder().s("id1").build()); + + Map originalItems = new HashMap<>(items); + + DefaultDynamoDbExtensionContext context = DefaultDynamoDbExtensionContext.builder() + .items(items) + .tableMetadata(TABLE_METADATA) + .tableSchema(TABLE_SCHEMA) + .operationName(operationName) + .operationContext(DefaultOperationContext.create(TABLE_NAME)) + .build(); + + WriteModification modification = extension.beforeWrite(context); + + assertThat(items).isEqualTo(originalItems); + assertThat(modification).isEqualTo(WriteModification.builder().build()); + } + + private static final class NoExtensionItem { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } +} + diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAtomicCounterTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAtomicCounterTest.java new file mode 100644 index 000000000000..09d4520e59b0 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAtomicCounterTest.java @@ -0,0 +1,64 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AtomicCounterRecord; + +public class AsyncAtomicCounterTest extends LocalDynamoDbAsyncTestBase { + private static final TableSchema TABLE_SCHEMA = TableSchema.fromClass(AtomicCounterRecord.class); + + private final DynamoDbEnhancedAsyncClient enhancedAsyncClient = + DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + + private final DynamoDbAsyncTable mappedTable = + enhancedAsyncClient.table(getConcreteTableName("table-name"), TABLE_SCHEMA); + + @Before + public void createTable() { + mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void deleteTable() { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("table-name"))).join(); + } + + @Test + public void repeatedUpdate_shouldIncrementCountersOnEachUpdate() { + AtomicCounterRecord record = new AtomicCounterRecord(); + record.setId("id1"); + record.setAttribute1("value"); + mappedTable.updateItem(record).join(); + mappedTable.updateItem(record).join(); + mappedTable.updateItem(record).join(); + + AtomicCounterRecord persisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + // AtomicCounterRecord annotations: defaultCounter (delta=1, start=0), customCounter (delta=5, start=10), + // decreasingCounter (delta=-1, start=-20). First updateItem creates the item using start values; + // each subsequent update adds delta. After 3 updateItem calls: 0+1+1=2, 10+5+5=20, -20-1-1=-22. + assertThat(persisted.getDefaultCounter()).isEqualTo(2L); + assertThat(persisted.getCustomCounter()).isEqualTo(20L); + assertThat(persisted.getDecreasingCounter()).isEqualTo(-22L); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedTimestampConvertedByListTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedTimestampConvertedByListTest.java new file mode 100644 index 000000000000..70cb39eea0ad --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedTimestampConvertedByListTest.java @@ -0,0 +1,163 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.time.Clock; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.BeanWithCustomConvertedList; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.CustomConvertedPojo; +import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; + +public class AsyncAutoGeneratedTimestampConvertedByListTest extends LocalDynamoDbAsyncTestBase { + private static final Instant MOCKED_INSTANT_NOW = Instant.parse("2019-01-13T14:00:00Z"); + + private DynamoDbEnhancedAsyncClient extensionEnhancedAsyncClient; + private DynamoDbAsyncTable table; + private String tableName; + + private final TableSchema tableSchema = + BeanTableSchema.create(BeanWithCustomConvertedList.class); + + private Clock mockClock; + + @Before + public void setUp() { + mockClock = Mockito.mock(Clock.class); + Mockito.when(mockClock.instant()).thenReturn(MOCKED_INSTANT_NOW); + + extensionEnhancedAsyncClient = + DefaultDynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.builder() + .baseClock(mockClock) + .build()) + .build(); + + tableName = getConcreteTableName("converted-by-list-extension-async-test-table"); + table = extensionEnhancedAsyncClient.table(tableName, tableSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void tearDown() { + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(tableName) + .build()).join(); + } + + @Test + public void putThenUpdateItem_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList initial = new BeanWithCustomConvertedList() + .setId("id1") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + table.putItem(r -> r.item(initial)).join(); + + List updatedCustomItems = Arrays.asList( + new CustomConvertedPojo("c", 3), + new CustomConvertedPojo("d", 4)); + + BeanWithCustomConvertedList updated = new BeanWithCustomConvertedList() + .setId("id1") + .setCustomItems(updatedCustomItems); + + table.updateItem(r -> r.item(updated)).join(); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), updatedCustomItems); + } + + @Test + public void batchWriteItem_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("id2") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + WriteBatch writeBatch = WriteBatch.builder(BeanWithCustomConvertedList.class) + .mappedTableResource(table) + .addPutItem(r -> r.item(record)) + .build(); + + extensionEnhancedAsyncClient.batchWriteItem( + BatchWriteItemEnhancedRequest.builder() + .writeBatches(Arrays.asList(writeBatch)) + .build()).join(); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id2"))).join(); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), record.getCustomItems()); + } + + @Test + public void transactWriteItems_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("id3") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + extensionEnhancedAsyncClient.transactWriteItems( + TransactWriteItemsEnhancedRequest.builder() + .addPutItem(table, record) + .build()).join(); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id3"))).join(); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), record.getCustomItems()); + } + + private static void assertCustomItems(List actual, + List expected) { + assertThat(actual.size(), is(expected.size())); + for (int i = 0; i < expected.size(); i++) { + assertThat(actual.get(i).getLabel(), is(expected.get(i).getLabel())); + assertThat(actual.get(i).getCount(), is(expected.get(i).getCount())); + } + } +} + diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedUuidRecordTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedUuidRecordTest.java new file mode 100644 index 000000000000..0a134b54abf7 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncAutoGeneratedUuidRecordTest.java @@ -0,0 +1,101 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension.AttributeTags.autoGeneratedUuidAttribute; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.updateBehavior; + +import java.util.UUID; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedUuidExtension; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.UpdateBehavior; + +public class AsyncAutoGeneratedUuidRecordTest extends LocalDynamoDbAsyncTestBase { + private static class Record { + private String id; + private String writeAlwaysUuid; + private String writeIfNotExistsUuid; + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getWriteAlwaysUuid() { return writeAlwaysUuid; } + public void setWriteAlwaysUuid(String writeAlwaysUuid) { this.writeAlwaysUuid = writeAlwaysUuid; } + public String getWriteIfNotExistsUuid() { return writeIfNotExistsUuid; } + public void setWriteIfNotExistsUuid(String writeIfNotExistsUuid) { this.writeIfNotExistsUuid = writeIfNotExistsUuid; } + } + + private static final TableSchema TABLE_SCHEMA = + StaticTableSchema.builder(Record.class) + .newItemSupplier(Record::new) + .addAttribute(String.class, a -> a.name("id").getter(Record::getId).setter(Record::setId) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("writeAlwaysUuid") + .getter(Record::getWriteAlwaysUuid) + .setter(Record::setWriteAlwaysUuid) + .tags(autoGeneratedUuidAttribute())) + .addAttribute(String.class, a -> a.name("writeIfNotExistsUuid") + .getter(Record::getWriteIfNotExistsUuid) + .setter(Record::setWriteIfNotExistsUuid) + .tags(autoGeneratedUuidAttribute(), + updateBehavior(UpdateBehavior.WRITE_IF_NOT_EXISTS))) + .build(); + + private final DynamoDbEnhancedAsyncClient enhancedAsyncClient = + DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedUuidExtension.create()) + .build(); + + private final DynamoDbAsyncTable mappedTable = enhancedAsyncClient.table(getConcreteTableName("table-name"), + TABLE_SCHEMA); + + @Before + public void createTable() { + mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void deleteTable() { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("table-name"))).join(); + } + + @Test + public void putOverwrite_withExplicitUuidValues_shouldRegenerateWriteAlwaysAndNotPreserveWriteIfNotExists() { + Record seed = new Record(); + seed.setId("id1"); + mappedTable.putItem(seed).join(); + + Record overwrite = new Record(); + overwrite.setId("id1"); + overwrite.setWriteAlwaysUuid("manual-a"); + overwrite.setWriteIfNotExistsUuid("manual-b"); + mappedTable.putItem(overwrite).join(); + Record persisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + + assertThat(persisted.getWriteAlwaysUuid()).isNotEqualTo("manual-a"); + UUID.fromString(persisted.getWriteAlwaysUuid()); + assertThat(persisted.getWriteIfNotExistsUuid()).isNotEqualTo("manual-b"); + assertThat(persisted.getWriteIfNotExistsUuid()).isNotNull(); + UUID.fromString(persisted.getWriteIfNotExistsUuid()); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicCrudTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicCrudTest.java index 7901f42fe594..f3637f439427 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicCrudTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicCrudTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; @@ -25,7 +26,10 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondaryPartitionKey; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondarySortKey; +import java.util.Collections; import java.util.Objects; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CompletionException; import org.junit.After; import org.junit.Before; @@ -37,6 +41,8 @@ import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.DeleteItemEnhancedRequest; @@ -44,6 +50,7 @@ import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ProjectionType; @@ -677,4 +684,29 @@ public void getAShortRecordWithNewModelledFields() { Record result = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id-value").sortValue("sort-value"))).join(); assertThat(result, is(expectedRecord)); } + + @Test + public void extensionEnabledClient_withUnsupportedCustomSchema_putAndUpdateDoNotThrow() { + DynamoDbEnhancedAsyncClient extensionClient = DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbAsyncTable> customTable = + extensionClient.table(getConcreteTableName("crud-custom-table"), new UnsupportedConverterTableSchema()); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-1").build()); + item.put("nested", + AttributeValue.builder() + .m(Collections.singletonMap("k", AttributeValue.builder().s("v").build())) + .build()); + + customTable.putItem(item).join(); + customTable.updateItem(item).join(); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))).join(); + assertThat(persisted, is(notNullValue())); + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("crud-custom-table"))).join(); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicQueryTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicQueryTest.java index b7fe4c041801..02382567bf0b 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicQueryTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicQueryTest.java @@ -25,11 +25,14 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey; import static software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional.keyEqualTo; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.CompletionException; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.junit.After; @@ -40,7 +43,10 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.InnerAttributeRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.NestedTestRecord; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.Page; @@ -48,6 +54,7 @@ import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.Select; public class AsyncBasicQueryTest extends LocalDynamoDbAsyncTestBase { private static class Record { @@ -119,19 +126,42 @@ public int hashCode() { .mapToObj(i -> new Record().setId("id-value").setSort(i).setValue(i)) .collect(Collectors.toList()); + private static final List NESTED_TEST_RECORDS = + IntStream.range(0, 10) + .mapToObj(i -> { + NestedTestRecord nestedTestRecord = new NestedTestRecord(); + nestedTestRecord.setOuterAttribOne("id-value-" + i); + nestedTestRecord.setSort(i); + InnerAttributeRecord innerAttributeRecord = new InnerAttributeRecord(); + innerAttributeRecord.setAttribOne("attribOne-" + i); + innerAttributeRecord.setAttribTwo(i); + nestedTestRecord.setInnerAttributeRecord(innerAttributeRecord); + nestedTestRecord.setDotVariable("v" + i); + return nestedTestRecord; + }) + .collect(Collectors.toList()); + private DynamoDbEnhancedAsyncClient enhancedAsyncClient = DefaultDynamoDbEnhancedAsyncClient.builder() .dynamoDbClient(getDynamoDbAsyncClient()) .build(); private DynamoDbAsyncTable mappedTable = enhancedAsyncClient.table(getConcreteTableName("table-name"), TABLE_SCHEMA); + private DynamoDbAsyncTable mappedNestedTable = + enhancedAsyncClient.table(getConcreteTableName("nested-table-name"), TableSchema.fromClass(NestedTestRecord.class)); private void insertRecords() { RECORDS.forEach(record -> mappedTable.putItem(r -> r.item(record)).join()); + NESTED_TEST_RECORDS.forEach(record -> mappedNestedTable.putItem(r -> r.item(record)).join()); + } + + private void insertNestedRecords() { + NESTED_TEST_RECORDS.forEach(record -> mappedNestedTable.putItem(r -> r.item(record)).join()); } @Before public void createTable() { mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + mappedNestedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); } @After @@ -140,6 +170,10 @@ public void deleteTable() { .tableName(getConcreteTableName("table-name")) .build()) .join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("nested-table-name")) + .build()) + .join(); } @Test @@ -182,6 +216,22 @@ public void queryAllRecordsWithFilter() { assertThat(page.lastEvaluatedKey(), is(nullValue())); } + @Test + public void queryAllRecords_withAttributeProjection_shouldExcludeUnprojectedAttributes() { + insertRecords(); + SdkPublisher> publisher = + mappedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .attributesToProject("value")); + + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.items().size(), is(RECORDS.size())); + Record firstRecord = page.items().get(0); + assertThat(firstRecord.id, is(nullValue())); + assertThat(firstRecord.sort, is(nullValue())); + assertThat(firstRecord.value, is(0)); + } + @Test public void queryAllRecordsWithFilter_viaItems() { insertRecords(); @@ -314,4 +364,72 @@ public void queryExclusiveStartKey() { assertThat(page.items(), is(RECORDS.subList(8, 10))); assertThat(page.lastEvaluatedKey(), is(nullValue())); } + + @Test + public void queryAllRecords_withSelectCount_shouldReturnCountNotItems() { + insertRecords(); + SdkPublisher> publisher = + mappedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .select(Select.COUNT)); + + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.count(), is(RECORDS.size())); + assertThat(page.scannedCount(), is(RECORDS.size())); + assertThat(page.items(), is(empty())); + } + + @Test + public void queryNestedRecord_withMixedNestedAndTopLevelProjections_shouldProjectMultipleAttributes() { + insertNestedRecords(); + SdkPublisher> publisher = + mappedNestedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value-1"))) + .addNestedAttributesToProject(Arrays.asList( + NestedAttributeName.builder().elements("innerAttributeRecord", "attribOne").build())) + .addNestedAttributesToProject(NestedAttributeName.create("innerAttributeRecord", "attribTwo")) + .addAttributeToProject("sort")); + + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.items().size(), is(1)); + NestedTestRecord firstRecord = page.items().get(0); + assertThat(firstRecord.getOuterAttribOne(), is(nullValue())); + assertThat(firstRecord.getSort(), is(1)); + assertThat(firstRecord.getInnerAttributeRecord().getAttribOne(), is("attribOne-1")); + assertThat(firstRecord.getInnerAttributeRecord().getAttribTwo(), is(1)); + } + + @Test + public void queryRecords_withEmptyProjectionList_shouldReturnAllAttributes() { + insertNestedRecords(); + SdkPublisher> publisher = + mappedNestedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value-7"))) + .attributesToProject(new ArrayList<>())); + List> results = drainPublisher(publisher, 1); + NestedTestRecord firstRecord = results.get(0).items().get(0); + assertThat(firstRecord.getOuterAttribOne(), is("id-value-7")); + assertThat(firstRecord.getSort(), is(7)); + assertThat(firstRecord.getInnerAttributeRecord().getAttribTwo(), is(7)); + assertThat(firstRecord.getDotVariable(), is("v7")); + } + + @Test + public void queryRecords_withEmptyProjectionString_shouldThrowCompletionException() { + insertNestedRecords(); + drainPublisherToError( + mappedNestedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value-3"))) + .attributesToProject("")), + 0, + CompletionException.class); + } + + @Test + public void queryRecords_withEmptyNestedProjectionName_shouldThrowCompletionException() { + insertNestedRecords(); + drainPublisherToError( + mappedNestedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value-3"))) + .addNestedAttributeToProject(NestedAttributeName.create(""))), + 0, + CompletionException.class); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicScanTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicScanTest.java index e69ff876e4ad..6e189fed7584 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicScanTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBasicScanTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; @@ -24,11 +25,13 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.CompletionException; import java.util.stream.Collectors; import java.util.stream.IntStream; import org.junit.After; @@ -38,13 +41,17 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.InnerAttributeRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.NestedTestRecord; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.Page; import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.Select; public class AsyncBasicScanTest extends LocalDynamoDbAsyncTestBase { private static class Record { @@ -102,20 +109,42 @@ public int hashCode() { .mapToObj(i -> new Record().setId("id-value").setSort(i)) .collect(Collectors.toList()); + private static final List NESTED_TEST_RECORDS = + IntStream.range(0, 10) + .mapToObj(i -> { + NestedTestRecord nestedTestRecord = new NestedTestRecord(); + nestedTestRecord.setOuterAttribOne("id-value-" + i); + nestedTestRecord.setSort(i); + InnerAttributeRecord innerAttributeRecord = new InnerAttributeRecord(); + innerAttributeRecord.setAttribOne("attribOne-" + i); + innerAttributeRecord.setAttribTwo(i); + nestedTestRecord.setInnerAttributeRecord(innerAttributeRecord); + nestedTestRecord.setDotVariable("v" + i); + return nestedTestRecord; + }) + .collect(Collectors.toList()); + private DynamoDbEnhancedAsyncClient enhancedAsyncClient = DefaultDynamoDbEnhancedAsyncClient.builder() .dynamoDbClient(getDynamoDbAsyncClient()) .build(); private DynamoDbAsyncTable mappedTable = enhancedAsyncClient.table(getConcreteTableName("table-name"), TABLE_SCHEMA); + private DynamoDbAsyncTable mappedNestedTable = + enhancedAsyncClient.table(getConcreteTableName("nested-table-name"), TableSchema.fromClass(NestedTestRecord.class)); private void insertRecords() { RECORDS.forEach(record -> mappedTable.putItem(r -> r.item(record)).join()); } + private void insertNestedRecords() { + NESTED_TEST_RECORDS.forEach(record -> mappedNestedTable.putItem(r -> r.item(record)).join()); + } + @Before public void createTable() { mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + mappedNestedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); } @After @@ -123,6 +152,9 @@ public void deleteTable() { getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() .tableName(getConcreteTableName("table-name")) .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("nested-table-name")) + .build()).join(); } @Test @@ -169,6 +201,40 @@ public void scanAllRecordsWithFilter() { assertThat(page.lastEvaluatedKey(), is(nullValue())); } + @Test + public void scanAllRecords_withAttributeProjection_shouldExcludeUnprojectedAttributes() { + insertRecords(); + SdkPublisher> publisher = mappedTable.scan(b -> b.attributesToProject("sort")); + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.items().size(), is(RECORDS.size())); + Record firstRecord = page.items().get(0); + assertThat(firstRecord.id, is(nullValue())); + assertThat(firstRecord.sort, is(0)); + } + + @Test + public void scanRecords_withBothFilterAndProjection_shouldApplyBoth() { + insertRecords(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + SdkPublisher> publisher = mappedTable.scan(ScanEnhancedRequest.builder() + .attributesToProject("sort") + .filterExpression(expression) + .build()); + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.items(), hasSize(3)); + assertThat(page.items().get(0).id, is(nullValue())); + assertThat(page.items().get(0).sort, is(3)); + } + @Test public void scanAllRecordsWithFilter_viaItems() { insertRecords(); @@ -261,6 +327,88 @@ public void scanExclusiveStartKey_viaItems() { assertThat(results, is(RECORDS.subList(8, 10))); } + @Test + public void scanAllRecords_withSelectCount_shouldReturnCountNotItems() { + insertRecords(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + SdkPublisher> publisher = mappedTable.scan(ScanEnhancedRequest.builder() + .select(Select.COUNT) + .filterExpression(expression) + .build()); + List> results = drainPublisher(publisher, 1); + Page page = results.get(0); + assertThat(page.count(), is(3)); + assertThat(page.items().size(), is(0)); + } + + @Test + public void scanRecords_withBothFilterAndNestedProjection_shouldApplyBoth() { + insertNestedRecords(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + SdkPublisher> publisher = mappedNestedTable.scan(ScanEnhancedRequest.builder() + .filterExpression(expression) + .addNestedAttributesToProject( + NestedAttributeName.create(Arrays.asList("innerAttributeRecord", "attribOne"))) + .build()); + List> results = drainPublisher(publisher, 1); + assertThat(results.get(0).items().size(), is(3)); + } + + @Test + public void scanRecords_withEmptyNestedAttributeName_shouldThrowCompletionException() { + insertNestedRecords(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + + drainPublisherToError(mappedNestedTable.scan(ScanEnhancedRequest.builder() + .filterExpression(expression) + .addNestedAttributesToProject(NestedAttributeName.builder() + .elements("") + .build()) + .build()), + 0, + CompletionException.class); + } + + @Test + public void scanRecords_withEmptyTopLevelAttributeName_shouldThrowCompletionException() { + insertNestedRecords(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + drainPublisherToError(mappedNestedTable.scan(ScanEnhancedRequest.builder() + .filterExpression(expression) + .addAttributeToProject("") + .build()), + 0, + CompletionException.class); + } + private Map getKeyMap(int sort) { Map result = new HashMap<>(); result.put("id", stringValue("id-value")); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchGetItemTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchGetItemTest.java index c22263f6e4e0..21ffed20859d 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchGetItemTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchGetItemTest.java @@ -38,6 +38,10 @@ import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetResultPage; import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetResultPagePublisher; @@ -47,6 +51,34 @@ import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class AsyncBatchGetItemTest extends LocalDynamoDbAsyncTestBase { + @DynamoDbBean + public static class BeanRecord { + private Integer id; + private String value; + @DynamoDbPartitionKey + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + public String getValue() { return value; } + public void setValue(String value) { this.value = value; } + } + + @DynamoDbImmutable(builder = ImmutableRecord.Builder.class) + public static final class ImmutableRecord { + private final Integer id; + private final String value; + private ImmutableRecord(Builder b) { this.id = b.id; this.value = b.value; } + @DynamoDbPartitionKey + public Integer id() { return id; } + public String value() { return value; } + public static Builder builder() { return new Builder(); } + public static final class Builder { + private Integer id; + private String value; + public Builder id(Integer id) { this.id = id; return this; } + public Builder value(String value) { this.value = value; return this; } + public ImmutableRecord build() { return new ImmutableRecord(this); } + } + } private static class Record1 { private Integer id; private String stringAttr; @@ -152,6 +184,10 @@ public int hashCode() { private final String tableName2 = getConcreteTableName("table-name-2"); private final DynamoDbAsyncTable mappedTable1 = enhancedAsyncClient.table(tableName1, TABLE_SCHEMA_1); private final DynamoDbAsyncTable mappedTable2 = enhancedAsyncClient.table(tableName2, TABLE_SCHEMA_2); + private final DynamoDbAsyncTable mappedBeanTable = + enhancedAsyncClient.table(getConcreteTableName("table-name-bean"), TableSchema.fromBean(BeanRecord.class)); + private final DynamoDbAsyncTable mappedImmutableTable = + enhancedAsyncClient.table(getConcreteTableName("table-name-immutable"), TableSchema.fromImmutableClass(ImmutableRecord.class)); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -167,6 +203,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + mappedBeanTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + mappedImmutableTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); } @After @@ -177,6 +215,12 @@ public void deleteTable() { getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() .tableName(tableName2) .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("table-name-bean")) + .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("table-name-immutable")) + .build()).join(); } private void insertRecords() { @@ -312,6 +356,74 @@ public void notFoundRecords_withReturnConsumedCapacity() { } + @Test + public void batchGetRecordsWithExtension_shouldPreserveAndReturnCorrectData() { + insertRecords(); + + DynamoDbEnhancedAsyncClient extensionClient = + DefaultDynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + + DynamoDbAsyncTable extensionMappedTable1 = extensionClient.table(tableName1, TABLE_SCHEMA_1); + DynamoDbAsyncTable extensionMappedTable2 = extensionClient.table(tableName2, TABLE_SCHEMA_2); + + BatchGetItemEnhancedRequest request = BatchGetItemEnhancedRequest.builder() + .readBatches( + ReadBatch.builder(Record1.class) + .mappedTableResource(extensionMappedTable1) + .addGetItem(i -> i.key(k -> k.partitionValue(0))) + .build(), + ReadBatch.builder(Record2.class) + .mappedTableResource(extensionMappedTable2) + .addGetItem(i -> i.key(k -> k.partitionValue(0))) + .build(), + ReadBatch.builder(Record2.class) + .mappedTableResource(extensionMappedTable2) + .addGetItem(i -> i.key(k -> k.partitionValue(1))) + .build(), + ReadBatch.builder(Record1.class) + .mappedTableResource(extensionMappedTable1) + .addGetItem(i -> i.key(k -> k.partitionValue(1))) + .build()) + .build(); + + BatchGetResultPagePublisher publisher = extensionClient.batchGetItem(request); + List results = drainPublisher(publisher, 1); + assertThat(results.size(), is(1)); + + BatchGetResultPage page = results.get(0); + List record1List = page.resultsForTable(extensionMappedTable1); + assertThat(record1List.size(), is(2)); + assertThat(record1List, containsInAnyOrder(RECORDS_1.get(0), RECORDS_1.get(1))); + + List record2List = page.resultsForTable(extensionMappedTable2); + assertThat(record2List.size(), is(2)); + assertThat(record2List, containsInAnyOrder(RECORDS_2.get(0), RECORDS_2.get(1))); + } + + @Test + public void batchGetRecords_fromMixedSchemaTypes_shouldReturnCorrectlyCastItems() { + insertRecords(); + BeanRecord bean = new BeanRecord(); + bean.setId(10); + bean.setValue("bean"); + mappedBeanTable.putItem(bean).join(); + ImmutableRecord immutable = ImmutableRecord.builder().id(20).value("immutable").build(); + mappedImmutableTable.putItem(immutable).join(); + + BatchGetResultPagePublisher publisher = enhancedAsyncClient.batchGetItem(r -> r.readBatches( + ReadBatch.builder(Record1.class).mappedTableResource(mappedTable1).addGetItem(i -> i.key(k -> k.partitionValue(0))).build(), + ReadBatch.builder(BeanRecord.class).mappedTableResource(mappedBeanTable).addGetItem(i -> i.key(k -> k.partitionValue(10))).build(), + ReadBatch.builder(ImmutableRecord.class).mappedTableResource(mappedImmutableTable).addGetItem(i -> i.key(k -> k.partitionValue(20))).build())); + + List pages = drainPublisher(publisher, 1); + assertThat(pages.size(), is(1)); + assertThat(pages.get(0).resultsForTable(mappedBeanTable).get(0).getValue(), is("bean")); + assertThat(pages.get(0).resultsForTable(mappedImmutableTable).get(0).value(), is("immutable")); + } + private BatchGetItemEnhancedRequest requestWithNotFoundRecord() { return BatchGetItemEnhancedRequest.builder() .readBatches( diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchWriteItemTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchWriteItemTest.java index 79df622d9a82..998acc7c2fd4 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchWriteItemTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncBatchWriteItemTest.java @@ -19,9 +19,12 @@ import static java.util.Collections.singletonList; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -35,6 +38,9 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.TimestampedRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; @@ -42,6 +48,7 @@ import software.amazon.awssdk.enhanced.dynamodb.model.DeleteItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ItemCollectionMetrics; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; @@ -158,11 +165,20 @@ public int hashCode() { DefaultDynamoDbEnhancedAsyncClient.builder() .dynamoDbClient(getDynamoDbAsyncClient()) .build(); + private DynamoDbEnhancedAsyncClient extensionEnhancedAsyncClient = + DefaultDynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); private DynamoDbAsyncTable mappedTable1 = enhancedAsyncClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); private DynamoDbAsyncTable mappedTable2 = enhancedAsyncClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + private DynamoDbAsyncTable timestampedTable = + extensionEnhancedAsyncClient.table(getConcreteTableName("timestamped-table"), TimestampedRecord.TABLE_SCHEMA); + private DynamoDbAsyncTable> unsupportedCustomSchemaTable = + extensionEnhancedAsyncClient.table(getConcreteTableName("unsupported-schema-table"), new UnsupportedConverterTableSchema()); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -178,6 +194,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + timestampedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + unsupportedCustomSchemaTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); } @After @@ -188,6 +206,12 @@ public void deleteTable() { getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() .tableName(getConcreteTableName("table-name-2")) .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("timestamped-table")) + .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("unsupported-schema-table")) + .build()).join(); } @Test @@ -419,4 +443,75 @@ public void mixedCommands_withConsumedCapacity() { assertThat(mappedTable2.getItem(r -> r.key(k -> k.partitionValue(0))).join(), is(nullValue())); } + @Test + public void batchWrite_withSupportedAndUnsupportedSchema_shouldPreserveUnsupportedSchemaValues() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(Collections.singletonMap("inner", + AttributeValue.builder().s("value").build())) + .build()); + + extensionEnhancedAsyncClient.batchWriteItem( + BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(TimestampedRecord.class) + .mappedTableResource(timestampedTable) + .addPutItem(r -> r.item(new TimestampedRecord().setId("ts-1"))) + .build(), + WriteBatch.builder(customTableType()) + .mappedTableResource(unsupportedCustomSchemaTable) + .addPutItem(r -> r.item(customItem)) + .build()) + .build()).join(); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))).join(); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))).join(); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } + + @Test + public void batchWriteWithResponse_withSupportedAndUnsupportedSchema_shouldReturnMetrics() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(Collections.singletonMap("inner", + AttributeValue.builder().s("value").build())) + .build()); + + BatchWriteResult result = + extensionEnhancedAsyncClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(TimestampedRecord.class) + .mappedTableResource(timestampedTable) + .addPutItem(r -> r.item(new TimestampedRecord().setId("ts-1"))) + .build(), + WriteBatch.builder(customTableType()) + .mappedTableResource(unsupportedCustomSchemaTable) + .addPutItem(r -> r.item(customItem)) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .build()).join(); + + assertThat(result.consumedCapacity(), is(notNullValue())); + assertThat(result.consumedCapacity().size(), is(2)); + assertThat(result.itemCollectionMetrics(), is(notNullValue())); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))).join(); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))).join(); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } + + @SuppressWarnings("unchecked") + private Class> customTableType() { + return (Class>) (Class) Map.class; + } + } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncDeleteItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncDeleteItemWithResponseTest.java index d4c9c2492800..ac2b4fe9fef9 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncDeleteItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncDeleteItemWithResponseTest.java @@ -116,4 +116,20 @@ public void returnConsumedCapacity_set_consumedCapacityNotNull() { assertThat(response.consumedCapacity()).isNotNull(); } + + @Test + public void deleteItem_simpleAndWithResponse_shouldReturnSameAttributes() { + Record first = new Record().setId(11).setStringAttr1("a"); + mappedTable1.putItem(first).join(); + Record deletedBySimple = mappedTable1.deleteItem(r -> r.key(k -> k.partitionValue(11))).join(); + assertThat(deletedBySimple).isEqualTo(first); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(11))).join()).isNull(); + + Record second = new Record().setId(12).setStringAttr1("b"); + mappedTable1.putItem(second).join(); + DeleteItemEnhancedResponse response = + mappedTable1.deleteItemWithResponse(r -> r.key(k -> k.partitionValue(12))).join(); + assertThat(response.attributes()).isEqualTo(second); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(12))).join()).isNull(); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncGetItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncGetItemWithResponseTest.java index 9581233810fa..2f2011535de8 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncGetItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncGetItemWithResponseTest.java @@ -27,6 +27,7 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedResponse; import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; @@ -152,6 +153,22 @@ public void getItemWithResponse_withReturnConsumedCapacity_when_recordIsPresent_ assertThat(consumedCapacity.capacityUnits()).isCloseTo(25.0, Offset.offset(0.01)); } + @Test + public void getItem_withExtension_simpleAndWithResponse_shouldReturnSameData() { + DynamoDbEnhancedAsyncClient extensionClient = DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbAsyncTable extensionTable = extensionClient.table(getConcreteTableName(TEST_TABLE_NAME), TABLE_SCHEMA); + Record original = new Record().setId(777).setStringAttr1("abc"); + extensionTable.putItem(original).join(); + + Record getResult = extensionTable.getItem(r -> r.key(k -> k.partitionValue(777))).join(); + GetItemEnhancedResponse response = + extensionTable.getItemWithResponse(r -> r.key(k -> k.partitionValue(777))).join(); + assertThat(getResult).isEqualTo(response.attributes()); + } + private static String getStringAttrValue(int numChars) { char[] chars = new char[numChars]; Arrays.fill(chars, 'a'); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexQueryTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexQueryTest.java index 0a53549e6f62..b8f658493652 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexQueryTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexQueryTest.java @@ -17,7 +17,10 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; @@ -52,6 +55,7 @@ import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class AsyncIndexQueryTest extends LocalDynamoDbAsyncTestBase { private static class Record { @@ -230,6 +234,26 @@ public void queryBetween() { assertThat(page.lastEvaluatedKey(), is(nullValue())); } + @Test + public void queryBetween_withConsumedCapacity_shouldReturnIndexMetrics() { + insertRecords(); + Key fromKey = Key.builder().partitionValue("gsi-id-value").sortValue(3).build(); + Key toKey = Key.builder().partitionValue("gsi-id-value").sortValue(5).build(); + SdkPublisher> publisher = + keysOnlyMappedIndex.query(r -> r.queryConditional(QueryConditional.sortBetween(fromKey, toKey)) + .returnConsumedCapacity(ReturnConsumedCapacity.INDEXES)); + + Page page = drainPublisher(publisher, 1).get(0); + assertThat(page.items(), + is(KEYS_ONLY_RECORDS.stream().filter(r -> r.sort >= 3 && r.sort <= 5).collect(Collectors.toList()))); + assertThat(page.consumedCapacity(), is(notNullValue())); + assertThat(page.consumedCapacity().globalSecondaryIndexes(), is(notNullValue())); + assertThat(page.consumedCapacity().globalSecondaryIndexes().isEmpty(), is(false)); + assertThat(page.consumedCapacity().capacityUnits(), is(greaterThan(0d))); + assertThat(page.count(), equalTo(3)); + assertThat(page.scannedCount(), equalTo(3)); + } + @Test public void queryLimit() { insertRecords(); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexScanTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexScanTest.java index 9de11ea5c0fd..2c28f41595da 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexScanTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncIndexScanTest.java @@ -17,7 +17,9 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; @@ -50,6 +52,7 @@ import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; public class AsyncIndexScanTest extends LocalDynamoDbAsyncTestBase { private static class Record { @@ -208,6 +211,19 @@ public void scanAllRecordsDefaultSettings() { assertThat(page.lastEvaluatedKey(), is(nullValue())); } + @Test + public void scanAllRecords_withConsumedCapacity_shouldReturnIndexMetrics() { + insertRecords(); + SdkPublisher> publisher = + keysOnlyMappedIndex.scan(r -> r.returnConsumedCapacity(ReturnConsumedCapacity.INDEXES)); + Page page = drainPublisher(publisher, 1).get(0); + assertThat(page.items(), is(KEYS_ONLY_RECORDS)); + assertThat(page.consumedCapacity(), is(notNullValue())); + assertThat(page.consumedCapacity().globalSecondaryIndexes(), is(notNullValue())); + assertThat(page.count(), equalTo(10)); + assertThat(page.scannedCount(), equalTo(10)); + } + @Test public void scanAllRecordsWithFilter() { insertRecords(); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncPutItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncPutItemWithResponseTest.java index 275aea9106ed..e15688705941 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncPutItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncPutItemWithResponseTest.java @@ -16,15 +16,18 @@ package software.amazon.awssdk.enhanced.dynamodb.functionaltests; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; import java.util.Objects; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; -import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbExtensionContext; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; @@ -162,4 +165,30 @@ public void returnItemCollectionMetrics_unset_itemCollectionMetricsNull() { assertThat(response.consumedCapacity()).isNull(); } + + @Test + public void putItemWithResponse_returnAllOld_shouldInvokeExtensionOnReturnedValues() { + DynamoDbEnhancedClientExtension extension = Mockito.spy(new NoOpExtension()); + DynamoDbEnhancedAsyncClient extensionClient = DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(extension) + .build(); + DynamoDbAsyncTable extensionTable = + extensionClient.table(getConcreteTableName("table-name-extension"), TABLE_SCHEMA); + extensionTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + + Record original = new Record().setId(77).setStringAttr1("a"); + extensionTable.putItem(original).join(); + Record update = new Record().setId(77).setStringAttr1("b"); + extensionTable.putItemWithResponse(r -> r.returnValues(ReturnValue.ALL_OLD).item(update)).join(); + + Mockito.verify(extension, Mockito.times(1)).afterRead(any(DynamoDbExtensionContext.AfterRead.class)); + Mockito.verify(extension, Mockito.times(2)).beforeWrite(any(DynamoDbExtensionContext.BeforeWrite.class)); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("table-name-extension")) + .build()).join(); + } + + private static class NoOpExtension implements DynamoDbEnhancedClientExtension { + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactGetItemsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactGetItemsTest.java index 18c2466cddab..8f2b2407fb2c 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactGetItemsTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactGetItemsTest.java @@ -32,6 +32,7 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.TransactGetItemsEnhancedRequest; @@ -190,5 +191,34 @@ public void notFoundRecordReturnsNull() { assertThat(results.get(2).getItem(mappedTable2), is(nullValue())); assertThat(results.get(3).getItem(mappedTable1), is(RECORDS_1.get(1))); } + + @Test + public void transactGetRecords_withExtension_shouldPreserveAndReturnCorrectData() { + insertRecords(); + + DynamoDbEnhancedAsyncClient extensionClient = DefaultDynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbAsyncTable extensionMappedTable1 = + extensionClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); + DynamoDbAsyncTable extensionMappedTable2 = + extensionClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + + TransactGetItemsEnhancedRequest request = + TransactGetItemsEnhancedRequest.builder() + .addGetItem(extensionMappedTable1, Key.builder().partitionValue(0).build()) + .addGetItem(extensionMappedTable2, Key.builder().partitionValue(0).build()) + .addGetItem(extensionMappedTable2, Key.builder().partitionValue(1).build()) + .addGetItem(extensionMappedTable1, Key.builder().partitionValue(1).build()) + .build(); + + List results = extensionClient.transactGetItems(request).join(); + assertThat(results.size(), is(4)); + assertThat(results.get(0).getItem(extensionMappedTable1), is(RECORDS_1.get(0))); + assertThat(results.get(1).getItem(extensionMappedTable2), is(RECORDS_2.get(0))); + assertThat(results.get(2).getItem(extensionMappedTable2), is(RECORDS_2.get(1))); + assertThat(results.get(3).getItem(extensionMappedTable1), is(RECORDS_1.get(1))); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactWriteItemsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactWriteItemsTest.java index f2be7ca4cbc1..ba7d36edc659 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactWriteItemsTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncTransactWriteItemsTest.java @@ -25,7 +25,9 @@ import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletionException; import java.util.stream.Collectors; @@ -38,14 +40,23 @@ import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.TimestampedRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.client.DefaultDynamoDbEnhancedAsyncClient; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.ConditionCheck; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactDeleteItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactPutItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactUpdateItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.model.CancellationReason; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; public class AsyncTransactWriteItemsTest extends LocalDynamoDbAsyncTestBase { @@ -151,11 +162,20 @@ public int hashCode() { DefaultDynamoDbEnhancedAsyncClient.builder() .dynamoDbClient(getDynamoDbAsyncClient()) .build(); + private DynamoDbEnhancedAsyncClient extensionEnhancedAsyncClient = + DefaultDynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); private DynamoDbAsyncTable mappedTable1 = enhancedAsyncClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); private DynamoDbAsyncTable mappedTable2 = enhancedAsyncClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + private DynamoDbAsyncTable timestampedTable = + extensionEnhancedAsyncClient.table(getConcreteTableName("timestamped-table"), TimestampedRecord.TABLE_SCHEMA); + private DynamoDbAsyncTable> unsupportedCustomSchemaTable = + extensionEnhancedAsyncClient.table(getConcreteTableName("unsupported-schema-table"), new UnsupportedConverterTableSchema()); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -171,6 +191,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + timestampedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + unsupportedCustomSchemaTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); } @After @@ -181,6 +203,12 @@ public void deleteTable() { getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() .tableName(getConcreteTableName("table-name-2")) .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("timestamped-table")) + .build()).join(); + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("unsupported-schema-table")) + .build()).join(); } @Test @@ -429,5 +457,107 @@ public void mixedCommands_conditionCheckFailsTransaction() { assertThat(mappedTable2.getItem(r -> r.key(k -> k.partitionValue(0))).join(), is(RECORDS_2.get(0))); assertThat(mappedTable2.getItem(r -> r.key(k -> k.partitionValue(1))).join(), is(nullValue())); } + + @Test + public void transactWrite_withConditionCheckFailure_shouldReturnAllOldValues() { + mappedTable1.putItem(r -> r.item(RECORDS_1.get(0))).join(); + mappedTable1.putItem(r -> r.item(RECORDS_1.get(1))).join(); + mappedTable2.putItem(r -> r.item(RECORDS_2.get(0))).join(); + + Expression conditionExpression = Expression.builder() + .expression("#attribute = :attribute") + .expressionValues(singletonMap(":attribute", stringValue("99"))) + .expressionNames(singletonMap("#attribute", "attribute")) + .build(); + + Key key0 = Key.builder().partitionValue(0).build(); + Key key1 = Key.builder().partitionValue(1).build(); + ReturnValuesOnConditionCheckFailure returnValues = ReturnValuesOnConditionCheckFailure.ALL_OLD; + + TransactPutItemEnhancedRequest putItemRequest = TransactPutItemEnhancedRequest.builder(Record2.class) + .conditionExpression(conditionExpression) + .item(RECORDS_2.get(0)) + .returnValuesOnConditionCheckFailure(returnValues) + .build(); + TransactUpdateItemEnhancedRequest updateItemRequest = TransactUpdateItemEnhancedRequest.builder(Record1.class) + .conditionExpression(conditionExpression) + .item(RECORDS_1.get(0)) + .returnValuesOnConditionCheckFailure(returnValues) + .build(); + TransactDeleteItemEnhancedRequest deleteItemRequest = TransactDeleteItemEnhancedRequest.builder() + .key(key1) + .conditionExpression(conditionExpression) + .returnValuesOnConditionCheckFailure(returnValues) + .build(); + + TransactWriteItemsEnhancedRequest request = TransactWriteItemsEnhancedRequest.builder() + .addPutItem(mappedTable2, putItemRequest) + .addUpdateItem(mappedTable1, updateItemRequest) + .addConditionCheck(mappedTable1, ConditionCheck.builder() + .key(key0) + .conditionExpression(conditionExpression) + .returnValuesOnConditionCheckFailure(returnValues) + .build()) + .addDeleteItem(mappedTable1, deleteItemRequest) + .build(); + + try { + enhancedAsyncClient.transactWriteItems(request).join(); + fail("Expected CompletionException to be thrown"); + } catch (CompletionException e) { + assertThat(e.getCause(), instanceOf(TransactionCanceledException.class)); + List reasons = ((TransactionCanceledException) e.getCause()).cancellationReasons(); + assertThat(reasons.size(), is(4)); + reasons.forEach(r -> assertThat(r.item().isEmpty(), is(false))); + } + } + + @Test + public void transactWrite_withSupportedAndUnsupportedSchema_shouldPreserveValues() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(singletonMap("inner", AttributeValue.builder().s("value").build())).build()); + + extensionEnhancedAsyncClient.transactWriteItems( + TransactWriteItemsEnhancedRequest.builder() + .addPutItem(timestampedTable, new TimestampedRecord().setId("ts-1")) + .addPutItem(unsupportedCustomSchemaTable, customItem) + .build()).join(); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))).join(); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))).join(); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } + + @Test + public void transactWriteWithResponse_withSupportedAndUnsupportedSchema_shouldReturnMetrics() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(singletonMap("inner", AttributeValue.builder().s("value").build())).build()); + + TransactWriteItemsEnhancedResponse response = extensionEnhancedAsyncClient.transactWriteItemsWithResponse( + TransactWriteItemsEnhancedRequest.builder() + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .addPutItem(timestampedTable, new TimestampedRecord().setId("ts-1")) + .addPutItem(unsupportedCustomSchemaTable, customItem) + .build()).join(); + + assertThat(response.consumedCapacity(), is(notNullValue())); + assertThat(response.consumedCapacity().size(), is(2)); + assertThat(response.itemCollectionMetrics(), is(notNullValue())); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))).join(); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))).join(); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateBehaviorTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateBehaviorTest.java new file mode 100644 index 000000000000..dc0056d11056 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateBehaviorTest.java @@ -0,0 +1,81 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Instant; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecordWithUpdateBehaviors; +import software.amazon.awssdk.enhanced.dynamodb.internal.client.ExtensionResolver; + +public class AsyncUpdateBehaviorTest extends LocalDynamoDbAsyncTestBase { + private static final Instant INSTANT_1 = Instant.parse("2020-05-03T10:00:00Z"); + private static final Instant INSTANT_2 = Instant.parse("2020-05-03T10:05:00Z"); + + private static final TableSchema TABLE_SCHEMA = + TableSchema.fromClass(RecordWithUpdateBehaviors.class); + + private final DynamoDbEnhancedAsyncClient enhancedAsyncClient = DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(Stream.concat( + ExtensionResolver.defaultExtensions().stream(), + Stream.of(AutoGeneratedTimestampRecordExtension.create())) + .collect(Collectors.toList())) + .build(); + + private final DynamoDbAsyncTable mappedTable = + enhancedAsyncClient.table(getConcreteTableName("table-name"), TABLE_SCHEMA); + + @Before + public void createTable() { + mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void deleteTable() { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("table-name"))).join(); + } + + @Test + public void updateItem_withWriteIfNotExistsBehavior_shouldPreserveOnSecondUpdateAndIncrementVersion() { + RecordWithUpdateBehaviors seed = new RecordWithUpdateBehaviors(); + seed.setId("id1"); + seed.setCreatedOn(INSTANT_1); + seed.setLastUpdatedOn(INSTANT_1); + mappedTable.updateItem(seed).join(); + + RecordWithUpdateBehaviors update = new RecordWithUpdateBehaviors(); + update.setId("id1"); + update.setVersion(1L); + update.setCreatedOn(INSTANT_2); + update.setLastUpdatedOn(INSTANT_2); + mappedTable.updateItem(update).join(); + + RecordWithUpdateBehaviors persisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + assertThat(persisted.getVersion()).isEqualTo(2L); + assertThat(persisted.getCreatedOn()).as("WRITE_IF_NOT_EXISTS should preserve created time").isEqualTo(INSTANT_1); + assertThat(persisted.getLastUpdatedOn()).isEqualTo(INSTANT_2); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateExpressionTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateExpressionTest.java new file mode 100644 index 000000000000..5e244dd4fb2f --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncUpdateExpressionTest.java @@ -0,0 +1,72 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.RecordForUpdateExpressions; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +public class AsyncUpdateExpressionTest extends LocalDynamoDbAsyncTestBase { + private static final TableSchema TABLE_SCHEMA = + TableSchema.fromClass(RecordForUpdateExpressions.class); + + private final DynamoDbEnhancedAsyncClient enhancedAsyncClient = + DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + + private final DynamoDbAsyncTable mappedTable = + enhancedAsyncClient.table(getConcreteTableName("table-name"), TABLE_SCHEMA); + + @Before + public void createTable() { + mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void deleteTable() { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("table-name"))).join(); + } + + @Test + public void updateItem_withConditionExpression_shouldNotApplyUpdateWhenConditionMatches() { + RecordForUpdateExpressions seed = new RecordForUpdateExpressions(); + seed.setId("id1"); + seed.setStringAttribute("init"); + mappedTable.putItem(seed).join(); + + RecordForUpdateExpressions update = new RecordForUpdateExpressions(); + update.setId("id1"); + update.setStringAttribute("changed"); + mappedTable.updateItem(r -> r.item(update) + .conditionExpression(Expression.builder() + .expression("id = :id") + .expressionValues(Collections.singletonMap(":id", + AttributeValue.builder().s("id1").build())) + .build())) + .join(); + + RecordForUpdateExpressions persisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + assertThat(persisted.getStringAttribute()).isEqualTo("init"); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncVersionedRecordTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncVersionedRecordTest.java new file mode 100644 index 000000000000..170637f1bca5 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AsyncVersionedRecordTest.java @@ -0,0 +1,93 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.extensions.VersionedRecordExtension.AttributeTags.versionAttribute; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.VersionedRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; + +public class AsyncVersionedRecordTest extends LocalDynamoDbAsyncTestBase { + private static class Record { + private String id; + private String attribute; + private Integer version; + public String getId() { return id; } + public void setId(String id) { this.id = id; } + public String getAttribute() { return attribute; } + public void setAttribute(String attribute) { this.attribute = attribute; } + public Integer getVersion() { return version; } + public void setVersion(Integer version) { this.version = version; } + } + + private static final TableSchema TABLE_SCHEMA = + StaticTableSchema.builder(Record.class) + .newItemSupplier(Record::new) + .addAttribute(String.class, a -> a.name("id").getter(Record::getId).setter(Record::setId) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("attribute").getter(Record::getAttribute) + .setter(Record::setAttribute)) + .addAttribute(Integer.class, a -> a.name("version").getter(Record::getVersion) + .setter(Record::setVersion).tags(versionAttribute())) + .build(); + + private final DynamoDbEnhancedAsyncClient enhancedAsyncClient = + DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(VersionedRecordExtension.builder().build()) + .build(); + + private final DynamoDbAsyncTable mappedTable = enhancedAsyncClient.table(getConcreteTableName("table-name"), + TABLE_SCHEMA); + + @Before + public void createTable() { + mappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void deleteTable() { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(getConcreteTableName("table-name"))).join(); + } + + @Test + public void transactWrite_updateVersionedRecord_shouldIncrementVersion() { + Record record = new Record(); + record.setId("id1"); + record.setAttribute("v1"); + mappedTable.updateItem(record).join(); + Record persistedAfterFirstUpdate = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + assertThat(persistedAfterFirstUpdate.getVersion()).isEqualTo(1); + + Record update = new Record(); + update.setId("id1"); + update.setAttribute("v2"); + update.setVersion(1); + enhancedAsyncClient.transactWriteItems(r -> r.addUpdateItem(mappedTable, update)).join(); + + Record persisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id1"))).join(); + assertThat(persisted.getVersion()).isEqualTo(persistedAfterFirstUpdate.getVersion() + 1); + assertThat(persisted.getAttribute()).isEqualTo("v2"); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AtomicCounterTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AtomicCounterTest.java index 2c54717600a6..dfd905250681 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AtomicCounterTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AtomicCounterTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.enhanced.dynamodb.functionaltests; import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import java.util.List; import java.util.stream.IntStream; @@ -26,10 +27,12 @@ import org.slf4j.event.Level; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.LogCaptor; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.extensions.AtomicCounterExtension; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AtomicCounterRecord; +import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; public class AtomicCounterTest extends LocalDynamoDbSyncTestBase { @@ -217,4 +220,35 @@ public void updateItem_withAtomicCounters_logsFilteredAttributes() { assertThat(logEventMessage.split(",")).hasSize(3); } } + + @Test + public void updateItem_withConditionExpression_shouldIncrementCountersAndPreserveAttribute() { + AtomicCounterRecord record = new AtomicCounterRecord(); + record.setId(RECORD_ID); + record.setAttribute1("initial"); + mappedTable.putItem(record); + + Expression expression = Expression.builder() + .expression("#a = :v") + .putExpressionName("#a", "attribute1") + .putExpressionValue(":v", stringValue("initial")) + .build(); + AtomicCounterRecord update = new AtomicCounterRecord(); + update.setId(RECORD_ID); + update.setAttribute1("updated"); + + mappedTable.updateItem(UpdateItemEnhancedRequest.builder(AtomicCounterRecord.class) + .item(update) + .conditionExpression(expression) + .build()); + + AtomicCounterRecord persisted = mappedTable.getItem(update); + assertThat(persisted.getAttribute1()).isEqualTo("updated"); + // AtomicCounterRecord annotations: defaultCounter (delta=1, start=0), customCounter (delta=5, start=10), + // decreasingCounter (delta=-1, start=-20). putItem initializes counters to start values; the following + // updateItem adds one delta: 0+1=1, 10+5=15, -20-1=-21. + assertThat(persisted.getDefaultCounter()).isEqualTo(1L); + assertThat(persisted.getCustomCounter()).isEqualTo(15L); + assertThat(persisted.getDecreasingCounter()).isEqualTo(-21L); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampConvertedByListTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampConvertedByListTest.java new file mode 100644 index 000000000000..63af1e6e372e --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampConvertedByListTest.java @@ -0,0 +1,167 @@ +/* + * 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.enhanced.dynamodb.functionaltests; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +import java.time.Clock; +import java.time.Instant; +import java.util.Arrays; +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.BeanWithCustomConvertedList; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.CustomConvertedPojo; +import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; + +/** + * Sync functional coverage for {@code @DynamoDbConvertedBy} list attributes used with + * {@link AutoGeneratedTimestampRecordExtension}. Mirrors + * {@link AsyncAutoGeneratedTimestampConvertedByListTest}. + */ +public class AutoGeneratedTimestampConvertedByListTest extends LocalDynamoDbSyncTestBase { + private static final Instant MOCKED_INSTANT_NOW = Instant.parse("2019-01-13T14:00:00Z"); + + private DynamoDbEnhancedClient extensionEnhancedClient; + private DynamoDbTable table; + private String tableName; + + private final TableSchema tableSchema = + BeanTableSchema.create(BeanWithCustomConvertedList.class); + + private Clock mockClock; + + @Before + public void setUp() { + mockClock = Mockito.mock(Clock.class); + Mockito.when(mockClock.instant()).thenReturn(MOCKED_INSTANT_NOW); + + extensionEnhancedClient = + DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.builder() + .baseClock(mockClock) + .build()) + .build(); + + tableName = getConcreteTableName("converted-by-list-extension-sync-test-table"); + table = extensionEnhancedClient.table(tableName, tableSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + } + + @After + public void tearDown() { + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(tableName) + .build()); + } + + @Test + public void putThenUpdateItem_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList initial = new BeanWithCustomConvertedList() + .setId("id1") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + table.putItem(r -> r.item(initial)); + + List updatedCustomItems = Arrays.asList( + new CustomConvertedPojo("c", 3), + new CustomConvertedPojo("d", 4)); + + BeanWithCustomConvertedList updated = new BeanWithCustomConvertedList() + .setId("id1") + .setCustomItems(updatedCustomItems); + + table.updateItem(r -> r.item(updated)); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id1"))); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), updatedCustomItems); + } + + @Test + public void batchWriteItem_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("id2") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + WriteBatch writeBatch = WriteBatch.builder(BeanWithCustomConvertedList.class) + .mappedTableResource(table) + .addPutItem(r -> r.item(record)) + .build(); + + extensionEnhancedClient.batchWriteItem( + BatchWriteItemEnhancedRequest.builder() + .writeBatches(Arrays.asList(writeBatch)) + .build()); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id2"))); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), record.getCustomItems()); + } + + @Test + public void transactWriteItems_customConvertedByList_doesNotThrow_setsTimestampAndPreservesCustomItems() { + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("id3") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + extensionEnhancedClient.transactWriteItems( + TransactWriteItemsEnhancedRequest.builder() + .addPutItem(table, record) + .build()); + + BeanWithCustomConvertedList result = + table.getItem(r -> r.key(k -> k.partitionValue("id3"))); + + assertThat(result, is(notNullValue())); + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertCustomItems(result.getCustomItems(), record.getCustomItems()); + } + + private static void assertCustomItems(List actual, + List expected) { + assertThat(actual.size(), is(expected.size())); + for (int i = 0; i < expected.size(); i++) { + assertThat(actual.get(i).getLabel(), is(expected.get(i).getLabel())); + assertThat(actual.get(i).getCount(), is(expected.get(i).getCount())); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampExtensionTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampExtensionTest.java index 52a14dbf65a6..cf687f1ace36 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampExtensionTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedTimestampExtensionTest.java @@ -91,8 +91,10 @@ import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.SimpleImmutableRecordWithMap; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.SimpleImmutableRecordWithSet; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.AutogeneratedTimestampTestModels.SimpleStaticRecordWithList; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.BeanTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticImmutableTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.UpdateBehavior; import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest; @@ -1471,6 +1473,72 @@ public void beforeWrite_listWithCustomConverter_whenElementTypeNotAnnotated_then assertThat(transformed.get("customItems"), is(originalList)); } + @Test + public void beforeWrite_listWithCustomConverter_whenElementTypeNotAnnotated_updateItem_thenTimestampSetAndListUnchanged() { + String expectedWrittenInstant = MOCKED_INSTANT_NOW.toString(); + TableSchema schema = BeanTableSchema.create(BeanWithCustomConvertedList.class); + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("1") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + Map updateItem = new HashMap<>(schema.itemToMap(record, false)); + AttributeValue originalList = updateItem.get("customItems"); + + WriteModification modification = + invokeBeforeWriteForOperation(updateItem, schema.tableMetadata(), schema, OperationName.UPDATE_ITEM); + Map transformed = modification.transformedItem(); + + assertThat(transformed, is(notNullValue())); + assertThat(transformed.get("time").s(), is(expectedWrittenInstant)); + assertThat(transformed.get("customItems"), is(originalList)); + } + + @Test + public void beforeWrite_listWithCustomConverter_whenElementTypeNotAnnotated_batchWriteItem_thenTimestampSetAndListUnchanged() { + String expectedWrittenInstant = MOCKED_INSTANT_NOW.toString(); + TableSchema schema = BeanTableSchema.create(BeanWithCustomConvertedList.class); + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("1") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + Map item = new HashMap<>(schema.itemToMap(record, false)); + AttributeValue originalList = item.get("customItems"); + + WriteModification modification = + invokeBeforeWriteForOperation(item, schema.tableMetadata(), schema, OperationName.BATCH_WRITE_ITEM); + Map transformed = modification.transformedItem(); + + assertThat(transformed, is(notNullValue())); + assertThat(transformed.get("time").s(), is(expectedWrittenInstant)); + assertThat(transformed.get("customItems"), is(originalList)); + } + + @Test + public void beforeWrite_listWithCustomConverter_whenElementTypeNotAnnotated_transactWriteItems_thenTimestampSetAndListUnchanged() { + String expectedWrittenInstant = MOCKED_INSTANT_NOW.toString(); + TableSchema schema = BeanTableSchema.create(BeanWithCustomConvertedList.class); + BeanWithCustomConvertedList record = new BeanWithCustomConvertedList() + .setId("1") + .setCustomItems(Arrays.asList( + new CustomConvertedPojo("a", 1), + new CustomConvertedPojo("b", 2))); + + Map item = new HashMap<>(schema.itemToMap(record, false)); + AttributeValue originalList = item.get("customItems"); + + WriteModification modification = + invokeBeforeWriteForOperation(item, schema.tableMetadata(), schema, OperationName.TRANSACT_WRITE_ITEMS); + Map transformed = modification.transformedItem(); + + assertThat(transformed, is(notNullValue())); + assertThat(transformed.get("time").s(), is(expectedWrittenInstant)); + assertThat(transformed.get("customItems"), is(originalList)); + } + @Test public void beforeWrite_mapWithCustomConverter_whenValueTypeNotAnnotated_thenTimestampSetAndMapUnchanged() { String expectedWrittenInstant = MOCKED_INSTANT_NOW.toString(); @@ -1564,6 +1632,281 @@ public void beforeWrite_customTableSchemaWithoutConverterForAttribute_doesNotThr assertThat(modification.transformedItem(), is(nullValue())); } + @Test + public void putItem_withUnsupportedCustomSchemaAndExtensionEnabled_writesWithoutTransformingNestedData() { + TableSchema> schema = new UnsupportedConverterTableSchema(); + DynamoDbTable> customTable = + enhancedClient.table(getConcreteTableName("custom-schema-table"), schema); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Map nestedMap = new HashMap<>(); + nestedMap.put("city", AttributeValue.builder().s("Seattle").build()); + nestedMap.put("country", AttributeValue.builder().s("US").build()); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-1").build()); + item.put("location", AttributeValue.builder().m(nestedMap).build()); + + customTable.putItem(item); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + assertThat(persisted.get("location").m(), is(nestedMap)); + customTable.deleteTable(); + } + + @Test + public void updateItem_withUnsupportedCustomSchemaAndNestedList_writesWithoutThrowing() { + TableSchema> schema = new UnsupportedConverterTableSchema(); + DynamoDbTable> customTable = + enhancedClient.table(getConcreteTableName("custom-schema-table"), schema); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Map nestedMap = new HashMap<>(); + nestedMap.put("child", AttributeValue.builder().s("one").build()); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-2").build()); + item.put("records", AttributeValue.builder() + .l(Arrays.asList(AttributeValue.builder().m(nestedMap).build(), + AttributeValue.builder().s("literal").build())) + .build()); + + customTable.updateItem(item); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-2"))); + assertThat(persisted.get("records").l().get(0).m(), is(nestedMap)); + assertThat(persisted.get("records").l().get(1).s(), is("literal")); + customTable.deleteTable(); + } + + /** + * Covers {@code applyAutoGeneratedTimestampsToMap}'s handling of nested schemas that throw + * {@link UnsupportedOperationException} from {@code converterForAttribute}. Wrapping only the nested schema (not the root) + * is required: when the root cannot resolve converters, nested schema lookup returns empty and this path is never reached. + */ + @Test + public void beforeWrite_nestedSchemaWithoutConverterForAttribute_doesNotThrow_nestedTimestampsSkipped() { + TableSchema supportedNestedSchema = + StaticImmutableTableSchema.builder(NestedImmutableChildRecordWithList.class, + NestedImmutableChildRecordWithList.Builder.class) + .newItemBuilder(NestedImmutableChildRecordWithList::builder, + NestedImmutableChildRecordWithList.Builder::build) + .addAttribute(Instant.class, a -> a.name("time") + .getter(NestedImmutableChildRecordWithList::getTime) + .setter(NestedImmutableChildRecordWithList.Builder::time) + .tags(autoGeneratedTimestampAttribute())) + .build(); + TableSchema unsupportedNestedSchema = + new DelegatingTableSchemaWithoutConverterForAttribute<>(supportedNestedSchema); + + TableSchema rootSchema = + StaticImmutableTableSchema.builder(NestedImmutableRecordWithList.class, + NestedImmutableRecordWithList.Builder.class) + .newItemBuilder(NestedImmutableRecordWithList::builder, + NestedImmutableRecordWithList.Builder::build) + .addAttribute(String.class, a -> a.name("id") + .getter(NestedImmutableRecordWithList::getId) + .setter(NestedImmutableRecordWithList.Builder::id) + .tags(primaryPartitionKey())) + .addAttribute(EnhancedType.documentOf(NestedImmutableChildRecordWithList.class, + unsupportedNestedSchema), + a -> a.name("level2") + .getter(NestedImmutableRecordWithList::getLevel2) + .setter(NestedImmutableRecordWithList.Builder::level2)) + .build(); + + Map nestedMap = new HashMap<>(); + nestedMap.put("time", AttributeValue.builder().s(MOCKED_INSTANT_UPDATE_TWO.toString()).build()); + + Map itemMap = new HashMap<>(); + itemMap.put("id", AttributeValue.builder().s("1").build()); + itemMap.put("level2", AttributeValue.builder().m(nestedMap).build()); + + WriteModification modification = invokeBeforeWriteForPutItem(itemMap, rootSchema); + + // Nested timestamp insertion is skipped when the nested schema cannot resolve converters. + assertThat(modification.transformedItem(), is(nullValue())); + } + + @Test + public void putItem_withoutConverterForAttribute_doesNotThrow_nestedTimestampsSkipped() { + TableSchema supportedSchema = + buildStaticImmutableSchemaForNestedRecordWithList(); + TableSchema unsupportedConverterSchema = + new DelegatingTableSchemaWithoutConverterForAttribute<>(supportedSchema); + + DynamoDbTable table = + enhancedClient.table(getConcreteTableName("unsupported-converter-table"), unsupportedConverterSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Instant rootTimeBefore = MOCKED_INSTANT_UPDATE_ONE; + Instant nestedTimeBefore = MOCKED_INSTANT_UPDATE_TWO; + + NestedImmutableRecordWithList item = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore).build()) + .build(); + + table.putItem(r -> r.item(item)); + + NestedImmutableRecordWithList result = table.getItem(r -> r.key(k -> k.partitionValue("1"))); + + // When converterForAttribute cannot be resolved, the extension skips timestamp insertion. + assertThat(result.getTime(), is(rootTimeBefore)); + assertThat(result.getLevel2().getTime(), is(nestedTimeBefore)); + + table.deleteTable(); + } + + @Test + public void updateItem_withoutConverterForAttribute_doesNotThrow_nestedTimestampsSkipped() { + TableSchema supportedSchema = + buildStaticImmutableSchemaForNestedRecordWithList(); + TableSchema unsupportedConverterSchema = + new DelegatingTableSchemaWithoutConverterForAttribute<>(supportedSchema); + + DynamoDbTable table = + enhancedClient.table(getConcreteTableName("unsupported-converter-table"), unsupportedConverterSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Instant rootTimeBefore = MOCKED_INSTANT_UPDATE_ONE; + Instant nestedTimeBefore = MOCKED_INSTANT_UPDATE_TWO; + + NestedImmutableRecordWithList initial = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore).build()) + .build(); + + table.putItem(r -> r.item(initial)); + + NestedImmutableRecordWithList update = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore).build()) + .build(); + + table.updateItem(r -> r.item(update)); + + NestedImmutableRecordWithList result = table.getItem(r -> r.key(k -> k.partitionValue("1"))); + + assertThat(result.getTime(), is(rootTimeBefore)); + assertThat(result.getLevel2().getTime(), is(nestedTimeBefore)); + + table.deleteTable(); + } + + @Test + public void putItem_converterForAttributeReturnsNull_doesNotThrow_nestedTimestampsSkipped() { + TableSchema supportedSchema = + buildStaticImmutableSchemaForNestedRecordWithList(); + TableSchema nullConverterSchema = + new DelegatingTableSchemaWithNullConverterForAttribute<>(supportedSchema); + + DynamoDbTable table = + enhancedClient.table(getConcreteTableName("null-converter-table"), nullConverterSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Instant rootTimeBefore = MOCKED_INSTANT_UPDATE_ONE; + Instant nestedTimeBefore = MOCKED_INSTANT_UPDATE_TWO; + + NestedImmutableRecordWithList item = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore).build()) + .build(); + + table.putItem(r -> r.item(item)); + + NestedImmutableRecordWithList result = table.getItem(r -> r.key(k -> k.partitionValue("1"))); + + assertThat(result.getTime(), is(rootTimeBefore)); + assertThat(result.getLevel2().getTime(), is(nestedTimeBefore)); + + table.deleteTable(); + } + + @Test + public void sharedClient_cacheIsolation_afterUnsupportedConverterForAttribute_thenSupportedSchemaAppliesNestedTimestamps() { + TableSchema supportedSchema = + buildStaticImmutableSchemaForNestedRecordWithList(); + TableSchema unsupportedConverterSchema = + new DelegatingTableSchemaWithoutConverterForAttribute<>(supportedSchema); + + String tableName = getConcreteTableName("cache-isolation-table"); + + DynamoDbTable unsupportedTable = + enhancedClient.table(tableName, unsupportedConverterSchema); + unsupportedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Instant rootTimeBefore = MOCKED_INSTANT_UPDATE_ONE; + Instant nestedTimeBefore = MOCKED_INSTANT_UPDATE_TWO; + + NestedImmutableRecordWithList unsupportedItem = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore).build()) + .build(); + + unsupportedTable.putItem(r -> r.item(unsupportedItem)); + + DynamoDbTable supportedTable = + enhancedClient.table(tableName, supportedSchema); + + // Second operation should apply nested timestamps even after a previous operation failed to resolve converters. + Instant nestedTimeBefore2 = MOCKED_INSTANT_UPDATE_ONE; + NestedImmutableRecordWithList supportedItem = NestedImmutableRecordWithList + .builder() + .id("1") + .time(rootTimeBefore) + .level2(NestedImmutableChildRecordWithList.builder().time(nestedTimeBefore2).build()) + .build(); + + supportedTable.putItem(r -> r.item(supportedItem)); + + NestedImmutableRecordWithList result = supportedTable.getItem(r -> r.key(k -> k.partitionValue("1"))); + + assertThat(result.getTime(), is(MOCKED_INSTANT_NOW)); + assertThat(result.getLevel2().getTime(), is(MOCKED_INSTANT_NOW)); + + unsupportedTable.deleteTable(); + } + + @Test + public void deleteItem_withoutConverterForAttribute_doesNotThrow() { + TableSchema supportedSchema = + buildStaticImmutableSchemaForNestedRecordWithList(); + TableSchema unsupportedConverterSchema = + new DelegatingTableSchemaWithoutConverterForAttribute<>(supportedSchema); + + String tableName = getConcreteTableName("delete-unsupported-converter-table"); + + DynamoDbTable table = + enhancedClient.table(tableName, unsupportedConverterSchema); + table.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + NestedImmutableRecordWithList item = NestedImmutableRecordWithList + .builder() + .id("1") + .time(MOCKED_INSTANT_UPDATE_ONE) + .level2(NestedImmutableChildRecordWithList.builder().time(MOCKED_INSTANT_UPDATE_TWO).build()) + .build(); + + table.putItem(r -> r.item(item)); + + table.deleteItem(r -> r.key(k -> k.partitionValue("1"))); + + assertThat(table.getItem(r -> r.key(k -> k.partitionValue("1"))), is(nullValue())); + + table.deleteTable(); + } + private WriteModification invokeBeforeWriteForPutItem(Map itemAttributes, TableSchema tableSchema) { return invokeBeforeWriteForPutItem(itemAttributes, tableSchema.tableMetadata(), tableSchema); @@ -1572,12 +1915,19 @@ private WriteModification invokeBeforeWriteForPutItem(Map itemAttributes, TableMetadata tableMetadata, TableSchema tableSchema) { + return invokeBeforeWriteForOperation(itemAttributes, tableMetadata, tableSchema, OperationName.PUT_ITEM); + } + + private WriteModification invokeBeforeWriteForOperation(Map itemAttributes, + TableMetadata tableMetadata, + TableSchema tableSchema, + OperationName operationName) { return standaloneExtension.beforeWrite( DefaultDynamoDbExtensionContext.builder() .items(itemAttributes) .tableMetadata(tableMetadata) .tableSchema(tableSchema) - .operationName(OperationName.PUT_ITEM) + .operationName(operationName) .operationContext(EXTENSION_DIRECT_TEST_OPERATION_CONTEXT) .build()); } @@ -2521,4 +2871,67 @@ public boolean isAbstract() { // converterForAttribute is intentionally NOT overridden. } + + private static class DelegatingTableSchemaWithoutConverterForAttribute implements TableSchema { + private final TableSchema delegate; + + private DelegatingTableSchemaWithoutConverterForAttribute(TableSchema delegate) { + this.delegate = delegate; + } + + @Override + public T mapToItem(Map attributeMap) { + return delegate.mapToItem(attributeMap); + } + + @Override + public Map itemToMap(T item, boolean ignoreNulls) { + return delegate.itemToMap(item, ignoreNulls); + } + + @Override + public Map itemToMap(T item, java.util.Collection attributes) { + return delegate.itemToMap(item, attributes); + } + + @Override + public AttributeValue attributeValue(T item, String attributeName) { + return delegate.attributeValue(item, attributeName); + } + + @Override + public TableMetadata tableMetadata() { + return delegate.tableMetadata(); + } + + @Override + public EnhancedType itemType() { + return delegate.itemType(); + } + + @Override + public List attributeNames() { + return delegate.attributeNames(); + } + + @Override + public boolean isAbstract() { + return delegate.isAbstract(); + } + + // converterForAttribute is intentionally NOT overridden, so the TableSchema default implementation + // throws UnsupportedOperationException. + } + + private static final class DelegatingTableSchemaWithNullConverterForAttribute + extends DelegatingTableSchemaWithoutConverterForAttribute { + private DelegatingTableSchemaWithNullConverterForAttribute(TableSchema delegate) { + super(delegate); + } + + @Override + public AttributeConverter converterForAttribute(Object key) { + return null; + } + } } \ No newline at end of file diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java index e59ea214399b..a6c207e1be0e 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/AutoGeneratedUuidRecordTest.java @@ -314,6 +314,28 @@ public void updateItemConditionTestFailure() { } + @Test + public void putOverwrite_withExplicitUuidValues_shouldRegenerateAllUuidsAffectedByBehavior() { + mappedTable.putItem(r -> r.item(new Record().id("overwrite-id").attribute("one"))); + Record first = mappedTable.getItem(r -> r.key(k -> k.partitionValue("overwrite-id"))); + + Record overwrite = new Record().id("overwrite-id") + .attribute("two") + .createdUuid("00000000-0000-0000-0000-000000000000") + .lastUpdatedUuid("00000000-0000-0000-0000-000000000001") + .flattenedRecord(new FlattenedRecord().generated("00000000-0000-0000-0000-000000000002")); + mappedTable.putItem(overwrite); + + Record second = mappedTable.getItem(r -> r.key(k -> k.partitionValue("overwrite-id"))); + assertRecordHasValidUuid(second); + Assertions.assertThat(second.getCreatedUuid()).isNotEqualTo(overwrite.getCreatedUuid()); + Assertions.assertThat(second.getLastUpdatedUuid()).isNotEqualTo(overwrite.getLastUpdatedUuid()); + Assertions.assertThat(second.getFlattenedRecord().getGenerated()) + .isNotEqualTo(overwrite.getFlattenedRecord().getGenerated()); + Assertions.assertThat(second.getCreatedUuid()).isNotEqualTo(first.getCreatedUuid()); + Assertions.assertThat(second.getAttribute()).isEqualTo("two"); + } + public static Record createUniqueFakeItem() { Record record = new Record(); record.setId(UUID.randomUUID().toString()); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BasicCrudTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BasicCrudTest.java index 8d59158b2931..84bd0b6e1b6f 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BasicCrudTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BasicCrudTest.java @@ -17,6 +17,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; @@ -25,6 +26,8 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondarySortKey; import java.util.Objects; +import java.util.HashMap; +import java.util.Map; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -35,12 +38,15 @@ import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.DeleteItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedGlobalSecondaryIndex; import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ProjectionType; @@ -656,4 +662,29 @@ public void getAShortRecordWithNewModelledFields() { Record result = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id-value").sortValue("sort-value"))); assertThat(result, is(expectedRecord)); } + + @Test + public void putAndUpdate_withUnsupportedCustomSchema_shouldSucceedWithoutException() { + DynamoDbEnhancedClient extensionClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbTable> customTable = + extensionClient.table(getConcreteTableName("crud-custom-table"), new UnsupportedConverterTableSchema()); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-1").build()); + item.put("nested", + AttributeValue.builder() + .m(java.util.Collections.singletonMap("k", AttributeValue.builder().s("v").build())) + .build()); + + customTable.putItem(item); + customTable.updateItem(item); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + assertThat(persisted, is(notNullValue())); + getDynamoDbClient().deleteTable(r -> r.tableName(getConcreteTableName("crud-custom-table"))); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchGetItemTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchGetItemTest.java index 6eb92c2d4409..1186ea45c683 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchGetItemTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchGetItemTest.java @@ -26,6 +26,9 @@ import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -41,8 +44,44 @@ import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; public class BatchGetItemTest extends LocalDynamoDbSyncTestBase { + @DynamoDbBean + public static class BeanRecord { + private Integer id; + private String value; + + @DynamoDbPartitionKey + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + public String getValue() { return value; } + public void setValue(String value) { this.value = value; } + } + + @DynamoDbImmutable(builder = ImmutableRecord.Builder.class) + public static final class ImmutableRecord { + private final Integer id; + private final String value; + + private ImmutableRecord(Builder builder) { + this.id = builder.id; + this.value = builder.value; + } + + @DynamoDbPartitionKey + public Integer id() { return id; } + public String value() { return value; } + + public static Builder builder() { return new Builder(); } + public static final class Builder { + private Integer id; + private String value; + public Builder id(Integer id) { this.id = id; return this; } + public Builder value(String value) { this.value = value; return this; } + public ImmutableRecord build() { return new ImmutableRecord(this); } + } + } private static class Record1 { private Integer id; private String stringAttr; @@ -147,6 +186,10 @@ public int hashCode() { private final String tableName2 = getConcreteTableName("table-name-2"); private final DynamoDbTable mappedTable1 = enhancedClient.table(tableName1, TABLE_SCHEMA_1); private final DynamoDbTable mappedTable2 = enhancedClient.table(tableName2, TABLE_SCHEMA_2); + private final DynamoDbTable mappedBeanTable = + enhancedClient.table(getConcreteTableName("table-name-bean"), TableSchema.fromBean(BeanRecord.class)); + private final DynamoDbTable mappedImmutableTable = + enhancedClient.table(getConcreteTableName("table-name-immutable"), TableSchema.fromImmutableClass(ImmutableRecord.class)); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -162,6 +205,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + mappedBeanTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + mappedImmutableTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); } @After @@ -172,6 +217,12 @@ public void deleteTable() { getDynamoDbClient().deleteTable(DeleteTableRequest.builder() .tableName(tableName2) .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("table-name-bean")) + .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("table-name-immutable")) + .build()); } private void insertRecords() { @@ -290,6 +341,72 @@ public void notFoundRecordIgnored_withReturnConsumedCapacity() { }); } + @Test + public void batchGetRecords_withExtension_shouldPreserveAndReturnCorrectData() { + insertRecords(); + + DynamoDbEnhancedClient extensionClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + + DynamoDbTable extensionMappedTable1 = extensionClient.table(tableName1, TABLE_SCHEMA_1); + DynamoDbTable extensionMappedTable2 = extensionClient.table(tableName2, TABLE_SCHEMA_2); + + BatchGetItemEnhancedRequest request = BatchGetItemEnhancedRequest.builder() + .readBatches( + ReadBatch.builder(Record1.class) + .mappedTableResource(extensionMappedTable1) + .addGetItem(i -> i.key(k -> k.partitionValue(0))) + .build(), + ReadBatch.builder(Record2.class) + .mappedTableResource(extensionMappedTable2) + .addGetItem(i -> i.key(k -> k.partitionValue(0))) + .build(), + ReadBatch.builder(Record2.class) + .mappedTableResource(extensionMappedTable2) + .addGetItem(i -> i.key(k -> k.partitionValue(1))) + .build(), + ReadBatch.builder(Record1.class) + .mappedTableResource(extensionMappedTable1) + .addGetItem(i -> i.key(k -> k.partitionValue(1))) + .build()) + .build(); + + SdkIterable results = extensionClient.batchGetItem(request); + + assertThat(results.stream().count(), is(1L)); + results.iterator().forEachRemaining(page -> { + List table1Results = page.resultsForTable(extensionMappedTable1); + assertThat(table1Results, containsInAnyOrder(RECORDS_1.toArray())); + + List table2Results = page.resultsForTable(extensionMappedTable2); + assertThat(table2Results, containsInAnyOrder(RECORDS_2.toArray())); + }); + } + + @Test + public void batchGetRecords_fromMixedSchemaTypes_shouldReturnCorrectlyCastItems() { + insertRecords(); + BeanRecord beanRecord = new BeanRecord(); + beanRecord.setId(10); + beanRecord.setValue("bean"); + mappedBeanTable.putItem(beanRecord); + ImmutableRecord immutableRecord = ImmutableRecord.builder().id(20).value("immutable").build(); + mappedImmutableTable.putItem(immutableRecord); + + BatchGetResultPageIterable pages = enhancedClient.batchGetItem(r -> r.readBatches( + ReadBatch.builder(Record1.class).mappedTableResource(mappedTable1).addGetItem(i -> i.key(k -> k.partitionValue(0))).build(), + ReadBatch.builder(BeanRecord.class).mappedTableResource(mappedBeanTable).addGetItem(i -> i.key(k -> k.partitionValue(10))).build(), + ReadBatch.builder(ImmutableRecord.class).mappedTableResource(mappedImmutableTable).addGetItem(i -> i.key(k -> k.partitionValue(20))).build())); + + List collected = pages.stream().collect(Collectors.toList()); + assertThat(collected.size(), is(1)); + assertThat(collected.get(0).resultsForTable(mappedTable1), containsInAnyOrder(RECORDS_1.get(0))); + assertThat(collected.get(0).resultsForTable(mappedBeanTable).get(0).getValue(), is("bean")); + assertThat(collected.get(0).resultsForTable(mappedImmutableTable).get(0).value(), is("immutable")); + } + private BatchGetItemEnhancedRequest batchGetItemEnhancedRequestWithNotFoundRecord() { return BatchGetItemEnhancedRequest.builder() .readBatches( diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchWriteItemTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchWriteItemTest.java index ca5bebc33bc4..457a4e485254 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchWriteItemTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/BatchWriteItemTest.java @@ -17,10 +17,14 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -32,11 +36,15 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.TimestampedRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteResult; import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics; @@ -151,9 +159,17 @@ public int hashCode() { private DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(getDynamoDbClient()) .build(); + private DynamoDbEnhancedClient extensionEnhancedClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); private DynamoDbTable mappedTable1 = enhancedClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); private DynamoDbTable mappedTable2 = enhancedClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + private DynamoDbTable timestampedTable = + extensionEnhancedClient.table(getConcreteTableName("timestamped-table"), TimestampedRecord.TABLE_SCHEMA); + private DynamoDbTable> unsupportedCustomSchemaTable = + extensionEnhancedClient.table(getConcreteTableName("unsupported-schema-table"), new UnsupportedConverterTableSchema()); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -169,6 +185,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + timestampedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + unsupportedCustomSchemaTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); } @After @@ -179,6 +197,12 @@ public void deleteTable() { getDynamoDbClient().deleteTable(DeleteTableRequest.builder() .tableName(getConcreteTableName("table-name-2")) .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("timestamped-table")) + .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("unsupported-schema-table")) + .build()); } @Test @@ -198,6 +222,24 @@ public void singlePut() { assertThat(record, is(RECORDS_1.get(0))); } + @Test + public void putItem_singleWithConsumedCapacity_shouldReturnMetrics() { + BatchWriteResult result = enhancedClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .addWriteBatch( + WriteBatch.builder(Record1.class) + .mappedTableResource(mappedTable1) + .addPutItem(r -> r.item(RECORDS_1.get(0))) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build()); + + Assertions.assertThat(result.consumedCapacity()).isNotEmpty(); + Assertions.assertThat(result.consumedCapacity().get(0).capacityUnits()).isGreaterThan(0d); + Assertions.assertThat(result.consumedCapacity().get(0).tableName()) + .isEqualTo(getConcreteTableName("table-name-1")); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(0))), is(RECORDS_1.get(0))); + } + @Test public void multiplePut() { BatchWriteItemEnhancedRequest batchWriteItemEnhancedRequest = @@ -273,6 +315,26 @@ public void singleDelete() { assertThat(record, is(nullValue())); } + @Test + public void deleteItem_singleWithConsumedCapacity_shouldReturnMetrics() { + mappedTable1.putItem(r -> r.item(RECORDS_1.get(0))); + + BatchWriteResult result = enhancedClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .addWriteBatch( + WriteBatch.builder(Record1.class) + .mappedTableResource(mappedTable1) + .addDeleteItem(r -> r.key(k -> k.partitionValue(0))) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build()); + + Assertions.assertThat(result.consumedCapacity()).isNotEmpty(); + Assertions.assertThat(result.consumedCapacity().get(0).capacityUnits()).isGreaterThan(0d); + Assertions.assertThat(result.consumedCapacity().get(0).tableName()) + .isEqualTo(getConcreteTableName("table-name-1")); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(0))), is(nullValue())); + } + @Test public void multipleDelete() { mappedTable1.putItem(r -> r.item(RECORDS_1.get(0))); @@ -384,5 +446,78 @@ public void mixedCommands_withConsumedCapacity() { assertThat(mappedTable2.getItem(r -> r.key(k -> k.partitionValue(0))), is(nullValue())); } + @Test + public void batchWrite_withSupportedAndUnsupportedSchema_shouldPreserveValues() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("details", + AttributeValue.builder().m(Collections.singletonMap("inner", + AttributeValue.builder().s("v").build())) + .build()); + + BatchWriteItemEnhancedRequest request = + BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(TimestampedRecord.class) + .mappedTableResource(timestampedTable) + .addPutItem(r -> r.item(new TimestampedRecord().setId("ts-1"))) + .build(), + WriteBatch.builder(customTableType()) + .mappedTableResource(unsupportedCustomSchemaTable) + .addPutItem(r -> r.item(customItem)) + .build()) + .build(); + + extensionEnhancedClient.batchWriteItem(request); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("details").m().get("inner").s(), is("v")); + } + + @Test + public void batchWriteWithResponse_withSupportedAndUnsupportedSchema_shouldReturnMetrics() { + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("details", + AttributeValue.builder().m(Collections.singletonMap("inner", + AttributeValue.builder().s("v").build())) + .build()); + + BatchWriteResult result = + extensionEnhancedClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(TimestampedRecord.class) + .mappedTableResource(timestampedTable) + .addPutItem(r -> r.item(new TimestampedRecord().setId("ts-1"))) + .build(), + WriteBatch.builder(customTableType()) + .mappedTableResource(unsupportedCustomSchemaTable) + .addPutItem(r -> r.item(customItem)) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .build()); + + assertThat(result.consumedCapacity(), is(notNullValue())); + assertThat(result.consumedCapacity().size(), is(2)); + assertThat(result.itemCollectionMetrics(), is(notNullValue())); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("details").m().get("inner").s(), is("v")); + } + + @SuppressWarnings("unchecked") + private Class> customTableType() { + return (Class>) (Class) Map.class; + } + } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/DeleteItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/DeleteItemWithResponseTest.java index 532bf220a842..1d051cae55a2 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/DeleteItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/DeleteItemWithResponseTest.java @@ -116,4 +116,20 @@ public void returnConsumedCapacity_set_consumedCapacityNotNull() { assertThat(response.consumedCapacity()).isNotNull(); } + + @Test + public void deleteItem_simpleAndWithResponse_shouldReturnSameAttributes() { + Record first = new Record().setId(11).setStringAttr1("a"); + mappedTable1.putItem(first); + Record deletedBySimple = mappedTable1.deleteItem(r -> r.key(k -> k.partitionValue(11))); + assertThat(deletedBySimple).isEqualTo(first); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(11)))).isNull(); + + Record second = new Record().setId(12).setStringAttr1("b"); + mappedTable1.putItem(second); + DeleteItemEnhancedResponse response = + mappedTable1.deleteItemWithResponse(r -> r.key(k -> k.partitionValue(12))); + assertThat(response.attributes()).isEqualTo(second); + assertThat(mappedTable1.getItem(r -> r.key(k -> k.partitionValue(12)))).isNull(); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenMapTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenMapTest.java index ee8f6be5e9bc..625948fb5750 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenMapTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenMapTest.java @@ -20,6 +20,8 @@ import java.util.Collections; import java.util.HashMap; +import java.util.Map; +import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.After; @@ -32,11 +34,15 @@ import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FlattenRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.internal.client.ExtensionResolver; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.flattenmap.FlattenMapAndFlattenRecordBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.flattenmap.FlattenMapInvalidBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.flattenmap.FlattenMapValidBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.flattenmap.NestedFlattenMapBean; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.ReadBatch; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; public class FlattenMapTest extends LocalDynamoDbSyncTestBase { @@ -238,4 +244,71 @@ public void updateItemWithNestedFlattenMap_correctlyFlattensMapAttributes() { getDynamoDbClient().deleteTable(r -> r.tableName(nestedTableName)); } } + + @Test + public void updateItem_withUnsupportedCustomSchema_shouldSucceedWithMixedNestedData() { + String customTableName = getConcreteTableName("custom-flatten-table"); + DynamoDbTable> customTable = + enhancedClient.table(customTableName, new UnsupportedConverterTableSchema()); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + + try { + Map nested = new HashMap<>(); + nested.put("mapAttribute1", AttributeValue.builder().s("mapValue1").build()); + nested.put("mapAttribute2", AttributeValue.builder().s("mapValue2").build()); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-flat-1").build()); + item.put("flattenLike", AttributeValue.builder().m(nested).build()); + item.put("records", AttributeValue.builder().l( + AttributeValue.builder().m(Collections.singletonMap("k", AttributeValue.builder().s("v").build())).build(), + AttributeValue.builder().s("literal").build()).build()); + + customTable.updateItem(item); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-flat-1"))); + assertThat(persisted.get("flattenLike").m().get("mapAttribute1").s()).isEqualTo("mapValue1"); + assertThat(persisted.get("records").l().get(1).s()).isEqualTo("literal"); + } finally { + getDynamoDbClient().deleteTable(r -> r.tableName(customTableName)); + } + } + + @Test + public void flattenMap_acrossMultipleOperations_shouldPreserveValues() { + FlattenMapValidBean record = new FlattenMapValidBean(); + record.setId("cross-1"); + record.setRootAttribute1("root-1"); + record.setAttributesMap(new HashMap() {{ + put("k1", "v1"); + put("k2", "v2"); + }}); + mappedTable.putItem(record); + + FlattenMapValidBean update = new FlattenMapValidBean(); + update.setId("cross-1"); + update.setRootAttribute2("root-2"); + update.setAttributesMap(new HashMap() {{ + put("k1", "v1u"); + put("k3", "v3u"); + }}); + mappedTable.updateItem(update); + + List scanned = mappedTable.scan().items().stream().collect(Collectors.toList()); + assertThat(scanned.size()).isEqualTo(1); + assertThat(scanned.get(0).getAttributesMap()).containsEntry("k1", "v1u"); + assertThat(scanned.get(0).getAttributesMap()).containsEntry("k3", "v3u"); + + List batchRead = enhancedClient.batchGetItem(BatchGetItemEnhancedRequest.builder() + .readBatches(ReadBatch.builder(FlattenMapValidBean.class) + .mappedTableResource(mappedTable) + .addGetItem(r -> r.key(k -> k.partitionValue("cross-1"))) + .build()) + .build()) + .resultsForTable(mappedTable) + .stream() + .collect(Collectors.toList()); + assertThat(batchRead).hasSize(1); + assertThat(batchRead.get(0).getRootAttribute2()).isEqualTo("root-2"); + } } \ No newline at end of file diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenTest.java index 10c343f7dfbb..bd3ece87a228 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenTest.java @@ -20,6 +20,8 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; import java.util.Objects; +import java.util.List; +import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -27,6 +29,8 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.ReadBatch; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; public class FlattenTest extends LocalDynamoDbSyncTestBase { @@ -202,4 +206,32 @@ public void update_nullDocument() { assertThat(updatedRecord, is(record)); assertThat(fetchedRecord, is(record)); } + + @Test + public void flattenedAttributes_acrossMultipleOperations_shouldPreserveValues() { + Record initial = new Record().setId("id-cross") + .setDocument(new Document().setDocumentAttribute1("a1").setDocumentAttribute2("a2")); + mappedTable.putItem(initial); + + Record update = new Record().setId("id-cross") + .setDocument(new Document().setDocumentAttribute1("a1u").setDocumentAttribute2("a2u") + .setDocumentAttribute3("a3u")); + mappedTable.updateItem(update); + + List scanned = mappedTable.scan().items().stream().collect(Collectors.toList()); + assertThat(scanned.size(), is(1)); + assertThat(scanned.get(0), is(update)); + + List batchRead = enhancedClient.batchGetItem(BatchGetItemEnhancedRequest.builder() + .readBatches(ReadBatch.builder(Record.class) + .mappedTableResource(mappedTable) + .addGetItem(r -> r.key(k -> k.partitionValue("id-cross"))) + .build()) + .build()) + .resultsForTable(mappedTable) + .stream() + .collect(Collectors.toList()); + assertThat(batchRead.size(), is(1)); + assertThat(batchRead.get(0), is(update)); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenWithTagsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenWithTagsTest.java index 9a87f9457b87..c095210b57ef 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenWithTagsTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/FlattenWithTagsTest.java @@ -21,6 +21,8 @@ import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey; import java.util.Objects; +import java.util.List; +import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -28,6 +30,8 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchGetItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.ReadBatch; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; public class FlattenWithTagsTest extends LocalDynamoDbSyncTestBase { @@ -192,4 +196,33 @@ public void update_someValues() { assertThat(updatedRecord, is(record)); assertThat(fetchedRecord, is(record)); } + + @Test + public void sortTaggedFlattenedPath_acrossMultipleOperations_shouldPreserveValues() { + Record initial = new Record().setId("id-tag") + .setDocument(new Document().setDocumentAttribute1("s1").setDocumentAttribute2("v2")); + mappedTable.putItem(initial); + + Record update = new Record().setId("id-tag") + .setDocument(new Document().setDocumentAttribute1("s1").setDocumentAttribute2("v2u") + .setDocumentAttribute3("v3u")); + mappedTable.updateItem(update); + + List scanned = mappedTable.scan().items().stream().collect(Collectors.toList()); + assertThat(scanned.size(), is(1)); + assertThat(scanned.get(0), is(update)); + + List batchRead = enhancedClient.batchGetItem(BatchGetItemEnhancedRequest.builder() + .readBatches(ReadBatch.builder(Record.class) + .mappedTableResource(mappedTable) + .addGetItem(r -> r.key(k -> k.partitionValue("id-tag") + .sortValue("s1"))) + .build()) + .build()) + .resultsForTable(mappedTable) + .stream() + .collect(Collectors.toList()); + assertThat(batchRead.size(), is(1)); + assertThat(batchRead.get(0), is(update)); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/GetItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/GetItemWithResponseTest.java index abce56fe3054..228e1644083b 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/GetItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/GetItemWithResponseTest.java @@ -31,6 +31,7 @@ import software.amazon.awssdk.enhanced.dynamodb.model.GetItemEnhancedResponse; import software.amazon.awssdk.services.dynamodb.model.ConsumedCapacity; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; public class GetItemWithResponseTest extends LocalDynamoDbSyncTestBase { @@ -153,6 +154,21 @@ public void getItemWithResponse_withReturnConsumedCapacity_when_recordIsPresent_ assertThat(consumedCapacity.capacityUnits()).isCloseTo(25.0, Offset.offset(0.01)); } + @Test + public void getItem_withExtension_simpleAndWithResponse_shouldReturnSameData() { + DynamoDbEnhancedClient extensionClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbTable extensionTable = extensionClient.table(getConcreteTableName(TEST_TABLE_NAME), TABLE_SCHEMA); + Record original = new Record().setId(501).setStringAttr1("abc"); + extensionTable.putItem(original); + + Record getResult = extensionTable.getItem(r -> r.key(k -> k.partitionValue(501))); + GetItemEnhancedResponse response = extensionTable.getItemWithResponse(r -> r.key(k -> k.partitionValue(501))); + assertThat(getResult).isEqualTo(response.attributes()); + } + private static String getStringAttrValue(int numChars) { char[] chars = new char[numChars]; Arrays.fill(chars, 'a'); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactGetItemsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactGetItemsTest.java index d5a12246dde2..451f933c20b1 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactGetItemsTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactGetItemsTest.java @@ -32,6 +32,7 @@ import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.TransactGetItemsEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; @@ -186,5 +187,32 @@ public void notFoundRecordReturnsNull() { assertThat(results.get(2).getItem(mappedTable2), is(nullValue())); assertThat(results.get(3).getItem(mappedTable1), is(RECORDS_1.get(1))); } + + @Test + public void transactGetRecords_withExtension_shouldPreserveAndReturnCorrectData() { + insertRecords(); + + DynamoDbEnhancedClient extensionClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + DynamoDbTable extensionMappedTable1 = extensionClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); + DynamoDbTable extensionMappedTable2 = extensionClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + + TransactGetItemsEnhancedRequest request = + TransactGetItemsEnhancedRequest.builder() + .addGetItem(extensionMappedTable1, Key.builder().partitionValue(0).build()) + .addGetItem(extensionMappedTable2, Key.builder().partitionValue(0).build()) + .addGetItem(extensionMappedTable2, Key.builder().partitionValue(1).build()) + .addGetItem(extensionMappedTable1, Key.builder().partitionValue(1).build()) + .build(); + + List results = extensionClient.transactGetItems(request); + assertThat(results.size(), is(4)); + assertThat(results.get(0).getItem(extensionMappedTable1), is(RECORDS_1.get(0))); + assertThat(results.get(1).getItem(extensionMappedTable2), is(RECORDS_2.get(0))); + assertThat(results.get(2).getItem(extensionMappedTable2), is(RECORDS_2.get(1))); + assertThat(results.get(3).getItem(extensionMappedTable1), is(RECORDS_1.get(1))); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactWriteItemsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactWriteItemsTest.java index b18e3185c3e9..f959ca9cca20 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactWriteItemsTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/TransactWriteItemsTest.java @@ -24,7 +24,9 @@ import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -36,6 +38,9 @@ import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.Key; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.TimestampedRecord; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.model.ConditionCheck; import software.amazon.awssdk.enhanced.dynamodb.model.TransactDeleteItemEnhancedRequest; @@ -48,6 +53,7 @@ import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics; import software.amazon.awssdk.services.dynamodb.model.ReturnValuesOnConditionCheckFailure; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.TransactionCanceledException; public class TransactWriteItemsTest extends LocalDynamoDbSyncTestBase { @@ -152,9 +158,17 @@ public int hashCode() { private DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder() .dynamoDbClient(getDynamoDbClient()) .build(); + private DynamoDbEnhancedClient extensionEnhancedClient = DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); private DynamoDbTable mappedTable1 = enhancedClient.table(getConcreteTableName("table-name-1"), TABLE_SCHEMA_1); private DynamoDbTable mappedTable2 = enhancedClient.table(getConcreteTableName("table-name-2"), TABLE_SCHEMA_2); + private DynamoDbTable timestampedTable = + extensionEnhancedClient.table(getConcreteTableName("timestamped-table"), TimestampedRecord.TABLE_SCHEMA); + private DynamoDbTable> unsupportedCustomSchemaTable = + extensionEnhancedClient.table(getConcreteTableName("unsupported-schema-table"), new UnsupportedConverterTableSchema()); private static final List RECORDS_1 = IntStream.range(0, 2) @@ -170,6 +184,8 @@ public int hashCode() { public void createTable() { mappedTable1.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); mappedTable2.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + timestampedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + unsupportedCustomSchemaTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); } @After @@ -180,6 +196,12 @@ public void deleteTable() { getDynamoDbClient().deleteTable(DeleteTableRequest.builder() .tableName(getConcreteTableName("table-name-2")) .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("timestamped-table")) + .build()); + getDynamoDbClient().deleteTable(DeleteTableRequest.builder() + .tableName(getConcreteTableName("unsupported-schema-table")) + .build()); } @Test @@ -493,5 +515,57 @@ public void mixedCommands_returnValuesOnConditionCheckFailureSet_allConditionsFa cancellationReasons.forEach(r -> assertThat(r.item().isEmpty(), is(false))); } } + + @Test + public void transactWrite_withSupportedAndUnsupportedSchema_shouldPreserveValues() { + TimestampedRecord timestampedRecord = new TimestampedRecord().setId("ts-1"); + + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(singletonMap("inner", AttributeValue.builder().s("value").build())).build()); + + extensionEnhancedClient.transactWriteItems( + TransactWriteItemsEnhancedRequest.builder() + .addPutItem(timestampedTable, timestampedRecord) + .addPutItem(unsupportedCustomSchemaTable, customItem) + .build()); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } + + @Test + public void transactWriteWithResponse_withSupportedAndUnsupportedSchema_shouldReturnMetrics() { + TimestampedRecord timestampedRecord = new TimestampedRecord().setId("ts-1"); + + Map customItem = new HashMap<>(); + customItem.put("pk", AttributeValue.builder().s("custom-1").build()); + customItem.put("payload", + AttributeValue.builder().m(singletonMap("inner", AttributeValue.builder().s("value").build())).build()); + + TransactWriteItemsEnhancedResponse response = extensionEnhancedClient.transactWriteItemsWithResponse( + TransactWriteItemsEnhancedRequest.builder() + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .addPutItem(timestampedTable, timestampedRecord) + .addPutItem(unsupportedCustomSchemaTable, customItem) + .build()); + + assertThat(response.consumedCapacity(), is(notNullValue())); + assertThat(response.consumedCapacity().size(), is(2)); + assertThat(response.itemCollectionMetrics(), is(notNullValue())); + + TimestampedRecord persistedTimestamped = timestampedTable.getItem(r -> r.key(k -> k.partitionValue("ts-1"))); + Map persistedCustom = + unsupportedCustomSchemaTable.getItem(r -> r.key(k -> k.partitionValue("custom-1"))); + + assertThat(persistedTimestamped.getTime(), is(notNullValue())); + assertThat(persistedCustom.get("payload").m().get("inner").s(), is("value")); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateBehaviorTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateBehaviorTest.java index fe87b1ece6e0..e6d0bb04bfe3 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateBehaviorTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateBehaviorTest.java @@ -5,7 +5,9 @@ import static org.junit.Assert.assertTrue; import java.time.Instant; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -14,8 +16,10 @@ import org.junit.Test; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.Expression; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.UnsupportedConverterTableSchema; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.CompositeRecord; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FlattenRecord; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.NestedRecordWithUpdateBehavior; @@ -164,6 +168,34 @@ public void updateBehaviors_transactWriteItems_secondUpdate() { assertThat(persistedRecord.getCreatedAutoUpdateOn()).isEqualTo(firstUpdatedRecord.getCreatedAutoUpdateOn()); } + @Test + public void updateItem_withConditionExpression_shouldPreserveWriteIfNotExistsField() { + RecordWithUpdateBehaviors seed = new RecordWithUpdateBehaviors(); + seed.setId("id-cond"); + seed.setCreatedOn(INSTANT_1); + seed.setLastUpdatedOn(INSTANT_1); + mappedTable.putItem(seed); + + RecordWithUpdateBehaviors update = new RecordWithUpdateBehaviors(); + update.setId("id-cond"); + update.setVersion(1L); + update.setCreatedOn(INSTANT_2); + update.setLastUpdatedOn(INSTANT_2); + + mappedTable.updateItem(r -> r.item(update) + .conditionExpression(Expression.builder() + .expression("id = :id") + .expressionValues(Collections.singletonMap(":id", + AttributeValue.builder() + .s("id-cond") + .build())) + .build())); + + RecordWithUpdateBehaviors persistedRecord = mappedTable.getItem(r -> r.key(k -> k.partitionValue("id-cond"))); + assertThat(persistedRecord.getCreatedOn()).isEqualTo(INSTANT_1); + assertThat(persistedRecord.getLastUpdatedOn()).isEqualTo(INSTANT_2); + } + @Test public void when_updatingNestedObjectWithSingleLevel_existingInformationIsPreserved_scalar_only_update() { @@ -585,4 +617,96 @@ public void updateBehaviors_nested() { assertThat(persistedRecord.getNestedRecord().getNestedUpdateBehaviorAttribute()).isNull(); assertThat(persistedRecord.getNestedRecord().getNestedTimeAttribute()).isAfterOrEqualTo(currentTime); } + + @Test + public void updateItem_withUnsupportedSchema_scalarOnlyMode_shouldSucceed() { + DynamoDbTable> customTable = createCustomModeTable(); + + Map item = new java.util.HashMap<>(); + item.put("pk", AttributeValue.builder().s("custom-scalar").build()); + item.put("simple", AttributeValue.builder().s("value").build()); + customTable.updateItem(r -> r.item(item).ignoreNullsMode(IgnoreNullsMode.SCALAR_ONLY)); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-scalar"))); + assertThat(persisted).isNotNull(); + assertThat(persisted.get("simple").s()).isEqualTo("value"); + deleteCustomModeTable(); + } + + @Test + public void updateItem_withUnsupportedSchema_mapsOnlyMode_shouldSucceed() { + DynamoDbTable> customTable = createCustomModeTable(); + + Map item = buildCustomSchemaItem("custom-maps"); + customTable.updateItem(r -> r.item(item).ignoreNullsMode(IgnoreNullsMode.MAPS_ONLY)); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-maps"))); + assertThat(persisted).isNotNull(); + assertThat(persisted.get("nested").m().get("city").s()).isEqualTo("Seattle"); + deleteCustomModeTable(); + } + + @Test + public void updateItem_withUnsupportedSchema_defaultMode_shouldSucceed() { + DynamoDbTable> customTable = createCustomModeTable(); + + Map item = buildCustomSchemaItem("custom-default"); + customTable.updateItem(item); + + Map persisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-default"))); + assertThat(persisted).isNotNull(); + assertThat(persisted.get("nested").m().get("country").s()).isEqualTo("US"); + deleteCustomModeTable(); + } + + @Test + public void sharedClient_withMixedSchemas_shouldApplySupportedAndSkipUnsupported() { + DynamoDbTable> customTable = createCustomModeTable(); + + RecordWithUpdateBehaviors supportedRecord = new RecordWithUpdateBehaviors(); + supportedRecord.setId("supported-id"); + mappedTable.updateItem(supportedRecord); + + Map customItem = buildCustomSchemaItem("custom-mixed"); + customTable.updateItem(customItem); + + RecordWithUpdateBehaviors supportedPersisted = mappedTable.getItem(r -> r.key(k -> k.partitionValue("supported-id"))); + Map customPersisted = customTable.getItem(r -> r.key(k -> k.partitionValue("custom-mixed"))); + + assertThat(supportedPersisted).isNotNull(); + assertThat(supportedPersisted.getLastAutoUpdatedOn()).isNotNull(); + assertThat(supportedPersisted.getCreatedAutoUpdateOn()).isNotNull(); + assertThat(customPersisted).isNotNull(); + assertThat(customPersisted.get("nested").m().get("city").s()).isEqualTo("Seattle"); + assertThat(customPersisted.get("records").l().get(1).s()).isEqualTo("literal"); + deleteCustomModeTable(); + } + + private DynamoDbTable> createCustomModeTable() { + DynamoDbTable> customTable = + enhancedClient.table(getConcreteTableName("custom-mode-table"), new UnsupportedConverterTableSchema()); + customTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + return customTable; + } + + private void deleteCustomModeTable() { + getDynamoDbClient().deleteTable(r -> r.tableName(getConcreteTableName("custom-mode-table"))); + } + + private Map buildCustomSchemaItem(String key) { + Map nested = new HashMap<>(); + nested.put("city", AttributeValue.builder().s("Seattle").build()); + nested.put("country", AttributeValue.builder().s("US").build()); + Map mapElement = new HashMap<>(); + mapElement.put("inner", AttributeValue.builder().s("value").build()); + + Map item = new HashMap<>(); + item.put("pk", AttributeValue.builder().s(key).build()); + item.put("nested", AttributeValue.builder().m(nested).build()); + item.put("records", AttributeValue.builder().l(Arrays.asList( + AttributeValue.builder().m(mapElement).build(), + AttributeValue.builder().s("literal").build())).build()); + return item; + } + } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateItemWithResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateItemWithResponseTest.java index c7557f7542b8..35daff8c3263 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateItemWithResponseTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/UpdateItemWithResponseTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.enhanced.dynamodb.functionaltests; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertNull; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; import java.util.Objects; @@ -29,6 +30,7 @@ import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedResponse; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ReturnValue; public class UpdateItemWithResponseTest extends LocalDynamoDbSyncTestBase { private static class Record { @@ -153,4 +155,56 @@ public void returnItemCollectionMetrics_unset_itemCollectionMetricsNull() { assertThat(response.itemCollectionMetrics()).isNull(); } + + @Test + public void updateItemWithResponse_returnAllOld_shouldMapAttributes() { + Record original = new Record().setId(1).setStringAttr1("attr"); + mappedTable1.putItem(original); + Record updated = new Record().setId(1).setStringAttr1("attr2"); + UpdateItemEnhancedResponse response = mappedTable1.updateItemWithResponse(r -> r.item(updated) + .returnValues(ReturnValue.ALL_OLD)); + assertThat(response.attributes()).isEqualTo(original); + } + + @Test + public void updateItemWithResponse_returnAllNew_shouldMapAttributes() { + Record original = new Record().setId(1).setStringAttr1("attr"); + mappedTable1.putItem(original); + Record updated = new Record().setId(1).setStringAttr1("attr2"); + UpdateItemEnhancedResponse response = mappedTable1.updateItemWithResponse(r -> r.item(updated) + .returnValues(ReturnValue.ALL_NEW)); + assertThat(response.attributes()).isEqualTo(updated); + } + + @Test + public void updateItemWithResponse_returnNone_shouldHaveNullAttributes() { + Record original = new Record().setId(1).setStringAttr1("attr"); + mappedTable1.putItem(original); + Record updated = new Record().setId(1).setStringAttr1("attr2"); + UpdateItemEnhancedResponse response = mappedTable1.updateItemWithResponse(r -> r.item(updated) + .returnValues(ReturnValue.NONE)); + assertNull(response.attributes()); + } + + @Test + public void updateItemWithResponse_returnUpdatedOld_shouldMapAttributes() { + Record original = new Record().setId(1).setStringAttr1("attr"); + mappedTable1.putItem(original); + Record updated = new Record().setId(1).setStringAttr1("attr2"); + UpdateItemEnhancedResponse response = mappedTable1.updateItemWithResponse(r -> r.item(updated) + .returnValues(ReturnValue.UPDATED_OLD)); + assertThat(response.attributes().getStringAttr1()).isEqualTo(original.stringAttr1); + assertThat(response.attributes().getId()).isNull(); + } + + @Test + public void updateItemWithResponse_returnUpdatedNew_shouldMapAttributes() { + Record original = new Record().setId(1).setStringAttr1("attr"); + mappedTable1.putItem(original); + Record updated = new Record().setId(1).setStringAttr1("attr2"); + UpdateItemEnhancedResponse response = mappedTable1.updateItemWithResponse(r -> r.item(updated) + .returnValues(ReturnValue.UPDATED_NEW)); + assertThat(response.attributes().getStringAttr1()).isEqualTo(updated.getStringAttr1()); + assertThat(response.attributes().getId()).isNull(); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/VersionedRecordTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/VersionedRecordTest.java index 9d9eec77cabc..c601ac6e0759 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/VersionedRecordTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/VersionedRecordTest.java @@ -41,6 +41,7 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.model.PutItemEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.UpdateItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException; import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; @@ -725,4 +726,21 @@ public void annotatedRecord_startAtNegativeOne_firstVersionIsZero() { AnnotatedRecordStartAtNegativeOne result = annotatedStartAtNegativeOneTable.getItem(r -> r.key(k -> k.partitionValue("test-id"))); assertThat(result.getVersion(), is(0L)); } + + @Test + public void transactWriteUpdate_versionedRecord_shouldIncrementVersion() { + mappedTable.putItem(r -> r.item(new Record().setId("tx-id").setAttribute("one"))); + Record existing = mappedTable.getItem(r -> r.key(k -> k.partitionValue("tx-id"))); + + enhancedClient.transactWriteItems(TransactWriteItemsEnhancedRequest.builder() + .addUpdateItem(mappedTable, + new Record().setId("tx-id") + .setAttribute("two") + .setVersion(existing.getVersion())) + .build()); + + Record updated = mappedTable.getItem(r -> r.key(k -> k.partitionValue("tx-id"))); + assertThat(updated.getVersion(), is(existing.getVersion() + 1)); + assertThat(updated.getAttribute(), is("two")); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicQueryTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicQueryTest.java new file mode 100644 index 000000000000..3e352e8d5c03 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicQueryTest.java @@ -0,0 +1,152 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; +import static software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional.keyEqualTo; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbAsyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.Page; +import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.Select; + +public class AsyncBasicQueryTest extends LocalDynamoDbAsyncTestBase { + private static final List DOCUMENTS = + IntStream.range(0, 10) + .mapToObj(i -> EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "id-value") + .putNumber("sort", i) + .putNumber("value", i) + .build()) + .collect(Collectors.toList()); + + private final String tableName = getConcreteTableName("doc-table-name"); + private DynamoDbEnhancedAsyncClient enhancedClient; + private DynamoDbAsyncTable docMappedTable; + + @Before + public void setup() { + enhancedClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + docMappedTable = enhancedClient.table(tableName, + TableSchema.documentSchemaBuilder() + .attributeConverterProviders(defaultProvider()) + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", + AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), "sort", + AttributeValueType.N) + .build()); + docMappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void cleanup() { + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder().tableName(tableName).build()).join(); + } + + private void insertDocuments() { + DOCUMENTS.forEach(d -> docMappedTable.putItem(d).join()); + } + + @Test + public void queryAllRecordsDefaultSettings_shortcutForm() { + insertDocuments(); + SdkPublisher> publisher = docMappedTable.query(keyEqualTo(k -> k.partitionValue("id-value"))); + List> pages = drainPublisher(publisher, 1); + assertThat(pages.get(0).items().size(), is(DOCUMENTS.size())); + } + + @Test + public void queryAllRecords_withProjection_shouldSelectOnlyProjectedAttributes() { + insertDocuments(); + SdkPublisher> publisher = + docMappedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .attributesToProject("value") + .select("SPECIFIC_ATTRIBUTES")); + List> pages = drainPublisher(publisher, 1); + EnhancedDocument first = pages.get(0).items().get(0); + assertThat(first.getString("id"), is(nullValue())); + assertThat(first.getNumber("sort"), is(nullValue())); + assertThat(first.getNumber("value").intValue(), is(0)); + } + + @Test + public void queryAllRecordsDefaultSettings_withSelectCount() { + insertDocuments(); + SdkPublisher> publisher = + docMappedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .select(Select.COUNT)); + Page page = drainPublisher(publisher, 1).get(0); + assertThat(page.count(), is(DOCUMENTS.size())); + assertThat(page.items(), is(empty())); + } + + @Test + public void queryRecords_withDottedAttributeName_shouldProjectCorrectly() { + EnhancedDocument nested = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "id-value") + .putNumber("sort", 1) + .putString("test.com", "v1") + .build(); + docMappedTable.putItem(nested).join(); + + SdkPublisher> publisher = + docMappedTable.query(b -> b.queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .addNestedAttributeToProject(NestedAttributeName.create("test.com"))); + EnhancedDocument first = drainPublisher(publisher, 1).get(0).items().get(0); + assertThat(first.getString("test.com"), is("v1")); + } + + @Test + public void queryExclusiveStartKey() { + insertDocuments(); + java.util.Map exclusiveStartKey = + new java.util.HashMap<>(); + exclusiveStartKey.put("id", stringValue("id-value")); + exclusiveStartKey.put("sort", numberValue(7)); + + SdkPublisher> publisher = + docMappedTable.query(QueryEnhancedRequest.builder() + .queryConditional(keyEqualTo(k -> k.partitionValue("id-value"))) + .exclusiveStartKey(exclusiveStartKey) + .build()); + List> pages = drainPublisher(publisher, 1); + assertThat(pages.get(0).items().isEmpty(), is(false)); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicScanTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicScanTest.java new file mode 100644 index 000000000000..36fb6c1556a5 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncBasicScanTest.java @@ -0,0 +1,133 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbAsyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.Page; +import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.Select; + +public class AsyncBasicScanTest extends LocalDynamoDbAsyncTestBase { + private static final List DOCUMENTS = + IntStream.range(0, 10) + .mapToObj(i -> EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "id-value") + .putNumber("sort", i) + .putNumber("value", i) + .build()) + .collect(Collectors.toList()); + + private final String tableName = getConcreteTableName("doc-table-name"); + private DynamoDbEnhancedAsyncClient enhancedClient; + private DynamoDbAsyncTable docMappedTable; + + @Before + public void setup() { + enhancedClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + docMappedTable = enhancedClient.table(tableName, + TableSchema.documentSchemaBuilder() + .attributeConverterProviders(defaultProvider()) + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", + AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), "sort", + AttributeValueType.N) + .build()); + docMappedTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + } + + @After + public void cleanup() { + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder().tableName(tableName).build()).join(); + } + + private void insertDocuments() { + DOCUMENTS.forEach(d -> docMappedTable.putItem(d).join()); + } + + @Test + public void scanAllRecordsDefaultSettings() { + insertDocuments(); + Page page = drainPublisher(docMappedTable.scan(), 1).get(0); + assertThat(page.items().size(), is(DOCUMENTS.size())); + } + + @Test + public void scanAllRecordsWithFilterAndProjection() { + insertDocuments(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("#sort >= :min_value AND #sort <= :max_value") + .expressionValues(expressionValues) + .putExpressionName("#sort", "sort") + .build(); + SdkPublisher> publisher = + docMappedTable.scan(ScanEnhancedRequest.builder() + .attributesToProject("sort") + .filterExpression(expression) + .build()); + Page page = drainPublisher(publisher, 1).get(0); + assertThat(page.items().size(), is(3)); + assertThat(page.items().get(0).getString("id"), is(nullValue())); + assertThat(page.items().get(0).getNumber("sort").intValue(), is(3)); + } + + @Test + public void scanAllRecords_withSelectCount_shouldReturnCount() { + insertDocuments(); + Page page = drainPublisher(docMappedTable.scan(b -> b.select(Select.COUNT)), 1).get(0); + assertThat(page.count(), is(DOCUMENTS.size())); + assertThat(page.items(), is(empty())); + } + + @Test + public void scanExclusiveStartKey() { + insertDocuments(); + Map key = new HashMap<>(); + key.put("id", stringValue("id-value")); + key.put("sort", numberValue(7)); + Page page = drainPublisher(docMappedTable.scan(b -> b.exclusiveStartKey(key)), 1).get(0); + assertThat(page.items().size(), is(2)); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexQueryTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexQueryTest.java new file mode 100644 index 000000000000..a718cf4293e6 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexQueryTest.java @@ -0,0 +1,147 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; +import static software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional.keyEqualTo; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncIndex; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbAsyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedGlobalSecondaryIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.Page; +import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional; +import software.amazon.awssdk.enhanced.dynamodb.model.QueryEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; + +public class AsyncIndexQueryTest extends LocalDynamoDbAsyncTestBase { + private static final List DOCUMENTS = + IntStream.range(0, 10) + .mapToObj(i -> EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "id-value") + .putNumber("sort", i) + .putString("gsi_id", "gsi-id-value") + .putNumber("gsi_sort", i) + .build()) + .collect(Collectors.toList()); + + private final String tableName = getConcreteTableName("doc-table-name"); + private DynamoDbEnhancedAsyncClient enhancedClient; + private DynamoDbAsyncTable table; + private DynamoDbAsyncIndex index; + + @Before + public void setup() { + enhancedClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + table = enhancedClient.table(tableName, + TableSchema.documentSchemaBuilder() + .attributeConverterProviders(defaultProvider()) + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), "sort", AttributeValueType.N) + .addIndexPartitionKey("gsi_keys_only", "gsi_id", AttributeValueType.S) + .addIndexSortKey("gsi_keys_only", "gsi_sort", AttributeValueType.N) + .build()); + table.createTable(CreateTableEnhancedRequest.builder() + .provisionedThroughput(getDefaultProvisionedThroughput()) + .globalSecondaryIndices( + EnhancedGlobalSecondaryIndex.builder() + .indexName("gsi_keys_only") + .projection(p -> p.projectionType(ProjectionType.KEYS_ONLY)) + .provisionedThroughput(getDefaultProvisionedThroughput()) + .build()) + .build()).join(); + index = table.index("gsi_keys_only"); + } + + @After + public void cleanup() { + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder().tableName(tableName).build()).join(); + } + + private void insertDocuments() { + DOCUMENTS.forEach(d -> table.putItem(d).join()); + } + + @Test + public void queryAllRecordsDefaultSettings_usingShortcutForm() { + insertDocuments(); + Page page = drainPublisher(index.query(keyEqualTo(k -> k.partitionValue("gsi-id-value"))), 1).get(0); + assertThat(page.items().size(), is(DOCUMENTS.size())); + } + + @Test + public void queryBetween() { + insertDocuments(); + Key fromKey = Key.builder().partitionValue("gsi-id-value").sortValue(3).build(); + Key toKey = Key.builder().partitionValue("gsi-id-value").sortValue(5).build(); + SdkPublisher> publisher = + index.query(r -> r.queryConditional(QueryConditional.sortBetween(fromKey, toKey))); + Page page = drainPublisher(publisher, 1).get(0); + assertThat(page.items().size(), is(3)); + } + + @Test + public void queryLimit() { + insertDocuments(); + List> pages = drainPublisher(index.query(QueryEnhancedRequest.builder() + .queryConditional(keyEqualTo(k -> k.partitionValue("gsi-id-value"))) + .limit(5) + .build()), 3); + assertThat(pages.get(0).items().size(), is(5)); + assertThat(pages.get(2).items(), is(empty())); + } + + @Test + public void queryExclusiveStartKey() { + insertDocuments(); + Map startKey = new HashMap<>(); + startKey.put("id", stringValue("id-value")); + startKey.put("sort", numberValue(7)); + startKey.put("gsi_id", stringValue("gsi-id-value")); + startKey.put("gsi_sort", numberValue(7)); + Page page = drainPublisher(index.query(QueryEnhancedRequest.builder() + .queryConditional(keyEqualTo(k -> k.partitionValue("gsi-id-value"))) + .exclusiveStartKey(startKey) + .build()), 1).get(0); + assertThat(page.lastEvaluatedKey(), is(nullValue())); + assertThat(page.items().size(), is(2)); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexScanTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexScanTest.java new file mode 100644 index 000000000000..c0c05699626e --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/AsyncIndexScanTest.java @@ -0,0 +1,143 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.numberValue; +import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncIndex; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbAsyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedGlobalSecondaryIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.Page; +import software.amazon.awssdk.enhanced.dynamodb.model.ScanEnhancedRequest; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; + +public class AsyncIndexScanTest extends LocalDynamoDbAsyncTestBase { + private static final List DOCUMENTS = + IntStream.range(0, 10) + .mapToObj(i -> EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "id-value") + .putNumber("sort", i) + .putString("gsi_id", "gsi-id-value") + .putNumber("gsi_sort", i) + .build()) + .collect(Collectors.toList()); + + private final String tableName = getConcreteTableName("doc-table-name"); + private DynamoDbEnhancedAsyncClient enhancedClient; + private DynamoDbAsyncTable table; + private DynamoDbAsyncIndex index; + + @Before + public void setup() { + enhancedClient = DynamoDbEnhancedAsyncClient.builder().dynamoDbClient(getDynamoDbAsyncClient()).build(); + table = enhancedClient.table(tableName, + TableSchema.documentSchemaBuilder() + .attributeConverterProviders(defaultProvider()) + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), "sort", AttributeValueType.N) + .addIndexPartitionKey("gsi_keys_only", "gsi_id", AttributeValueType.S) + .addIndexSortKey("gsi_keys_only", "gsi_sort", AttributeValueType.N) + .build()); + table.createTable(CreateTableEnhancedRequest.builder() + .provisionedThroughput(getDefaultProvisionedThroughput()) + .globalSecondaryIndices( + EnhancedGlobalSecondaryIndex.builder() + .indexName("gsi_keys_only") + .projection(p -> p.projectionType(ProjectionType.KEYS_ONLY)) + .provisionedThroughput(getDefaultProvisionedThroughput()) + .build()) + .build()).join(); + index = table.index("gsi_keys_only"); + } + + @After + public void cleanup() { + getDynamoDbAsyncClient().deleteTable(DeleteTableRequest.builder().tableName(tableName).build()).join(); + } + + private void insertDocuments() { + DOCUMENTS.forEach(d -> table.putItem(d).join()); + } + + @Test + public void scanAllRecordsDefaultSettings() { + insertDocuments(); + Page page = drainPublisher(index.scan(), 1).get(0); + assertThat(page.items().size(), is(DOCUMENTS.size())); + } + + @Test + public void scanAllRecordsWithFilter() { + insertDocuments(); + Map expressionValues = new HashMap<>(); + expressionValues.put(":min_value", numberValue(3)); + expressionValues.put(":max_value", numberValue(5)); + Expression expression = Expression.builder() + .expression("sort >= :min_value AND sort <= :max_value") + .expressionValues(expressionValues) + .build(); + Page page = drainPublisher(index.scan(ScanEnhancedRequest.builder() + .filterExpression(expression) + .build()), 1).get(0); + assertThat(page.items().size(), is(3)); + } + + @Test + public void scanLimit() { + insertDocuments(); + List> pages = drainPublisher(index.scan(r -> r.limit(5)), 3); + assertThat(pages.get(0).items().size(), is(5)); + assertThat(pages.get(2).items(), is(empty())); + } + + @Test + public void scanExclusiveStartKey() { + insertDocuments(); + Map startKey = new HashMap<>(); + startKey.put("id", stringValue("id-value")); + startKey.put("sort", numberValue(7)); + startKey.put("gsi_id", stringValue("gsi-id-value")); + startKey.put("gsi_sort", numberValue(7)); + Page page = drainPublisher(index.scan(r -> r.exclusiveStartKey(startKey)), 1).get(0); + assertThat(page.lastEvaluatedKey(), is(nullValue())); + assertThat(page.items().size(), is(2)); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionAsyncCrudTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionAsyncCrudTest.java new file mode 100644 index 000000000000..fa5772cf1fe7 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionAsyncCrudTest.java @@ -0,0 +1,221 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbAsyncTable; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedAsyncClient; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbAsyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteResult; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedResponse; +import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics; + +/** + * Async document-schema tests that exercise {@link AutoGeneratedTimestampRecordExtension}. + * Kept out of the parameterized {@link BasicAsyncCrudTest} because these scenarios do not use {@code testData}. + */ +public class DocumentSchemaExtensionAsyncCrudTest extends LocalDynamoDbAsyncTestBase { + + private DynamoDbEnhancedAsyncClient createExtensionClient() { + return DynamoDbEnhancedAsyncClient.builder() + .dynamoDbClient(getDynamoDbAsyncClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + } + + private DynamoDbAsyncTable createExtensionDocumentTable(DynamoDbEnhancedAsyncClient extensionClient, + String tableNameSuffix) { + String tableName = getConcreteTableName(tableNameSuffix); + DynamoDbAsyncTable extensionTable = + extensionClient.table(tableName, + TableSchema.documentSchemaBuilder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.S) + .attributeConverterProviders(defaultProvider()) + .build()); + extensionTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())).join(); + return extensionTable; + } + + private void deleteExtensionTable(String tableName) { + getDynamoDbAsyncClient().deleteTable(r -> r.tableName(tableName)).join(); + } + + @Test + public void documentSchema_withExtension_putAndUpdate_shouldSucceed() { + DynamoDbEnhancedAsyncClient extensionClient = createExtensionClient(); + DynamoDbAsyncTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument document = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("payload", "value") + .build(); + extensionTable.putItem(document).join(); + extensionTable.updateItem(document).join(); + + EnhancedDocument persisted = extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).join(); + assertThat(persisted, is(notNullValue())); + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchema_withExtension_shouldPreserveNonTimestampValues() { + DynamoDbEnhancedAsyncClient extensionClient = createExtensionClient(); + DynamoDbAsyncTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-integrity-table"); + String extensionTableName = extensionTable.tableName(); + + Map nested = new LinkedHashMap<>(); + nested.put("time", AttributeValue.fromS("nested-original")); + nested.put("flag", AttributeValue.fromS("x")); + + Map itemMap = new LinkedHashMap<>(); + itemMap.put("id", AttributeValue.fromS("doc-1")); + itemMap.put("time", AttributeValue.fromS("root-original")); + itemMap.put("payload", AttributeValue.fromM(nested)); + itemMap.put("records", AttributeValue.fromL(Collections.singletonList(AttributeValue.fromM(nested)))); + + EnhancedDocument document = EnhancedDocument.fromAttributeValueMap(itemMap).toBuilder() + .attributeConverterProviders(defaultProvider()) + .build(); + + extensionTable.putItem(document).join(); + extensionTable.updateItem(document).join(); + + EnhancedDocument persisted = extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).join(); + assertThat(persisted.toMap().get("time").s(), is("root-original")); + assertThat(persisted.toMap().get("payload").m().get("time").s(), is("nested-original")); + assertThat(persisted.toMap().get("records").l().get(0).m().get("time").s(), is("nested-original")); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchema_withExtension_deleteItem_shouldSucceed() { + DynamoDbEnhancedAsyncClient extensionClient = createExtensionClient(); + DynamoDbAsyncTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-delete-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument document = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("payload", "value") + .build(); + extensionTable.putItem(document).join(); + extensionTable.deleteItem(r -> r.key(k -> k.partitionValue("doc-1"))).join(); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).join(), is(nullValue())); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchemaBatchWrite_withExtension_shouldPreserveValuesAndReturnMetrics() { + DynamoDbEnhancedAsyncClient extensionClient = createExtensionClient(); + DynamoDbAsyncTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-batch-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument first = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("time", "value-one") + .build(); + EnhancedDocument second = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-2") + .putString("time", "value-two") + .build(); + + BatchWriteResult result = + extensionClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(EnhancedDocument.class) + .mappedTableResource(extensionTable) + .addPutItem(r -> r.item(first)) + .addPutItem(r -> r.item(second)) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .build()).join(); + + assertThat(result.consumedCapacity(), is(notNullValue())); + assertThat(result.itemCollectionMetrics(), is(notNullValue())); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).join().toMap().get("time").s(), + is("value-one")); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-2"))).join().toMap().get("time").s(), + is("value-two")); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchemaTransactWrite_withExtension_shouldPreserveValuesAndReturnMetrics() { + DynamoDbEnhancedAsyncClient extensionClient = createExtensionClient(); + DynamoDbAsyncTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-transact-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument first = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("time", "value-one") + .build(); + EnhancedDocument second = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-2") + .putString("time", "value-two") + .build(); + + TransactWriteItemsEnhancedResponse response = + extensionClient.transactWriteItemsWithResponse(TransactWriteItemsEnhancedRequest.builder() + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .addPutItem(extensionTable, first) + .addPutItem(extensionTable, second) + .build()).join(); + + assertThat(response.consumedCapacity(), is(notNullValue())); + assertThat(response.itemCollectionMetrics(), is(notNullValue())); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).join().toMap().get("time").s(), + is("value-one")); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-2"))).join().toMap().get("time").s(), + is("value-two")); + + deleteExtensionTable(extensionTableName); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionCrudTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionCrudTest.java new file mode 100644 index 000000000000..7a70212ce8c5 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/document/DocumentSchemaExtensionCrudTest.java @@ -0,0 +1,215 @@ +/* + * 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.enhanced.dynamodb.functionaltests.document; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider.defaultProvider; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.LocalDynamoDbSyncTestBase; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteItemEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.BatchWriteResult; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.TransactWriteItemsEnhancedResponse; +import software.amazon.awssdk.enhanced.dynamodb.model.WriteBatch; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.ReturnItemCollectionMetrics; + +/** + * Document-schema tests that exercise {@link AutoGeneratedTimestampRecordExtension}. + * Kept out of the parameterized {@link BasicCrudTest} because these scenarios do not use {@code testData}. + */ +public class DocumentSchemaExtensionCrudTest extends LocalDynamoDbSyncTestBase { + + private DynamoDbEnhancedClient createExtensionClient() { + return DynamoDbEnhancedClient.builder() + .dynamoDbClient(getDynamoDbClient()) + .extensions(AutoGeneratedTimestampRecordExtension.create()) + .build(); + } + + private DynamoDbTable createExtensionDocumentTable(DynamoDbEnhancedClient extensionClient, + String tableNameSuffix) { + String tableName = getConcreteTableName(tableNameSuffix); + DynamoDbTable extensionTable = + extensionClient.table(tableName, + TableSchema.documentSchemaBuilder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "id", AttributeValueType.S) + .attributeConverterProviders(defaultProvider()) + .build()); + extensionTable.createTable(r -> r.provisionedThroughput(getDefaultProvisionedThroughput())); + return extensionTable; + } + + private void deleteExtensionTable(String tableName) { + getDynamoDbClient().deleteTable(r -> r.tableName(tableName)); + } + + @Test + public void documentSchema_withExtension_putAndUpdate_shouldSucceed() { + DynamoDbEnhancedClient extensionClient = createExtensionClient(); + DynamoDbTable extensionTable = createExtensionDocumentTable(extensionClient, "doc-extension-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument document = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("payload", "value") + .build(); + extensionTable.putItem(document); + extensionTable.updateItem(document); + + EnhancedDocument persisted = extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))); + assertThat(persisted, is(notNullValue())); + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchema_withExtension_shouldPreserveNonTimestampValues() { + DynamoDbEnhancedClient extensionClient = createExtensionClient(); + DynamoDbTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-integrity-table"); + String extensionTableName = extensionTable.tableName(); + + Map nested = new LinkedHashMap<>(); + nested.put("time", AttributeValue.fromS("nested-original")); + nested.put("flag", AttributeValue.fromS("x")); + + Map itemMap = new LinkedHashMap<>(); + itemMap.put("id", AttributeValue.fromS("doc-1")); + itemMap.put("time", AttributeValue.fromS("root-original")); + itemMap.put("payload", AttributeValue.fromM(nested)); + itemMap.put("records", AttributeValue.fromL(Collections.singletonList(AttributeValue.fromM(nested)))); + + EnhancedDocument document = EnhancedDocument.fromAttributeValueMap(itemMap).toBuilder() + .attributeConverterProviders(defaultProvider()) + .build(); + + extensionTable.putItem(document); + extensionTable.updateItem(document); + + EnhancedDocument persisted = extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))); + assertThat(persisted.toMap().get("time").s(), is("root-original")); + assertThat(persisted.toMap().get("payload").m().get("time").s(), is("nested-original")); + assertThat(persisted.toMap().get("records").l().get(0).m().get("time").s(), is("nested-original")); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchema_withExtension_deleteItem_shouldSucceed() { + DynamoDbEnhancedClient extensionClient = createExtensionClient(); + DynamoDbTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-delete-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument document = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("payload", "value") + .build(); + extensionTable.putItem(document); + extensionTable.deleteItem(r -> r.key(k -> k.partitionValue("doc-1"))); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))), is(nullValue())); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchemaBatchWrite_withExtension_shouldPreserveValuesAndReturnMetrics() { + DynamoDbEnhancedClient extensionClient = createExtensionClient(); + DynamoDbTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-batch-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument first = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("time", "value-one") + .build(); + EnhancedDocument second = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-2") + .putString("time", "value-two") + .build(); + + BatchWriteResult result = extensionClient.batchWriteItem(BatchWriteItemEnhancedRequest.builder() + .writeBatches( + WriteBatch.builder(EnhancedDocument.class) + .mappedTableResource(extensionTable) + .addPutItem(r -> r.item(first)) + .addPutItem(r -> r.item(second)) + .build()) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .build()); + + assertThat(result.consumedCapacity(), is(notNullValue())); + assertThat(result.itemCollectionMetrics(), is(notNullValue())); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).toMap().get("time").s(), is("value-one")); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-2"))).toMap().get("time").s(), is("value-two")); + + deleteExtensionTable(extensionTableName); + } + + @Test + public void documentSchemaTransactWrite_withExtension_shouldPreserveValuesAndReturnMetrics() { + DynamoDbEnhancedClient extensionClient = createExtensionClient(); + DynamoDbTable extensionTable = + createExtensionDocumentTable(extensionClient, "doc-extension-transact-table"); + String extensionTableName = extensionTable.tableName(); + + EnhancedDocument first = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-1") + .putString("time", "value-one") + .build(); + EnhancedDocument second = EnhancedDocument.builder() + .attributeConverterProviders(defaultProvider()) + .putString("id", "doc-2") + .putString("time", "value-two") + .build(); + + TransactWriteItemsEnhancedResponse response = + extensionClient.transactWriteItemsWithResponse(TransactWriteItemsEnhancedRequest.builder() + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .returnItemCollectionMetrics(ReturnItemCollectionMetrics.SIZE) + .addPutItem(extensionTable, first) + .addPutItem(extensionTable, second) + .build()); + + assertThat(response.consumedCapacity(), is(notNullValue())); + assertThat(response.itemCollectionMetrics(), is(notNullValue())); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-1"))).toMap().get("time").s(), is("value-one")); + assertThat(extensionTable.getItem(r -> r.key(k -> k.partitionValue("doc-2"))).toMap().get("time").s(), is("value-two")); + + deleteExtensionTable(extensionTableName); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/TimestampedRecord.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/TimestampedRecord.java new file mode 100644 index 000000000000..8f24b09db055 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/TimestampedRecord.java @@ -0,0 +1,63 @@ +/* + * 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.enhanced.dynamodb.functionaltests.models; + +import static software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension.AttributeTags.autoGeneratedTimestampAttribute; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; + +import java.time.Instant; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; + +/** + * Shared test record used by batch/transact write functional tests that exercise + * {@link software.amazon.awssdk.enhanced.dynamodb.extensions.AutoGeneratedTimestampRecordExtension}. + */ +public class TimestampedRecord { + public static final TableSchema TABLE_SCHEMA = + StaticTableSchema.builder(TimestampedRecord.class) + .newItemSupplier(TimestampedRecord::new) + .addAttribute(String.class, a -> a.name("id") + .getter(TimestampedRecord::getId) + .setter(TimestampedRecord::setId) + .tags(primaryPartitionKey())) + .addAttribute(Instant.class, a -> a.name("time") + .getter(TimestampedRecord::getTime) + .setter(TimestampedRecord::setTime) + .tags(autoGeneratedTimestampAttribute())) + .build(); + + private String id; + private Instant time; + + public String getId() { + return id; + } + + public TimestampedRecord setId(String id) { + this.id = id; + return this; + } + + public Instant getTime() { + return time; + } + + public TimestampedRecord setTime(Instant time) { + this.time = time; + return this; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/UnsupportedConverterTableSchema.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/UnsupportedConverterTableSchema.java new file mode 100644 index 000000000000..d1d2fc7e3dae --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/functionaltests/models/UnsupportedConverterTableSchema.java @@ -0,0 +1,98 @@ +/* + * 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.enhanced.dynamodb.functionaltests.models; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableMetadata; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +/** + * Pass-through map schema that intentionally keeps the default {@link TableSchema#converterForAttribute(Object)} + * implementation, which throws {@link UnsupportedOperationException}. + */ +@SuppressWarnings("unchecked") +public final class UnsupportedConverterTableSchema implements TableSchema> { + private final TableMetadata tableMetadata = StaticTableMetadata.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), "pk", + AttributeValueType.S) + .build(); + + @Override + public Map mapToItem(Map attributeMap) { + return attributeMap == null ? Collections.emptyMap() : new HashMap<>(attributeMap); + } + + @Override + public Map itemToMap(Map item, boolean ignoreNulls) { + if (item == null) { + return Collections.emptyMap(); + } + + if (!ignoreNulls) { + return new HashMap<>(item); + } + + return item.entrySet() + .stream() + .filter(e -> e.getValue() != null && !Boolean.TRUE.equals(e.getValue().nul())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Override + public Map itemToMap(Map item, Collection attributes) { + if (item == null || attributes == null) { + return Collections.emptyMap(); + } + + return attributes.stream() + .filter(item::containsKey) + .collect(Collectors.toMap(a -> a, item::get)); + } + + @Override + public AttributeValue attributeValue(Map item, String attributeName) { + return item == null ? null : item.get(attributeName); + } + + @Override + public TableMetadata tableMetadata() { + return tableMetadata; + } + + @Override + public EnhancedType> itemType() { + return (EnhancedType>) (EnhancedType) EnhancedType.of(Map.class); + } + + @Override + public List attributeNames() { + return Collections.singletonList("pk"); + } + + @Override + public boolean isAbstract() { + return false; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtilsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtilsTest.java new file mode 100644 index 000000000000..b8a100e3d4ac --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/SearchVectorUtilsTest.java @@ -0,0 +1,103 @@ +/* + * 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.enhanced.dynamodb.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; + +public class SearchVectorUtilsTest { + + @Test + public void toSearchVector_fromFloatArray() { + List result = SearchVectorUtils.toSearchVector(new float[] {1.0f, 2.5f, -3.25f}); + + assertThat(result).hasSize(3); + assertThat(result.get(0).n()).isEqualTo("1.0"); + assertThat(result.get(1).n()).isEqualTo("2.5"); + assertThat(result.get(2).n()).isEqualTo("-3.25"); + } + + @Test + public void toSearchVector_fromFloatList() { + List result = SearchVectorUtils.toSearchVector(Arrays.asList(1.0f, 0.5f)); + + assertThat(result).hasSize(2); + assertThat(result.get(0).n()).isEqualTo("1.0"); + assertThat(result.get(1).n()).isEqualTo("0.5"); + } + + @Test + public void toSearchVector_nullFloatArray_returnsNull() { + List result = SearchVectorUtils.toSearchVector((float[]) null); + + assertThat(result).isNull(); + } + + @Test + public void toSearchVector_nullFloatList_returnsNull() { + List result = SearchVectorUtils.toSearchVector((List) null); + + assertThat(result).isNull(); + } + + @Test + public void toSearchVector_emptyFloatArray_returnsEmptyList() { + List result = SearchVectorUtils.toSearchVector(new float[0]); + + assertThat(result.isEmpty()).isTrue(); + } + + @Test + public void toSearchVector_emptyFloatList_returnsEmptyList() { + List result = SearchVectorUtils.toSearchVector(Collections.emptyList()); + + assertThat(result.isEmpty()).isTrue(); + } + + @Test + public void toSearchVector_nanInFloatArray_throwsIllegalArgumentException() { + assertThatThrownBy(() -> SearchVectorUtils.toSearchVector(new float[] {1.0f, Float.NaN})) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("NaN is not supported by the default converters."); + } + + @Test + public void toSearchVector_infinityInFloatArray_throwsIllegalArgumentException() { + assertThatThrownBy(() -> SearchVectorUtils.toSearchVector(new float[] {Float.POSITIVE_INFINITY})) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Infinite numbers are not supported by the default converters."); + } + + @Test + public void toSearchVector_nanInFloatList_throwsIllegalArgumentException() { + assertThatThrownBy(() -> SearchVectorUtils.toSearchVector(Arrays.asList(1.0f, Float.NaN))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("NaN is not supported by the default converters."); + } + + @Test + public void toSearchVector_infinityInFloatList_throwsIllegalArgumentException() { + assertThatThrownBy(() -> SearchVectorUtils.toSearchVector(Arrays.asList(Float.NEGATIVE_INFINITY))) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Infinite numbers are not supported by the default converters."); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndicesTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndicesTest.java new file mode 100644 index 000000000000..4eff1d85435d --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/TableVectorIndicesTest.java @@ -0,0 +1,171 @@ +/* + * 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.enhanced.dynamodb.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.HASH; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.INLINE_FILTER; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; + +public class TableVectorIndicesTest { + + @Test + public void enhancedVectorIndices_convertsCorrectly() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder() + .projectionType(ProjectionType.ALL) + .build()) + .searchSchemaElements(Arrays.asList( + SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(HASH) + .build(), + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(INLINE_FILTER) + .build())) + .build(); + + TableVectorIndices tableVectorIndices = new TableVectorIndices(Collections.singletonList(metadata)); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).hasSize(1); + EnhancedVectorIndex index = result.get(0); + assertThat(index.indexName()).isEqualTo("embeddings-index"); + assertThat(index.vectorAttributeName()).isEqualTo("embedding"); + assertThat(index.dimensions()).isEqualTo(1536); + assertThat(index.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(index.projection().projectionType()).isEqualTo(ProjectionType.ALL); + assertThat(index.searchSchemaElements()).hasSize(2); + assertThat(index.searchSchemaElements().get(0).attributeName()).isEqualTo("pk"); + assertThat(index.searchSchemaElements().get(0).searchSchemaElementType()).isEqualTo(HASH); + assertThat(index.searchSchemaElements().get(1).attributeName()).isEqualTo("category"); + assertThat(index.searchSchemaElements().get(1).searchSchemaElementType()).isEqualTo(INLINE_FILTER); + } + + @Test + public void enhancedVectorIndices_defaultProjectionAll() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .indexName("no-proj-index") + .vectorAttributeName("vec") + .dimensions(128) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + TableVectorIndices tableVectorIndices = new TableVectorIndices(Collections.singletonList(metadata)); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).hasSize(1); + assertThat(result.get(0).projection()).isNull(); + } + + @Test + public void enhancedVectorIndices_emptyList_returnsEmpty() { + TableVectorIndices tableVectorIndices = new TableVectorIndices(Collections.emptyList()); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).isEmpty(); + } + + @Test + public void enhancedVectorIndices_nullList_returnsEmpty() { + TableVectorIndices tableVectorIndices = new TableVectorIndices(null); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).isEmpty(); + } + + @Test + public void enhancedVectorIndices_nullSearchSchema_omitted() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .indexName("minimal-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + TableVectorIndices tableVectorIndices = new TableVectorIndices(Collections.singletonList(metadata)); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).hasSize(1); + assertThat(result.get(0).searchSchemaElements()).isEmpty(); + } + + @Test + public void enhancedVectorIndices_multipleIndices_convertsAll() { + VectorIndexMetadata first = VectorIndexMetadata.builder() + .indexName("index-1") + .vectorAttributeName("vec1") + .dimensions(128) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + VectorIndexMetadata second = VectorIndexMetadata.builder() + .indexName("index-2") + .vectorAttributeName("vec2") + .dimensions(256) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + VectorIndexMetadata third = VectorIndexMetadata.builder() + .indexName("index-3") + .vectorAttributeName("vec3") + .dimensions(512) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + TableVectorIndices tableVectorIndices = new TableVectorIndices(Arrays.asList(first, second, third)); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).hasSize(3); + assertThat(result.get(0).indexName()).isEqualTo("index-1"); + assertThat(result.get(1).indexName()).isEqualTo("index-2"); + assertThat(result.get(2).indexName()).isEqualTo("index-3"); + } + + @Test + public void enhancedVectorIndices_preservesExplicitProjection() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .indexName("keys-only-index") + .vectorAttributeName("vec") + .dimensions(768) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder() + .projectionType(ProjectionType.KEYS_ONLY) + .build()) + .build(); + + TableVectorIndices tableVectorIndices = new TableVectorIndices(Collections.singletonList(metadata)); + List result = tableVectorIndices.enhancedVectorIndices(); + + assertThat(result).hasSize(1); + assertThat(result.get(0).projection().projectionType()).isEqualTo(ProjectionType.KEYS_ONLY); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtilsTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtilsTest.java new file mode 100644 index 000000000000..ee28782ea992 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/VectorIndexUtilsTest.java @@ -0,0 +1,191 @@ +/* + * 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.enhanced.dynamodb.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.HASH; +import static software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType.INLINE_FILTER; + +import org.junit.Test; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; +import software.amazon.awssdk.services.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.services.dynamodb.model.VectorDistanceFunction; +import software.amazon.awssdk.services.dynamodb.model.VectorIndex; + +public class VectorIndexUtilsTest { + + @Test + public void toVectorIndex_mapsAllFields() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder() + .projectionType(ProjectionType.ALL) + .build()) + .addSearchSchemaElement(b -> b.attributeName("id") + .searchSchemaElementType(HASH)) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType(INLINE_FILTER)) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.indexName()).isEqualTo("embeddings-index"); + assertThat(vectorIndex.vectorAttribute().attributeName()).isEqualTo("embedding"); + assertThat(vectorIndex.dimensions()).isEqualTo(1536L); + assertThat(vectorIndex.distanceFunction()).isEqualTo(VectorDistanceFunction.COSINE); + assertThat(vectorIndex.projection().projectionType()).isEqualTo(ProjectionType.ALL); + assertThat(vectorIndex.searchSchema()).hasSize(2); + assertThat(vectorIndex.searchSchema().get(0).attributeName()).isEqualTo("id"); + assertThat(vectorIndex.searchSchema().get(0).searchSchemaElementType()).isEqualTo(SearchSchemaElementType.HASH); + assertThat(vectorIndex.searchSchema().get(1).attributeName()).isEqualTo("category"); + assertThat(vectorIndex.searchSchema().get(1).searchSchemaElementType()).isEqualTo(SearchSchemaElementType.INLINE_FILTER); + } + + @Test + public void toVectorIndex_emptySearchSchema_omitsSearchSchemaField() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("simple-index") + .vectorAttributeName("vec") + .dimensions(128) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .projection(Projection.builder() + .projectionType(ProjectionType.KEYS_ONLY) + .build()) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.indexName()).isEqualTo("simple-index"); + assertThat(vectorIndex.dimensions()).isEqualTo(128L); + assertThat(vectorIndex.hasSearchSchema()).isFalse(); + } + + @Test + public void toVectorIndex_dotProduct_mapsDistanceFunction() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("dp-index") + .vectorAttributeName("vec") + .dimensions(256) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.distanceFunction()).isEqualTo(VectorDistanceFunction.DOT_PRODUCT); + } + + @Test + public void toVectorIndex_nullProjection_defaultsToAll() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("no-proj-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.projection().projectionType()).isEqualTo(ProjectionType.ALL); + } + + @Test + public void toVectorIndex_nullDistanceFunction_returnsNullDistanceFunction() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("null-df-index") + .vectorAttributeName("vec") + .dimensions(64) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.distanceFunction()).isNull(); + } + + @Test + public void toVectorIndex_euclidean_mapsDistanceFunction() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("euclidean-index") + .vectorAttributeName("vec") + .dimensions(256) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.distanceFunction()).isEqualTo(VectorDistanceFunction.EUCLIDEAN); + } + + @Test + public void toVectorIndex_nullSearchSchemaElementType_returnsNullElementType() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("null-schema-type-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .addSearchSchemaElement(SearchSchemaElement.builder() + .attributeName( + "pk") + .build()) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.searchSchema()).hasSize(1); + assertThat(vectorIndex.searchSchema().get(0).attributeName()).isEqualTo("pk"); + assertThat(vectorIndex.searchSchema().get(0).searchSchemaElementType()).isNull(); + } + + @Test + public void toVectorIndex_hashSearchSchemaElementType_mapsToHash() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("hash-schema-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType(HASH)) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.searchSchema().get(0).searchSchemaElementType()) + .isEqualTo(SearchSchemaElementType.HASH); + } + + @Test + public void toVectorIndex_inlineFilterSearchSchemaElementType_mapsToInlineFilter() { + EnhancedVectorIndex enhancedVectorIndex = EnhancedVectorIndex.builder() + .indexName("filter-schema-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType(INLINE_FILTER)) + .build(); + + VectorIndex vectorIndex = VectorIndexUtils.toVectorIndex(enhancedVectorIndex); + + assertThat(vectorIndex.searchSchema().get(0).searchSchemaElementType()) + .isEqualTo(SearchSchemaElementType.INLINE_FILTER); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTableTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTableTest.java index 8d24d4a59411..5f157d967f63 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTableTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncTableTest.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.enhanced.dynamodb.internal.client; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,9 +33,16 @@ import org.mockito.junit.MockitoJUnitRunner; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithIndices; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse; @@ -175,4 +183,116 @@ public void createTable_groupsSecondaryIndexesExistingInTableSchema() { .collect(Collectors.toList()); assertThat(globalIndicesNames).containsExactlyInAnyOrder("gsi_1", "gsi_2"); } + + @Test + public void vectorIndex_constructsCorrectMappedVectorIndex() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbAsyncTable table = + new DefaultDynamoDbAsyncTable<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + DefaultDynamoDbAsyncVectorIndex vectorIndex = table.vectorIndex("embeddings-index"); + + assertThat(vectorIndex.tableSchema()).isSameAs(tableSchema); + assertThat(vectorIndex.tableName()).isEqualTo(TABLE_NAME); + assertThat(vectorIndex.indexName()).isEqualTo("embeddings-index"); + } + + @Test + public void vectorIndex_invalidIndex_throwsIllegalArgumentException() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbAsyncTable table = + new DefaultDynamoDbAsyncTable<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + assertThatThrownBy(() -> table.vectorIndex("nonexistent")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("nonexistent"); + } + + @Test + public void vectorIndex_returnsMapperExtension() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbAsyncTable table = + new DefaultDynamoDbAsyncTable<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + DefaultDynamoDbAsyncVectorIndex vectorIndex = table.vectorIndex("embeddings-index"); + + assertThat(vectorIndex.mapperExtension()).isSameAs(mockDynamoDbEnhancedClientExtension); + } + + @Test + public void createTable_noArg_includesVectorIndexesFromMetadata() { + TableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey( + TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .vectorIndex(b -> b.indexName("vec-index") + .vectorAttributeName("emb") + .dimensions(128) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbAsyncTable table = + new DefaultDynamoDbAsyncTable<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + when(mockDynamoDbAsyncClient.createTable(any(CreateTableRequest.class))) + .thenReturn(CompletableFuture.completedFuture(CreateTableResponse.builder().build())); + + table.createTable().join(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(CreateTableRequest.class); + verify(mockDynamoDbAsyncClient).createTable(captor.capture()); + + assertThat(captor.getValue().vectorIndexes()).hasSize(1); + assertThat(captor.getValue().vectorIndexes().get(0).indexName()).isEqualTo("vec-index"); + } + + @Test + public void createTable_noArg_noVectorMetadata_vectorIndexesEmpty() { + DefaultDynamoDbAsyncTable table = + new DefaultDynamoDbAsyncTable<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + FakeItem.getTableSchema(), + "test_table"); + + when(mockDynamoDbAsyncClient.createTable(any(CreateTableRequest.class))) + .thenReturn(CompletableFuture.completedFuture(CreateTableResponse.builder().build())); + + table.createTable().join(); + + ArgumentCaptor captor = ArgumentCaptor.forClass(CreateTableRequest.class); + verify(mockDynamoDbAsyncClient).createTable(captor.capture()); + + assertThat(captor.getValue().vectorIndexes()).isEmpty(); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndexTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndexTest.java new file mode 100644 index 000000000000..35e35cdbd131 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbAsyncVectorIndexTest.java @@ -0,0 +1,200 @@ +/* + * 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.enhanced.dynamodb.internal.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultDynamoDbAsyncVectorIndexTest { + private static final String TABLE_NAME = "table-name"; + private static final String VECTOR_INDEX_NAME = "vector-index-name"; + + @Mock + private DynamoDbAsyncClient mockDynamoDbAsyncClient; + + @Mock + private DynamoDbEnhancedClientExtension mockDynamoDbEnhancedClientExtension; + + private final TableSchema tableSchema = DocumentTableSchema.builder().build(); + + private DefaultDynamoDbAsyncVectorIndex createVectorIndex() { + return new DefaultDynamoDbAsyncVectorIndex<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME, + VECTOR_INDEX_NAME); + } + + @Test + public void searchVectorsWithResponse_createsOperationAndExecutes() { + SearchVectorsResponse serviceResponse = SearchVectorsResponse.builder() + .searchResults(Collections.emptyList()) + .build(); + when(mockDynamoDbAsyncClient.searchVectors(any(SearchVectorsRequest.class))) + .thenReturn(CompletableFuture.completedFuture(serviceResponse)); + + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(5) + .build(); + + SearchVectorsEnhancedResponse result = + vectorIndex.searchVectorsWithResponse(request).join(); + + assertThat(result).isNotNull(); + assertThat(result.results()).isEmpty(); + } + + @Test + public void searchVectorsWithResponse_consumerOverload() { + SearchVectorsResponse serviceResponse = SearchVectorsResponse.builder() + .searchResults(Collections.emptyList()) + .build(); + when(mockDynamoDbAsyncClient.searchVectors(any(SearchVectorsRequest.class))) + .thenReturn(CompletableFuture.completedFuture(serviceResponse)); + + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + SearchVectorsEnhancedResponse result = + vectorIndex.searchVectorsWithResponse(b -> b.searchVector(new float[] {1.0f, 2.0f}).topK(5)).join(); + + assertThat(result).isNotNull(); + assertThat(result.results()).isEmpty(); + } + + @Test + public void equals_sameObject_returnsTrue() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.equals(vectorIndex)).isTrue(); + } + + @Test + public void equals_equalObjects_returnsTrue() { + DefaultDynamoDbAsyncVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbAsyncVectorIndex vectorIndex2 = createVectorIndex(); + + assertThat(vectorIndex1).isEqualTo(vectorIndex2); + } + + @Test + public void equals_differentTableName_returnsFalse() { + DefaultDynamoDbAsyncVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbAsyncVectorIndex vectorIndex2 = + new DefaultDynamoDbAsyncVectorIndex<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + "different-table", + VECTOR_INDEX_NAME); + + assertThat(vectorIndex1).isNotEqualTo(vectorIndex2); + } + + @Test + public void equals_differentIndexName_returnsFalse() { + DefaultDynamoDbAsyncVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbAsyncVectorIndex vectorIndex2 = + new DefaultDynamoDbAsyncVectorIndex<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME, + "different-index"); + + assertThat(vectorIndex1).isNotEqualTo(vectorIndex2); + } + + @Test + public void equals_nullObject_returnsFalse() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex).isNotEqualTo(null); + } + + @Test + public void equals_differentClass_returnsFalse() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex).isNotEqualTo("a string"); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + DefaultDynamoDbAsyncVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbAsyncVectorIndex vectorIndex2 = createVectorIndex(); + + assertThat(vectorIndex1.hashCode()).isEqualTo(vectorIndex2.hashCode()); + } + + @Test + public void hashCode_differentObjects_differentHashCode() { + DefaultDynamoDbAsyncVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbAsyncVectorIndex vectorIndex2 = + new DefaultDynamoDbAsyncVectorIndex<>(mockDynamoDbAsyncClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + "different-table", + "different-index"); + + assertThat(vectorIndex1.hashCode()).isNotEqualTo(vectorIndex2.hashCode()); + } + + @Test + public void tableSchema_returnsSameInstance() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.tableSchema()).isSameAs(tableSchema); + } + + @Test + public void tableName_returnsCorrectValue() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.tableName()).isEqualTo(TABLE_NAME); + } + + @Test + public void indexName_returnsCorrectValue() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.indexName()).isEqualTo(VECTOR_INDEX_NAME); + } + + @Test + public void mapperExtension_returnsSameInstance() { + DefaultDynamoDbAsyncVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.mapperExtension()).isSameAs(mockDynamoDbEnhancedClientExtension); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTableTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTableTest.java index 069380956a8e..0c15776810ca 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTableTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbTableTest.java @@ -18,6 +18,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.sameInstance; import static org.mockito.Mockito.verify; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; @@ -32,17 +33,24 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithIndices; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SecondaryIndexBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SecondaryIndexMatchingTableKeyBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.VectorIndexBean; import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedGlobalSecondaryIndex; import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedLocalSecondaryIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; @RunWith(MockitoJUnitRunner.class) @@ -82,6 +90,133 @@ public void index_invalidIndex_throwsIllegalArgumentException() { dynamoDbMappedTable.index("invalid"); } + @Test + public void vectorIndex_constructsCorrectMappedVectorIndex() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbTable dynamoDbMappedTable = + new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + DefaultDynamoDbVectorIndex vectorIndex = dynamoDbMappedTable.vectorIndex("embeddings-index"); + + assertThat(vectorIndex.tableSchema(), is(sameInstance(tableSchema))); + assertThat(vectorIndex.indexName(), is("embeddings-index")); + assertThat(vectorIndex.tableName(), is(TABLE_NAME)); + } + + @Test(expected = IllegalArgumentException.class) + public void vectorIndex_invalidIndex_throwsIllegalArgumentException() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbTable dynamoDbMappedTable = + new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + dynamoDbMappedTable.vectorIndex("invalid"); + } + + @Test + public void vectorIndex_returnsMapperExtension() { + TableSchema tableSchema = DocumentTableSchema.builder() + .vectorIndex(b -> b.indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbTable dynamoDbMappedTable = + new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME); + + DefaultDynamoDbVectorIndex vectorIndex = dynamoDbMappedTable.vectorIndex("embeddings-index"); + + assertThat(vectorIndex.mapperExtension(), is(sameInstance(mockDynamoDbEnhancedClientExtension))); + } + + @Test + public void createTable_noArg_includesVectorIndexesFromMetadata() { + TableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey( + TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .vectorIndex(b -> b.indexName("vec-index") + .vectorAttributeName("emb") + .dimensions(128) + .distanceFunction( + DistanceFunction.COSINE)) + .build(); + DefaultDynamoDbTable table = + Mockito.spy(new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + tableSchema, + TABLE_NAME)); + + table.createTable(); + + CreateTableEnhancedRequest request = captureCreateTableRequest(table); + + assertThat(request.vectorIndexes(), is(notNullValue())); + assertThat(request.vectorIndexes().size(), is(1)); + EnhancedVectorIndex captured = request.vectorIndexes().iterator().next(); + assertThat(captured.indexName(), is("vec-index")); + assertThat(captured.vectorAttributeName(), is("emb")); + assertThat(captured.dimensions(), is(128)); + assertThat(captured.distanceFunction(), is(DistanceFunction.COSINE)); + } + + @Test + public void createTable_noArg_noVectorMetadata_vectorIndexesEmpty() { + DefaultDynamoDbTable table = + Mockito.spy(new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + FakeItem.getTableSchema(), + TABLE_NAME)); + + table.createTable(); + + CreateTableEnhancedRequest request = captureCreateTableRequest(table); + + assertThat(request.vectorIndexes().size(), is(0)); + } + + @Test + public void createTable_noArg_fromBeanWithVectorAnnotations_includesVectorIndexes() { + DefaultDynamoDbTable table = + Mockito.spy(new DefaultDynamoDbTable<>(mockDynamoDbClient, + mockDynamoDbEnhancedClientExtension, + TableSchema.fromBean(VectorIndexBean.class), + TABLE_NAME)); + + table.createTable(); + + CreateTableEnhancedRequest request = captureCreateTableRequest(table); + + assertThat(request.vectorIndexes().size(), is(1)); + EnhancedVectorIndex captured = request.vectorIndexes().iterator().next(); + assertThat(captured.indexName(), is("embedding-index")); + assertThat(captured.vectorAttributeName(), is("embedding")); + assertThat(captured.dimensions(), is(1536)); + assertThat(captured.distanceFunction(), is(DistanceFunction.COSINE)); + } + @Test public void keyFrom_primaryIndex_partitionAndSort() { FakeItemWithSort item = FakeItemWithSort.createUniqueFakeItemWithSort(); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndexTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndexTest.java new file mode 100644 index 000000000000..1762a1c55c79 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/client/DefaultDynamoDbVectorIndexTest.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.enhanced.dynamodb.internal.client; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Collections; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; + +@RunWith(MockitoJUnitRunner.class) +public class DefaultDynamoDbVectorIndexTest { + private static final String TABLE_NAME = "table-name"; + private static final String VECTOR_INDEX_NAME = "vector-index-name"; + + @Mock + private DynamoDbClient mockDynamoDbClient; + + @Mock + private DynamoDbEnhancedClientExtension mockExtension; + + private final TableSchema tableSchema = DocumentTableSchema.builder().build(); + + private DefaultDynamoDbVectorIndex createVectorIndex() { + return new DefaultDynamoDbVectorIndex<>(mockDynamoDbClient, mockExtension, tableSchema, + TABLE_NAME, VECTOR_INDEX_NAME); + } + + private DefaultDynamoDbVectorIndex createVectorIndex(String tableName, String indexName) { + return new DefaultDynamoDbVectorIndex<>(mockDynamoDbClient, mockExtension, tableSchema, + tableName, indexName); + } + + private void stubSearchVectors() { + when(mockDynamoDbClient.searchVectors(any(SearchVectorsRequest.class))) + .thenReturn(SearchVectorsResponse.builder() + .searchResults(Collections.emptyList()) + .build()); + } + + private SearchVectorsEnhancedRequest defaultRequest() { + return SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f, 3.0f}) + .topK(10) + .build(); + } + + @Test + public void searchVectorsWithResponse_createsOperationAndExecutes() { + stubSearchVectors(); + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + SearchVectorsEnhancedResponse response = + vectorIndex.searchVectorsWithResponse(defaultRequest()); + + assertThat(response.results()).isEmpty(); + verify(mockDynamoDbClient).searchVectors(any(SearchVectorsRequest.class)); + } + + @Test + public void searchVectorsWithResponse_consumerOverload() { + stubSearchVectors(); + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + SearchVectorsEnhancedResponse response = + vectorIndex.searchVectorsWithResponse( + b -> b.searchVector(new float[] {1.0f, 2.0f, 3.0f}).topK(10)); + + assertThat(response.results()).isEmpty(); + verify(mockDynamoDbClient).searchVectors(any(SearchVectorsRequest.class)); + } + + @Test + public void equals_sameObject_returnsTrue() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.equals(vectorIndex)).isTrue(); + } + + @Test + public void equals_equalObjects_returnsTrue() { + DefaultDynamoDbVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbVectorIndex vectorIndex2 = createVectorIndex(); + + assertThat(vectorIndex1.equals(vectorIndex2)).isTrue(); + } + + @Test + public void equals_differentTableName_returnsFalse() { + DefaultDynamoDbVectorIndex vectorIndex1 = createVectorIndex(TABLE_NAME, VECTOR_INDEX_NAME); + DefaultDynamoDbVectorIndex vectorIndex2 = createVectorIndex("other-table", VECTOR_INDEX_NAME); + + assertThat(vectorIndex1.equals(vectorIndex2)).isFalse(); + } + + @Test + public void equals_differentIndexName_returnsFalse() { + DefaultDynamoDbVectorIndex vectorIndex1 = createVectorIndex(TABLE_NAME, VECTOR_INDEX_NAME); + DefaultDynamoDbVectorIndex vectorIndex2 = createVectorIndex(TABLE_NAME, "other-index"); + + assertThat(vectorIndex1.equals(vectorIndex2)).isFalse(); + } + + @Test + public void equals_nullObject_returnsFalse() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.equals("not-a-vector-index")).isFalse(); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + DefaultDynamoDbVectorIndex vectorIndex1 = createVectorIndex(); + DefaultDynamoDbVectorIndex vectorIndex2 = createVectorIndex(); + + assertThat(vectorIndex1.hashCode()).isEqualTo(vectorIndex2.hashCode()); + } + + @Test + public void hashCode_differentObjects_differentHashCode() { + DefaultDynamoDbVectorIndex vectorIndex1 = createVectorIndex(TABLE_NAME, VECTOR_INDEX_NAME); + DefaultDynamoDbVectorIndex vectorIndex2 = createVectorIndex("other-table", "other-index"); + + assertThat(vectorIndex1.hashCode()).isNotEqualTo(vectorIndex2.hashCode()); + } + + @Test + public void tableSchema_returnsSameInstance() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.tableSchema()).isSameAs(tableSchema); + } + + @Test + public void tableName_returnsCorrectValue() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.tableName()).isEqualTo(TABLE_NAME); + } + + @Test + public void indexName_returnsCorrectValue() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.indexName()).isEqualTo(VECTOR_INDEX_NAME); + } + + @Test + public void mapperExtension_returnsSameInstance() { + DefaultDynamoDbVectorIndex vectorIndex = createVectorIndex(); + + assertThat(vectorIndex.mapperExtension()).isSameAs(mockExtension); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperationTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperationTest.java index 27ade077fba9..a98ab3617ec6 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperationTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/CreateTableOperationTest.java @@ -16,11 +16,14 @@ package software.amazon.awssdk.enhanced.dynamodb.internal.operations; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primarySortKey; import static software.amazon.awssdk.services.dynamodb.model.KeyType.HASH; import static software.amazon.awssdk.services.dynamodb.model.KeyType.RANGE; @@ -39,6 +42,9 @@ import software.amazon.awssdk.core.util.DefaultSdkAutoConstructList; import software.amazon.awssdk.enhanced.dynamodb.OperationContext; import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithBinaryKey; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithByteBufferKey; @@ -48,12 +54,16 @@ import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithMixedCompositeGsi; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithNumericSort; import software.amazon.awssdk.enhanced.dynamodb.mapper.ImmutableTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.mapper.StaticTableSchema; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.CompositeMetadataImmutable; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.CrossIndexImmutable; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MixedFlattenedImmutable; import software.amazon.awssdk.enhanced.dynamodb.model.CreateTableEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedGlobalSecondaryIndex; import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedLocalSecondaryIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; import software.amazon.awssdk.services.dynamodb.model.BillingMode; @@ -67,6 +77,8 @@ import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import software.amazon.awssdk.services.dynamodb.model.StreamSpecification; import software.amazon.awssdk.services.dynamodb.model.StreamViewType; +import software.amazon.awssdk.services.dynamodb.model.VectorDistanceFunction; +import software.amazon.awssdk.services.dynamodb.model.VectorIndex; @RunWith(MockitoJUnitRunner.class) @@ -881,4 +893,521 @@ public void generateRequest_immutableGsiWithMixedFlattenedKeys() { .collect(Collectors.toSet()); assertThat(sortKeyNames).containsExactlyInAnyOrder("rootKey2", "flatKey2"); } + + @Test + public void generateRequest_withVectorIndex() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "id", + AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), + "category", + AttributeValueType.S) + .build(); + Projection projection = Projection.builder().projectionType(ProjectionType.ALL).build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .projection(projection) + .addSearchSchemaElement(b -> b.attributeName("id") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.vectorIndexes().size()).isEqualTo(1); + VectorIndex sdkVectorIndex = request.vectorIndexes().get(0); + assertThat(sdkVectorIndex.indexName()).isEqualTo("embeddings-index"); + assertThat(sdkVectorIndex.vectorAttribute().attributeName()).isEqualTo("embedding"); + assertThat(sdkVectorIndex.dimensions()).isEqualTo(1536L); + assertThat(sdkVectorIndex.distanceFunction()).isEqualTo(VectorDistanceFunction.DOT_PRODUCT); + assertThat(sdkVectorIndex.projection()).isEqualTo(projection); + assertThat(sdkVectorIndex.searchSchema().size()).isEqualTo(2); + assertThat(sdkVectorIndex.searchSchema().get(0).attributeName()).isEqualTo("id"); + assertThat(sdkVectorIndex.searchSchema().get(0).searchSchemaElementTypeAsString()).isEqualTo("HASH"); + assertThat(sdkVectorIndex.searchSchema().get(1).attributeName()).isEqualTo("category"); + assertThat(sdkVectorIndex.searchSchema().get(1).searchSchemaElementTypeAsString()).isEqualTo("INLINE_FILTER"); + + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("category").attributeType(ScalarAttributeType.S).build()); + assertThat(request.globalSecondaryIndexes()).isEmpty(); + assertThat(request.localSecondaryIndexes()).isEmpty(); + } + + @Test + public void generateRequest_withVectorIndex_inlineFilterOnNonKeyAttribute() { + StaticTableSchema tableSchema = + StaticTableSchema.builder(ItemWithInlineFilterAttribute.class) + .newItemSupplier(ItemWithInlineFilterAttribute::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(ItemWithInlineFilterAttribute::getPk) + .setter(ItemWithInlineFilterAttribute::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(ItemWithInlineFilterAttribute::getSk) + .setter(ItemWithInlineFilterAttribute::setSk) + .tags(primarySortKey())) + .addAttribute(String.class, a -> a.name("category") + .getter(ItemWithInlineFilterAttribute::getCategory) + .setter(ItemWithInlineFilterAttribute::setCategory)) + .build(); + Projection projection = Projection.builder().projectionType(ProjectionType.ALL).build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("cosine-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(projection) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("pk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("sk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("category").attributeType(ScalarAttributeType.S).build()); + assertThat(request.vectorIndexes().get(0).searchSchema().size()).isEqualTo(2); + assertThat(request.vectorIndexes().get(0).searchSchema().get(1).attributeName()).isEqualTo("category"); + } + + @Test + public void generateRequest_withDocumentTableSchema_vectorIndex_inlineFilterOnNonKeyAttribute() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), + "sk", + AttributeValueType.S) + .build(); + Projection projection = Projection.builder().projectionType(ProjectionType.ALL).build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("cosine-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(projection) + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("pk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("sk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("category").attributeType(ScalarAttributeType.S).build()); + } + + @Test + public void generateRequest_withVectorIndexAndGsi() { + Projection projection = Projection.builder().projectionType(ProjectionType.ALL).build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(768) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .projection(projection) + .addSearchSchemaElement(b -> b.attributeName("id") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .addSearchSchemaElement(b -> b.attributeName("lsi_sort") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder() + .globalSecondaryIndices(EnhancedGlobalSecondaryIndex.builder() + .indexName("gsi_1") + .projection(projection) + .provisionedThroughput( + ProvisionedThroughput.builder() + .readCapacityUnits(1L) + .writeCapacityUnits(1L) + .build()) + .build()) + .vectorIndexes(vectorIndex) + .build()); + + CreateTableRequest request = operation.generateRequest(FakeItemWithIndices.getTableSchema(), + PRIMARY_CONTEXT, + null); + + assertThat(request.globalSecondaryIndexes().size()).isEqualTo(1); + assertThat(request.vectorIndexes().size()).isEqualTo(1); + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("sort").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("gsi_id").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("gsi_sort").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("lsi_sort").attributeType(ScalarAttributeType.S).build()); + } + + @Test + public void generateRequest_nullVectorIndexes_omitsFromRequest() { + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().build()); + + CreateTableRequest request = operation.generateRequest(FakeItem.getTableSchema(), PRIMARY_CONTEXT, null); + + assertThat(request.vectorIndexes()).isEmpty(); + } + + @Test + public void generateRequest_emptyVectorIndexes_omitsFromRequest() { + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(Collections.emptyList()).build()); + + CreateTableRequest request = operation.generateRequest(FakeItem.getTableSchema(), PRIMARY_CONTEXT, null); + + assertThat(request.vectorIndexes()).isEmpty(); + } + + @Test + public void generateRequest_multipleVectorIndexes() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "id", + AttributeValueType.S) + .build(); + EnhancedVectorIndex cosineIndex = EnhancedVectorIndex.builder() + .indexName("cosine-index") + .vectorAttributeName("embedding_a") + .dimensions(256) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder().projectionType(ProjectionType.ALL).build()) + .build(); + EnhancedVectorIndex euclideanIndex = EnhancedVectorIndex.builder() + .indexName("euclidean-index") + .vectorAttributeName("embedding_b") + .dimensions(512) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .projection(Projection.builder().projectionType(ProjectionType.KEYS_ONLY).build()) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(cosineIndex, euclideanIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.vectorIndexes().size()).isEqualTo(2); + assertThat(request.vectorIndexes().get(0).indexName()).isEqualTo("cosine-index"); + assertThat(request.vectorIndexes().get(1).indexName()).isEqualTo("euclidean-index"); + } + + @Test + public void generateRequest_vectorAttributeNotInAttributeDefinitions() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "id", + AttributeValueType.S) + .build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("vec-index") + .vectorAttributeName("embedding") + .dimensions(128) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder().projectionType(ProjectionType.ALL).build()) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + Set attributeNames = request.attributeDefinitions().stream() + .map(AttributeDefinition::attributeName) + .collect(Collectors.toSet()); + assertThat(attributeNames).doesNotContain("embedding"); + } + + @Test + public void generateRequest_vectorIndexEmptySearchSchema() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("no-schema-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .projection(Projection.builder().projectionType(ProjectionType.ALL).build()) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + VectorIndex sdkIndex = request.vectorIndexes().get(0); + assertThat(sdkIndex.hasSearchSchema()).isFalse(); + } + + @Test + public void generateRequest_vectorIndexNullProjection_defaultsToAll() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("default-proj-index") + .vectorAttributeName("vec") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.vectorIndexes().get(0).projection().projectionType()).isEqualTo(ProjectionType.ALL); + } + + @Test + public void generateRequest_noSearchSchema_onlyPrimaryKeysInAttributeDefinitions() { + StaticTableSchema tableSchema = + StaticTableSchema.builder(ItemWithInlineFilterAttribute.class) + .newItemSupplier(ItemWithInlineFilterAttribute::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(ItemWithInlineFilterAttribute::getPk) + .setter(ItemWithInlineFilterAttribute::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(ItemWithInlineFilterAttribute::getSk) + .setter(ItemWithInlineFilterAttribute::setSk) + .tags(primarySortKey())) + .build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("no-schema-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder().projectionType(ProjectionType.ALL).build()) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("pk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("sk").attributeType(ScalarAttributeType.S).build()); + assertThat(request.vectorIndexes().get(0).hasSearchSchema()).isFalse(); + } + + @Test + public void generateRequest_vectorIndexOnlyInlineFilter_mapsIndexWithoutHash() { + StaticTableSchema tableSchema = + StaticTableSchema.builder(ItemWithInlineFilterAttribute.class) + .newItemSupplier(ItemWithInlineFilterAttribute::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(ItemWithInlineFilterAttribute::getPk) + .setter(ItemWithInlineFilterAttribute::setPk) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("sk") + .getter(ItemWithInlineFilterAttribute::getSk) + .setter(ItemWithInlineFilterAttribute::setSk) + .tags(primarySortKey())) + .addAttribute(String.class, a -> a.name("category") + .getter(ItemWithInlineFilterAttribute::getCategory) + .setter(ItemWithInlineFilterAttribute::setCategory)) + .build(); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("inline-filter-only-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder().projectionType(ProjectionType.ALL).build()) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + VectorIndex sdkIndex = request.vectorIndexes().get(0); + assertThat(sdkIndex.searchSchema()).hasSize(1); + assertThat(sdkIndex.searchSchema().get(0).attributeName()).isEqualTo("category"); + assertThat(sdkIndex.searchSchema().get(0).searchSchemaElementTypeAsString()).isEqualTo("INLINE_FILTER"); + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("pk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("sk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("category").attributeType(ScalarAttributeType.S).build()); + } + + @Test + public void generateRequest_keyWithNonScalarType_documentTableSchemaFallsBackToString() { + DocumentTableSchema tableSchema = DocumentTableSchema.builder() + .addIndexPartitionKey(TableMetadata.primaryIndexName(), + "pk", + AttributeValueType.S) + .addIndexSortKey(TableMetadata.primaryIndexName(), + "boolKey", + AttributeValueType.BOOL) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().build()); + + CreateTableRequest request = operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null); + + assertThat(request.attributeDefinitions()).containsExactlyInAnyOrder( + AttributeDefinition.builder().attributeName("pk").attributeType(ScalarAttributeType.S).build(), + AttributeDefinition.builder().attributeName("boolKey").attributeType(ScalarAttributeType.S).build()); + } + + @Test + public void generateRequest_vectorSearchSchema_nonScalarConverterAttribute_throwsWhenScalarTypeIsNull() { + StaticTableSchema tableSchema = + StaticTableSchema.builder(ItemWithBooleanAttribute.class) + .newItemSupplier(ItemWithBooleanAttribute::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(ItemWithBooleanAttribute::getPk) + .setter(ItemWithBooleanAttribute::setPk) + .tags(primaryPartitionKey())) + .addAttribute(Boolean.class, a -> a.name("active") + .getter(ItemWithBooleanAttribute::getActive) + .setter(ItemWithBooleanAttribute::setActive)) + .build(); + + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("test-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder() + .projectionType(ProjectionType.ALL) + .build()) + .addSearchSchemaElement(b -> b.attributeName("active") + .searchSchemaElementType( + SearchSchemaElementType.INLINE_FILTER)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + assertThatThrownBy(() -> operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Attribute 'active' must be defined in the table schema as a scalar type (S, N, or B)") + .hasMessageContaining("found: BOOL"); + } + + @Test + public void generateRequest_vectorSearchSchema_undefinedAttribute_throwsWhenConverterIsNull() { + StaticTableSchema tableSchema = + StaticTableSchema.builder(ItemWithInlineFilterAttribute.class) + .newItemSupplier(ItemWithInlineFilterAttribute::new) + .addAttribute(String.class, a -> a.name("pk") + .getter(ItemWithInlineFilterAttribute::getPk) + .setter(ItemWithInlineFilterAttribute::setPk) + .tags(primaryPartitionKey())) + .build(); + + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("test-index") + .vectorAttributeName("embedding") + .dimensions(4) + .distanceFunction(DistanceFunction.COSINE) + .projection(Projection.builder() + .projectionType(ProjectionType.ALL) + .build()) + .addSearchSchemaElement(b -> b.attributeName("unknown_attr") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .build(); + + CreateTableOperation operation = CreateTableOperation.create( + CreateTableEnhancedRequest.builder().vectorIndexes(vectorIndex).build()); + + assertThatThrownBy(() -> operation.generateRequest(tableSchema, PRIMARY_CONTEXT, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Attribute 'unknown_attr' must be defined in the table schema as a scalar type (S, N, or B)") + .hasMessageContaining("found: UNDEFINED"); + } + + static class ItemWithBooleanAttribute { + private String pk; + private Boolean active; + + public String getPk() { + return pk; + } + + public void setPk(String pk) { + this.pk = pk; + } + + public Boolean getActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + } + + static class ItemWithInlineFilterAttribute { + private String pk; + private String sk; + private String category; + + public String getPk() { + return pk; + } + + public void setPk(String pk) { + this.pk = pk; + } + + public String getSk() { + return sk; + } + + public void setSk(String sk) { + this.sk = sk; + } + + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationNameTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationNameTest.java index f79ce5a1649a..4e7f9003a5a7 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationNameTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/OperationNameTest.java @@ -37,6 +37,7 @@ public void values_returnsExpectedConstantsInDeclarationOrder() { OperationName.QUERY, OperationName.PUT_ITEM, OperationName.SCAN, + OperationName.SEARCH_VECTORS, OperationName.TRANSACT_GET_ITEMS, OperationName.TRANSACT_WRITE_ITEMS, OperationName.UPDATE_ITEM @@ -46,7 +47,7 @@ public void values_returnsExpectedConstantsInDeclarationOrder() { @Test public void label_returnsExpectedLabelForEachConstant() { int operationNameCount = OperationName.values().length; - assertEquals(14, operationNameCount); + assertEquals(15, operationNameCount); assertNull(OperationName.NONE.label()); assertEquals("BatchGetItem", OperationName.BATCH_GET_ITEM.label()); @@ -59,6 +60,7 @@ public void label_returnsExpectedLabelForEachConstant() { assertEquals("Query", OperationName.QUERY.label()); assertEquals("PutItem", OperationName.PUT_ITEM.label()); assertEquals("Scan", OperationName.SCAN.label()); + assertEquals("SearchVectors", OperationName.SEARCH_VECTORS.label()); assertEquals("TransactGetItems", OperationName.TRANSACT_GET_ITEMS.label()); assertEquals("TransactWriteItems", OperationName.TRANSACT_WRITE_ITEMS.label()); assertEquals("UpdateItem", OperationName.UPDATE_ITEM.label()); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperationTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperationTest.java new file mode 100644 index 000000000000..7869ec8b86e3 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/internal/operations/SearchVectorsOperationTest.java @@ -0,0 +1,489 @@ +/* + * 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.enhanced.dynamodb.internal.operations; + +import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClientExtension; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbExtensionContext; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; +import software.amazon.awssdk.enhanced.dynamodb.OperationContext; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.document.DocumentTableSchema; +import software.amazon.awssdk.enhanced.dynamodb.document.EnhancedDocument; +import software.amazon.awssdk.enhanced.dynamodb.extensions.ReadModification; +import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithIndices; +import software.amazon.awssdk.enhanced.dynamodb.internal.extensions.DefaultDynamoDbExtensionContext; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedRequest; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchVectorsEnhancedResponse; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; +import software.amazon.awssdk.services.dynamodb.model.SearchResultItem; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsRequest; +import software.amazon.awssdk.services.dynamodb.model.SearchVectorsResponse; +import software.amazon.awssdk.services.dynamodb.model.VectorCapacity; + +@RunWith(MockitoJUnitRunner.class) +public class SearchVectorsOperationTest { + private static final String TABLE_NAME = "table-name"; + private static final String VECTOR_INDEX_NAME = "embeddings-index"; + private static final OperationContext VECTOR_INDEX_CONTEXT = + DefaultOperationContext.create(TABLE_NAME, VECTOR_INDEX_NAME); + + private static final OperationContext PRIMARY_INDEX_CONTEXT = + DefaultOperationContext.create(TABLE_NAME, TableMetadata.primaryIndexName()); + + private static final OperationContext SECONDARY_INDEX_CONTEXT = + DefaultOperationContext.create(TABLE_NAME, "gsi_1"); + + @Mock + private DynamoDbClient mockDynamoDbClient; + + @Mock + private DynamoDbAsyncClient mockDynamoDbAsyncClient; + + @Mock + private DynamoDbEnhancedClientExtension mockExtension; + + @Test + public void generateRequest_mapsRequestFields() { + Expression condition = Expression.builder() + .expression("#category = :category") + .putExpressionName("#category", "category") + .putExpressionValue(":category", AttributeValue.fromS("books")) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(10) + .searchConditionExpression(condition) + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, + null); + + assertThat(request.tableName()).isEqualTo(TABLE_NAME); + assertThat(request.indexName()).isEqualTo(VECTOR_INDEX_NAME); + assertThat(request.topK()).isEqualTo(10); + assertThat(request.searchConditionExpression()).isEqualTo("#category = :category"); + assertThat(request.expressionAttributeNames().get("#category")).isEqualTo("category"); + assertThat(request.expressionAttributeValues().get(":category")).isEqualTo(AttributeValue.fromS("books")); + assertThat(request.searchVector()).hasSize(2); + assertThat(request.searchVector().get(0).n()).isEqualTo("1.0"); + assertThat(request.searchVector().get(1).n()).isEqualTo("2.0"); + } + + @Test + public void serviceCall_makesTheRightCallAndReturnsResponse() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + SearchVectorsRequest searchVectorsRequest = SearchVectorsRequest.builder().tableName(TABLE_NAME).build(); + SearchVectorsResponse expectedResponse = SearchVectorsResponse.builder().build(); + when(mockDynamoDbClient.searchVectors(any(SearchVectorsRequest.class))).thenReturn(expectedResponse); + + SearchVectorsResponse response = operation.serviceCall(mockDynamoDbClient).apply(searchVectorsRequest); + + assertThat(response).isSameAs(expectedResponse); + verify(mockDynamoDbClient).searchVectors(searchVectorsRequest); + } + + @Test + public void transformResponse_mapsItemsAndScores() { + Map itemMap = new HashMap<>(); + itemMap.put("id", AttributeValue.fromS("item-1")); + + SearchVectorsResponse response = SearchVectorsResponse.builder() + .searchResults(SearchResultItem.builder() + .item(itemMap) + .score(0.95) + .build()) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.results()).hasSize(1); + assertThat(enhancedResponse.results().get(0).score()).isEqualTo(0.95); + assertThat(enhancedResponse.results().get(0).item().getString("id")).isEqualTo("item-1"); + } + + @Test + public void operationName_isSearchVectors() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + assertThat(operation.operationName()).isEqualTo(OperationName.SEARCH_VECTORS); + } + + @Test + public void generateRequest_withPrimaryIndex_throwsIllegalArgumentException() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + assertThatThrownBy(() -> operation.generateRequest(DocumentTableSchema.builder().build(), + PRIMARY_INDEX_CONTEXT, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("SearchVectors cannot be executed against a primary index. A vector index name is required."); + } + + @Test + public void generateRequest_withSecondaryIndex_throwsIllegalArgumentException() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + assertThatThrownBy(() -> operation.generateRequest(FakeItemWithIndices.getTableSchema(), + SECONDARY_INDEX_CONTEXT, null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("SearchVectors cannot be executed against a secondary index."); + } + + @Test + public void generateRequest_minimalRequest_onlySearchVector() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {0.5f}) + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, null); + + assertThat(request.tableName()).isEqualTo(TABLE_NAME); + assertThat(request.indexName()).isEqualTo(VECTOR_INDEX_NAME); + assertThat(request.searchVector()).hasSize(1); + assertThat(request.topK()).isNull(); + assertThat(request.searchConditionExpression()).isNull(); + assertThat(request.projectionExpression()).isNull(); + assertThat(request.hasExpressionAttributeNames()).isFalse(); + assertThat(request.hasExpressionAttributeValues()).isFalse(); + } + + @Test + public void generateRequest_withReturnConsumedCapacity() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, null); + + assertThat(request.returnConsumedCapacityAsString()).isEqualTo("TOTAL"); + } + + @Test + public void generateRequest_withProjectionExpression() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .attributesToProject("title", "category") + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, null); + + assertThat(request.projectionExpression()).isEqualTo("#AMZN_MAPPED_title,#AMZN_MAPPED_category"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_title")).isEqualTo("title"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_category")).isEqualTo("category"); + } + + @Test + public void generateRequest_withNestedProjectionExpression() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .addNestedAttributeToProject( + NestedAttributeName.create("metadata", "author")) + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, null); + + assertThat(request.projectionExpression()).isEqualTo("#AMZN_MAPPED_metadata.#AMZN_MAPPED_author"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_metadata")).isEqualTo("metadata"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_author")).isEqualTo("author"); + } + + @Test + public void generateRequest_conditionAndProjection_mergesExpressionNames() { + Expression condition = Expression.builder() + .expression("#pk = :pk") + .putExpressionName("#pk", "partitionKey") + .putExpressionValue(":pk", AttributeValue.fromS("articles")) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .searchConditionExpression(condition) + .addNestedAttributeToProject( + NestedAttributeName.create("metadata", "title")) + .build()); + + SearchVectorsRequest request = operation.generateRequest(DocumentTableSchema.builder().build(), + VECTOR_INDEX_CONTEXT, null); + + // Both the condition name and projection names must be present + assertThat(request.expressionAttributeNames().get("#pk")).isEqualTo("partitionKey"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_metadata")).isEqualTo("metadata"); + assertThat(request.expressionAttributeNames().get("#AMZN_MAPPED_title")).isEqualTo("title"); + assertThat(request.searchConditionExpression()).isEqualTo("#pk = :pk"); + assertThat(request.projectionExpression()).isEqualTo("#AMZN_MAPPED_metadata.#AMZN_MAPPED_title"); + } + + @Test + public void transformResponse_nullSearchResults_returnsEmptyList() { + SearchVectorsResponse response = SearchVectorsResponse.builder().build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.results()).isEmpty(); + } + + @Test + public void transformResponse_emptySearchResults_returnsEmptyList() { + SearchVectorsResponse response = SearchVectorsResponse.builder() + .searchResults(Collections.emptyList()) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.results()).isEmpty(); + } + + @Test + public void transformResponse_nullScore_returnsNull() { + Map itemMap = new HashMap<>(); + itemMap.put("id", AttributeValue.fromS("item-1")); + + SearchVectorsResponse response = SearchVectorsResponse.builder() + .searchResults(SearchResultItem.builder() + .item(itemMap) + .build()) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.results().get(0).score()).isNull(); + } + + @Test + public void transformResponse_mapsConsumedCapacityToVectorCapacity() { + VectorCapacity vectorCapacity = VectorCapacity.builder() + .vectorSearchRequestBytes(42.0) + .build(); + + SearchVectorsResponse response = SearchVectorsResponse.builder() + .consumedCapacity(vectorCapacity) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.consumedCapacity()).isNotNull(); + assertThat(enhancedResponse.consumedCapacity().vectorSearchRequestBytes()).isEqualTo(42.0); + } + + @Test + public void transformResponse_nullConsumedCapacity_returnsNullVectorCapacity() { + SearchVectorsResponse response = SearchVectorsResponse.builder().build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, DocumentTableSchema.builder().build(), VECTOR_INDEX_CONTEXT, null); + + assertThat(enhancedResponse.consumedCapacity()).isNull(); + } + + @Test + public void asyncServiceCall_makesTheRightCallAndReturnsResponse() { + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + SearchVectorsRequest searchVectorsRequest = SearchVectorsRequest.builder().tableName(TABLE_NAME).build(); + SearchVectorsResponse expectedResponse = SearchVectorsResponse.builder().build(); + when(mockDynamoDbAsyncClient.searchVectors(any(SearchVectorsRequest.class))) + .thenReturn(CompletableFuture.completedFuture(expectedResponse)); + + CompletableFuture responseFuture = + operation.asyncServiceCall(mockDynamoDbAsyncClient).apply(searchVectorsRequest); + + assertThat(responseFuture.join()).isSameAs(expectedResponse); + verify(mockDynamoDbAsyncClient).searchVectors(searchVectorsRequest); + } + + @Test + public void transformResponse_withExtension_transformsSearchResultItems() { + FakeItemWithIndices originalItem = FakeItemWithIndices.builder() + .id("original-id") + .sort("original-sort") + .build(); + + Map originalItemMap = toAttributeValueMap(originalItem); + Map transformedItemMap = new HashMap<>(); + transformedItemMap.put("id", AttributeValue.fromS("transformed-id")); + transformedItemMap.put("sort", AttributeValue.fromS("transformed-sort")); + + when(mockExtension.afterRead(any(DynamoDbExtensionContext.AfterRead.class))) + .thenReturn(ReadModification.builder().transformedItem(transformedItemMap).build()); + + SearchVectorsResponse response = SearchVectorsResponse.builder() + .searchResults(SearchResultItem.builder() + .item(originalItemMap) + .score(0.75) + .build()) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + SearchVectorsEnhancedResponse enhancedResponse = + operation.transformResponse(response, + FakeItemWithIndices.getTableSchema(), + VECTOR_INDEX_CONTEXT, + mockExtension); + + assertThat(enhancedResponse.results()).hasSize(1); + assertThat(enhancedResponse.results().get(0).score()).isEqualTo(0.75); + FakeItemWithIndices resultItem = enhancedResponse.results().get(0).item(); + assertThat(resultItem.getId()).isEqualTo("transformed-id"); + assertThat(resultItem.getSort()).isEqualTo("transformed-sort"); + } + + @Test + public void transformResponse_withExtension_invokesAfterReadForEachResult() { + List originalItems = Arrays.asList( + FakeItemWithIndices.builder().id("item-1").sort("sort-1").build(), + FakeItemWithIndices.builder().id("item-2").sort("sort-2").build()); + + List> originalItemMaps = + originalItems.stream().map(SearchVectorsOperationTest::toAttributeValueMap).collect(toList()); + + ReadModification[] readModifications = originalItemMaps.stream() + .map(itemMap -> ReadModification.builder() + .transformedItem(itemMap) + .build()) + .toArray(ReadModification[]::new); + + when(mockExtension.afterRead(any(DynamoDbExtensionContext.AfterRead.class))) + .thenReturn(readModifications[0], Arrays.copyOfRange(readModifications, 1, readModifications.length)); + + SearchVectorsResponse response = SearchVectorsResponse.builder() + .searchResults(originalItemMaps.stream() + .map(itemMap -> + SearchResultItem.builder() + .item(itemMap) + .score(1.0) + .build()) + .collect(toList())) + .build(); + + SearchVectorsOperation operation = + SearchVectorsOperation.create(SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build()); + + operation.transformResponse(response, + FakeItemWithIndices.getTableSchema(), + VECTOR_INDEX_CONTEXT, + mockExtension); + + InOrder inOrder = inOrder(mockExtension); + originalItemMaps.forEach(itemMap -> inOrder.verify(mockExtension) + .afterRead(DefaultDynamoDbExtensionContext.builder() + .tableMetadata( + FakeItemWithIndices.getTableSchema() + .tableMetadata()) + .operationContext( + VECTOR_INDEX_CONTEXT) + .tableSchema( + FakeItemWithIndices.getTableSchema()) + .items(itemMap) + .build())); + } + + private static Map toAttributeValueMap(FakeItemWithIndices item) { + Map itemMap = new HashMap<>(); + itemMap.put("id", AttributeValue.fromS(item.getId())); + itemMap.put("sort", AttributeValue.fromS(item.getSort())); + return itemMap; + } +} \ No newline at end of file diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchemaTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchemaTest.java index 6b154c95f6c4..3671d60da1a5 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchemaTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/BeanTableSchemaTest.java @@ -25,6 +25,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; @@ -47,6 +48,7 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbFlatten; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.AbstractBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.AbstractImmutable; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.AbstractNestedImmutable; @@ -72,6 +74,8 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MapBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MixedCompositeBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MixedOrderingBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.InlineFilterOnlyVectorBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MultiVectorIndexBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.MultipleConverterProvidersBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.NestedBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.NestedBeanIgnoreNulls; @@ -89,6 +93,13 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.SortKeyBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.ThreeSortKeyBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.TwoPartitionKeyBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.VectorAndGsiBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.VectorIndexBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.VectorWithNestingBean; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; @RunWith(MockitoJUnitRunner.class) @@ -1438,6 +1449,185 @@ public void whenCreatingBeanTableSchema_logsDebugMessage() { } } + @Test + public void vectorIndexBean_producesCorrectVectorIndexMetadata() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorIndexBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactlyInAnyOrder( + SearchSchemaElement.builder().attributeName("category").searchSchemaElementType(SearchSchemaElementType.HASH).build(), + SearchSchemaElement.builder().attributeName("brand").searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER).build() + ); + } + + @Test + public void vectorIndexBean_vectorIndexNotInIndices() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorIndexBean.class); + + assertThat(beanTableSchema.tableMetadata().indices().stream() + .filter(i -> "embedding-index".equals(i.name())) + .findAny()).isEmpty(); + } + + @Test + public void multiVectorIndexBean_producesFiveVectorIndices() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(MultiVectorIndexBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(5); + Map byName = vectorIndices.stream() + .collect(java.util.stream.Collectors.toMap(VectorIndexMetadata::indexName, v -> v)); + + assertThat(byName.get("cosine-idx").dimensions()).isEqualTo(128); + assertThat(byName.get("cosine-idx").distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(byName.get("cosine-idx").vectorAttributeName()).isEqualTo("embeddingCosine"); + + assertThat(byName.get("dot-idx").dimensions()).isEqualTo(256); + assertThat(byName.get("dot-idx").distanceFunction()).isEqualTo(DistanceFunction.DOT_PRODUCT); + assertThat(byName.get("dot-idx").vectorAttributeName()).isEqualTo("embeddingDot"); + + assertThat(byName.get("euclidean-idx").dimensions()).isEqualTo(512); + assertThat(byName.get("euclidean-idx").distanceFunction()).isEqualTo(DistanceFunction.EUCLIDEAN); + assertThat(byName.get("euclidean-idx").vectorAttributeName()).isEqualTo("embeddingEuclidean"); + + assertThat(byName.get("cosine-idx-2").dimensions()).isEqualTo(1024); + assertThat(byName.get("cosine-idx-2").distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(byName.get("cosine-idx-2").vectorAttributeName()).isEqualTo("embeddingCosine2"); + + assertThat(byName.get("dot-idx-2").dimensions()).isEqualTo(1536); + assertThat(byName.get("dot-idx-2").distanceFunction()).isEqualTo(DistanceFunction.DOT_PRODUCT); + assertThat(byName.get("dot-idx-2").vectorAttributeName()).isEqualTo("embeddingDot2"); + } + + @Test + public void multiVectorIndexBean_sharedHashKeyAppliedToAllIndices() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(MultiVectorIndexBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + SearchSchemaElement expectedHash = SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + for (VectorIndexMetadata vi : vectorIndices) { + assertThat(vi.searchSchemaElements()).contains(expectedHash); + } + } + + @Test + public void vectorIndexBean_withGsiAnnotations_gsiStillWorksCorrectly() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorAndGsiBean.class); + TableMetadata tableMetadata = beanTableSchema.tableMetadata(); + + assertThat(tableMetadata.indexPartitionKey("gsi-category")).isEqualTo("category"); + assertThat(tableMetadata.indexSortKey("gsi-category")).isEqualTo(Optional.of("sortValue")); + + assertThat(tableMetadata.indices().stream() + .filter(i -> "embedding-index".equals(i.name())) + .findAny()).isEmpty(); + + Collection vectorIndices = tableMetadata.vectorIndices(); + assertThat(vectorIndices).hasSize(1); + assertThat(vectorIndices.iterator().next().indexName()).isEqualTo("embedding-index"); + } + + @Test + public void inlineFilterOnlyVectorBean_createsValidIndexWithoutHashKey() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(InlineFilterOnlyVectorBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactly( + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build() + ); + } + + @Test + public void vectorWithNestingBean_nestedBeanPresent_vectorMetadataCorrect() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorWithNestingBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactly( + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build() + ); + } + + @Test + public void vectorWithNestingBean_nestedImmutablePresent_vectorMetadataCorrect() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorWithNestingBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactly( + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build()); + } + + @Test + public void vectorWithNestingBean_nestedBeanNull_vectorMetadataCorrect() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorWithNestingBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactly( + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build()); + } + + @Test + public void vectorWithNestingBean_nestedImmutableNull_vectorMetadataCorrect() { + BeanTableSchema beanTableSchema = BeanTableSchema.create(VectorWithNestingBean.class); + Collection vectorIndices = beanTableSchema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices).hasSize(1); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName()).isEqualTo("embedding-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(1536); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.searchSchemaElements()).containsExactly( + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build()); + } + @DynamoDbBean public static class MultipleFlattenMapsBean { private String id; diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchemaTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchemaTest.java index 6ecf3fedb454..17a11d99fd70 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchemaTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/ImmutableTableSchemaTest.java @@ -25,6 +25,7 @@ import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -52,7 +53,12 @@ import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.NonSequentialOrderImmutable; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.OrderPreservationImmutable; import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.ToBuilderImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.testbeans.VectorIndexImmutable; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; import software.amazon.awssdk.enhanced.dynamodb.model.ImmutableCompositeKeyRecord; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; public class ImmutableTableSchemaTest { @@ -422,4 +428,60 @@ public void rootSchema_areCached_but_flattenedAreNot() { ImmutableTableSchema.create(ImmutableCompositeKeyRecord.class, ExecutionContext.FLATTENED); assertThat(root1, not(flattened)); } + + @Test + public void fromImmutable_vectorAnnotations_producesCorrectMetadata() { + ImmutableTableSchema schema = + ImmutableTableSchema.create(VectorIndexImmutable.class); + Collection vectorIndices = schema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices.size(), is(1)); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName(), is("embedding-index")); + assertThat(metadata.vectorAttributeName(), is("embedding")); + assertThat(metadata.dimensions(), is(1536)); + assertThat(metadata.distanceFunction(), is(DistanceFunction.COSINE)); + assertThat(metadata.searchSchemaElements(), org.hamcrest.Matchers.containsInAnyOrder( + SearchSchemaElement.builder().attributeName("category").searchSchemaElementType(SearchSchemaElementType.HASH).build(), + SearchSchemaElement.builder().attributeName("brand").searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER).build() + )); + } + + @Test + public void fromImmutable_vectorIndexNotInIndices() { + ImmutableTableSchema schema = + ImmutableTableSchema.create(VectorIndexImmutable.class); + + boolean found = schema.tableMetadata().indices().stream() + .anyMatch(i -> "embedding-index".equals(i.name())); + assertThat(found, is(false)); + } + + @Test + public void fromImmutable_withNestedBean_vectorMetadataCorrect() { + ImmutableTableSchema schema = + ImmutableTableSchema.create(VectorIndexImmutable.class); + Collection vectorIndices = schema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices.size(), is(1)); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName(), is("embedding-index")); + assertThat(metadata.vectorAttributeName(), is("embedding")); + assertThat(metadata.dimensions(), is(1536)); + assertThat(metadata.distanceFunction(), is(DistanceFunction.COSINE)); + } + + @Test + public void fromImmutable_withNestedBeanNull_vectorMetadataCorrect() { + ImmutableTableSchema schema = + ImmutableTableSchema.create(VectorIndexImmutable.class); + Collection vectorIndices = schema.tableMetadata().vectorIndices(); + + assertThat(vectorIndices.size(), is(1)); + VectorIndexMetadata metadata = vectorIndices.iterator().next(); + assertThat(metadata.indexName(), is("embedding-index")); + assertThat(metadata.vectorAttributeName(), is("embedding")); + assertThat(metadata.dimensions(), is(1536)); + assertThat(metadata.distanceFunction(), is(DistanceFunction.COSINE)); + } } diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadataTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadataTest.java index 2edaa9247dda..ccaca6c0ab22 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadataTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableMetadataTest.java @@ -23,6 +23,8 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.sameInstance; import static software.amazon.awssdk.enhanced.dynamodb.TableMetadata.primaryIndexName; +import static software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction.COSINE; +import static software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction.EUCLIDEAN; import java.util.Collection; import java.util.Collections; @@ -34,6 +36,9 @@ import org.junit.rules.ExpectedException; import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType; import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; public class StaticTableMetadataTest { @@ -542,6 +547,128 @@ public void setAndRetrieveCustomMetadataOfDifferentButAssignableType() { assertThat(tableMetadata.customMetadataObject("custom-key", Number.class), is(Optional.of(123.45f))); } + @Test + public void setAndRetrieveVectorIndex() { + VectorIndexMetadata vectorIndex = VectorIndexMetadata.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(COSINE) + .build(); + + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addVectorIndex(vectorIndex) + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + assertThat(tableMetadata.vectorIndices(), contains(vectorIndex)); + assertThat(tableMetadata.indices().stream().anyMatch(index -> "embeddings-index".equals(index.name())), is(false)); + } + + @Test + public void addVectorIndex_fromEnhancedVectorIndex() { + EnhancedVectorIndex enhancedVectorIndex = + EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(768) + .distanceFunction(EUCLIDEAN) + .addSearchSchemaElement(b -> b.attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.HASH)) + .build(); + + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addVectorIndex(enhancedVectorIndex) + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + assertThat(tableMetadata.vectorIndices(), + contains(VectorIndexMetadata.fromEnhancedVectorIndex(enhancedVectorIndex))); + } + + @Test + public void addDuplicateVectorIndex_throws() { + VectorIndexMetadata vectorIndex = VectorIndexMetadata.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(COSINE) + .build(); + + StaticTableMetadata.Builder builder = StaticTableMetadata.builder().addVectorIndex(vectorIndex); + + exception.expect(IllegalArgumentException.class); + exception.expectMessage("Attempt to add a vector index that has already been added. Vector index name: embeddings-index"); + + builder.addVectorIndex(vectorIndex); + } + + @Test + public void mergeVectorIndices() { + VectorIndexMetadata vectorIndex = VectorIndexMetadata.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(COSINE) + .build(); + + StaticTableMetadata original = StaticTableMetadata.builder() + .addIndexPartitionKey(primaryIndexName(), "id", AttributeValueType.S) + .addVectorIndex(vectorIndex) + .build(); + + StaticTableMetadata merged = StaticTableMetadata.builder() + .mergeWith(original) + .build(); + + assertThat(merged, is(original)); + assertThat(merged.vectorIndices(), contains(vectorIndex)); + } + + @Test + public void mergeWithDuplicateVectorIndex() { + VectorIndexMetadata vectorIndex = VectorIndexMetadata.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(COSINE) + .build(); + + StaticTableMetadata.Builder builder = StaticTableMetadata.builder().addVectorIndex(vectorIndex); + + exception.expect(IllegalArgumentException.class); + exception.expectMessage("Attempt to add a vector index that has already been added. " + + "Vector index name: embeddings-index"); + + builder.mergeWith(builder.build()).build(); + } + + @Test + public void mergeWith_mergesPartialVectorIndexMetadataIntoSingleIndex() { + StaticTableMetadata hashOnly = StaticTableMetadata.builder() + .addSearchVectorsHashKey("idx", "category") + .build(); + + StaticTableMetadata vectorOnly = StaticTableMetadata.builder() + .setVectorAttribute("idx", "embedding", 1536, COSINE) + .build(); + + StaticTableMetadata merged = StaticTableMetadata.builder() + .mergeWith(hashOnly) + .mergeWith(vectorOnly) + .build(); + + assertThat(merged.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = merged.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.vectorAttributeName(), is("embedding")); + assertThat(vectorIndex.dimensions(), is(1536)); + assertThat(vectorIndex.distanceFunction(), is(COSINE)); + assertThat(vectorIndex.searchSchemaElements().size(), is(1)); + assertThat(vectorIndex.searchSchemaElements().get(0).attributeName(), is("category")); + assertThat(vectorIndex.searchSchemaElements().get(0).searchSchemaElementType(), is(SearchSchemaElementType.HASH)); + } + @Test public void mergeFullIntoEmpty() { StaticTableMetadata tableMetadata = StaticTableMetadata.builder() @@ -560,6 +687,149 @@ public void mergeFullIntoEmpty() { assertThat(mergedTableMetadata, is(tableMetadata)); } + @Test + public void addSearchVectorsHashKey_createsVectorIndexWithHashElement() { + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addSearchVectorsHashKey("idx", "category") + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = tableMetadata.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.searchSchemaElements().size(), is(1)); + assertThat(vectorIndex.searchSchemaElements().get(0).attributeName(), is("category")); + assertThat(vectorIndex.searchSchemaElements().get(0).searchSchemaElementType(), is(SearchSchemaElementType.HASH)); + } + + @Test + public void addSearchVectorsInlineFilterKey_createsVectorIndexWithInlineFilterElement() { + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addSearchVectorsInlineFilterKey("idx", "category") + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = tableMetadata.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.searchSchemaElements().size(), is(1)); + assertThat(vectorIndex.searchSchemaElements().get(0).attributeName(), is("category")); + assertThat(vectorIndex.searchSchemaElements().get(0).searchSchemaElementType(), + is(SearchSchemaElementType.INLINE_FILTER)); + } + + @Test + public void setVectorAttribute_setsVectorConfiguration() { + TableMetadata tableMetadata = StaticTableMetadata.builder() + .setVectorAttribute("idx", "embedding", 1536, COSINE) + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = tableMetadata.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.vectorAttributeName(), is("embedding")); + assertThat(vectorIndex.dimensions(), is(1536)); + assertThat(vectorIndex.distanceFunction(), is(COSINE)); + } + + @Test + public void setVectorAttribute_duplicateVectorAttribute_throws() { + StaticTableMetadata.Builder builder = StaticTableMetadata.builder() + .setVectorAttribute("idx", "embedding", 1536, COSINE); + + assertThatThrownBy(() -> builder.setVectorAttribute("idx", "otherEmbedding", 768, EUCLIDEAN)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Attempt to set a vector attribute for a vector index that already has one. " + + "Vector index name: idx"); + } + + @Test + public void mergeWith_duplicateVectorAttribute_throws() { + StaticTableMetadata first = StaticTableMetadata.builder() + .setVectorAttribute("idx", "embedding", 1536, COSINE) + .build(); + + StaticTableMetadata second = StaticTableMetadata.builder() + .setVectorAttribute("idx", "otherEmbedding", 768, EUCLIDEAN) + .build(); + + assertThatThrownBy(() -> StaticTableMetadata.builder().mergeWith(first).mergeWith(second).build()) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Attempt to set a vector attribute for a vector index that already has one. " + + "Vector index name: idx"); + } + + @Test + public void incrementalBuild_multipleElements_sameIndex() { + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addSearchVectorsHashKey("idx", "category") + .addSearchVectorsInlineFilterKey("idx", "status") + .setVectorAttribute("idx", "embedding", 1536, COSINE) + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = tableMetadata.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.vectorAttributeName(), is("embedding")); + assertThat(vectorIndex.dimensions(), is(1536)); + assertThat(vectorIndex.distanceFunction(), is(COSINE)); + assertThat(vectorIndex.searchSchemaElements().size(), is(2)); + assertThat(vectorIndex.searchSchemaElements().get(0).searchSchemaElementType(), is(SearchSchemaElementType.HASH)); + assertThat(vectorIndex.searchSchemaElements().get(1).searchSchemaElementType(), is(SearchSchemaElementType.INLINE_FILTER)); + } + + @Test + public void incrementalBuild_multipleInlineFilters() { + TableMetadata tableMetadata = StaticTableMetadata.builder() + .addSearchVectorsInlineFilterKey("idx", "category") + .addSearchVectorsInlineFilterKey("idx", "status") + .build(); + + assertThat(tableMetadata.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = tableMetadata.vectorIndices().iterator().next(); + assertThat(vectorIndex.searchSchemaElements().size(), is(2)); + assertThat(vectorIndex.searchSchemaElements().get(0).attributeName(), is("category")); + assertThat(vectorIndex.searchSchemaElements().get(0).searchSchemaElementType(), + is(SearchSchemaElementType.INLINE_FILTER)); + assertThat(vectorIndex.searchSchemaElements().get(1).attributeName(), is("status")); + assertThat(vectorIndex.searchSchemaElements().get(1).searchSchemaElementType(), + is(SearchSchemaElementType.INLINE_FILTER)); + } + + @Test + public void incrementalBuild_conflictWithProgrammatic_throwsException() { + VectorIndexMetadata vectorIndex = VectorIndexMetadata.builder() + .indexName("idx") + .build(); + + exception.expect(IllegalArgumentException.class); + exception.expectMessage("defined both programmatically and via annotations"); + + StaticTableMetadata.builder() + .addVectorIndex(vectorIndex) + .addSearchVectorsHashKey("idx", "cat") + .build(); + } + + @Test + public void mergeWith_preservesIncrementalVectorIndices() { + StaticTableMetadata original = StaticTableMetadata.builder() + .addSearchVectorsHashKey("idx", "category") + .setVectorAttribute("idx", "embedding", 1536, COSINE) + .build(); + + StaticTableMetadata merged = StaticTableMetadata.builder() + .mergeWith(original) + .build(); + + assertThat(merged.vectorIndices().size(), is(1)); + VectorIndexMetadata vectorIndex = merged.vectorIndices().iterator().next(); + assertThat(vectorIndex.indexName(), is("idx")); + assertThat(vectorIndex.vectorAttributeName(), is("embedding")); + assertThat(vectorIndex.dimensions(), is(1536)); + assertThat(vectorIndex.distanceFunction(), is(COSINE)); + assertThat(vectorIndex.searchSchemaElements().size(), is(1)); + assertThat(vectorIndex.searchSchemaElements().get(0).attributeName(), is("category")); + } + @Test public void mergeEmptyIntoFull() { StaticTableMetadata emptyTableMetadata = StaticTableMetadata.builder().build(); diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchemaTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchemaTest.java index 33eea634a883..11844a169b1d 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchemaTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/StaticTableSchemaTest.java @@ -26,8 +26,12 @@ import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.nullAttributeValue; import static software.amazon.awssdk.enhanced.dynamodb.internal.AttributeValues.stringValue; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.primaryPartitionKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.searchVectorsHashKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.searchVectorsInlineFilterKey; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondaryPartitionKey; import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.secondarySortKey; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.vectorAttribute; +import static software.amazon.awssdk.enhanced.dynamodb.mapper.StaticAttributeTags.vectorIndexes; import java.math.BigDecimal; import java.util.Arrays; @@ -42,6 +46,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; +import java.util.function.Function; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -53,6 +58,11 @@ import software.amazon.awssdk.enhanced.dynamodb.AttributeConverterProvider; import software.amazon.awssdk.enhanced.dynamodb.EnhancedType; import software.amazon.awssdk.enhanced.dynamodb.TableMetadata; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; +import software.amazon.awssdk.enhanced.dynamodb.model.EnhancedVectorIndex; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElement; +import software.amazon.awssdk.enhanced.dynamodb.model.SearchSchemaElementType; +import software.amazon.awssdk.enhanced.dynamodb.model.VectorIndexMetadata; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItem; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemComposedClass; import software.amazon.awssdk.enhanced.dynamodb.functionaltests.models.FakeItemWithSort; @@ -1471,6 +1481,73 @@ public void buildConcreteAddTag() { assertThat(concreteTableSchema.tableMetadata().customMetadataObject(TABLE_TAG_KEY, String.class)).isEqualTo(Optional.of(TABLE_TAG_VALUE)); } + @Test + public void buildWithVectorIndexTag() { + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + StaticTableSchema tableSchema = + StaticTableSchema.builder(FakeDocument.class) + .newItemSupplier(FakeDocument::new) + .tags(vectorIndexes(vectorIndex)) + .build(); + + assertThat(tableSchema.tableMetadata().vectorIndices()).hasSize(1); + assertThat(tableSchema.tableMetadata().vectorIndices()) + .containsExactly(VectorIndexMetadata.fromEnhancedVectorIndex(vectorIndex)); + assertThat(tableSchema.tableMetadata().indices().stream() + .anyMatch(index -> "embeddings-index".equals(index.name()))).isFalse(); + } + + @Test + public void buildStaticImmutableWithVectorIndexTag() { + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("immutable-vec-index") + .vectorAttributeName("embedding") + .dimensions(384) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + StaticImmutableTableSchema tableSchema = + StaticImmutableTableSchema.builder(FakeDocument.class, FakeDocument.class) + .newItemBuilder(FakeDocument::new, Function.identity()) + .addAttribute(String.class, a -> a.name("documentString") + .getter(FakeDocument::getDocumentString) + .setter(FakeDocument::setDocumentString)) + .tags(vectorIndexes(vectorIndex)) + .build(); + + assertThat(tableSchema.tableMetadata().vectorIndices()).hasSize(1); + assertThat(tableSchema.tableMetadata().vectorIndices()) + .containsExactly(VectorIndexMetadata.fromEnhancedVectorIndex(vectorIndex)); + assertThat(tableSchema.tableMetadata().indices().stream() + .anyMatch(index -> "immutable-vec-index".equals(index.name()))).isFalse(); + } + + @Test + public void buildWithVectorIndexTag_collectionOverload() { + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("collection-vec-index") + .vectorAttributeName("embedding") + .dimensions(768) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + StaticTableSchema tableSchema = + StaticTableSchema.builder(FakeDocument.class) + .newItemSupplier(FakeDocument::new) + .tags(vectorIndexes(Collections.singletonList(vectorIndex))) + .build(); + + assertThat(tableSchema.tableMetadata().vectorIndices()).hasSize(1); + assertThat(tableSchema.tableMetadata().vectorIndices()) + .containsExactly(VectorIndexMetadata.fromEnhancedVectorIndex(vectorIndex)); + } + @Test public void instantiateFlattenedAbstractClassShouldThrowException() { StaticTableSchema superclassTableSchema = @@ -1851,4 +1928,219 @@ public void validCompositeKeysWithExplicitOrder_succeeds() { assertThat(schema.tableMetadata().indexPartitionKeys("test_gsi")).containsExactly("gsi_pk1", "gsi_pk2"); assertThat(schema.tableMetadata().indexSortKeys("test_gsi")).containsExactly("gsi_sk1", "gsi_sk2"); } + + @Test + public void buildWithSearchVectorsHashKeyTag_producesCorrectMetadata() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("cat") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(searchVectorsHashKey("idx"))) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(1); + VectorIndexMetadata vim = schema.tableMetadata().vectorIndices().iterator().next(); + assertThat(vim.indexName()).isEqualTo("idx"); + assertThat(vim.searchSchemaElements()).anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("cat"); + assertThat(e.searchSchemaElementType()).isEqualTo(SearchSchemaElementType.HASH); + }); + } + + @Test + public void buildWithSearchVectorsInlineFilterKeyTag_producesCorrectMetadata() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("brand") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(searchVectorsInlineFilterKey("idx"))) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(1); + VectorIndexMetadata vim = schema.tableMetadata().vectorIndices().iterator().next(); + assertThat(vim.indexName()).isEqualTo("idx"); + assertThat(vim.searchSchemaElements()).anySatisfy(e -> { + assertThat(e.attributeName()).isEqualTo("brand"); + assertThat(e.searchSchemaElementType()).isEqualTo(SearchSchemaElementType.INLINE_FILTER); + }); + } + + @Test + public void buildWithVectorAttributeTag_producesCorrectMetadata() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(1); + VectorIndexMetadata vim = schema.tableMetadata().vectorIndices().iterator().next(); + assertThat(vim.indexName()).isEqualTo("idx"); + assertThat(vim.vectorAttributeName()).isEqualTo("emb"); + assertThat(vim.dimensions()).isEqualTo(1536); + assertThat(vim.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + } + + @Test + public void buildWithAllVectorTags_producesCompleteVectorIndex() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("cat") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(searchVectorsHashKey("idx"))) + .addAttribute(String.class, a -> a.name("brand") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(searchVectorsInlineFilterKey("idx"))) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(1); + VectorIndexMetadata vim = schema.tableMetadata().vectorIndices().iterator().next(); + assertThat(vim.indexName()).isEqualTo("idx"); + assertThat(vim.vectorAttributeName()).isEqualTo("emb"); + assertThat(vim.dimensions()).isEqualTo(1536); + assertThat(vim.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(vim.searchSchemaElements()).hasSize(2); + assertThat(vim.searchSchemaElements()).contains( + SearchSchemaElement.builder().attributeName("cat").searchSchemaElementType(SearchSchemaElementType.HASH).build(), + SearchSchemaElement.builder().attributeName("brand").searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER).build()); + } + + @Test + public void buildWithMultipleVectorIndexTags_producesMultipleIndices() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb1") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx1", 768, + DistanceFunction.EUCLIDEAN))) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb2") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("idx2", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(2); + assertThat(schema.tableMetadata().vectorIndices()) + .extracting(VectorIndexMetadata::indexName) + .containsExactlyInAnyOrder("idx1", "idx2"); + } + + @Test + public void vectorAttributeTag_notInIndices() { + StaticTableSchema schema = + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeMappedItem::getAString) + .setter(FakeMappedItem::setAString) + .tags(primaryPartitionKey())) + .addAttribute(EnhancedType.setOf(Float.class), a -> a.name("emb") + .getter(FakeMappedItem::getAFloatSet) + .setter(FakeMappedItem::setAFloatSet) + .tags(vectorAttribute("vec-idx", 1536, + DistanceFunction.COSINE))) + .build(); + + assertThat(schema.tableMetadata().indices().stream() + .anyMatch(index -> "vec-idx".equals(index.name()))).isFalse(); + } + + @Test + public void buildStaticImmutable_withVectorTags_producesCorrectMetadata() { + StaticImmutableTableSchema schema = + StaticImmutableTableSchema.builder(FakeDocument.class, FakeDocument.class) + .newItemBuilder(FakeDocument::new, Function.identity()) + .addAttribute(String.class, a -> a.name("id") + .getter(FakeDocument::getDocumentString) + .setter(FakeDocument::setDocumentString) + .tags(primaryPartitionKey())) + .addAttribute(String.class, a -> a.name("cat") + .getter(FakeDocument::getDocumentString) + .setter(FakeDocument::setDocumentString) + .tags(searchVectorsHashKey("vi"))) + .addAttribute(String.class, a -> a.name("brand") + .getter(FakeDocument::getDocumentString) + .setter(FakeDocument::setDocumentString) + .tags(searchVectorsInlineFilterKey("vi"))) + .addAttribute(EnhancedType.listOf(Float.class), a -> a.name("emb") + .getter(d -> null) + .setter((d, v) -> { + }) + .tags(vectorAttribute("vi", 384, + DistanceFunction.DOT_PRODUCT))) + .build(); + + assertThat(schema.tableMetadata().vectorIndices()).hasSize(1); + VectorIndexMetadata vim = schema.tableMetadata().vectorIndices().iterator().next(); + assertThat(vim.indexName()).isEqualTo("vi"); + assertThat(vim.vectorAttributeName()).isEqualTo("emb"); + assertThat(vim.dimensions()).isEqualTo(384); + assertThat(vim.distanceFunction()).isEqualTo(DistanceFunction.DOT_PRODUCT); + assertThat(vim.searchSchemaElements()).hasSize(2); + assertThat(schema.tableMetadata().indices().stream() + .anyMatch(index -> "vi".equals(index.name()))).isFalse(); + } + + @Test + public void nonScalarAttributeAsKey_throwsIllegalArgumentException() { + exception.expect(IllegalArgumentException.class); + exception.expectMessage("is not a suitable type to be used as a key"); + + StaticTableSchema.builder(FakeMappedItem.class) + .newItemSupplier(FakeMappedItem::new) + .addAttribute(Boolean.class, a -> a.name("id") + .getter(FakeMappedItem::getABoolean) + .setter(FakeMappedItem::setABoolean) + .tags(primaryPartitionKey())) + .build(); + } } \ No newline at end of file diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/InlineFilterOnlyVectorBean.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/InlineFilterOnlyVectorBean.java new file mode 100644 index 000000000000..a8262ba73927 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/InlineFilterOnlyVectorBean.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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbBean +public class InlineFilterOnlyVectorBean { + private String id; + private String category; + private List embedding; + + @DynamoDbPartitionKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"embedding-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbVectorAttribute(indexName = "embedding-index", dimensions = 1536, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/MultiVectorIndexBean.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/MultiVectorIndexBean.java new file mode 100644 index 000000000000..a53d078899e7 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/MultiVectorIndexBean.java @@ -0,0 +1,97 @@ +/* + * 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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbBean +public class MultiVectorIndexBean { + private String id; + private String category; + private List embeddingCosine; + private List embeddingDot; + private List embeddingEuclidean; + private List embeddingCosine2; + private List embeddingDot2; + + @DynamoDbPartitionKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"cosine-idx", "dot-idx", "euclidean-idx", "cosine-idx-2", "dot-idx-2"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbVectorAttribute(indexName = "cosine-idx", dimensions = 128, distanceFunction = DistanceFunction.COSINE) + public List getEmbeddingCosine() { + return embeddingCosine; + } + + public void setEmbeddingCosine(List embeddingCosine) { + this.embeddingCosine = embeddingCosine; + } + + @DynamoDbVectorAttribute(indexName = "dot-idx", dimensions = 256, distanceFunction = DistanceFunction.DOT_PRODUCT) + public List getEmbeddingDot() { + return embeddingDot; + } + + public void setEmbeddingDot(List embeddingDot) { + this.embeddingDot = embeddingDot; + } + + @DynamoDbVectorAttribute(indexName = "euclidean-idx", dimensions = 512, distanceFunction = DistanceFunction.EUCLIDEAN) + public List getEmbeddingEuclidean() { + return embeddingEuclidean; + } + + public void setEmbeddingEuclidean(List embeddingEuclidean) { + this.embeddingEuclidean = embeddingEuclidean; + } + + @DynamoDbVectorAttribute(indexName = "cosine-idx-2", dimensions = 1024, distanceFunction = DistanceFunction.COSINE) + public List getEmbeddingCosine2() { + return embeddingCosine2; + } + + public void setEmbeddingCosine2(List embeddingCosine2) { + this.embeddingCosine2 = embeddingCosine2; + } + + @DynamoDbVectorAttribute(indexName = "dot-idx-2", dimensions = 1536, distanceFunction = DistanceFunction.DOT_PRODUCT) + public List getEmbeddingDot2() { + return embeddingDot2; + } + + public void setEmbeddingDot2(List embeddingDot2) { + this.embeddingDot2 = embeddingDot2; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorAndGsiBean.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorAndGsiBean.java new file mode 100644 index 000000000000..f6fcb43a0740 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorAndGsiBean.java @@ -0,0 +1,70 @@ +/* + * 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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbBean +public class VectorAndGsiBean { + private String id; + private String category; + private String sortValue; + private List embedding; + + @DynamoDbPartitionKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDbSecondaryPartitionKey(indexNames = {"gsi-category"}) + @DynamoDbSearchVectorsHashKey(indexNames = {"embedding-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbSecondarySortKey(indexNames = {"gsi-category"}) + public String getSortValue() { + return sortValue; + } + + public void setSortValue(String sortValue) { + this.sortValue = sortValue; + } + + @DynamoDbVectorAttribute(indexName = "embedding-index", dimensions = 1536, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexBean.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexBean.java new file mode 100644 index 000000000000..589994e76b62 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexBean.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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbBean +public class VectorIndexBean { + private String id; + private String category; + private String brand; + private List embedding; + + @DynamoDbPartitionKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"embedding-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"embedding-index"}) + public String getBrand() { + return brand; + } + + public void setBrand(String brand) { + this.brand = brand; + } + + @DynamoDbVectorAttribute(indexName = "embedding-index", dimensions = 1536, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexImmutable.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexImmutable.java new file mode 100644 index 000000000000..06ff5223a1fe --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorIndexImmutable.java @@ -0,0 +1,131 @@ +/* + * 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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import java.util.Objects; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbImmutable; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsInlineFilterKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbImmutable(builder = VectorIndexImmutable.Builder.class) +public class VectorIndexImmutable { + private final String id; + private final String category; + private final String brand; + private final List embedding; + private final AbstractBean innerBean; + + private VectorIndexImmutable(Builder b) { + this.id = b.id; + this.category = b.category; + this.brand = b.brand; + this.embedding = b.embedding; + this.innerBean = b.innerBean; + } + + @DynamoDbPartitionKey + public String id() { + return id; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"embedding-index"}) + public String category() { + return category; + } + + @DynamoDbSearchVectorsInlineFilterKey(indexNames = {"embedding-index"}) + public String brand() { + return brand; + } + + @DynamoDbVectorAttribute(indexName = "embedding-index", dimensions = 1536, distanceFunction = DistanceFunction.COSINE) + public List embedding() { + return embedding; + } + + public AbstractBean innerBean() { + return innerBean; + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + VectorIndexImmutable that = (VectorIndexImmutable) o; + return Objects.equals(id, that.id) + && Objects.equals(category, that.category) + && Objects.equals(brand, that.brand) + && Objects.equals(embedding, that.embedding) + && Objects.equals(innerBean, that.innerBean); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, brand, embedding, innerBean); + } + + public static final class Builder { + private String id; + private String category; + private String brand; + private List embedding; + private AbstractBean innerBean; + + private Builder() { + } + + public Builder id(String id) { + this.id = id; + return this; + } + + public Builder category(String category) { + this.category = category; + return this; + } + + public Builder brand(String brand) { + this.brand = brand; + return this; + } + + public Builder embedding(List embedding) { + this.embedding = embedding; + return this; + } + + public Builder innerBean(AbstractBean innerBean) { + this.innerBean = innerBean; + return this; + } + + public VectorIndexImmutable build() { + return new VectorIndexImmutable(this); + } + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorWithNestingBean.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorWithNestingBean.java new file mode 100644 index 000000000000..208a8a54833f --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/mapper/testbeans/VectorWithNestingBean.java @@ -0,0 +1,75 @@ +/* + * 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.enhanced.dynamodb.mapper.testbeans; + +import java.util.List; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSearchVectorsHashKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbVectorAttribute; +import software.amazon.awssdk.enhanced.dynamodb.model.DistanceFunction; + +@DynamoDbBean +public class VectorWithNestingBean { + private String id; + private String category; + private List embedding; + private AbstractBean innerBean; + private AbstractImmutable innerImmutable; + + @DynamoDbPartitionKey + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @DynamoDbSearchVectorsHashKey(indexNames = {"embedding-index"}) + public String getCategory() { + return category; + } + + public void setCategory(String category) { + this.category = category; + } + + @DynamoDbVectorAttribute(indexName = "embedding-index", dimensions = 1536, distanceFunction = DistanceFunction.COSINE) + public List getEmbedding() { + return embedding; + } + + public void setEmbedding(List embedding) { + this.embedding = embedding; + } + + public AbstractBean getInnerBean() { + return innerBean; + } + + public void setInnerBean(AbstractBean innerBean) { + this.innerBean = innerBean; + } + + public AbstractImmutable getInnerImmutable() { + return innerImmutable; + } + + public void setInnerImmutable(AbstractImmutable innerImmutable) { + this.innerImmutable = innerImmutable; + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequestTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequestTest.java index 4c4251262d59..c2cc1bb3b256 100644 --- a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequestTest.java +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/CreateTableEnhancedRequestTest.java @@ -22,11 +22,11 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; +import java.util.Arrays; import java.util.Collections; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; -import software.amazon.awssdk.services.dynamodb.model.LocalSecondaryIndex; import software.amazon.awssdk.services.dynamodb.model.Projection; import software.amazon.awssdk.services.dynamodb.model.ProjectionType; import software.amazon.awssdk.services.dynamodb.model.ProvisionedThroughput; @@ -40,6 +40,7 @@ public void builder_minimal() { assertThat(builtObject.globalSecondaryIndices(), is(nullValue())); assertThat(builtObject.localSecondaryIndices(), is(nullValue())); + assertThat(builtObject.vectorIndexes(), is(nullValue())); assertThat(builtObject.provisionedThroughput(), is(nullValue())); } @@ -55,14 +56,24 @@ public void builder_maximal() { EnhancedLocalSecondaryIndex localSecondaryIndex = EnhancedLocalSecondaryIndex.create( "lsi", Projection.builder().projectionType(ProjectionType.ALL).build()); + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("embeddings-index") + .vectorAttributeName("embedding") + .dimensions(1536) + .distanceFunction(DistanceFunction.COSINE) + .projection(p -> p.projectionType(ProjectionType.ALL)) + .build(); + CreateTableEnhancedRequest builtObject = CreateTableEnhancedRequest.builder() .globalSecondaryIndices(globalSecondaryIndex) .localSecondaryIndices(localSecondaryIndex) + .vectorIndexes(vectorIndex) .provisionedThroughput(getDefaultProvisionedThroughput()) .build(); assertThat(builtObject.globalSecondaryIndices(), is(Collections.singletonList(globalSecondaryIndex))); assertThat(builtObject.localSecondaryIndices(), is(Collections.singletonList(localSecondaryIndex))); + assertThat(builtObject.vectorIndexes(), is(Collections.singletonList(vectorIndex))); assertThat(builtObject.provisionedThroughput(), is(getDefaultProvisionedThroughput())); } @@ -98,6 +109,71 @@ public void toBuilder() { assertThat(copiedObject, is(builtObject)); } + @Test + public void toBuilder_preservesVectorIndexes() { + EnhancedVectorIndex vectorIndex = EnhancedVectorIndex.builder() + .indexName("my-index") + .vectorAttributeName("emb") + .dimensions(512) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + CreateTableEnhancedRequest original = CreateTableEnhancedRequest.builder() + .vectorIndexes(vectorIndex) + .provisionedThroughput(getDefaultProvisionedThroughput()) + .build(); + + CreateTableEnhancedRequest rebuilt = original.toBuilder().build(); + + assertThat(rebuilt.vectorIndexes(), is(original.vectorIndexes())); + assertThat(rebuilt, is(original)); + } + + @Test + public void builder_vectorIndexes_consumerOverload() { + CreateTableEnhancedRequest request = + CreateTableEnhancedRequest.builder() + .vectorIndexes(vi -> vi.indexName("idx-a") + .vectorAttributeName("emb") + .dimensions(128) + .distanceFunction(DistanceFunction.COSINE), + vi -> vi.indexName("idx-b") + .vectorAttributeName("vec") + .dimensions(256) + .distanceFunction(DistanceFunction.EUCLIDEAN)) + .build(); + + assertThat(request.vectorIndexes().size(), is(2)); + assertThat(request.vectorIndexes(), + equalTo(asList(EnhancedVectorIndex.builder().indexName("idx-a").vectorAttributeName("emb") + .dimensions(128).distanceFunction(DistanceFunction.COSINE).build(), + EnhancedVectorIndex.builder().indexName("idx-b").vectorAttributeName("vec") + .dimensions(256).distanceFunction(DistanceFunction.EUCLIDEAN).build()))); + } + + @Test + public void builder_vectorIndexes_collectionOverload() { + EnhancedVectorIndex first = EnhancedVectorIndex.builder() + .indexName("col-idx-1") + .vectorAttributeName("emb") + .dimensions(512) + .distanceFunction(DistanceFunction.COSINE) + .build(); + EnhancedVectorIndex second = EnhancedVectorIndex.builder() + .indexName("col-idx-2") + .vectorAttributeName("vec") + .dimensions(768) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + CreateTableEnhancedRequest request = CreateTableEnhancedRequest.builder() + .vectorIndexes(Arrays.asList(first, second)) + .build(); + + assertThat(request.vectorIndexes().size(), is(2)); + assertThat(request.vectorIndexes(), equalTo(asList(first, second))); + } + private ProvisionedThroughput getDefaultProvisionedThroughput() { return ProvisionedThroughput.builder() .writeCapacityUnits(1L) diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndexTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndexTest.java new file mode 100644 index 000000000000..6c982b357778 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/EnhancedVectorIndexTest.java @@ -0,0 +1,216 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; + +public class EnhancedVectorIndexTest { + + private static final SearchSchemaElement HASH_ELEMENT = + SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + private static final SearchSchemaElement FILTER_ELEMENT = + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build(); + + private static final Projection PROJECTION = + Projection.builder().projectionType(ProjectionType.ALL).build(); + + @Test + public void builder_minimal() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder().build(); + + assertThat(index.indexName()).isNull(); + assertThat(index.vectorAttributeName()).isNull(); + assertThat(index.dimensions()).isEqualTo(0); + assertThat(index.distanceFunction()).isNull(); + assertThat(index.projection()).isNull(); + assertThat(index.searchSchemaElements()).isEmpty(); + } + + @Test + public void builder_maximal() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder() + .indexName("my-vector-index") + .vectorAttributeName("embedding") + .dimensions(128) + .distanceFunction(DistanceFunction.COSINE) + .projection(PROJECTION) + .searchSchemaElements(Arrays.asList(HASH_ELEMENT, FILTER_ELEMENT)) + .build(); + + assertThat(index.indexName()).isEqualTo("my-vector-index"); + assertThat(index.vectorAttributeName()).isEqualTo("embedding"); + assertThat(index.dimensions()).isEqualTo(128); + assertThat(index.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(index.projection()).isEqualTo(PROJECTION); + assertThat(index.searchSchemaElements()).containsExactly(HASH_ELEMENT, FILTER_ELEMENT); + } + + @Test + public void toBuilder_roundTrip() { + EnhancedVectorIndex original = EnhancedVectorIndex.builder() + .indexName("idx") + .vectorAttributeName("vec") + .dimensions(256) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .projection(PROJECTION) + .searchSchemaElements(Arrays.asList(HASH_ELEMENT)) + .build(); + + EnhancedVectorIndex rebuilt = original.toBuilder().build(); + + assertThat(rebuilt).isEqualTo(original); + } + + @Test + public void equals_sameObject() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder().indexName("idx").build(); + + assertThat(index).isSameAs(index); + assertThat(index.equals(index)).isTrue(); + } + + @Test + public void equals_equalObjects() { + EnhancedVectorIndex index1 = EnhancedVectorIndex.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + EnhancedVectorIndex index2 = EnhancedVectorIndex.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + assertThat(index1).isEqualTo(index2); + } + + @Test + public void equals_null_returnsFalse() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder().indexName("idx").build(); + + assertThat(index.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder().indexName("idx").build(); + + assertThat(index.equals("not-an-index")).isFalse(); + } + + @Test + public void equals_differentIndexName_returnsFalse() { + EnhancedVectorIndex index1 = EnhancedVectorIndex.builder().indexName("a").build(); + EnhancedVectorIndex index2 = EnhancedVectorIndex.builder().indexName("b").build(); + + assertThat(index1).isNotEqualTo(index2); + } + + @Test + public void equals_differentDimensions_returnsFalse() { + EnhancedVectorIndex index1 = EnhancedVectorIndex.builder().indexName("idx").dimensions(64).build(); + EnhancedVectorIndex index2 = EnhancedVectorIndex.builder().indexName("idx").dimensions(128).build(); + + assertThat(index1).isNotEqualTo(index2); + } + + @Test + public void equals_differentDistanceFunction_returnsFalse() { + EnhancedVectorIndex index1 = EnhancedVectorIndex.builder() + .indexName("idx") + .distanceFunction(DistanceFunction.COSINE) + .build(); + + EnhancedVectorIndex index2 = EnhancedVectorIndex.builder() + .indexName("idx") + .distanceFunction(DistanceFunction.EUCLIDEAN) + .build(); + + assertThat(index1).isNotEqualTo(index2); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + EnhancedVectorIndex index1 = EnhancedVectorIndex.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + EnhancedVectorIndex index2 = EnhancedVectorIndex.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + assertThat(index1.hashCode()).isEqualTo(index2.hashCode()); + } + + @Test + public void searchSchemaElements_nullDefaults_toEmptyList() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder() + .searchSchemaElements((List) null) + .build(); + + assertThat(index.searchSchemaElements()).isEmpty(); + } + + @Test + public void searchSchemaElements_varargs() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder() + .searchSchemaElements(HASH_ELEMENT, FILTER_ELEMENT) + .build(); + + assertThat(index.searchSchemaElements()).containsExactly(HASH_ELEMENT, FILTER_ELEMENT); + } + + @Test + public void addSearchSchemaElement_consumerOverload() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder() + .addSearchSchemaElement(b -> b.attributeName("pk") + .searchSchemaElementType( + SearchSchemaElementType.HASH)) + .build(); + + assertThat(index.searchSchemaElements()).hasSize(1); + assertThat(index.searchSchemaElements().get(0).attributeName()).isEqualTo("pk"); + assertThat(index.searchSchemaElements().get(0).searchSchemaElementType()).isEqualTo(SearchSchemaElementType.HASH); + } + + @Test + public void projection_consumerOverload() { + EnhancedVectorIndex index = EnhancedVectorIndex.builder() + .projection(b -> b.projectionType(ProjectionType.KEYS_ONLY)) + .build(); + + assertThat(index.projection().projectionType()).isEqualTo(ProjectionType.KEYS_ONLY); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItemTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItemTest.java new file mode 100644 index 000000000000..825888a55b4d --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchResultItemTest.java @@ -0,0 +1,132 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class SearchResultItemTest { + + @Test + public void builder_setsItemAndScore() { + SearchResultItem result = SearchResultItem.builder() + .item("hello") + .score(0.95) + .build(); + + assertThat(result.item()).isEqualTo("hello"); + assertThat(result.score()).isEqualTo(0.95); + } + + @Test + public void score_defaultsToNull() { + SearchResultItem result = SearchResultItem.builder() + .item("hello") + .build(); + + assertThat(result.score()).isNull(); + } + + @Test + public void equals_sameObject() { + SearchResultItem result = SearchResultItem.builder() + .item("hello") + .score(0.5) + .build(); + + assertThat(result).isSameAs(result); + assertThat(result.equals(result)).isTrue(); + } + + @Test + public void equals_equalObjects() { + SearchResultItem result1 = SearchResultItem.builder() + .item("hello") + .score(0.5) + .build(); + + SearchResultItem result2 = SearchResultItem.builder() + .item("hello") + .score(0.5) + .build(); + + assertThat(result1).isEqualTo(result2); + } + + @Test + public void equals_null_returnsFalse() { + SearchResultItem result = SearchResultItem.builder() + .item("hello") + .build(); + + assertThat(result.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + SearchResultItem result = SearchResultItem.builder() + .item("hello") + .build(); + + assertThat(result.equals("not-a-result")).isFalse(); + } + + @Test + public void equals_differentItem_returnsFalse() { + SearchResultItem result1 = SearchResultItem.builder() + .item("hello") + .score(0.5) + .build(); + + SearchResultItem result2 = SearchResultItem.builder() + .item("world") + .score(0.5) + .build(); + + assertThat(result1).isNotEqualTo(result2); + } + + @Test + public void equals_differentScore_returnsFalse() { + SearchResultItem result1 = SearchResultItem.builder() + .item("hello") + .score(0.5) + .build(); + + SearchResultItem result2 = SearchResultItem.builder() + .item("hello") + .score(0.9) + .build(); + + assertThat(result1).isNotEqualTo(result2); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + SearchResultItem result1 = SearchResultItem.builder() + .item("hello") + .score(0.75) + .build(); + + SearchResultItem result2 = SearchResultItem.builder() + .item("hello") + .score(0.75) + .build(); + + assertThat(result1.hashCode()).isEqualTo(result2.hashCode()); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementTest.java new file mode 100644 index 000000000000..944d491835a5 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchSchemaElementTest.java @@ -0,0 +1,135 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.Test; + +public class SearchSchemaElementTest { + + @Test + public void builder_setsFields() { + SearchSchemaElement element = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + assertThat(element.attributeName()).isEqualTo("pk"); + assertThat(element.searchSchemaElementType()).isEqualTo(SearchSchemaElementType.HASH); + } + + @Test + public void toBuilder_roundTrip() { + SearchSchemaElement original = SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build(); + + SearchSchemaElement rebuilt = original.toBuilder().build(); + + assertThat(rebuilt).isEqualTo(original); + } + + @Test + public void equals_sameObject() { + SearchSchemaElement element = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + assertThat(element).isSameAs(element); + assertThat(element.equals(element)).isTrue(); + } + + @Test + public void equals_equalObjects() { + SearchSchemaElement element1 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + SearchSchemaElement element2 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + assertThat(element1).isEqualTo(element2); + } + + @Test + public void equals_null_returnsFalse() { + SearchSchemaElement element = SearchSchemaElement.builder() + .attributeName("pk") + .build(); + + assertThat(element.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + SearchSchemaElement element = SearchSchemaElement.builder() + .attributeName("pk") + .build(); + + assertThat(element.equals("not-an-element")).isFalse(); + } + + @Test + public void equals_differentAttributeName_returnsFalse() { + SearchSchemaElement element1 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + SearchSchemaElement element2 = SearchSchemaElement.builder() + .attributeName("sk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + assertThat(element1).isNotEqualTo(element2); + } + + @Test + public void equals_differentType_returnsFalse() { + SearchSchemaElement element1 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + SearchSchemaElement element2 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build(); + + assertThat(element1).isNotEqualTo(element2); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + SearchSchemaElement element1 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + SearchSchemaElement element2 = SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + assertThat(element1.hashCode()).isEqualTo(element2.hashCode()); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequestTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequestTest.java new file mode 100644 index 000000000000..ac67f11f5246 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedRequestTest.java @@ -0,0 +1,257 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.enhanced.dynamodb.Expression; +import software.amazon.awssdk.enhanced.dynamodb.NestedAttributeName; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.ReturnConsumedCapacity; + +@RunWith(MockitoJUnitRunner.class) +public class SearchVectorsEnhancedRequestTest { + + @Test + public void builder_minimal() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder().build(); + + assertThat(request.searchVector()).isNull(); + assertThat(request.topK()).isNull(); + assertThat(request.searchConditionExpression()).isNull(); + assertThat(request.attributesToProject()).isNull(); + assertThat(request.nestedAttributesToProject()).isNull(); + assertThat(request.returnConsumedCapacityAsString()).isNull(); + } + + @Test + public void builder_maximal() { + Expression condition = Expression.builder() + .expression("#pk = :val") + .putExpressionName("#pk", "partitionKey") + .putExpressionValue(":val", AttributeValue.fromS("abc")) + .build(); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {0.1f, 0.2f, 0.3f}) + .topK(5) + .searchConditionExpression(condition) + .attributesToProject("title", "author") + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build(); + + assertThat(request.searchVector().length).isEqualTo(3); + assertThat(request.topK()).isEqualTo(5); + assertThat(request.searchConditionExpression()).isEqualTo(condition); + assertThat(request.attributesToProject()).isEqualTo(Arrays.asList("title", "author")); + assertThat(request.returnConsumedCapacity()).isEqualTo(ReturnConsumedCapacity.TOTAL); + } + + @Test + public void toBuilder_roundTrip() { + Expression condition = Expression.builder() + .expression("x = :x") + .putExpressionValue(":x", AttributeValue.fromS("y")) + .build(); + + SearchVectorsEnhancedRequest original = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(10) + .searchConditionExpression(condition) + .addNestedAttributeToProject( + NestedAttributeName.create("a", "b")) + .returnConsumedCapacity(ReturnConsumedCapacity.INDEXES) + .build(); + + SearchVectorsEnhancedRequest rebuilt = original.toBuilder().build(); + + assertThat(rebuilt).isEqualTo(original); + } + + @Test + public void searchVector_floatArray_defensiveCopy() { + float[] vector = {1.0f, 2.0f, 3.0f}; + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(vector) + .build(); + + vector[0] = 99.0f; + assertThat(request.searchVector()[0]).isEqualTo(1.0f); + + float[] returned = request.searchVector(); + returned[1] = 99.0f; + assertThat(request.searchVector()[1]).isEqualTo(2.0f); + } + + @Test + public void searchVector_listOverload() { + List vector = Arrays.asList(0.5f, 1.5f, 2.5f); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(vector) + .build(); + + assertThat(request.searchVector().length).isEqualTo(3); + assertThat(request.searchVector()[0]).isEqualTo(0.5f); + assertThat(request.searchVector()[2]).isEqualTo(2.5f); + } + + @Test + public void addNestedAttributeToProject() { + NestedAttributeName nested = NestedAttributeName.create("metadata", "tags", "primary"); + + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .addNestedAttributeToProject(nested) + .build(); + + assertThat(request.nestedAttributesToProject()).containsExactly(nested); + assertThat(request.attributesToProject()).containsExactly("metadata.tags.primary"); + } + + @Test + public void equals_sameObject_returnsTrue() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .topK(5) + .build(); + + assertThat(request.equals(request)).isTrue(); + } + + @Test + public void equals_null_returnsFalse() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build(); + + assertThat(request.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f}) + .build(); + + assertThat(request.equals("string")).isFalse(); + } + + @Test + public void equals_differentSearchVector_returnsFalse() { + SearchVectorsEnhancedRequest request1 = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(5) + .build(); + SearchVectorsEnhancedRequest request2 = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {3.0f, 4.0f}) + .topK(5) + .build(); + + assertThat(request1.equals(request2)).isFalse(); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + SearchVectorsEnhancedRequest request1 = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(10) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build(); + SearchVectorsEnhancedRequest request2 = SearchVectorsEnhancedRequest.builder() + .searchVector(new float[] {1.0f, 2.0f}) + .topK(10) + .returnConsumedCapacity(ReturnConsumedCapacity.TOTAL) + .build(); + + assertThat(request1.equals(request2)).isTrue(); + assertThat(request1.hashCode()).isEqualTo(request2.hashCode()); + } + + @Test + public void searchVector_nullList_returnsNull() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .searchVector((List) null) + .build(); + + assertThat(request.searchVector()).isNull(); + } + + @Test + public void topK_primitiveOverload() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .topK(7) + .build(); + + assertThat(request.topK()).isEqualTo(7); + } + + @Test + public void attributesToProject_collection_clearsExisting() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .attributesToProject("a", "b") + .attributesToProject(Arrays.asList("x", "y")) + .build(); + + assertThat(request.attributesToProject()).isEqualTo(Arrays.asList("x", "y")); + } + + @Test + public void addAttributeToProject_null_isNoOp() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .addAttributeToProject("existing") + .addAttributeToProject(null) + .build(); + + assertThat(request.attributesToProject()).isEqualTo(Collections.singletonList("existing")); + } + + @SuppressWarnings("unchecked") + @Test + public void addNestedAttributesToProject_nullCollection_isNoOp() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .addAttributeToProject("existing") + .addNestedAttributesToProject((Collection) null) + .build(); + + assertThat(request.attributesToProject()).isEqualTo(Collections.singletonList("existing")); + } + + @Test + public void returnConsumedCapacity_stringOverload() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .returnConsumedCapacity("TOTAL") + .build(); + + assertThat(request.returnConsumedCapacity()).isEqualTo(ReturnConsumedCapacity.TOTAL); + } + + @Test + public void returnConsumedCapacityAsString_returnsRawString() { + SearchVectorsEnhancedRequest request = SearchVectorsEnhancedRequest.builder() + .returnConsumedCapacity("INDEXES") + .build(); + + assertThat(request.returnConsumedCapacityAsString()).isEqualTo("INDEXES"); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponseTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponseTest.java new file mode 100644 index 000000000000..cca590e7443d --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/SearchVectorsEnhancedResponseTest.java @@ -0,0 +1,156 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import org.junit.Test; +import software.amazon.awssdk.services.dynamodb.model.VectorCapacity; + +public class SearchVectorsEnhancedResponseTest { + + private static final SearchResultItem RESULT_A = + SearchResultItem.builder().item("itemA").score(0.9).build(); + + private static final SearchResultItem RESULT_B = + SearchResultItem.builder().item("itemB").score(0.8).build(); + + @Test + public void builder_minimal_nullResultsDefaultsToEmptyList() { + SearchVectorsEnhancedResponse response = SearchVectorsEnhancedResponse.builder().build(); + + assertThat(response.results()).isEmpty(); + assertThat(response.consumedCapacity()).isNull(); + } + + @Test + public void builder_withResults() { + SearchVectorsEnhancedResponse response = + SearchVectorsEnhancedResponse.builder() + .results(Arrays.asList(RESULT_A, RESULT_B)) + .build(); + + assertThat(response.results()).containsExactly(RESULT_A, RESULT_B); + } + + @Test + public void addResult_initializesListWhenNull() { + SearchVectorsEnhancedResponse response = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_A) + .build(); + + assertThat(response.results()).containsExactly(RESULT_A); + } + + @Test + public void addResult_appendsToExistingList() { + SearchVectorsEnhancedResponse response = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_A) + .addResult(RESULT_B) + .build(); + + assertThat(response.results()).containsExactly(RESULT_A, RESULT_B); + } + + @Test + public void consumedCapacity_returnsSetValue() { + VectorCapacity capacity = VectorCapacity.builder().build(); + SearchVectorsEnhancedResponse response = + SearchVectorsEnhancedResponse.builder() + .consumedCapacity(capacity) + .build(); + + assertThat(response.consumedCapacity()).isEqualTo(capacity); + } + + @Test + public void consumedCapacity_defaultsToNull() { + SearchVectorsEnhancedResponse response = SearchVectorsEnhancedResponse.builder().build(); + + assertThat(response.consumedCapacity()).isNull(); + } + + @Test + public void equals_sameObject() { + SearchVectorsEnhancedResponse response = + SearchVectorsEnhancedResponse.builder().addResult(RESULT_A).build(); + + assertThat(response).isSameAs(response); + assertThat(response.equals(response)).isTrue(); + } + + @Test + public void equals_equalObjects() { + SearchVectorsEnhancedResponse response1 = + SearchVectorsEnhancedResponse.builder() + .results(Arrays.asList(RESULT_A)) + .build(); + + SearchVectorsEnhancedResponse response2 = + SearchVectorsEnhancedResponse.builder() + .results(Arrays.asList(RESULT_A)) + .build(); + + assertThat(response1).isEqualTo(response2); + } + + @Test + public void equals_null_returnsFalse() { + SearchVectorsEnhancedResponse response = SearchVectorsEnhancedResponse.builder().build(); + + assertThat(response.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + SearchVectorsEnhancedResponse response = SearchVectorsEnhancedResponse.builder().build(); + + assertThat(response.equals("not-a-response")).isFalse(); + } + + @Test + public void equals_differentResults_returnsFalse() { + SearchVectorsEnhancedResponse response1 = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_A) + .build(); + + SearchVectorsEnhancedResponse response2 = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_B) + .build(); + + assertThat(response1).isNotEqualTo(response2); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + SearchVectorsEnhancedResponse response1 = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_A) + .build(); + + SearchVectorsEnhancedResponse response2 = + SearchVectorsEnhancedResponse.builder() + .addResult(RESULT_A) + .build(); + + assertThat(response1.hashCode()).isEqualTo(response2.hashCode()); + } +} diff --git a/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadataTest.java b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadataTest.java new file mode 100644 index 000000000000..054a710f7e22 --- /dev/null +++ b/services-custom/dynamodb-enhanced/src/test/java/software/amazon/awssdk/enhanced/dynamodb/model/VectorIndexMetadataTest.java @@ -0,0 +1,205 @@ +/* + * 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.enhanced.dynamodb.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import org.junit.Test; +import software.amazon.awssdk.services.dynamodb.model.Projection; +import software.amazon.awssdk.services.dynamodb.model.ProjectionType; + +public class VectorIndexMetadataTest { + + private static final SearchSchemaElement HASH_ELEMENT = + SearchSchemaElement.builder() + .attributeName("pk") + .searchSchemaElementType(SearchSchemaElementType.HASH) + .build(); + + private static final SearchSchemaElement FILTER_ELEMENT = + SearchSchemaElement.builder() + .attributeName("category") + .searchSchemaElementType(SearchSchemaElementType.INLINE_FILTER) + .build(); + + private static final Projection PROJECTION = + Projection.builder().projectionType(ProjectionType.ALL).build(); + + @Test + public void builder_minimal() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder().build(); + + assertThat(metadata.indexName()).isNull(); + assertThat(metadata.vectorAttributeName()).isNull(); + assertThat(metadata.dimensions()).isEqualTo(0); + assertThat(metadata.distanceFunction()).isNull(); + assertThat(metadata.projection()).isNull(); + assertThat(metadata.searchSchemaElements()).isEmpty(); + } + + @Test + public void builder_maximal() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .indexName("my-vector-index") + .vectorAttributeName("embedding") + .dimensions(128) + .distanceFunction(DistanceFunction.COSINE) + .projection(PROJECTION) + .searchSchemaElements(Arrays.asList(HASH_ELEMENT, FILTER_ELEMENT)) + .build(); + + assertThat(metadata.indexName()).isEqualTo("my-vector-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(128); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.COSINE); + assertThat(metadata.projection()).isEqualTo(PROJECTION); + assertThat(metadata.searchSchemaElements()).containsExactly(HASH_ELEMENT, FILTER_ELEMENT); + } + + @Test + public void toBuilder_roundTrip() { + VectorIndexMetadata original = VectorIndexMetadata.builder() + .indexName("idx") + .vectorAttributeName("vec") + .dimensions(256) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .projection(PROJECTION) + .searchSchemaElements(Arrays.asList(HASH_ELEMENT)) + .build(); + + VectorIndexMetadata rebuilt = original.toBuilder().build(); + + assertThat(rebuilt).isEqualTo(original); + } + + @Test + public void fromEnhancedVectorIndex_mapsAllFields() { + List elements = Arrays.asList(HASH_ELEMENT, FILTER_ELEMENT); + + EnhancedVectorIndex enhancedIndex = EnhancedVectorIndex.builder() + .indexName("my-index") + .vectorAttributeName("embedding") + .dimensions(512) + .distanceFunction(DistanceFunction.EUCLIDEAN) + .projection(PROJECTION) + .searchSchemaElements(elements) + .build(); + + VectorIndexMetadata metadata = VectorIndexMetadata.fromEnhancedVectorIndex(enhancedIndex); + + assertThat(metadata.indexName()).isEqualTo("my-index"); + assertThat(metadata.vectorAttributeName()).isEqualTo("embedding"); + assertThat(metadata.dimensions()).isEqualTo(512); + assertThat(metadata.distanceFunction()).isEqualTo(DistanceFunction.EUCLIDEAN); + assertThat(metadata.projection()).isEqualTo(PROJECTION); + assertThat(metadata.searchSchemaElements()).containsExactly(HASH_ELEMENT, FILTER_ELEMENT); + } + + @Test + public void searchSchemaElements_nullDefaults_toEmptyList() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .searchSchemaElements(null) + .build(); + + assertThat(metadata.searchSchemaElements()).isEmpty(); + } + + @Test + public void equals_sameObject() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder().indexName("idx").build(); + + assertThat(metadata).isSameAs(metadata); + assertThat(metadata.equals(metadata)).isTrue(); + } + + @Test + public void equals_equalObjects() { + VectorIndexMetadata metadata1 = VectorIndexMetadata.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + VectorIndexMetadata metadata2 = VectorIndexMetadata.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.COSINE) + .build(); + + assertThat(metadata1).isEqualTo(metadata2); + } + + @Test + public void equals_null_returnsFalse() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder().indexName("idx").build(); + + assertThat(metadata.equals(null)).isFalse(); + } + + @Test + public void equals_differentClass_returnsFalse() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder().indexName("idx").build(); + + assertThat(metadata.equals("not-metadata")).isFalse(); + } + + @Test + public void equals_differentIndexName_returnsFalse() { + VectorIndexMetadata metadata1 = VectorIndexMetadata.builder().indexName("a").build(); + VectorIndexMetadata metadata2 = VectorIndexMetadata.builder().indexName("b").build(); + + assertThat(metadata1).isNotEqualTo(metadata2); + } + + @Test + public void hashCode_equalObjects_sameHashCode() { + VectorIndexMetadata metadata1 = VectorIndexMetadata.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + VectorIndexMetadata metadata2 = VectorIndexMetadata.builder() + .indexName("idx") + .dimensions(64) + .distanceFunction(DistanceFunction.DOT_PRODUCT) + .build(); + + assertThat(metadata1.hashCode()).isEqualTo(metadata2.hashCode()); + } + + @Test + public void addSearchSchemaElement_accumulatesElements() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .addSearchSchemaElement(HASH_ELEMENT) + .addSearchSchemaElement(FILTER_ELEMENT) + .build(); + + assertThat(metadata.searchSchemaElements()).containsExactly(HASH_ELEMENT, FILTER_ELEMENT); + } + + @Test + public void addSearchSchemaElement_initializesListOnFirstCall() { + VectorIndexMetadata metadata = VectorIndexMetadata.builder() + .addSearchSchemaElement(HASH_ELEMENT) + .build(); + + assertThat(metadata.searchSchemaElements()).hasSize(1); + assertThat(metadata.searchSchemaElements()).containsExactly(HASH_ELEMENT); + } +} diff --git a/services-custom/iam-policy-builder/pom.xml b/services-custom/iam-policy-builder/pom.xml index d83a55863eff..4fc6b9215ec5 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml iam-policy-builder diff --git a/services-custom/pom.xml b/services-custom/pom.xml index 62b6efe752d5..72a82d3bec44 100644 --- a/services-custom/pom.xml +++ b/services-custom/pom.xml @@ -19,7 +19,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 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 e70a4b5c16c2..6df723642014 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml s3-event-notifications diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationReader.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationReader.java index 5675d4e73a92..e069213f2b76 100644 --- a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationReader.java +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationReader.java @@ -20,13 +20,16 @@ import java.nio.charset.StandardCharsets; import java.time.Instant; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.eventnotifications.s3.model.EventHoldDuration; import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData; import software.amazon.awssdk.eventnotifications.s3.model.IntelligentTieringEventData; import software.amazon.awssdk.eventnotifications.s3.model.LifecycleEventData; +import software.amazon.awssdk.eventnotifications.s3.model.ObjectRetentionEventData; import software.amazon.awssdk.eventnotifications.s3.model.ReplicationEventData; import software.amazon.awssdk.eventnotifications.s3.model.RequestParameters; import software.amazon.awssdk.eventnotifications.s3.model.ResponseElements; @@ -130,9 +133,38 @@ private S3EventNotificationRecord readEventNotificationRecord(JsonNode jsonNode) ReplicationEventData replicationEventData = readReplicationEventData(recordNode.get("replicationEventData")); eventNotificationRecord.setReplicationEventData(replicationEventData); + ObjectRetentionEventData objectRetentionEventData = + readObjectRetentionEventData(recordNode.get("objectRetentionEventData")); + eventNotificationRecord.setObjectRetentionEventData(objectRetentionEventData); + return eventNotificationRecord; } + private ObjectRetentionEventData readObjectRetentionEventData(JsonNode jsonNode) { + Map retentionNode = expectObjectOrNull(jsonNode, "objectRetentionEventData"); + if (retentionNode == null) { + return null; + } + String mode = expectStringOrNull(retentionNode, "mode"); + String retainUntilDate = expectStringOrNull(retentionNode, "retainUntilDate"); + String eventHold = expectStringOrNull(retentionNode, "eventHold"); + EventHoldDuration eventHoldDuration = readEventHoldDuration(retentionNode.get("eventHoldDuration")); + return new ObjectRetentionEventData(mode, retainUntilDate, eventHold, eventHoldDuration); + } + + private EventHoldDuration readEventHoldDuration(JsonNode jsonNode) { + Map durationNode = expectObjectOrNull(jsonNode, "eventHoldDuration"); + if (durationNode == null || durationNode.isEmpty()) { + return null; + } + // The duration is a single {unit: value} pair (e.g. {"days": 90} or {"years": 1}). Read whichever + // unit the service emits, so a new unit does not require an SDK change. + Map.Entry entry = durationNode.entrySet().iterator().next(); + String unit = entry.getKey(); + Long value = expectLong(entry.getValue(), unit); + return new EventHoldDuration(unit, value); + } + private ReplicationEventData readReplicationEventData(JsonNode jsonNode) { Map replicationDataNode = expectObjectOrNull(jsonNode, "replicationEventData"); if (replicationDataNode == null) { @@ -242,7 +274,29 @@ private S3Bucket readBucket(JsonNode jsonNode) { String name = expectStringOrNull(bucketNode, "name"); UserIdentity ownerIdentity = readOwnerIdentity(bucketNode.get("ownerIdentity")); String arn = expectStringOrNull(bucketNode, "arn"); - return new S3Bucket(name, ownerIdentity, arn); + Map awsGeneratedTags = readStringMapOrNull(bucketNode.get("awsGeneratedTags"), "awsGeneratedTags"); + return new S3Bucket(name, ownerIdentity, arn, awsGeneratedTags); + } + + private Map readStringMapOrNull(JsonNode jsonNode, String name) { + Map mapNode = expectObjectOrNull(jsonNode, name); + if (mapNode == null) { + return null; + } + Map result = new LinkedHashMap<>(); + mapNode.forEach((tagKey, tagValueNode) -> + result.put(tagKey, readTagStringValueOrNull(name, tagKey, tagValueNode))); + return result; + } + + private String readTagStringValueOrNull(String mapName, String tagKey, JsonNode tagValue) { + if (isNull(tagValue)) { + return null; + } + Validate.isTrue(tagValue.isString(), + "The value of tag '%s' in '%s' was not a string, but was: %s", + tagKey, mapName, tagValue); + return tagValue.asString(); } private UserIdentity readOwnerIdentity(JsonNode jsonNode) { diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationWriter.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationWriter.java index 9e55f4d4c197..f974725ca2d5 100644 --- a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationWriter.java +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/internal/DefaultS3EventNotificationWriter.java @@ -19,10 +19,13 @@ import java.time.Instant; import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Map; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.eventnotifications.s3.model.EventHoldDuration; import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData; import software.amazon.awssdk.eventnotifications.s3.model.IntelligentTieringEventData; import software.amazon.awssdk.eventnotifications.s3.model.LifecycleEventData; +import software.amazon.awssdk.eventnotifications.s3.model.ObjectRetentionEventData; import software.amazon.awssdk.eventnotifications.s3.model.ReplicationEventData; import software.amazon.awssdk.eventnotifications.s3.model.RequestParameters; import software.amazon.awssdk.eventnotifications.s3.model.ResponseElements; @@ -121,6 +124,29 @@ private void writeRecord(JsonWriter writer, S3EventNotificationRecord rec) { writeLifecyleEventData(writer, rec.getLifecycleEventData()); } + if (rec.getObjectRetentionEventData() != null) { + writeObjectRetentionEventData(writer, rec.getObjectRetentionEventData()); + } + + writer.writeEndObject(); + } + + private void writeObjectRetentionEventData(JsonWriter writer, ObjectRetentionEventData objectRetentionEventData) { + writer.writeFieldName("objectRetentionEventData"); + writer.writeStartObject(); + writeStringField(writer, "mode", objectRetentionEventData.getMode()); + writeStringField(writer, "retainUntilDate", objectRetentionEventData.getRetainUntilDate()); + if (objectRetentionEventData.getEventHold() != null) { + writeStringField(writer, "eventHold", objectRetentionEventData.getEventHold()); + } + EventHoldDuration eventHoldDuration = objectRetentionEventData.getEventHoldDuration(); + if (eventHoldDuration != null && eventHoldDuration.getUnit() != null) { + writer.writeFieldName("eventHoldDuration"); + writer.writeStartObject(); + // Single {unit: value} pair, e.g. {"days": 90} or {"years": 1}. + writeNumericField(writer, eventHoldDuration.getUnit(), eventHoldDuration.getValue()); + writer.writeEndObject(); + } writer.writeEndObject(); } @@ -227,6 +253,17 @@ private void writeS3Bucket(JsonWriter writer, S3Bucket bucket) { writer.writeEndObject(); } writeStringField(writer, "arn", bucket.getArn()); + Map awsGeneratedTags = bucket.getAwsGeneratedTags(); + if (awsGeneratedTags != null && !awsGeneratedTags.isEmpty()) { + writeStringMap(writer, "awsGeneratedTags", awsGeneratedTags); + } + writer.writeEndObject(); + } + + private void writeStringMap(JsonWriter writer, String field, Map map) { + writer.writeFieldName(field); + writer.writeStartObject(); + map.forEach((k, v) -> writeStringField(writer, k, v)); writer.writeEndObject(); } diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/EventHoldDuration.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/EventHoldDuration.java new file mode 100644 index 000000000000..b6017f146c4d --- /dev/null +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/EventHoldDuration.java @@ -0,0 +1,87 @@ +/* + * 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.eventnotifications.s3.model; + +import java.util.Objects; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.utils.ToString; + +/** + * The duration of an event-hold retention, within {@link ObjectRetentionEventData}. Only present when variable + * (event-hold) retention is used. + * + *

    The duration is modeled as a single {@code unit}/{@code value} pair to mirror the message-format contract emitted + * by the service: the unit becomes the JSON key and the value its number, producing {@code {"days": 90}} or + * {@code {"years": 1}}. Modeling it this way (rather than fixed {@code days}/{@code years} fields) means the reader + * surfaces whatever unit the service emits, so a new unit does not require an SDK change. + */ +@SdkPublicApi +public class EventHoldDuration { + + private final String unit; + private final Long value; + + public EventHoldDuration(String unit, Long value) { + this.unit = unit; + this.value = value; + } + + /** + * @return the duration unit, for example {@code "days"} or {@code "years"}. + */ + public String getUnit() { + return unit; + } + + /** + * @return the duration value for the given {@link #getUnit() unit}. + */ + public Long getValue() { + return value; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + EventHoldDuration that = (EventHoldDuration) o; + + if (!Objects.equals(unit, that.unit)) { + return false; + } + return Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + int result = unit != null ? unit.hashCode() : 0; + result = 31 * result + (value != null ? value.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToString.builder("EventHoldDuration") + .add("unit", unit) + .add("value", value) + .build(); + } +} diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventData.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventData.java new file mode 100644 index 000000000000..e22f1da3e070 --- /dev/null +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventData.java @@ -0,0 +1,115 @@ +/* + * 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.eventnotifications.s3.model; + +import java.util.Objects; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.utils.ToString; + +/** + * The ObjectRetentionEventData is only visible for {@code s3:ObjectRetention:Put} events, which fire on the explicit + * PutObjectRetention API call. + * The {@code eventHold} and {@code eventHoldDuration} fields are only present when variable (event-hold) retention is used; + * they are absent for fixed retention. + */ +@SdkPublicApi +public class ObjectRetentionEventData { + + private final String mode; + private final String retainUntilDate; + private final String eventHold; + private final EventHoldDuration eventHoldDuration; + + public ObjectRetentionEventData(String mode, String retainUntilDate, String eventHold, + EventHoldDuration eventHoldDuration) { + this.mode = mode; + this.retainUntilDate = retainUntilDate; + this.eventHold = eventHold; + this.eventHoldDuration = eventHoldDuration; + } + + /** + * @return the retention mode, {@code COMPLIANCE} or {@code GOVERNANCE}. + */ + public String getMode() { + return mode; + } + + /** + * @return the retain-until-date in ISO-8601 format after the operation completed. For variable retention with event + * hold ON, this is dynamically computed as {@code now + duration}. + */ + public String getRetainUntilDate() { + return retainUntilDate; + } + + /** + * @return the event hold state, {@code ON} or {@code OFF}. Only present when variable retention is used; absent for + * fixed retention. + */ + public String getEventHold() { + return eventHold; + } + + /** + * @return the event hold duration. Only present when variable retention is used; absent for fixed retention. + */ + public EventHoldDuration getEventHoldDuration() { + return eventHoldDuration; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + ObjectRetentionEventData that = (ObjectRetentionEventData) o; + + if (!Objects.equals(mode, that.mode)) { + return false; + } + if (!Objects.equals(retainUntilDate, that.retainUntilDate)) { + return false; + } + if (!Objects.equals(eventHold, that.eventHold)) { + return false; + } + return Objects.equals(eventHoldDuration, that.eventHoldDuration); + } + + @Override + public int hashCode() { + int result = mode != null ? mode.hashCode() : 0; + result = 31 * result + (retainUntilDate != null ? retainUntilDate.hashCode() : 0); + result = 31 * result + (eventHold != null ? eventHold.hashCode() : 0); + result = 31 * result + (eventHoldDuration != null ? eventHoldDuration.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToString.builder("ObjectRetentionEventData") + .add("mode", mode) + .add("retainUntilDate", retainUntilDate) + .add("eventHold", eventHold) + .add("eventHoldDuration", eventHoldDuration) + .build(); + } +} diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3Bucket.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3Bucket.java index 3cfe0f695d73..c0e71a8831d3 100644 --- a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3Bucket.java +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3Bucket.java @@ -16,6 +16,9 @@ package software.amazon.awssdk.eventnotifications.s3.model; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Objects; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.utils.ToString; @@ -29,11 +32,19 @@ public class S3Bucket { private final String name; private final UserIdentity ownerIdentity; private final String arn; + private final Map awsGeneratedTags; public S3Bucket(String name, UserIdentity ownerIdentity, String arn) { + this(name, ownerIdentity, arn, null); + } + + public S3Bucket(String name, UserIdentity ownerIdentity, String arn, Map awsGeneratedTags) { this.name = name; this.ownerIdentity = ownerIdentity; this.arn = arn; + this.awsGeneratedTags = awsGeneratedTags == null + ? null + : Collections.unmodifiableMap(new LinkedHashMap<>(awsGeneratedTags)); } /** @@ -57,6 +68,14 @@ public String getArn() { return arn; } + /** + * @return The AWS-generated system tags for the bucket, or {@code null} if not present in the event. The returned map + * is unmodifiable. + */ + public Map getAwsGeneratedTags() { + return awsGeneratedTags; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -74,7 +93,10 @@ public boolean equals(Object o) { if (!Objects.equals(ownerIdentity, s3Bucket.ownerIdentity)) { return false; } - return Objects.equals(arn, s3Bucket.arn); + if (!Objects.equals(arn, s3Bucket.arn)) { + return false; + } + return Objects.equals(awsGeneratedTags, s3Bucket.awsGeneratedTags); } @Override @@ -82,15 +104,19 @@ public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (ownerIdentity != null ? ownerIdentity.hashCode() : 0); result = 31 * result + (arn != null ? arn.hashCode() : 0); + result = 31 * result + (awsGeneratedTags != null ? awsGeneratedTags.hashCode() : 0); return result; } @Override public String toString() { - return ToString.builder("S3Bucket") - .add("name", name) - .add("ownerIdentity", ownerIdentity) - .add("arn", arn) - .build(); + ToString builder = ToString.builder("S3Bucket") + .add("name", name) + .add("ownerIdentity", ownerIdentity) + .add("arn", arn); + if (awsGeneratedTags != null) { + builder.add("awsGeneratedTags", awsGeneratedTags); + } + return builder.build(); } } diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.java index fcfa5bb4a6f8..9a94ed44bfd7 100644 --- a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.java +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.java @@ -42,6 +42,7 @@ public class S3EventNotificationRecord { private LifecycleEventData lifecycleEventData; private IntelligentTieringEventData intelligentTieringEventData; private ReplicationEventData replicationEventData; + private ObjectRetentionEventData objectRetentionEventData; private Instant eventTime; public S3EventNotificationRecord() { @@ -221,6 +222,15 @@ public ReplicationEventData getReplicationEventData() { return replicationEventData; } + /** + * The ObjectRetentionEventData is only visible for {@code s3:ObjectRetention:Put} events, fired on the explicit + * PutObjectRetention API call. + * @return the object retention event data. + */ + public ObjectRetentionEventData getObjectRetentionEventData() { + return objectRetentionEventData; + } + public void setAwsRegion(String awsRegion) { this.awsRegion = awsRegion; } @@ -269,6 +279,10 @@ public void setReplicationEventData(ReplicationEventData replicationEventData) { this.replicationEventData = replicationEventData; } + public void setObjectRetentionEventData(ObjectRetentionEventData objectRetentionEventData) { + this.objectRetentionEventData = objectRetentionEventData; + } + public void setEventTime(Instant eventTime) { this.eventTime = eventTime; } @@ -320,6 +334,9 @@ public boolean equals(Object o) { if (!Objects.equals(replicationEventData, that.replicationEventData)) { return false; } + if (!Objects.equals(objectRetentionEventData, that.objectRetentionEventData)) { + return false; + } return Objects.equals(eventTime, that.eventTime); } @@ -337,6 +354,7 @@ public int hashCode() { result = 31 * result + (lifecycleEventData != null ? lifecycleEventData.hashCode() : 0); result = 31 * result + (intelligentTieringEventData != null ? intelligentTieringEventData.hashCode() : 0); result = 31 * result + (replicationEventData != null ? replicationEventData.hashCode() : 0); + result = 31 * result + (objectRetentionEventData != null ? objectRetentionEventData.hashCode() : 0); result = 31 * result + (eventTime != null ? eventTime.hashCode() : 0); return result; } @@ -356,6 +374,7 @@ public String toString() { .add("lifecycleEventData", lifecycleEventData) .add("intelligentTieringEventData", intelligentTieringEventData) .add("replicationEventData", replicationEventData) + .add("objectRetentionEventData", objectRetentionEventData) .add("eventTime", eventTime) .build(); } diff --git a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/internal/EqualsAndHashCodeTest.java b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/internal/EqualsAndHashCodeTest.java index 118f2ff38050..b7b7c65bb1bf 100644 --- a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/internal/EqualsAndHashCodeTest.java +++ b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/internal/EqualsAndHashCodeTest.java @@ -15,9 +15,8 @@ package software.amazon.awssdk.eventnotifications.s3.internal; -import nl.jqno.equalsverifier.Warning; - import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; class EqualsAndHashCodeTest { diff --git a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventDataTest.java b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventDataTest.java new file mode 100644 index 000000000000..9be3dc9b3a39 --- /dev/null +++ b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/ObjectRetentionEventDataTest.java @@ -0,0 +1,389 @@ +/* + * 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.eventnotifications.s3.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Collections; +import org.junit.jupiter.api.Test; + +class ObjectRetentionEventDataTest { + + @Test + void readEvent_withObjectRetentionEventData_allFieldsPopulated() { + String json = "{\n" + + " \"Records\": [{\n" + + " \"eventVersion\": \"2.5\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-east-1\",\n" + + " \"eventTime\": \"2024-06-15T12:00:00.000Z\",\n" + + " \"eventName\": \"ObjectRetention:Put\",\n" + + " \"userIdentity\": { \"principalId\": \"EXAMPLE\" },\n" + + " \"requestParameters\": { \"sourceIPAddress\": \"127.0.0.1\" },\n" + + " \"responseElements\": { \"x-amz-request-id\": \"REQ1\", \"x-amz-id-2\": \"ID2\" },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"retentionConfig\",\n" + + " \"bucket\": {\n" + + " \"name\": \"my-bucket\",\n" + + " \"ownerIdentity\": { \"principalId\": \"OWNER\" },\n" + + " \"arn\": \"arn:aws:s3:::my-bucket\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"my-object.txt\",\n" + + " \"size\": 512,\n" + + " \"eTag\": \"abc123\",\n" + + " \"versionId\": \"v1\",\n" + + " \"sequencer\": \"SEQ1\"\n" + + " }\n" + + " },\n" + + " \"objectRetentionEventData\": {\n" + + " \"mode\": \"COMPLIANCE\",\n" + + " \"retainUntilDate\": \"2025-06-15T12:00:00.000Z\",\n" + + " \"eventHold\": \"ON\",\n" + + " \"eventHoldDuration\": { \"days\": 90 }\n" + + " }\n" + + " }]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + + assertThat(event.getRecords()).hasSize(1); + S3EventNotificationRecord rec = event.getRecords().get(0); + + ObjectRetentionEventData retention = rec.getObjectRetentionEventData(); + assertThat(retention).isNotNull(); + assertThat(retention.getMode()).isEqualTo("COMPLIANCE"); + assertThat(retention.getRetainUntilDate()).isEqualTo("2025-06-15T12:00:00.000Z"); + assertThat(retention.getEventHold()).isEqualTo("ON"); + + EventHoldDuration duration = retention.getEventHoldDuration(); + assertThat(duration).isNotNull(); + assertThat(duration.getUnit()).isEqualTo("days"); + assertThat(duration.getValue()).isEqualTo(90L); + } + + @Test + void readEvent_withObjectRetentionEventData_yearsUnit() { + String json = "{\n" + + " \"Records\": [{\n" + + " \"eventVersion\": \"2.5\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"eu-west-1\",\n" + + " \"eventTime\": \"2024-06-15T12:00:00.000Z\",\n" + + " \"eventName\": \"ObjectRetention:Put\",\n" + + " \"userIdentity\": { \"principalId\": \"EXAMPLE\" },\n" + + " \"requestParameters\": { \"sourceIPAddress\": \"10.0.0.1\" },\n" + + " \"responseElements\": { \"x-amz-request-id\": \"REQ2\", \"x-amz-id-2\": \"ID2\" },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"retentionConfig\",\n" + + " \"bucket\": {\n" + + " \"name\": \"my-bucket\",\n" + + " \"ownerIdentity\": { \"principalId\": \"OWNER\" },\n" + + " \"arn\": \"arn:aws:s3:::my-bucket\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"doc.pdf\",\n" + + " \"size\": 2048,\n" + + " \"eTag\": \"def456\",\n" + + " \"versionId\": \"v2\",\n" + + " \"sequencer\": \"SEQ2\"\n" + + " }\n" + + " },\n" + + " \"objectRetentionEventData\": {\n" + + " \"mode\": \"GOVERNANCE\",\n" + + " \"retainUntilDate\": \"2027-06-15T12:00:00.000Z\",\n" + + " \"eventHold\": \"ON\",\n" + + " \"eventHoldDuration\": { \"years\": 3 }\n" + + " }\n" + + " }]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + S3EventNotificationRecord rec = event.getRecords().get(0); + + EventHoldDuration duration = rec.getObjectRetentionEventData().getEventHoldDuration(); + assertThat(duration).isNotNull(); + assertThat(duration.getUnit()).isEqualTo("years"); + assertThat(duration.getValue()).isEqualTo(3L); + } + + @Test + void readEvent_withObjectRetentionEventData_fixedRetention_noEventHoldFields() { + String json = "{\n" + + " \"Records\": [{\n" + + " \"eventVersion\": \"2.5\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-west-2\",\n" + + " \"eventTime\": \"2024-06-15T12:00:00.000Z\",\n" + + " \"eventName\": \"ObjectRetention:Put\",\n" + + " \"userIdentity\": { \"principalId\": \"EXAMPLE\" },\n" + + " \"requestParameters\": { \"sourceIPAddress\": \"127.0.0.1\" },\n" + + " \"responseElements\": { \"x-amz-request-id\": \"REQ3\", \"x-amz-id-2\": \"ID3\" },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"retentionConfig\",\n" + + " \"bucket\": {\n" + + " \"name\": \"my-bucket\",\n" + + " \"ownerIdentity\": { \"principalId\": \"OWNER\" },\n" + + " \"arn\": \"arn:aws:s3:::my-bucket\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"report.csv\",\n" + + " \"size\": 100,\n" + + " \"eTag\": \"ghi789\",\n" + + " \"versionId\": \"v3\",\n" + + " \"sequencer\": \"SEQ3\"\n" + + " }\n" + + " },\n" + + " \"objectRetentionEventData\": {\n" + + " \"mode\": \"COMPLIANCE\",\n" + + " \"retainUntilDate\": \"2030-01-01T00:00:00.000Z\"\n" + + " }\n" + + " }]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + S3EventNotificationRecord rec = event.getRecords().get(0); + + ObjectRetentionEventData retention = rec.getObjectRetentionEventData(); + assertThat(retention).isNotNull(); + assertThat(retention.getMode()).isEqualTo("COMPLIANCE"); + assertThat(retention.getRetainUntilDate()).isEqualTo("2030-01-01T00:00:00.000Z"); + assertThat(retention.getEventHold()).isNull(); + assertThat(retention.getEventHoldDuration()).isNull(); + } + + @Test + void readEvent_withoutObjectRetentionEventData_fieldIsNull() { + String json = "{\n" + + " \"Records\": [{\n" + + " \"eventVersion\": \"2.5\",\n" + + " \"eventSource\": \"aws:s3\",\n" + + " \"awsRegion\": \"us-west-2\",\n" + + " \"eventTime\": \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\": \"ObjectCreated:Put\",\n" + + " \"userIdentity\": { \"principalId\": \"EXAMPLE\" },\n" + + " \"requestParameters\": { \"sourceIPAddress\": \"127.0.0.1\" },\n" + + " \"responseElements\": { \"x-amz-request-id\": \"REQ\", \"x-amz-id-2\": \"ID\" },\n" + + " \"s3\": {\n" + + " \"s3SchemaVersion\": \"1.0\",\n" + + " \"configurationId\": \"testConfig\",\n" + + " \"bucket\": {\n" + + " \"name\": \"mybucket\",\n" + + " \"ownerIdentity\": { \"principalId\": \"OWNER\" },\n" + + " \"arn\": \"arn:aws:s3:::mybucket\"\n" + + " },\n" + + " \"object\": {\n" + + " \"key\": \"test.txt\",\n" + + " \"size\": 1024,\n" + + " \"eTag\": \"etag\",\n" + + " \"versionId\": \"vid\",\n" + + " \"sequencer\": \"seq\"\n" + + " }\n" + + " }\n" + + " }]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + S3EventNotificationRecord rec = event.getRecords().get(0); + assertThat(rec.getObjectRetentionEventData()).isNull(); + } + + @Test + void writeEvent_withObjectRetentionEventData_roundTrips() { + ObjectRetentionEventData retentionData = new ObjectRetentionEventData( + "COMPLIANCE", "2025-06-15T12:00:00.000Z", "ON", new EventHoldDuration("days", 90L)); + + S3EventNotificationRecord record = new S3EventNotificationRecord( + "us-east-1", + "ObjectRetention:Put", + "aws:s3", + "2024-06-15T12:00:00.000Z", + "2.5", + new RequestParameters("127.0.0.1"), + new ResponseElements("ID2", "REQ1"), + new S3( + "retentionConfig", + new S3Bucket("my-bucket", new UserIdentity("OWNER"), "arn:aws:s3:::my-bucket"), + new S3Object("my-object.txt", 512L, "abc123", "v1", "SEQ1"), + "1.0"), + new UserIdentity("EXAMPLE")); + record.setObjectRetentionEventData(retentionData); + + S3EventNotification event = new S3EventNotification(Collections.singletonList(record)); + String json = event.toJson(); + + assertThat(json).contains("\"objectRetentionEventData\""); + assertThat(json).contains("\"mode\":\"COMPLIANCE\""); + assertThat(json).contains("\"retainUntilDate\":\"2025-06-15T12:00:00.000Z\""); + assertThat(json).contains("\"eventHold\":\"ON\""); + assertThat(json).contains("\"eventHoldDuration\":{\"days\":90}"); + + // Round trip + S3EventNotification parsed = S3EventNotification.fromJson(json); + assertThat(parsed.getRecords().get(0).getObjectRetentionEventData()).isEqualTo(retentionData); + } + + @Test + void writeEvent_withObjectRetentionEventData_noEventHoldDuration_roundTrips() { + ObjectRetentionEventData retentionData = new ObjectRetentionEventData( + "GOVERNANCE", "2030-01-01T00:00:00.000Z", null, null); + + S3EventNotificationRecord record = new S3EventNotificationRecord( + "us-west-2", + "ObjectRetention:Put", + "aws:s3", + "2024-06-15T12:00:00.000Z", + "2.5", + new RequestParameters("10.0.0.1"), + new ResponseElements("ID3", "REQ3"), + new S3( + "retentionConfig", + new S3Bucket("my-bucket", new UserIdentity("OWNER"), "arn:aws:s3:::my-bucket"), + new S3Object("report.csv", 100L, "ghi789", "v3", "SEQ3"), + "1.0"), + new UserIdentity("EXAMPLE")); + record.setObjectRetentionEventData(retentionData); + + S3EventNotification event = new S3EventNotification(Collections.singletonList(record)); + String json = event.toJson(); + + assertThat(json).contains("\"objectRetentionEventData\""); + assertThat(json).contains("\"mode\":\"GOVERNANCE\""); + assertThat(json).doesNotContain("\"eventHold\""); + assertThat(json).doesNotContain("\"eventHoldDuration\""); + + // Round trip + S3EventNotification parsed = S3EventNotification.fromJson(json); + ObjectRetentionEventData parsedRetention = parsed.getRecords().get(0).getObjectRetentionEventData(); + assertThat(parsedRetention).isEqualTo(retentionData); + assertThat(parsedRetention.getEventHold()).isNull(); + assertThat(parsedRetention.getEventHoldDuration()).isNull(); + } + + @Test + void writeEvent_withoutObjectRetentionEventData_fieldOmitted() { + S3EventNotification event = new S3EventNotification( + Collections.singletonList(new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + new RequestParameters("127.0.0.1"), + new ResponseElements("ID", "REQ"), + new S3( + "testConfig", + new S3Bucket("mybucket", new UserIdentity("OWNER"), "arn:aws:s3:::mybucket"), + new S3Object("test.txt", 1024L, "etag", "vid", "seq"), + "1.0"), + new UserIdentity("EXAMPLE")))); + + String json = event.toJson(); + assertThat(json).doesNotContain("objectRetentionEventData"); + } + + @Test + void equalsAndHashCode_sameValues_areEqual() { + EventHoldDuration duration1 = new EventHoldDuration("days", 90L); + EventHoldDuration duration2 = new EventHoldDuration("days", 90L); + assertThat(duration1).isEqualTo(duration2); + assertThat(duration1.hashCode()).isEqualTo(duration2.hashCode()); + + ObjectRetentionEventData data1 = new ObjectRetentionEventData("COMPLIANCE", "2025-01-01T00:00:00Z", "ON", duration1); + ObjectRetentionEventData data2 = new ObjectRetentionEventData("COMPLIANCE", "2025-01-01T00:00:00Z", "ON", duration2); + assertThat(data1).isEqualTo(data2); + assertThat(data1.hashCode()).isEqualTo(data2.hashCode()); + } + + @Test + void equalsAndHashCode_differentValues_areNotEqual() { + EventHoldDuration durationDays = new EventHoldDuration("days", 90L); + EventHoldDuration durationYears = new EventHoldDuration("years", 1L); + assertThat(durationDays).isNotEqualTo(durationYears); + + ObjectRetentionEventData compliance = new ObjectRetentionEventData( + "COMPLIANCE", "2025-01-01T00:00:00Z", "ON", durationDays); + ObjectRetentionEventData governance = new ObjectRetentionEventData( + "GOVERNANCE", "2025-01-01T00:00:00Z", "ON", durationDays); + assertThat(compliance).isNotEqualTo(governance); + } + + @Test + void equalsAndHashCode_nullFields() { + ObjectRetentionEventData allNull = new ObjectRetentionEventData(null, null, null, null); + ObjectRetentionEventData anotherAllNull = new ObjectRetentionEventData(null, null, null, null); + assertThat(allNull).isEqualTo(anotherAllNull); + assertThat(allNull.hashCode()).isEqualTo(anotherAllNull.hashCode()); + + EventHoldDuration nullDuration = new EventHoldDuration(null, null); + EventHoldDuration anotherNullDuration = new EventHoldDuration(null, null); + assertThat(nullDuration).isEqualTo(anotherNullDuration); + assertThat(nullDuration.hashCode()).isEqualTo(anotherNullDuration.hashCode()); + } + + @Test + void toString_containsAllFields() { + EventHoldDuration duration = new EventHoldDuration("days", 90L); + assertThat(duration.toString()).contains("days"); + assertThat(duration.toString()).contains("90"); + + ObjectRetentionEventData data = new ObjectRetentionEventData( + "COMPLIANCE", "2025-01-01T00:00:00Z", "ON", duration); + assertThat(data.toString()).contains("COMPLIANCE"); + assertThat(data.toString()).contains("2025-01-01T00:00:00Z"); + assertThat(data.toString()).contains("ON"); + assertThat(data.toString()).contains("EventHoldDuration"); + } + + @Test + void prettyPrint_withObjectRetentionEventData_formatsCorrectly() { + ObjectRetentionEventData retentionData = new ObjectRetentionEventData( + "COMPLIANCE", "2025-06-15T12:00:00.000Z", "ON", new EventHoldDuration("days", 90L)); + + S3EventNotificationRecord record = new S3EventNotificationRecord( + "us-east-1", + "ObjectRetention:Put", + "aws:s3", + "2024-06-15T12:00:00.000Z", + "2.5", + new RequestParameters("127.0.0.1"), + new ResponseElements("ID2", "REQ1"), + new S3( + "retentionConfig", + new S3Bucket("my-bucket", new UserIdentity("OWNER"), "arn:aws:s3:::my-bucket"), + new S3Object("my-object.txt", 512L, "abc123", "v1", "SEQ1"), + "1.0"), + new UserIdentity("EXAMPLE")); + record.setObjectRetentionEventData(retentionData); + + S3EventNotification event = new S3EventNotification(Collections.singletonList(record)); + String prettyJson = event.toJsonPretty(); + + assertThat(prettyJson).contains("\"objectRetentionEventData\""); + assertThat(prettyJson).contains("\"mode\" : \"COMPLIANCE\""); + assertThat(prettyJson).contains("\"retainUntilDate\" : \"2025-06-15T12:00:00.000Z\""); + assertThat(prettyJson).contains("\"eventHold\" : \"ON\""); + assertThat(prettyJson).contains("\"eventHoldDuration\""); + assertThat(prettyJson).contains("\"days\" : 90"); + + // Round trip from pretty JSON + S3EventNotification parsed = S3EventNotification.fromJson(prettyJson); + assertThat(parsed.getRecords().get(0).getObjectRetentionEventData()).isEqualTo(retentionData); + } +} diff --git a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3BucketTest.java b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3BucketTest.java new file mode 100644 index 000000000000..8e77bae6757a --- /dev/null +++ b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3BucketTest.java @@ -0,0 +1,82 @@ +/* + * 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.eventnotifications.s3.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.LinkedHashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; + +class S3BucketTest { + + @Test + void awsGeneratedTags_nullInput_returnsNull() { + S3Bucket bucket = new S3Bucket("name", new UserIdentity("p"), "arn", null); + assertThat(bucket.getAwsGeneratedTags()).isNull(); + } + + @Test + void threeArgConstructor_leavesAwsGeneratedTagsNull() { + S3Bucket bucket = new S3Bucket("name", new UserIdentity("p"), "arn"); + assertThat(bucket.getAwsGeneratedTags()).isNull(); + } + + @Test + void toString_omitsAwsGeneratedTags_whenNull() { + S3Bucket bucket = new S3Bucket("mybucket", new UserIdentity("p"), "arn:aws:s3:::mybucket"); + assertThat(bucket.toString()).doesNotContain("awsGeneratedTags"); + } + + @Test + void toString_includesAwsGeneratedTags_whenPresent() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", "123456789012"); + tags.put("aws:resource:region", "us-west-2"); + + S3Bucket bucket = new S3Bucket("mybucket", new UserIdentity("p"), "arn:aws:s3:::mybucket", tags); + assertThat(bucket.toString()) + .contains("awsGeneratedTags={aws:resource:owner=123456789012, aws:resource:region=us-west-2}"); + } + + @Test + void awsGeneratedTags_isDefensivelyCopied() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", "123456789012"); + + S3Bucket bucket = new S3Bucket("mybucket", new UserIdentity("p"), "arn:aws:s3:::mybucket", tags); + + // Mutating the caller's map after construction must not affect the bucket. + tags.put("aws:resource:region", "us-west-2"); + tags.remove("aws:resource:owner"); + + assertThat(bucket.getAwsGeneratedTags()) + .containsExactly(new java.util.AbstractMap.SimpleEntry<>("aws:resource:owner", "123456789012")); + } + + @Test + void getAwsGeneratedTags_isUnmodifiable() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", "123456789012"); + + S3Bucket bucket = new S3Bucket("mybucket", new UserIdentity("p"), "arn:aws:s3:::mybucket", tags); + + Map returned = bucket.getAwsGeneratedTags(); + assertThatThrownBy(() -> returned.put("aws:resource:region", "us-west-2")) + .isInstanceOf(UnsupportedOperationException.class); + } +} 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 fe1c199e07a8..1a0f30efd8ee 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 @@ -22,6 +22,8 @@ import java.time.Instant; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData; import software.amazon.awssdk.eventnotifications.s3.model.IntelligentTieringEventData; @@ -49,7 +51,7 @@ void fromJson_containsNullValues_shouldSucceed() { "ObjectCreated:Put", "aws:s3", "1970-01-01T00:00:00.000Z", - "2.4", + "2.5", null, new ResponseElements( null, null), @@ -73,7 +75,7 @@ void fromJson_containsNullValues_shouldSucceed() { String json = eventNotification.toJsonPretty(); assertThat(json).isEqualTo("{\n" + " \"Records\" : [ {\n" - + " \"eventVersion\" : \"2.4\",\n" + + " \"eventVersion\" : \"2.5\",\n" + " \"eventSource\" : \"aws:s3\",\n" + " \"awsRegion\" : \"us-west-2\",\n" + " \"eventTime\" : \"1970-01-01T00:00:00Z\",\n" @@ -115,7 +117,7 @@ void givenEventWithoutOptionalFields_whenReadingJson_expectOnlyRequiredFields() String eventJson = "{ " + " \"Records\":[ " + " { " - + " \"eventVersion\":\"2.4\"," + + " \"eventVersion\":\"2.5\"," + " \"eventSource\":\"aws:s3\"," + " \"awsRegion\":\"us-west-2\"," + " \"eventTime\":\"1970-01-01T00:00:00.000Z\"," @@ -163,7 +165,7 @@ void givenEventWithoutOptionalFields_whenReadingJson_expectOnlyRequiredFields() "ObjectCreated:Put", "aws:s3", "1970-01-01T00:00:00.000Z", - "2.4", + "2.5", new RequestParameters("127.0.0.1"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD", "C3D13FE58DE4C810"), @@ -192,7 +194,7 @@ void givenEventWithoutOptionalFields_whenReadingJson_expectOnlyRequiredFields() 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.4"); + assertThat(rec.getEventVersion()).isEqualTo("2.5"); UserIdentity userIdentity = rec.getUserIdentity(); assertThat(userIdentity).isNotNull(); @@ -238,7 +240,7 @@ void givenEventContainingOptionalFields_whenReadingJson_expectAllFields() { String eventJson = "{\n" + " \"Records\":[\n" + " {\n" - + " \"eventVersion\":\"2.4\",\n" + + " \"eventVersion\":\"2.5\",\n" + " \"eventSource\":\"aws:s3\",\n" + " \"awsRegion\":\"us-west-2\",\n" + " \"eventTime\":\"1970-01-01T00:00:00.000Z\",\n" @@ -313,7 +315,7 @@ void givenEventContainingOptionalFields_whenReadingJson_expectAllFields() { "ObjectCreated:Put", "aws:s3", "1970-01-01T00:00:00.000Z", - "2.4", + "2.5", new RequestParameters("127.0.0.1"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD", "C3D13FE58DE4C810"), @@ -419,7 +421,7 @@ void emptyRecordList_shouldContainEmptyRecordList() { void missingField_shouldBeNull() { String json = "{\n" + " \"Records\" : [ {\n" - + " \"eventVersion\" : \"2.4\",\n" + + " \"eventVersion\" : \"2.5\",\n" + " \"eventSource\" : \"aws:s3\",\n" + " \"awsRegion\" : \"us-west-2\",\n" + " \"eventTime\" : \"1970-01-01T01:01:01.001Z\",\n" @@ -463,7 +465,7 @@ void missingField_shouldBeNull() { void eventTimeIsNullWhenEventNamePresent_shouldSucceed() { String json = "{\n" + " \"Records\" : [ {\n" - + " \"eventVersion\" : \"2.4\",\n" + + " \"eventVersion\" : \"2.5\",\n" + " \"eventSource\" : \"aws:s3\",\n" + " \"awsRegion\" : \"us-west-2\",\n" // missing eventTime @@ -525,7 +527,7 @@ void fromJsonInputStream_handlesCorrectly() { String eventJson = "{ " + " \"Records\":[ " + " { " - + " \"eventVersion\":\"2.4\"," + + " \"eventVersion\":\"2.5\"," + " \"eventSource\":\"aws:s3\"," + " \"awsRegion\":\"us-west-2\"," + " \"eventTime\":\"1970-01-01T00:00:00.000Z\"," @@ -575,7 +577,7 @@ void fromJsonInputStream_handlesCorrectly() { "ObjectCreated:Put", "aws:s3", "1970-01-01T00:00:00.000Z", - "2.4", + "2.5", new RequestParameters("127.0.0.1"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD", "C3D13FE58DE4C810"), @@ -608,7 +610,7 @@ void fromJsonInputStream_handlesCorrectly() { 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.4"); + assertThat(rec.getEventVersion()).isEqualTo("2.5"); UserIdentity userIdentity = rec.getUserIdentity(); assertThat(userIdentity).isNotNull(); @@ -655,4 +657,249 @@ void fromJsonInputStream_handlesCorrectly() { assertThat(rec.getReplicationEventData()).isNull(); } + + @Test + void awsGeneratedTags_whenPresent_isParsed() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"eventVersion\" : \"2.5\",\n" + + " \"eventSource\" : \"aws:s3\",\n" + + " \"awsRegion\" : \"us-west-2\",\n" + + " \"eventTime\" : \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\" : \"ObjectCreated:Put\",\n" + + " \"s3\" : {\n" + + " \"s3SchemaVersion\" : \"1.0\",\n" + + " \"configurationId\" : \"testConfigRule\",\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"ownerIdentity\" : {\n" + + " \"principalId\" : \"A3NL1KOZZKExample\"\n" + + " },\n" + + " \"arn\" : \"arn:aws:s3:::mybucket\",\n" + + " \"awsGeneratedTags\" : {\n" + + " \"aws:resource:owner\" : \"123456789012\",\n" + + " \"aws:resource:region\" : \"us-west-2\"\n" + + " }\n" + + " },\n" + + " \"object\" : {\n" + + " \"key\" : \"HappyFace.jpg\",\n" + + " \"size\" : 1024,\n" + + " \"eTag\" : \"d41d8cd98f00b204e9800998ecf8427e\",\n" + + " \"versionId\" : \"096fKKXTRTtl3on89fVO.nfljtsv6qko\",\n" + + " \"sequencer\" : \"0055AED6DCD90281E5\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + S3Bucket bucket = event.getRecords().get(0).getS3().getBucket(); + + Map expectedTags = new LinkedHashMap<>(); + expectedTags.put("aws:resource:owner", "123456789012"); + expectedTags.put("aws:resource:region", "us-west-2"); + assertThat(bucket.getAwsGeneratedTags()).containsExactlyEntriesOf(expectedTags); + } + + @Test + void awsGeneratedTags_whenAbsent_isNull() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"eventVersion\" : \"2.5\",\n" + + " \"eventSource\" : \"aws:s3\",\n" + + " \"awsRegion\" : \"us-west-2\",\n" + + " \"eventTime\" : \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\" : \"ObjectCreated:Put\",\n" + + " \"s3\" : {\n" + + " \"s3SchemaVersion\" : \"1.0\",\n" + + " \"configurationId\" : \"testConfigRule\",\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"ownerIdentity\" : {\n" + + " \"principalId\" : \"A3NL1KOZZKExample\"\n" + + " },\n" + + " \"arn\" : \"arn:aws:s3:::mybucket\"\n" + + " },\n" + + " \"object\" : {\n" + + " \"key\" : \"HappyFace.jpg\",\n" + + " \"size\" : 1024,\n" + + " \"eTag\" : \"d41d8cd98f00b204e9800998ecf8427e\",\n" + + " \"versionId\" : \"096fKKXTRTtl3on89fVO.nfljtsv6qko\",\n" + + " \"sequencer\" : \"0055AED6DCD90281E5\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + assertThat(event.getRecords().get(0).getS3().getBucket().getAwsGeneratedTags()).isNull(); + } + + @Test + void awsGeneratedTags_whenEmpty_isEmptyMap() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"eventVersion\" : \"2.5\",\n" + + " \"eventSource\" : \"aws:s3\",\n" + + " \"awsRegion\" : \"us-west-2\",\n" + + " \"eventTime\" : \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\" : \"ObjectCreated:Put\",\n" + + " \"s3\" : {\n" + + " \"s3SchemaVersion\" : \"1.0\",\n" + + " \"configurationId\" : \"testConfigRule\",\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"ownerIdentity\" : {\n" + + " \"principalId\" : \"A3NL1KOZZKExample\"\n" + + " },\n" + + " \"arn\" : \"arn:aws:s3:::mybucket\",\n" + + " \"awsGeneratedTags\" : {}\n" + + " },\n" + + " \"object\" : {\n" + + " \"key\" : \"HappyFace.jpg\",\n" + + " \"size\" : 1024,\n" + + " \"eTag\" : \"d41d8cd98f00b204e9800998ecf8427e\",\n" + + " \"versionId\" : \"096fKKXTRTtl3on89fVO.nfljtsv6qko\",\n" + + " \"sequencer\" : \"0055AED6DCD90281E5\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + assertThat(event.getRecords().get(0).getS3().getBucket().getAwsGeneratedTags()).isEmpty(); + } + + @Test + void awsGeneratedTags_withEmptyStringValue_isPreservedAsEmptyString() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"eventVersion\" : \"2.5\",\n" + + " \"eventSource\" : \"aws:s3\",\n" + + " \"awsRegion\" : \"us-west-2\",\n" + + " \"eventTime\" : \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\" : \"ObjectCreated:Put\",\n" + + " \"s3\" : {\n" + + " \"s3SchemaVersion\" : \"1.0\",\n" + + " \"configurationId\" : \"testConfigRule\",\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"ownerIdentity\" : { \"principalId\" : \"A3NL1KOZZKExample\" },\n" + + " \"arn\" : \"arn:aws:s3:::mybucket\",\n" + + " \"awsGeneratedTags\" : {\n" + + " \"aws:resource:owner\" : \"\"\n" + + " }\n" + + " },\n" + + " \"object\" : {\n" + + " \"key\" : \"HappyFace.jpg\",\n" + + " \"size\" : 1024,\n" + + " \"eTag\" : \"d41d8cd98f00b204e9800998ecf8427e\",\n" + + " \"versionId\" : \"096fKKXTRTtl3on89fVO.nfljtsv6qko\",\n" + + " \"sequencer\" : \"0055AED6DCD90281E5\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + Map tags = event.getRecords().get(0).getS3().getBucket().getAwsGeneratedTags(); + assertThat(tags).containsEntry("aws:resource:owner", ""); + } + + @Test + void awsGeneratedTags_withNullValue_isPreservedAsNull() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"eventVersion\" : \"2.5\",\n" + + " \"eventSource\" : \"aws:s3\",\n" + + " \"awsRegion\" : \"us-west-2\",\n" + + " \"eventTime\" : \"1970-01-01T00:00:00.000Z\",\n" + + " \"eventName\" : \"ObjectCreated:Put\",\n" + + " \"s3\" : {\n" + + " \"s3SchemaVersion\" : \"1.0\",\n" + + " \"configurationId\" : \"testConfigRule\",\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"ownerIdentity\" : { \"principalId\" : \"A3NL1KOZZKExample\" },\n" + + " \"arn\" : \"arn:aws:s3:::mybucket\",\n" + + " \"awsGeneratedTags\" : {\n" + + " \"aws:resource:owner\" : null,\n" + + " \"aws:resource:region\" : \"us-west-2\"\n" + + " }\n" + + " },\n" + + " \"object\" : {\n" + + " \"key\" : \"HappyFace.jpg\",\n" + + " \"size\" : 1024,\n" + + " \"eTag\" : \"d41d8cd98f00b204e9800998ecf8427e\",\n" + + " \"versionId\" : \"096fKKXTRTtl3on89fVO.nfljtsv6qko\",\n" + + " \"sequencer\" : \"0055AED6DCD90281E5\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(json); + Map tags = event.getRecords().get(0).getS3().getBucket().getAwsGeneratedTags(); + assertThat(tags).containsEntry("aws:resource:owner", null); + assertThat(tags).containsEntry("aws:resource:region", "us-west-2"); + } + + @Test + void awsGeneratedTags_withNonStringValue_throws() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"s3\" : {\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"awsGeneratedTags\" : {\n" + + " \"aws:resource:owner\" : 123\n" + + " }\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + assertThatThrownBy(() -> S3EventNotification.fromJson(json)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("The value of tag 'aws:resource:owner' in 'awsGeneratedTags' was not a string, but was: 123"); + } + + @Test + void awsGeneratedTags_withBooleanValue_throws() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"s3\" : {\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"awsGeneratedTags\" : {\n" + + " \"aws:resource:owner\" : true\n" + + " }\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + assertThatThrownBy(() -> S3EventNotification.fromJson(json)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("The value of tag 'aws:resource:owner' in 'awsGeneratedTags' was not a string, but was: true"); + } + + @Test + void awsGeneratedTags_notAnObject_throws() { + String json = "{\n" + + " \"Records\" : [ {\n" + + " \"s3\" : {\n" + + " \"bucket\" : {\n" + + " \"name\" : \"mybucket\",\n" + + " \"awsGeneratedTags\" : \"not-an-object\"\n" + + " }\n" + + " }\n" + + " } ]\n" + + "}"; + + assertThatThrownBy(() -> S3EventNotification.fromJson(json)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("expected 'awsGeneratedTags' to be an object, but was not."); + } + } diff --git a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationWriterTest.java b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationWriterTest.java index a9b9beca7734..248536bdc1f8 100644 --- a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationWriterTest.java +++ b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationWriterTest.java @@ -19,6 +19,8 @@ import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; import org.junit.jupiter.api.Test; import software.amazon.awssdk.eventnotifications.s3.model.GlacierEventData; import software.amazon.awssdk.eventnotifications.s3.model.IntelligentTieringEventData; @@ -46,7 +48,7 @@ void testPrettyPrint_requiredFieldOnly() { "ObjectCreated:Get", "aws:s3", "1970-01-01T01:01:01.001Z", - "2.4", + "2.5", new RequestParameters("127.1.2.3"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANxid2", "C3D13FE58DE4CRID"), @@ -70,7 +72,7 @@ void testPrettyPrint_requiredFieldOnly() { String expected = "{\n" + " \"Records\" : [ {\n" - + " \"eventVersion\" : \"2.4\",\n" + + " \"eventVersion\" : \"2.5\",\n" + " \"eventSource\" : \"aws:s3\",\n" + " \"awsRegion\" : \"us-west-2\",\n" + " \"eventTime\" : \"1970-01-01T01:01:01.001Z\",\n" @@ -110,7 +112,7 @@ void testPrettyPrint_requiredFieldOnly() { @Test void testToJson_requiredFielsdOnly() { - String expected = "{\"Records\":[{\"eventVersion\":\"2.4\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-west-2\"," + String expected = "{\"Records\":[{\"eventVersion\":\"2.5\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"us-west-2\"," + "\"eventTime\":\"1970-01-01T01:01:01.001Z\",\"eventName\":\"ObjectCreated:Get\"," + "\"userIdentity\":{\"principalId\"" + ":\"AIDAJDPLRKLG7UEXAMUID\"},\"requestParameters\":{\"sourceIPAddress\":\"127.1.2.3\"}," @@ -128,7 +130,7 @@ void testToJson_requiredFielsdOnly() { "ObjectCreated:Get", "aws:s3", "1970-01-01T01:01:01.001Z", - "2.4", + "2.5", new RequestParameters("127.1.2.3"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANxid2", "C3D13FE58DE4CRID"), @@ -156,7 +158,7 @@ void testToJson_requiredFielsdOnly() { void testPrettyPrint_allFields() { String expected = "{\n" + " \"Records\" : [ {\n" - + " \"eventVersion\" : \"2.4\",\n" + + " \"eventVersion\" : \"2.5\",\n" + " \"eventSource\" : \"aws:s3\",\n" + " \"awsRegion\" : \"us-west-2\",\n" + " \"eventTime\" : \"1970-01-01T01:01:01.001Z\",\n" @@ -226,7 +228,7 @@ void testPrettyPrint_allFields() { "ObjectCreated:Put", "aws:s3", "1970-01-01T01:01:01.001Z", - "2.4", + "2.5", new RequestParameters("127.0.0.1"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD", "C3D13FE58DE4C810"), @@ -267,7 +269,7 @@ void testPrettyPrint_allFields() { @Test void testToJson_allFields() { - String expected = "{\"Records\":[{\"eventVersion\":\"2.4\",\"eventSource\":\"aws:s3\",\"awsRegion\":" + String expected = "{\"Records\":[{\"eventVersion\":\"2.5\",\"eventSource\":\"aws:s3\",\"awsRegion\":" + "\"us-west-2\",\"eventTime\":\"1970-01-01T01:01:01.001Z\",\"eventName\":\"ObjectCreated:Get\"," + "\"userIdentity\":{\"principalId\":\"PRINCIPALIDTEST\"},\"requestParameters\":{\"sourceIPAddress\":" + "\"127.1.2.3\"},\"responseElements\":{\"x-amz-request-id\":\"C3D13FE58DE4CRID\",\"x-amz-id-2\":" @@ -292,7 +294,7 @@ void testToJson_allFields() { "ObjectCreated:Get", "aws:s3", "1970-01-01T01:01:01.001Z", - "2.4", + "2.5", new RequestParameters("127.1.2.3"), new ResponseElements( "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANxid2", "C3D13FE58DE4CRID"), @@ -388,4 +390,188 @@ void nullableNumberFieldsHandledCorrectly() { assertThat(event.toJson()).isEqualTo(expected); } + + @Test + void awsGeneratedTags_whenSet_isWritten() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", "123456789012"); + tags.put("aws:resource:region", "us-west-2"); + + S3EventNotification event = new S3EventNotification(Collections.singletonList( + new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + null, + null, + new S3( + "testConfigRule", + new S3Bucket( + "mybucket", + new UserIdentity("A3NL1KOZZKExample"), + "arn:aws:s3:::mybucket", + tags), + new S3Object( + "HappyFace.jpg", + 1024L, + "d41d8cd98f00b204e9800998ecf8427e", + "096fKKXTRTtl3on89fVO.nfljtsv6qko", + "0055AED6DCD90281E5"), + "1.0"), + new UserIdentity("AIDAJDPLRKLG7UEXAMPLE")) + )); + + String json = event.toJson(); + assertThat(json).contains("\"arn\":\"arn:aws:s3:::mybucket\"," + + "\"awsGeneratedTags\":{" + + "\"aws:resource:owner\":\"123456789012\"," + + "\"aws:resource:region\":\"us-west-2\"" + + "}"); + + // Round trip + assertThat(S3EventNotification.fromJson(json)).isEqualTo(event); + } + + @Test + void awsGeneratedTags_whenNull_isOmitted() { + S3EventNotification event = new S3EventNotification(Collections.singletonList( + new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + null, + null, + 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.toJson()).doesNotContain("awsGeneratedTags"); + } + + @Test + void awsGeneratedTags_withNullValue_isWritten() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", null); + tags.put("aws:resource:region", "us-west-2"); + + S3EventNotification event = new S3EventNotification(Collections.singletonList( + new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + null, + null, + new S3( + "testConfigRule", + new S3Bucket( + "mybucket", + new UserIdentity("A3NL1KOZZKExample"), + "arn:aws:s3:::mybucket", + tags), + new S3Object( + "HappyFace.jpg", + 1024L, + "d41d8cd98f00b204e9800998ecf8427e", + "096fKKXTRTtl3on89fVO.nfljtsv6qko", + "0055AED6DCD90281E5"), + "1.0"), + new UserIdentity("AIDAJDPLRKLG7UEXAMPLE")) + )); + + String json = event.toJson(); + assertThat(json).contains("\"awsGeneratedTags\":{" + + "\"aws:resource:owner\":null," + + "\"aws:resource:region\":\"us-west-2\"" + + "}"); + + // Round trip + assertThat(S3EventNotification.fromJson(json)).isEqualTo(event); + } + + @Test + void awsGeneratedTags_withEmptyStringValue_isWritten() { + Map tags = new LinkedHashMap<>(); + tags.put("aws:resource:owner", ""); + + S3EventNotification event = new S3EventNotification(Collections.singletonList( + new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + null, + null, + new S3( + "testConfigRule", + new S3Bucket( + "mybucket", + new UserIdentity("A3NL1KOZZKExample"), + "arn:aws:s3:::mybucket", + tags), + new S3Object( + "HappyFace.jpg", + 1024L, + "d41d8cd98f00b204e9800998ecf8427e", + "096fKKXTRTtl3on89fVO.nfljtsv6qko", + "0055AED6DCD90281E5"), + "1.0"), + new UserIdentity("AIDAJDPLRKLG7UEXAMPLE")) + )); + + String json = event.toJson(); + assertThat(json).contains("\"awsGeneratedTags\":{\"aws:resource:owner\":\"\"}"); + + // Round trip + assertThat(S3EventNotification.fromJson(json)).isEqualTo(event); + } + + @Test + void awsGeneratedTags_whenEmpty_isOmitted() { + S3EventNotification event = new S3EventNotification(Collections.singletonList( + new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.5", + null, + null, + new S3( + "testConfigRule", + new S3Bucket( + "mybucket", + new UserIdentity("A3NL1KOZZKExample"), + "arn:aws:s3:::mybucket", + Collections.emptyMap()), + new S3Object( + "HappyFace.jpg", + 1024L, + "d41d8cd98f00b204e9800998ecf8427e", + "096fKKXTRTtl3on89fVO.nfljtsv6qko", + "0055AED6DCD90281E5"), + "1.0"), + new UserIdentity("AIDAJDPLRKLG7UEXAMPLE")) + )); + + assertThat(event.toJson()).doesNotContain("awsGeneratedTags"); + } } diff --git a/services-custom/s3-transfer-manager/pom.xml b/services-custom/s3-transfer-manager/pom.xml index fcc302752f37..f7996292ba99 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml s3-transfer-manager @@ -185,11 +185,6 @@ commons-lang3 test - - org.reactivestreams - reactive-streams-tck - test - com.google.jimfs jimfs diff --git a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3IntegrationTestBase.java b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3IntegrationTestBase.java index 07ca3eb0cb45..9385b577f105 100644 --- a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3IntegrationTestBase.java +++ b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3IntegrationTestBase.java @@ -57,11 +57,13 @@ public class S3IntegrationTestBase extends AwsTestBase { protected static S3Client s3; protected static S3AsyncClient s3Async; + protected static S3AsyncClient s3NonMultipartAsync; protected static S3AsyncClient s3CrtAsync; protected static S3TransferManager tmCrt; protected static S3TransferManager tmJava; + protected static S3TransferManager tmNonMultipartJava; /** * Loads the AWS account info for the integration tests and creates an S3 @@ -73,6 +75,11 @@ public static void setUpForAllIntegTests() throws Exception { System.setProperty("aws.crt.debugnative", "true"); s3 = s3ClientBuilder().build(); s3Async = s3AsyncClientBuilder().build(); + s3NonMultipartAsync = S3AsyncClient.builder() + .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) + .region(DEFAULT_REGION) + .build(); + s3CrtAsync = S3CrtAsyncClient.builder() .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) .region(DEFAULT_REGION) @@ -84,6 +91,9 @@ public static void setUpForAllIntegTests() throws Exception { tmJava = S3TransferManager.builder() .s3Client(s3Async) .build(); + tmNonMultipartJava = S3TransferManager.builder() + .s3Client(s3NonMultipartAsync) + .build(); } @@ -91,8 +101,11 @@ public static void setUpForAllIntegTests() throws Exception { public static void cleanUpForAllIntegTests() { s3.close(); s3Async.close(); + s3NonMultipartAsync.close(); s3CrtAsync.close(); tmCrt.close(); + tmJava.close(); + tmNonMultipartJava.close(); CrtResource.waitForNoResources(); } @@ -188,4 +201,11 @@ static Stream transferManagers() { Arguments.of(tmJava)); } + static Stream presignedUrlTransferManagers() { + return Stream.of( + // TODO: uncomment when CRT for presigned URL is supported + // Arguments.of(tmCrt), + Arguments.of(tmNonMultipartJava), + Arguments.of(tmJava)); + } } diff --git a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerDownloadPauseResumeIntegrationTest.java b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerDownloadPauseResumeIntegrationTest.java index 1d53c6099481..122804c507b6 100644 --- a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerDownloadPauseResumeIntegrationTest.java +++ b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerDownloadPauseResumeIntegrationTest.java @@ -26,7 +26,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; -import java.util.Optional; import org.apache.commons.lang3.RandomStringUtils; import org.apache.logging.log4j.Level; import org.assertj.core.api.Assertions; @@ -35,12 +34,11 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.core.waiters.Waiter; import software.amazon.awssdk.core.waiters.WaiterAcceptor; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.testutils.LogCaptor; @@ -94,7 +92,10 @@ void pauseAndResume_ObjectEtagChange_shouldRestartDownload(S3TransferManager tm) ResumableFileDownload resumableFileDownload = download.pause(); log.debug(() -> "Paused: " + resumableFileDownload); - String originalEtag = testDownloadListener.getObjectResponse.eTag(); + // The ETag has to be read off the resume token rather than the progress snapshot: when CRT writes the body directly + // to the file, the SDK never sees the GetObjectResponse until the transfer finishes. + String originalEtag = resumableFileDownload.s3ObjectEtag().orElse(null); + assertThat(originalEtag).isNotNull(); File newSourceFile = new RandomTempFile(OBJ_SIZE); PutObjectResponse putResponse = s3.putObject(PutObjectRequest.builder() @@ -149,12 +150,13 @@ void pauseAndResume_ObjectNotChanged_shouldResumeDownload(S3TransferManager tm) long bytesTransferred = resumableFileDownload.bytesTransferred(); log.debug(() -> "Paused: " + resumableFileDownload); assertEqualsBySdkFields(resumableFileDownload.downloadFileRequest(), request); - assertThat(testDownloadListener.getObjectResponse).isNotNull(); // Skip the test if everything has been downloaded. Assumptions.assumeTrue(resumableFileDownload.bytesTransferred() < sourceFile.length()); - assertThat(resumableFileDownload.s3ObjectLastModified()).hasValue(testDownloadListener.getObjectResponse.lastModified()); + HeadObjectResponse headObjectResponse = s3.headObject(b -> b.bucket(BUCKET).key(KEY)); + assertThat(resumableFileDownload.s3ObjectLastModified()).hasValue(headObjectResponse.lastModified()); + assertThat(resumableFileDownload.s3ObjectEtag()).hasValue(headObjectResponse.eTag()); // Request may not be cancelled right away when pause is invoked, so there may be more bytes written to the file assertThat(bytesTransferred).isLessThanOrEqualTo(path.toFile().length()); assertThat(resumableFileDownload.totalSizeInBytes()).hasValue(sourceFile.length()); @@ -254,20 +256,11 @@ private static void waitUntilFirstByteBufferDelivered(FileDownload download) { private static final class TestDownloadListener implements TransferListener { private int transferInitiatedCount = 0; - private GetObjectResponse getObjectResponse; @Override public void transferInitiated(Context.TransferInitiated context) { transferInitiatedCount++; } - - @Override - public void bytesTransferred(Context.BytesTransferred context) { - Optional sdkResponse = context.progressSnapshot().sdkResponse(); - if (sdkResponse.isPresent() && sdkResponse.get() instanceof GetObjectResponse) { - getObjectResponse = (GetObjectResponse) sdkResponse.get(); - } - } } } diff --git a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerPresignedUrlDownloadIntegrationTest.java b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerPresignedUrlDownloadIntegrationTest.java new file mode 100644 index 000000000000..003fddb5d5b7 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerPresignedUrlDownloadIntegrationTest.java @@ -0,0 +1,211 @@ +/* + * 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.transfer.s3; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +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.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; +import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; +import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.testutils.RandomTempFile; +import software.amazon.awssdk.transfer.s3.model.CompletedDownload; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; +import software.amazon.awssdk.transfer.s3.model.Download; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; +import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener; +import software.amazon.awssdk.utils.Md5Utils; + +public class S3TransferManagerPresignedUrlDownloadIntegrationTest extends S3IntegrationTestBase { + private static final String BUCKET = temporaryBucketName(S3TransferManagerPresignedUrlDownloadIntegrationTest.class); + private static final String SMALL_KEY = "small-key"; + private static final String LARGE_KEY = "large-key"; + private static final int SMALL_OBJ_SIZE = 5 * 1024 * 1024; + private static final int LARGE_OBJ_SIZE = 16 * 1024 * 1024; + + private static File smallFile; + private static File largeFile; + private static S3Presigner presigner; + + @BeforeAll + public static void setup() throws IOException { + createBucket(BUCKET); + smallFile = new RandomTempFile(SMALL_OBJ_SIZE); + largeFile = new RandomTempFile(LARGE_OBJ_SIZE); + s3.putObject(PutObjectRequest.builder().bucket(BUCKET).key(SMALL_KEY).build(), smallFile.toPath()); + s3.putObject(PutObjectRequest.builder().bucket(BUCKET).key(LARGE_KEY).build(), largeFile.toPath()); + presigner = S3Presigner.builder() + .region(DEFAULT_REGION) + .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) + .build(); + } + + @AfterAll + public static void cleanup() { + if (presigner != null) { + presigner.close(); + } + deleteBucketAndAllContents(BUCKET); + } + + static Stream testCases() { + return presignedUrlTransferManagers().flatMap(tmArg -> Stream.of( + Arguments.of(tmArg.get()[0], SMALL_KEY, smallFile, SMALL_OBJ_SIZE), + Arguments.of(tmArg.get()[0], LARGE_KEY, largeFile, LARGE_OBJ_SIZE) + )); + } + + @ParameterizedTest(name = "downloadFileWithPresignedUrl_{1}") + @MethodSource("testCases") + void downloadFileWithPresignedUrl_shouldDownloadCorrectly(S3TransferManager tm, String key, + File sourceFile, int objSize) throws Exception { + Path downloadPath = RandomTempFile.randomUncreatedFile().toPath(); + PresignedFileDownload download = tm.downloadFileWithPresignedUrl(createFileDownloadRequest(key, downloadPath)); + CompletedFileDownload completed = download.completionFuture().join(); + + assertThat(Files.exists(downloadPath)).isTrue(); + assertThat(Md5Utils.md5AsBase64(downloadPath.toFile())).isEqualTo(Md5Utils.md5AsBase64(sourceFile)); + assertThat(completed.response().responseMetadata().requestId()).isNotNull(); + } + + @ParameterizedTest(name = "downloadWithPresignedUrl_toBytes_{1}") + @MethodSource("testCases") + void downloadWithPresignedUrl_toBytes_shouldReturnCorrectData(S3TransferManager tm, String key, + File sourceFile, int objSize) { + CompletedDownload> completed = + tm.downloadWithPresignedUrl(createBytesDownloadRequest(key)).completionFuture().join(); + + assertThat(completed.result().asByteArray()).hasSize(objSize); + } + + static Stream progressTestCases() { + return Stream.of( + Arguments.of("multipart", tmJava, LARGE_KEY, null, LARGE_OBJ_SIZE), + Arguments.of("multipart", tmJava, LARGE_KEY, "bytes=0-1048575", 1048576), + Arguments.of("nonMultipart", tmNonMultipartJava, LARGE_KEY, null, LARGE_OBJ_SIZE), + Arguments.of("nonMultipart", tmNonMultipartJava, LARGE_KEY, "bytes=0-1048575", 1048576) + ); + } + + @ParameterizedTest(name = "downloadFileWithPresignedUrl_progress_{0}_range={3}") + @MethodSource("progressTestCases") + void downloadFileWithPresignedUrl_progressTracking(String tmType, S3TransferManager tm, String key, + String range, int expectedSize) throws Exception { + Path downloadPath = RandomTempFile.randomUncreatedFile().toPath(); + + PresignedUrlDownloadRequest.Builder requestBuilder = PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedRequest(key).url()); + if (range != null) { + requestBuilder.range(range); + } + + PresignedFileDownload download = tm.downloadFileWithPresignedUrl( + PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(requestBuilder.build()) + .destination(downloadPath) + .addTransferListener(LoggingTransferListener.create()) + .build()); + + download.completionFuture().join(); + + // Verify progress tracking worked - totalBytes is set correctly + assertThat(download.progress().snapshot().totalBytes()).isPresent(); + assertThat(download.progress().snapshot().totalBytes().getAsLong()).isEqualTo(expectedSize); + + // Verify transferredBytes reached expectedSize + assertThat(download.progress().snapshot().transferredBytes()).isEqualTo(expectedSize); + + // Verify file size matches expected + assertThat(downloadPath.toFile().length()).isEqualTo(expectedSize); + } + + @ParameterizedTest(name = "downloadWithPresignedUrl_toBytes_progress_{0}_range={3}") + @MethodSource("progressTestCases") + void downloadWithPresignedUrl_toBytes_progressTracking(String tmType, S3TransferManager tm, String key, + String range, int expectedSize) throws Exception { + + PresignedUrlDownloadRequest.Builder requestBuilder = PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedRequest(key).url()); + if (range != null) { + requestBuilder.range(range); + } + + Download> download = tm.downloadWithPresignedUrl( + PresignedDownloadRequest.>builder() + .presignedUrlDownloadRequest(requestBuilder.build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .addTransferListener(LoggingTransferListener.create()) + .build()); + + CompletedDownload> completed = download.completionFuture().join(); + + assertThat(download.progress().snapshot().totalBytes()).isPresent(); + assertThat(download.progress().snapshot().totalBytes().getAsLong()).isEqualTo(expectedSize); + + assertThat(download.progress().snapshot().transferredBytes()).isEqualTo(expectedSize); + + assertThat(completed.result().asByteArray()).hasSize(expectedSize); + } + + private static PresignedDownloadFileRequest createFileDownloadRequest(String key, Path destination) { + return PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedRequest(key).url()) + .build()) + .destination(destination) + .addTransferListener(LoggingTransferListener.create()) + .build(); + } + + private static PresignedDownloadRequest> createBytesDownloadRequest(String key) { + return PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedRequest(key).url()) + .build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .addTransferListener(LoggingTransferListener.create()) + .build(); + } + + private static PresignedGetObjectRequest createPresignedRequest(String key) { + return presigner.presignGetObject(GetObjectPresignRequest.builder() + .signatureDuration(Duration.ofMinutes(10)) + .getObjectRequest(GetObjectRequest.builder() + .bucket(BUCKET) + .key(key) + .build()) + .build()); + } +} 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 f8e51246fa66..84a6939f67fa 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 @@ -31,10 +31,13 @@ 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.ResponseInputStream; import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy; +import software.amazon.awssdk.core.sync.ResponseTransformer; 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.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse; import software.amazon.awssdk.services.s3.model.ListPartsResponse; import software.amazon.awssdk.services.s3.model.NoSuchUploadException; @@ -43,6 +46,7 @@ import software.amazon.awssdk.transfer.s3.model.ResumableFileUpload; import software.amazon.awssdk.transfer.s3.model.UploadFileRequest; import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener; +import software.amazon.awssdk.transfer.s3.util.ChecksumUtils; import software.amazon.awssdk.utils.Logger; public class S3TransferManagerUploadPauseResumeIntegrationTest extends S3IntegrationTestBase { @@ -167,7 +171,12 @@ void pause_fileChanged_resumeShouldStartFromBeginning(S3TransferManager uploadTm FileUpload resumedUpload = resumeTm.resumeUploadFile(resumableFileUpload); resumedUpload.completionFuture().join(); verifyMultipartUploadIdNotExist(resumableFileUpload); - assertThat(resumedUpload.progress().snapshot().totalBytes()).hasValue(bytes.length); + + // Verify via S3 checksum instead of progress snapshot, which may be empty for cross-TM resume + ResponseInputStream obj = + s3.getObject(r -> r.bucket(BUCKET).key(KEY), ResponseTransformer.toInputStream()); + assertThat(ChecksumUtils.computeCheckSum(bytes)) + .isEqualTo(ChecksumUtils.computeCheckSum(obj)); } finally { Files.write(largeFile.toPath(), originalBytes); } diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/S3TransferManager.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/S3TransferManager.java index 6bdc2c12d580..b42582395a19 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/S3TransferManager.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/S3TransferManager.java @@ -43,6 +43,9 @@ import software.amazon.awssdk.transfer.s3.model.DownloadRequest; import software.amazon.awssdk.transfer.s3.model.FileDownload; import software.amazon.awssdk.transfer.s3.model.FileUpload; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileUpload; import software.amazon.awssdk.transfer.s3.model.Upload; @@ -701,6 +704,107 @@ default Copy copy(Consumer copyRequestBuilder) { return copy(CopyRequest.builder().applyMutation(copyRequestBuilder).build()); } + /** + * Downloads an object using a pre-signed URL to a local file. For non-file-based downloads, you may use + * {@link #downloadWithPresignedUrl(PresignedDownloadRequest)} instead. + *

    + * This method supports multipart downloads when using a CRT-based or multipart-enabled S3 client, + * providing enhanced throughput and reliability for large objects. Progress can be monitored + * through {@link TransferListener}s attached to the request. + *

    + * The SDK will create a new file if the provided destination doesn't exist. If the file already exists, + * it will be replaced. In the event of an error, the SDK will NOT attempt to delete + * the file, leaving it as-is. + *

    + * Note: The result of the operation doesn't support pause and resume functionality. + *

    + *

    + * Usage Example: + * {@snippet : + * S3TransferManager transferManager = S3TransferManager.create(); + * + * // Create presigned URL (typically done by another service) + * PresignedUrlDownloadRequest presignedRequest = PresignedUrlDownloadRequest.builder() + * .presignedUrl(presignedUrl) + * .build(); + * + * PresignedDownloadFileRequest request = PresignedDownloadFileRequest.builder() + * .presignedUrlDownloadRequest(presignedRequest) + * .destination(Paths.get("downloaded-file.txt")) + * .addTransferListener( + * LoggingTransferListener.create()) + * .build(); + * + * PresignedFileDownload download = transferManager.downloadFileWithPresignedUrl(request); + * download.completionFuture().join(); + * } + * + * @param presignedDownloadFileRequest the presigned download file request + * @return A {@link PresignedFileDownload} that can be used to track the ongoing transfer + * @see #downloadFileWithPresignedUrl(Consumer) + * @see #downloadWithPresignedUrl(PresignedDownloadRequest) + */ + default PresignedFileDownload downloadFileWithPresignedUrl(PresignedDownloadFileRequest presignedDownloadFileRequest) { + throw new UnsupportedOperationException(); + } + + /** + * This is a convenience method that creates an instance of the {@link PresignedDownloadFileRequest} builder, + * avoiding the need to create one manually via {@link PresignedDownloadFileRequest#builder()}. + *

    + * Note: The result of the operation doesn't support pause and resume functionality. + *

    + * + * @see #downloadFileWithPresignedUrl(PresignedDownloadFileRequest) + */ + default PresignedFileDownload downloadFileWithPresignedUrl( + Consumer presignedDownloadFileRequest) { + return downloadFileWithPresignedUrl( + PresignedDownloadFileRequest.builder().applyMutation(presignedDownloadFileRequest).build()); + } + + /** + * Downloads an object using a pre-signed URL through the given {@link AsyncResponseTransformer}. For downloading + * to a file, you may use {@link #downloadFileWithPresignedUrl(PresignedDownloadFileRequest)} instead. + *

    + * This method supports multipart downloads when using a CRT-based or multipart-enabled S3 client, + * providing enhanced throughput and reliability for large objects. Progress can be monitored + * through {@link TransferListener}s attached to the request. + *

    + * Note: The result of the operation doesn't support pause and resume functionality. + *

    + *

    + * Usage Example (downloading to memory - not suitable for large objects): + * {@snippet : + * S3TransferManager transferManager = S3TransferManager.create(); + * + * // Create presigned URL (typically done by another service) + * PresignedUrlDownloadRequest presignedRequest = PresignedUrlDownloadRequest.builder() + * .presignedUrl(presignedUrl) + * .build(); + * + * PresignedDownloadRequest> request = + * PresignedDownloadRequest.builder() + * .presignedUrlDownloadRequest(presignedRequest) + * .responseTransformer(AsyncResponseTransformer.toBytes()) + * .addTransferListener(LoggingTransferListener.create()) + * .build(); + * + * Download> download = transferManager.downloadWithPresignedUrl(request); + * ResponseBytes result = download.completionFuture().join().result(); + * } + * + * @param presignedDownloadRequest the presigned download request + * @param The type of data the {@link AsyncResponseTransformer} produces + * @return A {@link Download} that can be used to track the ongoing transfer + * @see #downloadFileWithPresignedUrl(PresignedDownloadFileRequest) + * @see AsyncResponseTransformer + */ + default Download downloadWithPresignedUrl( + PresignedDownloadRequest presignedDownloadRequest) { + throw new UnsupportedOperationException(); + } + /** * Create an {@code S3TransferManager} using the default values. *

    diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriber.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriber.java index a992d308857e..4375ecd6b76e 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriber.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriber.java @@ -40,6 +40,7 @@ public class AsyncBufferingSubscriber implements Subscriber { private final int maxConcurrentExecutions; private final AtomicInteger numRequestsInFlight; private volatile boolean upstreamDone; + private volatile boolean onErrorInvoked; private volatile Subscription subscription; private final Set> requestsInFlight; @@ -56,9 +57,14 @@ public AsyncBufferingSubscriber(Function> consumer, returnFuture.whenComplete((r, t) -> { if (t != null) { requestsInFlight.forEach(f -> f.cancel(true)); - synchronized (this) { - if (subscription != null) { - subscription.cancel(); + // Skip cancelling when the failure came from onError: upstream has already terminated, and cancelling here + // would call Subscription::cancel from within onError (Reactive Streams rule 2.3). Still cancel on an + // external abort. + if (!onErrorInvoked) { + synchronized (this) { + if (subscription != null) { + subscription.cancel(); + } } } } @@ -79,6 +85,8 @@ public void onSubscribe(Subscription subscription) { @Override public void onNext(T item) { + // Reactive Streams rule 2.13: onNext must throw NullPointerException on a null element. + Validate.paramNotNull(item, "item"); numRequestsInFlight.incrementAndGet(); CompletableFuture currentRequest; @@ -111,6 +119,9 @@ public void onNext(T item) { @Override public void onError(Throwable t) { + // Set before completing the future: completeExceptionally may run the whenComplete handler synchronously, and it + // must see this flag to avoid cancelling the subscription from within onError (see constructor). + onErrorInvoked = true; // Need to complete future exceptionally first to prevent // accidental successful completion by a concurrent checkForCompletion. returnFuture.completeExceptionally(t); diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManager.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManager.java index d099a41398e2..76836040c4a0 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManager.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManager.java @@ -18,31 +18,49 @@ import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SDK_HTTP_EXECUTION_ATTRIBUTES; import static software.amazon.awssdk.services.s3.crt.S3CrtSdkHttpExecutionAttribute.CRT_PROGRESS_LISTENER; import static software.amazon.awssdk.services.s3.crt.S3CrtSdkHttpExecutionAttribute.METAREQUEST_PAUSE_OBSERVABLE; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_OPTION; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_PATH; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.CRT_PAUSE_RESUME_TOKEN; +import static software.amazon.awssdk.transfer.s3.internal.utils.ResumableRequestConverter.canResumeDownload; +import static software.amazon.awssdk.transfer.s3.internal.utils.ResumableRequestConverter.toCrtDownloadFileRequest; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.crt.s3.ResumeToken; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions.ResponseFileOption; import software.amazon.awssdk.http.SdkHttpExecutionAttributes; import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.internal.crt.CrtResponseFileResponseTransformer; import software.amazon.awssdk.services.s3.internal.crt.S3MetaRequestPauseObservable; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.transfer.s3.S3TransferManager; +import software.amazon.awssdk.transfer.s3.internal.model.CrtFileDownload; import software.amazon.awssdk.transfer.s3.internal.model.CrtFileUpload; import software.amazon.awssdk.transfer.s3.internal.model.DefaultUpload; +import software.amazon.awssdk.transfer.s3.internal.progress.ResumeTransferProgress; import software.amazon.awssdk.transfer.s3.internal.progress.TransferProgressUpdater; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload; import software.amazon.awssdk.transfer.s3.model.CompletedUpload; +import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.FileDownload; import software.amazon.awssdk.transfer.s3.model.FileUpload; +import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileUpload; import software.amazon.awssdk.transfer.s3.model.Upload; import software.amazon.awssdk.transfer.s3.model.UploadFileRequest; import software.amazon.awssdk.transfer.s3.model.UploadRequest; +import software.amazon.awssdk.transfer.s3.progress.TransferProgress; import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Validate; /** @@ -50,6 +68,8 @@ */ @SdkInternalApi class CrtS3TransferManager extends GenericS3TransferManager { + private static final Logger log = Logger.loggerFor(S3TransferManager.class); + private final S3AsyncClient s3AsyncClient; CrtS3TransferManager(TransferManagerConfiguration transferConfiguration, S3AsyncClient s3AsyncClient, @@ -137,6 +157,137 @@ FileUpload doResumeUpload(ResumableFileUpload resumableFileUpload) { .build()); } + /** + * Downloads the object by handing the destination file to CRT, which writes the response body to it directly rather than + * streaming the body back through the SDK. + */ + @Override + FileDownload doDownloadFile(DownloadFileRequest downloadRequest) { + S3MetaRequestPauseObservable observable = new S3MetaRequestPauseObservable(); + TransferProgressUpdater progressUpdater = new TransferProgressUpdater(downloadRequest, null); + + DownloadFileRequest crtDownloadRequest = crtDownloadFileRequest(downloadRequest, observable, progressUpdater, + ResponseFileOption.CREATE_OR_REPLACE); + + CompletableFuture returnFuture = new CompletableFuture<>(); + initiateCrtDownload(crtDownloadRequest, progressUpdater, returnFuture); + + return new CrtFileDownload(returnFuture, progressUpdater.progress(), observable, () -> crtDownloadRequest, null); + } + + @Override + FileDownload doResumeDownloadFile(ResumableFileDownload resumableFileDownload) { + DownloadFileRequest originalDownloadRequest = resumableFileDownload.downloadFileRequest(); + GetObjectRequest getObjectRequest = originalDownloadRequest.getObjectRequest(); + + CompletableFuture returnFuture = new CompletableFuture<>(); + CompletableFuture progressFuture = new CompletableFuture<>(); + CompletableFuture newDownloadFileRequestFuture = new CompletableFuture<>(); + S3MetaRequestPauseObservable observable = new S3MetaRequestPauseObservable(); + + CompletableFuture headFuture = + s3AsyncClient.headObject(b -> b.bucket(getObjectRequest.bucket()).key(getObjectRequest.key())); + + // Ensure cancellations are forwarded to the head future + CompletableFutureUtils.forwardExceptionTo(returnFuture, headFuture); + + headFuture.thenAccept(headObjectResponse -> { + boolean restartFromBeginning = !canResumeDownload(resumableFileDownload, headObjectResponse) + || hasCompletedParts(resumableFileDownload); + + DownloadFileRequest newDownloadFileRequest = toCrtDownloadFileRequest(resumableFileDownload, headObjectResponse, + originalDownloadRequest, + restartFromBeginning); + + // CRT appends to whatever the destination file already holds, so appending is only correct when the download is + // genuinely being continued. Otherwise the file has to be replaced. + ResponseFileOption responseFileOption = restartFromBeginning ? ResponseFileOption.CREATE_OR_REPLACE + : ResponseFileOption.CREATE_OR_APPEND; + + TransferProgressUpdater progressUpdater = new TransferProgressUpdater(newDownloadFileRequest, null); + DownloadFileRequest crtDownloadRequest = crtDownloadFileRequest(newDownloadFileRequest, observable, + progressUpdater, responseFileOption); + + newDownloadFileRequestFuture.complete(crtDownloadRequest); + log.debug(() -> "Sending downloadFileRequest " + crtDownloadRequest); + + initiateCrtDownload(crtDownloadRequest, progressUpdater, returnFuture); + progressFuture.complete(progressUpdater.progress()); + }).exceptionally(throwable -> { + handleException(returnFuture, progressFuture, newDownloadFileRequestFuture, throwable); + return null; + }); + + return new CrtFileDownload(returnFuture, + new ResumeTransferProgress(progressFuture), + observable, + () -> newOrOriginalRequestForPause(newDownloadFileRequestFuture, + originalDownloadRequest), + resumableFileDownload); + } + + /** + * A download that was paused while fetching individual parts can leave gaps in the destination file, because parts are + * written at their own offsets rather than in order. The CRT-based client only ever appends to the end of the file, so + * such a download cannot be continued and has to start over. This only arises when a {@link ResumableFileDownload} + * produced by the Java-based transfer manager is resumed with the CRT-based one. + */ + private static boolean hasCompletedParts(ResumableFileDownload resumableFileDownload) { + if (resumableFileDownload.completedParts().isEmpty()) { + return false; + } + log.debug(() -> "The paused download had completed individual parts, which the CRT-based S3 client cannot continue " + + "from. The SDK will download the S3 object from the beginning."); + return true; + } + + private void initiateCrtDownload(DownloadFileRequest downloadRequest, + TransferProgressUpdater progressUpdater, + CompletableFuture returnFuture) { + try { + progressUpdater.transferInitiated(); + AsyncResponseTransformer responseTransformer = + progressUpdater.wrapCrtResponseFileTransformer(new CrtResponseFileResponseTransformer<>()); + progressUpdater.registerCompletion(returnFuture); + + assertNotUnsupportedArn(downloadRequest.getObjectRequest().bucket(), "download"); + + CompletableFuture crtFuture = + s3AsyncClient.getObject(downloadRequest.getObjectRequest(), responseTransformer); + + // Forward download cancellation to CRT future + CompletableFutureUtils.forwardExceptionTo(returnFuture, crtFuture); + + CompletableFutureUtils.forwardTransformedResultTo(crtFuture, returnFuture, + res -> CompletedFileDownload.builder() + .response(res) + .build()); + } catch (Throwable throwable) { + returnFuture.completeExceptionally(throwable); + } + } + + /** + * Attaches the execution attributes that tell the CRT-based client to write the response body straight to the destination + * file, together with the progress listener and pause observable needed to report progress on and pause that transfer. + */ + private DownloadFileRequest crtDownloadFileRequest(DownloadFileRequest downloadRequest, + S3MetaRequestPauseObservable observable, + TransferProgressUpdater progressUpdater, + ResponseFileOption responseFileOption) { + GetObjectRequest getObjectRequest = attachSdkAttribute( + downloadRequest.getObjectRequest(), + b -> b.putExecutionAttribute(RESPONSE_FILE_PATH, downloadRequest.destination()) + .putExecutionAttribute(RESPONSE_FILE_OPTION, responseFileOption)); + + GetObjectRequest crtGetObjectRequest = attachCrtSdkAttribute( + getObjectRequest, + b -> b.put(METAREQUEST_PAUSE_OBSERVABLE, observable) + .put(CRT_PROGRESS_LISTENER, progressUpdater.crtProgressListener())); + + return downloadRequest.copy(r -> r.getObjectRequest(crtGetObjectRequest)); + } + private static ResumeToken crtResumeToken(ResumableFileUpload resumableFileUpload) { return new ResumeToken(new ResumeToken.PutResumeTokenBuilder() .withNumPartsCompleted(resumableFileUpload.transferredParts().orElse(0L)) @@ -166,4 +317,20 @@ private PutObjectRequest attachCrtSdkAttribute(PutObjectRequest putObjectRequest .overrideConfiguration(modifiedRequestOverrideConfig) .build(); } + + private GetObjectRequest attachCrtSdkAttribute(GetObjectRequest getObjectRequest, + Consumer builderMutation) { + SdkHttpExecutionAttributes existingAttributes = + getObjectRequest.overrideConfiguration() + .map(o -> o.executionAttributes().getAttribute(SDK_HTTP_EXECUTION_ATTRIBUTES)) + .orElse(null); + + SdkHttpExecutionAttributes modifiedAttributes = + (existingAttributes == null ? SdkHttpExecutionAttributes.builder() : existingAttributes.toBuilder()) + .applyMutation(builderMutation) + .build(); + + return attachSdkAttribute(getObjectRequest, + b -> b.putExecutionAttribute(SDK_HTTP_EXECUTION_ATTRIBUTES, modifiedAttributes)); + } } diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/DelegatingS3TransferManager.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/DelegatingS3TransferManager.java index f2929bf8f988..6907f1f00d08 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/DelegatingS3TransferManager.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/DelegatingS3TransferManager.java @@ -27,6 +27,9 @@ import software.amazon.awssdk.transfer.s3.model.DownloadRequest; import software.amazon.awssdk.transfer.s3.model.FileDownload; import software.amazon.awssdk.transfer.s3.model.FileUpload; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; import software.amazon.awssdk.transfer.s3.model.Upload; import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest; @@ -85,6 +88,16 @@ public Copy copy(CopyRequest copyRequest) { return delegate.copy(copyRequest); } + @Override + public PresignedFileDownload downloadFileWithPresignedUrl(PresignedDownloadFileRequest presignedDownloadFileRequest) { + return delegate.downloadFileWithPresignedUrl(presignedDownloadFileRequest); + } + + @Override + public Download downloadWithPresignedUrl(PresignedDownloadRequest presignedDownloadRequest) { + return delegate.downloadWithPresignedUrl(presignedDownloadRequest); + } + @Override public void close() { delegate.close(); diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/GenericS3TransferManager.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/GenericS3TransferManager.java index 4814b862e379..741c8e7e85cb 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/GenericS3TransferManager.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/GenericS3TransferManager.java @@ -55,6 +55,7 @@ import software.amazon.awssdk.transfer.s3.internal.model.DefaultDownload; import software.amazon.awssdk.transfer.s3.internal.model.DefaultFileDownload; import software.amazon.awssdk.transfer.s3.internal.model.DefaultFileUpload; +import software.amazon.awssdk.transfer.s3.internal.model.DefaultPresignedFileDownload; import software.amazon.awssdk.transfer.s3.internal.model.DefaultUpload; import software.amazon.awssdk.transfer.s3.internal.progress.DefaultTransferProgress; import software.amazon.awssdk.transfer.s3.internal.progress.DefaultTransferProgressSnapshot; @@ -75,6 +76,9 @@ import software.amazon.awssdk.transfer.s3.model.DownloadRequest; import software.amazon.awssdk.transfer.s3.model.FileDownload; import software.amazon.awssdk.transfer.s3.model.FileUpload; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; import software.amazon.awssdk.transfer.s3.model.ResumableFileUpload; import software.amazon.awssdk.transfer.s3.model.Upload; @@ -329,8 +333,8 @@ private CopyObjectRequest attachSdkAttribute(CopyObjectRequest copyObjectRequest .build(); } - private GetObjectRequest attachSdkAttribute(GetObjectRequest request, - Consumer builderMutation) { + GetObjectRequest attachSdkAttribute(GetObjectRequest request, + Consumer builderMutation) { AwsRequestOverrideConfiguration modifiedRequestOverrideConfig = request.overrideConfiguration() .map(o -> o.toBuilder().applyMutation(builderMutation).build()) @@ -404,7 +408,13 @@ public final Download download(DownloadRequest downl @Override public final FileDownload downloadFile(DownloadFileRequest downloadRequest) { Validate.paramNotNull(downloadRequest, "downloadFileRequest"); + return doDownloadFile(downloadRequest); + } + /** + * May be overridden by subclasses to provide customized behavior + */ + FileDownload doDownloadFile(DownloadFileRequest downloadRequest) { GetObjectRequest getObjectRequestWithAttributes = attachSdkAttribute( downloadRequest.getObjectRequest(), b -> b.putExecutionAttribute(MULTIPART_DOWNLOAD_RESUME_CONTEXT, new MultipartDownloadResumeContext())); @@ -416,13 +426,13 @@ public final FileDownload downloadFile(DownloadFileRequest downloadRequest) { FileTransformerConfiguration.defaultCreateOrReplaceExisting()); CompletableFuture returnFuture = new CompletableFuture<>(); - TransferProgressUpdater progressUpdater = doDownloadFile( + TransferProgressUpdater progressUpdater = initiateDownload( downloadFileRequestWithAttributes, responseTransformer, returnFuture); return new DefaultFileDownload(returnFuture, progressUpdater.progress(), () -> downloadFileRequestWithAttributes, null); } - private TransferProgressUpdater doDownloadFile( + private TransferProgressUpdater initiateDownload( DownloadFileRequest downloadRequest, AsyncResponseTransformer responseTransformer, CompletableFuture returnFuture) { @@ -456,7 +466,13 @@ private TransferProgressUpdater doDownloadFile( @Override public final FileDownload resumeDownloadFile(ResumableFileDownload resumableFileDownload) { Validate.paramNotNull(resumableFileDownload, "resumableFileDownload"); + return doResumeDownloadFile(resumableFileDownload); + } + /** + * May be overridden by subclasses to provide customized behavior + */ + FileDownload doResumeDownloadFile(ResumableFileDownload resumableFileDownload) { // check if the multipart-download was already completed and handle it gracefully. Optional optCtx = multipartDownloadResumeContext(resumableFileDownload.downloadFileRequest().getObjectRequest()); @@ -487,9 +503,9 @@ public final FileDownload resumeDownloadFile(ResumableFileDownload resumableFile newDownloadFileRequestFuture.complete(newDownloadFileRequest); log.debug(() -> "Sending downloadFileRequest " + newDownloadFileRequest); - TransferProgressUpdater progressUpdater = doDownloadFile(newDownloadFileRequest, - requestPair.right(), - returnFuture); + TransferProgressUpdater progressUpdater = initiateDownload(newDownloadFileRequest, + requestPair.right(), + returnFuture); progressFuture.complete(progressUpdater.progress()); }).exceptionally(throwable -> { handleException(returnFuture, progressFuture, newDownloadFileRequestFuture, throwable); @@ -516,8 +532,8 @@ private FileDownload completedDownload(ResumableFileDownload resumableFileDownlo resumableFileDownload); } - private DownloadFileRequest newOrOriginalRequestForPause(CompletableFuture newDownloadFuture, - DownloadFileRequest originalDownloadRequest) { + DownloadFileRequest newOrOriginalRequestForPause(CompletableFuture newDownloadFuture, + DownloadFileRequest originalDownloadRequest) { try { return newDownloadFuture.getNow(originalDownloadRequest); } catch (CompletionException e) { @@ -525,10 +541,10 @@ private DownloadFileRequest newOrOriginalRequestForPause(CompletableFuture returnFuture, - CompletableFuture progressFuture, - CompletableFuture newDownloadFileRequestFuture, - Throwable throwable) { + static void handleException(CompletableFuture returnFuture, + CompletableFuture progressFuture, + CompletableFuture newDownloadFileRequestFuture, + Throwable throwable) { Throwable exceptionCause = throwable instanceof CompletionException ? throwable.getCause() : throwable; Throwable propagatedException = exceptionCause instanceof SdkException || exceptionCause instanceof Error @@ -597,6 +613,78 @@ public final Copy copy(CopyRequest copyRequest) { return new DefaultCopy(returnFuture, progressUpdater.progress()); } + @Override + public final PresignedFileDownload downloadFileWithPresignedUrl(PresignedDownloadFileRequest presignedDownloadFileRequest) { + Validate.paramNotNull(presignedDownloadFileRequest, "presignedDownloadFileRequest"); + + AsyncResponseTransformer responseTransformer = + AsyncResponseTransformer.toFile(presignedDownloadFileRequest.destination(), + FileTransformerConfiguration.defaultCreateOrReplaceExisting()); + + CompletableFuture returnFuture = new CompletableFuture<>(); + + TransferProgressUpdater progressUpdater = new TransferProgressUpdater(presignedDownloadFileRequest, null); + progressUpdater.transferInitiated(); + + responseTransformer = isS3ClientMultipartEnabled() + && presignedDownloadFileRequest.presignedUrlDownloadRequest().range() == null + ? progressUpdater.wrapForNonSerialFileDownload( + responseTransformer, GetObjectRequest.builder().build()) + : progressUpdater.wrapResponseTransformer(responseTransformer); + progressUpdater.registerCompletion(returnFuture); + + try { + CompletableFuture future = s3AsyncClient.presignedUrlExtension().getObject( + presignedDownloadFileRequest.presignedUrlDownloadRequest(), responseTransformer); + + CompletableFutureUtils.forwardExceptionTo(returnFuture, future); + CompletableFutureUtils.forwardTransformedResultTo(future, returnFuture, + res -> CompletedFileDownload.builder() + .response(res) + .build()); + } catch (Throwable throwable) { + returnFuture.completeExceptionally(throwable); + } + + return new DefaultPresignedFileDownload(returnFuture, progressUpdater.progress()); + } + + @Override + public final Download downloadWithPresignedUrl( + PresignedDownloadRequest presignedDownloadRequest) { + Validate.paramNotNull(presignedDownloadRequest, "presignedDownloadRequest"); + + AsyncResponseTransformer responseTransformer = + presignedDownloadRequest.responseTransformer(); + + CompletableFuture> returnFuture = new CompletableFuture<>(); + + TransferProgressUpdater progressUpdater = new TransferProgressUpdater(presignedDownloadRequest, null); + progressUpdater.transferInitiated(); + + responseTransformer = isS3ClientMultipartEnabled() + && presignedDownloadRequest.presignedUrlDownloadRequest().range() == null + ? progressUpdater.wrapForNonSerialFileDownload( + responseTransformer, GetObjectRequest.builder().build()) + : progressUpdater.wrapResponseTransformer(responseTransformer); + progressUpdater.registerCompletion(returnFuture); + + try { + CompletableFuture future = s3AsyncClient.presignedUrlExtension().getObject( + presignedDownloadRequest.presignedUrlDownloadRequest(), responseTransformer); + + CompletableFutureUtils.forwardExceptionTo(returnFuture, future); + CompletableFutureUtils.forwardTransformedResultTo(future, returnFuture, + r -> CompletedDownload.builder() + .result(r) + .build()); + } catch (Throwable throwable) { + returnFuture.completeExceptionally(throwable); + } + + return new DefaultDownload<>(returnFuture, progressUpdater.progress()); + } + @Override public final void close() { if (isDefaultS3AsyncClient) { diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownload.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownload.java new file mode 100644 index 000000000000..95f0f04d36ae --- /dev/null +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownload.java @@ -0,0 +1,235 @@ +/* + * 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.transfer.s3.internal.model; + +import java.io.File; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.crt.s3.ResumeToken; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions; +import software.amazon.awssdk.services.s3.internal.crt.S3MetaRequestPauseObservable; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.FileDownload; +import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; +import software.amazon.awssdk.transfer.s3.progress.TransferProgress; +import software.amazon.awssdk.transfer.s3.progress.TransferProgressSnapshot; +import software.amazon.awssdk.utils.DateUtils; +import software.amazon.awssdk.utils.Lazy; +import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; + +/** + * A {@link FileDownload} for a download whose response body is written to the destination file by CRT rather than by an + * {@code AsyncResponseTransformer}. + *

    + * Because the response body never passes through the SDK, the response headers are not surfaced until the transfer finishes, + * so the ETag and last-modified time needed to resume the download cannot be read from the progress snapshot the way + * {@link DefaultFileDownload} reads them. They are instead taken from the {@link ResumeToken} that CRT hands back when the + * meta request is paused. + */ +@SdkInternalApi +public final class CrtFileDownload implements FileDownload { + private static final Logger log = Logger.loggerFor(CrtFileDownload.class); + + /** + * How long to wait for CRT to quiesce the transfer when pausing. {@link #pause()} is a blocking API, so this bounds how + * long a caller can be held up by an unresponsive meta request. + */ + private static final Duration DEFAULT_PAUSE_TIMEOUT = Duration.ofSeconds(10); + + private final Lazy resumableFileDownload; + private final CompletableFuture completionFuture; + private final TransferProgress progress; + private final S3MetaRequestPauseObservable observable; + private final Supplier requestSupplier; + private final ResumableFileDownload resumedDownload; + private final Duration pauseTimeout; + + public CrtFileDownload(CompletableFuture completionFuture, + TransferProgress progress, + S3MetaRequestPauseObservable observable, + Supplier requestSupplier, + ResumableFileDownload resumedDownload) { + this(completionFuture, progress, observable, requestSupplier, resumedDownload, DEFAULT_PAUSE_TIMEOUT); + } + + @SdkTestInternalApi + CrtFileDownload(CompletableFuture completionFuture, + TransferProgress progress, + S3MetaRequestPauseObservable observable, + Supplier requestSupplier, + ResumableFileDownload resumedDownload, + Duration pauseTimeout) { + this.completionFuture = Validate.paramNotNull(completionFuture, "completionFuture"); + this.progress = Validate.paramNotNull(progress, "progress"); + this.observable = Validate.paramNotNull(observable, "observable"); + this.requestSupplier = Validate.paramNotNull(requestSupplier, "requestSupplier"); + this.resumedDownload = resumedDownload; + this.pauseTimeout = Validate.paramNotNull(pauseTimeout, "pauseTimeout"); + this.resumableFileDownload = new Lazy<>(this::doPause); + } + + @Override + public TransferProgress progress() { + return progress; + } + + @Override + public CompletableFuture completionFuture() { + return completionFuture; + } + + @Override + public ResumableFileDownload pause() { + return resumableFileDownload.getValue(); + } + + private ResumableFileDownload doPause() { + if (completionFuture.isDone() && !completionFuture.isCompletedExceptionally()) { + log.debug(() -> "The download future was already completed. There will be no CRT ResumeToken returned."); + return resumableFileDownload(null); + } + + // The pause must be awaited before the completion future is cancelled: cancelling closes the underlying CRT meta + // request, and a closed meta request can no longer produce a resume token. + ResumeToken token = pauseMetaRequest(); + completionFuture.cancel(true); + return resumableFileDownload(token); + } + + /** + * Pauses the underlying CRT meta request and waits for it to quiesce, which for a download to a file means the file has + * been fully written and closed. + * + * @return the resume token, or null if none was available. Without a token the object metadata needed to resume has to + * come from elsewhere, and if it is not available the download simply starts over, which is always safe. + */ + private ResumeToken pauseMetaRequest() { + try { + return observable.pauseAsync().get(pauseTimeout.toMillis(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw SdkClientException.create("The thread was interrupted while pausing the download", e); + } catch (TimeoutException e) { + log.warn(() -> String.format("Timed out after %s waiting for the download to pause. It will be restarted from " + + "the beginning if resumed.", pauseTimeout)); + } catch (ExecutionException e) { + log.warn(() -> "Failed to pause the download. It will be restarted from the beginning if resumed.", e.getCause()); + } + return null; + } + + private ResumableFileDownload resumableFileDownload(ResumeToken token) { + DownloadFileRequest request = requestSupplier.get(); + File destination = request.destination().toFile(); + + ResumableFileDownload.Builder builder = + ResumableFileDownload.builder() + .downloadFileRequest(request) + .fileLastModified(Instant.ofEpochMilli(destination.lastModified())); + + if (isDownloadResumeToken(token)) { + // getContinuesDownloadedBytes() is the length of the gap-free prefix that CRT has downloaded, relative to the + // start of this request's range, so offsetting it by the range start gives the absolute offset in the object, + // which is also the number of bytes that should be in the destination file. If parts landed out of order the + // file may be longer than that, in which case the file-modified check on resume fails and the download + // correctly starts over rather than appending onto a gap. + builder.bytesTransferred(token.getObjectRangeStart() + token.getContinuesDownloadedBytes()) + .s3ObjectEtag(emptyToNull(token.getEtag())) + .s3ObjectLastModified(s3ObjectLastModified(token)) + .totalSizeInBytes(positiveOrNull(token.getObjectSize())); + return builder.build(); + } + + builder.bytesTransferred(destination.length()); + populateFromResponseOrResumedDownload(builder); + return builder.build(); + } + + /** + * Populates the S3 object metadata needed to detect whether the object changed while the download was paused, for the + * cases where CRT did not give us a resume token: either the transfer already finished, in which case the response is on + * the progress snapshot, or it never really started, in which case anything we knew came from the + * {@link ResumableFileDownload} being resumed. + */ + private void populateFromResponseOrResumedDownload(ResumableFileDownload.Builder builder) { + TransferProgressSnapshot snapshot = progress.snapshot(); + if (snapshot.sdkResponse().isPresent() && snapshot.sdkResponse().get() instanceof GetObjectResponse) { + GetObjectResponse response = (GetObjectResponse) snapshot.sdkResponse().get(); + Long contentLength = response.contentLength(); + builder.s3ObjectEtag(response.eTag()) + .s3ObjectLastModified(response.lastModified()) + .totalSizeInBytes(contentLength == null ? null : positiveOrNull(contentLength)); + } else if (resumedDownload != null) { + builder.s3ObjectEtag(resumedDownload.s3ObjectEtag().orElse(null)) + .s3ObjectLastModified(resumedDownload.s3ObjectLastModified().orElse(null)) + .totalSizeInBytes(resumedDownload.totalSizeInBytes().isPresent() + ? resumedDownload.totalSizeInBytes().getAsLong() + : null); + } + } + + /** + * CRT's download-specific getters throw if they are read off an upload token, so the token type has to be checked before + * any of them are used. + */ + private static boolean isDownloadResumeToken(ResumeToken token) { + return token != null && token.getType() == S3MetaRequestOptions.MetaRequestType.GET_OBJECT; + } + + private static Instant s3ObjectLastModified(ResumeToken token) { + String lastModified = emptyToNull(token.getS3ObjectLastModified()); + if (lastModified == null) { + return null; + } + try { + return DateUtils.parseRfc1123Date(lastModified); + } catch (RuntimeException e) { + // Losing the last-modified time only costs us the ability to resume; it must not fail the pause itself. + log.warn(() -> "Could not parse the last-modified time reported by CRT. The download will be restarted from the " + + "beginning if resumed.", e); + return null; + } + } + + private static String emptyToNull(String value) { + return value == null || value.isEmpty() ? null : value; + } + + private static Long positiveOrNull(long value) { + return value > 0 ? value : null; + } + + @Override + public String toString() { + return ToString.builder("CrtFileDownload") + .add("completionFuture", completionFuture) + .add("progress", progress) + .add("request", requestSupplier.get()) + .build(); + } +} diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/DefaultPresignedFileDownload.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/DefaultPresignedFileDownload.java new file mode 100644 index 000000000000..253c60a8a42a --- /dev/null +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/model/DefaultPresignedFileDownload.java @@ -0,0 +1,79 @@ +/* + * 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.transfer.s3.internal.model; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; +import software.amazon.awssdk.transfer.s3.progress.TransferProgress; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; + +@SdkInternalApi +public final class DefaultPresignedFileDownload implements PresignedFileDownload { + private final CompletableFuture completionFuture; + private final TransferProgress progress; + + public DefaultPresignedFileDownload(CompletableFuture completionFuture, + TransferProgress progress) { + this.completionFuture = Validate.paramNotNull(completionFuture, "completionFuture"); + this.progress = Validate.paramNotNull(progress, "progress"); + } + + @Override + public CompletableFuture completionFuture() { + return completionFuture; + } + + @Override + public TransferProgress progress() { + return progress; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultPresignedFileDownload that = (DefaultPresignedFileDownload) o; + + if (!Objects.equals(completionFuture, that.completionFuture)) { + return false; + } + return Objects.equals(progress, that.progress); + } + + @Override + public int hashCode() { + int result = completionFuture != null ? completionFuture.hashCode() : 0; + result = 31 * result + (progress != null ? progress.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToString.builder("DefaultPresignedFileDownload") + .add("completionFuture", completionFuture) + .add("progress", progress) + .build(); + } +} diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferProgressUpdater.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferProgressUpdater.java index b87178c76616..3e88cff400fc 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferProgressUpdater.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferProgressUpdater.java @@ -168,6 +168,14 @@ public void publisherSubscribe(Subscriber subscri @Override public void subscriberOnNext(S3MetaRequestProgress s3MetaRequestProgress) { + // For a download whose body CRT writes straight to a file, the response headers are not surfaced to the SDK + // until the transfer has finished, so CRT's progress is the only source of the total size while the transfer + // is in flight. Seed it here so that ratioTransferred() is available during the download; the exact value + // from the response Content-Length replaces this once the transfer completes. + long contentLength = s3MetaRequestProgress.getContentLength(); + if (contentLength > 0 && !progress.snapshot().totalBytes().isPresent()) { + updateTotalBytes(contentLength, null); + } incrementBytesTransferred(s3MetaRequestProgress.getBytesTransferred()); } @@ -295,6 +303,63 @@ public void transformerOnResponse(GetObjectResponse response) { }); } + /** + * Wraps the response transformer used when the CRT-based S3 client writes the response body straight to a file. + *

    + * Byte-level progress for that path is reported by {@link #crtProgressListener()} rather than by the response + * transformer, because no response body is ever delivered to the SDK. The transformer's publisher is also only subscribed + * to once the transfer has already finished, so unlike {@link #wrapResponseTransformer(AsyncResponseTransformer)} this + * wrapper must neither reset nor increment the transferred byte count - doing so would discard the progress that CRT + * already reported. + */ + public AsyncResponseTransformer wrapCrtResponseFileTransformer( + AsyncResponseTransformer responseTransformer) { + return AsyncResponseTransformerListener.wrap( + responseTransformer, + new AsyncResponseTransformerListener() { + @Override + public void transformerOnResponse(GetObjectResponse response) { + if (response.contentLength() != null) { + updateTotalBytes(response.contentLength(), response); + } + } + + @Override + public void transformerExceptionOccurred(Throwable t) { + transferFailed(t); + } + + @Override + public void subscriberOnError(Throwable t) { + transferFailed(t); + } + + @Override + public void subscriberOnComplete() { + endOfStreamFuture.complete(null); + } + }); + } + + /** + * Records the total size of a transfer, and the response it came from, without breaking the + * {@link DefaultTransferProgressSnapshot} invariant that the transferred byte count must not exceed the total. + *

    + * This is only used on the CRT paths, where the transferred count comes from CRT's progress callbacks while the total + * comes from the response, so the two are accounted for independently and could in principle disagree. If they do, the + * larger byte count is trusted rather than failing the transfer: throwing from here would either propagate out of a CRT + * callback or, in the response transformer, be swallowed and silently discard the response that pausing needs in order to + * build a resume token. + */ + private void updateTotalBytes(long totalBytes, GetObjectResponse sdkResponse) { + progress.updateAndGet(b -> { + b.totalBytes(Math.max(totalBytes, b.getTransferredBytes())); + if (sdkResponse != null) { + b.sdkResponse(sdkResponse); + } + }); + } + private void resetBytesTransferred() { progress.updateAndGet(b -> b.transferredBytes(0L)); } diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/utils/ResumableRequestConverter.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/utils/ResumableRequestConverter.java index a61da15e7a5d..c991b87e9066 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/utils/ResumableRequestConverter.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/internal/utils/ResumableRequestConverter.java @@ -59,22 +59,9 @@ private ResumableRequestConverter() { GetObjectRequest getObjectRequest = originalDownloadRequest.getObjectRequest(); DownloadFileRequest newDownloadFileRequest; - Instant lastModified = resumableFileDownload.s3ObjectLastModified().orElse(null); - String resumableFileDownloadEtag = resumableFileDownload.s3ObjectEtag().orElse(null); - - String s3ObjectEtag = headObjectResponse.eTag(); - boolean etagModified = resumableFileDownloadEtag != null && - !resumableFileDownloadEtag.equals(s3ObjectEtag); - - boolean s3ObjectModified = !headObjectResponse.lastModified().equals(lastModified); - boolean fileModified = !fileNotModified(resumableFileDownload.bytesTransferred(), - resumableFileDownload.fileLastModified(), - resumableFileDownload.downloadFileRequest().destination()); - - if (fileModified || s3ObjectModified || etagModified) { + if (!canResumeDownload(resumableFileDownload, headObjectResponse)) { // modification detected: new download request for the whole object from the beginning - logIfNeeded(originalDownloadRequest, getObjectRequest, fileModified, s3ObjectModified, etagModified); newDownloadFileRequest = newDownloadFileRequest(originalDownloadRequest, getObjectRequest, headObjectResponse); AsyncResponseTransformer responseTransformer = @@ -104,6 +91,58 @@ private ResumableRequestConverter() { return Pair.of(newDownloadFileRequest, responseTransformer); } + /** + * Determines whether a paused download can continue from where it left off, or whether it has to be restarted from the + * beginning because either the S3 object or the local file was modified while the download was paused. Logs the reason at + * debug level when a restart is required. + * + * @return true if the remaining bytes can be fetched, false if the whole object must be downloaded again + */ + public static boolean canResumeDownload(ResumableFileDownload resumableFileDownload, + HeadObjectResponse headObjectResponse) { + DownloadFileRequest downloadRequest = resumableFileDownload.downloadFileRequest(); + Instant lastModified = resumableFileDownload.s3ObjectLastModified().orElse(null); + String resumableFileDownloadEtag = resumableFileDownload.s3ObjectEtag().orElse(null); + + String s3ObjectEtag = headObjectResponse.eTag(); + boolean etagModified = resumableFileDownloadEtag != null && + !resumableFileDownloadEtag.equals(s3ObjectEtag); + + boolean s3ObjectModified = !headObjectResponse.lastModified().equals(lastModified); + boolean fileModified = !fileNotModified(resumableFileDownload.bytesTransferred(), + resumableFileDownload.fileLastModified(), + downloadRequest.destination()); + + if (fileModified || s3ObjectModified || etagModified) { + logIfNeeded(downloadRequest, downloadRequest.getObjectRequest(), fileModified, s3ObjectModified, etagModified); + return false; + } + return true; + } + + /** + * Builds the {@link DownloadFileRequest} for resuming a paused download that is being written to the destination file by + * CRT rather than by an {@link AsyncResponseTransformer}. Unlike + * {@link #toDownloadFileRequestAndTransformer(ResumableFileDownload, HeadObjectResponse, DownloadFileRequest)} there is no + * transformer to pair the request with, and no part-GET variant to consider, since the CRT-based client always downloads + * an object with a single meta request. + * + * @param restartFromBeginning whether the whole object should be downloaded again rather than only the remaining bytes + */ + public static DownloadFileRequest toCrtDownloadFileRequest(ResumableFileDownload resumableFileDownload, + HeadObjectResponse headObjectResponse, + DownloadFileRequest originalDownloadRequest, + boolean restartFromBeginning) { + GetObjectRequest getObjectRequest = originalDownloadRequest.getObjectRequest(); + if (restartFromBeginning) { + return newDownloadFileRequest(originalDownloadRequest, getObjectRequest, headObjectResponse); + } + + log.debug(() -> "Resuming the paused download with a range GET for the remaining bytes."); + return resumedDownloadFileRequest(resumableFileDownload, originalDownloadRequest, getObjectRequest, + headObjectResponse); + } + private static boolean hasRemainingParts(GetObjectRequest getObjectRequest) { Optional optCtx = MultipartDownloadUtils.multipartDownloadResumeContext(getObjectRequest); if (!optCtx.isPresent()) { diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/FileDownload.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/FileDownload.java index 6c16798fd87b..f5c34526f418 100644 --- a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/FileDownload.java +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/FileDownload.java @@ -33,6 +33,9 @@ public interface FileDownload extends ObjectTransfer { * The information object is serializable for persistent storage until it should be resumed. * See {@link ResumableFileDownload} for supported formats. * + *

    Pause may block the caller for a short time until in-progress requests are canceled and + * cleaned up to ensure a consistent state. + * * @return A {@link ResumableFileDownload} that can be used to resume the download. */ ResumableFileDownload pause(); diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequest.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequest.java new file mode 100644 index 000000000000..b165292b22e5 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequest.java @@ -0,0 +1,286 @@ +/* + * 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.transfer.s3.model; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.transfer.s3.S3TransferManager; +import software.amazon.awssdk.transfer.s3.progress.TransferListener; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; +import software.amazon.awssdk.utils.builder.CopyableBuilder; +import software.amazon.awssdk.utils.builder.ToCopyableBuilder; + +/** + * Download an object using a pre-signed URL to a local file. For non-file-based downloads, you may use {@link + * PresignedDownloadRequest} instead. + * + * @see S3TransferManager#downloadFileWithPresignedUrl(PresignedDownloadFileRequest) + */ +@SdkPublicApi +public final class PresignedDownloadFileRequest + implements TransferObjectRequest, ToCopyableBuilder { + + private final Path destination; + private final PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private final List transferListeners; + + private PresignedDownloadFileRequest(DefaultBuilder builder) { + this.destination = Validate.paramNotNull(builder.destination, "destination"); + this.presignedUrlDownloadRequest = Validate.paramNotNull(builder.presignedUrlDownloadRequest, + "presignedUrlDownloadRequest"); + this.transferListeners = builder.transferListeners; + } + + /** + * Creates a builder that can be used to create a {@link PresignedDownloadFileRequest}. + * + * @see S3TransferManager#downloadFileWithPresignedUrl(PresignedDownloadFileRequest) + */ + public static Builder builder() { + return new DefaultBuilder(); + } + + @Override + public Builder toBuilder() { + return new DefaultBuilder(this); + } + + /** + * The {@link Path} to file that response contents will be written to. The file must not exist or this method + * will throw an exception. If the file is not writable by the current user then an exception will be thrown. + * + * @return the destination path + */ + public Path destination() { + return destination; + } + + /** + * @return The {@link PresignedUrlDownloadRequest} request that should be used for the download + */ + public PresignedUrlDownloadRequest presignedUrlDownloadRequest() { + return presignedUrlDownloadRequest; + } + + /** + * + * @return List of {@link TransferListener}s that will be notified as part of this request. + */ + @Override + public List transferListeners() { + return transferListeners; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + PresignedDownloadFileRequest that = (PresignedDownloadFileRequest) o; + + if (!Objects.equals(destination, that.destination)) { + return false; + } + if (!Objects.equals(presignedUrlDownloadRequest, that.presignedUrlDownloadRequest)) { + return false; + } + return Objects.equals(transferListeners, that.transferListeners); + } + + @Override + public int hashCode() { + int result = destination != null ? destination.hashCode() : 0; + result = 31 * result + (presignedUrlDownloadRequest != null ? presignedUrlDownloadRequest.hashCode() : 0); + result = 31 * result + (transferListeners != null ? transferListeners.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToString.builder("PresignedDownloadFileRequest") + .add("destination", destination) + .add("presignedUrlDownloadRequest", presignedUrlDownloadRequest) + .add("transferListeners", transferListeners) + .build(); + } + + public static Class serializableBuilderClass() { + return DefaultBuilder.class; + } + + /** + * A builder for a {@link PresignedDownloadFileRequest}, created with {@link #builder()} + */ + @SdkPublicApi + @NotThreadSafe + public interface Builder extends CopyableBuilder { + + /** + * The {@link Path} to file that response contents will be written to. The file must not exist or this method + * will throw an exception. If the file is not writable by the current user then an exception will be thrown. + * + * @param destination the destination path + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder destination(Path destination); + + /** + * The file that response contents will be written to. The file must not exist or this method + * will throw an exception. If the file is not writable by the current user then an exception will be thrown. + * + * @param destination the destination path + * @return Returns a reference to this object so that method calls can be chained together. + */ + default Builder destination(File destination) { + Validate.paramNotNull(destination, "destination"); + return destination(destination.toPath()); + } + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + * + * @param presignedUrlDownloadRequest the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(Consumer) + */ + Builder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest); + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + * + *

    + * This is a convenience method that creates an instance of the {@link PresignedUrlDownloadRequest} builder avoiding the + * need to create one manually via {@link PresignedUrlDownloadRequest#builder()}. + * + * @param presignedUrlDownloadRequestBuilder the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(PresignedUrlDownloadRequest) + */ + default Builder presignedUrlDownloadRequest( + Consumer presignedUrlDownloadRequestBuilder) { + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .applyMutation(presignedUrlDownloadRequestBuilder) + .build(); + presignedUrlDownloadRequest(request); + return this; + } + + /** + * The {@link TransferListener}s that will be notified as part of this request. This method overrides and replaces any + * transferListeners that have already been set. Add an optional request override configuration. + * + * @param transferListeners the collection of transferListeners + * @return Returns a reference to this object so that method calls can be chained together. + * @return This builder for method chaining. + * @see TransferListener + */ + Builder transferListeners(Collection transferListeners); + + /** + * Add a {@link TransferListener} that will be notified as part of this request. + * + * @param transferListener the transferListener to add + * @return Returns a reference to this object so that method calls can be chained together. + * @see TransferListener + */ + Builder addTransferListener(TransferListener transferListener); + + } + + private static final class DefaultBuilder implements Builder { + private Path destination; + private PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private List transferListeners; + + private DefaultBuilder() { + } + + private DefaultBuilder(PresignedDownloadFileRequest presignedDownloadFileRequest) { + this.destination = presignedDownloadFileRequest.destination; + this.presignedUrlDownloadRequest = presignedDownloadFileRequest.presignedUrlDownloadRequest; + this.transferListeners = presignedDownloadFileRequest.transferListeners; + } + + @Override + public Builder destination(Path destination) { + this.destination = Validate.paramNotNull(destination, "destination"); + return this; + } + + public Path getDestination() { + return destination; + } + + public void setDestination(Path destination) { + destination(destination); + } + + @Override + public DefaultBuilder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest) { + this.presignedUrlDownloadRequest = presignedUrlDownloadRequest; + return this; + } + + public PresignedUrlDownloadRequest getPresignedUrlDownloadRequest() { + return presignedUrlDownloadRequest; + } + + public void setPresignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest) { + presignedUrlDownloadRequest(presignedUrlDownloadRequest); + } + + @Override + public DefaultBuilder transferListeners(Collection transferListeners) { + this.transferListeners = transferListeners != null ? new ArrayList<>(transferListeners) : null; + return this; + } + + @Override + public Builder addTransferListener(TransferListener transferListener) { + if (transferListeners == null) { + transferListeners = new ArrayList<>(); + } + transferListeners.add(transferListener); + return this; + } + + public List getTransferListeners() { + return transferListeners; + } + + public void setTransferListeners(Collection transferListeners) { + transferListeners(transferListeners); + } + + @Override + public PresignedDownloadFileRequest build() { + return new PresignedDownloadFileRequest(this); + } + } +} \ No newline at end of file diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequest.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequest.java new file mode 100644 index 000000000000..1a45eeb21254 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequest.java @@ -0,0 +1,391 @@ +/* + * 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.transfer.s3.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.transfer.s3.S3TransferManager; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest.TypedBuilder; +import software.amazon.awssdk.transfer.s3.progress.TransferListener; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; +import software.amazon.awssdk.utils.builder.CopyableBuilder; +import software.amazon.awssdk.utils.builder.ToCopyableBuilder; + +/** + * Represents the request to download an object using a pre-signed URL through the given + * {@link AsyncResponseTransformer}. For downloading to a file, + * you may use {@link PresignedDownloadFileRequest} instead. + * + * @see S3TransferManager#downloadWithPresignedUrl(PresignedDownloadRequest) + */ +@SdkPublicApi +public final class PresignedDownloadRequest + implements TransferObjectRequest, + ToCopyableBuilder, PresignedDownloadRequest> { + + private final AsyncResponseTransformer responseTransformer; + private final PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private final List transferListeners; + + private PresignedDownloadRequest(DefaultTypedBuilder builder) { + this.responseTransformer = Validate.paramNotNull(builder.responseTransformer, "responseTransformer"); + this.presignedUrlDownloadRequest = Validate.paramNotNull(builder.presignedUrlDownloadRequest, + "presignedUrlDownloadRequest"); + this.transferListeners = builder.transferListeners; + } + + /** + * Creates a builder that can be used to create a {@link PresignedDownloadRequest}. + * + * @see UntypedBuilder + */ + public static UntypedBuilder builder() { + return new DefaultUntypedBuilder(); + } + + + @Override + public TypedBuilder toBuilder() { + return new DefaultTypedBuilder<>(this); + } + + /** + * The {@link AsyncResponseTransformer} that response contents will be written to. + * + * @return the response transformer + */ + public AsyncResponseTransformer responseTransformer() { + return responseTransformer; + } + + /** + * @return The {@link PresignedUrlDownloadRequest} request that should be used for the download + */ + public PresignedUrlDownloadRequest presignedUrlDownloadRequest() { + return presignedUrlDownloadRequest; + } + + /** + * @return the List of transferListeners. + * @see TypedBuilder#transferListeners(Collection) + */ + @Override + public List transferListeners() { + return transferListeners; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + PresignedDownloadRequest that = (PresignedDownloadRequest) o; + + if (!Objects.equals(responseTransformer, that.responseTransformer)) { + return false; + } + if (!Objects.equals(presignedUrlDownloadRequest, that.presignedUrlDownloadRequest)) { + return false; + } + return Objects.equals(transferListeners, that.transferListeners); + } + + @Override + public int hashCode() { + int result = responseTransformer != null ? responseTransformer.hashCode() : 0; + result = 31 * result + (presignedUrlDownloadRequest != null ? presignedUrlDownloadRequest.hashCode() : 0); + result = 31 * result + (transferListeners != null ? transferListeners.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return ToString.builder("PresignedDownloadRequest") + .add("responseTransformer", responseTransformer) + .add("presignedUrlDownloadRequest", presignedUrlDownloadRequest) + .add("transferListeners", transferListeners) + .build(); + } + + /** + * Initial calls to {@link PresignedDownloadRequest#builder()} return an {@link UntypedBuilder}, where the builder is not yet + * parameterized with the generic type associated with {@link PresignedDownloadRequest}. + * This prevents the otherwise awkward syntax of having to explicitly cast the builder type, e.g., + *

    +     * {@code PresignedDownloadRequest.>builder()}
    +     * 
    + * Instead, the type may be inferred as part of specifying the {@link #responseTransformer(AsyncResponseTransformer)} + * parameter, at which point the builder chain will return a new {@link TypedBuilder}. + */ + public interface UntypedBuilder { + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + * + * @param presignedUrlDownloadRequest the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(Consumer) + */ + UntypedBuilder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest); + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + *

    + * This is a convenience method that creates an instance of the {@link PresignedUrlDownloadRequest} + * builder, avoiding the need to create one manually via {@link PresignedUrlDownloadRequest#builder()}. + * + * @param presignedUrlDownloadRequestBuilder the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(PresignedUrlDownloadRequest) + */ + default UntypedBuilder presignedUrlDownloadRequest( + Consumer presignedUrlDownloadRequestBuilder) { + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .applyMutation(presignedUrlDownloadRequestBuilder) + .build(); + presignedUrlDownloadRequest(request); + return this; + } + + /** + * The {@link TransferListener}s that will be notified as part of this request. This method + * overrides and replaces any transferListeners that have already been set. Add an optional + * request override configuration. + * + * @param transferListeners the collection of transferListeners + * @return Returns a reference to this object so that method calls can be chained together. + * @return This builder for method chaining. + * @see TransferListener + */ + UntypedBuilder transferListeners( + Collection transferListeners); + + /** + * Adds a {@link TransferListener} that will be notified as part of this request. + * + * @param transferListener the transferListener to add + * @return Returns a reference to this object so that method calls can be chained together. + * @see TransferListener + */ + UntypedBuilder addTransferListener(TransferListener transferListener); + + /** + * Specifies the {@link AsyncResponseTransformer} that should be used for the download. This + * method also infers the generic type of {@link PresignedDownloadRequest} to create, + * inferred from the second type parameter of the provided {@link AsyncResponseTransformer}. + * E.g, specifying {@link AsyncResponseTransformer#toBytes()} would result in inferring the + * type of the {@link PresignedDownloadRequest} to be of {@code ResponseBytes}. + * See the static factory methods available in {@link AsyncResponseTransformer}. + * + * @param responseTransformer the AsyncResponseTransformer + * @param the type of {@link PresignedDownloadRequest} to create + * @return a reference to this object so that method calls can be chained together. + * @see AsyncResponseTransformer + */ + TypedBuilder responseTransformer( + AsyncResponseTransformer responseTransformer); + } + + private static final class DefaultUntypedBuilder implements UntypedBuilder { + private PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private List transferListeners; + + private DefaultUntypedBuilder() { + } + + @Override + public UntypedBuilder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest) { + this.presignedUrlDownloadRequest = presignedUrlDownloadRequest; + return this; + } + + @Override + public UntypedBuilder transferListeners( + Collection transferListeners) { + this.transferListeners = transferListeners != null ? + new ArrayList<>(transferListeners) : null; + return this; + } + + @Override + public UntypedBuilder addTransferListener(TransferListener transferListener) { + if (transferListeners == null) { + transferListeners = new ArrayList<>(); + } + transferListeners.add(transferListener); + return this; + } + + public List getTransferListeners() { + return transferListeners; + } + + public void setTransferListeners( + Collection transferListeners) { + transferListeners(transferListeners); + } + + @Override + public TypedBuilder responseTransformer( + AsyncResponseTransformer responseTransformer) { + return new DefaultTypedBuilder() + .presignedUrlDownloadRequest(presignedUrlDownloadRequest) + .transferListeners(transferListeners) + .responseTransformer(responseTransformer); + } + } + + /** + * The type-parameterized version of {@link UntypedBuilder}. This builder's type is inferred as part of specifying {@link + * UntypedBuilder#responseTransformer(AsyncResponseTransformer)}, after which this builder can be used to construct a {@link + * PresignedDownloadRequest} with the same generic type. + */ + public interface TypedBuilder extends CopyableBuilder, PresignedDownloadRequest> { + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + * + * @param presignedUrlDownloadRequest the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(Consumer) + */ + TypedBuilder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest); + + /** + * The {@link PresignedUrlDownloadRequest} request that should be used for the download + *

    + * This is a convenience method that creates an instance of the {@link PresignedUrlDownloadRequest} builder, + * avoiding the need to create one manually via {@link PresignedUrlDownloadRequest#builder()}. + * + * @param presignedUrlDownloadRequestBuilder the presigned URL download request + * @return a reference to this object so that method calls can be chained together. + * @see #presignedUrlDownloadRequest(PresignedUrlDownloadRequest) + */ + default TypedBuilder presignedUrlDownloadRequest( + Consumer presignedUrlDownloadRequestBuilder) { + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .applyMutation(presignedUrlDownloadRequestBuilder) + .build(); + presignedUrlDownloadRequest(request); + return this; + } + + /** + * The {@link TransferListener}s that will be notified as part of this request. This method overrides and + * replaces any transferListeners that have already been set. Add an optional request override + * configuration. + * + * @param transferListeners the collection of transferListeners + * @return Returns a reference to this object so that method calls can be chained together. + * @return This builder for method chaining. + * @see TransferListener + */ + TypedBuilder transferListeners( + Collection transferListeners); + + /** + * Add a {@link TransferListener} that will be notified as part of this request. + * + * @param transferListener the transferListener to add + * @return Returns a reference to this object so that method calls can be chained together. + * @see TransferListener + */ + TypedBuilder addTransferListener(TransferListener transferListener); + + /** + * Specifies the {@link AsyncResponseTransformer} that should be used for the download. The generic type used is + * constrained by the {@link UntypedBuilder#responseTransformer(AsyncResponseTransformer)} that was previously used to + * create this {@link TypedBuilder}. + * + * @param responseTransformer the AsyncResponseTransformer + * @return a reference to this object so that method calls can be chained together. + * @see AsyncResponseTransformer + */ + TypedBuilder responseTransformer( + AsyncResponseTransformer responseTransformer); + } + + private static class DefaultTypedBuilder implements TypedBuilder { + private PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private List transferListeners; + private AsyncResponseTransformer responseTransformer; + + private DefaultTypedBuilder() { + } + + private DefaultTypedBuilder(PresignedDownloadRequest request) { + this.presignedUrlDownloadRequest = request.presignedUrlDownloadRequest; + this.responseTransformer = request.responseTransformer; + this.transferListeners = request.transferListeners; + } + + @Override + public TypedBuilder presignedUrlDownloadRequest(PresignedUrlDownloadRequest presignedUrlDownloadRequest) { + this.presignedUrlDownloadRequest = presignedUrlDownloadRequest; + return this; + } + + @Override + public TypedBuilder responseTransformer( + AsyncResponseTransformer responseTransformer) { + this.responseTransformer = responseTransformer; + return this; + } + + @Override + public TypedBuilder transferListeners( + Collection transferListeners) { + this.transferListeners = transferListeners != null ? + new ArrayList<>(transferListeners) : null; + return this; + } + + @Override + public TypedBuilder addTransferListener(TransferListener transferListener) { + if (transferListeners == null) { + transferListeners = new ArrayList<>(); + } + transferListeners.add(transferListener); + return this; + } + + public List getTransferListeners() { + return transferListeners; + } + + public void setTransferListeners( + Collection transferListeners) { + transferListeners(transferListeners); + } + + @Override + public PresignedDownloadRequest build() { + return new PresignedDownloadRequest<>(this); + } + } +} \ No newline at end of file diff --git a/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedFileDownload.java b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedFileDownload.java new file mode 100644 index 000000000000..669712c2dea1 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/main/java/software/amazon/awssdk/transfer/s3/model/PresignedFileDownload.java @@ -0,0 +1,33 @@ +/* + * 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.transfer.s3.model; + +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.annotations.ThreadSafe; + +/** + * A download transfer of a single object from S3 using a presigned URL. + * + *

    Unlike {@link FileDownload}, this type does not support pause/resume. + */ +@SdkPublicApi +@ThreadSafe +public interface PresignedFileDownload extends ObjectTransfer { + + @Override + CompletableFuture completionFuture(); +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriberTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriberTest.java index 9b570af8cd42..be82440f86ad 100644 --- a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriberTest.java +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/AsyncBufferingSubscriberTest.java @@ -128,12 +128,9 @@ public void consumerFunctionThrows_shouldCancelSubscriptionAndCompleteFutureExce subscriber.onSubscribe(mockSubscription); subscriber.onNext("item"); - /* - subscription.cancel() now exists in two codepaths: - - in onNext() catch block. - - in future.whenComplete() - */ - verify(mockSubscription, times(2)).cancel(); + // Cancelled once, from the onNext() catch block. The whenComplete() handler does not cancel again, which would + // violate Reactive Streams rule 2.3 (cancel from within onError). + verify(mockSubscription, times(1)).cancel(); assertThatThrownBy(future::join).hasCause(exception); } diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerDownloadWireMockTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerDownloadWireMockTest.java new file mode 100644 index 000000000000..8b41e5948a9a --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerDownloadWireMockTest.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.transfer.s3.internal; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.head; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +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.IOException; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.util.concurrent.CompletionException; +import java.util.concurrent.TimeUnit; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.testutils.RandomTempFile; +import software.amazon.awssdk.transfer.s3.CaptureTransferListener; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.FileDownload; +import software.amazon.awssdk.transfer.s3.progress.TransferProgressSnapshot; + +/** + * Exercises the CRT-based transfer manager's download against a real CRT client, so that the response file is genuinely + * written by CRT rather than by the SDK. + */ +@WireMockTest +public class CrtS3TransferManagerDownloadWireMockTest { + private static final String BUCKET = "bucket"; + private static final String KEY = "key"; + private static final int OBJ_SIZE = 16 * 1024; + private static final String E_TAG = "\"1234\""; + + private byte[] content; + private Path destination; + private S3AsyncClient crtClient; + private CrtS3TransferManager tm; + + @BeforeEach + void setUp(WireMockRuntimeInfo wm) throws IOException { + content = RandomStringUtils.randomAlphanumeric(OBJ_SIZE).getBytes(StandardCharsets.UTF_8); + destination = RandomTempFile.randomUncreatedFile().toPath(); + crtClient = S3AsyncClient.crtBuilder() + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:" + wm.getHttpPort())) + .forcePathStyle(true) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("key", "secret"))) + .build(); + tm = new CrtS3TransferManager(TransferManagerConfiguration.builder().build(), crtClient, false); + } + + @AfterEach + void tearDown() { + tm.close(); + crtClient.close(); + destination.toFile().delete(); + } + + @Test + void downloadFile_crtWritesResponseBodyToDestinationFile() throws Exception { + stubSuccessfulGetObject(); + CaptureTransferListener listener = new CaptureTransferListener(); + + FileDownload download = tm.downloadFile(r -> r.getObjectRequest(g -> g.bucket(BUCKET).key(KEY)) + .destination(destination) + .addTransferListener(listener)); + CompletedFileDownload completed = download.completionFuture().join(); + + assertThat(destination).hasBinaryContent(content); + assertThat(completed.response().eTag()).isEqualTo(E_TAG); + + listener.getCompletionFuture().get(10, TimeUnit.SECONDS); + assertThat(listener.isTransferInitiated()).isTrue(); + assertThat(listener.isTransferComplete()).isTrue(); + } + + @Test + void downloadFile_crtWritesResponseBodyToDestinationFile_progressIsNotResetWhenTransferCompletes() throws Exception { + // CRT hands the (empty) body publisher to the SDK only once the transfer has finished, so a response transformer + // wrapper that reset the byte count on subscribe would wipe out all the progress CRT reported. + stubSuccessfulGetObject(); + CaptureTransferListener listener = new CaptureTransferListener(); + + FileDownload download = tm.downloadFile(r -> r.getObjectRequest(g -> g.bucket(BUCKET).key(KEY)) + .destination(destination) + .addTransferListener(listener)); + download.completionFuture().join(); + listener.getCompletionFuture().get(10, TimeUnit.SECONDS); + + TransferProgressSnapshot snapshot = download.progress().snapshot(); + assertThat(snapshot.transferredBytes()).isEqualTo(OBJ_SIZE); + assertThat(snapshot.totalBytes()).hasValue((long) OBJ_SIZE); + assertThat(snapshot.ratioTransferred()).hasValue(1.0); + assertThat(listener.getRatioTransferredList()).contains(1.0); + } + + @Test + void downloadFile_serverError_completesExceptionallyAndReportsFailure() throws Exception { + stubFor(head(anyUrl()).willReturn(aResponse().withStatus(404))); + stubFor(get(anyUrl()).willReturn(aResponse().withStatus(404) + .withBody("" + + "NoSuchKey" + + "does not exist"))); + CaptureTransferListener listener = new CaptureTransferListener(); + + FileDownload download = tm.downloadFile(r -> r.getObjectRequest(g -> g.bucket(BUCKET).key(KEY)) + .destination(destination) + .addTransferListener(listener)); + + assertThatExceptionOfType(CompletionException.class) + .isThrownBy(() -> download.completionFuture().join()) + .withCauseInstanceOf(S3Exception.class); + assertThat(listener.isTransferComplete()).isFalse(); + } + + private void stubSuccessfulGetObject() { + stubFor(head(anyUrl()).willReturn(aResponse().withStatus(200) + .withHeader("Content-Length", String.valueOf(OBJ_SIZE)) + .withHeader("ETag", E_TAG))); + stubFor(get(anyUrl()).willReturn(aResponse().withStatus(200) + .withHeader("ETag", E_TAG) + .withBody(content))); + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerTest.java index 454cd2b7d987..57e3eda18632 100644 --- a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerTest.java +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtS3TransferManagerTest.java @@ -22,6 +22,8 @@ import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SDK_HTTP_EXECUTION_ATTRIBUTES; import static software.amazon.awssdk.services.s3.crt.S3CrtSdkHttpExecutionAttribute.CRT_PROGRESS_LISTENER; import static software.amazon.awssdk.services.s3.crt.S3CrtSdkHttpExecutionAttribute.METAREQUEST_PAUSE_OBSERVABLE; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_OPTION; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_PATH; import com.google.common.jimfs.Jimfs; import java.io.IOException; @@ -40,10 +42,18 @@ import org.mockito.exceptions.verification.WantedButNotInvoked; import org.mockito.junit.jupiter.MockitoExtension; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.listener.AsyncResponseTransformerListener.NotifyingAsyncResponseTransformer; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions.ResponseFileOption; import software.amazon.awssdk.http.SdkHttpExecutionAttributes; import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.internal.crt.CrtResponseFileResponseTransformer; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest; import software.amazon.awssdk.transfer.s3.model.UploadFileRequest; import software.amazon.awssdk.transfer.s3.model.UploadRequest; @@ -101,6 +111,44 @@ void uploadFile_shouldUseCrtUploadFile() { } + @Test + void downloadFile_shouldLetCrtWriteToTheDestinationFile() { + when(s3AsyncClient.getObject(any(GetObjectRequest.class), any(AsyncResponseTransformer.class))) + .thenReturn(CompletableFuture.completedFuture(GetObjectResponse.builder().build())); + Path destination = localDirectory.resolve("download.txt"); + + transferManager.downloadFile(DownloadFileRequest.builder() + .getObjectRequest(r -> r.bucket("test").key("test")) + .destination(destination) + .build()) + .completionFuture() + .join(); + + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(GetObjectRequest.class); + ArgumentCaptor transformerCaptor = + ArgumentCaptor.forClass(AsyncResponseTransformer.class); + verify(s3AsyncClient).getObject(requestCaptor.capture(), transformerCaptor.capture()); + + ExecutionAttributes executionAttributes = requestCaptor.getValue() + .overrideConfiguration() + .orElseThrow(AssertionError::new) + .executionAttributes(); + assertThat(executionAttributes.getAttribute(RESPONSE_FILE_PATH)).isEqualTo(destination); + assertThat(executionAttributes.getAttribute(RESPONSE_FILE_OPTION)).isEqualTo(ResponseFileOption.CREATE_OR_REPLACE); + + SdkHttpExecutionAttributes httpExecutionAttributes = + executionAttributes.getAttribute(SDK_HTTP_EXECUTION_ATTRIBUTES); + assertThat(httpExecutionAttributes).isNotNull(); + assertThat(httpExecutionAttributes.getAttribute(CRT_PROGRESS_LISTENER)).isNotNull(); + assertThat(httpExecutionAttributes.getAttribute(METAREQUEST_PAUSE_OBSERVABLE)).isNotNull(); + + // The body is written by CRT, so the SDK must not be given a transformer that also tries to write the file. + AsyncResponseTransformer transformer = transformerCaptor.getValue(); + assertThat(transformer).isInstanceOf(NotifyingAsyncResponseTransformer.class); + assertThat(((NotifyingAsyncResponseTransformer) transformer).getDelegate()) + .isInstanceOf(CrtResponseFileResponseTransformer.class); + } + @Test void upload_shouldUseCrtUpload() { when(s3AsyncClient.putObject(any(PutObjectRequest.class), any(AsyncRequestBody.class))).thenReturn(CompletableFuture.completedFuture(PutObjectResponse.builder().build())); diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtTransferManagerPauseAndResumeTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtTransferManagerPauseAndResumeTest.java index 8544e37a6470..40349dc4ae22 100644 --- a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtTransferManagerPauseAndResumeTest.java +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/CrtTransferManagerPauseAndResumeTest.java @@ -21,12 +21,16 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_OPTION; +import static software.amazon.awssdk.services.s3.internal.crt.DefaultS3CrtAsyncClient.RESPONSE_FILE_PATH; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.time.Instant; +import java.util.Arrays; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -38,6 +42,8 @@ import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions.ResponseFileOption; import software.amazon.awssdk.services.s3.internal.crt.S3CrtAsyncClient; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; @@ -231,11 +237,127 @@ public void pauseAfterResumeAfterHeadBeforeGetSucceeds() throws InterruptedExcep } - private void verifyActualGetObjectRequest(GetObjectRequest getObjectRequest, String range) { + @Test + void resumeDownloadFile_objectNotModified_shouldAppendRemainingBytesToDestinationFile() { + Instant s3ObjectLastModified = Instant.now(); + DownloadFileRequest downloadFileRequest = downloadFileRequest(); + stubGetObject(); + when(mockS3Crt.headObject(any(Consumer.class))) + .thenReturn(CompletableFuture.completedFuture(headObjectResponse(s3ObjectLastModified, "etag"))); + + tm.resumeDownloadFile(r -> r.bytesTransferred(file.length()) + .downloadFileRequest(downloadFileRequest) + .fileLastModified(Instant.ofEpochMilli(file.lastModified())) + .s3ObjectEtag("etag") + .s3ObjectLastModified(s3ObjectLastModified)) + .completionFuture() + .join(); + + GetObjectRequest actualRequest = capturedGetObjectRequest(); + assertThat(actualRequest.range()).isEqualTo("bytes=1000-2000"); + assertThat(responseFileOption(actualRequest)).isEqualTo(ResponseFileOption.CREATE_OR_APPEND); + assertThat(responseFilePath(actualRequest)).isEqualTo(file.toPath()); + } + + @Test + void resumeDownloadFile_objectEtagModified_shouldReplaceDestinationFile() { + Instant s3ObjectLastModified = Instant.now(); + DownloadFileRequest downloadFileRequest = downloadFileRequest(); + stubGetObject(); + when(mockS3Crt.headObject(any(Consumer.class))) + .thenReturn(CompletableFuture.completedFuture(headObjectResponse(s3ObjectLastModified, "newEtag"))); + + tm.resumeDownloadFile(r -> r.bytesTransferred(file.length()) + .downloadFileRequest(downloadFileRequest) + .fileLastModified(Instant.ofEpochMilli(file.lastModified())) + .s3ObjectEtag("originalEtag") + .s3ObjectLastModified(s3ObjectLastModified)) + .completionFuture() + .join(); + + GetObjectRequest actualRequest = capturedGetObjectRequest(); + assertThat(actualRequest.range()).isNull(); + assertThat(responseFileOption(actualRequest)).isEqualTo(ResponseFileOption.CREATE_OR_REPLACE); + } + + @Test + void resumeDownloadFile_fileModified_shouldReplaceDestinationFile() { + Instant s3ObjectLastModified = Instant.now(); + DownloadFileRequest downloadFileRequest = downloadFileRequest(); + stubGetObject(); + when(mockS3Crt.headObject(any(Consumer.class))) + .thenReturn(CompletableFuture.completedFuture(headObjectResponse(s3ObjectLastModified, "etag"))); + + // bytesTransferred no longer matches the length of the file on disk, so the file was modified while paused + tm.resumeDownloadFile(r -> r.bytesTransferred(file.length() - 1) + .downloadFileRequest(downloadFileRequest) + .fileLastModified(Instant.ofEpochMilli(file.lastModified())) + .s3ObjectEtag("etag") + .s3ObjectLastModified(s3ObjectLastModified)) + .completionFuture() + .join(); + + GetObjectRequest actualRequest = capturedGetObjectRequest(); + assertThat(actualRequest.range()).isNull(); + assertThat(responseFileOption(actualRequest)).isEqualTo(ResponseFileOption.CREATE_OR_REPLACE); + } + + @Test + void resumeDownloadFile_downloadHadCompletedParts_shouldReplaceDestinationFile() { + // A part-by-part download can leave gaps in the file, and CRT can only append, so it must not be continued. + Instant s3ObjectLastModified = Instant.now(); + DownloadFileRequest downloadFileRequest = downloadFileRequest(); + stubGetObject(); + when(mockS3Crt.headObject(any(Consumer.class))) + .thenReturn(CompletableFuture.completedFuture(headObjectResponse(s3ObjectLastModified, "etag"))); + + tm.resumeDownloadFile(r -> r.bytesTransferred(file.length()) + .downloadFileRequest(downloadFileRequest) + .fileLastModified(Instant.ofEpochMilli(file.lastModified())) + .s3ObjectEtag("etag") + .s3ObjectLastModified(s3ObjectLastModified) + .completedParts(Arrays.asList(1, 2))) + .completionFuture() + .join(); + + GetObjectRequest actualRequest = capturedGetObjectRequest(); + assertThat(actualRequest.range()).isNull(); + assertThat(responseFileOption(actualRequest)).isEqualTo(ResponseFileOption.CREATE_OR_REPLACE); + } + + private void stubGetObject() { + when(mockS3Crt.getObject(any(GetObjectRequest.class), any(AsyncResponseTransformer.class))) + .thenReturn(CompletableFuture.completedFuture(GetObjectResponse.builder().build())); + } + + private DownloadFileRequest downloadFileRequest() { + return DownloadFileRequest.builder() + .getObjectRequest(getObjectRequest()) + .destination(file) + .build(); + } + + private static ResponseFileOption responseFileOption(GetObjectRequest request) { + return executionAttributes(request).getAttribute(RESPONSE_FILE_OPTION); + } + + private static Path responseFilePath(GetObjectRequest request) { + return executionAttributes(request).getAttribute(RESPONSE_FILE_PATH); + } + + private static ExecutionAttributes executionAttributes(GetObjectRequest request) { + return request.overrideConfiguration().orElseThrow(AssertionError::new).executionAttributes(); + } + + private GetObjectRequest capturedGetObjectRequest() { ArgumentCaptor getObjectRequestArgumentCaptor = ArgumentCaptor.forClass(GetObjectRequest.class); verify(mockS3Crt).getObject(getObjectRequestArgumentCaptor.capture(), any(AsyncResponseTransformer.class)); - GetObjectRequest actualRequest = getObjectRequestArgumentCaptor.getValue(); + return getObjectRequestArgumentCaptor.getValue(); + } + + private void verifyActualGetObjectRequest(GetObjectRequest getObjectRequest, String range) { + GetObjectRequest actualRequest = capturedGetObjectRequest(); assertThat(actualRequest.bucket()).isEqualTo(getObjectRequest.bucket()); assertThat(actualRequest.key()).isEqualTo(getObjectRequest.key()); assertThat(actualRequest.range()).isEqualTo(range); @@ -249,10 +371,15 @@ private static GetObjectRequest getObjectRequest() { } private static HeadObjectResponse headObjectResponse(Instant s3ObjectLastModified) { + return headObjectResponse(s3ObjectLastModified, null); + } + + private static HeadObjectResponse headObjectResponse(Instant s3ObjectLastModified, String etag) { return HeadObjectResponse .builder() .contentLength(2000L) .lastModified(s3ObjectLastModified) + .eTag(etag) .build(); } diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultPresignedFileDownloadTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultPresignedFileDownloadTest.java new file mode 100644 index 000000000000..b98a4cb35454 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultPresignedFileDownloadTest.java @@ -0,0 +1,30 @@ +/* + * 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.transfer.s3.internal; + +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.transfer.s3.internal.model.DefaultPresignedFileDownload; + +public class DefaultPresignedFileDownloadTest { + + @Test + public void equals_hashcode() { + EqualsVerifier.forClass(DefaultPresignedFileDownload.class) + .withNonnullFields("completionFuture", "progress") + .verify(); + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlDownloadTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlDownloadTest.java new file mode 100644 index 000000000000..a299e5ca41f7 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlDownloadTest.java @@ -0,0 +1,179 @@ +/* + * 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.transfer.s3.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.URL; +import java.nio.file.Paths; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.transfer.s3.model.CompletedDownload; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; + +/** + * Unit tests for S3TransferManager presigned URL download functionality. + */ +class S3TransferManagerPresignedUrlDownloadTest { + private static final String PRESIGNED_URL = "https://test-bucket.s3.amazonaws.com/test-key" + + "?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKID" + + "&X-Amz-Date=20260101T000000Z&X-Amz-Expires=600" + + "&X-Amz-SignedHeaders=host&X-Amz-Signature=abc123"; + + private S3AsyncClient mockS3AsyncClient; + private AsyncPresignedUrlExtension mockPresignedUrlExtension; + private GenericS3TransferManager tm; + private URL presignedUrl; + + @BeforeEach + public void methodSetup() throws Exception { + mockS3AsyncClient = mock(S3AsyncClient.class); + mockPresignedUrlExtension = mock(AsyncPresignedUrlExtension.class); + presignedUrl = new URL(PRESIGNED_URL); + + when(mockS3AsyncClient.presignedUrlExtension()).thenReturn(mockPresignedUrlExtension); + + tm = new GenericS3TransferManager(mockS3AsyncClient, + mock(UploadDirectoryHelper.class), + mock(TransferManagerConfiguration.class), + mock(DownloadDirectoryHelper.class)); + } + + @AfterEach + public void methodTeardown() { + tm.close(); + } + + @Test + void downloadFileWithPresignedUrl_withValidRequest_returnsResponse() { + GetObjectResponse response = GetObjectResponse.builder().build(); + stubGetObject(CompletableFuture.completedFuture(response)); + + CompletedFileDownload completed = tm.downloadFileWithPresignedUrl(fileDownloadRequest()) + .completionFuture().join(); + + assertThat(completed.response()).isEqualTo(response); + } + + @Test + void downloadWithPresignedUrl_withValidRequest_returnsResponse() { + ResponseBytes responseBytes = ResponseBytes.fromByteArray( + GetObjectResponse.builder().build(), "test".getBytes()); + stubGetObject(CompletableFuture.completedFuture(responseBytes)); + + CompletedDownload> completed = + tm.downloadWithPresignedUrl(bytesDownloadRequest()).completionFuture().join(); + + assertThat(completed.result()).isEqualTo(responseBytes); + } + + @Test + void downloadFileWithPresignedUrl_withConsumerBuilder_returnsResponse() { + GetObjectResponse response = GetObjectResponse.builder().build(); + stubGetObject(CompletableFuture.completedFuture(response)); + + CompletedFileDownload completed = tm.downloadFileWithPresignedUrl( + request -> request.presignedUrlDownloadRequest(p -> p.presignedUrl(presignedUrl)) + .destination(Paths.get("/tmp/test"))) + .completionFuture().join(); + + assertThat(completed.response()).isEqualTo(response); + } + + @Test + void downloadFileWithPresignedUrl_whenCancelled_shouldForwardCancellation() { + CompletableFuture s3Future = new CompletableFuture<>(); + stubGetObject(s3Future); + + CompletableFuture future = + tm.downloadFileWithPresignedUrl(fileDownloadRequest()).completionFuture(); + + future.cancel(true); + assertThat(s3Future).isCancelled(); + } + + @Test + void downloadFileWithPresignedUrl_whenRequestFails_shouldCompleteExceptionally() { + CompletableFuture failedFuture = new CompletableFuture<>(); + failedFuture.completeExceptionally(new RuntimeException("download failed")); + stubGetObject(failedFuture); + + assertThatThrownBy(() -> tm.downloadFileWithPresignedUrl(fileDownloadRequest()).completionFuture().join()) + .hasCauseInstanceOf(RuntimeException.class) + .hasMessageContaining("download failed"); + } + + @Test + void downloadWithPresignedUrl_whenCancelled_shouldForwardCancellation() { + CompletableFuture s3Future = new CompletableFuture<>(); + stubGetObject(s3Future); + + CompletableFuture>> future = + tm.downloadWithPresignedUrl(bytesDownloadRequest()).completionFuture(); + + future.cancel(true); + assertThat(s3Future).isCancelled(); + } + + @Test + void downloadFileWithPresignedUrl_withNullRequest_shouldThrowNullPointerException() { + assertThatThrownBy(() -> tm.downloadFileWithPresignedUrl((PresignedDownloadFileRequest) null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + void downloadWithPresignedUrl_withNullRequest_shouldThrowNullPointerException() { + assertThatThrownBy(() -> tm.downloadWithPresignedUrl(null)) + .isInstanceOf(NullPointerException.class); + } + + private PresignedDownloadFileRequest fileDownloadRequest() { + return PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .destination(Paths.get("/tmp/test")) + .build(); + } + + private PresignedDownloadRequest> bytesDownloadRequest() { + return PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .build(); + } + + private void stubGetObject(CompletableFuture future) { + when(mockPresignedUrlExtension.getObject(any(PresignedUrlDownloadRequest.class), any(AsyncResponseTransformer.class))) + .thenReturn(future); + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlListenerWiremockTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlListenerWiremockTest.java new file mode 100644 index 000000000000..2e9e5dbecca8 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/S3TransferManagerPresignedUrlListenerWiremockTest.java @@ -0,0 +1,253 @@ +/* + * 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.transfer.s3.internal; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; + +import com.github.tomakehurst.wiremock.client.WireMock; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.util.concurrent.CompletionException; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeAll; +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.ArgumentMatchers; +import org.mockito.Mockito; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.testutils.RandomTempFile; +import software.amazon.awssdk.transfer.s3.S3TransferManager; +import software.amazon.awssdk.transfer.s3.model.Download; +import software.amazon.awssdk.transfer.s3.model.PresignedFileDownload; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadRequest; +import software.amazon.awssdk.transfer.s3.progress.TransferListener; + +/** + * Tests that TransferListener callbacks fire correctly for presigned URL downloads + * with both multipart-enabled and non-multipart clients. + */ +@WireMockTest +public class S3TransferManagerPresignedUrlListenerWiremockTest { + + private static URI testEndpoint; + private static RandomTempFile testFile; + + @BeforeAll + public static void init(WireMockRuntimeInfo wm) throws IOException { + testEndpoint = URI.create(wm.getHttpBaseUrl()); + testFile = new RandomTempFile("presigned-listener-test", 1024); + } + + @BeforeEach + void resetWireMock() { + WireMock.reset(); + } + + private static S3AsyncClient s3AsyncClient(boolean multipartEnabled) { + return S3AsyncClient.builder() + .multipartEnabled(multipartEnabled) + .region(Region.US_EAST_1) + .endpointOverride(testEndpoint) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("key", "secret"))) + .build(); + } + + static Stream presignedUrlTestCases() { + return Stream.of( + Arguments.of(true, "toFile", null), + Arguments.of(true, "toFile", "bytes=0-511"), + Arguments.of(true, "toBytes", null), + Arguments.of(true, "toBytes", "bytes=0-511"), + Arguments.of(false, "toFile", null), + Arguments.of(false, "toFile", "bytes=0-511"), + Arguments.of(false, "toBytes", null), + Arguments.of(false, "toBytes", "bytes=0-511") + ); + } + + @ParameterizedTest(name = "presignedUrlDownload_multipart={0}_type={1}_range={2}") + @MethodSource("presignedUrlTestCases") + void presignedUrlDownload_shouldInvokeListener(boolean multipartEnabled, String type, String range) throws Exception { + S3AsyncClient s3Async = s3AsyncClient(multipartEnabled); + S3TransferManager tm = new GenericS3TransferManager(s3Async, mock(UploadDirectoryHelper.class), + mock(TransferManagerConfiguration.class), + mock(DownloadDirectoryHelper.class)); + + byte[] responseBody = new byte[512]; + stubFor(get(urlPathEqualTo("/presigned-key")).willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "512") + .withHeader("Content-Range", "bytes 0-511/512") + .withHeader("ETag", "\"test-etag\"") + .withBody(responseBody))); + + TransferListener listener = mock(TransferListener.class); + URL presignedUrl = new URL(testEndpoint + "/presigned-key?X-Amz-Algorithm=AWS4-HMAC-SHA256"); + + PresignedUrlDownloadRequest.Builder requestBuilder = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl); + if (range != null) { + requestBuilder.range(range); + } + + if ("toFile".equals(type)) { + PresignedFileDownload download = tm.downloadFileWithPresignedUrl( + PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(requestBuilder.build()) + .destination(testFile.toPath()) + .addTransferListener(listener) + .build()); + download.completionFuture().join(); + } else { + Download download = tm.downloadWithPresignedUrl( + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(requestBuilder.build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .addTransferListener(listener) + .build()); + download.completionFuture().join(); + } + + Mockito.verify(listener, timeout(1000).times(1)).transferInitiated(ArgumentMatchers.any()); + Mockito.verify(listener, timeout(1000).atLeastOnce()).bytesTransferred(ArgumentMatchers.any()); + + tm.close(); + s3Async.close(); + } + + static Stream presignedUrlFailureTestCases() { + return Stream.of( + Arguments.of(true, "toFile"), + Arguments.of(true, "toBytes"), + Arguments.of(false, "toFile"), + Arguments.of(false, "toBytes") + ); + } + + @ParameterizedTest(name = "presignedUrlDownload_failure_multipart={0}_type={1}") + @MethodSource("presignedUrlFailureTestCases") + void presignedUrlDownload_failure_shouldInvokeListener(boolean multipartEnabled, String type) throws Exception { + S3AsyncClient s3Async = s3AsyncClient(multipartEnabled); + S3TransferManager tm = new GenericS3TransferManager(s3Async, mock(UploadDirectoryHelper.class), + mock(TransferManagerConfiguration.class), + mock(DownloadDirectoryHelper.class)); + + stubFor(get(urlPathEqualTo("/presigned-key")) + .willReturn(aResponse().withStatus(404) + .withBody("TestErrorTest failure"))); + + TransferListener listener = mock(TransferListener.class); + URL presignedUrl = new URL(testEndpoint + "/presigned-key?X-Amz-Algorithm=AWS4-HMAC-SHA256"); + + if ("toFile".equals(type)) { + PresignedFileDownload download = tm.downloadFileWithPresignedUrl( + PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .destination(testFile.toPath()) + .addTransferListener(listener) + .build()); + assertThatExceptionOfType(CompletionException.class).isThrownBy(() -> download.completionFuture().join()); + } else { + Download download = tm.downloadWithPresignedUrl( + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .addTransferListener(listener) + .build()); + assertThatExceptionOfType(CompletionException.class).isThrownBy(() -> download.completionFuture().join()); + } + + Mockito.verify(listener, timeout(1000).times(1)).transferInitiated(ArgumentMatchers.any()); + Mockito.verify(listener, timeout(1000).times(1)).transferFailed(ArgumentMatchers.any()); + Mockito.verify(listener, times(0)).transferComplete(ArgumentMatchers.any()); + + tm.close(); + s3Async.close(); + } + + @ParameterizedTest(name = "presignedUrlDownload_cancelled_multipart={0}_type={1}") + @MethodSource("presignedUrlFailureTestCases") + void presignedUrlDownload_cancelled_shouldInvokeTransferFailed(boolean multipartEnabled, String type) throws Exception { + S3AsyncClient s3Async = s3AsyncClient(multipartEnabled); + S3TransferManager tm = new GenericS3TransferManager(s3Async, mock(UploadDirectoryHelper.class), + mock(TransferManagerConfiguration.class), + mock(DownloadDirectoryHelper.class)); + + // Slow response to keep request in-flight during cancellation + stubFor(get(urlPathEqualTo("/presigned-key")).willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "512") + .withHeader("Content-Range", "bytes 0-511/512") + .withHeader("ETag", "\"test-etag\"") + .withBody(new byte[512]) + .withFixedDelay(5000))); + + TransferListener listener = mock(TransferListener.class); + URL presignedUrl = new URL(testEndpoint + "/presigned-key?X-Amz-Algorithm=AWS4-HMAC-SHA256"); + + if ("toFile".equals(type)) { + PresignedFileDownload download = tm.downloadFileWithPresignedUrl( + PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .destination(testFile.toPath()) + .addTransferListener(listener) + .build()); + download.completionFuture().cancel(true); + } else { + Download download = tm.downloadWithPresignedUrl( + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .addTransferListener(listener) + .build()); + download.completionFuture().cancel(true); + } + + Mockito.verify(listener, timeout(1000).times(1)).transferInitiated(ArgumentMatchers.any()); + Mockito.verify(listener, timeout(1000).times(1)).transferFailed(ArgumentMatchers.any()); + Mockito.verify(listener, times(0)).transferComplete(ArgumentMatchers.any()); + + tm.close(); + s3Async.close(); + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferManagerUploadUserAgentBusinessMetricWireMockTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferManagerUploadUserAgentBusinessMetricWireMockTest.java new file mode 100644 index 000000000000..a87fcb61f305 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferManagerUploadUserAgentBusinessMetricWireMockTest.java @@ -0,0 +1,304 @@ +/* + * 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.transfer.s3.internal; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +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.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder; +import java.io.ByteArrayInputStream; +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.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +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.async.AsyncRequestBody; +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.S3CrtAsyncClientBuilder; +import software.amazon.awssdk.transfer.s3.S3TransferManager; +import software.amazon.awssdk.transfer.s3.model.UploadRequest; + +/** + * Verifies that {@link S3TransferManager} uploads propagate the request-body business metric ({@code md/rb#}) onto the user + * agent of the request that carries the body, on the wire, across both TM flavors (Java-based and CRT-based) and the file, bytes, + * and stream body types. + */ +public class TransferManagerUploadUserAgentBusinessMetricWireMockTest { + private static final WireMockServer wireMock = new WireMockServer(wireMockConfig().dynamicPort()); + private static final long PART_SIZE = 100L; + private static Path smallFile; + private static Path largeFile; + private static ExecutorService streamExecutor; + + @BeforeAll + public static void setup() throws IOException { + smallFile = Files.createTempFile("single-part", ".dat"); + writeTestFile(smallFile, PART_SIZE / 2); + largeFile = Files.createTempFile("multi-part", ".dat"); + writeTestFile(largeFile, PART_SIZE * 2); + streamExecutor = Executors.newSingleThreadExecutor(); + wireMock.start(); + } + + @AfterAll + public static void teardown() throws IOException { + Files.deleteIfExists(smallFile); + Files.deleteIfExists(largeFile); + streamExecutor.shutdownNow(); + wireMock.stop(); + } + + private static Stream uploadMatrix() { + return Stream.of( + Arguments.of("JAVA / single-part file -> PutObject", TmFlavor.JAVA, Scenario.SINGLE_PART_FILE, "md/rb#f"), + Arguments.of("JAVA / single-part bytes -> PutObject", TmFlavor.JAVA, Scenario.SINGLE_PART_BYTES, "md/rb#b"), + Arguments.of("JAVA / single-part stream -> PutObject", TmFlavor.JAVA, Scenario.SINGLE_PART_STREAM, "md/rb#s"), + Arguments.of("JAVA / multipart file -> UploadPart", TmFlavor.JAVA, Scenario.MULTIPART_FILE, "md/rb#f"), + Arguments.of("CRT / single-part file -> PutObject", TmFlavor.CRT, Scenario.SINGLE_PART_FILE, "md/rb#f"), + Arguments.of("CRT / single-part bytes -> PutObject", TmFlavor.CRT, Scenario.SINGLE_PART_BYTES, "md/rb#b"), + Arguments.of("CRT / single-part stream -> PutObject", TmFlavor.CRT, Scenario.SINGLE_PART_STREAM, "md/rb#s"), + Arguments.of("CRT / multipart file -> UploadPart", TmFlavor.CRT, Scenario.MULTIPART_FILE, "md/rb#f")); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("uploadMatrix") + void upload_userAgentCarriesExpectedBodyMetric(String description, TmFlavor flavor, Scenario scenario, + String expectedMetric) { + wireMock.resetAll(); + scenario.stub(); + + try (S3TransferManager tm = flavor.create(scenario.multipartEnabled())) { + scenario.runUpload(tm); + } + + wireMock.verify(scenario.verification().withHeader("User-Agent", containing(expectedMetric))); + } + + private static void uploadFile(S3TransferManager tm, Path source) { + tm.uploadFile(u -> u.source(source).putObjectRequest(put -> put.bucket("bucket").key("key"))) + .completionFuture().join(); + } + + private static void upload(S3TransferManager tm, AsyncRequestBody body) { + tm.upload(UploadRequest.builder() + .requestBody(body) + .putObjectRequest(put -> put.bucket("bucket").key("key")) + .build()) + .completionFuture().join(); + } + + private static S3AsyncClientBuilder javaClientBuilder() { + return S3AsyncClient.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .region(Region.US_EAST_1) + .forcePathStyle(true); + } + + private static S3CrtAsyncClientBuilder crtClientBuilder() { + return S3AsyncClient.crtBuilder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .region(Region.US_EAST_1) + .forcePathStyle(true); + } + + private static void stubSinglePutSuccess() { + wireMock.stubFor(put(anyUrl()).willReturn(aResponse().withStatus(200))); + } + + private static void stubSuccessfulMultipartUpload() { + String mpuInitBody = "\n" + + "\n" + + " bucket\n" + + " key\n" + + " uploadId\n" + + ""; + wireMock.stubFor(post(urlEqualTo("/bucket/key?uploads")) + .willReturn(aResponse().withStatus(200).withBody(mpuInitBody))); + + for (int i = 1; i <= 2; i++) { + // The CRT native client reads the part ETag from the response header; the Java client reads it from the body. + // Provide both so the one stub serves both flavors. + wireMock.stubFor(put(urlEqualTo("/bucket/key?partNumber=" + i + "&uploadId=uploadId")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", "\"etag" + i + "\"") + .withBody("" + i + + "\"etag" + i + "\""))); + } + + 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 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); + } + } + + enum TmFlavor { + JAVA { + @Override + S3TransferManager create(boolean multipartEnabled) { + S3AsyncClientBuilder builder = javaClientBuilder(); + if (multipartEnabled) { + builder.multipartEnabled(true) + .multipartConfiguration(c -> c.thresholdInBytes(PART_SIZE) + .minimumPartSizeInBytes(PART_SIZE) + .apiCallBufferSizeInBytes(PART_SIZE * 4)); + } + return S3TransferManager.builder().s3Client(builder.build()).build(); + } + }, + CRT { + @Override + S3TransferManager create(boolean multipartEnabled) { + S3CrtAsyncClientBuilder builder = crtClientBuilder(); + if (multipartEnabled) { + // The CRT client always chunks natively; a small part size forces >1 UploadPart against WireMock. + builder.minimumPartSizeInBytes(PART_SIZE).thresholdInBytes(PART_SIZE); + } + return S3TransferManager.builder().s3Client(builder.build()).build(); + } + }; + + abstract S3TransferManager create(boolean multipartEnabled); + } + + enum Scenario { + SINGLE_PART_FILE(false) { + @Override + void stub() { + stubSinglePutSuccess(); + } + + @Override + void runUpload(S3TransferManager tm) { + uploadFile(tm, smallFile); + } + + @Override + RequestPatternBuilder verification() { + return putRequestedFor(urlPathEqualTo("/bucket/key")); + } + }, + SINGLE_PART_BYTES(false) { + @Override + void stub() { + stubSinglePutSuccess(); + } + + @Override + void runUpload(S3TransferManager tm) { + upload(tm, AsyncRequestBody.fromString("hello world")); + } + + @Override + RequestPatternBuilder verification() { + return putRequestedFor(urlPathEqualTo("/bucket/key")); + } + }, + SINGLE_PART_STREAM(false) { + @Override + void stub() { + stubSinglePutSuccess(); + } + + @Override + void runUpload(S3TransferManager tm) { + upload(tm, AsyncRequestBody.fromInputStream(new ByteArrayInputStream(new byte[16]), 16L, + streamExecutor)); + } + + @Override + RequestPatternBuilder verification() { + return putRequestedFor(urlPathEqualTo("/bucket/key")); + } + }, + MULTIPART_FILE(true) { + @Override + void stub() { + stubSuccessfulMultipartUpload(); + } + + @Override + void runUpload(S3TransferManager tm) { + uploadFile(tm, largeFile); + } + + @Override + RequestPatternBuilder verification() { + return putRequestedFor(urlPathEqualTo("/bucket/key")).withQueryParam("partNumber", containing("1")); + } + }; + + private final boolean multipartEnabled; + + Scenario(boolean multipartEnabled) { + this.multipartEnabled = multipartEnabled; + } + + boolean multipartEnabled() { + return multipartEnabled; + } + + abstract void stub(); + + abstract void runUpload(S3TransferManager tm); + + abstract RequestPatternBuilder verification(); + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferProgressUpdaterTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferProgressUpdaterTest.java index 88dd1665bf25..aaa33a9b5ea7 100644 --- a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferProgressUpdaterTest.java +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/TransferProgressUpdaterTest.java @@ -50,6 +50,8 @@ import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.async.listener.PublisherListener; +import software.amazon.awssdk.crt.s3.S3MetaRequestProgress; import software.amazon.awssdk.http.async.SimpleSubscriber; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; @@ -469,6 +471,96 @@ public void onComplete() { assertThat(upstreamBytesReceived.get()).isEqualTo(60 + (int) partSize); } + @Test + void crtProgressListener_totalBytesUnknownUpFront_takesTotalBytesFromCrtProgress() { + TransferProgressUpdater updater = new TransferProgressUpdater(Mockito.mock(TransferObjectRequest.class), null); + PublisherListener listener = updater.crtProgressListener(); + + assertThat(updater.progress().snapshot().totalBytes()).isEmpty(); + + listener.subscriberOnNext(new S3MetaRequestProgress().withContentLength(1024L).withBytesTransferred(256L)); + + assertThat(updater.progress().snapshot().totalBytes()).hasValue(1024L); + assertThat(updater.progress().snapshot().transferredBytes()).isEqualTo(256L); + assertThat(updater.progress().snapshot().ratioTransferred()).hasValue(0.25); + + listener.subscriberOnNext(new S3MetaRequestProgress().withContentLength(1024L).withBytesTransferred(768L)); + + assertThat(updater.progress().snapshot().totalBytes()).hasValue(1024L); + assertThat(updater.progress().snapshot().transferredBytes()).isEqualTo(1024L); + } + + @Test + void crtProgressListener_totalBytesKnownUpFront_keepsTheKnownTotalBytes() { + TransferProgressUpdater updater = new TransferProgressUpdater(Mockito.mock(TransferObjectRequest.class), 2048L); + + updater.crtProgressListener() + .subscriberOnNext(new S3MetaRequestProgress().withContentLength(1024L).withBytesTransferred(256L)); + + assertThat(updater.progress().snapshot().totalBytes()).hasValue(2048L); + } + + @Test + void wrapCrtResponseFileTransformer_publisherSubscribedAfterTransfer_keepsProgressReportedByCrt() { + // When CRT writes the body straight to a file the SDK only sees the response, and the (already empty) body publisher, + // once the transfer has finished. Resetting the byte count at that point would discard everything CRT reported. + TransferProgressUpdater updater = new TransferProgressUpdater(Mockito.mock(TransferObjectRequest.class), null); + updater.crtProgressListener() + .subscriberOnNext(new S3MetaRequestProgress().withContentLength(1024L).withBytesTransferred(1024L)); + assertThat(updater.progress().snapshot().transferredBytes()).isEqualTo(1024L); + + AsyncResponseTransformer transformer = + updater.wrapCrtResponseFileTransformer(noOpTransformer()); + transformer.prepare(); + transformer.onResponse(GetObjectResponse.builder().contentLength(1024L).build()); + transformer.onStream(SdkPublisher.adapt(new SimplePublisher<>())); + + assertThat(updater.progress().snapshot().transferredBytes()).isEqualTo(1024L); + assertThat(updater.progress().snapshot().totalBytes()).hasValue(1024L); + assertThat(updater.progress().snapshot().sdkResponse()).isPresent(); + } + + @Test + void wrapResponseTransformer_publisherSubscribed_resetsProgress() { + // Contrast with wrapCrtResponseFileTransformer: on the Java path the publisher is subscribed before any body arrives, + // so resetting there is what makes retries report progress correctly. + TransferProgressUpdater updater = new TransferProgressUpdater(Mockito.mock(TransferObjectRequest.class), null); + updater.crtProgressListener() + .subscriberOnNext(new S3MetaRequestProgress().withContentLength(1024L).withBytesTransferred(1024L)); + + AsyncResponseTransformer transformer = + updater.wrapResponseTransformer(noOpTransformer()); + transformer.prepare(); + transformer.onResponse(GetObjectResponse.builder().contentLength(1024L).build()); + transformer.onStream(SdkPublisher.adapt(new SimplePublisher<>())); + + assertThat(updater.progress().snapshot().transferredBytes()).isZero(); + } + + private static AsyncResponseTransformer noOpTransformer() { + return new AsyncResponseTransformer() { + @Override + public CompletableFuture prepare() { + return new CompletableFuture<>(); + } + + @Override + public void onResponse(GetObjectResponse response) { + // noop, test only + } + + @Override + public void onStream(SdkPublisher publisher) { + publisher.subscribe(b -> { /* do nothing, test only */ }); + } + + @Override + public void exceptionOccurred(Throwable error) { + // noop, test only + } + }; + } + private static class ExceptionThrowingByteArrayInputStream extends ByteArrayInputStream { private final int exceptionPosition; diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownloadTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownloadTest.java new file mode 100644 index 000000000000..72932ad7b085 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/model/CrtFileDownloadTest.java @@ -0,0 +1,302 @@ +/* + * 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.transfer.s3.internal.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.commons.lang3.RandomStringUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.crt.CrtRuntimeException; +import software.amazon.awssdk.crt.s3.ResumeToken; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions; +import software.amazon.awssdk.services.s3.internal.crt.S3MetaRequestPauseObservable; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.transfer.s3.internal.progress.DefaultTransferProgress; +import software.amazon.awssdk.transfer.s3.internal.progress.DefaultTransferProgressSnapshot; +import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload; +import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest; +import software.amazon.awssdk.transfer.s3.model.ResumableFileDownload; +import software.amazon.awssdk.transfer.s3.progress.TransferProgress; +import software.amazon.awssdk.utils.CompletableFutureUtils; + +/** + * Note that the download-specific fields of {@link ResumeToken} are populated by CRT's native code and there is no public + * builder for them, so a download token can only be mocked here rather than constructed. + */ +class CrtFileDownloadTest { + + private static final String ETAG = "\"abc123\""; + private static final Instant S3_OBJECT_LAST_MODIFIED = Instant.parse("2026-07-15T10:15:30Z"); + private static final String S3_OBJECT_LAST_MODIFIED_HTTP_DATE = "Wed, 15 Jul 2026 10:15:30 GMT"; + private static final long OBJECT_SIZE = 8000L; + private static final long FILE_CONTENT_LENGTH = 2000L; + + private File file; + private S3MetaRequestPauseObservable observable; + private CompletableFuture completionFuture; + private DownloadFileRequest request; + + @BeforeEach + void setUp() throws IOException { + file = File.createTempFile("test", UUID.randomUUID().toString()); + Files.write(file.toPath(), RandomStringUtils.randomAlphanumeric((int) FILE_CONTENT_LENGTH) + .getBytes(StandardCharsets.UTF_8)); + observable = mock(S3MetaRequestPauseObservable.class); + completionFuture = new CompletableFuture<>(); + request = DownloadFileRequest.builder() + .getObjectRequest(r -> r.bucket("bucket").key("key")) + .destination(file) + .build(); + } + + @AfterEach + void tearDown() { + file.delete(); + } + + @Test + void pause_withDownloadResumeToken_takesObjectMetadataFromToken() { + ResumeToken token = downloadResumeToken(0, 1500); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(1500L); + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + assertThat(resumable.s3ObjectLastModified()).hasValue(S3_OBJECT_LAST_MODIFIED); + assertThat(resumable.totalSizeInBytes()).hasValue(OBJECT_SIZE); + assertThat(resumable.fileLastModified()).isEqualTo(Instant.ofEpochMilli(file.lastModified())); + assertThat(resumable.downloadFileRequest()).isEqualTo(request); + assertThat(completionFuture).isCancelled(); + } + + @Test + void pause_withDownloadResumeTokenForRangedDownload_bytesTransferredIsAbsoluteObjectOffset() { + // A resumed download issues a ranged GET, so CRT reports the gap-free prefix relative to the range start rather than + // to the start of the object. + ResumeToken token = downloadResumeToken(2000, 1500); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(3500L); + } + + @Test + void pause_pauseReturnsNoToken_fallsBackToFileLengthAndResumedDownloadMetadata() { + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(null)); + ResumableFileDownload resumedDownload = resumedDownload(); + + ResumableFileDownload resumable = fileDownload(resumedDownload).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + assertThat(resumable.s3ObjectLastModified()).hasValue(S3_OBJECT_LAST_MODIFIED); + assertThat(resumable.totalSizeInBytes()).hasValue(OBJECT_SIZE); + } + + @Test + void pause_pauseReturnsNoTokenAndNoResumedDownload_returnsNoObjectMetadata() { + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(null)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(resumable.s3ObjectEtag()).isEmpty(); + assertThat(resumable.s3ObjectLastModified()).isEmpty(); + assertThat(resumable.totalSizeInBytes()).isEmpty(); + } + + @Test + void pause_uploadResumeToken_ignoresTokenAndDoesNotThrow() { + // The download-specific getters throw when read off an upload token, so the token type must be checked first. + ResumeToken uploadToken = new ResumeToken(new ResumeToken.PutResumeTokenBuilder().withPartSize(8L) + .withTotalNumParts(2L) + .withNumPartsCompleted(1L) + .withUploadId("id")); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(uploadToken)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(resumable.s3ObjectEtag()).isEmpty(); + } + + @Test + void pause_completionFutureAlreadyComplete_doesNotPauseAndUsesResponseFromProgress() { + GetObjectResponse response = GetObjectResponse.builder() + .eTag(ETAG) + .lastModified(S3_OBJECT_LAST_MODIFIED) + .contentLength(OBJECT_SIZE) + .build(); + completionFuture.complete(CompletedFileDownload.builder().response(response).build()); + TransferProgress progress = new DefaultTransferProgress( + DefaultTransferProgressSnapshot.builder() + .transferredBytes(FILE_CONTENT_LENGTH) + .totalBytes(OBJECT_SIZE) + .sdkResponse(response) + .build()); + + ResumableFileDownload resumable = new CrtFileDownload(completionFuture, progress, observable, () -> request, null) + .pause(); + + verify(observable, never()).pauseAsync(); + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + assertThat(resumable.s3ObjectLastModified()).hasValue(S3_OBJECT_LAST_MODIFIED); + assertThat(resumable.totalSizeInBytes()).hasValue(OBJECT_SIZE); + } + + @Test + void pause_completedEmptyObject_omitsTotalSize() { + // ResumableFileDownload rejects a non-positive totalSizeInBytes, so a zero-length object must not be passed through. + GetObjectResponse response = GetObjectResponse.builder().eTag(ETAG).contentLength(0L).build(); + completionFuture.complete(CompletedFileDownload.builder().response(response).build()); + TransferProgress progress = new DefaultTransferProgress( + DefaultTransferProgressSnapshot.builder().transferredBytes(0L).sdkResponse(response).build()); + + ResumableFileDownload resumable = new CrtFileDownload(completionFuture, progress, observable, () -> request, null) + .pause(); + + assertThat(resumable.totalSizeInBytes()).isEmpty(); + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + } + + @Test + void pause_pauseTimesOut_stillReturnsResumableFromFallbackMetadata() { + // Never completes, so the bounded wait in pause() has to give up rather than block the caller forever. + when(observable.pauseAsync()).thenReturn(new CompletableFuture<>()); + + ResumableFileDownload resumable = + new CrtFileDownload(completionFuture, progress(), observable, () -> request, resumedDownload(), + Duration.ofMillis(50)).pause(); + + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(completionFuture).isCancelled(); + } + + @Test + void pause_pauseFails_returnsResumableThatRestartsFromTheBeginning() { + when(observable.pauseAsync()).thenReturn(CompletableFutureUtils.failedFuture(new CrtRuntimeException(1))); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.bytesTransferred()).isEqualTo(FILE_CONTENT_LENGTH); + assertThat(resumable.s3ObjectEtag()).isEmpty(); + assertThat(completionFuture).isCancelled(); + } + + @Test + void pause_awaitsTheCrtPauseBeforeCancellingTheTransfer() { + // Cancelling closes the underlying CRT meta request, and a closed meta request can no longer hand back a resume + // token, so the pause has to be awaited first. + ResumeToken token = downloadResumeToken(0, 1500); + AtomicBoolean alreadyCancelledWhenPaused = new AtomicBoolean(true); + when(observable.pauseAsync()).thenAnswer(invocation -> { + alreadyCancelledWhenPaused.set(completionFuture.isCancelled()); + return CompletableFuture.completedFuture(token); + }); + + fileDownload(null).pause(); + + assertThat(alreadyCancelledWhenPaused).isFalse(); + assertThat(completionFuture).isCancelled(); + } + + @Test + void pause_calledTwice_pausesUnderlyingRequestOnlyOnce() { + ResumeToken token = downloadResumeToken(0, 1500); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + CrtFileDownload download = fileDownload(null); + + ResumableFileDownload first = download.pause(); + ResumableFileDownload second = download.pause(); + + assertThat(first).isSameAs(second); + verify(observable, times(1)).pauseAsync(); + } + + @Test + void pause_unparsableLastModifiedFromToken_omitsLastModified() { + ResumeToken token = downloadResumeToken(0, 1500); + when(token.getS3ObjectLastModified()).thenReturn("not-a-date"); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.s3ObjectLastModified()).isEmpty(); + assertThat(resumable.s3ObjectEtag()).hasValue(ETAG); + } + + @Test + void pause_tokenWithUnknownObjectSize_omitsTotalSize() { + ResumeToken token = downloadResumeToken(0, 0); + when(token.getObjectSize()).thenReturn(0L); + when(observable.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + + ResumableFileDownload resumable = fileDownload(null).pause(); + + assertThat(resumable.totalSizeInBytes()).isEmpty(); + assertThat(resumable.bytesTransferred()).isZero(); + } + + private CrtFileDownload fileDownload(ResumableFileDownload resumedDownload) { + return new CrtFileDownload(completionFuture, progress(), observable, () -> request, resumedDownload); + } + + private TransferProgress progress() { + return new DefaultTransferProgress(DefaultTransferProgressSnapshot.builder().transferredBytes(0L).build()); + } + + private ResumableFileDownload resumedDownload() { + return ResumableFileDownload.builder() + .downloadFileRequest(request) + .bytesTransferred(FILE_CONTENT_LENGTH) + .fileLastModified(Instant.ofEpochMilli(file.lastModified())) + .s3ObjectEtag(ETAG) + .s3ObjectLastModified(S3_OBJECT_LAST_MODIFIED) + .totalSizeInBytes(OBJECT_SIZE) + .build(); + } + + private static ResumeToken downloadResumeToken(long objectRangeStart, long continuesDownloadedBytes) { + ResumeToken token = mock(ResumeToken.class); + when(token.getType()).thenReturn(S3MetaRequestOptions.MetaRequestType.GET_OBJECT); + when(token.getObjectRangeStart()).thenReturn(objectRangeStart); + when(token.getContinuesDownloadedBytes()).thenReturn(continuesDownloadedBytes); + when(token.getEtag()).thenReturn(ETAG); + when(token.getS3ObjectLastModified()).thenReturn(S3_OBJECT_LAST_MODIFIED_HTTP_DATE); + when(token.getObjectSize()).thenReturn(OBJECT_SIZE); + return token; + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferListenerContextTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferListenerContextTest.java new file mode 100644 index 000000000000..cea4f6be4537 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/progress/TransferListenerContextTest.java @@ -0,0 +1,125 @@ +/* + * 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.transfer.s3.internal.progress; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; +import java.util.concurrent.CompletionException; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.transfer.s3.model.PresignedDownloadFileRequest; + +class TransferListenerContextTest { + + @Test + void toString_redactsPresignedUrlQueryString() { + URL url = signedUrl(); + + String result = presignedContext(url).toString(); + + assertNoSignatureMaterial(result, url); + } + + @Test + void failedContext_toString_redactsRequest_withUnrelatedException() { + URL url = signedUrl(); + + TransferListenerFailedContext failedContext = + TransferListenerFailedContext.builder() + .transferContext(presignedContext(url)) + .exception(new RuntimeException("boom")) + .build(); + + assertNoSignatureMaterial(failedContext.toString(), url); + } + + @Test + void failedContext_toString_redactsRequest_withMarshallingShapedException() throws Exception { + URL url = signedUrl(); + URL malformedUrl = new URL("https", "bucket.s3.us-east-1.amazonaws.com", -1, + "/my key.txt?X-Amz-Signature=deadbeefdeadbeef" + + "&X-Amz-Security-Token=SESSIONTOKENEXAMPLE"); + + // Shaped like the exception the marshaller builds: a redacted message over a URISyntaxException embedding the URL. + SdkClientException marshallingException = + SdkClientException.builder() + .message("Unable to marshall pre-signed URL Request for " + + "https://bucket.s3.us-east-1.amazonaws.com/my key.txt" + + "?*** Sensitive Data Redacted ***: Illegal character in path at index 44") + .cause(uriSyntaxExceptionFor(malformedUrl)) + .build(); + + TransferListenerFailedContext failedContext = + TransferListenerFailedContext.builder() + .transferContext(presignedContext(url)) + .exception(new CompletionException(marshallingException)) + .build(); + + assertNoSignatureMaterial(failedContext.toString(), url); + assertThat(failedContext.toString()).doesNotContain(malformedUrl.getQuery()); + } + + private void assertNoSignatureMaterial(String result, URL url) { + assertThat(result) + .doesNotContain("X-Amz-Signature") + .doesNotContain("deadbeef") + .doesNotContain("X-Amz-Credential") + .doesNotContain("AKIAEXAMPLE") + .doesNotContain("X-Amz-Security-Token") + .doesNotContain("SESSIONTOKENEXAMPLE") + .doesNotContain(url.getQuery()) + .contains("*** Sensitive Data Redacted ***"); + } + + private TransferListenerContext presignedContext(URL url) { + PresignedDownloadFileRequest request = + PresignedDownloadFileRequest.builder() + .destination(Paths.get("destination-file.txt")) + .presignedUrlDownloadRequest(b -> b.presignedUrl(url)) + .build(); + + return TransferListenerContext.builder() + .request(request) + .progressSnapshot(DefaultTransferProgressSnapshot.builder() + .transferredBytes(0L) + .build()) + .build(); + } + + private URISyntaxException uriSyntaxExceptionFor(URL url) { + try { + url.toURI(); + } catch (URISyntaxException e) { + return e; + } + throw new AssertionError("Expected " + url + " to be unconvertible to a URI"); + } + + private URL signedUrl() { + try { + return new URL("https://bucket.s3.us-east-1.amazonaws.com/dir/key.txt?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-Credential=AKIAEXAMPLE%2F20240101%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Security-Token=SESSIONTOKENEXAMPLE&" + + "X-Amz-Signature=deadbeefdeadbeef"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequestTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequestTest.java new file mode 100644 index 000000000000..a06b584358a5 --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadFileRequestTest.java @@ -0,0 +1,154 @@ +/* + * 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.transfer.s3.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.File; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +class PresignedDownloadFileRequestTest { + + @Test + void build_withoutPresignedUrlDownloadRequest_throwsNullPointerException() { + assertThatThrownBy(() -> PresignedDownloadFileRequest.builder() + .destination(Paths.get(".")) + .build()) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("presignedUrlDownloadRequest"); + } + + @Test + void build_withoutDestination_throwsNullPointerException() { + assertThatThrownBy(() -> PresignedDownloadFileRequest.builder() + .presignedUrlDownloadRequest(createPresignedRequest()) + .build()) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("destination"); + } + + @Test + void build_withPath_setsDestinationCorrectly() { + Path path = Paths.get("."); + PresignedUrlDownloadRequest presignedRequest = createPresignedRequest(); + + PresignedDownloadFileRequest request = PresignedDownloadFileRequest.builder() + .destination(path) + .presignedUrlDownloadRequest(presignedRequest) + .build(); + + assertThat(request.destination()).isEqualTo(path); + assertThat(request.presignedUrlDownloadRequest()).isEqualTo(presignedRequest); + } + + @Test + void build_withFile_convertsToPathCorrectly() { + Path path = Paths.get("."); + PresignedUrlDownloadRequest presignedRequest = createPresignedRequest(); + + PresignedDownloadFileRequest request = PresignedDownloadFileRequest.builder() + .destination(path.toFile()) + .presignedUrlDownloadRequest(presignedRequest) + .build(); + + assertThat(request.destination()).isEqualTo(path); + } + + @Test + void destination_withNullFile_throwsNullPointerException() { + File file = null; + + assertThatThrownBy(() -> PresignedDownloadFileRequest.builder() + .destination(file)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("destination"); + } + + @Test + void presignedUrlDownloadRequest_withConsumerBuilder_buildsCorrectly() { + Path path = Paths.get("."); + + PresignedDownloadFileRequest request = PresignedDownloadFileRequest.builder() + .destination(path) + .presignedUrlDownloadRequest(b -> b.presignedUrl(createTestUrl())) + .build(); + + assertThat(request.presignedUrlDownloadRequest()).isNotNull(); + assertThat(request.presignedUrlDownloadRequest().presignedUrl()).isEqualTo(createTestUrl()); + } + + @Test + void equalsHashCodeTest() { + EqualsVerifier.forClass(PresignedDownloadFileRequest.class) + .withNonnullFields("destination", "presignedUrlDownloadRequest") + .verify(); + } + + @Test + void toString_redactsPresignedUrlQueryString() { + URL url = createSignedTestUrl(); + Path path = Paths.get("destination-file.txt"); + + PresignedDownloadFileRequest request = + PresignedDownloadFileRequest.builder() + .destination(path) + .presignedUrlDownloadRequest(b -> b.presignedUrl(url)) + .build(); + + assertThat(request.toString()) + .doesNotContain("X-Amz-Signature") + .doesNotContain("deadbeef") + .doesNotContain("X-Amz-Credential") + .doesNotContain("AKIAEXAMPLE") + .doesNotContain("X-Amz-Security-Token") + .doesNotContain("SESSIONTOKENEXAMPLE") + .doesNotContain(url.getQuery()) + .contains("destination-file.txt") + .contains("*** Sensitive Data Redacted ***"); + } + + private PresignedUrlDownloadRequest createPresignedRequest() { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(createTestUrl()) + .build(); + } + + private URL createTestUrl() { + try { + return new URL("https://example.com/test"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private URL createSignedTestUrl() { + try { + return new URL("https://bucket.s3.us-east-1.amazonaws.com/dir/key.txt?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-Credential=AKIAEXAMPLE%2F20240101%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Security-Token=SESSIONTOKENEXAMPLE&" + + "X-Amz-Signature=deadbeefdeadbeef"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequestTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequestTest.java new file mode 100644 index 000000000000..8fa413874d7f --- /dev/null +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/model/PresignedDownloadRequestTest.java @@ -0,0 +1,169 @@ +/* + * 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.transfer.s3.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.net.URL; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +class PresignedDownloadRequestTest { + + @Test + void build_withoutPresignedUrlDownloadRequest_throwsNullPointerException() { + assertThatThrownBy(() -> PresignedDownloadRequest.builder() + .responseTransformer(AsyncResponseTransformer.toBytes()) + .build()) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("presignedUrlDownloadRequest"); + } + + @Test + void builder_withoutResponseTransformer_returnsUntypedBuilder() { + PresignedDownloadRequest.UntypedBuilder untypedBuilder = PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(createPresignedRequest()); + + assertThat(untypedBuilder).isNotNull(); + } + + @Test + void build_withResponseTransformer_createsRequestCorrectly() { + AsyncResponseTransformer> responseTransformer = + AsyncResponseTransformer.toBytes(); + PresignedUrlDownloadRequest presignedRequest = createPresignedRequest(); + + PresignedDownloadRequest> request = + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(presignedRequest) + .responseTransformer(responseTransformer) + .build(); + + assertThat(request.responseTransformer()).isEqualTo(responseTransformer); + assertThat(request.presignedUrlDownloadRequest()).isEqualTo(presignedRequest); + } + + @Test + void presignedUrlDownloadRequest_withConsumerBuilder_buildsCorrectly() { + AsyncResponseTransformer> responseTransformer = + AsyncResponseTransformer.toBytes(); + + PresignedDownloadRequest> request = + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(b -> b.presignedUrl(createTestUrl())) + .responseTransformer(responseTransformer) + .build(); + + assertThat(request.presignedUrlDownloadRequest()).isNotNull(); + assertThat(request.presignedUrlDownloadRequest().presignedUrl()).isEqualTo(createTestUrl()); + } + + @Test + void responseTransformer_withNull_throwsNullPointerException() { + assertThatThrownBy(() -> PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(createPresignedRequest()) + .responseTransformer(null) + .build()) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("responseTransformer"); + } + + @Test + void builder_untypedToTypedTransition_worksCorrectly() { + PresignedDownloadRequest.UntypedBuilder untypedBuilder = PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(createPresignedRequest()); + + PresignedDownloadRequest> request = + untypedBuilder.responseTransformer(AsyncResponseTransformer.toBytes()) + .build(); + + assertThat(request.responseTransformer()).isNotNull(); + assertThat(request.presignedUrlDownloadRequest()).isNotNull(); + } + + @Test + void toBuilder_copiesAllFields() { + PresignedDownloadRequest> original = + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(createPresignedRequest()) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .build(); + + PresignedDownloadRequest> copy = original.toBuilder().build(); + + assertThat(copy.responseTransformer()).isEqualTo(original.responseTransformer()); + assertThat(copy.presignedUrlDownloadRequest()).isEqualTo(original.presignedUrlDownloadRequest()); + } + + @Test + void equalsHashCodeTest() { + EqualsVerifier.forClass(PresignedDownloadRequest.class) + .withNonnullFields("responseTransformer", "presignedUrlDownloadRequest") + .verify(); + } + + @Test + void toString_redactsPresignedUrlQueryString() { + URL url = createSignedTestUrl(); + + PresignedDownloadRequest> request = + PresignedDownloadRequest.builder() + .presignedUrlDownloadRequest(b -> b.presignedUrl(url)) + .responseTransformer(AsyncResponseTransformer.toBytes()) + .build(); + + assertThat(request.toString()) + .doesNotContain("X-Amz-Signature") + .doesNotContain("deadbeef") + .doesNotContain("X-Amz-Credential") + .doesNotContain("AKIAEXAMPLE") + .doesNotContain("X-Amz-Security-Token") + .doesNotContain("SESSIONTOKENEXAMPLE") + .doesNotContain(url.getQuery()) + .contains("*** Sensitive Data Redacted ***"); + } + + private PresignedUrlDownloadRequest createPresignedRequest() { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(createTestUrl()) + .build(); + } + + private URL createTestUrl() { + try { + return new URL("https://example.com/test"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private URL createSignedTestUrl() { + try { + return new URL("https://bucket.s3.us-east-1.amazonaws.com/dir/key.txt?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-Credential=AKIAEXAMPLE%2F20240101%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Security-Token=SESSIONTOKENEXAMPLE&" + + "X-Amz-Signature=deadbeefdeadbeef"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/services-custom/sns-message-manager/pom.xml b/services-custom/sns-message-manager/pom.xml index afabd2168f0a..8f47a3b0b726 100644 --- a/services-custom/sns-message-manager/pom.xml +++ b/services-custom/sns-message-manager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml sns-message-manager diff --git a/services/accessanalyzer/pom.xml b/services/accessanalyzer/pom.xml index 104222fb589d..243466ba8c23 100644 --- a/services/accessanalyzer/pom.xml +++ b/services/accessanalyzer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT accessanalyzer AWS Java SDK :: Services :: AccessAnalyzer diff --git a/services/accessanalyzer/src/main/resources/codegen-resources/customization.config b/services/accessanalyzer/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/accessanalyzer/src/main/resources/codegen-resources/customization.config +++ b/services/accessanalyzer/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..257d56457c4c --- /dev/null +++ b/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://access-analyzer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://access-analyzer.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://access-analyzer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://access-analyzer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://access-analyzer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ffa10668ffed..000000000000 --- a/services/accessanalyzer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://access-analyzer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://access-analyzer.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://access-analyzer-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://access-analyzer.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://access-analyzer.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/account/pom.xml b/services/account/pom.xml index d957e497cd6f..481be8a91514 100644 --- a/services/account/pom.xml +++ b/services/account/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT account AWS Java SDK :: Services :: Account diff --git a/services/account/src/main/resources/codegen-resources/customization.config b/services/account/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/account/src/main/resources/codegen-resources/customization.config +++ b/services/account/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/account/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/account/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..80e78551ec2b --- /dev/null +++ b/services/account/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,216 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/account/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/account/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d2d919ff30ee..000000000000 --- a/services/account/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://account-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://account-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://account.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://account.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/account/src/main/resources/codegen-resources/service-2.json b/services/account/src/main/resources/codegen-resources/service-2.json index f571c0194ab5..3d7391a09274 100644 --- a/services/account/src/main/resources/codegen-resources/service-2.json +++ b/services/account/src/main/resources/codegen-resources/service-2.json @@ -179,6 +179,25 @@ "documentation":"

    Retrieves the primary email address for the specified account.

    ", "readonly":true }, + "GetPrimaryEmailUpdateStatus":{ + "name":"GetPrimaryEmailUpdateStatus", + "http":{ + "method":"POST", + "requestUri":"/getPrimaryEmailUpdateStatus", + "responseCode":200 + }, + "input":{"shape":"GetPrimaryEmailUpdateStatusRequest"}, + "output":{"shape":"GetPrimaryEmailUpdateStatusResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the status of the most recent primary email update for the specified account. For complete details about how to update the primary email address, see Update the primary email address for your AWS account.

    ", + "readonly":true + }, "GetRegionOptStatus":{ "name":"GetRegionOptStatus", "http":{ @@ -693,6 +712,29 @@ } } }, + "GetPrimaryEmailUpdateStatusRequest":{ + "type":"structure", + "members":{ + "AccountId":{ + "shape":"AccountId", + "documentation":"

    Specifies the 12-digit account ID number of the Amazon Web Services account that you want to access or modify with this operation. To use this parameter, the caller must be an identity in the organization's management account or a delegated administrator account. The specified account ID must be a member account in the same organization. The organization must have all features enabled, and the organization must have trusted access enabled for the Account Management service, and optionally a delegated admin account assigned.

    This operation can only be called from the management account or the delegated administrator account of an organization for a member account.

    The management account can't specify its own AccountId.

    " + } + } + }, + "GetPrimaryEmailUpdateStatusResponse":{ + "type":"structure", + "required":["Status"], + "members":{ + "Status":{ + "shape":"PrimaryEmailUpdateStatus", + "documentation":"

    The status of the most recent primary email update request.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the most recent primary email update status was last changed.

    " + } + } + }, "GetRegionOptStatusRequest":{ "type":"structure", "required":["RegionName"], @@ -817,7 +859,9 @@ "type":"string", "enum":[ "PENDING", - "ACCEPTED" + "ACCEPTED", + "COMPLETED", + "FAILED" ] }, "PutAccountNameRequest":{ @@ -996,6 +1040,7 @@ "sensitive":true }, "String":{"type":"string"}, + "Timestamp":{"type":"timestamp"}, "Title":{ "type":"string", "max":50, diff --git a/services/accountaccess/pom.xml b/services/accountaccess/pom.xml new file mode 100644 index 000000000000..d7fe5af85003 --- /dev/null +++ b/services/accountaccess/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + accountaccess + AWS Java SDK :: Services :: Account Access + The AWS Java SDK for Account Access module holds the client classes that are used for + communicating with Account Access. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.accountaccess + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/accountaccess/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/accountaccess/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cf491e5401b1 --- /dev/null +++ b/services/accountaccess/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account-access-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://account-access.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/accountaccess/src/main/resources/codegen-resources/endpoint-tests.json b/services/accountaccess/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..be124c272ac5 --- /dev/null +++ b/services/accountaccess/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,105 @@ +{ + "testCases": [ + { + "documentation": "For custom endpoint with region not set and fips disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": false + } + }, + { + "documentation": "For custom endpoint with fips enabled", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access-fips.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": true + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": false + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access-fips.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://account-access.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false + } + }, + { + "documentation": "Missing region", + "expect": { + "error": "Invalid Configuration: Missing Region" + } + } + ], + "version": "1.0" +} \ No newline at end of file diff --git a/services/accountaccess/src/main/resources/codegen-resources/paginators-1.json b/services/accountaccess/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..f2c21e0c6fb2 --- /dev/null +++ b/services/accountaccess/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,16 @@ +{ + "pagination": { + "ListApplications": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "applications" + }, + "ListEntitlements": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "entitlements" + } + } +} diff --git a/services/accountaccess/src/main/resources/codegen-resources/service-2.json b/services/accountaccess/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..6b6742620b1c --- /dev/null +++ b/services/accountaccess/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,1039 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2018-05-10", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"account-access", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"Account Access", + "serviceId":"Account Access", + "signatureVersion":"v4", + "signingName":"account-access", + "uid":"account-access-2018-05-10" + }, + "operations":{ + "CreateApplication":{ + "name":"CreateApplication", + "http":{ + "method":"POST", + "requestUri":"/applications", + "responseCode":200 + }, + "input":{"shape":"CreateApplicationRequest"}, + "output":{"shape":"CreateApplicationResponse"}, + "errors":[ + {"shape":"AlreadyCreatedException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates an account access manager instance and its Amazon Web Services account access application in the associated IAM Identity Center instance. This operation is idempotent; calling it multiple times with the same parameters returns the existing application.

    ", + "idempotent":true + }, + "CreateEntitlement":{ + "name":"CreateEntitlement", + "http":{ + "method":"POST", + "requestUri":"/entitlements", + "responseCode":200 + }, + "input":{"shape":"CreateEntitlementRequest"}, + "output":{"shape":"CreateEntitlementResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates an entitlement (assignment) in account access manager. An entitlement (assignment) grants a principal (IAM Identity Center user or group) permission to assume a specified IAM role in an Amazon Web Services account. This operation is idempotent.

    ", + "idempotent":true + }, + "DeleteApplication":{ + "name":"DeleteApplication", + "http":{ + "method":"DELETE", + "requestUri":"/applications/{applicationArn}", + "responseCode":204 + }, + "input":{"shape":"DeleteApplicationRequest"}, + "output":{"shape":"DeleteApplicationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes an account access manager application. This operation is idempotent; deleting an application that has already been deleted does not return an error.

    ", + "idempotent":true + }, + "DeleteEntitlement":{ + "name":"DeleteEntitlement", + "http":{ + "method":"DELETE", + "requestUri":"/entitlements/{entitlementId}", + "responseCode":204 + }, + "input":{"shape":"DeleteEntitlementRequest"}, + "output":{"shape":"DeleteEntitlementResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes an entitlement from an account access manager application. This operation is idempotent; deleting an entitlement that has already been deleted does not return an error.

    ", + "idempotent":true + }, + "GetApplication":{ + "name":"GetApplication", + "http":{ + "method":"GET", + "requestUri":"/applications/{applicationArn}", + "responseCode":200 + }, + "input":{"shape":"GetApplicationRequest"}, + "output":{"shape":"GetApplicationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves details about an account access manager application, including its status, identity source, and tags.

    ", + "readonly":true + }, + "GetEntitlement":{ + "name":"GetEntitlement", + "http":{ + "method":"GET", + "requestUri":"/entitlements/{entitlementId}", + "responseCode":200 + }, + "input":{"shape":"GetEntitlementRequest"}, + "output":{"shape":"GetEntitlementResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves details about a specific entitlement for an account access manager application, including the principal, IAM role, and target account.

    ", + "readonly":true + }, + "ListApplications":{ + "name":"ListApplications", + "http":{ + "method":"POST", + "requestUri":"/applications-list", + "responseCode":200 + }, + "input":{"shape":"ListApplicationsRequest"}, + "output":{"shape":"ListApplicationsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the account access manager applications in your account. Use pagination to ensure that the operation returns quickly and successfully.

    ", + "readonly":true + }, + "ListEntitlements":{ + "name":"ListEntitlements", + "http":{ + "method":"POST", + "requestUri":"/entitlements-list", + "responseCode":200 + }, + "input":{"shape":"ListEntitlementsRequest"}, + "output":{"shape":"ListEntitlementsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the entitlements for a specified account access manager application. You can filter results by principal, IAM role, or account. Use pagination to ensure that the operation returns quickly and successfully.

    ", + "readonly":true + }, + "ListTagsForResource":{ + "name":"ListTagsForResource", + "http":{ + "method":"GET", + "requestUri":"/tags/{resourceArn}", + "responseCode":200 + }, + "input":{"shape":"ListTagsForResourceRequest"}, + "output":{"shape":"ListTagsForResourceResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the tags associated with an account access manager resource.

    ", + "readonly":true + }, + "TagResource":{ + "name":"TagResource", + "http":{ + "method":"POST", + "requestUri":"/tags/{resourceArn}", + "responseCode":200 + }, + "input":{"shape":"TagResourceRequest"}, + "output":{"shape":"TagResourceResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Adds tags to an account access manager resource.

    " + }, + "UntagResource":{ + "name":"UntagResource", + "http":{ + "method":"DELETE", + "requestUri":"/tags/{resourceArn}", + "responseCode":200 + }, + "input":{"shape":"UntagResourceRequest"}, + "output":{"shape":"UntagResourceResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Removes tags from an account access manager resource.

    ", + "idempotent":true + } + }, + "shapes":{ + "AccessDeniedException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    You do not have sufficient access to perform this operation.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "Account":{ + "type":"string", + "max":12, + "min":12, + "pattern":"[0-9]{12}" + }, + "AlreadyCreatedException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The resource you are trying to create already exists. To retrieve the existing resource, use the corresponding Get operation.

    ", + "exception":true + }, + "ApplicationArn":{ + "type":"string", + "max":2048, + "min":49, + "pattern":"arn:[a-z0-9-]+:account-access:[a-z0-9]+(-[a-z0-9]+)*:[0-9]{12}:application/[a-zA-Z0-9-]+" + }, + "ApplicationList":{ + "type":"list", + "member":{"shape":"ApplicationSummary"} + }, + "ApplicationSummary":{ + "type":"structure", + "required":[ + "applicationArn", + "createdAt", + "updatedAt" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    The ARN of the application.

    " + }, + "tenantId":{ + "shape":"String", + "documentation":"

    The tenant identifier associated with the application.

    " + }, + "createdAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the application was created.

    " + }, + "updatedAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the application was last updated.

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

    Contains summary information about an account access manager application.

    " + }, + "ConflictException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request conflicts with the current state of the resource.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "CreateApplicationRequest":{ + "type":"structure", + "required":["identitySource"], + "members":{ + "identitySource":{ + "shape":"IdentitySource", + "documentation":"

    Specifies the identity source for the application. The identity source defines the IAM Identity Center instance that provides principals for entitlements.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    Specifies the tags to assign to the application.

    " + } + } + }, + "CreateApplicationResponse":{ + "type":"structure", + "required":["applicationArn"], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

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

    " + } + } + }, + "CreateEntitlementRequest":{ + "type":"structure", + "required":[ + "applicationArn", + "entitlement" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application to create the entitlement for.

    " + }, + "entitlement":{ + "shape":"Entitlement", + "documentation":"

    Specifies the entitlement configuration, including the principal and the IAM role to grant access to.

    " + } + } + }, + "CreateEntitlementResponse":{ + "type":"structure", + "required":["entitlementId"], + "members":{ + "entitlementId":{ + "shape":"String", + "documentation":"

    The unique identifier of the created entitlement.

    " + } + } + }, + "DateTime":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, + "DeleteApplicationRequest":{ + "type":"structure", + "required":["applicationArn"], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application to delete.

    ", + "location":"uri", + "locationName":"applicationArn" + } + } + }, + "DeleteApplicationResponse":{ + "type":"structure", + "members":{} + }, + "DeleteEntitlementRequest":{ + "type":"structure", + "required":[ + "applicationArn", + "entitlementId" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application that the entitlement belongs to.

    ", + "location":"querystring", + "locationName":"applicationArn" + }, + "entitlementId":{ + "shape":"String", + "documentation":"

    Specifies the unique identifier of the entitlement to delete.

    ", + "location":"uri", + "locationName":"entitlementId" + } + } + }, + "DeleteEntitlementResponse":{ + "type":"structure", + "members":{} + }, + "Entitlement":{ + "type":"structure", + "members":{ + "principalRole":{ + "shape":"PrincipalRoleEntitlement", + "documentation":"

    The principal-to-role mapping for the entitlement.

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

    Specifies the entitlement configuration for an account access manager application, defining which principal can assume which IAM role.

    ", + "union":true + }, + "EntitlementDetails":{ + "type":"structure", + "members":{ + "principalRole":{ + "shape":"PrincipalRoleEntitlementDetails", + "documentation":"

    The principal-to-role mapping details for the entitlement, including the target account.

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

    Contains detailed information about an entitlement, including the principal, IAM role, and target account.

    ", + "union":true + }, + "EntitlementFilter":{ + "type":"structure", + "members":{ + "principalRole":{ + "shape":"PrincipalRoleEntitlementFilter", + "documentation":"

    The principal-to-role filter criteria for narrowing entitlement results.

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

    Specifies filter criteria for listing entitlements.

    " + }, + "EntitlementSummary":{ + "type":"structure", + "members":{ + "principalRole":{ + "shape":"PrincipalRoleEntitlementSummary", + "documentation":"

    The principal-to-role mapping summary for the entitlement.

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

    Contains summary information about an entitlement.

    ", + "union":true + }, + "EntitlementsList":{ + "type":"list", + "member":{"shape":"EntitlementsListMember"} + }, + "EntitlementsListMember":{ + "type":"structure", + "required":[ + "entitlementId", + "entitlement", + "createdAt" + ], + "members":{ + "entitlementId":{ + "shape":"String", + "documentation":"

    The unique identifier of the entitlement.

    " + }, + "entitlement":{ + "shape":"EntitlementSummary", + "documentation":"

    The summary information for the entitlement.

    " + }, + "createdAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the entitlement was created.

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

    Contains information about an entitlement in a list result.

    " + }, + "ErrorCode":{ + "type":"string", + "enum":[ + "AUTHORIZATION_ERROR", + "RESOURCE_NOT_FOUND_ERROR", + "SERVICE_QUOTA_EXCEEDED_ERROR", + "INTERNAL_SERVICE_ERROR" + ] + }, + "ErrorDetails":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"ErrorCode", + "documentation":"

    The error code that identifies the type of error.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A human-readable message that describes the error.

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

    Contains information about an error that occurred during application processing.

    " + }, + "GetApplicationRequest":{ + "type":"structure", + "required":["applicationArn"], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application to retrieve.

    ", + "location":"uri", + "locationName":"applicationArn" + } + } + }, + "GetApplicationResponse":{ + "type":"structure", + "required":[ + "identitySource", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "identitySource":{ + "shape":"IdentitySourceDetails", + "documentation":"

    The identity source details for the application, including the IAM Identity Center instance configuration.

    " + }, + "status":{ + "shape":"Status", + "documentation":"

    The current status of the application.

    " + }, + "tenantId":{ + "shape":"String", + "documentation":"

    The tenant identifier associated with the application.

    " + }, + "createdAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the application was created.

    " + }, + "updatedAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the application was last updated.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags associated with the application.

    " + }, + "error":{ + "shape":"ErrorDetails", + "documentation":"

    The error details if the application is in a failed state.

    " + } + } + }, + "GetEntitlementRequest":{ + "type":"structure", + "required":[ + "applicationArn", + "entitlementId" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application that the entitlement belongs to.

    ", + "location":"querystring", + "locationName":"applicationArn" + }, + "entitlementId":{ + "shape":"String", + "documentation":"

    Specifies the unique identifier of the entitlement to retrieve.

    ", + "location":"uri", + "locationName":"entitlementId" + } + } + }, + "GetEntitlementResponse":{ + "type":"structure", + "required":[ + "applicationArn", + "entitlementId", + "entitlement", + "createdAt" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    The ARN of the application that the entitlement belongs to.

    " + }, + "entitlementId":{ + "shape":"String", + "documentation":"

    The unique identifier of the entitlement.

    " + }, + "entitlement":{ + "shape":"EntitlementDetails", + "documentation":"

    The entitlement details, including the principal, IAM role, and target account.

    " + }, + "createdAt":{ + "shape":"DateTime", + "documentation":"

    The date and time when the entitlement was created.

    " + } + } + }, + "GroupId":{ + "type":"string", + "max":47, + "min":1, + "pattern":"([0-9a-f]{10}-|)[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + }, + "IdentityCenter":{ + "type":"structure", + "required":["instanceArn"], + "members":{ + "instanceArn":{ + "shape":"IdentityCenterInstanceArn", + "documentation":"

    The ARN of the IAM Identity Center instance.

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

    Specifies the IAM Identity Center instance to use as the identity source for an application.

    " + }, + "IdentityCenterApplicationArn":{ + "type":"string", + "max":1224, + "min":10, + "pattern":"arn:[a-z0-9-]+:sso::[0-9]{12}:application/(sso)?ins-[a-zA-Z0-9-.]{16}/apl-[a-zA-Z0-9]{16}" + }, + "IdentityCenterDetails":{ + "type":"structure", + "required":["instanceArn"], + "members":{ + "instanceArn":{ + "shape":"IdentityCenterInstanceArn", + "documentation":"

    The ARN of the IAM Identity Center instance.

    " + }, + "applicationArn":{ + "shape":"IdentityCenterApplicationArn", + "documentation":"

    The ARN of the IAM Identity Center application created for this account access manager application.

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

    Contains detailed information about the IAM Identity Center configuration for an application.

    " + }, + "IdentityCenterInstanceArn":{ + "type":"string", + "max":1224, + "min":10, + "pattern":"arn:[a-z0-9-]+:sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}" + }, + "IdentityCenterPrincipal":{ + "type":"structure", + "members":{ + "userId":{ + "shape":"UserId", + "documentation":"

    The unique identifier of a user in IAM Identity Center.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    The unique identifier of a group in IAM Identity Center.

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

    Identifies a user or group from IAM Identity Center.

    ", + "union":true + }, + "IdentityCenterPrincipalFilter":{ + "type":"structure", + "members":{ + "userId":{ + "shape":"UserId", + "documentation":"

    The unique identifier of a user in IAM Identity Center to filter by.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    The unique identifier of a group in IAM Identity Center to filter by.

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

    Specifies filter criteria for an IAM Identity Center principal.

    ", + "union":true + }, + "IdentitySource":{ + "type":"structure", + "members":{ + "identityCenter":{ + "shape":"IdentityCenter", + "documentation":"

    The IAM Identity Center instance to use as the identity source.

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

    Specifies the identity source for an account access manager application.

    ", + "union":true + }, + "IdentitySourceDetails":{ + "type":"structure", + "members":{ + "identityCenter":{ + "shape":"IdentityCenterDetails", + "documentation":"

    The IAM Identity Center configuration details for the identity source.

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

    Contains detailed information about the identity source for an application.

    ", + "union":true + }, + "InternalServerException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    An internal service error occurred. Try your request again later.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, + "ListApplicationsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListApplicationsRequestMaxResultsInteger", + "documentation":"

    Specifies the maximum number of results to return in a single call.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    Specifies the pagination token from a previous call to retrieve the next set of results.

    " + } + } + }, + "ListApplicationsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListApplicationsResponse":{ + "type":"structure", + "required":["applications"], + "members":{ + "applications":{ + "shape":"ApplicationList", + "documentation":"

    The list of applications.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The pagination token to use in a subsequent request to retrieve the next set of results. This value is null when there are no more results to return.

    " + } + } + }, + "ListEntitlementsRequest":{ + "type":"structure", + "required":[ + "applicationArn", + "filter" + ], + "members":{ + "applicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the application to list entitlements for.

    " + }, + "filter":{ + "shape":"EntitlementFilter", + "documentation":"

    Specifies filter criteria to narrow the entitlements returned. You can filter by principal, IAM role, or account.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    Specifies the pagination token from a previous call to retrieve the next set of results.

    " + }, + "maxResults":{ + "shape":"ListEntitlementsRequestMaxResultsInteger", + "documentation":"

    Specifies the maximum number of results to return in a single call.

    " + } + } + }, + "ListEntitlementsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListEntitlementsResponse":{ + "type":"structure", + "required":["entitlements"], + "members":{ + "entitlements":{ + "shape":"EntitlementsList", + "documentation":"

    The list of entitlements for the specified application.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The pagination token to use in a subsequent request to retrieve the next set of results. This value is null when there are no more results to return.

    " + } + } + }, + "ListTagsForResourceRequest":{ + "type":"structure", + "required":["resourceArn"], + "members":{ + "resourceArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the resource to list tags for.

    ", + "location":"uri", + "locationName":"resourceArn" + } + } + }, + "ListTagsForResourceResponse":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags associated with the resource.

    " + } + } + }, + "Principal":{ + "type":"structure", + "members":{ + "identityCenter":{ + "shape":"IdentityCenterPrincipal", + "documentation":"

    The IAM Identity Center principal (user or group).

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

    Identifies a principal (user or group) that can be granted entitlements.

    ", + "union":true + }, + "PrincipalFilter":{ + "type":"structure", + "members":{ + "identityCenter":{ + "shape":"IdentityCenterPrincipalFilter", + "documentation":"

    The IAM Identity Center principal filter criteria.

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

    Specifies filter criteria for a principal.

    ", + "union":true + }, + "PrincipalRoleEntitlement":{ + "type":"structure", + "required":[ + "principal", + "roleArn" + ], + "members":{ + "principal":{ + "shape":"Principal", + "documentation":"

    The principal (user or group) that is granted access to assume the IAM role.

    " + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM role that the principal can assume.

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

    Specifies a principal-to-role entitlement that grants an IAM Identity Center principal permission to assume an IAM role.

    " + }, + "PrincipalRoleEntitlementDetails":{ + "type":"structure", + "required":[ + "principal", + "roleArn", + "account" + ], + "members":{ + "principal":{ + "shape":"Principal", + "documentation":"

    The principal (user or group) that is granted access to assume the IAM role.

    " + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM role that the principal can assume.

    " + }, + "account":{ + "shape":"Account", + "documentation":"

    The 12-digit Amazon Web Services account ID where the IAM role resides.

    " + }, + "accountName":{ + "shape":"String", + "documentation":"

    The friendly name of the Amazon Web Services account where the IAM role resides.

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

    Contains detailed information about a principal-to-role entitlement, including the target account.

    " + }, + "PrincipalRoleEntitlementFilter":{ + "type":"structure", + "members":{ + "principal":{ + "shape":"PrincipalFilter", + "documentation":"

    The principal to filter entitlements by.

    " + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    The IAM role ARN to filter entitlements by.

    " + }, + "account":{ + "shape":"Account", + "documentation":"

    The 12-digit Amazon Web Services account ID to filter entitlements by.

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

    Specifies filter criteria for principal-to-role entitlements. All specified criteria must match for an entitlement to be returned.

    " + }, + "PrincipalRoleEntitlementSummary":{ + "type":"structure", + "required":[ + "principal", + "roleArn", + "account" + ], + "members":{ + "principal":{ + "shape":"Principal", + "documentation":"

    The principal (user or group) that is granted access to assume the IAM role.

    " + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM role that the principal can assume.

    " + }, + "account":{ + "shape":"Account", + "documentation":"

    The 12-digit Amazon Web Services account ID where the IAM role resides.

    " + }, + "accountName":{ + "shape":"String", + "documentation":"

    The friendly name of the Amazon Web Services account where the IAM role resides.

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

    Contains summary information about a principal-to-role entitlement.

    " + }, + "ResourceNotFoundException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The specified resource does not exist. Verify that the resource identifier is correct and that the resource exists in the current Region.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "RoleArn":{ + "type":"string", + "pattern":"arn:[a-z0-9-]+:iam::[0-9]{12}:role/([a-zA-Z0-9+=,.@_-]+/)*[a-zA-Z0-9+=,.@_-]+" + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request exceeds a service quota for your account.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "Status":{ + "type":"string", + "enum":[ + "CREATE_IN_PROGRESS", + "ACTIVE", + "DELETE_IN_PROGRESS", + "CREATE_FAILED", + "DELETE_FAILED" + ] + }, + "String":{"type":"string"}, + "TagKeys":{ + "type":"list", + "member":{"shape":"String"} + }, + "TagResourceRequest":{ + "type":"structure", + "required":[ + "resourceArn", + "tags" + ], + "members":{ + "resourceArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the resource to add tags to.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    Specifies the tags to add to the resource.

    " + } + } + }, + "TagResourceResponse":{ + "type":"structure", + "members":{} + }, + "TagsMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "ThrottlingException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request was denied due to request throttling. Try your request again later.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true + }, + "UntagResourceRequest":{ + "type":"structure", + "required":[ + "resourceArn", + "tagKeys" + ], + "members":{ + "resourceArn":{ + "shape":"ApplicationArn", + "documentation":"

    Specifies the ARN of the resource to remove tags from.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tagKeys":{ + "shape":"TagKeys", + "documentation":"

    Specifies the tag keys to remove from the resource.

    ", + "location":"querystring", + "locationName":"tagKeys" + } + } + }, + "UntagResourceResponse":{ + "type":"structure", + "members":{} + }, + "UserId":{ + "type":"string", + "max":47, + "min":1, + "pattern":"([0-9a-f]{10}-|)[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + }, + "ValidationException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The input does not satisfy the constraints specified by the service. Check your request parameters and retry the request.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + } + }, + "documentation":"

    Account access manager enables you to manage applications and entitlements that grant IAM Identity Center principals access to IAM roles across accounts.

    " +} diff --git a/services/accountaccess/src/main/resources/codegen-resources/waiters-2.json b/services/accountaccess/src/main/resources/codegen-resources/waiters-2.json new file mode 100644 index 000000000000..28fe0b5082f3 --- /dev/null +++ b/services/accountaccess/src/main/resources/codegen-resources/waiters-2.json @@ -0,0 +1,26 @@ +{ + "version" : 2, + "waiters" : { + "ApplicationActive" : { + "delay" : 5, + "maxAttempts" : 24, + "operation" : "GetApplication", + "acceptors" : [ { + "matcher" : "path", + "argument" : "status", + "state" : "success", + "expected" : "ACTIVE" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "CREATE_FAILED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "DELETE_FAILED" + } ] + } + } +} \ No newline at end of file diff --git a/services/acm/pom.xml b/services/acm/pom.xml index af6cb66aa320..47b72bcc00db 100644 --- a/services/acm/pom.xml +++ b/services/acm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT acm AWS Java SDK :: Services :: AWS Certificate Manager diff --git a/services/acm/src/main/resources/codegen-resources/customization.config b/services/acm/src/main/resources/codegen-resources/customization.config index 0d45746d8f8a..a4de213ec307 100644 --- a/services/acm/src/main/resources/codegen-resources/customization.config +++ b/services/acm/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listCertificates" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/acm/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/acm/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..58db217ece48 --- /dev/null +++ b/services/acm/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,200 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region to send requests to.", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send requests.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "Use FIPS endpoints.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "Use dual-stack endpoints.", + "type": "boolean" + }, + "ServiceType": { + "required": true, + "documentation": "The service type: ACM or ACM-ACME. Injected via @staticContextParams.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "ServiceType" + }, + "ACM-ACME" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS endpoints are not available for ACME operations", + "type": "error" + }, + { + "documentation": "ACME standard", + "conditions": [], + "endpoint": { + "url": "https://acm-acme.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "ACME operations are only available in commercial AWS partitions", + "conditions": [], + "error": "ACME operations are only available in commercial AWS partitions", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "ACM FIPS standard", + "conditions": [], + "endpoint": { + "url": "https://acm-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "ACM standard", + "conditions": [], + "endpoint": { + "url": "https://acm.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "Fallback error if region is not set", + "conditions": [], + "error": "Region must be set to resolve an endpoint.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 10, + "nodes": "/////wAAAAH/////AAAAAAX14QEAAAADAAAAAQAAAAQF9eEKAAAAAgAAAAkAAAAFAAAABAAAAAcAAAAGAAAABQX14QgF9eEJAAAABQX14QUAAAAIAAAABgX14QYF9eEHAAAAAwAAAAoF9eEEAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/acm/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/acm/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3928d2c71723..000000000000 --- a/services/acm/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "type": "string", - "builtIn": "AWS::Region", - "required": true, - "documentation": "The AWS region to send requests to." - }, - "Endpoint": { - "type": "string", - "builtIn": "SDK::Endpoint", - "documentation": "Override the endpoint used to send requests." - }, - "UseFIPS": { - "type": "boolean", - "builtIn": "AWS::UseFIPS", - "documentation": "Use FIPS endpoints.", - "default": false, - "required": true - }, - "UseDualStack": { - "type": "boolean", - "builtIn": "AWS::UseDualStack", - "documentation": "Use dual-stack endpoints.", - "default": false, - "required": true - }, - "ServiceType": { - "type": "string", - "required": true, - "documentation": "The service type: ACM or ACM-ACME. Injected via @staticContextParams." - } - }, - "rules": [ - { - "documentation": "Use custom endpoint if provided", - "type": "endpoint", - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": "{Endpoint}" - } - }, - { - "documentation": "Resolve partition for region", - "type": "tree", - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "documentation": "ACME operations", - "type": "tree", - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ServiceType" - }, - "ACM-ACME" - ] - } - ], - "rules": [ - { - "documentation": "ACME with custom endpoint", - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": "{Endpoint}" - }, - "type": "endpoint" - }, - { - "documentation": "ACME operations are only available in commercial AWS partitions", - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "rules": [ - { - "documentation": "FIPS endpoints are not available for ACME operations", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "FIPS endpoints are not available for ACME operations", - "type": "error" - }, - { - "documentation": "ACME standard", - "conditions": [], - "endpoint": { - "url": "https://acm-acme.{Region}.{PartitionResult#dualStackDnsSuffix}" - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "documentation": "ACME operations are only available in commercial AWS partitions", - "conditions": [], - "error": "ACME operations are only available in commercial AWS partitions", - "type": "error" - } - ] - }, - { - "documentation": "ACM operations", - "type": "tree", - "conditions": [], - "rules": [ - { - "documentation": "ACM FIPS + DualStack", - "type": "endpoint", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://acm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}" - } - }, - { - "documentation": "ACM FIPS only", - "type": "tree", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "documentation": "ACM FIPS GovCloud", - "type": "endpoint", - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://acm.{Region}.amazonaws.com" - } - }, - { - "documentation": "ACM FIPS standard", - "type": "endpoint", - "conditions": [], - "endpoint": { - "url": "https://acm-fips.{Region}.{PartitionResult#dnsSuffix}" - } - } - ] - }, - { - "documentation": "ACM DualStack only", - "type": "endpoint", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://acm.{Region}.{PartitionResult#dualStackDnsSuffix}" - } - }, - { - "documentation": "ACM standard", - "type": "endpoint", - "conditions": [], - "endpoint": { - "url": "https://acm.{Region}.{PartitionResult#dnsSuffix}" - } - } - ] - } - ] - }, - { - "documentation": "Fallback error if region is not set", - "type": "error", - "conditions": [], - "error": "Region must be set to resolve an endpoint." - } - ] -} \ No newline at end of file diff --git a/services/acm/src/main/resources/codegen-resources/paginators-1.json b/services/acm/src/main/resources/codegen-resources/paginators-1.json index fc0cdca72589..628523864021 100644 --- a/services/acm/src/main/resources/codegen-resources/paginators-1.json +++ b/services/acm/src/main/resources/codegen-resources/paginators-1.json @@ -24,6 +24,12 @@ "limit_key": "MaxResults", "result_key": "ExternalAccountBindings" }, + "ListCertificateDomainValidations": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxItems", + "result_key": "DomainValidationSummaryList" + }, "ListCertificates": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/acm/src/main/resources/codegen-resources/service-2.json b/services/acm/src/main/resources/codegen-resources/service-2.json index 6c6f04c523e0..2659f95051e1 100644 --- a/services/acm/src/main/resources/codegen-resources/service-2.json +++ b/services/acm/src/main/resources/codegen-resources/service-2.json @@ -470,6 +470,26 @@ "ServiceType":{"value":"ACM-ACME"} } }, + "ListCertificateDomainValidations":{ + "name":"ListCertificateDomainValidations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListCertificateDomainValidationsRequest"}, + "output":{"shape":"ListCertificateDomainValidationsResponse"}, + "errors":[ + {"shape":"InvalidArgsException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns per-domain validation summaries for an ACM certificate. Each summary includes the domain name, the active validation configuration, and the requested validation configuration when a validation method migration is in progress. You can use the results to monitor the progress of an email-to-DNS validation migration and to retrieve the CNAME records required for DNS validation.

    ", + "readonly":true, + "staticContextParams":{ + "ServiceType":{"value":"ACM"} + } + }, "ListCertificates":{ "name":"ListCertificates", "http":{ @@ -787,12 +807,13 @@ "input":{"shape":"UpdateCertificateOptionsRequest"}, "errors":[ {"shape":"InvalidArnException"}, + {"shape":"ConflictException"}, {"shape":"LimitExceededException"}, {"shape":"ValidationException"}, {"shape":"InvalidStateException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Updates a certificate. You can use this function to specify whether to export your certificate. Certificate transparency logging opt-out is no longer available. For more information, see Certificate Transparency Logging and Certificate Manager Exportable Managed Certificates.

    ", + "documentation":"

    Updates certificate options. You can use this operation to change the domain validation method or specify whether to export your certificate. For more information, see Migrate from email to DNS validation and Certificate Manager Exportable Managed Certificates.

    ", "staticContextParams":{ "ServiceType":{"value":"ACM"} } @@ -1354,6 +1375,12 @@ "pattern":"arn:[\\w+=/,.@-]+:acm:[\\w+=/,.@-]*:[0-9]+:[\\w+=,.@-]+(/[\\w+=,.@-]+)*" }, "AvailabilityErrorMessage":{"type":"string"}, + "CertificateArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:[\\w+=/,.@-]+:acm:[\\w+=/,.@-]*:[0-9]+:certificate/[\\w+=,.@-]+.*" + }, "CertificateAuthority":{ "type":"structure", "members":{ @@ -1498,6 +1525,10 @@ "shape":"CertificateOptions", "documentation":"

    Contains the certificate options. Certificate transparency logging opt-out is no longer available. All public certificates are recorded in a certificate transparency log.

    " }, + "UpdateSummary":{ + "shape":"UpdateSummary", + "documentation":"

    Contains information about the most recent update to the certificate. This field exists only when the certificate type is AMAZON_ISSUED and a certificate update has been requested.

    " + }, "CertificateKeyPairOrigin":{ "shape":"CertificateKeyPairOrigin", "documentation":"

    The origin of the certificate's key pair.

    " @@ -1613,9 +1644,13 @@ "Export":{ "shape":"CertificateExport", "documentation":"

    You can opt in to allow the export of your certificates by specifying ENABLED. You cannot update the value of Export after the the certificate is created.

    " + }, + "ValidationMethod":{ + "shape":"ValidationMethod", + "documentation":"

    The domain validation method for the certificate. To migrate from email to DNS validation, specify DNS.

    " } }, - "documentation":"

    Structure that contains options for your certificate. You can use this structure to specify whether to export your certificate.

    Certificate transparency logging opt-out is no longer available. All public certificates are recorded in a certificate transparency log. For general information, see Certificate Transparency Logging.

    You can export public ACM certificates to use with Amazon Web Services services as well as outside Amazon Web Services Cloud. For more information, see Certificate Manager exportable public certificate.

    " + "documentation":"

    Structure that contains options for your certificate. You can use this structure to change the domain validation method or specify whether to export your certificate.

    All public certificates are recorded in a certificate transparency log. For general information, see Certificate Transparency Logging.

    You can export public ACM certificates to use with Amazon Web Services services as well as outside Amazon Web Services Cloud. For more information, see Certificate Manager exportable public certificate.

    " }, "CertificateSearchResult":{ "type":"structure", @@ -2213,6 +2248,16 @@ }, "documentation":"

    DNS prevalidation options for domain validation.

    " }, + "DnsValidationChallenge":{ + "type":"structure", + "members":{ + "ResourceRecord":{ + "shape":"ResourceRecord", + "documentation":"

    The CNAME record that ACM creates for DNS validation. Add this record to your DNS configuration to prove that you own or control the domain.

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

    Contains the CNAME record that you must add to your DNS configuration to validate domain ownership using DNS validation.

    " + }, "DomainComponentList":{ "type":"list", "member":{"shape":"String"}, @@ -2310,6 +2355,20 @@ "max":1000, "min":1 }, + "DomainValidationMethodUpdateSummary":{ + "type":"structure", + "members":{ + "From":{ + "shape":"ValidationMethod", + "documentation":"

    The validation method that the certificate was using before the update.

    " + }, + "To":{ + "shape":"ValidationMethod", + "documentation":"

    The target validation method for the update.

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

    Contains information about a domain validation method migration, including the previous validation method and the target validation method.

    " + }, "DomainValidationOption":{ "type":"structure", "required":[ @@ -2334,6 +2393,43 @@ "max":100, "min":1 }, + "DomainValidationSummary":{ + "type":"structure", + "required":["DomainName"], + "members":{ + "DomainName":{ + "shape":"DomainNameString", + "documentation":"

    The fully qualified domain name (FQDN) in the certificate for which this validation summary applies.

    " + }, + "ActiveValidationConfiguration":{ + "shape":"ValidationConfiguration", + "documentation":"

    The validation configuration currently in effect for this domain. This reflects the validation method that ACM is currently using to validate domain ownership (for example, email or DNS).

    " + }, + "RequestedValidationConfiguration":{ + "shape":"ValidationConfiguration", + "documentation":"

    The validation configuration for a pending validation method migration. This field is present only when a migration is in progress (for example, from email to DNS validation). It contains the target validation method, the current validation status, and the validation challenge details (such as the CNAME record to add to your DNS configuration).

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

    Contains per-domain validation information for a certificate. This structure is returned as a member of the ListCertificateDomainValidations response.

    " + }, + "DomainValidationSummaryList":{ + "type":"list", + "member":{"shape":"DomainValidationSummary"} + }, + "EmailValidationChallenge":{ + "type":"structure", + "members":{ + "ValidationEmails":{ + "shape":"ValidationEmailList", + "documentation":"

    A list of email addresses that ACM uses to send domain validation emails.

    " + }, + "ValidationDomain":{ + "shape":"DomainNameString", + "documentation":"

    The domain name that ACM uses to send validation emails.

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

    Contains the email addresses used for email-based domain validation.

    " + }, "Expiration":{ "type":"structure", "required":[ @@ -2937,6 +3033,37 @@ } } }, + "ListCertificateDomainValidationsRequest":{ + "type":"structure", + "required":["CertificateArn"], + "members":{ + "CertificateArn":{ + "shape":"CertificateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the certificate for which to list domain validation summaries.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    A token returned by a previous call to ListCertificateDomainValidations. If the number of results exceeds MaxItems, use this token to retrieve the next page of results.

    " + }, + "MaxItems":{ + "shape":"MaxItems", + "documentation":"

    The maximum number of domain validation summaries to return. If you don't specify a value, the default is 1000.

    " + } + } + }, + "ListCertificateDomainValidationsResponse":{ + "type":"structure", + "members":{ + "DomainValidationSummaryList":{ + "shape":"DomainValidationSummaryList", + "documentation":"

    A list of DomainValidationSummary objects, one for each domain on the certificate. Each object contains the domain name and its active and requested validation configurations.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If the number of results exceeds MaxItems, this token is included in the response. Use this token in a subsequent ListCertificateDomainValidations request to retrieve the next page of results.

    " + } + } + }, "ListCertificatesRequest":{ "type":"structure", "members":{ @@ -3740,10 +3867,77 @@ }, "Options":{ "shape":"CertificateOptions", - "documentation":"

    Use to update the options for your certificate. Currently, you can specify whether to export your certificate. Certificate transparency logging opt-out is no longer available. All public certificates are recorded in a certificate transparency log. For more information, see Certificate Transparency Logging.

    " + "documentation":"

    Use to update the options for your certificate. Currently, you can change the domain validation method or specify whether to export your certificate. For more information about migrating from email to DNS validation, see Migrate from email to DNS validation.

    " } } }, + "UpdateStatus":{ + "type":"string", + "documentation":"

    The status of a certificate update. Possible values:

    • PENDING_DOMAIN_VALIDATION – The update is waiting for domain validation to complete.

    • SUCCESS – The update completed successfully.

    • FAILED – The update failed.

    ", + "enum":[ + "PENDING_DOMAIN_VALIDATION", + "SUCCESS", + "FAILED" + ] + }, + "UpdateSummary":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"UpdateStatus", + "documentation":"

    The status of the certificate update. The following are valid values:

    • PENDING_DOMAIN_VALIDATION – The certificate update is waiting for domain ownership validation to complete.

    • SUCCESS – The certificate was updated successfully.

    • FAILED – The certificate update failed.

    " + }, + "Type":{ + "shape":"UpdateType", + "documentation":"

    The type of update that was requested for the certificate. The following are valid values:

    • DOMAIN_VALIDATION_METHOD – The update changes the domain validation method for the certificate.

    " + }, + "DomainValidationMethodUpdateSummary":{ + "shape":"DomainValidationMethodUpdateSummary", + "documentation":"

    Contains information about a domain validation method migration, including the previous and target validation methods.

    " + }, + "RequestedAt":{ + "shape":"TStamp", + "documentation":"

    The time at which the certificate update was requested.

    " + }, + "UpdatedAt":{ + "shape":"TStamp", + "documentation":"

    The time at which the certificate update status was last changed.

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

    Contains information about the most recent certificate update, such as a domain validation method migration. This structure is returned as part of the CertificateDetail response from DescribeCertificate.

    " + }, + "UpdateType":{ + "type":"string", + "documentation":"

    The type of certificate update. Valid values:

    • DOMAIN_VALIDATION_METHOD – A change to the domain validation method for the certificate.

    ", + "enum":["DOMAIN_VALIDATION_METHOD"] + }, + "ValidationChallenge":{ + "type":"structure", + "members":{ + "EmailValidationChallenge":{"shape":"EmailValidationChallenge"}, + "DnsValidationChallenge":{"shape":"DnsValidationChallenge"} + }, + "documentation":"

    Contains the challenge details that you use to prove domain ownership. Only one member is set, depending on the validation method.

    ", + "union":true + }, + "ValidationConfiguration":{ + "type":"structure", + "members":{ + "ValidationMethod":{ + "shape":"ValidationMethod", + "documentation":"

    The validation method for this configuration. Valid values:

    • DNS – Validation using a CNAME record added to your DNS configuration.

    • EMAIL – Validation using an approval email sent to domain contacts.

    • HTTP – Validation using an HTTP resource placed on your web server.

    " + }, + "ValidationChallenge":{ + "shape":"ValidationChallenge", + "documentation":"

    The validation challenge details for this configuration. The structure varies by validation method: for DNS validation, contains a DnsValidationChallenge with the CNAME record to add; for email validation, contains an EmailValidationChallenge with the validation email addresses.

    " + }, + "ValidationStatus":{ + "shape":"DomainStatus", + "documentation":"

    The validation status for this domain. Valid values:

    • PENDING_VALIDATION – The domain is waiting for validation to complete.

    • SUCCESS – Validation completed successfully.

    • FAILED – Validation failed.

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

    Contains the validation method, validation status, and validation challenge details for a domain. This structure appears in DomainValidationSummary as both the active and requested validation configuration.

    " + }, "ValidationEmailList":{ "type":"list", "member":{"shape":"String"} diff --git a/services/acmpca/pom.xml b/services/acmpca/pom.xml index a099b218c5cd..066d03984b76 100644 --- a/services/acmpca/pom.xml +++ b/services/acmpca/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT acmpca AWS Java SDK :: Services :: ACM PCA diff --git a/services/acmpca/src/main/resources/codegen-resources/customization.config b/services/acmpca/src/main/resources/codegen-resources/customization.config index 866842bc7215..db9b82cfd1ce 100644 --- a/services/acmpca/src/main/resources/codegen-resources/customization.config +++ b/services/acmpca/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listCertificateAuthorities" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/acmpca/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/acmpca/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8d4afc0be156 --- /dev/null +++ b/services/acmpca/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-pca-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-pca.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-pca-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-pca.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://acm-pca.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/acmpca/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/acmpca/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 20b1ccf09447..000000000000 --- a/services/acmpca/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://acm-pca-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://acm-pca.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://acm-pca-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://acm-pca.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://acm-pca.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/acmpca/src/main/resources/codegen-resources/service-2.json b/services/acmpca/src/main/resources/codegen-resources/service-2.json index 9c35080a2070..d063fea22af5 100644 --- a/services/acmpca/src/main/resources/codegen-resources/service-2.json +++ b/services/acmpca/src/main/resources/codegen-resources/service-2.json @@ -241,8 +241,8 @@ "errors":[ {"shape":"LimitExceededException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"InvalidArgsException"}, {"shape":"InvalidArnException"}, + {"shape":"InvalidArgsException"}, {"shape":"InvalidStateException"}, {"shape":"MalformedCSRException"} ], @@ -668,7 +668,7 @@ }, "SigningAlgorithm":{ "shape":"SigningAlgorithm", - "documentation":"

    Name of the algorithm your private CA uses to sign certificate requests.

    This parameter should not be confused with the SigningAlgorithm parameter used to sign certificates when they are issued.

    " + "documentation":"

    Name of the algorithm your private CA uses to sign certificate requests.

    This parameter should not be confused with the SigningAlgorithm parameter of the IssueCertificate API action, which is used to sign certificates when they are issued.

    " }, "Subject":{ "shape":"ASN1Subject", @@ -879,11 +879,11 @@ }, "S3BucketName":{ "shape":"S3BucketName3To255", - "documentation":"

    Name of the S3 bucket that contains the CRL. If you do not provide a value for the CustomCname argument, the name of your S3 bucket is placed into the CRL Distribution Points extension of the issued certificate. You can change the name of your bucket by calling the UpdateCertificateAuthority operation. You must specify a bucket policy that allows Amazon Web Services Private CA to write the CRL to your bucket.

    The S3BucketName parameter must conform to the S3 bucket naming rules.

    " + "documentation":"

    Name of the S3 bucket that contains the CRL. If you do not provide a value for the CustomCname argument, the name of your S3 bucket is placed into the CRL Distribution Points extension of the issued certificate. You can change the name of your bucket by calling the UpdateCertificateAuthority operation. You must specify a bucket policy that allows Amazon Web Services Private CA to write the CRL to your bucket.

    The S3BucketName parameter must conform to the S3 bucket naming rules.

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

    Determines whether the CRL will be publicly readable or privately held in the CRL Amazon S3 bucket. If you choose PUBLIC_READ, the CRL will be accessible over the public internet. If you choose BUCKET_OWNER_FULL_CONTROL, only the owner of the CRL S3 bucket can access the CRL, and your PKI clients may need an alternative method of access.

    If no value is specified, the default is PUBLIC_READ.

    Note: This default can cause CA creation to fail in some circumstances. If you have have enabled the Block Public Access (BPA) feature in your S3 account, then you must specify the value of this parameter as BUCKET_OWNER_FULL_CONTROL, and not doing so results in an error. If you have disabled BPA in S3, then you can specify either BUCKET_OWNER_FULL_CONTROL or PUBLIC_READ as the value.

    For more information, see Blocking public access to the S3 bucket.

    " + "documentation":"

    Determines whether the CRL will be publicly readable or privately held in the CRL Amazon S3 bucket. If you choose PUBLIC_READ, the CRL will be accessible over the public internet. If you choose BUCKET_OWNER_FULL_CONTROL, only the owner of the CRL S3 bucket can access the CRL, and your PKI clients may need an alternative method of access.

    If no value is specified, the default is PUBLIC_READ.

    Note: This default can cause CA creation to fail in some circumstances. If you have have enabled the Block Public Access (BPA) feature in your S3 account, then you must specify the value of this parameter as BUCKET_OWNER_FULL_CONTROL, and not doing so results in an error. If you have disabled BPA in S3, then you can specify either BUCKET_OWNER_FULL_CONTROL or PUBLIC_READ as the value.

    For more information, see Blocking public access to the S3 bucket.

    " }, "CrlDistributionPointExtensionConfiguration":{ "shape":"CrlDistributionPointExtensionConfiguration", @@ -891,7 +891,7 @@ }, "CrlType":{ "shape":"CrlType", - "documentation":"

    Specifies whether to create a complete or partitioned CRL. This setting determines the maximum number of certificates that the certificate authority can issue and revoke. For more information, see Amazon Web Services Private CA quotas.

    • COMPLETE - The default setting. Amazon Web Services Private CA maintains a single CRL file for all unexpired certificates issued by a CA that have been revoked for any reason. Each certificate that Amazon Web Services Private CA issues is bound to a specific CRL through its CRL distribution point (CDP) extension, defined in RFC 5280.

    • PARTITIONED - Compared to complete CRLs, partitioned CRLs dramatically increase the number of certificates your private CA can issue.

      When using partitioned CRLs, you must validate that the CRL's associated issuing distribution point (IDP) URI matches the certificate's CDP URI to ensure the right CRL has been fetched. Amazon Web Services Private CA marks the IDP extension as critical, which your client must be able to process.

    " + "documentation":"

    Specifies whether to create a complete or partitioned CRL. This setting determines the maximum number of certificates that the certificate authority can issue and revoke. For more information, see Amazon Web Services Private CA quotas.

    • COMPLETE - The default setting. Amazon Web Services Private CA maintains a single CRL file for all unexpired certificates issued by a CA that have been revoked for any reason. Each certificate that Amazon Web Services Private CA issues is bound to a specific CRL through its CRL distribution point (CDP) extension, defined in RFC 5280.

    • PARTITIONED - Compared to complete CRLs, partitioned CRLs dramatically increase the number of certificates your private CA can issue.

      When using partitioned CRLs, you must validate that the CRL's associated issuing distribution point (IDP) URI matches the certificate's CDP URI to ensure the right CRL has been fetched. Amazon Web Services Private CA marks the IDP extension as critical, which your client must be able to process.

    " }, "CustomPath":{ "shape":"CrlPathString", @@ -906,7 +906,7 @@ "members":{ "OmitExtension":{ "shape":"Boolean", - "documentation":"

    Configures whether the CRL Distribution Point extension should be populated with the default URL to the CRL. If set to true, then the CDP extension will not be present in any certificates issued by that CA unless otherwise specified through CSR or API passthrough.

    Only set this if you have another way to distribute the CRL Distribution Points ffor certificates issued by your CA, such as the Matter Distributed Compliance Ledger

    This configuration cannot be enabled with a custom CNAME set.

    ", + "documentation":"

    Configures whether the CRL Distribution Point extension should be populated with the default URL to the CRL. If set to true, then the CDP extension will not be present in any certificates issued by that CA unless otherwise specified through CSR or API passthrough.

    Only set this if you have another way to distribute the CRL Distribution Points for certificates issued by your CA, such as the Matter Distributed Compliance Ledger

    This configuration cannot be enabled with a custom CNAME set.

    ", "box":true } }, @@ -916,7 +916,7 @@ "type":"string", "max":253, "min":0, - "pattern":"[-a-zA-Z0-9;?:@&=+$,%_.!~*()']+(/[-a-zA-Z0-9;?:@&=+$,%_.!~*()']+)*" + "pattern":"(/|[-a-zA-Z0-9;?:@&=+$,%_.!~*()']+(/[-a-zA-Z0-9;?:@&=+$,%_.!~*()']+)*)" }, "CrlType":{ "type":"string", @@ -1954,6 +1954,9 @@ "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA", + "SHA256WITHRSA_PSS", + "SHA384WITHRSA_PSS", + "SHA512WITHRSA_PSS", "SM3WITHSM2", "ML_DSA_44", "ML_DSA_65", diff --git a/services/agentregistry/pom.xml b/services/agentregistry/pom.xml new file mode 100644 index 000000000000..a58092171ff3 --- /dev/null +++ b/services/agentregistry/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + agentregistry + AWS Java SDK :: Services :: Agent Registry + The AWS Java SDK for Agent Registry module holds the client classes that are used for + communicating with Agent Registry. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.agentregistry + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/agentregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/agentregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2780ec13f4c5 --- /dev/null +++ b/services/agentregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,65 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region of the service.", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send requests.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agent-registry.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Unable to resolve an Agent Registry endpoint: Region was not set and no explicit Endpoint override was provided.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 3, + "nodes": "/////wAAAAH/////AAAAAAX14QEAAAADAAAAAQX14QIF9eED" +} \ No newline at end of file diff --git a/services/agentregistry/src/main/resources/codegen-resources/endpoint-tests.json b/services/agentregistry/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..a5f91c38b149 --- /dev/null +++ b/services/agentregistry/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,39 @@ +{ + "version": "1.0", + "testCases": [ + { + "documentation": "Region us-west-2 -> region-based prod host.", + "params": { + "Region": "us-west-2" + }, + "expect": { + "endpoint": { + "url": "https://agent-registry.us-west-2.api.aws" + } + } + }, + { + "documentation": "Region us-east-1 -> region-based prod host.", + "params": { + "Region": "us-east-1" + }, + "expect": { + "endpoint": { + "url": "https://agent-registry.us-east-1.api.aws" + } + } + }, + { + "documentation": "Endpoint override wins over region.", + "params": { + "Region": "us-west-2", + "Endpoint": "https://custom.example.aws.dev" + }, + "expect": { + "endpoint": { + "url": "https://custom.example.aws.dev" + } + } + } + ] +} \ No newline at end of file diff --git a/services/agentregistry/src/main/resources/codegen-resources/paginators-1.json b/services/agentregistry/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..52b793e10607 --- /dev/null +++ b/services/agentregistry/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,10 @@ +{ + "pagination": { + "ListDiscoverableRegistryRecords": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "registryRecords" + } + } +} diff --git a/services/agentregistry/src/main/resources/codegen-resources/service-2.json b/services/agentregistry/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..6ec3d74dcffa --- /dev/null +++ b/services/agentregistry/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,897 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2025-12-01", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"agent-registry", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"Agent Registry", + "serviceId":"Agent Registry", + "signatureVersion":"v4", + "signingName":"agent-registry", + "uid":"agent-registry-2025-12-01" + }, + "operations":{ + "BatchGetDiscoverableRegistryRecord":{ + "name":"BatchGetDiscoverableRegistryRecord", + "http":{ + "method":"POST", + "requestUri":"/discoverable-records-batch", + "responseCode":200 + }, + "input":{"shape":"BatchGetDiscoverableRegistryRecordRequest"}, + "output":{"shape":"BatchGetDiscoverableRegistryRecordResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Retrieves multiple discoverable registry records by ID from a single registry. Records that cannot be retrieved are reported individually in the errors list rather than failing the entire request.

    " + }, + "ListDiscoverableRegistryRecords":{ + "name":"ListDiscoverableRegistryRecords", + "http":{ + "method":"POST", + "requestUri":"/registries/{registryId}/discoverable-records-list", + "responseCode":200 + }, + "input":{"shape":"ListDiscoverableRegistryRecordsRequest"}, + "output":{"shape":"ListDiscoverableRegistryRecordsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Lists the discoverable registry records in a registry. You can optionally filter and paginate the results.

    ", + "readonly":true + }, + "SearchDiscoverableRegistryRecords":{ + "name":"SearchDiscoverableRegistryRecords", + "http":{ + "method":"POST", + "requestUri":"/discoverable-records-search", + "responseCode":200 + }, + "input":{"shape":"SearchDiscoverableRegistryRecordsRequest"}, + "output":{"shape":"SearchDiscoverableRegistryRecordsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Searches the discoverable registry records in a registry using a natural language query. Returns metadata for the matching records ordered by relevance.

    " + } + }, + "shapes":{ + "A2aAgentCardDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The A2A agent card content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The source location from which the A2A (Agent-to-Agent) agent card descriptor content was retrieved.

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

    Descriptor that defines the content of an A2A (Agent-to-Agent) agent card registry record. The content is validated against the A2A protocol schema.

    " + }, + "AccessDeniedException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The caller is not authorized to perform the requested action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "AgUiDescriptor":{ + "type":"structure", + "members":{ + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The source location of the AG-UI protocol endpoint.

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

    A descriptor for a registry record that exposes an AG-UI protocol endpoint. This descriptor is source-only: it identifies where the endpoint is located and carries no descriptor payload data or schema version.

    " + }, + "AgentSkillsAdditionalData":{ + "type":"structure", + "members":{ + "skillMd":{ + "shape":"AgentSkillsMdDescriptor", + "documentation":"

    The agent skills markdown descriptor associated with the agent skills definition.

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

    Additional data for an agent skills definition descriptor.

    " + }, + "AgentSkillsDefinitionDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The agent skills definition content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "additionalData":{ + "shape":"AgentSkillsAdditionalData", + "documentation":"

    Additional data for the agent skills definition, such as the skills markdown descriptor.

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

    Descriptor that defines an agent skills registry record and its associated content.

    " + }, + "AgentSkillsMdDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The agent skills markdown content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The source location from which the agent skills markdown content was retrieved.

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

    Markdown-format descriptor containing an agent skills document.

    " + }, + "BatchGetDiscoverableRegistryRecordError":{ + "type":"structure", + "required":[ + "registryId", + "recordId", + "errorCode" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry the record was requested from, echoed from the request.

    " + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the record that could not be retrieved, echoed from the request in the same format that you supplied (ARN or record ID).

    " + }, + "errorCode":{ + "shape":"BatchGetDiscoverableRegistryRecordErrorCode", + "documentation":"

    The machine-readable reason that the record could not be retrieved.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    An optional human-readable detail about the error. Do not parse this value programmatically.

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

    Describes why a requested record could not be retrieved.

    " + }, + "BatchGetDiscoverableRegistryRecordErrorCode":{ + "type":"string", + "enum":[ + "RESOURCE_NOT_FOUND", + "ACCESS_DENIED", + "INTERNAL_ERROR" + ] + }, + "BatchGetDiscoverableRegistryRecordErrorList":{ + "type":"list", + "member":{"shape":"BatchGetDiscoverableRegistryRecordError"} + }, + "BatchGetDiscoverableRegistryRecordRequest":{ + "type":"structure", + "required":["entries"], + "members":{ + "entries":{ + "shape":"BatchGetDiscoverableRegistryRecordRequestEntriesList", + "documentation":"

    The registry-scoped groups of record IDs to retrieve. Currently, you can specify exactly one entry.

    " + } + } + }, + "BatchGetDiscoverableRegistryRecordRequestEntriesList":{ + "type":"list", + "member":{"shape":"RegistryRecordsEntry"}, + "max":1, + "min":1 + }, + "BatchGetDiscoverableRegistryRecordResponse":{ + "type":"structure", + "required":[ + "registryRecords", + "errors" + ], + "members":{ + "registryRecords":{ + "shape":"RegistryRecordSummaryList", + "documentation":"

    The records that were successfully retrieved. Each record correlates to the request by its recordId.

    " + }, + "errors":{ + "shape":"BatchGetDiscoverableRegistryRecordErrorList", + "documentation":"

    The per-record errors for records that could not be retrieved. This list is empty when all requested records were returned.

    " + } + } + }, + "CustomDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The custom descriptor content, serialized as descriptor payload data.

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

    Custom descriptor for user-defined content

    " + }, + "DataSchemaVersion":{ + "type":"string", + "documentation":"

    Version of the descriptor type schema

    ", + "max":255, + "min":1 + }, + "DateTimestamp":{ + "type":"timestamp", + "documentation":"

    Timestamp in ISO 8601 date-time format

    ", + "timestampFormat":"iso8601" + }, + "Description":{ + "type":"string", + "documentation":"

    Description of the Resource

    ", + "max":4096, + "min":1, + "sensitive":true + }, + "DescriptorData":{ + "type":"string", + "documentation":"

    Descriptor payload data

    ", + "max":102400, + "min":1, + "sensitive":true + }, + "DescriptorSource":{ + "type":"structure", + "members":{ + "fromUrl":{ + "shape":"DescriptorSourceFromUrl", + "documentation":"

    The URL-based descriptor source, populated when descriptor content is synchronized from a URL.

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

    The source location from which a descriptor's content was retrieved.

    " + }, + "DescriptorSourceFromUrl":{ + "type":"structure", + "required":["url"], + "members":{ + "url":{ + "shape":"DescriptorSourceUrl", + "documentation":"

    The URL from which the descriptor content is retrieved.

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

    A URL-based descriptor source that identifies where descriptor content is retrieved from.

    " + }, + "DescriptorSourceUrl":{ + "type":"string", + "documentation":"

    URL source for descriptor content

    ", + "max":2048, + "min":1, + "pattern":"https://.*" + }, + "DescriptorTypeList":{ + "type":"list", + "member":{"shape":"String"}, + "max":10, + "min":0 + }, + "Descriptors":{ + "type":"structure", + "members":{ + "mcpServer":{ + "shape":"McpServerDescriptor", + "documentation":"

    The MCP server descriptor, populated when the record type is MCP.

    " + }, + "a2aAgentCard":{ + "shape":"A2aAgentCardDescriptor", + "documentation":"

    The A2A agent card descriptor, populated when the record type is AGENT.

    " + }, + "agentSkillsDefinition":{ + "shape":"AgentSkillsDefinitionDescriptor", + "documentation":"

    The agent skills definition descriptor, populated when the record type is SKILL.

    " + }, + "custom":{ + "shape":"CustomDescriptor", + "documentation":"

    The custom descriptor, populated when the record type is CUSTOM.

    " + }, + "http":{ + "shape":"HttpDescriptor", + "documentation":"

    The HTTP descriptor, populated when the record exposes an HTTP endpoint.

    " + }, + "agui":{ + "shape":"AgUiDescriptor", + "documentation":"

    The AG-UI descriptor, populated when the record exposes an AG-UI protocol endpoint.

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

    The protocol-specific descriptors that describe how to connect to and use the registry record.

    " + }, + "DiscoverableFilterValues":{ + "type":"list", + "member":{"shape":"FilterValue"}, + "max":10, + "min":1 + }, + "DiscoverableRegistryRecordSummary":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "name", + "recordType", + "recordVersion", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The Amazon Resource Name (ARN) of the parent registry that owns the record.

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The Amazon Resource Name (ARN) of the registry record.

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The unique identifier of the registry record.

    " + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record. Names are unique within a registry.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A human-readable description of the registry record. Use this field to explain the record's purpose or content to consumers discovering it in the registry.

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record. MCP is a Model Context Protocol server record, AGENT is an Agent-to-Agent (A2A) agent card record, SKILL is an agent skills definition record, and CUSTOM is a record with a custom descriptor.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version identifier of the registry record.

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The lifecycle status of the registry record. A record is DRAFT before it is submitted, PENDING_APPROVAL while awaiting curator review, and APPROVED once it is approved and discoverable. REJECTED and DEPRECATED records are not discoverable. The CREATING, UPDATING, CREATE_FAILED, and UPDATE_FAILED values reflect the state of an in-progress or failed asynchronous change.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was last updated.

    " + }, + "descriptorTypes":{ + "shape":"DescriptorTypeList", + "documentation":"

    The descriptor types that are present on this registry record. Each value corresponds to a descriptor entry key on the approved record.

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

    Summary information about a discoverable registry record returned by ListDiscoverableRegistryRecords. This summary does not include descriptors.

    " + }, + "DiscoverableRegistryRecordSummaryList":{ + "type":"list", + "member":{"shape":"DiscoverableRegistryRecordSummary"} + }, + "FilterValue":{ + "type":"string", + "documentation":"

    A single filter value. Constrained by length only; the accepted set of values is filter-specific and validated server-side so enum-style values such as READY or AWS_IAM are accepted.

    ", + "max":255, + "min":1 + }, + "HttpDescriptor":{ + "type":"structure", + "members":{ + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The source location of the HTTP endpoint.

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

    A descriptor for a registry record that exposes an HTTP endpoint. This descriptor is source-only: it identifies where the endpoint is located and carries no descriptor payload data or schema version.

    " + }, + "InternalServerException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request failed due to an unexpected internal error; the caller may retry.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, + "ListDiscoverableRegistryRecordsRequest":{ + "type":"structure", + "required":["registryId"], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry whose discoverable records are listed. You can provide either the full Amazon Resource Name (ARN) or the registry ID.

    ", + "location":"uri", + "locationName":"registryId" + }, + "maxResults":{ + "shape":"ListDiscoverableRegistryRecordsRequestMaxResultsInteger", + "documentation":"

    The maximum number of records to return in a single page. Valid values are 1 through 100.

    " + }, + "nextToken":{ + "shape":"ListDiscoverableRegistryRecordsRequestNextTokenString", + "documentation":"

    The pagination token returned by a previous request. Use this value to retrieve the next page of results.

    " + }, + "filters":{ + "shape":"RegistryRecordFilterList", + "documentation":"

    The filters to apply to the discoverable registry record list.

    " + } + } + }, + "ListDiscoverableRegistryRecordsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListDiscoverableRegistryRecordsRequestNextTokenString":{ + "type":"string", + "max":4096, + "min":1 + }, + "ListDiscoverableRegistryRecordsResponse":{ + "type":"structure", + "required":["registryRecords"], + "members":{ + "registryRecords":{ + "shape":"DiscoverableRegistryRecordSummaryList", + "documentation":"

    The page of discoverable registry record summaries.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The pagination token to pass to a subsequent request to retrieve the next page of results. This field is absent when there are no more results.

    " + } + } + }, + "McpServerAdditionalData":{ + "type":"structure", + "members":{ + "tools":{ + "shape":"McpToolsDescriptor", + "documentation":"

    The MCP tools descriptor that defines the tools exposed by the MCP server.

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

    Additional data for an MCP server descriptor

    " + }, + "McpServerDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The MCP server descriptor content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "additionalData":{ + "shape":"McpServerAdditionalData", + "documentation":"

    Additional data associated with the MCP server descriptor, such as tool definitions.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The source location from which the MCP (Model Context Protocol) server descriptor content was retrieved.

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

    Descriptor that defines the content of an MCP (Model Context Protocol) server registry record, including the server definition and its tool definitions. The content is validated against the MCP protocol schema.

    " + }, + "McpToolsDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The MCP tools descriptor content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

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

    MCP tools descriptor containing tool definitions

    " + }, + "MetadataFilterExpression":{ + "type":"structure", + "members":{}, + "document":true, + "sensitive":true + }, + "NonBlankString":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"[\\s\\S]+" + }, + "RecordIdentifier":{ + "type":"string", + "documentation":"

    Record identifier that accepts either ARN or ID format

    ", + "max":2048, + "min":1, + "pattern":"(arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}/record/)?[a-zA-Z0-9]{12}" + }, + "RecordType":{ + "type":"string", + "documentation":"

    Record type enum for registry record classification

    ", + "enum":[ + "MCP", + "AGENT", + "CUSTOM", + "SKILL", + "GATEWAY" + ] + }, + "RegistryArn":{ + "type":"string", + "documentation":"

    Registry Amazon Resource Name

    ", + "max":2048, + "min":46, + "pattern":"arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}" + }, + "RegistryIdentifier":{ + "type":"string", + "documentation":"

    Registry identifier that accepts either ARN or ID format

    ", + "max":2048, + "min":1, + "pattern":"(arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/)?[a-zA-Z0-9]{12,16}" + }, + "RegistryRecordArn":{ + "type":"string", + "documentation":"

    Registry Record Amazon Resource Name

    ", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}/record/[a-zA-Z0-9]{12}" + }, + "RegistryRecordDisplayName":{ + "type":"string", + "documentation":"

    Display name for a registry record

    ", + "max":255, + "min":1 + }, + "RegistryRecordFilter":{ + "type":"structure", + "required":[ + "name", + "values" + ], + "members":{ + "name":{ + "shape":"RegistryRecordFilterName", + "documentation":"

    The attribute to filter on.

    " + }, + "values":{ + "shape":"DiscoverableFilterValues", + "documentation":"

    The values to match for the attribute.

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

    A single filter applied to a ListDiscoverableRegistryRecords request.

    " + }, + "RegistryRecordFilterList":{ + "type":"list", + "member":{"shape":"RegistryRecordFilter"}, + "documentation":"

    The list of filters applied to a ListDiscoverableRegistryRecords request.

    ", + "max":10, + "min":0 + }, + "RegistryRecordFilterName":{ + "type":"string", + "documentation":"

    The attribute to filter registry records on.

    ", + "enum":[ + "recordType", + "descriptorType" + ] + }, + "RegistryRecordId":{ + "type":"string", + "documentation":"

    Registry Record unique identifier - 12-character alphanumeric string

    ", + "max":12, + "min":12, + "pattern":"[a-zA-Z0-9]{12}" + }, + "RegistryRecordName":{ + "type":"string", + "documentation":"

    Registry Record name

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9_\\-\\.\\/]*" + }, + "RegistryRecordStatus":{ + "type":"string", + "documentation":"

    Registry record status

    ", + "enum":[ + "DRAFT", + "PENDING_APPROVAL", + "APPROVED", + "REJECTED", + "DEPRECATED", + "CREATING", + "UPDATING", + "CREATE_FAILED", + "UPDATE_FAILED" + ] + }, + "RegistryRecordSummary":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "name", + "recordType", + "descriptors", + "recordVersion", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The Amazon Resource Name (ARN) of the parent registry that owns the record.

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The Amazon Resource Name (ARN) of the registry record.

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The unique identifier of the registry record.

    " + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record. Names are unique within a registry.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A human-readable description of the registry record. Use this field to explain the record's purpose or content to consumers discovering it in the registry.

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record. MCP is a Model Context Protocol server record, AGENT is an Agent-to-Agent (A2A) agent card record, SKILL is an agent skills definition record, and CUSTOM is a record with a custom descriptor.

    " + }, + "descriptors":{ + "shape":"Descriptors", + "documentation":"

    The protocol-specific descriptors that describe how to connect to and use the record.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version identifier of the registry record.

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The lifecycle status of the registry record. A record is DRAFT before it is submitted, PENDING_APPROVAL while awaiting curator review, and APPROVED once it is approved and discoverable. REJECTED and DEPRECATED records are not discoverable. The CREATING, UPDATING, CREATE_FAILED, and UPDATE_FAILED values reflect the state of an in-progress or failed asynchronous change.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was last updated.

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

    Summary information about a registry record, including its descriptors.

    " + }, + "RegistryRecordSummaryList":{ + "type":"list", + "member":{"shape":"RegistryRecordSummary"} + }, + "RegistryRecordVersion":{ + "type":"string", + "documentation":"

    Version of the registry record

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9.-]+" + }, + "RegistryRecordsEntry":{ + "type":"structure", + "required":[ + "registryId", + "recordIds" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry to retrieve the records from. You can provide either the full Amazon Resource Name (ARN) or the registry ID.

    " + }, + "recordIds":{ + "shape":"RegistryRecordsEntryRecordIdsList", + "documentation":"

    The record IDs to retrieve from the registry. You can specify 1 through 100 record IDs.

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

    Binds one registry to the record IDs requested from it.

    " + }, + "RegistryRecordsEntryRecordIdsList":{ + "type":"list", + "member":{"shape":"RecordIdentifier"}, + "max":100, + "min":1 + }, + "ResourceNotFoundException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The requested resource was not found.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "SearchDiscoverableRegistryRecordsRequest":{ + "type":"structure", + "required":[ + "searchQuery", + "registryIds" + ], + "members":{ + "searchQuery":{ + "shape":"SearchQuery", + "documentation":"

    The natural language query to search for matching registry records.

    " + }, + "registryIds":{ + "shape":"SearchDiscoverableRegistryRecordsRequestRegistryIdsList", + "documentation":"

    The registry identifiers to search within. Currently, you must specify exactly one registry identifier. You can provide either the full Amazon Web Services Resource Name (ARN) or the registry ID.

    " + }, + "maxResults":{ + "shape":"SearchDiscoverableRegistryRecordsRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return. Valid values are 1 through 20. The default value is 10.

    " + }, + "filters":{ + "shape":"MetadataFilterExpression", + "documentation":"

    An optional structured JSON metadata filter that narrows the search results. Supports the field-level operators $eq, $ne, and $in, and the logical operators $and and $or on filterable fields.

    " + } + } + }, + "SearchDiscoverableRegistryRecordsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":20, + "min":1 + }, + "SearchDiscoverableRegistryRecordsRequestRegistryIdsList":{ + "type":"list", + "member":{"shape":"RegistryIdentifier"}, + "max":1, + "min":1 + }, + "SearchDiscoverableRegistryRecordsResponse":{ + "type":"structure", + "required":["registryRecords"], + "members":{ + "registryRecords":{ + "shape":"RegistryRecordSummaryList", + "documentation":"

    The registry records that match the search query, ordered by relevance.

    " + } + } + }, + "SearchQuery":{ + "type":"string", + "max":256, + "min":0, + "sensitive":true + }, + "String":{"type":"string"}, + "ThrottlingException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request was denied due to request throttling; the caller may retry after a delay.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true + }, + "UnauthorizedException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request could not be authenticated.

    ", + "error":{ + "httpStatusCode":401, + "senderFault":true + }, + "exception":true + }, + "ValidationException":{ + "type":"structure", + "required":[ + "message", + "reason" + ], + "members":{ + "message":{"shape":"String"}, + "reason":{ + "shape":"ValidationExceptionReason", + "documentation":"

    The reason the request failed validation.

    " + }, + "fieldList":{ + "shape":"ValidationExceptionFieldList", + "documentation":"

    The list of input fields that failed validation.

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

    The request failed validation of one or more input fields.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "ValidationExceptionField":{ + "type":"structure", + "required":[ + "name", + "message" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the field that failed validation.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A description of why the field failed validation.

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

    Describes a single input field that failed validation.

    " + }, + "ValidationExceptionFieldList":{ + "type":"list", + "member":{"shape":"ValidationExceptionField"} + }, + "ValidationExceptionReason":{ + "type":"string", + "enum":[ + "CannotParse", + "FieldValidationFailed", + "IdempotentParameterMismatchException", + "EventInOtherSession", + "ResourceConflict" + ] + } + }, + "documentation":"

    Agent Registry lets callers discover, list, and retrieve approved records published to a registry.

    " +} diff --git a/services/agentregistrycontrol/pom.xml b/services/agentregistrycontrol/pom.xml new file mode 100644 index 000000000000..49735fbabeef --- /dev/null +++ b/services/agentregistrycontrol/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + agentregistrycontrol + AWS Java SDK :: Services :: Agent Registry Control + The AWS Java SDK for Agent Registry Control module holds the client classes that are used for + communicating with Agent Registry Control. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.agentregistrycontrol + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ab4d863b26a6 --- /dev/null +++ b/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,66 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region of the service.", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send requests.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agent-registry-control.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "Region is required to resolve an endpoint.", + "conditions": [], + "error": "Unable to resolve an Agent Registry Control endpoint: Region was not set and no explicit Endpoint override was provided.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 3, + "nodes": "/////wAAAAH/////AAAAAAX14QEAAAADAAAAAQX14QIF9eED" +} \ No newline at end of file diff --git a/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-tests.json b/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..f9c482c0e703 --- /dev/null +++ b/services/agentregistrycontrol/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,39 @@ +{ + "version": "1.0", + "testCases": [ + { + "documentation": "Region us-west-2 -> region-based prod host.", + "params": { + "Region": "us-west-2" + }, + "expect": { + "endpoint": { + "url": "https://agent-registry-control.us-west-2.api.aws" + } + } + }, + { + "documentation": "Region us-east-1 -> region-based prod host.", + "params": { + "Region": "us-east-1" + }, + "expect": { + "endpoint": { + "url": "https://agent-registry-control.us-east-1.api.aws" + } + } + }, + { + "documentation": "Endpoint override wins over region.", + "params": { + "Region": "us-west-2", + "Endpoint": "https://custom.example.aws.dev" + }, + "expect": { + "endpoint": { + "url": "https://custom.example.aws.dev" + } + } + } + ] +} \ No newline at end of file diff --git a/services/agentregistrycontrol/src/main/resources/codegen-resources/paginators-1.json b/services/agentregistrycontrol/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..768d128fffcc --- /dev/null +++ b/services/agentregistrycontrol/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,16 @@ +{ + "pagination": { + "ListRegistries": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "registries" + }, + "ListRegistryRecords": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "registryRecords" + } + } +} diff --git a/services/agentregistrycontrol/src/main/resources/codegen-resources/service-2.json b/services/agentregistrycontrol/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..8fc5f5c67133 --- /dev/null +++ b/services/agentregistrycontrol/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,2972 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2025-12-01", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"agent-registry-control", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"Agent Registry Control", + "serviceId":"Agent Registry Control", + "signatureVersion":"v4", + "signingName":"agent-registry", + "uid":"agent-registry-control-2025-12-01" + }, + "operations":{ + "CreateRegistry":{ + "name":"CreateRegistry", + "http":{ + "method":"POST", + "requestUri":"/registries", + "responseCode":202 + }, + "input":{"shape":"CreateRegistryRequest"}, + "output":{"shape":"CreateRegistryResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates a new registry, a catalog that organizes registry records and defines their discovery authorization and record approval behavior. Creation is asynchronous: the registry begins in the CREATING status and becomes usable once it reaches READY.

    ", + "idempotent":true + }, + "CreateRegistryRecord":{ + "name":"CreateRegistryRecord", + "http":{ + "method":"POST", + "requestUri":"/registries/{registryId}/records", + "responseCode":202 + }, + "input":{"shape":"CreateRegistryRecordRequest"}, + "output":{"shape":"CreateRegistryRecordResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates a registry record within a registry. A registry record describes a discoverable resource, such as an MCP server, an agent, an agent skill, or a custom resource. Creation is asynchronous: the record is returned with the CREATING status while it is processed.

    ", + "idempotent":true + }, + "DeleteRegistry":{ + "name":"DeleteRegistry", + "http":{ + "method":"DELETE", + "requestUri":"/registries/{registryId}", + "responseCode":202 + }, + "input":{"shape":"DeleteRegistryRequest"}, + "output":{"shape":"DeleteRegistryResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Deletes a registry. Deletion is asynchronous: the registry transitions to the DELETING status and is removed along with its registry records.

    ", + "idempotent":true + }, + "DeleteRegistryRecord":{ + "name":"DeleteRegistryRecord", + "http":{ + "method":"DELETE", + "requestUri":"/registries/{registryId}/records/{recordId}", + "responseCode":200 + }, + "input":{"shape":"DeleteRegistryRecordRequest"}, + "output":{"shape":"DeleteRegistryRecordResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Deletes a registry record

    ", + "idempotent":true + }, + "GetRegistry":{ + "name":"GetRegistry", + "http":{ + "method":"GET", + "requestUri":"/registries/{registryId}", + "responseCode":200 + }, + "input":{"shape":"GetRegistryRequest"}, + "output":{"shape":"GetRegistryResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Gets a registry by identifier (ARN or ID)

    ", + "readonly":true + }, + "GetRegistryRecord":{ + "name":"GetRegistryRecord", + "http":{ + "method":"GET", + "requestUri":"/registries/{registryId}/records/{recordId}", + "responseCode":200 + }, + "input":{"shape":"GetRegistryRecordRequest"}, + "output":{"shape":"GetRegistryRecordResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Retrieves the details of a registry record

    ", + "readonly":true + }, + "ListRegistries":{ + "name":"ListRegistries", + "http":{ + "method":"POST", + "requestUri":"/registries-list", + "responseCode":200 + }, + "input":{"shape":"ListRegistriesRequest"}, + "output":{"shape":"ListRegistriesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Lists the registries in the caller's account and Region, with optional filtering by status and discovery authorizer type

    ", + "readonly":true + }, + "ListRegistryRecords":{ + "name":"ListRegistryRecords", + "http":{ + "method":"POST", + "requestUri":"/registries/{registryId}/records-list", + "responseCode":200 + }, + "input":{"shape":"ListRegistryRecordsRequest"}, + "output":{"shape":"ListRegistryRecordsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Lists the registry records within a registry, with optional filtering by name, status, and record type

    ", + "readonly":true + }, + "ListTagsForResource":{ + "name":"ListTagsForResource", + "http":{ + "method":"GET", + "requestUri":"/tags/{resourceArn+}", + "responseCode":200 + }, + "input":{"shape":"ListTagsForResourceRequest"}, + "output":{"shape":"ListTagsForResourceResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Lists the tags associated with the specified Amazon Web Services Agent Registry resource. Returns the current tag key-value pairs on the resource.

    ", + "readonly":true + }, + "SubmitRegistryRecordForApproval":{ + "name":"SubmitRegistryRecordForApproval", + "http":{ + "method":"POST", + "requestUri":"/registries/{registryId}/records/{recordId}/submit-for-approval", + "responseCode":202 + }, + "input":{"shape":"SubmitRegistryRecordForApprovalRequest"}, + "output":{"shape":"SubmitRegistryRecordForApprovalResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Submits a DRAFT registry record for approval, moving it into the registry's approval workflow. Depending on the registry's approval configuration, the record is either auto-approved or set to PENDING_APPROVAL for a curator to approve or reject.

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

    Adds or overwrites one or more tags for the specified Amazon Web Services Agent Registry resource. Tags are key-value pairs that you can use to categorize and manage Amazon Web Services resources. If a tag with the same key already exists on the resource, the service replaces its value with the value you specify.

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

    Removes one or more tags from the specified Amazon Web Services Agent Registry resource. The operation removes only the tags whose keys you supply; other tags on the resource remain unchanged.

    ", + "idempotent":true + }, + "UpdateRegistry":{ + "name":"UpdateRegistry", + "http":{ + "method":"PATCH", + "requestUri":"/registries/{registryId}", + "responseCode":202 + }, + "input":{"shape":"UpdateRegistryRequest"}, + "output":{"shape":"UpdateRegistryResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates an existing registry. This operation uses PATCH semantics: specify only the fields you want to change, and omit the rest to leave them unchanged. Updates are applied asynchronously and the registry transitions to the UPDATING status while they are processed.

    " + }, + "UpdateRegistryRecord":{ + "name":"UpdateRegistryRecord", + "http":{ + "method":"PATCH", + "requestUri":"/registries/{registryId}/records/{recordId}", + "responseCode":202 + }, + "input":{"shape":"UpdateRegistryRecordRequest"}, + "output":{"shape":"UpdateRegistryRecordResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates a registry record. The update is asynchronous: the record is returned with the UPDATING status while it is processed. Fields that use update wrappers follow PATCH semantics: omit the field to leave it unchanged.

    " + }, + "UpdateRegistryRecordStatus":{ + "name":"UpdateRegistryRecordStatus", + "http":{ + "method":"PATCH", + "requestUri":"/registries/{registryId}/records/{recordId}/status", + "responseCode":202 + }, + "input":{"shape":"UpdateRegistryRecordStatusRequest"}, + "output":{"shape":"UpdateRegistryRecordStatusResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the status of a registry record as part of the registry's curation workflow, for example to approve or reject a record that is pending approval, or to deprecate an approved record so that it is no longer discoverable

    " + } + }, + "shapes":{ + "A2aAgentCardDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The A2A agent card content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The optional source configuration used to synchronize the A2A agent card descriptor content.

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

    Descriptor that defines the content of an A2A (Agent-to-Agent) agent card registry record. The content is validated against the A2A protocol schema.

    " + }, + "AccessDeniedException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The caller is not authorized to perform the requested action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "AgUiDescriptor":{ + "type":"structure", + "members":{ + "source":{"shape":"DescriptorSource"} + }, + "documentation":"

    A registry record descriptor for the AG-UI (Agent-User Interaction) protocol.

    " + }, + "AgentCoreGatewayProtocolType":{ + "type":"string", + "documentation":"

    The protocol type of an AgentCore Gateway.

    ", + "enum":["MCP"] + }, + "AgentCoreGatewaySourceDetails":{ + "type":"structure", + "members":{ + "protocolType":{"shape":"AgentCoreGatewayProtocolType"}, + "authorizerType":{ + "shape":"String", + "documentation":"

    The type of authorizer configured on the AgentCore Gateway resource that the registry record was detected from.

    " + }, + "authorizerConfiguration":{"shape":"AuthorizerConfiguration"}, + "workloadIdentityDetails":{"shape":"WorkloadIdentityDetails"} + }, + "documentation":"

    Source details for a record auto-detected from an AgentCore Gateway resource.

    " + }, + "AgentCoreRuntimeProtocolConfiguration":{ + "type":"structure", + "members":{ + "serverProtocol":{"shape":"AgentCoreRuntimeServerProtocol"} + }, + "documentation":"

    Protocol configuration for an AgentCore Runtime.

    " + }, + "AgentCoreRuntimeServerProtocol":{ + "type":"string", + "documentation":"

    The server protocol used by an AgentCore Runtime.

    ", + "enum":[ + "HTTP", + "A2A", + "MCP", + "AGUI" + ] + }, + "AgentCoreRuntimeSourceDetails":{ + "type":"structure", + "members":{ + "protocolConfiguration":{"shape":"AgentCoreRuntimeProtocolConfiguration"}, + "authorizerConfiguration":{"shape":"AuthorizerConfiguration"}, + "workloadIdentityDetails":{"shape":"WorkloadIdentityDetails"} + }, + "documentation":"

    Source details for a record auto-detected from an AgentCore Runtime resource.

    " + }, + "AgentSkillsAdditionalData":{ + "type":"structure", + "members":{ + "skillMd":{ + "shape":"AgentSkillsMdDescriptor", + "documentation":"

    The markdown skill content associated with an agent skills definition.

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

    Additional data associated with an agent skills definition descriptor.

    " + }, + "AgentSkillsDefinitionDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The agent skills definition content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "additionalData":{ + "shape":"AgentSkillsAdditionalData", + "documentation":"

    Additional data associated with the agent skills definition descriptor.

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

    Descriptor that defines an agent skills registry record and its associated content.

    " + }, + "AgentSkillsMdDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The agent skills markdown content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The optional source configuration used to synchronize the agent skills markdown content.

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

    Markdown-format descriptor containing an agent skills document.

    " + }, + "AllowedAudience":{ + "type":"string", + "documentation":"

    An audience value that an inbound JWT must contain to be authorized.

    ", + "max":255, + "min":1 + }, + "AllowedAudienceList":{ + "type":"list", + "member":{"shape":"AllowedAudience"}, + "documentation":"

    The list of audience values accepted during JWT validation.

    ", + "min":1 + }, + "AllowedClient":{ + "type":"string", + "documentation":"

    A client identifier that an inbound JWT must be issued to in order to be authorized.

    ", + "max":255, + "min":1 + }, + "AllowedClientsList":{ + "type":"list", + "member":{"shape":"AllowedClient"}, + "documentation":"

    The list of client identifiers accepted during JWT validation.

    ", + "min":1 + }, + "AllowedScopeType":{ + "type":"string", + "documentation":"

    A scope value that an inbound JWT must carry to be authorized.

    ", + "max":255, + "min":1, + "pattern":"[\\x21\\x23-\\x5B\\x5D-\\x7E]+" + }, + "AllowedScopesType":{ + "type":"list", + "member":{"shape":"AllowedScopeType"}, + "documentation":"

    The list of scopes accepted during JWT validation.

    ", + "min":1 + }, + "ApprovalConfiguration":{ + "type":"structure", + "members":{ + "autoApprovalRules":{ + "shape":"AutoApprovalRuleList", + "documentation":"

    The rules that determine which registry records are automatically approved on submission. When omitted or empty, submitted records require manual review.

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

    Configuration for the registry's record approval workflow. Controls whether records submitted for approval require manual review before they become approved and discoverable, or are auto-approved. When no auto-approval rules are configured, submitted records require manual review.

    " + }, + "AuthorizerConfiguration":{ + "type":"structure", + "members":{ + "customJWTAuthorizer":{ + "shape":"CustomJWTAuthorizerConfiguration", + "documentation":"

    Configuration for a custom JWT authorizer.

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

    The authorizer configuration for a registry. Exactly one member is set.

    ", + "union":true + }, + "AuthorizingClaimMatchValueType":{ + "type":"structure", + "required":[ + "claimMatchValue", + "claimMatchOperator" + ], + "members":{ + "claimMatchValue":{ + "shape":"ClaimMatchValueType", + "documentation":"

    The expected value or values that the claim is compared against.

    " + }, + "claimMatchOperator":{ + "shape":"ClaimMatchOperatorType", + "documentation":"

    The operator used to compare the claim value against the expected value.

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

    The value and match operator used to authorize a claim during JWT validation.

    " + }, + "AutoApprovalRule":{ + "type":"string", + "enum":["APPROVE_ALL"] + }, + "AutoApprovalRuleList":{ + "type":"list", + "member":{"shape":"AutoApprovalRule"}, + "max":10, + "min":0 + }, + "AutoDetection":{ + "type":"structure", + "required":[ + "configuration", + "status" + ], + "members":{ + "configuration":{ + "shape":"AutoDetectionConfiguration", + "documentation":"

    The auto-detection settings that control how resources are discovered for the registry.

    " + }, + "status":{ + "shape":"AutoDetectionStatus", + "documentation":"

    The current auto-detection status. ACTIVE indicates that the registry is actively being populated with detected resources. INACTIVE indicates that the preconditions required at the configured scope are not currently met.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable explanation of the current auto-detection status. Typically populated when the status requires additional context.

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

    The auto-detection properties for a registry, including the requested configuration and the current detection status. When auto-detection is enabled and the scope preconditions are met, the registry is automatically populated with discovered resources.

    " + }, + "AutoDetectionConfiguration":{ + "type":"structure", + "required":[ + "scope", + "enabled" + ], + "members":{ + "scope":{ + "shape":"AutoDetectionScope", + "documentation":"

    The source from which resources are detected. For example, ORGANIZATION sources resources from all member accounts of an Amazon Web Services organization.

    " + }, + "enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether auto-detection is requested for the registry. Setting this to true is necessary but not sufficient for auto-detection to become active; the preconditions of the configured scope must also be met.

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

    The customer-defined auto-detection settings for a registry.

    " + }, + "AutoDetectionScope":{ + "type":"string", + "enum":["ORGANIZATION"] + }, + "AutoDetectionStatus":{ + "type":"string", + "enum":[ + "ACTIVE", + "INACTIVE" + ] + }, + "Boolean":{ + "type":"boolean", + "box":true + }, + "ClaimMatchOperatorType":{ + "type":"string", + "documentation":"

    The operator used to compare a claim value against the expected value during JWT validation.

    ", + "enum":[ + "EQUALS", + "CONTAINS", + "CONTAINS_ANY" + ] + }, + "ClaimMatchValueType":{ + "type":"structure", + "members":{ + "matchValueString":{ + "shape":"MatchValueString", + "documentation":"

    A single string value to match the claim against.

    " + }, + "matchValueStringList":{ + "shape":"MatchValueStringList", + "documentation":"

    A list of string values to match the claim against.

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

    The expected value used to match a claim. Exactly one member is set.

    ", + "union":true + }, + "ClientToken":{ + "type":"string", + "documentation":"

    Client specified token used for idempotency checks

    ", + "max":256, + "min":33, + "pattern":"[a-zA-Z0-9](-*[a-zA-Z0-9]){0,256}" + }, + "ConflictException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request conflicts with the current state of the resource.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "CreateRegistryRecordRequest":{ + "type":"structure", + "required":[ + "registryId", + "name", + "recordType", + "descriptors" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry in which to create the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the registry record

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record, which determines the descriptor format

    " + }, + "descriptors":{ + "shape":"Descriptors", + "documentation":"

    The typed descriptor content for the registry record

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version of the registry record

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Client token for idempotency

    ", + "idempotencyToken":true + }, + "provenance":{"shape":"ProvenanceList"}, + "tags":{ + "shape":"TagsMap", + "documentation":"

    Tags to associate with the registry record

    " + } + } + }, + "CreateRegistryRecordResponse":{ + "type":"structure", + "required":[ + "recordArn", + "status" + ], + "members":{ + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The ARN of the created registry record

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The status of the registry record, set to CREATING while the asynchronous workflow is in progress

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

    Response structure for creating a registry record

    " + }, + "CreateRegistryRequest":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"RegistryName", + "documentation":"

    The name of the registry

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the registry

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The optional server-side encryption configuration for the registry. When you provide this field, the specified customer-managed Amazon Web Services KMS key encrypts the registry's content. Omit this field to use an Amazon Web Services-owned encryption key. You cannot change the encryption configuration after registry creation.

    " + }, + "discoveryConfiguration":{ + "shape":"DiscoveryConfiguration", + "documentation":"

    Discovery configuration for the registry

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request, but does not return an error.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    Tags to associate with the registry

    " + }, + "approvalConfiguration":{ + "shape":"ApprovalConfiguration", + "documentation":"

    Approval configuration for registry records

    " + }, + "autoDetectionConfiguration":{ + "shape":"AutoDetectionConfiguration", + "documentation":"

    The optional auto-detection configuration for the registry. When provided, the registry is automatically populated with resources discovered according to the configuration. Omit this field for registries whose records are managed exclusively through the Agent Registry Control API.

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

    Request structure for creating a registry

    " + }, + "CreateRegistryResponse":{ + "type":"structure", + "required":["registryArn"], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The ARN of the created registry

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

    Response structure for creating a registry

    " + }, + "CreatorAccountId":{ + "type":"string", + "max":12, + "min":12, + "pattern":"[0-9]{12}" + }, + "CredentialProviderArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:.*" + }, + "CustomClaimValidationType":{ + "type":"structure", + "required":[ + "inboundTokenClaimName", + "inboundTokenClaimValueType", + "authorizingClaimMatchValue" + ], + "members":{ + "inboundTokenClaimName":{ + "shape":"InboundTokenClaimNameType", + "documentation":"

    The name of the claim in the inbound token to validate.

    " + }, + "inboundTokenClaimValueType":{ + "shape":"InboundTokenClaimValueType", + "documentation":"

    The value type of the claim in the inbound token, either a string or an array of strings.

    " + }, + "authorizingClaimMatchValue":{ + "shape":"AuthorizingClaimMatchValueType", + "documentation":"

    The value and match operator used to authorize the claim.

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

    A validation rule applied to a single claim of an inbound JWT.

    " + }, + "CustomClaimValidationsType":{ + "type":"list", + "member":{"shape":"CustomClaimValidationType"}, + "documentation":"

    The list of custom claim validations applied to an inbound JWT.

    ", + "min":1 + }, + "CustomDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The custom descriptor content, serialized as descriptor payload data.

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

    Custom descriptor for user-defined content

    " + }, + "CustomJWTAuthorizerConfiguration":{ + "type":"structure", + "required":["discoveryUrl"], + "members":{ + "discoveryUrl":{ + "shape":"DiscoveryUrl", + "documentation":"

    The OpenID Connect discovery URL used to retrieve the identity provider's metadata and signing keys.

    " + }, + "allowedAudience":{ + "shape":"AllowedAudienceList", + "documentation":"

    The audience values accepted during JWT validation. A token is rejected if none of its audience claims match.

    " + }, + "allowedClients":{ + "shape":"AllowedClientsList", + "documentation":"

    The client identifiers accepted during JWT validation. A token is rejected if it was not issued to one of these clients.

    " + }, + "allowedScopes":{ + "shape":"AllowedScopesType", + "documentation":"

    The scopes accepted during JWT validation. A token is rejected if it does not carry one of these scopes.

    " + }, + "customClaims":{ + "shape":"CustomClaimValidationsType", + "documentation":"

    Additional custom claim validations applied to the inbound JWT.

    " + }, + "privateEndpoint":{ + "shape":"PrivateEndpoint", + "documentation":"

    The private endpoint used to reach the identity provider's discovery URL over a private network path.

    " + }, + "privateEndpointOverrides":{ + "shape":"PrivateEndpointOverrides", + "documentation":"

    Per-domain private endpoint overrides that route specific identity provider domains through distinct private endpoints.

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

    Configuration for a custom JWT authorizer that validates inbound bearer tokens against an OpenID Connect identity provider.

    " + }, + "CustomParameterMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "DataSchemaVersion":{ + "type":"string", + "documentation":"

    Version of the descriptor type schema

    ", + "max":255, + "min":1 + }, + "DateTimestamp":{ + "type":"timestamp", + "documentation":"

    Timestamp in ISO 8601 date-time format

    ", + "timestampFormat":"iso8601" + }, + "DeleteRegistryRecordRequest":{ + "type":"structure", + "required":[ + "registryId", + "recordId" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry containing the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the registry record to delete (ARN or ID)

    ", + "location":"uri", + "locationName":"recordId" + } + } + }, + "DeleteRegistryRecordResponse":{ + "type":"structure", + "members":{}, + "documentation":"

    Response structure for deleting a registry record

    " + }, + "DeleteRegistryRequest":{ + "type":"structure", + "required":["registryId"], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry to delete (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + } + }, + "documentation":"

    Request structure for deleting a registry

    " + }, + "DeleteRegistryResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"RegistryStatus", + "documentation":"

    Current status of the registry, set to DELETING when deletion is initiated

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

    Response structure for deleting a registry

    " + }, + "Description":{ + "type":"string", + "documentation":"

    Description of the Resource

    ", + "max":4096, + "min":1, + "sensitive":true + }, + "DescriptorData":{ + "type":"string", + "documentation":"

    Descriptor payload data

    ", + "max":102400, + "min":1, + "sensitive":true + }, + "DescriptorSource":{ + "type":"structure", + "members":{ + "fromUrl":{ + "shape":"DescriptorSourceFromUrl", + "documentation":"

    URL-based descriptor source, populated when descriptor content is synchronized from a URL.

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

    The source configuration that defines where descriptor content is retrieved from.

    " + }, + "DescriptorSourceFromUrl":{ + "type":"structure", + "required":["url"], + "members":{ + "url":{ + "shape":"DescriptorSourceUrl", + "documentation":"

    The URL from which the descriptor content is retrieved.

    " + }, + "credentialProviderConfigurations":{ + "shape":"RegistryRecordCredentialProviderConfigurationList", + "documentation":"

    The credential providers used to authenticate when fetching descriptor content from the source URL.

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

    URL-based descriptor source configuration, with credential provider configurations for authenticated URL retrieval.

    " + }, + "DescriptorSourceUrl":{ + "type":"string", + "documentation":"

    URL source for descriptor content

    ", + "max":2048, + "min":1, + "pattern":"https://.*" + }, + "Descriptors":{ + "type":"structure", + "members":{ + "mcpServer":{ + "shape":"McpServerDescriptor", + "documentation":"

    The MCP server descriptor, populated when the record type is MCP.

    " + }, + "a2aAgentCard":{ + "shape":"A2aAgentCardDescriptor", + "documentation":"

    The A2A agent card descriptor, populated when the record type is AGENT.

    " + }, + "agentSkillsDefinition":{ + "shape":"AgentSkillsDefinitionDescriptor", + "documentation":"

    The agent skills definition descriptor, populated when the record type is SKILL.

    " + }, + "custom":{ + "shape":"CustomDescriptor", + "documentation":"

    The custom descriptor, populated when the record type is CUSTOM.

    " + }, + "http":{ + "shape":"HttpDescriptor", + "documentation":"

    The HTTP descriptor, populated for records detected from an HTTP protocol source.

    " + }, + "agui":{ + "shape":"AgUiDescriptor", + "documentation":"

    The AG-UI descriptor, populated for records detected from an AG-UI protocol source.

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

    The typed set of descriptors for a registry record. Exactly one descriptor field is populated based on the record type.

    " + }, + "DiscoveryConfiguration":{ + "type":"structure", + "members":{ + "authorizerConfiguration":{ + "shape":"AuthorizerConfiguration", + "documentation":"

    The authorizer configuration for the registry. Required when authorizerType is CUSTOM_JWT.

    " + }, + "authorizerType":{ + "shape":"RegistryAuthorizerType", + "documentation":"

    The type of authorizer that controls how consumers access the registry's search and MCP invoke operations.

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

    Discovery configuration for the registry. Controls how consumers are authorized to search the registry and invoke its MCP endpoint.

    " + }, + "DiscoveryUrl":{ + "type":"string", + "documentation":"

    The OpenID Connect discovery URL, ending in /.well-known/openid-configuration, used to retrieve the identity provider's metadata and signing keys.

    ", + "max":2048, + "min":1, + "pattern":".+/\\.well-known/openid-configuration" + }, + "EncryptionConfiguration":{ + "type":"structure", + "required":["kmsKeyArn"], + "members":{ + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the customer-managed Amazon Web Services KMS key used to encrypt the registry's content. The key must be a symmetric encryption key in the same Amazon Web Services account and Region as the registry.

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

    The server-side encryption configuration for a registry. Specifies a customer-managed Amazon Web Services KMS key used to encrypt the registry's content.

    " + }, + "EndpointIpAddressType":{ + "type":"string", + "documentation":"

    The IP address type used by a private endpoint.

    ", + "enum":[ + "IPV4", + "IPV6" + ] + }, + "FilterValue":{ + "type":"string", + "documentation":"

    A single filter value. Constrained by length only; the accepted set of values is filter-specific and validated server-side so enum-style values such as READY or AWS_IAM are accepted.

    ", + "max":255, + "min":1 + }, + "FilterValues":{ + "type":"list", + "member":{"shape":"FilterValue"}, + "documentation":"

    The values supplied for a single filter.

    ", + "max":1, + "min":1 + }, + "GetRegistryRecordRequest":{ + "type":"structure", + "required":[ + "registryId", + "recordId" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry containing the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the registry record to retrieve (ARN or ID)

    ", + "location":"uri", + "locationName":"recordId" + } + } + }, + "GetRegistryRecordResponse":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "name", + "recordType", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The Amazon Resource Name (ARN) of the parent registry that owns the record.

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The Amazon Resource Name (ARN) of the registry record.

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The unique identifier of the registry record.

    " + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record. Names are unique within a registry.

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A description of the registry record.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record, such as MCP, AGENT, SKILL, or CUSTOM.

    " + }, + "descriptors":{ + "shape":"Descriptors", + "documentation":"

    The typed descriptors that define the content of the registry record.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version identifier of the registry record.

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The lifecycle status of the registry record.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was last updated.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the current status. Typically populated when the status indicates a failure state.

    " + }, + "provenance":{"shape":"ProvenanceList"}, + "createdByAutoDetection":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the registry record was created by auto-detection. true indicates the record was automatically created by the service based on the registry's auto-detection configuration; false indicates the record was created through a control-plane API call.

    " + }, + "createdBy":{ + "shape":"CreatorAccountId", + "documentation":"

    The ID of the Amazon Web Services account that created the registry record.

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

    Response structure for retrieving a registry record

    " + }, + "GetRegistryRequest":{ + "type":"structure", + "required":["registryId"], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry to retrieve (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + } + }, + "documentation":"

    Request structure for getting a registry

    " + }, + "GetRegistryResponse":{ + "type":"structure", + "required":[ + "name", + "registryId", + "registryArn", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "name":{ + "shape":"RegistryName", + "documentation":"

    The name of the registry

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the registry

    " + }, + "registryId":{ + "shape":"RegistryId", + "documentation":"

    The unique identifier of the registry

    " + }, + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The ARN of the registry

    " + }, + "discoveryConfiguration":{ + "shape":"DiscoveryConfiguration", + "documentation":"

    Discovery configuration for the registry

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The server-side encryption configuration for the registry. Appears only when a customer-managed Amazon Web Services KMS key encrypts the registry.

    " + }, + "approvalConfiguration":{ + "shape":"ApprovalConfiguration", + "documentation":"

    Approval configuration for registry records

    " + }, + "status":{ + "shape":"RegistryStatus", + "documentation":"

    Current status of the registry

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the current status. Typically populated when the status indicates a failure state.

    " + }, + "autoDetection":{ + "shape":"AutoDetection", + "documentation":"

    The registry's auto-detection properties, including the requested configuration and the current detection status. Present only when auto-detection was configured for the registry.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was created

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was last updated

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

    Response structure for getting a registry

    " + }, + "HttpDescriptor":{ + "type":"structure", + "members":{ + "source":{"shape":"DescriptorSource"} + }, + "documentation":"

    A registry record descriptor for the HTTP protocol. This descriptor is source-only: its content is synchronized from the configured source URL rather than supplied inline.

    " + }, + "IamRoleArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:iam::[0-9]{12}:role/.+" + }, + "IamSigningRegion":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "IamSigningServiceName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "InboundTokenClaimNameType":{ + "type":"string", + "documentation":"

    The name of a claim in an inbound JWT.

    ", + "max":255, + "min":1, + "pattern":"[A-Za-z0-9_.-:]+" + }, + "InboundTokenClaimValueType":{ + "type":"string", + "documentation":"

    The value type of a claim in an inbound JWT.

    ", + "enum":[ + "STRING", + "STRING_ARRAY" + ] + }, + "InternalServerException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request failed due to an unexpected internal error; the caller may retry.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, + "KmsKeyArn":{ + "type":"string", + "documentation":"

    A KMS key ARN

    ", + "max":2048, + "min":1, + "pattern":"arn:aws(|-cn|-us-gov):kms:[a-zA-Z0-9-]*:[0-9]{12}:key/[a-zA-Z0-9-]{36}" + }, + "ListRegistriesRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    Maximum number of results to return

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Token for pagination

    " + }, + "filters":{ + "shape":"RegistryFilterList", + "documentation":"

    Filters to apply to the registry list

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

    Request structure for listing registries

    " + }, + "ListRegistriesResponse":{ + "type":"structure", + "required":["registries"], + "members":{ + "registries":{ + "shape":"RegistrySummaryList", + "documentation":"

    List of registry summaries

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Token for next page of results

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

    Response structure for listing registries

    " + }, + "ListRegistryRecordsRequest":{ + "type":"structure", + "required":["registryId"], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry to list records from (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    Maximum number of records to return

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Token for pagination

    " + }, + "filters":{ + "shape":"RegistryRecordFilterList", + "documentation":"

    Filters to apply to the registry record list

    " + } + } + }, + "ListRegistryRecordsResponse":{ + "type":"structure", + "required":["registryRecords"], + "members":{ + "registryRecords":{ + "shape":"RegistryRecordSummaryList", + "documentation":"

    List of registry record summaries

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Token for next page of results

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

    Response structure for listing registry records

    " + }, + "ListTagsForResourceRequest":{ + "type":"structure", + "required":["resourceArn"], + "members":{ + "resourceArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource to list tags for. Supported resources include registries and registry records.

    ", + "location":"uri", + "locationName":"resourceArn" + } + } + }, + "ListTagsForResourceResponse":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"ResourceTagsMap", + "documentation":"

    The tags currently associated with the resource, as a map of tag keys to tag values.

    " + } + } + }, + "ManagedVpcResource":{ + "type":"structure", + "required":[ + "vpcIdentifier", + "subnetIds", + "endpointIpAddressType" + ], + "members":{ + "vpcIdentifier":{ + "shape":"VpcIdentifier", + "documentation":"

    The identifier of the VPC in which the private endpoint is provisioned.

    " + }, + "subnetIds":{ + "shape":"SubnetIds", + "documentation":"

    The identifiers of the subnets in which the private endpoint network interfaces are placed.

    " + }, + "endpointIpAddressType":{ + "shape":"EndpointIpAddressType", + "documentation":"

    The IP address type used by the private endpoint, either IPV4 or IPV6.

    " + }, + "securityGroupIds":{ + "shape":"SecurityGroupIds", + "documentation":"

    The identifiers of the security groups associated with the private endpoint network interfaces.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags applied to the service-managed VPC resource.

    " + }, + "routingDomain":{ + "shape":"RoutingDomain", + "documentation":"

    The routing domain used to resolve traffic through the private endpoint.

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

    A service-managed private endpoint provisioned within a customer VPC.

    " + }, + "MatchValueString":{ + "type":"string", + "documentation":"

    A single value used to match a claim during JWT validation.

    ", + "max":255, + "min":1, + "pattern":"[A-Za-z0-9_.:/-]+" + }, + "MatchValueStringList":{ + "type":"list", + "member":{"shape":"MatchValueString"}, + "documentation":"

    A list of values used to match a claim during JWT validation.

    ", + "min":1 + }, + "MaxResults":{ + "type":"integer", + "documentation":"

    Maximum number of items to be listed

    ", + "box":true, + "max":100, + "min":1 + }, + "McpServerAdditionalData":{ + "type":"structure", + "members":{ + "tools":{ + "shape":"McpToolsDescriptor", + "documentation":"

    The MCP tools descriptor that defines the tools exposed by the MCP server.

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

    Additional data for an MCP server descriptor

    " + }, + "McpServerDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The MCP server descriptor content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

    " + }, + "additionalData":{ + "shape":"McpServerAdditionalData", + "documentation":"

    Additional data associated with the MCP server descriptor, such as tool definitions.

    " + }, + "source":{ + "shape":"DescriptorSource", + "documentation":"

    The optional source configuration used to synchronize the MCP server descriptor content.

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

    Descriptor that defines the content of an MCP (Model Context Protocol) server registry record, including the server definition and its tool definitions. The content is validated against the MCP protocol schema.

    " + }, + "McpToolsDescriptor":{ + "type":"structure", + "members":{ + "data":{ + "shape":"DescriptorData", + "documentation":"

    The MCP tools descriptor content, serialized as descriptor payload data.

    " + }, + "dataSchemaVersion":{ + "shape":"DataSchemaVersion", + "documentation":"

    The schema version of the descriptor payload.

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

    MCP tools descriptor containing tool definitions

    " + }, + "NextToken":{ + "type":"string", + "documentation":"

    Opaque continuation token of previous paginated response

    ", + "max":2048, + "min":1, + "pattern":"\\S*" + }, + "NonBlankString":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"[\\s\\S]+" + }, + "PrivateEndpoint":{ + "type":"structure", + "members":{ + "selfManagedLatticeResource":{ + "shape":"SelfManagedLatticeResource", + "documentation":"

    A private endpoint backed by a self-managed VPC Lattice resource configuration.

    " + }, + "managedVpcResource":{ + "shape":"ManagedVpcResource", + "documentation":"

    A private endpoint backed by a service-managed VPC resource.

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

    A private network endpoint used to reach a resource over a private path. Exactly one member is set.

    ", + "union":true + }, + "PrivateEndpointOverride":{ + "type":"structure", + "required":[ + "domain", + "privateEndpoint" + ], + "members":{ + "domain":{ + "shape":"PrivateEndpointOverrideDomain", + "documentation":"

    The domain name to which this private endpoint override applies.

    " + }, + "privateEndpoint":{ + "shape":"PrivateEndpoint", + "documentation":"

    The private endpoint used to reach the specified domain.

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

    A mapping of a domain to the private endpoint used to reach it.

    " + }, + "PrivateEndpointOverrideDomain":{ + "type":"string", + "documentation":"

    A domain name for which a specific private endpoint override applies.

    ", + "max":253, + "min":1 + }, + "PrivateEndpointOverrides":{ + "type":"list", + "member":{"shape":"PrivateEndpointOverride"}, + "documentation":"

    The list of per-domain private endpoint overrides.

    ", + "max":5, + "min":0 + }, + "Provenance":{ + "type":"structure", + "required":[ + "relation", + "sourceId" + ], + "members":{ + "relation":{"shape":"ProvenanceRelation"}, + "sourceId":{ + "shape":"SourceId", + "documentation":"

    The identifier of the upstream source that the registry record was detected from.

    " + }, + "sourceType":{ + "shape":"SourceType", + "documentation":"

    The type of the upstream source that the registry record was detected from.

    " + }, + "sourceDetails":{ + "shape":"SourceDetails", + "documentation":"

    Additional details about the upstream source that the registry record was detected from, such as the AgentCore Gateway or Runtime configuration. The populated member corresponds to the source type.

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

    One provenance entry describing the lineage of a registry record.

    " + }, + "ProvenanceList":{ + "type":"list", + "member":{"shape":"Provenance"}, + "documentation":"

    List of provenance entries on a registry record. Capped at one entry today: a record carries a single DETECTED_FROM lineage. Modeled as a list so additional relations can be unlocked post-GA by raising this bound without a breaking shape change.

    ", + "max":1, + "min":0 + }, + "ProvenanceRelation":{ + "type":"string", + "documentation":"

    The relationship between the registry record and its provenance source.

    ", + "enum":["DETECTED_FROM"] + }, + "ProvenanceSummary":{ + "type":"structure", + "required":[ + "relation", + "sourceId" + ], + "members":{ + "relation":{"shape":"ProvenanceRelation"}, + "sourceId":{ + "shape":"SourceId", + "documentation":"

    The identifier of the upstream source that the registry record was detected from.

    " + }, + "sourceType":{ + "shape":"SourceType", + "documentation":"

    The type of the upstream source that the registry record was detected from.

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

    Condensed provenance entry for list results — the key triple only (no sourceDetails union). Enough to display and client-side-filter lineage without the full-read config payload.

    " + }, + "ProvenanceSummaryList":{ + "type":"list", + "member":{"shape":"ProvenanceSummary"}, + "documentation":"

    List of condensed provenance entries surfaced on RegistryRecordSummary. Mirrors ProvenanceList's cardinality (one entry today); modeled as a list for forward-compatibility.

    ", + "max":1, + "min":0 + }, + "RecordIdentifier":{ + "type":"string", + "documentation":"

    Record identifier that accepts either ARN or ID format

    ", + "max":2048, + "min":1, + "pattern":"(arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}/record/)?[a-zA-Z0-9]{12}" + }, + "RecordType":{ + "type":"string", + "documentation":"

    Record type enum for registry record classification

    ", + "enum":[ + "MCP", + "AGENT", + "CUSTOM", + "SKILL", + "GATEWAY" + ] + }, + "RegistryArn":{ + "type":"string", + "documentation":"

    Registry Amazon Resource Name

    ", + "max":2048, + "min":46, + "pattern":"arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}" + }, + "RegistryAuthorizerType":{ + "type":"string", + "enum":[ + "CUSTOM_JWT", + "AWS_IAM" + ] + }, + "RegistryFilter":{ + "type":"structure", + "required":[ + "name", + "values" + ], + "members":{ + "name":{ + "shape":"RegistryFilterName", + "documentation":"

    The attribute to filter on

    " + }, + "values":{ + "shape":"FilterValues", + "documentation":"

    The values to match for the attribute

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

    A single filter applied to a ListRegistries request.

    " + }, + "RegistryFilterList":{ + "type":"list", + "member":{"shape":"RegistryFilter"}, + "max":10, + "min":0 + }, + "RegistryFilterName":{ + "type":"string", + "enum":[ + "status", + "discoveryConfiguration.authorizerType" + ] + }, + "RegistryId":{ + "type":"string", + "documentation":"

    Registry unique identifier - 12-character alphanumeric string

    ", + "max":16, + "min":12, + "pattern":"[a-zA-Z0-9]{12,16}" + }, + "RegistryIdentifier":{ + "type":"string", + "documentation":"

    Registry identifier that accepts either ARN or ID format

    ", + "max":2048, + "min":1, + "pattern":"(arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/)?[a-zA-Z0-9]{12,16}" + }, + "RegistryName":{ + "type":"string", + "documentation":"

    Registry name with validation pattern

    ", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9_\\-\\.\\/]*" + }, + "RegistryRecordArn":{ + "type":"string", + "documentation":"

    Registry Record Amazon Resource Name

    ", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:agent-registry:[a-z0-9-]+:[0-9]{12}:registry/[a-zA-Z0-9]{12,16}/record/[a-zA-Z0-9]{12}" + }, + "RegistryRecordCredentialProviderConfiguration":{ + "type":"structure", + "required":[ + "credentialProviderType", + "credentialProvider" + ], + "members":{ + "credentialProviderType":{ + "shape":"RegistryRecordCredentialProviderType", + "documentation":"

    The type of credential provider.

    " + }, + "credentialProvider":{ + "shape":"RegistryRecordCredentialProviderUnion", + "documentation":"

    The credential provider details corresponding to the specified credential provider type.

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

    A credential provider configuration that specifies how to authenticate when fetching descriptor content from a registry record's source URL.

    " + }, + "RegistryRecordCredentialProviderConfigurationList":{ + "type":"list", + "member":{"shape":"RegistryRecordCredentialProviderConfiguration"}, + "max":1, + "min":0 + }, + "RegistryRecordCredentialProviderType":{ + "type":"string", + "enum":[ + "OAUTH", + "IAM" + ] + }, + "RegistryRecordCredentialProviderUnion":{ + "type":"structure", + "members":{ + "oauthCredentialProvider":{ + "shape":"RegistryRecordOAuthCredentialProvider", + "documentation":"

    The OAuth 2.0 credential provider details.

    " + }, + "iamCredentialProvider":{ + "shape":"RegistryRecordIamCredentialProvider", + "documentation":"

    The IAM role credential provider details.

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

    The credential provider details for a registry record. Exactly one member is populated, matching the configured credential provider type.

    ", + "union":true + }, + "RegistryRecordDisplayName":{ + "type":"string", + "documentation":"

    Display name for a registry record

    ", + "max":255, + "min":1 + }, + "RegistryRecordFilter":{ + "type":"structure", + "required":[ + "name", + "values" + ], + "members":{ + "name":{ + "shape":"RegistryRecordFilterName", + "documentation":"

    The attribute to filter on

    " + }, + "values":{ + "shape":"FilterValues", + "documentation":"

    The values to match for the attribute

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

    A single filter applied to a ListRegistryRecords request.

    " + }, + "RegistryRecordFilterList":{ + "type":"list", + "member":{"shape":"RegistryRecordFilter"}, + "max":10, + "min":0 + }, + "RegistryRecordFilterName":{ + "type":"string", + "enum":[ + "name", + "status", + "recordType" + ] + }, + "RegistryRecordIamCredentialProvider":{ + "type":"structure", + "members":{ + "roleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role to assume for request signing.

    " + }, + "service":{ + "shape":"IamSigningServiceName", + "documentation":"

    The service name to use for request signing, such as execute-api.

    " + }, + "region":{ + "shape":"IamSigningRegion", + "documentation":"

    The Amazon Web Services Region to use for request signing. If not specified, the Region is derived from the source URL hostname, falling back to the Region of the registry.

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

    The configuration for an IAM role credential provider that signs requests to a registry record's source with Amazon Web Services Signature Version 4 (SigV4).

    " + }, + "RegistryRecordId":{ + "type":"string", + "documentation":"

    Registry Record unique identifier - 12-character alphanumeric string

    ", + "max":12, + "min":12, + "pattern":"[a-zA-Z0-9]{12}" + }, + "RegistryRecordName":{ + "type":"string", + "documentation":"

    Registry Record name

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9_\\-\\.\\/]*" + }, + "RegistryRecordOAuthCredentialProvider":{ + "type":"structure", + "required":["providerArn"], + "members":{ + "providerArn":{ + "shape":"CredentialProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the OAuth 2.0 credential provider resource in Amazon Bedrock AgentCore Identity.

    " + }, + "grantType":{ + "shape":"RegistryRecordOAuthGrantType", + "documentation":"

    The OAuth 2.0 grant type used to obtain access tokens.

    " + }, + "scopes":{ + "shape":"ScopeList", + "documentation":"

    The OAuth 2.0 scopes to request when obtaining access tokens.

    " + }, + "customParameters":{ + "shape":"CustomParameterMap", + "documentation":"

    Additional parameters to include in the OAuth 2.0 token request.

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

    The configuration for an OAuth 2.0 credential provider that authenticates requests to a registry record's source.

    " + }, + "RegistryRecordOAuthGrantType":{ + "type":"string", + "enum":["CLIENT_CREDENTIALS"] + }, + "RegistryRecordStatus":{ + "type":"string", + "documentation":"

    Registry record status

    ", + "enum":[ + "DRAFT", + "PENDING_APPROVAL", + "APPROVED", + "REJECTED", + "DEPRECATED", + "CREATING", + "UPDATING", + "CREATE_FAILED", + "UPDATE_FAILED" + ] + }, + "RegistryRecordSummary":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "name", + "recordType", + "recordVersion", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The Amazon Resource Name (ARN) of the parent registry that owns the record.

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The Amazon Resource Name (ARN) of the registry record.

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The unique identifier of the registry record.

    " + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record. Names are unique within a registry.

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A description of the registry record.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record, such as MCP, AGENT, SKILL, or CUSTOM.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version identifier of the registry record.

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The lifecycle status of the registry record.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was last updated.

    " + }, + "createdByAutoDetection":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the registry record was created by auto-detection. true indicates the record was automatically created by the service based on the registry's auto-detection configuration; false indicates the record was created through a control-plane API call.

    " + }, + "createdBy":{ + "shape":"CreatorAccountId", + "documentation":"

    The ID of the Amazon Web Services account that created the registry record.

    " + }, + "provenanceSummaryList":{"shape":"ProvenanceSummaryList"} + }, + "documentation":"

    A summary of a registry record returned by list operations. Contains identifying and lifecycle fields but omits descriptor content.

    " + }, + "RegistryRecordSummaryList":{ + "type":"list", + "member":{"shape":"RegistryRecordSummary"} + }, + "RegistryRecordVersion":{ + "type":"string", + "documentation":"

    Version of the registry record

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9.-]+" + }, + "RegistryStatus":{ + "type":"string", + "enum":[ + "CREATING", + "READY", + "UPDATING", + "CREATE_FAILED", + "UPDATE_FAILED", + "DELETING", + "DELETE_FAILED" + ] + }, + "RegistrySummary":{ + "type":"structure", + "required":[ + "name", + "registryId", + "registryArn", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "name":{ + "shape":"RegistryName", + "documentation":"

    Registry name

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    Registry description

    " + }, + "registryId":{ + "shape":"RegistryId", + "documentation":"

    Unique registry identifier

    " + }, + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    Registry Amazon Resource Name

    " + }, + "discoveryConfiguration":{ + "shape":"DiscoveryConfiguration", + "documentation":"

    Discovery configuration for the registry

    " + }, + "status":{ + "shape":"RegistryStatus", + "documentation":"

    Current status of the registry

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the current status. Typically populated when the status indicates a failure state.

    " + }, + "autoDetection":{ + "shape":"AutoDetection", + "documentation":"

    The registry's auto-detection properties, including the requested configuration and the current detection status. Present only when auto-detection was configured for the registry.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was created

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was last updated

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

    Registry summary for list operations

    " + }, + "RegistrySummaryList":{ + "type":"list", + "member":{"shape":"RegistrySummary"} + }, + "ResourceArn":{ + "type":"string", + "documentation":"

    ARN of a taggable Agent Registry resource.

    ", + "max":1011, + "min":1 + }, + "ResourceConfigurationIdentifier":{ + "type":"string", + "documentation":"

    The identifier of a VPC Lattice resource configuration, specified as a resource configuration ID or ARN.

    ", + "max":2048, + "min":20, + "pattern":"((rcfg-[0-9a-z]{17})|(arn:[a-z0-9\\-]+:vpc-lattice:[a-zA-Z0-9\\-]+:\\d{12}:resourceconfiguration/rcfg-[0-9a-z]{17}))" + }, + "ResourceNotFoundException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The requested resource was not found.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "ResourceTagsMap":{ + "type":"map", + "key":{"shape":"TagKey"}, + "value":{"shape":"TagValue"}, + "documentation":"

    A map of tag keys to tag values returned by read operations (may be empty).

    ", + "max":50, + "min":0 + }, + "RoutingDomain":{ + "type":"string", + "documentation":"

    The routing domain used to resolve traffic through a private endpoint.

    ", + "max":255, + "min":3 + }, + "ScopeList":{ + "type":"list", + "member":{"shape":"String"} + }, + "SecurityGroupIdentifier":{ + "type":"string", + "documentation":"

    The identifier of a security group.

    ", + "max":48, + "min":10, + "pattern":"sg-(([0-9a-z]{8})|([0-9a-z]{17}))" + }, + "SecurityGroupIds":{ + "type":"list", + "member":{"shape":"SecurityGroupIdentifier"}, + "documentation":"

    The list of security group identifiers associated with a private endpoint.

    ", + "max":5, + "min":0 + }, + "SelfManagedLatticeResource":{ + "type":"structure", + "members":{ + "resourceConfigurationIdentifier":{ + "shape":"ResourceConfigurationIdentifier", + "documentation":"

    The identifier of the VPC Lattice resource configuration, specified as a resource configuration ID or ARN.

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

    A self-managed private endpoint backed by a VPC Lattice resource configuration. Exactly one member is set.

    ", + "union":true + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request would exceed a service quota.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "SourceDetails":{ + "type":"structure", + "members":{ + "agentcoreRuntime":{"shape":"AgentCoreRuntimeSourceDetails"}, + "agentcoreGateway":{"shape":"AgentCoreGatewaySourceDetails"} + }, + "documentation":"

    The details about the upstream source from which a registry record was detected. Exactly one member is populated, corresponding to the source type.

    ", + "union":true + }, + "SourceId":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:[a-zA-Z0-9-]+:[a-z0-9-]*:[0-9]{12}:.+" + }, + "SourceType":{ + "type":"string", + "enum":[ + "AWS::BedrockAgentCore::Runtime", + "AWS::BedrockAgentCore::Gateway" + ] + }, + "String":{"type":"string"}, + "SubmitRegistryRecordForApprovalRequest":{ + "type":"structure", + "required":[ + "registryId", + "recordId" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry containing the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the registry record to submit for approval (ARN or ID)

    ", + "location":"uri", + "locationName":"recordId" + } + } + }, + "SubmitRegistryRecordForApprovalResponse":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "status", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The ARN of the registry

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The ARN of the registry record

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The ID of the registry record

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The resulting status of the registry record

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the record was last updated

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

    Response structure for submitting a registry record for approval

    " + }, + "SubnetId":{ + "type":"string", + "documentation":"

    Subnet identifier

    ", + "max":24, + "min":15, + "pattern":"subnet-[0-9a-zA-Z]{8,17}" + }, + "SubnetIds":{ + "type":"list", + "member":{"shape":"SubnetId"}, + "documentation":"

    The list of subnet identifiers in which the private endpoint network interfaces are placed.

    " + }, + "TagKey":{ + "type":"string", + "documentation":"

    Key of a tag.

    ", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9\\s._:/=+@-]*" + }, + "TagKeyList":{ + "type":"list", + "member":{"shape":"TagKey"}, + "documentation":"

    A list of tag keys.

    ", + "max":50, + "min":1 + }, + "TagResourceRequest":{ + "type":"structure", + "required":[ + "resourceArn", + "tags" + ], + "members":{ + "resourceArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource to tag. Supported resources include registries and registry records.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags to apply to the resource, as a map of tag keys to tag values. Tag keys must be unique within the request.

    " + } + } + }, + "TagResourceResponse":{ + "type":"structure", + "members":{} + }, + "TagValue":{ + "type":"string", + "documentation":"

    Value of a tag.

    ", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9\\s._:/=+@-]*" + }, + "TagsMap":{ + "type":"map", + "key":{"shape":"TagKey"}, + "value":{"shape":"TagValue"}, + "documentation":"

    A map of tag keys to tag values.

    ", + "max":50, + "min":1 + }, + "ThrottlingException":{ + "type":"structure", + "members":{ + "message":{"shape":"NonBlankString"} + }, + "documentation":"

    The request was denied due to request throttling; the caller may retry after a delay.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true + }, + "UntagResourceRequest":{ + "type":"structure", + "required":[ + "resourceArn", + "tagKeys" + ], + "members":{ + "resourceArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource to remove tags from. Supported resources include registries and registry records.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tagKeys":{ + "shape":"TagKeyList", + "documentation":"

    The keys of the tags to remove from the resource. Tags with keys not included in this list remain on the resource.

    ", + "location":"querystring", + "locationName":"tagKeys" + } + } + }, + "UntagResourceResponse":{ + "type":"structure", + "members":{} + }, + "UpdateRegistryRecordRequest":{ + "type":"structure", + "required":[ + "registryId", + "recordId" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry containing the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the registry record to update (ARN or ID)

    ", + "location":"uri", + "locationName":"recordId" + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The updated name of the registry record. Omit to leave the name unchanged.

    " + }, + "displayName":{ + "shape":"UpdatedDisplayName", + "documentation":"

    The updated display name of the registry record. Omit to leave the display name unchanged; provide an empty wrapper to unset it.

    " + }, + "description":{ + "shape":"UpdatedDescription", + "documentation":"

    The updated description of the registry record. Omit to leave the description unchanged; provide an empty wrapper to unset it.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The updated type of the registry record. Omit to leave the record type unchanged.

    " + }, + "descriptors":{ + "shape":"UpdatedDescriptors", + "documentation":"

    The updated typed descriptor content for the registry record. Omit to leave the descriptors unchanged.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The updated version of the registry record. Omit to leave the version unchanged.

    " + }, + "triggerSynchronization":{ + "shape":"Boolean", + "documentation":"

    Whether to trigger synchronization of the record's descriptor content from its source

    " + }, + "provenance":{"shape":"ProvenanceList"} + } + }, + "UpdateRegistryRecordResponse":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "name", + "recordType", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The Amazon Resource Name (ARN) of the parent registry that owns the record.

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The Amazon Resource Name (ARN) of the registry record.

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The unique identifier of the registry record.

    " + }, + "name":{ + "shape":"RegistryRecordName", + "documentation":"

    The name of the registry record. Names are unique within a registry.

    " + }, + "displayName":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The human-readable display name of the registry record.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A description of the registry record.

    " + }, + "recordType":{ + "shape":"RecordType", + "documentation":"

    The type of the registry record, such as MCP, AGENT, SKILL, or CUSTOM.

    " + }, + "descriptors":{ + "shape":"Descriptors", + "documentation":"

    The typed descriptors that define the content of the registry record.

    " + }, + "recordVersion":{ + "shape":"RegistryRecordVersion", + "documentation":"

    The version identifier of the registry record.

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The lifecycle status of the registry record.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry record was last updated.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the current status. Typically populated when the status indicates a failure state.

    " + }, + "provenance":{"shape":"ProvenanceList"}, + "createdByAutoDetection":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the registry record was created by auto-detection. true indicates the record was automatically created by the service based on the registry's auto-detection configuration; false indicates the record was created through a control-plane API call.

    " + }, + "createdBy":{ + "shape":"CreatorAccountId", + "documentation":"

    The ID of the Amazon Web Services account that created the registry record.

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

    Response structure for updating a registry record

    " + }, + "UpdateRegistryRecordStatusRequest":{ + "type":"structure", + "required":[ + "registryId", + "recordId", + "status", + "statusReason" + ], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry containing the record (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "recordId":{ + "shape":"RecordIdentifier", + "documentation":"

    The identifier of the registry record to update the status of (ARN or ID)

    ", + "location":"uri", + "locationName":"recordId" + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The target status for the registry record

    " + }, + "statusReason":{ + "shape":"UpdateRegistryRecordStatusRequestStatusReasonString", + "documentation":"

    The reason for the status change, for example why the record was approved, rejected, or deprecated

    " + } + } + }, + "UpdateRegistryRecordStatusRequestStatusReasonString":{ + "type":"string", + "max":255, + "min":0 + }, + "UpdateRegistryRecordStatusResponse":{ + "type":"structure", + "required":[ + "registryArn", + "recordArn", + "recordId", + "status", + "statusReason", + "updatedAt" + ], + "members":{ + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The ARN of the registry

    " + }, + "recordArn":{ + "shape":"RegistryRecordArn", + "documentation":"

    The ARN of the registry record

    " + }, + "recordId":{ + "shape":"RegistryRecordId", + "documentation":"

    The ID of the registry record

    " + }, + "status":{ + "shape":"RegistryRecordStatus", + "documentation":"

    The resulting status of the registry record

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the status change

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the record was last updated

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

    Response structure for updating a registry record status

    " + }, + "UpdateRegistryRequest":{ + "type":"structure", + "required":["registryId"], + "members":{ + "registryId":{ + "shape":"RegistryIdentifier", + "documentation":"

    The identifier of the registry to update (ARN or ID)

    ", + "location":"uri", + "locationName":"registryId" + }, + "name":{ + "shape":"RegistryName", + "documentation":"

    The updated name of the registry

    " + }, + "description":{ + "shape":"UpdatedDescription", + "documentation":"

    The updated description of the registry

    " + }, + "discoveryConfiguration":{ + "shape":"UpdatedDiscoveryConfiguration", + "documentation":"

    The updated discovery configuration. Changing the discovery authorization can break existing consumers that rely on the previous authorization type.

    " + }, + "approvalConfiguration":{ + "shape":"UpdatedApprovalConfiguration", + "documentation":"

    The updated approval configuration. The change applies only to records that move to PENDING_APPROVAL after the update; records already in PENDING_APPROVAL are unaffected.

    " + }, + "autoDetectionConfiguration":{ + "shape":"UpdatedAutoDetectionConfiguration", + "documentation":"

    The updated auto-detection configuration for the registry, with PATCH semantics. Omit this field to leave the current configuration unchanged. Supply an empty wrapper to unset it. Supply optionalValue to replace it.

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

    Request structure for updating a registry

    " + }, + "UpdateRegistryResponse":{ + "type":"structure", + "required":[ + "name", + "registryId", + "registryArn", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "name":{ + "shape":"RegistryName", + "documentation":"

    The name of the registry

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the registry

    " + }, + "registryId":{ + "shape":"RegistryId", + "documentation":"

    The unique identifier of the registry

    " + }, + "registryArn":{ + "shape":"RegistryArn", + "documentation":"

    The ARN of the registry

    " + }, + "discoveryConfiguration":{ + "shape":"DiscoveryConfiguration", + "documentation":"

    Discovery configuration for the registry

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The server-side encryption configuration for the registry. Appears only when a customer-managed Amazon Web Services KMS key encrypts the registry.

    " + }, + "approvalConfiguration":{ + "shape":"ApprovalConfiguration", + "documentation":"

    Approval configuration for registry records

    " + }, + "status":{ + "shape":"RegistryStatus", + "documentation":"

    Current status of the registry

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    The reason for the current status. Typically populated when the status indicates a failure state.

    " + }, + "autoDetection":{ + "shape":"AutoDetection", + "documentation":"

    The registry's auto-detection properties, including the requested configuration and the current detection status. Present only when auto-detection was configured for the registry.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was created

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the registry was last updated

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

    Response structure for updating a registry

    " + }, + "UpdatedA2aAgentCardDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedA2aAgentCardDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The A2A agent card descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedA2aAgentCardDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

    " + }, + "dataSchemaVersion":{ + "shape":"UpdatedDataSchemaVersion", + "documentation":"

    The patch for the descriptor's data schema version field.

    " + }, + "source":{ + "shape":"UpdatedDescriptorSource", + "documentation":"

    The patch for the descriptor's source field.

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

    The set of A2A agent card descriptor fields that can be individually updated.

    " + }, + "UpdatedAgUiDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedAgUiDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The AG-UI descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedAgUiDescriptorFields":{ + "type":"structure", + "members":{ + "source":{ + "shape":"UpdatedDescriptorSource", + "documentation":"

    The patch for the descriptor's source field.

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

    The set of AG-UI descriptor fields that can be individually updated.

    " + }, + "UpdatedAgentSkillsAdditionalData":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedAgentSkillsAdditionalDataFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The agent skills additional-data patch wrapper. Omit to leave the additional data unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedAgentSkillsAdditionalDataFields":{ + "type":"structure", + "members":{ + "skillMd":{ + "shape":"UpdatedAgentSkillsMdDescriptor", + "documentation":"

    The patch for the agent skills markdown descriptor field.

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

    The set of agent skills additional-data fields that can be individually updated.

    " + }, + "UpdatedAgentSkillsDefinitionDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedAgentSkillsDefinitionDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The agent skills definition descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedAgentSkillsDefinitionDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

    " + }, + "dataSchemaVersion":{ + "shape":"UpdatedDataSchemaVersion", + "documentation":"

    The patch for the descriptor's data schema version field.

    " + }, + "additionalData":{ + "shape":"UpdatedAgentSkillsAdditionalData", + "documentation":"

    The patch for the descriptor's additional data field.

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

    The set of agent skills definition descriptor fields that can be individually updated.

    " + }, + "UpdatedAgentSkillsMdDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedAgentSkillsMdDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The agent skills markdown descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedAgentSkillsMdDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

    " + }, + "dataSchemaVersion":{ + "shape":"UpdatedDataSchemaVersion", + "documentation":"

    The patch for the descriptor's data schema version field.

    " + }, + "source":{ + "shape":"UpdatedDescriptorSource", + "documentation":"

    The patch for the descriptor's source field.

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

    The set of agent skills markdown descriptor fields that can be individually updated.

    " + }, + "UpdatedApprovalConfiguration":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"ApprovalConfiguration", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    A wrapper for updating the approval configuration of a registry. Include this wrapper to replace the approval configuration with the specified value; omit it to leave the approval configuration unchanged.

    " + }, + "UpdatedAuthorizerConfiguration":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"AuthorizerConfiguration", + "documentation":"

    The new authorizer configuration to set. Omit to leave the existing configuration unchanged.

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

    Wrapper for updating an optional authorizer configuration with PATCH semantics.

    " + }, + "UpdatedAutoDetectionConfiguration":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"AutoDetectionConfiguration", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    A wrapper for updating the auto-detection configuration of a registry with PATCH semantics. Include this wrapper to replace the auto-detection configuration with the specified value. Omit it to leave the auto-detection configuration unchanged. To clear the configuration, include the wrapper with a null optionalValue.

    " + }, + "UpdatedCustomDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedCustomDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The custom descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedCustomDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

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

    The set of custom descriptor fields that can be individually updated.

    " + }, + "UpdatedDataSchemaVersion":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"DataSchemaVersion", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    Leaf patch wrapper for a descriptor's data schema version. Omit to leave unchanged; supply an empty object to unset; supply optionalValue to set.

    " + }, + "UpdatedDescription":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"Description", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    Wrapper for updating an optional Description field with PATCH semantics

    " + }, + "UpdatedDescriptorData":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"DescriptorData", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    Leaf patch wrapper for descriptor data. Omit to leave unchanged; supply an empty object to unset; supply optionalValue to set.

    " + }, + "UpdatedDescriptorSource":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"DescriptorSource", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    Leaf patch wrapper for a descriptor's source configuration. Omit to leave unchanged; supply an empty object to unset; supply optionalValue to set.

    " + }, + "UpdatedDescriptors":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedDescriptorsFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The top-level descriptors patch wrapper used in UpdateRegistryRecord. Omit to leave the current descriptors unchanged; supply an empty object to clear them; supply optionalValue to apply a per-field patch.

    " + }, + "UpdatedDescriptorsFields":{ + "type":"structure", + "members":{ + "mcpServer":{ + "shape":"UpdatedMcpServerDescriptor", + "documentation":"

    The patch for the MCP server descriptor.

    " + }, + "a2aAgentCard":{ + "shape":"UpdatedA2aAgentCardDescriptor", + "documentation":"

    The patch for the A2A agent card descriptor.

    " + }, + "agentSkillsDefinition":{ + "shape":"UpdatedAgentSkillsDefinitionDescriptor", + "documentation":"

    The patch for the agent skills definition descriptor.

    " + }, + "custom":{ + "shape":"UpdatedCustomDescriptor", + "documentation":"

    The patch for the custom descriptor.

    " + }, + "http":{ + "shape":"UpdatedHttpDescriptor", + "documentation":"

    The patch for the HTTP descriptor.

    " + }, + "agui":{ + "shape":"UpdatedAgUiDescriptor", + "documentation":"

    The patch for the AG-UI descriptor.

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

    The patchable descriptor fields applied during an UpdateRegistryRecord call. Each field is independently patchable.

    " + }, + "UpdatedDiscoveryConfiguration":{ + "type":"structure", + "members":{ + "authorizerConfiguration":{ + "shape":"UpdatedAuthorizerConfiguration", + "documentation":"

    Authorization configuration for the registry, with PATCH semantics

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

    The discovery configuration fields to update on a registry. Omit this structure to leave the discovery configuration unchanged.

    " + }, + "UpdatedDisplayName":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"RegistryRecordDisplayName", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    Leaf patch wrapper for a registry record's display name. Omit to leave unchanged; supply an empty object to unset; supply optionalValue to set.

    " + }, + "UpdatedHttpDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedHttpDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The HTTP descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedHttpDescriptorFields":{ + "type":"structure", + "members":{ + "source":{ + "shape":"UpdatedDescriptorSource", + "documentation":"

    The patch for the descriptor's source field.

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

    The set of HTTP descriptor fields that can be individually updated.

    " + }, + "UpdatedMcpServerAdditionalData":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedMcpServerAdditionalDataFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The MCP server additional-data patch wrapper. Omit to leave the additional data unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedMcpServerAdditionalDataFields":{ + "type":"structure", + "members":{ + "tools":{ + "shape":"UpdatedMcpToolsDescriptor", + "documentation":"

    The patch for the MCP tools descriptor field.

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

    The set of MCP server additional-data fields that can be individually updated.

    " + }, + "UpdatedMcpServerDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedMcpServerDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The MCP server descriptor patch wrapper. Omit to leave the descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedMcpServerDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

    " + }, + "dataSchemaVersion":{ + "shape":"UpdatedDataSchemaVersion", + "documentation":"

    The patch for the descriptor's data schema version field.

    " + }, + "source":{ + "shape":"UpdatedDescriptorSource", + "documentation":"

    The patch for the descriptor's source field.

    " + }, + "additionalData":{ + "shape":"UpdatedMcpServerAdditionalData", + "documentation":"

    The patch for the descriptor's additional data field.

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

    The set of MCP server descriptor fields that can be individually updated.

    " + }, + "UpdatedMcpToolsDescriptor":{ + "type":"structure", + "members":{ + "optionalValue":{ + "shape":"UpdatedMcpToolsDescriptorFields", + "documentation":"

    The value to set for this field. Omit the wrapper to leave the field unchanged.

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

    The MCP tools descriptor patch wrapper. Omit to leave the tools descriptor unchanged; supply an empty object to remove it; supply optionalValue to patch its fields.

    " + }, + "UpdatedMcpToolsDescriptorFields":{ + "type":"structure", + "members":{ + "data":{ + "shape":"UpdatedDescriptorData", + "documentation":"

    The patch for the descriptor's data field.

    " + }, + "dataSchemaVersion":{ + "shape":"UpdatedDataSchemaVersion", + "documentation":"

    The patch for the descriptor's data schema version field.

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

    The set of MCP tools descriptor fields that can be individually updated.

    " + }, + "ValidationException":{ + "type":"structure", + "required":[ + "message", + "reason" + ], + "members":{ + "message":{"shape":"String"}, + "reason":{ + "shape":"ValidationExceptionReason", + "documentation":"

    The reason the request failed validation.

    " + }, + "fieldList":{ + "shape":"ValidationExceptionFieldList", + "documentation":"

    The list of input fields that failed validation.

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

    The request failed validation of one or more input fields.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "ValidationExceptionField":{ + "type":"structure", + "required":[ + "name", + "message" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the field that failed validation.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A description of why the field failed validation.

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

    Describes a single input field that failed validation.

    " + }, + "ValidationExceptionFieldList":{ + "type":"list", + "member":{"shape":"ValidationExceptionField"} + }, + "ValidationExceptionReason":{ + "type":"string", + "enum":[ + "CannotParse", + "FieldValidationFailed", + "IdempotentParameterMismatchException", + "EventInOtherSession", + "ResourceConflict" + ] + }, + "VpcIdentifier":{ + "type":"string", + "documentation":"

    The identifier of a VPC.

    ", + "max":48, + "min":10, + "pattern":"vpc-(([0-9a-z]{8})|([0-9a-z]{17}))" + }, + "WorkloadIdentityDetails":{ + "type":"structure", + "required":["workloadIdentityArn"], + "members":{ + "workloadIdentityArn":{ + "shape":"WorkloadIdentityDetailsWorkloadIdentityArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the workload identity associated with the source resource.

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

    Workload identity details associated with a source resource.

    " + }, + "WorkloadIdentityDetailsWorkloadIdentityArnString":{ + "type":"string", + "max":1024, + "min":1 + } + }, + "documentation":"

    Amazon Web Services Agent Registry is a managed catalog for publishing and discovering resources such as MCP servers, agents, and agent skills. Agent Registry Control is its control-plane API: use it to create and manage registries and the records they contain, configure discovery and authorization, govern record approval and curation workflows, and manage automatic detection of resources. Data-plane search and MCP invocation operations are provided by the companion Agent Registry API.

    " +} diff --git a/services/agentregistrycontrol/src/main/resources/codegen-resources/waiters-2.json b/services/agentregistrycontrol/src/main/resources/codegen-resources/waiters-2.json new file mode 100644 index 000000000000..bbce1e931254 --- /dev/null +++ b/services/agentregistrycontrol/src/main/resources/codegen-resources/waiters-2.json @@ -0,0 +1,57 @@ +{ + "version" : 2, + "waiters" : { + "RegistryReady" : { + "delay" : 30, + "maxAttempts" : 5, + "operation" : "GetRegistry", + "acceptors" : [ { + "matcher" : "path", + "argument" : "status", + "state" : "success", + "expected" : "READY" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "CREATE_FAILED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "UPDATE_FAILED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "DELETE_FAILED" + } ] + }, + "RegistryRecordApproved" : { + "delay" : 30, + "maxAttempts" : 5, + "operation" : "GetRegistryRecord", + "acceptors" : [ { + "matcher" : "path", + "argument" : "status", + "state" : "success", + "expected" : "APPROVED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "REJECTED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "CREATE_FAILED" + }, { + "matcher" : "path", + "argument" : "status", + "state" : "failure", + "expected" : "UPDATE_FAILED" + } ] + } + } +} \ No newline at end of file diff --git a/services/aiops/pom.xml b/services/aiops/pom.xml index 92d83c4604b1..0ed7bbd8a377 100644 --- a/services/aiops/pom.xml +++ b/services/aiops/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT aiops AWS Java SDK :: Services :: AI Ops diff --git a/services/aiops/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/aiops/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..866b9187308d --- /dev/null +++ b/services/aiops/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aiops-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aiops-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aiops.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aiops.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/aiops/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/aiops/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 81086942a44a..000000000000 --- a/services/aiops/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aiops-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aiops-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aiops.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aiops.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/amp/pom.xml b/services/amp/pom.xml index e63598b0f8f6..424102bdd11a 100644 --- a/services/amp/pom.xml +++ b/services/amp/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT amp AWS Java SDK :: Services :: Amp diff --git a/services/amp/src/main/resources/codegen-resources/customization.config b/services/amp/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/amp/src/main/resources/codegen-resources/customization.config +++ b/services/amp/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/amp/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/amp/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1228e44ad61b --- /dev/null +++ b/services/amp/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aps-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aps.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aps.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/amp/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/amp/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e7af5c45b79a..000000000000 --- a/services/amp/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aps-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aps.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://aps.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/amp/src/main/resources/codegen-resources/service-2.json b/services/amp/src/main/resources/codegen-resources/service-2.json index a3cbedb26f86..a6510b598f7e 100644 --- a/services/amp/src/main/resources/codegen-resources/service-2.json +++ b/services/amp/src/main/resources/codegen-resources/service-2.json @@ -129,7 +129,7 @@ {"shape":"InternalServerException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    The CreateScraper operation creates a scraper to collect metrics. A scraper pulls metrics from Prometheus-compatible sources and sends them to your Amazon Managed Service for Prometheus workspace. You can configure scrapers to collect metrics from Amazon EKS clusters, Amazon MSK clusters, or from VPC-based sources that support DNS-based service discovery. Scrapers are flexible, and can be configured to control what metrics are collected, the frequency of collection, what transformations are applied to the metrics, and more.

    An IAM role will be created for you that Amazon Managed Service for Prometheus uses to access the metrics in your source. You must configure this role with a policy that allows it to scrape metrics from your source. For Amazon EKS sources, see Configuring your Amazon EKS cluster in the Amazon Managed Service for Prometheus User Guide.

    The scrapeConfiguration parameter contains the base-64 encoded YAML configuration for the scraper.

    When creating a scraper, the service creates a Network Interface in each Availability Zone that are passed into CreateScraper through subnets. These network interfaces are used to connect to your source within the VPC for scraping metrics.

    For more information about collectors, including what metrics are collected, and how to configure the scraper, see Using an Amazon Web Services managed collector in the Amazon Managed Service for Prometheus User Guide.

    ", + "documentation":"

    Creates a scraper to collect metrics from Prometheus-compatible sources. The scraper sends the collected metrics to Amazon Managed Service for Prometheus workspaces or CloudWatch datasets. You can configure scrapers to collect metrics from Amazon EKS clusters, Amazon MSK clusters, or from VPC-based sources that support DNS-based service discovery. Scrapers are flexible. You can configure a scraper to control which metrics to collect, the frequency of collection, which transformations to apply to the metrics, and more.

    An IAM role will be created for you that Amazon Managed Service for Prometheus uses to access the metrics in your source. You must configure this role with a policy that allows it to scrape metrics from your source. For Amazon EKS sources, see Configuring your Amazon EKS cluster in the Amazon Managed Service for Prometheus User Guide.

    The scrapeConfiguration parameter contains the base-64 encoded YAML configuration for the scraper.

    When creating a scraper, the service creates a Network Interface in each Availability Zone that are passed into CreateScraper through subnets. These network interfaces are used to connect to your source within the VPC for scraping metrics.

    For more information about collectors, including what metrics are collected, and how to configure the scraper, see Using an Amazon Web Services managed collector in the Amazon Managed Service for Prometheus User Guide.

    ", "idempotent":true }, "CreateWorkspace":{ @@ -1128,6 +1128,22 @@ "type":"boolean", "box":true }, + "CloudWatchConfiguration":{ + "type":"structure", + "required":["datasetArn"], + "members":{ + "datasetArn":{ + "shape":"CloudWatchDatasetArn", + "documentation":"

    The Amazon Resource Name (ARN) of the CloudWatch dataset. To use the default dataset, specify arn:aws:cloudwatch:<region>:<account-id>:dataset/default.

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

    The configuration identifies the CloudWatch dataset used as a scraper destination.

    " + }, + "CloudWatchDatasetArn":{ + "type":"string", + "documentation":"

    An Amazon Resource Name (ARN) that identifies a dataset in CloudWatch.

    ", + "pattern":"arn:aws[-a-z]*:cloudwatch:[-a-z0-9]+:[0-9]{12}:dataset\\/.+" + }, "CloudWatchLogDestination":{ "type":"structure", "required":["logGroupArn"], @@ -1449,7 +1465,7 @@ }, "destination":{ "shape":"Destination", - "documentation":"

    The Amazon Managed Service for Prometheus workspace to send metrics to.

    " + "documentation":"

    The destination where the scraper sends the collected metrics. Valid destinations are Amazon Managed Service for Prometheus workspaces and CloudWatch datasets.

    " }, "roleConfiguration":{ "shape":"RoleConfiguration", @@ -1463,6 +1479,10 @@ "tags":{ "shape":"TagMap", "documentation":"

    (Optional) The list of tag keys and values to associate with the scraper.

    " + }, + "exporters":{ + "shape":"ExporterList", + "documentation":"

    The exporter configurations for the scraper. You can configure at most one Amazon OpenSearch Service domain. If you don't specify a value, the scraper is created without an exporter configuration.

    " } }, "documentation":"

    Represents the input of a CreateScraper operation.

    " @@ -2054,6 +2074,10 @@ "ampConfiguration":{ "shape":"AmpConfiguration", "documentation":"

    The Amazon Managed Service for Prometheus workspace to send metrics to.

    " + }, + "cloudWatchConfiguration":{ + "shape":"CloudWatchConfiguration", + "documentation":"

    The CloudWatch dataset to send metrics to.

    " } }, "documentation":"

    Where to send the metrics from a scraper.

    ", @@ -2081,6 +2105,24 @@ }, "documentation":"

    The EksConfiguration structure describes the connection to the Amazon EKS cluster from which a scraper collects metrics.

    " }, + "ExporterConfiguration":{ + "type":"structure", + "members":{ + "openSearchConfiguration":{ + "shape":"OpenSearchExporterConfiguration", + "documentation":"

    The configuration that the scraper uses to export metrics to an Amazon OpenSearch Service domain.

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

    Contains the configuration for an exporter managed by the scraper.

    ", + "union":true + }, + "ExporterList":{ + "type":"list", + "member":{"shape":"ExporterConfiguration"}, + "documentation":"

    A list of exporter configurations for a scraper. You can configure at most one Amazon OpenSearch Service domain.

    ", + "max":1, + "min":0 + }, "FilterKey":{ "type":"string", "documentation":"

    The name of the key by which to filter.

    ", @@ -2553,6 +2595,22 @@ "box":true, "min":0 }, + "OpenSearchDomainArn":{ + "type":"string", + "documentation":"

    An Amazon Resource Name (ARN) that identifies an Amazon OpenSearch Service domain.

    ", + "pattern":"arn:aws[-a-z]*:es:[-a-z0-9]+:[0-9]{12}:domain\\/.+" + }, + "OpenSearchExporterConfiguration":{ + "type":"structure", + "required":["domainArn"], + "members":{ + "domainArn":{ + "shape":"OpenSearchDomainArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon OpenSearch Service domain.

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

    The configuration for exporting metrics to an Amazon OpenSearch Service domain.

    " + }, "PaginationToken":{ "type":"string", "documentation":"

    A token used to access the next page in a paginated result set.

    ", @@ -3165,11 +3223,15 @@ }, "destination":{ "shape":"Destination", - "documentation":"

    The Amazon Managed Service for Prometheus workspace the scraper sends metrics to.

    " + "documentation":"

    The destination where the scraper sends metrics. Valid destinations are Amazon Managed Service for Prometheus workspaces and CloudWatch datasets.

    " }, "roleConfiguration":{ "shape":"RoleConfiguration", "documentation":"

    This structure displays information about the IAM roles used for cross-account scraping configuration.

    " + }, + "exporters":{ + "shape":"ExporterList", + "documentation":"

    The exporter configurations for the scraper, if configured. The list contains at most one configuration for an Amazon OpenSearch Service domain.

    " } }, "documentation":"

    The ScraperDescription structure contains the full details about one scraper in your account.

    " @@ -3311,11 +3373,15 @@ }, "destination":{ "shape":"Destination", - "documentation":"

    The Amazon Managed Service for Prometheus workspace the scraper sends metrics to.

    " + "documentation":"

    The destination where the scraper sends metrics. Valid destinations are Amazon Managed Service for Prometheus workspaces and CloudWatch datasets.

    " }, "roleConfiguration":{ "shape":"RoleConfiguration", "documentation":"

    This structure displays information about the IAM roles used for cross-account scraping configuration.

    " + }, + "exporters":{ + "shape":"ExporterList", + "documentation":"

    The exporter configurations for the scraper, if configured. The list contains at most one configuration for an Amazon OpenSearch Service domain.

    " } }, "documentation":"

    The ScraperSummary structure contains a summary of the details about one scraper in your account.

    " @@ -3651,7 +3717,7 @@ }, "destination":{ "shape":"Destination", - "documentation":"

    The new Amazon Managed Service for Prometheus workspace to send metrics to.

    " + "documentation":"

    The new destination where the scraper sends metrics. Valid destinations are Amazon Managed Service for Prometheus workspaces and CloudWatch datasets.

    " }, "roleConfiguration":{ "shape":"RoleConfiguration", @@ -3661,6 +3727,10 @@ "shape":"IdempotencyToken", "documentation":"

    A unique identifier that you can provide to ensure the idempotency of the request. Case-sensitive.

    ", "idempotencyToken":true + }, + "exporters":{ + "shape":"ExporterList", + "documentation":"

    The exporter configurations for the scraper. You can configure at most one Amazon OpenSearch Service domain. If you don't specify a value, the existing exporter configuration remains unchanged.

    " } } }, diff --git a/services/amplify/pom.xml b/services/amplify/pom.xml index 14df6c119ec2..603fc4f3ec14 100644 --- a/services/amplify/pom.xml +++ b/services/amplify/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT amplify AWS Java SDK :: Services :: Amplify diff --git a/services/amplify/src/main/resources/codegen-resources/customization.config b/services/amplify/src/main/resources/codegen-resources/customization.config index 1a37c2370c98..cd8f1c2140be 100644 --- a/services/amplify/src/main/resources/codegen-resources/customization.config +++ b/services/amplify/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listApps" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/amplify/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/amplify/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9e8ede4917e0 --- /dev/null +++ b/services/amplify/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplify-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplify-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplify.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplify.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/amplify/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/amplify/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ce23986394ce..000000000000 --- a/services/amplify/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplify-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplify-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplify.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://amplify.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/amplify/src/main/resources/codegen-resources/service-2.json b/services/amplify/src/main/resources/codegen-resources/service-2.json index e300f0afbf98..4eda060c7582 100644 --- a/services/amplify/src/main/resources/codegen-resources/service-2.json +++ b/services/amplify/src/main/resources/codegen-resources/service-2.json @@ -627,7 +627,7 @@ "shapes":{ "AccessToken":{ "type":"string", - "max":255, + "max":4096, "min":1, "pattern":"(?s).+", "sensitive":true @@ -2794,7 +2794,7 @@ }, "OauthToken":{ "type":"string", - "max":1000, + "max":4096, "pattern":"(?s).*", "sensitive":true }, diff --git a/services/amplifybackend/pom.xml b/services/amplifybackend/pom.xml index ad9a1afc78df..d9d091bad4d8 100644 --- a/services/amplifybackend/pom.xml +++ b/services/amplifybackend/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT amplifybackend AWS Java SDK :: Services :: Amplify Backend diff --git a/services/amplifybackend/src/main/resources/codegen-resources/customization.config b/services/amplifybackend/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/amplifybackend/src/main/resources/codegen-resources/customization.config +++ b/services/amplifybackend/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/amplifybackend/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/amplifybackend/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8b246dadc3ff --- /dev/null +++ b/services/amplifybackend/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifybackend-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifybackend-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifybackend.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifybackend.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/amplifybackend/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/amplifybackend/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6d19e9548647..000000000000 --- a/services/amplifybackend/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifybackend-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifybackend-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifybackend.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://amplifybackend.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/amplifyuibuilder/pom.xml b/services/amplifyuibuilder/pom.xml index 131ab1653f9e..3821650eddc1 100644 --- a/services/amplifyuibuilder/pom.xml +++ b/services/amplifyuibuilder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT amplifyuibuilder AWS Java SDK :: Services :: Amplify UI Builder diff --git a/services/amplifyuibuilder/src/main/resources/codegen-resources/customization.config b/services/amplifyuibuilder/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/amplifyuibuilder/src/main/resources/codegen-resources/customization.config +++ b/services/amplifyuibuilder/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4f3fff7f21c2 --- /dev/null +++ b/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifyuibuilder-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifyuibuilder-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifyuibuilder.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://amplifyuibuilder.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5819ce91ad91..000000000000 --- a/services/amplifyuibuilder/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifyuibuilder-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifyuibuilder-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://amplifyuibuilder.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://amplifyuibuilder.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/apigateway/pom.xml b/services/apigateway/pom.xml index 70a43a031afa..12389c16f622 100644 --- a/services/apigateway/pom.xml +++ b/services/apigateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apigateway AWS Java SDK :: Services :: Amazon API Gateway diff --git a/services/apigateway/src/main/resources/codegen-resources/customization.config b/services/apigateway/src/main/resources/codegen-resources/customization.config index 082dea59b374..520761d7df21 100644 --- a/services/apigateway/src/main/resources/codegen-resources/customization.config +++ b/services/apigateway/src/main/resources/codegen-resources/customization.config @@ -23,6 +23,5 @@ ], "interceptors": [ "software.amazon.awssdk.services.apigateway.internal.AcceptJsonInterceptor" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/apigateway/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/apigateway/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6b57776b5058 --- /dev/null +++ b/services/apigateway/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/apigateway/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/apigateway/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8be2a0672b4c..000000000000 --- a/services/apigateway/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://apigateway.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file 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 982a563d23e0..630ed32af337 100644 --- a/services/apigateway/src/main/resources/codegen-resources/service-2.json +++ b/services/apigateway/src/main/resources/codegen-resources/service-2.json @@ -6565,6 +6565,8 @@ "SecurityPolicy_TLS13_1_2_PFS_PQ_2025_09", "SecurityPolicy_TLS13_1_2_FIPS_PQ_2025_09", "SecurityPolicy_TLS13_1_2_FIPS_PFS_PQ_2025_09", + "SecurityPolicy_TLS13_1_2_Ext2_PQ_2025_09", + "SecurityPolicy_TLS13_1_2_Ext2_FIPS_PQ_2025_09", "SecurityPolicy_TLS13_1_2_PQ_2025_09", "SecurityPolicy_TLS13_1_2_2021_06", "SecurityPolicy_TLS13_2025_EDGE", diff --git a/services/apigatewaymanagementapi/pom.xml b/services/apigatewaymanagementapi/pom.xml index b038efaa920f..d9639286b399 100644 --- a/services/apigatewaymanagementapi/pom.xml +++ b/services/apigatewaymanagementapi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apigatewaymanagementapi AWS Java SDK :: Services :: ApiGatewayManagementApi diff --git a/services/apigatewaymanagementapi/src/main/resources/codegen-resources/customization.config b/services/apigatewaymanagementapi/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/apigatewaymanagementapi/src/main/resources/codegen-resources/customization.config +++ b/services/apigatewaymanagementapi/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ba3b39e142e1 --- /dev/null +++ b/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://execute-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://execute-api-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://execute-api.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://execute-api.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5d1f808d9d0b..000000000000 --- a/services/apigatewaymanagementapi/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://execute-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://execute-api-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://execute-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://execute-api.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/apigatewayv2/pom.xml b/services/apigatewayv2/pom.xml index 5f9fafde5030..6638c325b41a 100644 --- a/services/apigatewayv2/pom.xml +++ b/services/apigatewayv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apigatewayv2 AWS Java SDK :: Services :: ApiGatewayV2 diff --git a/services/apigatewayv2/src/main/resources/codegen-resources/customization.config b/services/apigatewayv2/src/main/resources/codegen-resources/customization.config index 11eb6b271d1f..1474ea0d5c3e 100644 --- a/services/apigatewayv2/src/main/resources/codegen-resources/customization.config +++ b/services/apigatewayv2/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "getApis", "getDomainNames" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6b57776b5058 --- /dev/null +++ b/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apigateway.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8be2a0672b4c..000000000000 --- a/services/apigatewayv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apigateway.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://apigateway.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appconfig/pom.xml b/services/appconfig/pom.xml index 8ac76b14efc1..d7d59e41300b 100644 --- a/services/appconfig/pom.xml +++ b/services/appconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appconfig AWS Java SDK :: Services :: AppConfig diff --git a/services/appconfig/src/main/resources/codegen-resources/customization.config b/services/appconfig/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/appconfig/src/main/resources/codegen-resources/customization.config +++ b/services/appconfig/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/appconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..265571e741f5 --- /dev/null +++ b/services/appconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfig.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appconfig/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appconfig/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e65569660c02..000000000000 --- a/services/appconfig/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appconfig-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://appconfig.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://appconfig.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appconfig-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appconfig.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appconfig.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appconfigdata/pom.xml b/services/appconfigdata/pom.xml index 98038f7df7d7..6584c7104483 100644 --- a/services/appconfigdata/pom.xml +++ b/services/appconfigdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appconfigdata AWS Java SDK :: Services :: App Config Data diff --git a/services/appconfigdata/src/main/resources/codegen-resources/customization.config b/services/appconfigdata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/appconfigdata/src/main/resources/codegen-resources/customization.config +++ b/services/appconfigdata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/appconfigdata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appconfigdata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e3ccfb00d509 --- /dev/null +++ b/services/appconfigdata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfigdata-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfigdata.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfigdata-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfigdata.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appconfigdata.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appconfigdata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appconfigdata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a6e9d35df41b..000000000000 --- a/services/appconfigdata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appconfigdata-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://appconfigdata.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appconfigdata-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appconfigdata.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appconfigdata.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appfabric/pom.xml b/services/appfabric/pom.xml index c6db9b287b40..c8e5bbfad7d4 100644 --- a/services/appfabric/pom.xml +++ b/services/appfabric/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appfabric AWS Java SDK :: Services :: App Fabric diff --git a/services/appfabric/src/main/resources/codegen-resources/customization.config b/services/appfabric/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/appfabric/src/main/resources/codegen-resources/customization.config +++ b/services/appfabric/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/appfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e81abeaa3364 --- /dev/null +++ b/services/appfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appfabric-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appfabric-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appfabric.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appfabric.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appfabric/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appfabric/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b1ad721b0aee..000000000000 --- a/services/appfabric/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appfabric-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appfabric-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appfabric.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appfabric.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/appflow/pom.xml b/services/appflow/pom.xml index 346b314e3c6f..6daa3c30bb50 100644 --- a/services/appflow/pom.xml +++ b/services/appflow/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appflow AWS Java SDK :: Services :: Appflow diff --git a/services/appflow/src/main/resources/codegen-resources/customization.config b/services/appflow/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/appflow/src/main/resources/codegen-resources/customization.config +++ b/services/appflow/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/appflow/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appflow/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a74ce047a98e --- /dev/null +++ b/services/appflow/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appflow-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appflow.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appflow.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appflow/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appflow/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3ac8b53bbfe2..000000000000 --- a/services/appflow/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appflow-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appflow.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appflow.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appflow/src/main/resources/codegen-resources/service-2.json b/services/appflow/src/main/resources/codegen-resources/service-2.json index b1c58d620a12..a69281708b3a 100644 --- a/services/appflow/src/main/resources/codegen-resources/service-2.json +++ b/services/appflow/src/main/resources/codegen-resources/service-2.json @@ -757,6 +757,13 @@ "max":512, "pattern":"\\S+" }, + "CodeVerifier":{ + "type":"string", + "max":128, + "min":43, + "pattern":"^[A-Za-z0-9\\-._~]+$", + "sensitive":true + }, "ConflictException":{ "type":"structure", "members":{ @@ -1171,6 +1178,10 @@ "redirectUri":{ "shape":"RedirectUri", "documentation":"

    The URL to which the authentication server redirects the browser after authorization has been granted.

    " + }, + "codeVerifier":{ + "shape":"CodeVerifier", + "documentation":"

    The code verifier used in the PKCE (Proof Key for Code Exchange) OAuth flow.

    " } }, "documentation":"

    Used by select connectors for which the OAuth workflow is supported, such as Salesforce, Google Analytics, Marketo, Zendesk, and Slack.

    " @@ -3870,6 +3881,13 @@ "CREATED" ] }, + "PrivateKey":{ + "type":"string", + "max":8192, + "min":1, + "pattern":".*", + "sensitive":true + }, "PrivateLinkServiceName":{ "type":"string", "max":512, @@ -4822,10 +4840,7 @@ }, "SnowflakeConnectorProfileCredentials":{ "type":"structure", - "required":[ - "username", - "password" - ], + "required":["username"], "members":{ "username":{ "shape":"Username", @@ -4834,6 +4849,10 @@ "password":{ "shape":"Password", "documentation":"

    The password that corresponds to the user name.

    " + }, + "privateKey":{ + "shape":"PrivateKey", + "documentation":"

    The RSA private key used for key pair authentication with Snowflake. Provide this instead of a password when your Snowflake account uses key pair authentication.

    " } }, "documentation":"

    The connector-specific profile credentials required when using Snowflake.

    " diff --git a/services/appintegrations/pom.xml b/services/appintegrations/pom.xml index 92daaee02e27..5e7702af29b3 100644 --- a/services/appintegrations/pom.xml +++ b/services/appintegrations/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appintegrations AWS Java SDK :: Services :: App Integrations diff --git a/services/appintegrations/src/main/resources/codegen-resources/customization.config b/services/appintegrations/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/appintegrations/src/main/resources/codegen-resources/customization.config +++ b/services/appintegrations/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/appintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7be68bded5c7 --- /dev/null +++ b/services/appintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://app-integrations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://app-integrations-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://app-integrations.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://app-integrations.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2d879db102ae..000000000000 --- a/services/appintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://app-integrations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://app-integrations-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://app-integrations.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://app-integrations.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appintegrations/src/main/resources/codegen-resources/service-2.json b/services/appintegrations/src/main/resources/codegen-resources/service-2.json index d41d2aea9424..cecd94278d71 100644 --- a/services/appintegrations/src/main/resources/codegen-resources/service-2.json +++ b/services/appintegrations/src/main/resources/codegen-resources/service-2.json @@ -102,7 +102,7 @@ {"shape":"InvalidRequestException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Deletes the Application. Only Applications that don't have any Application Associations can be deleted.

    " + "documentation":"

    Deletes an application. If the application has associations, you must delete them first. Alternatively, use the force option to delete the application and remove its associations.

    " }, "DeleteDataIntegration":{ "name":"DeleteDataIntegration", @@ -350,7 +350,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InvalidRequestException"}, {"shape":"AccessDeniedException"}, - {"shape":"UnsupportedOperationException"} + {"shape":"UnsupportedOperationException"}, + {"shape":"ConflictException"} ], "documentation":"

    Updates and persists an Application resource.

    " }, @@ -531,7 +532,8 @@ "enum":[ "STANDARD", "SERVICE", - "MCP_SERVER" + "MCP_SERVER", + "A2A_SERVER" ] }, "ApplicationsList":{ @@ -552,6 +554,24 @@ "min":1, "pattern":"^(arn:aws:[A-Za-z0-9][A-Za-z0-9_/.-]{0,62}:[A-Za-z0-9_/.-]{0,63}:[A-Za-z0-9_/.-]{0,63}:[A-Za-z0-9][A-Za-z0-9:_/+=,@.-]{0,1023}|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})(:[\\w\\$]+)?$" }, + "AuthConfig":{ + "type":"structure", + "members":{ + "AuthType":{ + "shape":"AuthType", + "documentation":"

    The type of authentication used when calling the external application.

    " + }, + "CredentialProviderIdentifier":{ + "shape":"Arn", + "documentation":"

    The ARN of the Secrets Manager secret that stores the credentials. The secret must be accessible to Connect Customer.

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

    Contains the authentication settings that Connect Customer uses to call an external application endpoint. The configuration includes the authentication type and credential location.

    " + }, + "AuthType":{ + "type":"string", + "enum":["API_KEY"] + }, "Boolean":{"type":"boolean"}, "ClientAssociationMetadata":{ "type":"map", @@ -564,6 +584,15 @@ "min":1, "pattern":".*" }, + "ConflictException":{ + "type":"structure", + "members":{ + "Message":{"shape":"Message"} + }, + "documentation":"

    The request conflicts with the current state of the resource. Verify the application's current state and retry the request.

    ", + "error":{"httpStatusCode":409}, + "exception":true + }, "ContactHandling":{ "type":"structure", "members":{ @@ -652,6 +681,10 @@ "ApplicationType":{ "shape":"ApplicationType", "documentation":"

    The type of application.

    " + }, + "AuthConfig":{ + "shape":"AuthConfig", + "documentation":"

    The authentication settings that Connect Customer uses when calling the external application.

    " } } }, @@ -920,6 +953,12 @@ "documentation":"

    The Amazon Resource Name (ARN) of the Application.

    ", "location":"uri", "locationName":"ApplicationIdentifier" + }, + "Force":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to delete the application even if it still has application associations. If true, the operation removes the application and its associations. If false or absent, the delete fails when associations exist.

    Setting this parameter to true permanently removes all of the application's associations. Doing so might impact other resources that rely on and reference the application. This action can't be undone.

    ", + "location":"querystring", + "locationName":"force" } } }, @@ -1257,6 +1296,10 @@ "ApplicationType":{ "shape":"ApplicationType", "documentation":"

    The type of application.

    " + }, + "AuthConfig":{ + "shape":"AuthConfig", + "documentation":"

    The authentication settings that Connect Customer uses when calling the external application.

    " } } }, @@ -1993,6 +2036,10 @@ "ApplicationType":{ "shape":"ApplicationType", "documentation":"

    The type of application.

    " + }, + "AuthConfig":{ + "shape":"AuthConfig", + "documentation":"

    The authentication settings that Connect Customer uses when calling the external application.

    " } } }, diff --git a/services/applicationautoscaling/pom.xml b/services/applicationautoscaling/pom.xml index 2cc5ac082fda..ffd2a1edbb5e 100644 --- a/services/applicationautoscaling/pom.xml +++ b/services/applicationautoscaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT applicationautoscaling AWS Java SDK :: Services :: AWS Application Auto Scaling diff --git a/services/applicationautoscaling/src/main/resources/codegen-resources/customization.config b/services/applicationautoscaling/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/applicationautoscaling/src/main/resources/codegen-resources/customization.config +++ b/services/applicationautoscaling/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bf6d5d67a59b --- /dev/null +++ b/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-autoscaling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-autoscaling.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-autoscaling-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-autoscaling.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-autoscaling.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0b71dd146505..000000000000 --- a/services/applicationautoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://application-autoscaling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://application-autoscaling.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://application-autoscaling-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://application-autoscaling.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://application-autoscaling.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/applicationcostprofiler/pom.xml b/services/applicationcostprofiler/pom.xml index 6954ee346e6e..6521ef500094 100644 --- a/services/applicationcostprofiler/pom.xml +++ b/services/applicationcostprofiler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT applicationcostprofiler AWS Java SDK :: Services :: Application Cost Profiler diff --git a/services/applicationcostprofiler/src/main/resources/codegen-resources/customization.config b/services/applicationcostprofiler/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/applicationcostprofiler/src/main/resources/codegen-resources/customization.config +++ b/services/applicationcostprofiler/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e08bebdf522b --- /dev/null +++ b/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-cost-profiler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-cost-profiler-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-cost-profiler.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-cost-profiler.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0cfd0d588b15..000000000000 --- a/services/applicationcostprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://application-cost-profiler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://application-cost-profiler-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://application-cost-profiler.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://application-cost-profiler.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/applicationdiscovery/pom.xml b/services/applicationdiscovery/pom.xml index f7643e8335a3..d9bcadb85be6 100644 --- a/services/applicationdiscovery/pom.xml +++ b/services/applicationdiscovery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT applicationdiscovery AWS Java SDK :: Services :: AWS Application Discovery Service diff --git a/services/applicationdiscovery/src/main/resources/codegen-resources/customization.config b/services/applicationdiscovery/src/main/resources/codegen-resources/customization.config index dfddca8bbd59..d344cbdbcb95 100644 --- a/services/applicationdiscovery/src/main/resources/codegen-resources/customization.config +++ b/services/applicationdiscovery/src/main/resources/codegen-resources/customization.config @@ -16,6 +16,5 @@ "deprecatedOperations": [ "DescribeExportConfigurations", "ExportConfigurations" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0bfb11879c37 --- /dev/null +++ b/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3182d1292dd4..000000000000 --- a/services/applicationdiscovery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://discovery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://discovery-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://discovery.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://discovery.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/applicationinsights/pom.xml b/services/applicationinsights/pom.xml index 8eb858bacaef..2619be04d9cf 100644 --- a/services/applicationinsights/pom.xml +++ b/services/applicationinsights/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT applicationinsights AWS Java SDK :: Services :: Application Insights @@ -61,5 +61,10 @@ http-auth-aws ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + diff --git a/services/applicationinsights/src/main/resources/codegen-resources/customization.config b/services/applicationinsights/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/applicationinsights/src/main/resources/codegen-resources/customization.config +++ b/services/applicationinsights/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/applicationinsights/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/applicationinsights/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..373f1f01082f --- /dev/null +++ b/services/applicationinsights/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://applicationinsights-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://applicationinsights-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://applicationinsights.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://applicationinsights.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/applicationinsights/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/applicationinsights/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d65dcb947586..000000000000 --- a/services/applicationinsights/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://applicationinsights-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://applicationinsights-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://applicationinsights.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://applicationinsights.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/applicationinsights/src/main/resources/codegen-resources/service-2.json b/services/applicationinsights/src/main/resources/codegen-resources/service-2.json index 0ca2afcdd5ba..e791db4a5e35 100644 --- a/services/applicationinsights/src/main/resources/codegen-resources/service-2.json +++ b/services/applicationinsights/src/main/resources/codegen-resources/service-2.json @@ -4,8 +4,11 @@ "apiVersion":"2018-11-25", "endpointPrefix":"applicationinsights", "jsonVersion":"1.1", - "protocol":"json", - "protocols":["json"], + "protocol":"smithy-rpc-v2-cbor", + "protocols":[ + "smithy-rpc-v2-cbor", + "json" + ], "serviceAbbreviation":"Application Insights", "serviceFullName":"Amazon CloudWatch Application Insights", "serviceId":"Application Insights", @@ -527,6 +530,7 @@ "Message":{"shape":"ErrorMsg"} }, "documentation":"

    User does not have permissions to perform this action.

    ", + "error":{"httpStatusCode":403}, "exception":true }, "AccountId":{ @@ -2197,6 +2201,7 @@ "Message":{"shape":"ExceptionMessage"} }, "documentation":"

    Tags are already registered for the specified application ARN.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "Tier":{ @@ -2240,6 +2245,7 @@ } }, "documentation":"

    The number of the provided tags is beyond the limit, or the number of total tags you are trying to attach to the specified resource exceeds the limit.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "Unit":{"type":"string"}, diff --git a/services/applicationsignals/pom.xml b/services/applicationsignals/pom.xml index f161cc72c9d2..1aaa59faa38d 100644 --- a/services/applicationsignals/pom.xml +++ b/services/applicationsignals/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT applicationsignals AWS Java SDK :: Services :: Application Signals diff --git a/services/applicationsignals/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/applicationsignals/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..871c2d961c56 --- /dev/null +++ b/services/applicationsignals/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-signals-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://application-signals.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/applicationsignals/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/applicationsignals/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0cc7c6a55acc..000000000000 --- a/services/applicationsignals/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://application-signals-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://application-signals.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/appmesh/pom.xml b/services/appmesh/pom.xml index 931061865015..372376906115 100644 --- a/services/appmesh/pom.xml +++ b/services/appmesh/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appmesh AWS Java SDK :: Services :: App Mesh diff --git a/services/appmesh/src/main/resources/codegen-resources/customization.config b/services/appmesh/src/main/resources/codegen-resources/customization.config index e7aad41e84d7..ef03b85518cc 100644 --- a/services/appmesh/src/main/resources/codegen-resources/customization.config +++ b/services/appmesh/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listMeshes" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/appmesh/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appmesh/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5c151819a562 --- /dev/null +++ b/services/appmesh/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appmesh-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appmesh-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appmesh.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appmesh.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appmesh/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appmesh/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d1129b793f33..000000000000 --- a/services/appmesh/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appmesh-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appmesh-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appmesh.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appmesh.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/apprunner/pom.xml b/services/apprunner/pom.xml index 4dc866e059d8..35d73c88bd43 100644 --- a/services/apprunner/pom.xml +++ b/services/apprunner/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT apprunner AWS Java SDK :: Services :: App Runner diff --git a/services/apprunner/src/main/resources/codegen-resources/customization.config b/services/apprunner/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/apprunner/src/main/resources/codegen-resources/customization.config +++ b/services/apprunner/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/apprunner/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/apprunner/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..10ba4d296aa3 --- /dev/null +++ b/services/apprunner/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apprunner-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apprunner-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apprunner.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://apprunner.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/apprunner/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/apprunner/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3189e54bdde2..000000000000 --- a/services/apprunner/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apprunner-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apprunner-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://apprunner.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://apprunner.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appstream/pom.xml b/services/appstream/pom.xml index 0eba7fdb9836..05903d47c728 100644 --- a/services/appstream/pom.xml +++ b/services/appstream/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appstream AWS Java SDK :: Services :: Amazon AppStream @@ -61,5 +61,10 @@ http-auth-aws ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + diff --git a/services/appstream/src/main/resources/codegen-resources/customization.config b/services/appstream/src/main/resources/codegen-resources/customization.config index 8f6624671cda..1c8d014e4ede 100644 --- a/services/appstream/src/main/resources/codegen-resources/customization.config +++ b/services/appstream/src/main/resources/codegen-resources/customization.config @@ -9,6 +9,5 @@ "describeImageBuilders", "describeImages", "describeStacks" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/appstream/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appstream/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f50aaccaeb69 --- /dev/null +++ b/services/appstream/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,227 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appstream2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appstream2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appstream2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appstream2.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appstream2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAABwX14QoAAAAIAAAACAX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAwAAAALAAAABgX14QYF9eEHAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appstream/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appstream/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index dc30801e01bf..000000000000 --- a/services/appstream/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appstream2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appstream2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appstream2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://appstream2.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://appstream2.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appstream2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/appstream/src/main/resources/codegen-resources/service-2.json b/services/appstream/src/main/resources/codegen-resources/service-2.json index aa8eec6a6551..5c4da6f48e57 100644 --- a/services/appstream/src/main/resources/codegen-resources/service-2.json +++ b/services/appstream/src/main/resources/codegen-resources/service-2.json @@ -4,8 +4,11 @@ "apiVersion":"2016-12-01", "endpointPrefix":"appstream2", "jsonVersion":"1.1", - "protocol":"json", - "protocols":["json"], + "protocol":"smithy-rpc-v2-cbor", + "protocols":[ + "smithy-rpc-v2-cbor", + "json" + ], "serviceFullName":"Amazon AppStream", "serviceId":"AppStream", "signatureVersion":"v4", @@ -2314,6 +2317,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    An API error occurred. Wait a few minutes and try again.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ContentRedirection":{ @@ -4256,6 +4260,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The exception that is thrown when a dry run operation is requested. This indicates that the validation checks have been performed successfully, but no actual resources were created or modified.

    ", + "error":{"httpStatusCode":412}, "exception":true }, "DynamicAppProvidersEnabled":{ @@ -4359,6 +4364,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The entitlement already exists.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "EntitlementAttribute":{ @@ -4394,6 +4400,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The entitlement can't be found.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ErrorDetails":{ @@ -5088,6 +5095,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The image can't be updated because it's not compatible for updates.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "InstanceDrainStatus":{ @@ -5110,6 +5118,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The resource cannot be created because your AWS account is suspended. For assistance, contact AWS Support.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "InvalidParameterCombinationException":{ @@ -5118,6 +5127,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    Indicates an incorrect combination of parameters, or a missing parameter.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "InvalidRoleException":{ @@ -5126,6 +5136,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The specified role is invalid.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "LastReportGenerationExecutionError":{ @@ -5165,6 +5176,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The requested limit exceeds the permitted limit for an account.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ListAssociatedFleetsRequest":{ @@ -5355,6 +5367,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The attempted operation is not permitted.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "OrganizationalUnitDistinguishedName":{ @@ -5424,6 +5437,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    WorkSpaces Applications can’t process the request right now because the Describe calls from your AWS account are being throttled by Amazon EC2. Try again later.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ResourceAlreadyExistsException":{ @@ -5432,6 +5446,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The specified resource already exists.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ResourceError":{ @@ -5468,6 +5483,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The specified resource is in use.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ResourceNotAvailableException":{ @@ -5476,6 +5492,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The specified resource exists and is not in use, but isn't available.

    ", + "error":{"httpStatusCode":400}, "exception":true }, "ResourceNotFoundException":{ @@ -5484,6 +5501,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The specified resource was not found.

    ", + "error":{"httpStatusCode":404}, "exception":true }, "RuntimeValidationConfig":{ diff --git a/services/appsync/pom.xml b/services/appsync/pom.xml index 14e2a62c5878..85f01da32b6a 100644 --- a/services/appsync/pom.xml +++ b/services/appsync/pom.xml @@ -21,7 +21,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT appsync diff --git a/services/appsync/src/main/resources/codegen-resources/customization.config b/services/appsync/src/main/resources/codegen-resources/customization.config index 1ab9852214b6..80acbbb56853 100644 --- a/services/appsync/src/main/resources/codegen-resources/customization.config +++ b/services/appsync/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listGraphqlApis" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/appsync/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/appsync/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..910f64cbf64e --- /dev/null +++ b/services/appsync/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appsync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appsync-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appsync.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://appsync.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/appsync/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/appsync/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e2c159e7b983..000000000000 --- a/services/appsync/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appsync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appsync-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://appsync.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://appsync.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/arcregionswitch/pom.xml b/services/arcregionswitch/pom.xml index 7023ae976129..718a7f26fa54 100644 --- a/services/arcregionswitch/pom.xml +++ b/services/arcregionswitch/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT arcregionswitch AWS Java SDK :: Services :: ARC Region Switch diff --git a/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c5e3d6b01bd1 --- /dev/null +++ b/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,195 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseControlPlaneEndpoint": { + "required": false, + "documentation": "Whether the operation is a control plane operation. Control plane operations are routed to a centralized endpoint in the partition leader.", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseControlPlaneEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://arc-region-switch-control-plane.cn-north-1.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "arc-region-switch", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS is not supported in this partition", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-region-switch-control-plane-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "arc-region-switch", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-region-switch-control-plane.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "arc-region-switch", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-region-switch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-region-switch.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 10, + "nodes": "/////wAAAAH/////AAAAAAAAAAoAAAADAAAAAQAAAAQF9eEJAAAAAgAAAAUF9eEJAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEIAAAABQX14QEF9eEEAAAABAAAAAkF9eEHAAAABQX14QIF9eEDAAAAAwX14QUF9eEG" +} \ No newline at end of file diff --git a/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index abd72333dde9..000000000000 --- a/services/arcregionswitch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,434 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseControlPlaneEndpoint": { - "required": false, - "documentation": "Whether the operation is a control plane operation. Control plane operations are routed to a centralized endpoint in the partition leader.", - "type": "boolean" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-region-switch-control-plane.cn-north-1.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "arc-region-switch", - "signingRegion": "cn-north-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "error": "Invalid Configuration: FIPS is not supported in this partition", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-region-switch-control-plane-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "arc-region-switch", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseControlPlaneEndpoint" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-region-switch-control-plane.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "arc-region-switch", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://arc-region-switch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://arc-region-switch.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/arcregionswitch/src/main/resources/codegen-resources/service-2.json b/services/arcregionswitch/src/main/resources/codegen-resources/service-2.json index c38e30ff4cc8..1e8083fae3aa 100644 --- a/services/arcregionswitch/src/main/resources/codegen-resources/service-2.json +++ b/services/arcregionswitch/src/main/resources/codegen-resources/service-2.json @@ -264,7 +264,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"IllegalStateException"}, {"shape":"AccessDeniedException"}, - {"shape":"IllegalArgumentException"} + {"shape":"IllegalArgumentException"}, + {"shape":"ConflictException"} ], "documentation":"

    Starts the execution of a Region switch plan. You can execute a plan in either graceful or ungraceful mode.

    Specifing ungraceful mode either changes the behavior of the execution blocks in a workflow or skips specific execution blocks.

    " }, @@ -785,6 +786,27 @@ "type":"structure", "members":{} }, + "ConflictException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource involved in the client token conflict.

    " + }, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource involved in the client token conflict.

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

    The client token was already used with different request parameters. A client token must map to the same parameters for every request. To retry this operation, provide a new client token.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, "CreatePlanRequest":{ "type":"structure", "required":[ @@ -1336,6 +1358,10 @@ "neptuneGlobalDatabaseConfig":{ "shape":"NeptuneGlobalDatabaseConfiguration", "documentation":"

    A Neptune global database execution block.

    " + }, + "rdsSwitchoverReadReplicaConfig":{ + "shape":"RdsSwitchoverReadReplicaConfiguration", + "documentation":"

    An Amazon RDS switchover read replica execution block.

    " } }, "documentation":"

    Execution block configurations for a workflow in a Region switch plan. An execution block represents a specific type of action to perform during a Region switch.

    ", @@ -1360,7 +1386,8 @@ "LambdaEventSourceMapping", "AuroraServerlessScaling", "AuroraProvisionedScaling", - "NeptuneGlobalDatabase" + "NeptuneGlobalDatabase", + "RdsSwitchoverReadReplica" ] }, "ExecutionComment":{ @@ -2498,6 +2525,53 @@ "box":true, "min":1 }, + "RdsSwitchoverReadReplicaConfiguration":{ + "type":"structure", + "required":["dbInstanceArnMap"], + "members":{ + "timeoutMinutes":{ + "shape":"RdsSwitchoverReadReplicaConfigurationTimeoutMinutesInteger", + "documentation":"

    The timeout value specified for the configuration.

    " + }, + "crossAccountRole":{ + "shape":"IamRoleArn", + "documentation":"

    The cross-account role for the configuration.

    " + }, + "externalId":{ + "shape":"String", + "documentation":"

    The external ID (secret key) for the configuration.

    " + }, + "dbInstanceArnMap":{ + "shape":"RdsDbInstanceArnMap", + "documentation":"

    A map of database instance ARNs for each Region in the plan.

    " + }, + "ungraceful":{ + "shape":"RdsUngraceful", + "documentation":"

    The ungraceful execution settings for the configuration.

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

    Configuration for switching over an Amazon RDS read replica to become the new primary database instance during a Region switch.

    " + }, + "RdsSwitchoverReadReplicaConfigurationTimeoutMinutesInteger":{ + "type":"integer", + "box":true, + "min":1 + }, + "RdsUngraceful":{ + "type":"structure", + "members":{ + "ungraceful":{ + "shape":"RdsUngracefulBehavior", + "documentation":"

    The ungraceful behavior to perform if switching to ungraceful execution.

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

    The ungraceful execution settings for an Amazon RDS switchover read replica execution block.

    " + }, + "RdsUngracefulBehavior":{ + "type":"string", + "documentation":"

    The ungraceful behavior for an Amazon RDS switchover read replica, that is, promote the read replica to a standalone primary.

    ", + "enum":["promoteReadReplica"] + }, "RecoveryApproach":{ "type":"string", "enum":[ @@ -2916,9 +2990,20 @@ "recoveryExecutionId":{ "shape":"RecoveryExecutionId", "documentation":"

    The execution identifier of the recovery execution that ran in the opposite region post-recovery is ran in. Required when starting a post-recovery execution.

    " + }, + "clientToken":{ + "shape":"StartPlanExecutionRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request and returns the result of the original successful request. If you don't provide a client token, the service automatically generates one. For more information about idempotency, see Making retries safe with idempotent APIs.

    ", + "idempotencyToken":true } } }, + "StartPlanExecutionRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, "StartPlanExecutionResponse":{ "type":"structure", "members":{ diff --git a/services/arczonalshift/pom.xml b/services/arczonalshift/pom.xml index b048e4702813..d4da0bf4ebf7 100644 --- a/services/arczonalshift/pom.xml +++ b/services/arczonalshift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT arczonalshift AWS Java SDK :: Services :: ARC Zonal Shift diff --git a/services/arczonalshift/src/main/resources/codegen-resources/customization.config b/services/arczonalshift/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/arczonalshift/src/main/resources/codegen-resources/customization.config +++ b/services/arczonalshift/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/arczonalshift/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/arczonalshift/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a7e221fbaf00 --- /dev/null +++ b/services/arczonalshift/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-zonal-shift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-zonal-shift-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-zonal-shift.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-zonal-shift.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/arczonalshift/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/arczonalshift/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8112ca9affb4..000000000000 --- a/services/arczonalshift/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-zonal-shift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-zonal-shift-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-zonal-shift.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://arc-zonal-shift.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/artifact/pom.xml b/services/artifact/pom.xml index 15a8853f242c..e6152dcf29ba 100644 --- a/services/artifact/pom.xml +++ b/services/artifact/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT artifact AWS Java SDK :: Services :: Artifact diff --git a/services/artifact/src/main/resources/codegen-resources/customization.config b/services/artifact/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/artifact/src/main/resources/codegen-resources/customization.config +++ b/services/artifact/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/artifact/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/artifact/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3895dfbb4c95 --- /dev/null +++ b/services/artifact/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,216 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://artifact-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://artifact-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://artifact.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://artifact.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/artifact/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/artifact/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fed0e11d843e..000000000000 --- a/services/artifact/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://artifact-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://artifact-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://artifact.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://artifact.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/artifact/src/main/resources/codegen-resources/service-2.json b/services/artifact/src/main/resources/codegen-resources/service-2.json index edcca3c7d407..82a1ec80af9c 100644 --- a/services/artifact/src/main/resources/codegen-resources/service-2.json +++ b/services/artifact/src/main/resources/codegen-resources/service-2.json @@ -287,6 +287,26 @@ "documentation":"

    Put the account settings for Artifact.

    ", "idempotent":true }, + "PutComplianceInquiryFeedback":{ + "name":"PutComplianceInquiryFeedback", + "http":{ + "method":"PUT", + "requestUri":"/v1/compliance-inquiry/putFeedback", + "responseCode":200 + }, + "input":{"shape":"PutComplianceInquiryFeedbackRequest"}, + "output":{"shape":"PutComplianceInquiryFeedbackResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Submits feedback on a compliance inquiry response.

    ", + "idempotent":true + }, "TagResource":{ "name":"TagResource", "http":{ @@ -430,7 +450,7 @@ ], "members":{ "name":{ - "shape":"String", + "shape":"InquiryName", "documentation":"

    Title of the inquiry.

    " }, "inquiryContent":{ @@ -570,6 +590,32 @@ } } }, + "FeedbackCommentAttribute":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"[a-zA-Z0-9\\s.,;:!?'\\-()/@#&+=]+", + "sensitive":true + }, + "FeedbackRating":{ + "type":"string", + "enum":[ + "THUMBS_UP", + "THUMBS_DOWN" + ] + }, + "FeedbackReasonCode":{ + "type":"string", + "enum":[ + "OTHER", + "PARTIAL_RESPONSE", + "IRRELEVANT_RESPONSE" + ] + }, + "FeedbackReasonCodeList":{ + "type":"list", + "member":{"shape":"FeedbackReasonCode"} + }, "GetAccountSettingsRequest":{ "type":"structure", "members":{} @@ -818,6 +864,10 @@ "type":"string", "pattern":"compliance-inquiry-[a-zA-Z0-9]{16}" }, + "InquiryName":{ + "type":"string", + "sensitive":true + }, "InquiryStatus":{ "type":"string", "enum":[ @@ -1148,6 +1198,54 @@ "accountSettings":{"shape":"AccountSettings"} } }, + "PutComplianceInquiryFeedbackRequest":{ + "type":"structure", + "required":[ + "complianceInquiryId", + "rating" + ], + "members":{ + "complianceInquiryId":{ + "shape":"InquiryId", + "documentation":"

    The unique identifier for the compliance inquiry.

    " + }, + "queryIdentifier":{ + "shape":"Integer", + "documentation":"

    The sequential identifier of the query to provide feedback on.

    " + }, + "rating":{ + "shape":"FeedbackRating", + "documentation":"

    The rating for the feedback. Valid values are THUMBS_UP and THUMBS_DOWN.

    " + }, + "responseRevisionId":{ + "shape":"Integer", + "documentation":"

    The response revision ID. Use this value to prevent submitting feedback on a stale response.

    " + }, + "reasonCodes":{ + "shape":"FeedbackReasonCodeList", + "documentation":"

    The reason codes that describe why you rated the response. Valid values are OTHER, PARTIAL_RESPONSE, and IRRELEVANT_RESPONSE.

    " + }, + "comment":{ + "shape":"FeedbackCommentAttribute", + "documentation":"

    An optional comment for the feedback.

    " + }, + "clientToken":{ + "shape":"IdempotentClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "PutComplianceInquiryFeedbackResponse":{ + "type":"structure", + "required":["submittedAt"], + "members":{ + "submittedAt":{ + "shape":"TimestampAttribute", + "documentation":"

    The timestamp when the feedback was submitted.

    " + } + } + }, "QueriesList":{ "type":"list", "member":{"shape":"QuerySummary"} diff --git a/services/athena/pom.xml b/services/athena/pom.xml index f43006d5dcfc..e23024869190 100644 --- a/services/athena/pom.xml +++ b/services/athena/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT athena AWS Java SDK :: Services :: Amazon Athena diff --git a/services/athena/src/main/resources/codegen-resources/customization.config b/services/athena/src/main/resources/codegen-resources/customization.config index a9daa25042de..3d64415e323b 100644 --- a/services/athena/src/main/resources/codegen-resources/customization.config +++ b/services/athena/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "listNamedQueries", "listQueryExecutions" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/athena/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/athena/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3ca1a9e2713b --- /dev/null +++ b/services/athena/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://athena-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://athena-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://athena.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://athena.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/athena/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/athena/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 75ba17c7d15d..000000000000 --- a/services/athena/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://athena-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://athena-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://athena.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://athena.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/auditmanager/pom.xml b/services/auditmanager/pom.xml index 7b207edc5505..909d8f326c39 100644 --- a/services/auditmanager/pom.xml +++ b/services/auditmanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT auditmanager AWS Java SDK :: Services :: Audit Manager diff --git a/services/auditmanager/src/main/resources/codegen-resources/customization.config b/services/auditmanager/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/auditmanager/src/main/resources/codegen-resources/customization.config +++ b/services/auditmanager/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/auditmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/auditmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e21e5e7cf30d --- /dev/null +++ b/services/auditmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://auditmanager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://auditmanager-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://auditmanager.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://auditmanager.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/auditmanager/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/auditmanager/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ee4dac13f961..000000000000 --- a/services/auditmanager/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://auditmanager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://auditmanager-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://auditmanager.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://auditmanager.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/autoscaling/pom.xml b/services/autoscaling/pom.xml index 503c47d86a3a..da419762d74a 100644 --- a/services/autoscaling/pom.xml +++ b/services/autoscaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT autoscaling AWS Java SDK :: Services :: Auto Scaling diff --git a/services/autoscaling/src/main/resources/codegen-resources/customization.config b/services/autoscaling/src/main/resources/codegen-resources/customization.config index 43e909112803..d2d1115c2022 100644 --- a/services/autoscaling/src/main/resources/codegen-resources/customization.config +++ b/services/autoscaling/src/main/resources/codegen-resources/customization.config @@ -15,8 +15,6 @@ "describeScheduledActions", "describeTags", "describeTerminationPolicyTypes" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/autoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/autoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a3b545842a76 --- /dev/null +++ b/services/autoscaling/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/autoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/autoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d035ac54ac26..000000000000 --- a/services/autoscaling/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://autoscaling.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/autoscaling/src/main/resources/codegen-resources/service-2.json b/services/autoscaling/src/main/resources/codegen-resources/service-2.json index 367cca7ac650..4c88d044f7e4 100644 --- a/services/autoscaling/src/main/resources/codegen-resources/service-2.json +++ b/services/autoscaling/src/main/resources/codegen-resources/service-2.json @@ -810,7 +810,8 @@ }, "errors":[ {"shape":"ResourceContentionFault"}, - {"shape":"IdempotentParameterMismatchError"} + {"shape":"IdempotentParameterMismatchError"}, + {"shape":"IdempotentCallInProgressFault"} ], "documentation":"

    Launches a specified number of instances in an Auto Scaling group. Returns instance IDs and other details if launch is successful or error details if launch is unsuccessful.

    " }, @@ -1031,7 +1032,7 @@ {"shape":"ScalingActivityInProgressFault"}, {"shape":"ResourceContentionFault"} ], - "documentation":"

    Terminates the specified instance and optionally adjusts the desired group size. This operation cannot be called on instances in a warm pool.

    This call simply makes a termination request. The instance is not terminated immediately. When an instance is terminated, the instance status changes to terminated. You can't connect to or start an instance after you've terminated it.

    If you do not specify the option to decrement the desired capacity, Amazon EC2 Auto Scaling launches instances to replace the ones that are terminated.

    By default, Amazon EC2 Auto Scaling balances instances across all Availability Zones. If you decrement the desired capacity, your Auto Scaling group can become unbalanced between Availability Zones. Amazon EC2 Auto Scaling tries to rebalance the group, and rebalancing might terminate instances in other zones. For more information, see Manual scaling in the Amazon EC2 Auto Scaling User Guide.

    " + "documentation":"

    Terminates the specified instance and optionally adjusts the desired group size. This operation cannot be called on instances in a warm pool.

    This call simply makes a termination request. The instances are not terminated immediately. When an instance is terminated, the instance status changes to terminated. You can't connect to or start an instance after you've terminated it.

    If you do not specify the option to decrement the desired capacity, Amazon EC2 Auto Scaling launches instances to replace the ones that are terminated.

    To terminate multiple instances in a single call, use the InstanceIds and AutoScalingGroupName parameters instead of InstanceId. When terminating multiple instances, the response populates Activities instead of Activity.

    By default, Amazon EC2 Auto Scaling balances instances across all Availability Zones. If you decrement the desired capacity, your Auto Scaling group can become unbalanced between Availability Zones. Amazon EC2 Auto Scaling tries to rebalance the group, and rebalancing might terminate instances in other zones. For more information, see Manual scaling in the Amazon EC2 Auto Scaling User Guide.

    " }, "UpdateAutoScalingGroup":{ "name":"UpdateAutoScalingGroup", @@ -1220,6 +1221,10 @@ "Activity":{ "shape":"Activity", "documentation":"

    A scaling activity.

    " + }, + "Activities":{ + "shape":"Activities", + "documentation":"

    The scaling activities related to terminating the instances from the Auto Scaling group.

    " } } }, @@ -1567,6 +1572,10 @@ "InstanceLifecyclePolicy":{ "shape":"InstanceLifecyclePolicy", "documentation":"

    The instance lifecycle policy for the Auto Scaling group.

    " + }, + "Operator":{ + "shape":"Operator", + "documentation":"

    The entity that manages the Auto Scaling group, if applicable. When set, only the designated operator can make changes to the group configuration.

    " } }, "documentation":"

    Describes an Auto Scaling group.

    " @@ -1715,7 +1724,7 @@ "members":{ "CapacityDistributionStrategy":{ "shape":"CapacityDistributionStrategy", - "documentation":"

    If launches fail in an Availability Zone, the following strategies are available. The default is balanced-best-effort.

    • balanced-only - If launches fail in an Availability Zone, Auto Scaling will continue to attempt to launch in the unhealthy zone to preserve a balanced distribution.

    • balanced-best-effort - If launches fail in an Availability Zone, Auto Scaling will attempt to launch in another healthy Availability Zone instead.

    • reservations-then-balanced - Auto Scaling will first attempt to launch into your Capacity Reservations, and then balance any remaining capacity across the healthy Availability Zones.

    " + "documentation":"

    If launches fail in an Availability Zone, the following strategies are available. The default is balanced-best-effort.

    • balanced-only - If launches fail in an Availability Zone, Auto Scaling will continue to attempt to launch in the unhealthy zone to preserve a balanced distribution.

    • balanced-best-effort - If launches fail in an Availability Zone, Auto Scaling will attempt to launch in another healthy Availability Zone instead.

    • reservations-then-balanced - Auto Scaling will first attempt to launch into your Capacity Reservations, and then balance any remaining capacity across healthy Availability Zones.

    " } }, "documentation":"

    Describes an Availability Zone distribution.

    " @@ -2095,7 +2104,7 @@ }, "MixedInstancesPolicy":{ "shape":"MixedInstancesPolicy", - "documentation":"

    The mixed instances policy. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    " + "documentation":"

    The mixed instances policy. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide. To learn how to prioritize multiple capacity types, see Use Distribution Segments to target multiple capacity types in the Amazon EC2 Auto Scaling User Guide.

    " }, "InstanceId":{ "shape":"XmlStringMaxLen19", @@ -2220,6 +2229,10 @@ "InstanceLifecyclePolicy":{ "shape":"InstanceLifecyclePolicy", "documentation":"

    The instance lifecycle policy for the Auto Scaling group. This policy controls instance behavior when an instance transitions through its lifecycle states. Configure retention triggers to specify when instances should move to a Retained state instead of automatic termination.

    For more information, see Control instance retention with instance lifecycle policies in the Amazon EC2 Auto Scaling User Guide.

    Instances in a Retained state will continue to incur standard EC2 charges until terminated.

    " + }, + "Operator":{ + "shape":"Operator", + "documentation":"

    The entity that manages the Auto Scaling group. If you specify this parameter, Amazon EC2 Auto Scaling passes the operator identity to EC2 for instance launches and only allows the designated operator to make changes to the Auto Scaling group. All mutating API calls from non-operator callers are rejected with an AccessDenied exception.

    " } } }, @@ -2886,7 +2899,7 @@ }, "MixedInstancesPolicy":{ "shape":"MixedInstancesPolicy", - "documentation":"

    Use this structure to launch multiple instance types and On-Demand Instances and Spot Instances within a single Auto Scaling group.

    A mixed instances policy contains information that Amazon EC2 Auto Scaling can use to launch instances and help optimize your costs. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    " + "documentation":"

    Use this structure to launch multiple instance types and configure how capacity is distributed across On-Demand, Spot, and supported Capacity Reservation types within a single Auto Scaling group.

    A mixed instances policy contains information that Amazon EC2 Auto Scaling can use to launch instances, prioritize capacity types, and help optimize your costs. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    " } }, "documentation":"

    Describes the desired configuration for an instance refresh.

    If you specify a desired configuration, you must specify either a LaunchTemplate or a MixedInstancesPolicy.

    " @@ -2999,6 +3012,20 @@ } }, "DisableScaleIn":{"type":"boolean"}, + "DistributionSegment":{ + "type":"structure", + "members":{ + "TargetCapacityTypes":{ + "shape":"TargetCapacityTypes", + "documentation":"

    The capacity types to prioritize, in order. Amazon EC2 Auto Scaling attempts to launch instances in the priority order of the capacity types, and within each capacity type, in the order of instance types listed in your launch template Overrides.

    The following lists the valid values:

    on-demand-capacity-reservation

    On-Demand Capacity Reservations.

    capacity-block

    Capacity Blocks.

    interruptible-capacity-reservation

    Interruptible Capacity Reservations.

    on-demand

    On-Demand capacity. Include this value to allow the group to fall back to On-Demand capacity when the preceding capacity types are unavailable.

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

    Use this structure to specify the capacity types that Amazon EC2 Auto Scaling prioritizes when it launches instances.

    " + }, + "DistributionSegments":{ + "type":"list", + "member":{"shape":"DistributionSegment"} + }, "Ebs":{ "type":"structure", "members":{ @@ -3259,6 +3286,19 @@ "HealthCheckGracePeriod":{"type":"integer"}, "HeartbeatTimeout":{"type":"integer"}, "HonorCooldown":{"type":"boolean"}, + "IdempotentCallInProgressFault":{ + "type":"structure", + "members":{ + "Message":{"shape":"XmlStringMaxLen255"} + }, + "documentation":"

    The service is currently processing another request with the same client token. Retry the request with the same client token—the in-flight operation will complete and return its result.

    ", + "error":{ + "code":"IdempotentCallInProgress", + "httpStatusCode":500, + "senderFault":true + }, + "exception":true + }, "IdempotentParameterMismatchError":{ "type":"structure", "members":{ @@ -3751,9 +3791,13 @@ "SpotMaxPrice":{ "shape":"MixedInstanceSpotPrice", "documentation":"

    The maximum price per unit hour that you are willing to pay for a Spot Instance. If your maximum price is lower than the Spot price for the instance types that you selected, your Spot Instances are not launched. We do not recommend specifying a maximum price because it can lead to increased interruptions. When Spot Instances launch, you pay the current Spot price. To remove a maximum price that you previously set, include the property but specify an empty string (\"\") for the value.

    If you specify a maximum price, your instances will be interrupted more frequently than if you do not specify one.

    Valid Range: Minimum value of 0.001

    " + }, + "DistributionSegments":{ + "shape":"DistributionSegments", + "documentation":"

    The Distribution Segments configuration. Each segment contains an ordered list of capacity types to prioritize.

    For more information, see Use Distribution Segments to target multiple capacity types in the Amazon EC2 Auto Scaling User Guide.

    " } }, - "documentation":"

    Use this structure to specify the distribution of On-Demand Instances and Spot Instances and the allocation strategies used to fulfill On-Demand and Spot capacities for a mixed instances policy.

    " + "documentation":"

    Use this structure to specify how a mixed instances policy distributes capacity across On-Demand, Spot, and supported Capacity Reservation types, and to specify the allocation strategies that are used to fulfill the capacity.

    " }, "InstancesToUpdate":{ "type":"integer", @@ -4348,6 +4392,11 @@ "type":"list", "member":{"shape":"LocalStorageType"} }, + "ManagerIdentifier":{ + "type":"string", + "max":128, + "min":1 + }, "MaxGroupPreparedCapacity":{ "type":"integer", "min":-1 @@ -4558,14 +4607,14 @@ "members":{ "LaunchTemplate":{ "shape":"LaunchTemplate", - "documentation":"

    One or more launch templates and the instance types (overrides) that are used to launch EC2 instances to fulfill On-Demand and Spot capacities.

    " + "documentation":"

    One or more launch templates and the instance types (overrides) that are used to launch EC2 instances to fulfill the configured capacities.

    " }, "InstancesDistribution":{ "shape":"InstancesDistribution", "documentation":"

    The instances distribution.

    " } }, - "documentation":"

    Use this structure to launch multiple instance types and On-Demand Instances and Spot Instances within a single Auto Scaling group.

    A mixed instances policy contains information that Amazon EC2 Auto Scaling can use to launch instances and help optimize your costs. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    " + "documentation":"

    Use this structure to launch multiple instance types and configure how capacity is distributed across On-Demand, Spot, and supported Capacity Reservation types within a single Auto Scaling group.

    A mixed instances policy contains information that Amazon EC2 Auto Scaling can use to launch instances, prioritize capacity types, and help optimize your costs. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide. To learn how to prioritize multiple capacity types, see Use Distribution Segments to target multiple capacity types in the Amazon EC2 Auto Scaling User Guide.

    " }, "MonitoringEnabled":{"type":"boolean"}, "NetworkBandwidthGbpsRequest":{ @@ -4643,6 +4692,17 @@ "NumberOfLaunchConfigurations":{"type":"integer"}, "OnDemandBaseCapacity":{"type":"integer"}, "OnDemandPercentageAboveBaseCapacity":{"type":"integer"}, + "Operator":{ + "type":"structure", + "required":["Principal"], + "members":{ + "Principal":{ + "shape":"ManagerIdentifier", + "documentation":"

    The service principal that is authorized to manage the Auto Scaling group. When an operator is specified, only the designated operator service principal can make mutating changes to the Auto Scaling group.

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

    Describes the entity that manages an Auto Scaling group.

    " + }, "Overrides":{ "type":"list", "member":{"shape":"LaunchTemplateOverrides"} @@ -5233,7 +5293,7 @@ }, "MaxHealthyPercentage":{ "shape":"IntPercent100To200", - "documentation":"

    Specifies the maximum percentage of the group that can be in service and healthy, or pending, to support your workload when replacing instances. The value is expressed as a percentage of the desired capacity of the Auto Scaling group. Value range is 100 to 200.

    If you specify MaxHealthyPercentage, you must also specify MinHealthyPercentage, and the difference between them cannot be greater than 100. A larger range increases the number of instances that can be replaced at the same time.

    If you do not specify this property, the default is 100 percent, or the percentage set in the instance maintenance policy for the Auto Scaling group, if defined.

    " + "documentation":"

    Specifies the maximum percentage of the group that can be in service and healthy, or pending, to support your workload when replacing instances. The value is expressed as a percentage of the desired capacity of the Auto Scaling group. Value range is 100 to 200.

    If you specify MaxHealthyPercentage, you must also specify MinHealthyPercentage, and the difference between them cannot be greater than 100. A larger range increases the number of instances that can be replaced at the same time.

    If you do not specify this property, the default is 100 percent, or the percentage set in the instance maintenance policy for the Auto Scaling group, if defined.

    Explicitly setting MaxHealthyPercentage to 100 is not equivalent to omitting it. When MaxHealthyPercentage is explicitly set and it is mathematically impossible to replace instances while honoring both MinHealthyPercentage and MaxHealthyPercentage bounds simultaneously, Auto Scaling launches a new instance before terminating an old one (temporarily exceeding the desired capacity). When MaxHealthyPercentage is omitted, Auto Scaling terminates an instance and launches its replacement simultaneously. This behavioral difference can affect workflows that depend on instance replacement ordering.

    " }, "BakeTime":{ "shape":"BakeTime", @@ -5877,6 +5937,19 @@ } } }, + "TargetCapacityType":{ + "type":"string", + "enum":[ + "on-demand-capacity-reservation", + "capacity-block", + "interruptible-capacity-reservation", + "on-demand" + ] + }, + "TargetCapacityTypes":{ + "type":"list", + "member":{"shape":"TargetCapacityType"} + }, "TargetGroupARNs":{ "type":"list", "member":{"shape":"XmlStringMaxLen511"} @@ -5967,21 +6040,32 @@ }, "TerminateInstanceInAutoScalingGroupType":{ "type":"structure", - "required":[ - "InstanceId", - "ShouldDecrementDesiredCapacity" - ], + "required":["ShouldDecrementDesiredCapacity"], "members":{ "InstanceId":{ "shape":"XmlStringMaxLen19", "documentation":"

    The ID of the instance.

    " }, + "InstanceIds":{ + "shape":"TerminationInstanceIds", + "documentation":"

    The IDs of the instances. You can specify up to 100 instances.

    This parameter requires that you also specify AutoScalingGroupName.

    " + }, + "AutoScalingGroupName":{ + "shape":"XmlStringMaxLen255", + "documentation":"

    The name of the Auto Scaling group. Required when using InstanceIds.

    " + }, "ShouldDecrementDesiredCapacity":{ "shape":"ShouldDecrementDesiredCapacity", "documentation":"

    Indicates whether terminating the instance also decrements the size of the Auto Scaling group.

    " } } }, + "TerminationInstanceIds":{ + "type":"list", + "member":{"shape":"XmlStringMaxLen19"}, + "max":100, + "min":1 + }, "TerminationPolicies":{ "type":"list", "member":{"shape":"XmlStringMaxLen1600"} @@ -6066,7 +6150,7 @@ }, "MixedInstancesPolicy":{ "shape":"MixedInstancesPolicy", - "documentation":"

    The mixed instances policy. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    " + "documentation":"

    The mixed instances policy. For more information, see Auto Scaling groups with multiple instance types and purchase options in the Amazon EC2 Auto Scaling User Guide.

    You can remove the Distribution Segments configuration by specifying OnDemandBaseCapacity or OnDemandPercentageAboveBaseCapacity. You can also remove it explicitly by specifying an empty list for DistributionSegments.

    " }, "MinSize":{ "shape":"AutoScalingGroupMinSize", diff --git a/services/autoscalingplans/pom.xml b/services/autoscalingplans/pom.xml index 351b7ec2b751..238ebf813cbe 100644 --- a/services/autoscalingplans/pom.xml +++ b/services/autoscalingplans/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT autoscalingplans AWS Java SDK :: Services :: Auto Scaling Plans diff --git a/services/autoscalingplans/src/main/resources/codegen-resources/customization.config b/services/autoscalingplans/src/main/resources/codegen-resources/customization.config index eada5dbbe962..46cf450eb96e 100644 --- a/services/autoscalingplans/src/main/resources/codegen-resources/customization.config +++ b/services/autoscalingplans/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "describeScalingPlans" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e9c22484d81b --- /dev/null +++ b/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://autoscaling-plans.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index df1bd6c02d6c..000000000000 --- a/services/autoscalingplans/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-plans-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://autoscaling-plans.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://autoscaling-plans.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-plans-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-plans.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://autoscaling-plans.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/b2bi/pom.xml b/services/b2bi/pom.xml index 2d5584d2cd11..969dc9e6f3d5 100644 --- a/services/b2bi/pom.xml +++ b/services/b2bi/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT b2bi AWS Java SDK :: Services :: B2 Bi diff --git a/services/b2bi/src/main/resources/codegen-resources/customization.config b/services/b2bi/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/b2bi/src/main/resources/codegen-resources/customization.config +++ b/services/b2bi/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/b2bi/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/b2bi/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a65fcf816bda --- /dev/null +++ b/services/b2bi/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://b2bi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://b2bi-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://b2bi.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://b2bi.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/b2bi/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/b2bi/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4f9fa8a6f3da..000000000000 --- a/services/b2bi/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://b2bi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://b2bi-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://b2bi.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://b2bi.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/backup/pom.xml b/services/backup/pom.xml index 13c615b67ace..be2ab8375fa0 100644 --- a/services/backup/pom.xml +++ b/services/backup/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT backup AWS Java SDK :: Services :: Backup diff --git a/services/backup/src/main/resources/codegen-resources/customization.config b/services/backup/src/main/resources/codegen-resources/customization.config index d259e73cd1ec..6b4840597fb3 100644 --- a/services/backup/src/main/resources/codegen-resources/customization.config +++ b/services/backup/src/main/resources/codegen-resources/customization.config @@ -9,6 +9,5 @@ "listBackupVaults", "listProtectedResources", "listRestoreJobs" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/backup/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/backup/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..868ed110f332 --- /dev/null +++ b/services/backup/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/backup/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/backup/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b7625343c1e1..000000000000 --- a/services/backup/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://backup.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/backup/src/main/resources/codegen-resources/paginators-1.json b/services/backup/src/main/resources/codegen-resources/paginators-1.json index 9b84e98551f1..03f55a3a0ed0 100644 --- a/services/backup/src/main/resources/codegen-resources/paginators-1.json +++ b/services/backup/src/main/resources/codegen-resources/paginators-1.json @@ -1,5 +1,23 @@ { "pagination": { + "ListBackupAccessPoints": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "BackupAccessPoints" + }, + "ListBackupAccessPointsByRecoveryPoint": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "BackupAccessPoints" + }, + "ListBackupAccessPointsByResource": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "BackupAccessPoints" + }, "ListBackupJobSummaries": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/backup/src/main/resources/codegen-resources/service-2.json b/services/backup/src/main/resources/codegen-resources/service-2.json index 8f2313a90ca8..ba72e4e19bdc 100644 --- a/services/backup/src/main/resources/codegen-resources/service-2.json +++ b/services/backup/src/main/resources/codegen-resources/service-2.json @@ -49,6 +49,28 @@ "documentation":"

    Removes the specified legal hold on a recovery point. This action can only be performed by a user with sufficient permissions.

    ", "idempotent":true }, + "CreateBackupAccessPoint":{ + "name":"CreateBackupAccessPoint", + "http":{ + "method":"PUT", + "requestUri":"/backup-access-point/create", + "responseCode":201 + }, + "input":{"shape":"CreateBackupAccessPointRequest"}, + "output":{"shape":"CreateBackupAccessPointResponse"}, + "errors":[ + {"shape":"AlreadyExistsException"}, + {"shape":"ConflictException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InvalidRequestException"}, + {"shape":"LimitExceededException"}, + {"shape":"MissingParameterValueException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Creates a backup access point for an Amazon S3 recovery point. A backup access point provides on-demand, read-only access to the backup data in a recovery point through an Amazon S3 access point, without initiating a restore.

    While a backup access point is active for a recovery point, Backup pauses lifecycle transitions and blocks deletion of that recovery point.

    ", + "idempotent":true + }, "CreateBackupPlan":{ "name":"CreateBackupPlan", "http":{ @@ -254,6 +276,24 @@ "documentation":"

    Creates a tiering configuration.

    A tiering configuration enables automatic movement of backup data to a lower-cost storage tier based on the age of backed-up objects in the backup vault.

    Each vault can only have one vault-specific tiering configuration, in addition to any global configuration that applies to all vaults.

    ", "idempotent":true }, + "DeleteBackupAccessPoint":{ + "name":"DeleteBackupAccessPoint", + "http":{ + "method":"DELETE", + "requestUri":"/backup-access-point/delete/{AccessPointArn}", + "responseCode":204 + }, + "input":{"shape":"DeleteBackupAccessPointInput"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"InvalidRequestException"}, + {"shape":"MissingParameterValueException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Deletes a backup access point. This deletes the underlying Amazon S3 access point and, if no other backup access points remain for the recovery point, resumes lifecycle transitions for that recovery point.

    Always delete backup access points using this operation rather than deleting the underlying Amazon S3 access point directly.

    ", + "idempotent":true + }, "DeleteBackupPlan":{ "name":"DeleteBackupPlan", "http":{ @@ -450,6 +490,25 @@ "documentation":"

    Deletes the tiering configuration specified by a tiering configuration name.

    ", "idempotent":true }, + "DescribeBackupAccessPoint":{ + "name":"DescribeBackupAccessPoint", + "http":{ + "method":"GET", + "requestUri":"/backup-access-point/{AccessPointArn}", + "responseCode":200 + }, + "input":{"shape":"DescribeBackupAccessPointInput"}, + "output":{"shape":"DescribeBackupAccessPointResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"InvalidRequestException"}, + {"shape":"MissingParameterValueException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Returns metadata about a backup access point, including its status and the details of the underlying Amazon S3 access point.

    After a backup access point reaches the AVAILABLE status, use this operation to retrieve the Amazon S3 access point ARN and alias that you need to read the backup data.

    ", + "readonly":true + }, "DescribeBackupJob":{ "name":"DescribeBackupJob", "http":{ @@ -975,6 +1034,54 @@ "documentation":"

    Returns TieringConfiguration details for the specified TieringConfigurationName. The details are the body of a tiering configuration in JSON format, in addition to configuration metadata.

    ", "idempotent":true }, + "ListBackupAccessPoints":{ + "name":"ListBackupAccessPoints", + "http":{ + "method":"GET", + "requestUri":"/backup-access-point", + "responseCode":200 + }, + "input":{"shape":"ListBackupAccessPointsRequest"}, + "output":{"shape":"ListBackupAccessPointsResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Returns a list of the backup access points in your account and Region.

    ", + "readonly":true + }, + "ListBackupAccessPointsByRecoveryPoint":{ + "name":"ListBackupAccessPointsByRecoveryPoint", + "http":{ + "method":"POST", + "requestUri":"/backup-access-point/recovery-point/{RecoveryPointArn}", + "responseCode":200 + }, + "input":{"shape":"ListBackupAccessPointsByRecoveryPointRequest"}, + "output":{"shape":"ListBackupAccessPointsByRecoveryPointResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Returns the backup access points associated with the specified recovery point.

    If you own the recovery point and have shared it with other accounts, the response includes backup access points created by those accounts.

    ", + "readonly":true + }, + "ListBackupAccessPointsByResource":{ + "name":"ListBackupAccessPointsByResource", + "http":{ + "method":"POST", + "requestUri":"/backup-access-point/resource/{ResourceArn}", + "responseCode":200 + }, + "input":{"shape":"ListBackupAccessPointsByResourceRequest"}, + "output":{"shape":"ListBackupAccessPointsByResourceResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Returns the backup access points associated with the specified resource, such as an Amazon S3 bucket.

    ", + "readonly":true + }, "ListBackupJobSummaries":{ "name":"ListBackupJobSummaries", "http":{ @@ -987,7 +1094,7 @@ {"shape":"InvalidParameterValueException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    This is a request for a summary of backup jobs created or running within the most recent 30 days. You can include parameters AccountID, State, ResourceType, MessageCategory, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, ResourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This is a request for a summary of backup jobs created or running within the most recent 14 days. You can include parameters AccountID, State, ResourceType, MessageCategory, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, ResourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "ListBackupJobs":{ "name":"ListBackupJobs", @@ -1100,7 +1207,7 @@ {"shape":"InvalidParameterValueException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    This request obtains a list of copy jobs created or running within the the most recent 30 days. You can include parameters AccountID, State, ResourceType, MessageCategory, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This request obtains a list of copy jobs created or running within the the most recent 14 days. You can include parameters AccountID, State, ResourceType, MessageCategory, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "ListCopyJobs":{ "name":"ListCopyJobs", @@ -1173,7 +1280,7 @@ {"shape":"InvalidParameterValueException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    Returns an array of resources successfully backed up by Backup, including the time the resource was saved, an Amazon Resource Name (ARN) of the resource, and a resource type.

    ", + "documentation":"

    Returns an array of resources with recovery points created by Backup (regardless of the recovery point's status), including the time the resource was saved, an Amazon Resource Name (ARN) of the resource, and a resource type.

    ", "idempotent":true }, "ListProtectedResourcesByBackupVault":{ @@ -1298,7 +1405,7 @@ {"shape":"InvalidParameterValueException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    This request obtains a summary of restore jobs created or running within the the most recent 30 days. You can include parameters AccountID, State, ResourceType, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This request obtains a summary of restore jobs created or running within the the most recent 14 days. You can include parameters AccountID, State, ResourceType, AggregationPeriod, MaxResults, or NextToken to filter results.

    This request returns a summary that contains Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "ListRestoreJobs":{ "name":"ListRestoreJobs", @@ -1376,7 +1483,7 @@ {"shape":"InvalidParameterValueException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    This is a request for a summary of scan jobs created or running within the most recent 30 days.

    " + "documentation":"

    This is a request for a summary of scan jobs created or running within the most recent 14 days.

    " }, "ListScanJobs":{ "name":"ListScanJobs", @@ -1832,6 +1939,47 @@ }, "shapes":{ "ARN":{"type":"string"}, + "AccessPointArn":{ + "type":"string", + "pattern":"(arn:aws[a-z-]*:backup:[a-z-\\d]+:\\d{12}:accesspoint/)[\\da-z]{1}[\\da-z-]{1,48}[\\da-z]{1}(?The value of time in number format of a job end time.

    This value is the time in Unix format, Coordinated Universal Time (UTC), and accurate to milliseconds. For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " } }, - "documentation":"

    This is a summary of jobs created or running within the most recent 30 days.

    The returned summary may contain the following: Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This is a summary of jobs created or running within the most recent 14 days.

    The returned summary may contain the following: Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "BackupJobSummaryList":{ "type":"list", @@ -2478,6 +2630,7 @@ }, "documentation":"

    Contains metadata about a BackupSelection object.

    " }, + "BackupVaultArn":{"type":"string"}, "BackupVaultEvent":{ "type":"string", "enum":[ @@ -2504,7 +2657,13 @@ "RECOVERY_POINT_INDEXING_FAILED", "EKS_RESTORE_OBJECT_FAILED", "EKS_RESTORE_OBJECT_SKIPPED", - "EKS_BACKUP_OBJECT_FAILED" + "EKS_BACKUP_OBJECT_FAILED", + "ACCESS_POINT_AVAILABLE", + "ACCESS_POINT_CREATION_FAILED", + "ACCESS_POINT_DELETED", + "ACCESS_POINT_DELETION_FAILED", + "ACCESS_POINT_EXPIRED", + "ACCESS_POINT_DISASSOCIATED" ] }, "BackupVaultEvents":{ @@ -2548,7 +2707,7 @@ }, "NumberOfRecoveryPoints":{ "shape":"long", - "documentation":"

    The number of recovery points that are stored in a backup vault.

    " + "documentation":"

    The number of recovery points that are stored in a backup vault. Recovery point count value displayed in the console can be an approximation.

    " }, "Locked":{ "shape":"Boolean", @@ -2947,7 +3106,7 @@ "documentation":"

    The value of time in number format of a job end time.

    This value is the time in Unix format, Coordinated Universal Time (UTC), and accurate to milliseconds. For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " } }, - "documentation":"

    This is a summary of copy jobs created or running within the most recent 30 days.

    The returned summary may contain the following: Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This is a summary of copy jobs created or running within the most recent 14 days.

    The returned summary may contain the following: Region, Account, State, RestourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "CopyJobSummaryList":{ "type":"list", @@ -2957,6 +3116,52 @@ "type":"list", "member":{"shape":"CopyJob"} }, + "CreateBackupAccessPointRequest":{ + "type":"structure", + "required":[ + "Name", + "RecoveryPointArn" + ], + "members":{ + "AccessPointMetadata":{ + "shape":"AccessPointMetadataMap", + "documentation":"

    Metadata for the backup access point. For continuous (point-in-time) recovery points, you must include an AccessPointInTime timestamp (in format 2021-11-27T03:30:27Z). The access point provides access to the content present in the backup at that specific time. You can specify any time within the continuous backup's retention period, up to the latest restorable time. For snapshot recovery points, do not include AccessPointInTime.

    " + }, + "AccessPointPolicy":{ + "shape":"AccessPointPolicy", + "documentation":"

    An optional resource-based policy, in JSON format, to apply to the underlying Amazon S3 access point. The policy controls how backup data can be accessed through the access point. If you do not specify a policy, access is governed by the caller's IAM permissions. For more information, see Configuring IAM policies for using access points in the Amazon S3 User Guide.

    " + }, + "Name":{ + "shape":"AccessPointName", + "documentation":"

    The name of the backup access point. This name is shared with the Amazon S3 access point namespace. It must be unique within your account and Region and cannot conflict with an existing Amazon S3 access point. For more information about access point naming, see Access points naming rules, restrictions, and limitations in the Amazon S3 User Guide.

    " + }, + "RecoveryPointArn":{ + "shape":"RecoveryPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recovery point for which to create the backup access point. The recovery point must be an Amazon S3 recovery point in the AVAILABLE, STOPPED, or COMPLETED state.

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

    The tags to assign to the backup access point.

    " + } + } + }, + "CreateBackupAccessPointResponse":{ + "type":"structure", + "required":[ + "AccessPointArn", + "Status" + ], + "members":{ + "AccessPointArn":{ + "shape":"AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the created backup access point.

    " + }, + "Status":{ + "shape":"AccessPointStatus", + "documentation":"

    The current status of the backup access point. A newly created backup access point begins in the CREATING state and becomes usable when it reaches AVAILABLE.

    " + } + } + }, "CreateBackupPlanInput":{ "type":"structure", "required":["BackupPlan"], @@ -3494,6 +3699,18 @@ }, "documentation":"

    This is a resource filter containing FromDate: DateTime and ToDate: DateTime. Both values are required. Future DateTime values are not permitted.

    The date and time are in Unix format and Coordinated Universal Time (UTC), and it is accurate to milliseconds ((milliseconds are optional). For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " }, + "DeleteBackupAccessPointInput":{ + "type":"structure", + "required":["AccessPointArn"], + "members":{ + "AccessPointArn":{ + "shape":"AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup access point to delete.

    ", + "location":"uri", + "locationName":"AccessPointArn" + } + } + }, "DeleteBackupPlanInput":{ "type":"structure", "required":["BackupPlanId"], @@ -3708,6 +3925,77 @@ "exception":true, "fault":true }, + "DescribeBackupAccessPointInput":{ + "type":"structure", + "required":["AccessPointArn"], + "members":{ + "AccessPointArn":{ + "shape":"AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup access point to describe.

    ", + "location":"uri", + "locationName":"AccessPointArn" + } + } + }, + "DescribeBackupAccessPointResponse":{ + "type":"structure", + "required":[ + "AccessPointArn", + "BackupVaultName", + "CreationTime", + "Name", + "RecoveryPointArn", + "ResourceArn", + "ResourceType", + "Status" + ], + "members":{ + "AccessPointArn":{ + "shape":"AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the backup access point.

    " + }, + "AccessPointMetadata":{ + "shape":"AccessPointMetadataMap", + "documentation":"

    Metadata for the backup access point. After the backup access point reaches the AVAILABLE status, this map contains S3AccessPointArn and S3AccessPointAlias, which you use with standard Amazon S3 read APIs to access the backup data. For continuous recovery points, this map also contains AccessPointInTime (in format 2021-11-27T03:30:27Z). The access point provides access to the content present in the backup at that specific time.

    " + }, + "BackupVaultArn":{ + "shape":"BackupVaultArn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup vault that contains the recovery point.

    " + }, + "BackupVaultName":{ + "shape":"BackupVaultName", + "documentation":"

    The name of the backup vault that contains the recovery point.

    " + }, + "CreationTime":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the backup access point was created, in Unix format and Coordinated Universal Time (UTC). The value of CreationTime is accurate to milliseconds. For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " + }, + "Name":{ + "shape":"AccessPointName", + "documentation":"

    The name of the backup access point.

    " + }, + "RecoveryPointArn":{ + "shape":"RecoveryPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recovery point that the backup access point provides access to.

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

    The Amazon Resource Name (ARN) of the resource that was backed up, such as an Amazon S3 bucket.

    " + }, + "ResourceType":{ + "shape":"String", + "documentation":"

    The type of Amazon Web Services resource associated with the recovery point. For example, S3 for Amazon Simple Storage Service.

    " + }, + "Status":{ + "shape":"AccessPointStatus", + "documentation":"

    The current status of the backup access point.

    " + }, + "StatusMessage":{ + "shape":"String", + "documentation":"

    A message that provides additional detail about the status of the backup access point, such as the reason a creation or deletion attempt failed.

    " + } + } + }, "DescribeBackupJobInput":{ "type":"structure", "required":["BackupJobId"], @@ -5569,6 +5857,192 @@ "documentation":"

    A limit in the request has been exceeded; for example, a maximum number of items allowed in a request.

    ", "exception":true }, + "ListAccessPointsMember":{ + "type":"structure", + "required":[ + "AccessPointArn", + "AccessPointMetadata", + "BackupVaultName", + "CreationTime", + "Name", + "RecoveryPointArn", + "ResourceArn", + "ResourceType", + "Status" + ], + "members":{ + "AccessPointArn":{ + "shape":"AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the backup access point.

    " + }, + "AccessPointMetadata":{ + "shape":"AccessPointMetadataMap", + "documentation":"

    Metadata for the backup access point. After the backup access point reaches the AVAILABLE status, this map contains S3AccessPointArn and S3AccessPointAlias, which you use with standard Amazon S3 read APIs to access the backup data. For continuous recovery points, this map also contains AccessPointInTime (in format 2021-11-27T03:30:27Z). The access point provides access to the content present in the backup at that specific time.

    " + }, + "BackupVaultArn":{ + "shape":"BackupVaultArn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup vault that contains the recovery point.

    " + }, + "BackupVaultName":{ + "shape":"BackupVaultName", + "documentation":"

    The name of the backup vault that contains the recovery point.

    " + }, + "CreationTime":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the backup access point was created, in Unix format and Coordinated Universal Time (UTC). The value of CreationTime is accurate to milliseconds. For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " + }, + "Name":{ + "shape":"AccessPointName", + "documentation":"

    The name of the backup access point.

    " + }, + "RecoveryPointArn":{ + "shape":"RecoveryPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recovery point that the backup access point provides access to.

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

    The Amazon Resource Name (ARN) of the resource that was backed up, such as an Amazon S3 bucket.

    " + }, + "ResourceType":{ + "shape":"String", + "documentation":"

    The type of Amazon Web Services resource associated with the recovery point. For example, S3 for Amazon Simple Storage Service.

    " + }, + "Status":{ + "shape":"AccessPointStatus", + "documentation":"

    The current status of the backup access point.

    " + }, + "StatusMessage":{ + "shape":"String", + "documentation":"

    A message that provides additional detail about the status of the backup access point, such as the reason a creation or deletion attempt failed.

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

    Contains metadata about a backup access point.

    " + }, + "ListBackupAccessPointsByRecoveryPointRequest":{ + "type":"structure", + "required":["RecoveryPointArn"], + "members":{ + "MaxResults":{ + "shape":"ListBackupAccessPointsByRecoveryPointRequestMaxResultsInteger", + "documentation":"

    The maximum number of items to be returned.

    ", + "location":"querystring", + "locationName":"MaxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    ", + "location":"querystring", + "locationName":"NextToken" + }, + "RecoveryPointArn":{ + "shape":"RecoveryPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recovery point whose backup access points you want to list.

    ", + "location":"uri", + "locationName":"RecoveryPointArn" + } + } + }, + "ListBackupAccessPointsByRecoveryPointRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListBackupAccessPointsByRecoveryPointResponse":{ + "type":"structure", + "required":["BackupAccessPoints"], + "members":{ + "BackupAccessPoints":{ + "shape":"BackupAccessPoints", + "documentation":"

    A list of backup access points, each containing metadata such as its name, ARN, status, and associated recovery point.

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

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    " + } + } + }, + "ListBackupAccessPointsByResourceRequest":{ + "type":"structure", + "required":["ResourceArn"], + "members":{ + "MaxResults":{ + "shape":"ListBackupAccessPointsByResourceRequestMaxResultsInteger", + "documentation":"

    The maximum number of items to be returned.

    ", + "location":"querystring", + "locationName":"MaxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    ", + "location":"querystring", + "locationName":"NextToken" + }, + "ResourceArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource whose backup access points you want to list.

    ", + "location":"uri", + "locationName":"ResourceArn" + } + } + }, + "ListBackupAccessPointsByResourceRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListBackupAccessPointsByResourceResponse":{ + "type":"structure", + "required":["BackupAccessPoints"], + "members":{ + "BackupAccessPoints":{ + "shape":"BackupAccessPoints", + "documentation":"

    A list of backup access points, each containing metadata such as its name, ARN, status, and associated recovery point.

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

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    " + } + } + }, + "ListBackupAccessPointsRequest":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"ListBackupAccessPointsRequestMaxResultsInteger", + "documentation":"

    The maximum number of items to be returned.

    ", + "location":"querystring", + "locationName":"MaxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    ", + "location":"querystring", + "locationName":"NextToken" + } + } + }, + "ListBackupAccessPointsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListBackupAccessPointsResponse":{ + "type":"structure", + "required":["BackupAccessPoints"], + "members":{ + "BackupAccessPoints":{ + "shape":"BackupAccessPoints", + "documentation":"

    A list of backup access points, each containing metadata such as its name, ARN, status, and associated recovery point.

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

    The next item following a partial list of returned items. For example, if a request is made to return MaxResults number of items, NextToken allows you to return more items in your list starting at the location pointed to by the next token.

    " + } + } + }, "ListBackupJobSummariesInput":{ "type":"structure", "members":{ @@ -6414,7 +6888,7 @@ }, "ManagedByAWSBackupOnly":{ "shape":"boolean", - "documentation":"

    This attribute filters recovery points based on ownership.

    If this is set to TRUE, the response will contain recovery points associated with the selected resources that are managed by Backup.

    If this is set to FALSE, the response will contain all recovery points associated with the selected resource.

    Type: Boolean

    ", + "documentation":"

    This attribute filters recovery points based on ownership.

    If this is set to TRUE, the response will contain recovery points associated with the selected resources that are managed by Backup.

    If this is set to FALSE, the response will contain all recovery points associated with the selected resource, except for EBS snapshots copied within the same Region and account.

    Type: Boolean

    ", "location":"querystring", "locationName":"managedByAWSBackupOnly" } @@ -7264,6 +7738,10 @@ } } }, + "RecoveryPointArn":{ + "type":"string", + "pattern":"(arn:aws[a-z-]*:[a-z-\\d]+:[a-z-\\d]+:).+" + }, "RecoveryPointByBackupVault":{ "type":"structure", "members":{ @@ -7717,6 +8195,10 @@ "type":"string", "sensitive":true }, + "ResourceArn":{ + "type":"string", + "pattern":"(arn:aws[a-z-]*:[a-z-\\d]+:).+" + }, "ResourceArns":{ "type":"list", "member":{"shape":"ARN"} @@ -7895,7 +8377,7 @@ "documentation":"

    The value of time in number format of a job end time.

    This value is the time in Unix format, Coordinated Universal Time (UTC), and accurate to milliseconds. For example, the value 1516925490.087 represents Friday, January 26, 2018 12:11:30.087 AM.

    " } }, - "documentation":"

    This is a summary of restore jobs created or running within the most recent 30 days.

    The returned summary may contain the following: Region, Account, State, ResourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " + "documentation":"

    This is a summary of restore jobs created or running within the most recent 14 days.

    The returned summary may contain the following: Region, Account, State, ResourceType, MessageCategory, StartTime, EndTime, and Count of included jobs.

    " }, "RestoreJobSummaryList":{ "type":"list", @@ -8178,7 +8660,7 @@ }, "SelectionWindowDays":{ "shape":"integer", - "documentation":"

    Accepted values are integers from 1 to 365.

    " + "documentation":"

    Accepted values are integers from 1 to 365. If not included, the value defaults to 30. The selection window is calculated from the actual job execution time, not the plan's scheduled start time.

    " } }, "documentation":"

    RecoveryPointSelection has five parameters (three required and two optional). The values you specify determine which recovery point is included in the restore test. You must indicate with Algorithm if you want the latest recovery point within your SelectionWindowDays or if you want a random recovery point, and you must indicate through IncludeVaults from which vaults the recovery points can be chosen.

    Algorithm (required) Valid values: \"LATEST_WITHIN_WINDOW\" or \"RANDOM_WITHIN_WINDOW\".

    Recovery point types (required) Valid values: \"SNAPSHOT\" and/or \"CONTINUOUS\". Include SNAPSHOT to restore only snapshot recovery points; include CONTINUOUS to restore continuous recovery points (point in time restore / PITR); use both to restore either a snapshot or a continuous recovery point. The recovery point will be determined by the value for Algorithm.

    IncludeVaults (required). You must include one or more backup vaults. Use the wildcard [\"*\"] or specific ARNs.

    SelectionWindowDays (optional) Value must be an integer (in days) from 1 to 365. If not included, the value defaults to 30.

    ExcludeVaults (optional). You can choose to input one or more specific backup vault ARNs to exclude those vaults' contents from restore eligibility. Or, you can include a list of selectors. If this parameter and its value are not included, it defaults to empty list.

    " @@ -9069,6 +9551,24 @@ "member":{"shape":"string"}, "sensitive":true }, + "TagMap":{ + "type":"map", + "key":{"shape":"TagMapKeyString"}, + "value":{"shape":"TagMapValueString"}, + "max":200, + "min":0, + "sensitive":true + }, + "TagMapKeyString":{ + "type":"string", + "max":128, + "min":1 + }, + "TagMapValueString":{ + "type":"string", + "max":256, + "min":0 + }, "TagResourceInput":{ "type":"structure", "required":[ diff --git a/services/backupgateway/pom.xml b/services/backupgateway/pom.xml index 6cbeb847801f..faa8505e71de 100644 --- a/services/backupgateway/pom.xml +++ b/services/backupgateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT backupgateway AWS Java SDK :: Services :: Backup Gateway @@ -61,5 +61,10 @@ http-auth-aws ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + diff --git a/services/backupgateway/src/main/resources/codegen-resources/customization.config b/services/backupgateway/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/backupgateway/src/main/resources/codegen-resources/customization.config +++ b/services/backupgateway/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/backupgateway/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/backupgateway/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ddf13eaa4a26 --- /dev/null +++ b/services/backupgateway/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-gateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-gateway-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-gateway.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-gateway.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/backupgateway/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/backupgateway/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bdefabdd2142..000000000000 --- a/services/backupgateway/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup-gateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup-gateway-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://backup-gateway.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://backup-gateway.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/backupgateway/src/main/resources/codegen-resources/service-2.json b/services/backupgateway/src/main/resources/codegen-resources/service-2.json index 651f52481db6..129bc56dfbff 100644 --- a/services/backupgateway/src/main/resources/codegen-resources/service-2.json +++ b/services/backupgateway/src/main/resources/codegen-resources/service-2.json @@ -5,8 +5,11 @@ "auth":["aws.auth#sigv4"], "endpointPrefix":"backup-gateway", "jsonVersion":"1.0", - "protocol":"json", - "protocols":["json"], + "protocol":"smithy-rpc-v2-cbor", + "protocols":[ + "smithy-rpc-v2-cbor", + "json" + ], "serviceFullName":"AWS Backup Gateway", "serviceId":"Backup Gateway", "signatureVersion":"v4", @@ -113,7 +116,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Retrieves the bandwidth rate limit schedule for a specified gateway. By default, gateways do not have bandwidth rate limit schedules, which means no bandwidth rate limiting is in effect. Use this to get a gateway's bandwidth rate limit schedule.

    " + "documentation":"

    Retrieves the bandwidth rate limit schedule for a specified gateway. By default, gateways do not have bandwidth rate limit schedules, which means no bandwidth rate limiting is in effect. Use this to get a gateway's bandwidth rate limit schedule.

    ", + "readonly":true }, "GetGateway":{ "name":"GetGateway", @@ -129,7 +133,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    By providing the ARN (Amazon Resource Name), this API returns the gateway.

    " + "documentation":"

    By providing the ARN (Amazon Resource Name), this API returns the gateway.

    ", + "readonly":true }, "GetHypervisor":{ "name":"GetHypervisor", @@ -145,7 +150,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    This action requests information about the specified hypervisor to which the gateway will connect. A hypervisor is hardware, software, or firmware that creates and manages virtual machines, and allocates resources to them.

    " + "documentation":"

    This action requests information about the specified hypervisor to which the gateway will connect. A hypervisor is hardware, software, or firmware that creates and manages virtual machines, and allocates resources to them.

    ", + "readonly":true }, "GetHypervisorPropertyMappings":{ "name":"GetHypervisorPropertyMappings", @@ -161,7 +167,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    This action retrieves the property mappings for the specified hypervisor. A hypervisor property mapping displays the relationship of entity properties available from the hypervisor to the properties available in Amazon Web Services.

    " + "documentation":"

    This action retrieves the property mappings for the specified hypervisor. A hypervisor property mapping displays the relationship of entity properties available from the hypervisor to the properties available in Amazon Web Services.

    ", + "readonly":true }, "GetVirtualMachine":{ "name":"GetVirtualMachine", @@ -177,7 +184,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    By providing the ARN (Amazon Resource Name), this API returns the virtual machine.

    " + "documentation":"

    By providing the ARN (Amazon Resource Name), this API returns the virtual machine.

    ", + "readonly":true }, "ImportHypervisorConfiguration":{ "name":"ImportHypervisorConfiguration", @@ -209,7 +217,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Lists backup gateways owned by an Amazon Web Services account in an Amazon Web Services Region. The returned list is ordered by gateway Amazon Resource Name (ARN).

    " + "documentation":"

    Lists backup gateways owned by an Amazon Web Services account in an Amazon Web Services Region. The returned list is ordered by gateway Amazon Resource Name (ARN).

    ", + "readonly":true }, "ListHypervisors":{ "name":"ListHypervisors", @@ -224,7 +233,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Lists your hypervisors.

    " + "documentation":"

    Lists your hypervisors.

    ", + "readonly":true }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -255,7 +265,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Lists your virtual machines.

    " + "documentation":"

    Lists your virtual machines.

    ", + "readonly":true }, "PutBandwidthRateLimitSchedule":{ "name":"PutBandwidthRateLimitSchedule", @@ -440,6 +451,10 @@ "Message":{"shape":"string"} }, "documentation":"

    The operation cannot proceed because you have insufficient permissions.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, "exception":true }, "ActivationKey":{ @@ -534,6 +549,10 @@ "Message":{"shape":"string"} }, "documentation":"

    The operation cannot proceed because it is not supported.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, "exception":true }, "CreateGatewayInput":{ @@ -995,6 +1014,7 @@ "Message":{"shape":"string"} }, "documentation":"

    The operation did not succeed because an internal error occurred. Try again later.

    ", + "error":{"httpStatusCode":500}, "exception":true, "fault":true }, @@ -1289,6 +1309,10 @@ "Message":{"shape":"string"} }, "documentation":"

    A resource that is required for the action wasn't found.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, "exception":true }, "ServerArn":{ @@ -1417,8 +1441,7 @@ }, "TestHypervisorConfigurationOutput":{ "type":"structure", - "members":{ - } + "members":{} }, "ThrottlingException":{ "type":"structure", @@ -1431,6 +1454,10 @@ "Message":{"shape":"string"} }, "documentation":"

    TPS has been limited to protect against intentional or unintentional high request volumes.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, "exception":true }, "Time":{"type":"timestamp"}, @@ -1558,6 +1585,10 @@ "Message":{"shape":"string"} }, "documentation":"

    The operation did not succeed because a validation error occurred.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, "exception":true }, "VirtualMachine":{ diff --git a/services/backupsearch/pom.xml b/services/backupsearch/pom.xml index 8b65d8a1d649..f865f9b111f8 100644 --- a/services/backupsearch/pom.xml +++ b/services/backupsearch/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT backupsearch AWS Java SDK :: Services :: Backup Search diff --git a/services/backupsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/backupsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4997266d19fb --- /dev/null +++ b/services/backupsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-search-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://backup-search.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/backupsearch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/backupsearch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3790357e9f00..000000000000 --- a/services/backupsearch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://backup-search-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://backup-search.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/batch/pom.xml b/services/batch/pom.xml index a813e561360a..26e391e586cd 100644 --- a/services/batch/pom.xml +++ b/services/batch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT batch AWS Java SDK :: Services :: AWS Batch diff --git a/services/batch/src/main/resources/codegen-resources/customization.config b/services/batch/src/main/resources/codegen-resources/customization.config index 2a5ae03cf740..505c1cefc6be 100644 --- a/services/batch/src/main/resources/codegen-resources/customization.config +++ b/services/batch/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ ], "excludedSimpleMethods": [ "listJobs" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/batch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/batch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0fd8dc3ae4f7 --- /dev/null +++ b/services/batch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://batch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fips.batch.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://batch.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://batch-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://batch.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://batch.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/batch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/batch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2e82612e4da3..000000000000 --- a/services/batch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://batch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://fips.batch.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://batch.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://batch-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://batch.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://batch.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/batch/src/main/resources/codegen-resources/service-2.json b/services/batch/src/main/resources/codegen-resources/service-2.json index 16d164383d5c..5ef118a0b45c 100644 --- a/services/batch/src/main/resources/codegen-resources/service-2.json +++ b/services/batch/src/main/resources/codegen-resources/service-2.json @@ -26,7 +26,21 @@ {"shape":"ClientException"}, {"shape":"ServerException"} ], - "documentation":"

    Cancels a job in an Batch job queue. Jobs that are in a SUBMITTED, PENDING, or RUNNABLE state are cancelled and the job status is updated to FAILED.

    A PENDING job is canceled after all dependency jobs are completed. Therefore, it may take longer than expected to cancel a job in PENDING status.

    When you try to cancel an array parent job in PENDING, Batch attempts to cancel all child jobs. The array parent job is canceled when all child jobs are completed.

    Jobs that progressed to the STARTING or RUNNING state aren't canceled. However, the API operation still succeeds, even if no job is canceled. These jobs must be terminated with the TerminateJob operation.

    " + "documentation":"

    Cancels a job in an Batch job queue. Jobs that are in a SUBMITTED, PENDING, or RUNNABLE state are cancelled and the job status is updated to FAILED.

    A PENDING job is cancelled after all dependency jobs are completed. Therefore, it might take longer than expected to cancel a job in PENDING status.

    When you try to cancel an array parent job in PENDING, Batch attempts to cancel all child jobs. The array parent job is cancelled when all child jobs are completed.

    Jobs that progressed to the STARTING or RUNNING state aren't cancelled. However, the API operation still succeeds, even if no job is cancelled. These jobs must be terminated with the TerminateJob or TerminateJobs operation.

    " + }, + "CancelJobs":{ + "name":"CancelJobs", + "http":{ + "method":"POST", + "requestUri":"/v1/canceljobs" + }, + "input":{"shape":"CancelJobsRequest"}, + "output":{"shape":"CancelJobsResponse"}, + "errors":[ + {"shape":"ClientException"}, + {"shape":"ServerException"} + ], + "documentation":"

    Cancels up to 50 jobs in an Batch job queue. This is a bulk version of CancelJob. Jobs that are in a SUBMITTED, PENDING, or RUNNABLE state are cancelled and the job status is updated to FAILED.

    A PENDING job is cancelled after all dependency jobs are completed. Therefore, it might take longer than expected to cancel a job in PENDING status.

    When you try to cancel an array parent job in PENDING, Batch attempts to cancel all child jobs. The array parent job is cancelled when all child jobs are completed.

    Jobs that progressed to the STARTING or RUNNING state aren't cancelled. These jobs must be terminated with the TerminateJob or TerminateJobs operation.

    Batch reports the result for each job individually in the response. Jobs that were processed successfully are reported in the successful list. Jobs that encountered errors are reported in the errors list. The response returns an HTTP status code of 200 even when some jobs encountered errors, so check the errors list. Jobs that can't be found are treated as successfully processed.

    " }, "CreateComputeEnvironment":{ "name":"CreateComputeEnvironment", @@ -518,6 +532,20 @@ ], "documentation":"

    Terminates a job in a job queue. Jobs that are in the STARTING or RUNNING state are terminated, which causes them to transition to FAILED. Jobs that have not progressed to the STARTING state are cancelled.

    " }, + "TerminateJobs":{ + "name":"TerminateJobs", + "http":{ + "method":"POST", + "requestUri":"/v1/terminatejobs" + }, + "input":{"shape":"TerminateJobsRequest"}, + "output":{"shape":"TerminateJobsResponse"}, + "errors":[ + {"shape":"ClientException"}, + {"shape":"ServerException"} + ], + "documentation":"

    Terminates up to 50 jobs in a job queue. This is a bulk version of TerminateJob. Jobs that are in the STARTING or RUNNING state are terminated, which causes them to transition to FAILED. Jobs that have not progressed to the STARTING state are cancelled.

    Batch reports the result for each job individually in the response. Jobs that were processed successfully are reported in the successful list. Jobs that encountered errors are reported in the errors list. The response returns an HTTP status code of 200 even when some jobs encountered errors, so check the errors list. Jobs that can't be found are treated as successfully processed.

    " + }, "TerminateServiceJob":{ "name":"TerminateServiceJob", "http":{ @@ -532,6 +560,20 @@ ], "documentation":"

    Terminates a service job in a job queue.

    " }, + "TerminateServiceJobs":{ + "name":"TerminateServiceJobs", + "http":{ + "method":"POST", + "requestUri":"/v1/terminateservicejobs" + }, + "input":{"shape":"TerminateServiceJobsRequest"}, + "output":{"shape":"TerminateServiceJobsResponse"}, + "errors":[ + {"shape":"ClientException"}, + {"shape":"ServerException"} + ], + "documentation":"

    Terminates up to 50 service jobs in a job queue. This is a bulk version of TerminateServiceJob.

    Batch reports the result for each service job individually in the response. Service jobs that were processed successfully are reported in the successful list. Service jobs that encountered errors are reported in the errors list. The response returns an HTTP status code of 200 even when some service jobs encountered errors, so check the errors list. Service jobs that can't be found are treated as successfully processed.

    " + }, "UntagResource":{ "name":"UntagResource", "http":{ @@ -866,7 +908,8 @@ "EC2", "SPOT", "FARGATE", - "FARGATE_SPOT" + "FARGATE_SPOT", + "ECS_MANAGED_INSTANCES" ] }, "CRUpdateAllocationStrategy":{ @@ -892,7 +935,7 @@ }, "reason":{ "shape":"String", - "documentation":"

    A message to attach to the job that explains the reason for canceling it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has as limit of 1024 characters.

    " + "documentation":"

    A message to attach to the job that explains the reason for cancelling it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has a limit of 1024 characters.

    " } }, "documentation":"

    Contains the parameters for CancelJob.

    " @@ -901,6 +944,69 @@ "type":"structure", "members":{} }, + "CancelJobsErrorDetail":{ + "type":"structure", + "required":[ + "job", + "code", + "message" + ], + "members":{ + "job":{ + "shape":"String", + "documentation":"

    The Batch job ID of the job that couldn't be cancelled.

    " + }, + "code":{ + "shape":"String", + "documentation":"

    An error code that identifies the reason the job couldn't be cancelled. Valid values are:

    • ValidationException – A job identifier in the request is malformed or isn't valid.

    • ClientException – The request failed because of a client error.

    • ThrottlingException – The request was throttled. Retry the request.

    • ServerException – An internal error occurred. Retry the request.

    • AccessDenied – The caller isn't authorized to perform the action on the specified job.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A message that describes the reason the job couldn't be cancelled.

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

    An object that contains the details of a job that couldn't be cancelled by a CancelJobs operation.

    " + }, + "CancelJobsErrorDetailList":{ + "type":"list", + "member":{"shape":"CancelJobsErrorDetail"} + }, + "CancelJobsRequest":{ + "type":"structure", + "required":[ + "jobs", + "reason" + ], + "members":{ + "jobs":{ + "shape":"StringList", + "documentation":"

    An array of up to 50 Batch job IDs of the jobs to cancel.

    " + }, + "reason":{ + "shape":"String", + "documentation":"

    A message to attach to the job that explains the reason for cancelling it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has a limit of 1024 characters.

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

    Specifies the jobs to cancel and the reason for the cancellation.

    " + }, + "CancelJobsResponse":{ + "type":"structure", + "required":[ + "successful", + "errors" + ], + "members":{ + "successful":{ + "shape":"StringList", + "documentation":"

    A list of the job IDs whose cancellation request was accepted.

    " + }, + "errors":{ + "shape":"CancelJobsErrorDetailList", + "documentation":"

    A list of CancelJobsErrorDetail items, one for each job that couldn't be cancelled. Each item includes the job ID along with a code and message that describe why the job wasn't cancelled.

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

    The result of a CancelJobs request, including the jobs whose cancellation request was accepted and the errors for jobs that couldn't be cancelled.

    " + }, "CapacityLimit":{ "type":"structure", "members":{ @@ -919,6 +1025,20 @@ "type":"list", "member":{"shape":"CapacityLimit"} }, + "CapacityReservationRequest":{ + "type":"structure", + "members":{ + "reservationGroupArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity reservation group to target.

    " + }, + "reservationPreference":{ + "shape":"String", + "documentation":"

    The capacity reservation preference. Valid values:

    • RESERVATIONS_ONLY — Use only capacity reservations.

    • RESERVATIONS_FIRST — Prefer capacity reservations but fall back to On-Demand if unavailable.

    • RESERVATIONS_EXCLUDED — Do not use capacity reservations.

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

    The capacity reservation configuration for Amazon ECS Managed Instances. Use this to target On-Demand Capacity Reservations or Reserved Instances.

    " + }, "ClientException":{ "type":"structure", "members":{ @@ -1003,6 +1123,10 @@ "context":{ "shape":"String", "documentation":"

    Reserved.

    " + }, + "ecsSettings":{ + "shape":"EcsSettings", + "documentation":"

    The Amazon ECS settings for the compute environment. These settings control CloudWatch Container Insights collection.

    " } }, "documentation":"

    An object that represents an Batch compute environment.

    " @@ -1042,7 +1166,7 @@ "members":{ "type":{ "shape":"CRType", - "documentation":"

    The type of compute environment: EC2, SPOT, FARGATE, or FARGATE_SPOT. For more information, see Compute environments in the Batch User Guide.

    If you choose SPOT, you must also specify an Amazon EC2 Spot Fleet role with the spotIamFleetRole parameter. For more information, see Amazon EC2 spot fleet role in the Batch User Guide.

    Multi-node parallel jobs aren't supported on Spot Instances.

    " + "documentation":"

    The type of compute environment: EC2, SPOT, FARGATE, FARGATE_SPOT, or ECS_MANAGED_INSTANCES. For more information, see Compute environments in the Batch User Guide.

    If you choose SPOT, you must also specify an Amazon EC2 Spot Fleet role with the spotIamFleetRole parameter. For more information, see Amazon EC2 spot fleet role in the Batch User Guide.

    If you choose ECS_MANAGED_INSTANCES, you must also specify a managedInstancesProvider configuration. To use Spot capacity, set capacityOptionType to SPOT in the managedInstancesProvider.instanceLaunchTemplate configuration. For more information, see Amazon ECS Managed Instances compute environments in the Batch User Guide.

    Multi-node parallel jobs aren't supported on Spot Instances or Amazon ECS Managed Instances.

    " }, "allocationStrategy":{ "shape":"CRAllocationStrategy", @@ -1113,6 +1237,14 @@ "scalingPolicy":{ "shape":"ComputeScalingPolicy", "documentation":"

    The scaling policy configuration for the compute environment.

    This parameter isn't applicable to jobs that are running on Fargate resources. Don't specify it.

    " + }, + "managedInstancesProvider":{ + "shape":"ManagedInstancesProvider", + "documentation":"

    The configuration for the Amazon ECS Managed Instances capacity provider. This parameter is required when computeResources.type is ECS_MANAGED_INSTANCES and must not be specified for other compute environment types.

    For more information, see Amazon ECS Managed Instances compute environments in the Batch User Guide.

    " + }, + "capacityTags":{ + "shape":"TagrisTagsMap", + "documentation":"

    The tags to apply to the Amazon ECS capacity provider and Amazon EC2 instances launched by the compute environment. These tags are separate from the compute environment resource tags (the top-level tags parameter). Use capacityTags for cost allocation and organization of the underlying infrastructure resources.

    This parameter is only valid for ECS_MANAGED_INSTANCES compute environments. You must have the batch:SetCapacityTags permission on the compute environment resource to use this parameter.

    " } }, "documentation":"

    An object that represents an Batch compute resource. For more information, see Compute environments in the Batch User Guide.

    " @@ -1182,7 +1314,7 @@ }, "type":{ "shape":"CRType", - "documentation":"

    The type of compute environment: EC2, SPOT, FARGATE, or FARGATE_SPOT. For more information, see Compute environments in the Batch User Guide.

    If you choose SPOT, you must also specify an Amazon EC2 Spot Fleet role with the spotIamFleetRole parameter. For more information, see Amazon EC2 spot fleet role in the Batch User Guide.

    When updating a compute environment, changing the type of a compute environment requires an infrastructure update of the compute environment. For more information, see Updating compute environments in the Batch User Guide.

    " + "documentation":"

    The type of compute environment: EC2, SPOT, FARGATE, FARGATE_SPOT, or ECS_MANAGED_INSTANCES. For more information, see Compute environments in the Batch User Guide.

    If you choose SPOT, you must also specify an Amazon EC2 Spot Fleet role with the spotIamFleetRole parameter. For more information, see Amazon EC2 spot fleet role in the Batch User Guide.

    When updating a compute environment, changing the type of a compute environment requires an infrastructure update of the compute environment. For more information, see Updating compute environments in the Batch User Guide.

    You cannot change the type to or from ECS_MANAGED_INSTANCES.

    " }, "imageId":{ "shape":"String", @@ -1191,6 +1323,14 @@ "scalingPolicy":{ "shape":"ComputeScalingPolicy", "documentation":"

    The scaling policy configuration for the compute environment.

    This parameter isn't applicable to jobs that are running on Fargate resources. Don't specify it.

    " + }, + "managedInstancesProvider":{ + "shape":"UpdateManagedInstancesProviderConfiguration", + "documentation":"

    The updated configuration for the Amazon ECS Managed Instances capacity provider. This parameter is only valid when the compute environment type is ECS_MANAGED_INSTANCES. You cannot change capacityOptionType or fipsEnabled on update.

    " + }, + "capacityTags":{ + "shape":"TagrisTagsMap", + "documentation":"

    The updated tags to apply to the Amazon ECS capacity provider and Amazon EC2 instances. This parameter is only valid for ECS_MANAGED_INSTANCES compute environments. You must have the batch:SetCapacityTags permission on the compute environment resource to use this parameter.

    " } }, "documentation":"

    An object that represents the attributes of a compute environment that can be updated. For more information, see Updating compute environments in the Batch User Guide.

    " @@ -1276,7 +1416,7 @@ }, "vcpus":{ "shape":"Integer", - "documentation":"

    The number of vCPUs reserved for the container. For jobs that run on Amazon EC2 resources, you can specify the vCPU requirement for the job using resourceRequirements, but you can't specify the vCPU requirements in both the vcpus and resourceRequirements object. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. Each vCPU is equivalent to 1,024 CPU shares. You must specify at least one vCPU. This is required but can be specified in several places. It must be specified for each node at least once.

    This parameter isn't applicable to jobs that run on Fargate resources. For jobs that run on Fargate resources, you must specify the vCPU requirement for the job using resourceRequirements.

    " + "documentation":"

    The number of vCPUs reserved for the container. For jobs that run on Amazon EC2 resources, you can specify the vCPU requirement for the job using resourceRequirements, but you can't specify the vCPU requirements in both the vcpus and resourceRequirements object. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. Each vCPU is equivalent to 1,024 CPU shares. You must specify at least one vCPU. This is required but can be specified in several places. It must be specified for each node at least once.

    This parameter isn't applicable to jobs that run on Fargate resources. For jobs that run on Fargate resources, you must specify the vCPU requirement for the job using resourceRequirements.

    " }, "memory":{ "shape":"Integer", @@ -1308,11 +1448,11 @@ }, "readonlyRootFilesystem":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run .

    " + "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run .

    " }, "ulimits":{ "shape":"Ulimits", - "documentation":"

    A list of ulimit values to set in the container. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources.

    " + "documentation":"

    A list of ulimit values to set in the container. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources.

    " }, "privileged":{ "shape":"Boolean", @@ -1320,7 +1460,7 @@ }, "user":{ "shape":"String", - "documentation":"

    The user name to use inside the container. This parameter maps to User in the Create a container section of the Docker Remote API and the --user option to docker run.

    " + "documentation":"

    The user name to use inside the container. This parameter maps to User in the Create a container section of the Docker Remote API and the --user option to docker run.

    " }, "exitCode":{ "shape":"Integer", @@ -1360,7 +1500,7 @@ }, "logConfiguration":{ "shape":"LogConfiguration", - "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run. By default, containers use the same logging driver that the Docker daemon uses. However, the container might use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance. Or, alternatively, it must be configured on a different log server for remote logging options. For more information on the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Batch currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers might be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version | grep \"Server API version\"

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " + "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run. By default, containers use the same logging driver that the Docker daemon uses. However, the container might use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance. Or, alternatively, it must be configured on a different log server for remote logging options. For more information on the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Batch currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers might be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version | grep \"Server API version\"

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " }, "secrets":{ "shape":"SecretList", @@ -1393,6 +1533,15 @@ }, "documentation":"

    An object that represents the details of a container that's part of a job.

    " }, + "ContainerInsights":{ + "type":"string", + "documentation":"

    Specifies the CloudWatch Container Insights mode for the compute environment.

    ", + "enum":[ + "ENABLED", + "ENHANCED", + "DISABLED" + ] + }, "ContainerOverrides":{ "type":"structure", "members":{ @@ -1432,11 +1581,11 @@ "members":{ "image":{ "shape":"String", - "documentation":"

    Required. The image used to start a container. This string is passed directly to the Docker daemon. Images in the Docker Hub registry are available by default. Other repositories are specified with repository-url/image:tag . It can be 255 characters long. It can contain uppercase and lowercase letters, numbers, hyphens (-), underscores (_), colons (:), periods (.), forward slashes (/), and number signs (#). This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of docker run.

    Docker image architecture must match the processor architecture of the compute resources that they're scheduled on. For example, ARM-based Docker images can only run on ARM-based compute resources.

    • Images in Amazon ECR Public repositories use the full registry/repository[:tag] or registry/repository[@digest] naming conventions. For example, public.ecr.aws/registry_alias/my-web-app:latest .

    • Images in Amazon ECR repositories use the full registry and repository URI (for example, 123456789012.dkr.ecr.<region-name>.amazonaws.com/<repository-name>).

    • Images in official repositories on Docker Hub use a single name (for example, ubuntu or mongo).

    • Images in other repositories on Docker Hub are qualified with an organization name (for example, amazon/amazon-ecs-agent).

    • Images in other online repositories are qualified further by a domain name (for example, quay.io/assemblyline/ubuntu).

    " + "documentation":"

    Required. The image used to start a container. This string is passed directly to the Docker daemon. Images in the Docker Hub registry are available by default. Other repositories are specified with repository-url/image:tag . It can be 255 characters long. It can contain uppercase and lowercase letters, numbers, hyphens (-), underscores (_), colons (:), periods (.), forward slashes (/), and number signs (#). This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of docker run.

    Docker image architecture must match the processor architecture of the compute resources that they're scheduled on. For example, ARM-based Docker images can only run on ARM-based compute resources.

    • Images in Amazon ECR Public repositories use the full registry/repository[:tag] or registry/repository[@digest] naming conventions. For example, public.ecr.aws/registry_alias/my-web-app:latest .

    • Images in Amazon ECR repositories use the full registry and repository URI (for example, 123456789012.dkr.ecr.<region-name>.amazonaws.com/<repository-name>).

    • Images in official repositories on Docker Hub use a single name (for example, ubuntu or mongo).

    • Images in other repositories on Docker Hub are qualified with an organization name (for example, amazon/amazon-ecs-agent).

    • Images in other online repositories are qualified further by a domain name (for example, quay.io/assemblyline/ubuntu).

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

    This parameter is deprecated, use resourceRequirements to specify the vCPU requirements for the job definition. It's not supported for jobs running on Fargate resources. For jobs running on Amazon EC2 resources, it specifies the number of vCPUs reserved for the job.

    Each vCPU is equivalent to 1,024 CPU shares. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. The number of vCPUs must be specified but can be specified in several places. You must specify it at least once for each node.

    ", + "documentation":"

    This parameter is deprecated, use resourceRequirements to specify the vCPU requirements for the job definition. It's not supported for jobs running on Fargate resources. For jobs running on Amazon EC2 resources, it specifies the number of vCPUs reserved for the job.

    Each vCPU is equivalent to 1,024 CPU shares. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. The number of vCPUs must be specified but can be specified in several places. You must specify it at least once for each node.

    ", "deprecated":true, "deprecatedMessage":"This field is deprecated, use resourceRequirements instead." }, @@ -1448,7 +1597,7 @@ }, "command":{ "shape":"StringList", - "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see https://docs.docker.com/engine/reference/builder/#cmd.

    " + "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see https://docs.docker.com/engine/reference/builder/#cmd.

    " }, "jobRoleArn":{ "shape":"String", @@ -1464,27 +1613,27 @@ }, "environment":{ "shape":"EnvironmentVariables", - "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env option to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    Environment variables cannot start with \"AWS_BATCH\". This naming convention is reserved for variables that Batch sets.

    " + "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env option to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    Environment variables cannot start with \"AWS_BATCH\". This naming convention is reserved for variables that Batch sets.

    " }, "mountPoints":{ "shape":"MountPoints", - "documentation":"

    The mount points for data volumes in your container. This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    " + "documentation":"

    The mount points for data volumes in your container. This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    " }, "readonlyRootFilesystem":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    " + "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    " }, "privileged":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given elevated permissions on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run. The default value is false.

    This parameter isn't applicable to jobs that are running on Fargate resources and shouldn't be provided, or specified as false.

    " + "documentation":"

    When this parameter is true, the container is given elevated permissions on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run. The default value is false.

    This parameter isn't applicable to jobs that are running on Fargate resources and shouldn't be provided, or specified as false.

    " }, "ulimits":{ "shape":"Ulimits", - "documentation":"

    A list of ulimits to set in the container. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources and shouldn't be provided.

    " + "documentation":"

    A list of ulimits to set in the container. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources and shouldn't be provided.

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

    The user name to use inside the container. This parameter maps to User in the Create a container section of the Docker Remote API and the --user option to docker run.

    " + "documentation":"

    The user name to use inside the container. This parameter maps to User in the Create a container section of the Docker Remote API and the --user option to docker run.

    " }, "instanceType":{ "shape":"String", @@ -1500,7 +1649,7 @@ }, "logConfiguration":{ "shape":"LogConfiguration", - "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run. By default, containers use the same logging driver that the Docker daemon uses. However the container might use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information on the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Batch currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type).

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version | grep \"Server API version\"

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " + "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run. By default, containers use the same logging driver that the Docker daemon uses. However the container might use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information on the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Batch currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type).

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version | grep \"Server API version\"

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " }, "secrets":{ "shape":"SecretList", @@ -1589,6 +1738,10 @@ "context":{ "shape":"String", "documentation":"

    Reserved.

    " + }, + "ecsSettings":{ + "shape":"EcsSettings", + "documentation":"

    The Amazon ECS settings for the compute environment. These settings control CloudWatch Container Insights collection for the compute environment.

    " } }, "documentation":"

    Contains the parameters for CreateComputeEnvironment.

    " @@ -2490,6 +2643,16 @@ }, "documentation":"

    An object that contains overrides for the Amazon ECS task definition of a job.

    " }, + "EcsSettings":{ + "type":"structure", + "members":{ + "containerInsights":{ + "shape":"ContainerInsights", + "documentation":"

    Specifies the CloudWatch Container Insights mode for the compute environment. Valid values are:

    ENABLED

    Turns on standard Container Insights, which collects CPU, memory, disk, and network utilization metrics for the compute environment.

    ENHANCED

    Turns on enhanced Container Insights, which collects the standard metrics along with additional per-task observability metrics.

    DISABLED

    Turns off Container Insights for the compute environment.

    If you don't specify a value, the default is DISABLED. For more information, see Container Insights in the Batch User Guide.

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

    The Amazon ECS settings for a compute environment, including the CloudWatch Container Insights mode. Use this structure with CreateComputeEnvironment and UpdateComputeEnvironment.

    " + }, "EcsTaskDetails":{ "type":"structure", "members":{ @@ -2535,7 +2698,7 @@ }, "runtimePlatform":{ "shape":"RuntimePlatform", - "documentation":"

    An object that represents the compute environment architecture for Batch jobs on Fargate.

    " + "documentation":"

    An object that represents the compute environment architecture for Batch jobs on Fargate or Amazon ECS Managed Instances. Contains the operating system family and CPU architecture of the task.

    " }, "volumes":{ "shape":"Volumes", @@ -2544,6 +2707,10 @@ "enableExecuteCommand":{ "shape":"Boolean", "documentation":"

    Determines whether execute command functionality is turned on for this task. If true, execute command functionality is turned on all the containers in the task.

    " + }, + "networkMode":{ + "shape":"String", + "documentation":"

    The network mode configured for the task. This field is populated for jobs running on Amazon ECS Managed Instances (MANAGED_INSTANCES platform capability) and always returns host.

    " } }, "documentation":"

    The details of a task definition that describes the container and volume definitions of an Amazon ECS task.

    " @@ -2570,7 +2737,7 @@ }, "ipcMode":{ "shape":"String", - "documentation":"

    The IPC resource namespace to use for the containers in the task. The valid values are host, task, or none.

    If host is specified, all containers within the tasks that specified the host IPC mode on the same container instance share the same IPC resources with the host Amazon EC2 instance.

    If task is specified, all containers within the specified task share the same IPC resources.

    If none is specified, the IPC resources within the containers of a task are private, and are not shared with other containers in a task or on the container instance.

    If no value is specified, then the IPC resource namespace sharing depends on the Docker daemon setting on the container instance. For more information, see IPC settings in the Docker run reference.

    " + "documentation":"

    The IPC resource namespace to use for the containers in the task. The valid values are host, task, or none.

    If host is specified, all containers within the tasks that specified the host IPC mode on the same container instance share the same IPC resources with the host Amazon EC2 instance.

    If task is specified, all containers within the specified task share the same IPC resources.

    If none is specified, the IPC resources within the containers of a task are private, and are not shared with other containers in a task or on the container instance.

    If no value is specified, then the IPC resource namespace sharing depends on the Docker daemon setting on the container instance. For more information, see IPC settings in the Docker run reference.

    This parameter is not supported for jobs that run on Fargate resources.

    " }, "taskRoleArn":{ "shape":"String", @@ -2582,11 +2749,11 @@ }, "networkConfiguration":{ "shape":"NetworkConfiguration", - "documentation":"

    The network configuration for jobs that are running on Fargate resources. Jobs that are running on Amazon EC2 resources must not specify this parameter.

    " + "documentation":"

    The network configuration for jobs that are running on Fargate resources. Jobs that are running on Amazon EC2 resources or Amazon ECS Managed Instances must not specify this parameter.

    " }, "runtimePlatform":{ "shape":"RuntimePlatform", - "documentation":"

    An object that represents the compute environment architecture for Batch jobs on Fargate.

    " + "documentation":"

    An object that represents the compute environment architecture for Batch jobs on Fargate or Amazon ECS Managed Instances. Use this to specify the operating system family (operatingSystemFamily) and CPU architecture (cpuArchitecture).

    For Amazon ECS Managed Instances, the valid value for operatingSystemFamily is LINUX (default). The valid values for cpuArchitecture are X86_64 and ARM64.

    " }, "volumes":{ "shape":"Volumes", @@ -2595,6 +2762,10 @@ "enableExecuteCommand":{ "shape":"Boolean", "documentation":"

    Determines whether execute command functionality is turned on for this task. If true, execute command functionality is turned on all the containers in the task.

    " + }, + "networkMode":{ + "shape":"String", + "documentation":"

    The network mode to use for the task. Valid values: host. When not specified, the default is host.

    With host mode, the container shares the host instance's network stack directly. When running tasks that use the host network mode, do not run containers using the root user (UID 0). Running as root grants unrestricted access to host resources and increases the attack surface.

    This parameter only applies to jobs running on Amazon ECS Managed Instances (MANAGED_INSTANCES platform capability). It cannot be specified for Fargate or Amazon EC2 platform job definitions.

    " } }, "documentation":"

    The properties for a task definition that describes the container and volume definitions of an Amazon ECS task. You can specify which Docker images to use, the required resources, and other configurations related to launching the task definition through an Amazon ECS service or task.

    " @@ -3455,6 +3626,114 @@ "max":256, "min":1 }, + "InfrastructureOptimization":{ + "type":"structure", + "members":{ + "scaleInAfter":{ + "shape":"Integer", + "documentation":"

    The number of seconds an instance can remain idle before it is terminated. Valid values are -1 or 0 to 3600. Use -1 as a special value to disable scale-in (instances are never terminated for being idle). If not specified, a default value applies.

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

    The infrastructure optimization configuration for an Amazon ECS Managed Instances capacity provider. Specifies the idle-instance scale-in behavior.

    " + }, + "InstanceLaunchTemplate":{ + "type":"structure", + "required":[ + "ec2InstanceProfileArn", + "networkConfiguration" + ], + "members":{ + "ec2InstanceProfileArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon EC2 instance profile for the managed instances. The instance profile must use the AmazonECSInstanceRolePolicyForManagedInstances managed policy with a trust policy for ec2.amazonaws.com.

    " + }, + "networkConfiguration":{ + "shape":"ManagedInstancesNetworkConfiguration", + "documentation":"

    The network configuration for the managed instances. Specifies the VPC subnets and security groups where instances are launched.

    " + }, + "instanceRequirements":{ + "shape":"InstanceRequirementsRequest", + "documentation":"

    The instance type requirements for the capacity provider. Use this to constrain which Amazon EC2 instance types Amazon ECS can launch. If not specified, all available instance types are eligible.

    " + }, + "capacityOptionType":{ + "shape":"String", + "documentation":"

    The capacity pricing model for the managed instances. Valid values:

    • ON_DEMAND (default) — On-Demand pricing.

    • SPOT — Spot Instances, which can provide significant cost savings for fault-tolerant workloads.

    " + }, + "storageConfiguration":{ + "shape":"ManagedInstancesStorageConfiguration", + "documentation":"

    The storage configuration for the managed instances. Configures the root EBS volume size. If not specified, the service uses the default EBS volume size for the instance type.

    " + }, + "monitoring":{ + "shape":"String", + "documentation":"

    The level of CloudWatch monitoring for the managed instances. Valid values are BASIC and DETAILED.

    " + }, + "fipsEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether FIPS 140-2 validated cryptographic modules are enabled on the managed instances. Not available in all Regions.

    " + }, + "capacityReservations":{ + "shape":"CapacityReservationRequest", + "documentation":"

    The capacity reservation configuration for the managed instances. Use this to target On-Demand Capacity Reservations or Reserved Instances for predictable capacity and cost optimization.

    " + }, + "instanceMetadataTagsPropagation":{ + "shape":"Boolean", + "documentation":"

    Specifies whether instance tags are accessible from the instance metadata service (IMDS). If not specified, instance tags are not accessible from IMDS.

    " + }, + "localStorageConfiguration":{ + "shape":"ManagedInstancesLocalStorageConfiguration", + "documentation":"

    The local storage configuration for the managed instances. If not specified, instance store volumes are not available to containers.

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

    The instance launch configuration for an Amazon ECS Managed Instances capacity provider. Specifies the instance profile, networking, instance selection constraints, capacity pricing model, storage, and monitoring settings.

    " + }, + "InstanceLaunchTemplateUpdate":{ + "type":"structure", + "members":{ + "ec2InstanceProfileArn":{ + "shape":"String", + "documentation":"

    The updated Amazon Resource Name (ARN) of the Amazon EC2 instance profile for the managed instances.

    " + }, + "networkConfiguration":{ + "shape":"ManagedInstancesNetworkConfiguration", + "documentation":"

    The updated network configuration for the managed instances.

    " + }, + "instanceRequirements":{ + "shape":"InstanceRequirementsRequest", + "documentation":"

    The updated instance type requirements for the capacity provider.

    " + }, + "storageConfiguration":{ + "shape":"ManagedInstancesStorageConfiguration", + "documentation":"

    The updated storage configuration for the managed instances.

    " + }, + "monitoring":{ + "shape":"String", + "documentation":"

    The updated monitoring level. Valid values are BASIC and DETAILED.

    " + }, + "capacityReservations":{ + "shape":"CapacityReservationRequest", + "documentation":"

    The updated capacity reservation configuration.

    " + }, + "instanceMetadataTagsPropagation":{ + "shape":"Boolean", + "documentation":"

    Specifies whether instance tags are accessible from the instance metadata service (IMDS).

    " + }, + "localStorageConfiguration":{ + "shape":"ManagedInstancesLocalStorageConfiguration", + "documentation":"

    The updated local storage configuration.

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

    The instance launch configuration for updating an Amazon ECS Managed Instances capacity provider. You cannot change capacityOptionType or fipsEnabled after the compute environment is created.

    " + }, + "InstanceRequirementsRequest":{ + "type":"structure", + "members":{ + "allowedInstanceTypes":{ + "shape":"StringList", + "documentation":"

    A list of specific instance types or instance families that Amazon ECS can launch (for example, m5.large or g5). When specified, only these instance types are used.

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

    The instance type requirements for the Amazon ECS Managed Instances capacity provider. Use this to specify which Amazon EC2 instance types or instance families Amazon ECS can launch.

    " + }, "Integer":{"type":"integer"}, "JQState":{ "type":"string", @@ -3555,7 +3834,7 @@ }, "platformCapabilities":{ "shape":"PlatformCapabilityList", - "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. Jobs run on Fargate resources specify FARGATE.

    " + "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. Jobs run on Fargate resources specify FARGATE. Jobs run on Amazon ECS Managed Instances specify MANAGED_INSTANCES.

    " }, "ecsProperties":{ "shape":"EcsProperties", @@ -3710,7 +3989,7 @@ }, "platformCapabilities":{ "shape":"PlatformCapabilityList", - "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. Jobs run on Fargate resources specify FARGATE.

    " + "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. Jobs run on Fargate resources specify FARGATE. Jobs run on Amazon ECS Managed Instances specify MANAGED_INSTANCES.

    " }, "eksProperties":{ "shape":"EksPropertiesDetail", @@ -3726,7 +4005,7 @@ }, "isCancelled":{ "shape":"Boolean", - "documentation":"

    Indicates whether the job is canceled.

    " + "documentation":"

    Indicates whether the job is cancelled.

    " }, "isTerminated":{ "shape":"Boolean", @@ -3819,7 +4098,8 @@ "EKS", "ECS", "ECS_FARGATE", - "SAGEMAKER_TRAINING" + "SAGEMAKER_TRAINING", + "ECS_MANAGED_INSTANCES" ] }, "JobStateTimeLimitAction":{ @@ -3943,6 +4223,14 @@ "jobDefinition":{ "shape":"String", "documentation":"

    The Amazon Resource Name (ARN) of the job definition.

    " + }, + "isCancelled":{ + "shape":"Boolean", + "documentation":"

    Indicates whether a cancellation request has been accepted for the job. This field is only present when the value is true.

    " + }, + "isTerminated":{ + "shape":"Boolean", + "documentation":"

    Indicates whether a termination request has been accepted for the job. This field is only present when the value is true.

    " } }, "documentation":"

    An object that represents summary details of a job.

    " @@ -4065,7 +4353,7 @@ "members":{ "devices":{ "shape":"DevicesList", - "documentation":"

    Any of the host devices to expose to the container. This parameter maps to Devices in the Create a container section of the Docker Remote API and the --device option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources. Don't provide it for these jobs.

    " + "documentation":"

    Any of the host devices to expose to the container. This parameter maps to Devices in the Create a container section of the Docker Remote API and the --device option to docker run.

    This parameter isn't applicable to jobs that are running on Fargate resources. Don't provide it for these jobs.

    " }, "initProcessEnabled":{ "shape":"Boolean", @@ -4469,6 +4757,70 @@ ] }, "Long":{"type":"long"}, + "ManagedInstancesLocalStorageConfiguration":{ + "type":"structure", + "members":{ + "useLocalStorage":{ + "shape":"Boolean", + "documentation":"

    Specifies whether instance store volumes (local NVMe SSDs) are available to containers. When enabled, containers can use the instance store for high-performance temporary storage.

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

    The local storage configuration for Amazon ECS Managed Instances.

    " + }, + "ManagedInstancesNetworkConfiguration":{ + "type":"structure", + "required":[ + "subnets", + "securityGroups" + ], + "members":{ + "subnets":{ + "shape":"StringList", + "documentation":"

    The VPC subnets where managed instances are launched. If your subnets don't provide public IP addresses, they must have a NAT gateway for outbound internet access.

    " + }, + "securityGroups":{ + "shape":"StringList", + "documentation":"

    The VPC security groups to associate with the managed instances.

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

    The network configuration for Amazon ECS Managed Instances. Specifies the VPC subnets and security groups where instances are launched.

    " + }, + "ManagedInstancesProvider":{ + "type":"structure", + "required":[ + "infrastructureRoleArn", + "instanceLaunchTemplate" + ], + "members":{ + "propagateTags":{ + "shape":"String", + "documentation":"

    Specifies whether tags on the capacity provider are propagated to the Amazon EC2 instances it launches. Valid values:

    • CAPACITY_PROVIDER — Propagates tags to instances.

    • NONE (default) — Does not propagate tags to instances.

    " + }, + "infrastructureRoleArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon ECS assumes to manage Amazon EC2 instances on your behalf. This role must have a trust policy for ecs.amazonaws.com. You must have the iam:PassRole permission for this role with the condition iam:PassedToService: ecs.amazonaws.com.

    " + }, + "instanceLaunchTemplate":{ + "shape":"InstanceLaunchTemplate", + "documentation":"

    The instance launch configuration for the Amazon ECS Managed Instances capacity provider. Contains networking, instance profile, instance requirements, capacity type, storage, and monitoring configuration.

    " + }, + "infrastructureOptimization":{ + "shape":"InfrastructureOptimization", + "documentation":"

    The infrastructure optimization configuration for the capacity provider. Specifies the idle-instance scale-in behavior.

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

    The configuration for an Amazon ECS Managed Instances capacity provider. This object is required when creating a compute environment with computeResources.type set to ECS_MANAGED_INSTANCES.

    " + }, + "ManagedInstancesStorageConfiguration":{ + "type":"structure", + "members":{ + "storageSizeGiB":{ + "shape":"Integer", + "documentation":"

    The size of the root EBS volume in GiB for the managed instances.

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

    The storage configuration for Amazon ECS Managed Instances.

    " + }, "MountPoint":{ "type":"structure", "members":{ @@ -4485,7 +4837,7 @@ "documentation":"

    The name of the volume to mount.

    " } }, - "documentation":"

    Details for a Docker volume mount point that's used in a job's container properties. This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    " + "documentation":"

    Details for a Docker volume mount point that's used in a job's container properties. This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    " }, "MountPoints":{ "type":"list", @@ -4678,7 +5030,8 @@ "type":"string", "enum":[ "EC2", - "FARGATE" + "FARGATE", + "MANAGED_INSTANCES" ] }, "PlatformCapabilityList":{ @@ -4962,7 +5315,7 @@ }, "platformCapabilities":{ "shape":"PlatformCapabilityList", - "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. To run the job on Fargate resources, specify FARGATE.

    If the job runs on Amazon EKS resources, then you must not specify platformCapabilities.

    " + "documentation":"

    The platform capabilities required by the job definition. If no value is specified, it defaults to EC2. To run the job on Fargate resources, specify FARGATE. To run the job on Amazon ECS Managed Instances, specify MANAGED_INSTANCES.

    Jobs with the MANAGED_INSTANCES platform capability must use ecsProperties (not containerProperties) and do not support multi-node parallel jobs.

    If the job runs on Amazon EKS resources, then you must not specify platformCapabilities.

    " }, "eksProperties":{ "shape":"EksProperties", @@ -5021,7 +5374,7 @@ "members":{ "value":{ "shape":"String", - "documentation":"

    The quantity of the specified resource to reserve for the container. The values vary based on the type specified.

    type=\"GPU\"

    The number of physical GPUs to reserve for the container. Make sure that the number of GPUs reserved for all containers in a job doesn't exceed the number of available GPUs on the compute resource that the job is launched on.

    GPUs aren't available for jobs that are running on Fargate resources.

    type=\"MEMORY\"

    The memory hard limit (in MiB) present to the container. This parameter is supported for jobs that are running on Amazon EC2 resources. If your container attempts to exceed the memory specified, the container is terminated. This parameter maps to Memory in the Create a container section of the Docker Remote API and the --memory option to docker run. You must specify at least 4 MiB of memory for a job. This is required but can be specified in several places for multi-node parallel (MNP) jobs. It must be specified for each node at least once. This parameter maps to Memory in the Create a container section of the Docker Remote API and the --memory option to docker run.

    If you're trying to maximize your resource utilization by providing your jobs as much memory as possible for a particular instance type, see Memory management in the Batch User Guide.

    For jobs that are running on Fargate resources, then value is the hard limit (in MiB), and must match one of the supported values and the VCPU values must be one of the values supported for that memory value.

    value = 512

    VCPU = 0.25

    value = 1024

    VCPU = 0.25 or 0.5

    value = 2048

    VCPU = 0.25, 0.5, or 1

    value = 3072

    VCPU = 0.5, or 1

    value = 4096

    VCPU = 0.5, 1, or 2

    value = 5120, 6144, or 7168

    VCPU = 1 or 2

    value = 8192

    VCPU = 1, 2, or 4

    value = 9216, 10240, 11264, 12288, 13312, 14336, or 15360

    VCPU = 2 or 4

    value = 16384

    VCPU = 2, 4, or 8

    value = 17408, 18432, 19456, 21504, 22528, 23552, 25600, 26624, 27648, 29696, or 30720

    VCPU = 4

    value = 20480, 24576, or 28672

    VCPU = 4 or 8

    value = 36864, 45056, 53248, or 61440

    VCPU = 8

    value = 32768, 40960, 49152, or 57344

    VCPU = 8 or 16

    value = 65536, 73728, 81920, 90112, 98304, 106496, 114688, or 122880

    VCPU = 16

    type=\"VCPU\"

    The number of vCPUs reserved for the container. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. Each vCPU is equivalent to 1,024 CPU shares. For Amazon EC2 resources, you must specify at least one vCPU. This is required but can be specified in several places; it must be specified for each node at least once.

    The default for the Fargate On-Demand vCPU resource count quota is 6 vCPUs. For more information about Fargate quotas, see Fargate quotas in the Amazon Web Services General Reference.

    For jobs that are running on Fargate resources, then value must match one of the supported values and the MEMORY values must be one of the values supported for that VCPU value. The supported values are 0.25, 0.5, 1, 2, 4, 8, and 16

    value = 0.25

    MEMORY = 512, 1024, or 2048

    value = 0.5

    MEMORY = 1024, 2048, 3072, or 4096

    value = 1

    MEMORY = 2048, 3072, 4096, 5120, 6144, 7168, or 8192

    value = 2

    MEMORY = 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, or 16384

    value = 4

    MEMORY = 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, or 30720

    value = 8

    MEMORY = 16384, 20480, 24576, 28672, 32768, 36864, 40960, 45056, 49152, 53248, 57344, or 61440

    value = 16

    MEMORY = 32768, 40960, 49152, 57344, 65536, 73728, 81920, 90112, 98304, 106496, 114688, or 122880

    " + "documentation":"

    The quantity of the specified resource to reserve for the container. The values vary based on the type specified.

    type=\"GPU\"

    The number of physical GPUs to reserve for the container. Make sure that the number of GPUs reserved for all containers in a job doesn't exceed the number of available GPUs on the compute resource that the job is launched on.

    GPUs aren't available for jobs that are running on Fargate resources.

    type=\"MEMORY\"

    The memory hard limit (in MiB) present to the container. This parameter is supported for jobs that are running on Amazon EC2 resources. If your container attempts to exceed the memory specified, the container is terminated. This parameter maps to Memory in the Create a container section of the Docker Remote API and the --memory option to docker run. You must specify at least 4 MiB of memory for a job. This is required but can be specified in several places for multi-node parallel (MNP) jobs. It must be specified for each node at least once. This parameter maps to Memory in the Create a container section of the Docker Remote API and the --memory option to docker run.

    If you're trying to maximize your resource utilization by providing your jobs as much memory as possible for a particular instance type, see Memory management in the Batch User Guide.

    For jobs that are running on Fargate resources, then value is the hard limit (in MiB), and must match one of the supported values and the VCPU values must be one of the values supported for that memory value.

    value = 512

    VCPU = 0.25

    value = 1024

    VCPU = 0.25 or 0.5

    value = 2048

    VCPU = 0.25, 0.5, or 1

    value = 3072

    VCPU = 0.5, or 1

    value = 4096

    VCPU = 0.5, 1, or 2

    value = 5120, 6144, or 7168

    VCPU = 1 or 2

    value = 8192

    VCPU = 1, 2, or 4

    value = 9216, 10240, 11264, 12288, 13312, 14336, or 15360

    VCPU = 2 or 4

    value = 16384

    VCPU = 2, 4, or 8

    value = 17408, 18432, 19456, 21504, 22528, 23552, 25600, 26624, 27648, 29696, or 30720

    VCPU = 4

    value = 20480, 24576, or 28672

    VCPU = 4 or 8

    value = 36864, 45056, or 53248

    VCPU = 8

    value = 61440

    VCPU = 8 or 32

    value = 32768, 40960, 49152, or 57344

    VCPU = 8 or 16

    value = 65536, 73728, 81920, 90112, 98304, 106496, or 114688

    VCPU = 16

    value = 122880

    VCPU = 16 or 32

    value = 249856

    VCPU = 32

    type=\"VCPU\"

    The number of vCPUs reserved for the container. This parameter maps to CpuShares in the Create a container section of the Docker Remote API and the --cpu-shares option to docker run. Each vCPU is equivalent to 1,024 CPU shares. For Amazon EC2 resources, you must specify at least one vCPU. This is required but can be specified in several places; it must be specified for each node at least once.

    The default for the Fargate On-Demand vCPU resource count quota is 6 vCPUs. For more information about Fargate quotas, see Fargate quotas in the Amazon Web Services General Reference.

    For jobs that are running on Fargate resources, then value must match one of the supported values and the MEMORY values must be one of the values supported for that VCPU value. The supported values are 0.25, 0.5, 1, 2, 4, 8, 16, and 32.

    value = 0.25

    MEMORY = 512, 1024, or 2048

    value = 0.5

    MEMORY = 1024, 2048, 3072, or 4096

    value = 1

    MEMORY = 2048, 3072, 4096, 5120, 6144, 7168, or 8192

    value = 2

    MEMORY = 4096, 5120, 6144, 7168, 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, or 16384

    value = 4

    MEMORY = 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360, 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576, 25600, 26624, 27648, 28672, 29696, or 30720

    value = 8

    MEMORY = 16384, 20480, 24576, 28672, 32768, 36864, 40960, 45056, 49152, 53248, 57344, or 61440

    value = 16

    MEMORY = 32768, 40960, 49152, 57344, 65536, 73728, 81920, 90112, 98304, 106496, 114688, or 122880

    value = 32

    MEMORY = 61440, 122880, or 249856

    " }, "type":{ "shape":"ResourceType", @@ -5497,6 +5850,10 @@ "stoppedAt":{ "shape":"Long", "documentation":"

    The Unix timestamp (in milliseconds) for when the service job stopped running.

    " + }, + "isTerminated":{ + "shape":"Boolean", + "documentation":"

    Indicates whether a termination request has been accepted for the service job. This field is only present when the value is true.

    " } }, "documentation":"

    Summary information about a service job.

    " @@ -5820,7 +6177,7 @@ "members":{ "command":{ "shape":"StringList", - "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see https://docs.docker.com/engine/reference/builder/#cmd.

    " + "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see https://docs.docker.com/engine/reference/builder/#cmd.

    " }, "dependsOn":{ "shape":"TaskContainerDependencyList", @@ -5828,7 +6185,7 @@ }, "environment":{ "shape":"EnvironmentVariables", - "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env option to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    " + "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env option to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    " }, "essential":{ "shape":"Boolean", @@ -5840,7 +6197,7 @@ }, "image":{ "shape":"String", - "documentation":"

    The image used to start a container. This string is passed directly to the Docker daemon. By default, images in the Docker Hub registry are available. Other repositories are specified with either repository-url/image:tag or repository-url/image@digest. Up to 255 letters (uppercase and lowercase), numbers, hyphens, underscores, colons, periods, forward slashes, and number signs are allowed. This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of the docker run .

    " + "documentation":"

    The image used to start a container. This string is passed directly to the Docker daemon. By default, images in the Docker Hub registry are available. Other repositories are specified with either repository-url/image:tag or repository-url/image@digest. Up to 255 letters (uppercase and lowercase), numbers, hyphens, underscores, colons, periods, forward slashes, and number signs are allowed. This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of the docker run .

    " }, "linuxParameters":{ "shape":"LinuxParameters", @@ -5848,11 +6205,11 @@ }, "logConfiguration":{ "shape":"LogConfiguration", - "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run.

    By default, containers use the same logging driver that the Docker daemon uses. However the container can use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information about the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Amazon ECS currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers may be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " + "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run.

    By default, containers use the same logging driver that the Docker daemon uses. However the container can use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information about the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Amazon ECS currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers may be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " }, "mountPoints":{ "shape":"MountPoints", - "documentation":"

    The mount points for data volumes in your container.

    This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    Windows containers can mount whole directories on the same drive as $env:ProgramData. Windows containers can't mount directories on a different drive, and mount point can't be across drives.

    " + "documentation":"

    The mount points for data volumes in your container.

    This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    Windows containers can mount whole directories on the same drive as $env:ProgramData. Windows containers can't mount directories on a different drive, and mount point can't be across drives.

    " }, "name":{ "shape":"String", @@ -5860,11 +6217,11 @@ }, "privileged":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run.

    This parameter is not supported for Windows containers or tasks run on Fargate.

    " + "documentation":"

    When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run.

    This parameter is not supported for Windows containers or tasks run on Fargate.

    " }, "readonlyRootFilesystem":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    This parameter is not supported for Windows containers.

    " + "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    This parameter is not supported for Windows containers.

    " }, "repositoryCredentials":{ "shape":"RepositoryCredentials", @@ -5880,7 +6237,7 @@ }, "ulimits":{ "shape":"Ulimits", - "documentation":"

    A list of ulimits to set in the container. If a ulimit value is specified in a task definition, it overrides the default values set by Docker. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    Amazon ECS tasks hosted on Fargate use the default resource limit values set by the operating system with the exception of the nofile resource limit parameter which Fargate overrides. The nofile resource limit sets a restriction on the number of open files that a container can use. The default nofile soft limit is 1024 and the default hard limit is 65535.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    This parameter is not supported for Windows containers.

    " + "documentation":"

    A list of ulimits to set in the container. If a ulimit value is specified in a task definition, it overrides the default values set by Docker. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    Amazon ECS tasks hosted on Fargate use the default resource limit values set by the operating system with the exception of the nofile resource limit parameter which Fargate overrides. The nofile resource limit sets a restriction on the number of open files that a container can use. The default nofile soft limit is 1024 and the default hard limit is 65535.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    This parameter is not supported for Windows containers.

    " }, "user":{ "shape":"String", @@ -5941,7 +6298,7 @@ "members":{ "command":{ "shape":"StringList", - "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see Dockerfile reference: CMD.

    " + "documentation":"

    The command that's passed to the container. This parameter maps to Cmd in the Create a container section of the Docker Remote API and the COMMAND parameter to docker run. For more information, see Dockerfile reference: CMD.

    " }, "dependsOn":{ "shape":"TaskContainerDependencyList", @@ -5949,7 +6306,7 @@ }, "environment":{ "shape":"EnvironmentVariables", - "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env parameter to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    Environment variables cannot start with AWS_BATCH. This naming convention is reserved for variables that Batch sets.

    " + "documentation":"

    The environment variables to pass to a container. This parameter maps to Env in the Create a container section of the Docker Remote API and the --env parameter to docker run.

    We don't recommend using plaintext environment variables for sensitive information, such as credential data.

    Environment variables cannot start with AWS_BATCH. This naming convention is reserved for variables that Batch sets.

    " }, "essential":{ "shape":"Boolean", @@ -5961,7 +6318,7 @@ }, "image":{ "shape":"String", - "documentation":"

    The image used to start a container. This string is passed directly to the Docker daemon. By default, images in the Docker Hub registry are available. Other repositories are specified with either repository-url/image:tag or repository-url/image@digest. Up to 255 letters (uppercase and lowercase), numbers, hyphens, underscores, colons, periods, forward slashes, and number signs are allowed. This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of the docker run .

    " + "documentation":"

    The image used to start a container. This string is passed directly to the Docker daemon. By default, images in the Docker Hub registry are available. Other repositories are specified with either repository-url/image:tag or repository-url/image@digest. Up to 255 letters (uppercase and lowercase), numbers, hyphens, underscores, colons, periods, forward slashes, and number signs are allowed. This parameter maps to Image in the Create a container section of the Docker Remote API and the IMAGE parameter of the docker run .

    " }, "linuxParameters":{ "shape":"LinuxParameters", @@ -5969,11 +6326,11 @@ }, "logConfiguration":{ "shape":"LogConfiguration", - "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run.

    By default, containers use the same logging driver that the Docker daemon uses. However the container can use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information about the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Amazon ECS currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers may be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " + "documentation":"

    The log configuration specification for the container.

    This parameter maps to LogConfig in the Create a container section of the Docker Remote API and the --log-driver option to docker run.

    By default, containers use the same logging driver that the Docker daemon uses. However the container can use a different logging driver than the Docker daemon by specifying a log driver with this parameter in the container definition. To use a different logging driver for a container, the log system must be configured properly on the container instance (or on a different log server for remote logging options). For more information about the options for different supported log drivers, see Configure logging drivers in the Docker documentation.

    Amazon ECS currently supports a subset of the logging drivers available to the Docker daemon (shown in the LogConfiguration data type). Additional log drivers may be available in future releases of the Amazon ECS container agent.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    The Amazon ECS container agent running on a container instance must register the logging drivers available on that instance with the ECS_AVAILABLE_LOGGING_DRIVERS environment variable before containers placed on that instance can use these log configuration options. For more information, see Amazon ECS container agent configuration in the Amazon Elastic Container Service Developer Guide.

    " }, "mountPoints":{ "shape":"MountPoints", - "documentation":"

    The mount points for data volumes in your container.

    This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    Windows containers can mount whole directories on the same drive as $env:ProgramData. Windows containers can't mount directories on a different drive, and mount point can't be across drives.

    " + "documentation":"

    The mount points for data volumes in your container.

    This parameter maps to Volumes in the Create a container section of the Docker Remote API and the --volume option to docker run.

    Windows containers can mount whole directories on the same drive as $env:ProgramData. Windows containers can't mount directories on a different drive, and mount point can't be across drives.

    " }, "name":{ "shape":"String", @@ -5981,11 +6338,11 @@ }, "privileged":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run.

    This parameter is not supported for Windows containers or tasks run on Fargate.

    " + "documentation":"

    When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user). This parameter maps to Privileged in the Create a container section of the Docker Remote API and the --privileged option to docker run.

    This parameter is not supported for Windows containers or tasks run on Fargate.

    " }, "readonlyRootFilesystem":{ "shape":"Boolean", - "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    This parameter is not supported for Windows containers.

    " + "documentation":"

    When this parameter is true, the container is given read-only access to its root file system. This parameter maps to ReadonlyRootfs in the Create a container section of the Docker Remote API and the --read-only option to docker run.

    This parameter is not supported for Windows containers.

    " }, "repositoryCredentials":{ "shape":"RepositoryCredentials", @@ -6001,7 +6358,7 @@ }, "ulimits":{ "shape":"Ulimits", - "documentation":"

    A list of ulimits to set in the container. If a ulimit value is specified in a task definition, it overrides the default values set by Docker. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    Amazon ECS tasks hosted on Fargate use the default resource limit values set by the operating system with the exception of the nofile resource limit parameter which Fargate overrides. The nofile resource limit sets a restriction on the number of open files that a container can use. The default nofile soft limit is 1024 and the default hard limit is 65535.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    This parameter is not supported for Windows containers.

    " + "documentation":"

    A list of ulimits to set in the container. If a ulimit value is specified in a task definition, it overrides the default values set by Docker. This parameter maps to Ulimits in the Create a container section of the Docker Remote API and the --ulimit option to docker run.

    Amazon ECS tasks hosted on Fargate use the default resource limit values set by the operating system with the exception of the nofile resource limit parameter which Fargate overrides. The nofile resource limit sets a restriction on the number of open files that a container can use. The default nofile soft limit is 1024 and the default hard limit is 65535.

    This parameter requires version 1.18 of the Docker Remote API or greater on your container instance. To check the Docker Remote API version on your container instance, log in to your container instance and run the following command: sudo docker version --format '{{.Server.APIVersion}}'

    This parameter is not supported for Windows containers.

    " }, "user":{ "shape":"String", @@ -6041,7 +6398,7 @@ }, "reason":{ "shape":"String", - "documentation":"

    A message to attach to the job that explains the reason for canceling it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has as limit of 1024 characters.

    " + "documentation":"

    A message to attach to the job that explains the reason for terminating it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has a limit of 1024 characters.

    " } }, "documentation":"

    Contains the parameters for TerminateJob.

    " @@ -6050,6 +6407,69 @@ "type":"structure", "members":{} }, + "TerminateJobsErrorDetail":{ + "type":"structure", + "required":[ + "job", + "code", + "message" + ], + "members":{ + "job":{ + "shape":"String", + "documentation":"

    The Batch job ID of the job that couldn't be terminated.

    " + }, + "code":{ + "shape":"String", + "documentation":"

    An error code that identifies the reason the job couldn't be terminated. Valid values are:

    • ValidationException – A job identifier in the request is malformed or isn't valid.

    • ClientException – The request failed because of a client error.

    • ThrottlingException – The request was throttled. Retry the request.

    • ServerException – An internal error occurred. Retry the request.

    • AccessDenied – The caller isn't authorized to perform the action on the specified job.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A message that describes the reason the job couldn't be terminated.

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

    An object that contains the details of a job that couldn't be terminated by a TerminateJobs operation.

    " + }, + "TerminateJobsErrorDetailList":{ + "type":"list", + "member":{"shape":"TerminateJobsErrorDetail"} + }, + "TerminateJobsRequest":{ + "type":"structure", + "required":[ + "jobs", + "reason" + ], + "members":{ + "jobs":{ + "shape":"StringList", + "documentation":"

    An array of up to 50 Batch job IDs of the jobs to terminate.

    " + }, + "reason":{ + "shape":"String", + "documentation":"

    A message to attach to the job that explains the reason for terminating it. This message is returned by future DescribeJobs operations on the job. It is also recorded in the Batch activity logs.

    This parameter has a limit of 1024 characters.

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

    Specifies the jobs to terminate and the reason for the termination.

    " + }, + "TerminateJobsResponse":{ + "type":"structure", + "required":[ + "successful", + "errors" + ], + "members":{ + "successful":{ + "shape":"StringList", + "documentation":"

    A list of the job IDs whose termination request was accepted.

    " + }, + "errors":{ + "shape":"TerminateJobsErrorDetailList", + "documentation":"

    A list of TerminateJobsErrorDetail items, one for each job that couldn't be terminated. Each item includes the job ID along with a code and message that describe why the job wasn't terminated.

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

    The result of a TerminateJobs request, including the jobs whose termination request was accepted and the errors for jobs that couldn't be terminated.

    " + }, "TerminateServiceJobRequest":{ "type":"structure", "required":[ @@ -6063,7 +6483,7 @@ }, "reason":{ "shape":"String", - "documentation":"

    A message to attach to the service job that explains the reason for canceling it. This message is returned by DescribeServiceJob operations on the service job.

    " + "documentation":"

    A message to attach to the service job that explains the reason for terminating it. This message is returned by DescribeServiceJob operations on the service job.

    " } } }, @@ -6071,6 +6491,69 @@ "type":"structure", "members":{} }, + "TerminateServiceJobsErrorDetail":{ + "type":"structure", + "required":[ + "job", + "code", + "message" + ], + "members":{ + "job":{ + "shape":"String", + "documentation":"

    The service job ID of the service job that couldn't be terminated.

    " + }, + "code":{ + "shape":"String", + "documentation":"

    An error code that identifies the reason the service job couldn't be terminated. Valid values are:

    • ValidationException – A service job identifier in the request is malformed or isn't valid.

    • ClientException – The request failed because of a client error.

    • ThrottlingException – The request was throttled. Retry the request.

    • ServerException – An internal error occurred. Retry the request.

    • AccessDenied – The caller isn't authorized to perform the action on the specified service job.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A message that describes the reason the service job couldn't be terminated.

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

    An object that contains the details of a service job that couldn't be terminated by a TerminateServiceJobs operation.

    " + }, + "TerminateServiceJobsErrorDetailList":{ + "type":"list", + "member":{"shape":"TerminateServiceJobsErrorDetail"} + }, + "TerminateServiceJobsRequest":{ + "type":"structure", + "required":[ + "jobs", + "reason" + ], + "members":{ + "jobs":{ + "shape":"StringList", + "documentation":"

    An array of up to 50 service job IDs of the service jobs to terminate.

    " + }, + "reason":{ + "shape":"String", + "documentation":"

    A message to attach to the service job that explains the reason for terminating it. This message is returned by DescribeServiceJob operations on the service job.

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

    Specifies the service jobs to terminate and the reason for the termination.

    " + }, + "TerminateServiceJobsResponse":{ + "type":"structure", + "required":[ + "successful", + "errors" + ], + "members":{ + "successful":{ + "shape":"StringList", + "documentation":"

    A list of the service job IDs whose termination request was accepted.

    " + }, + "errors":{ + "shape":"TerminateServiceJobsErrorDetailList", + "documentation":"

    A list of TerminateServiceJobsErrorDetail items, one for each service job that couldn't be terminated. Each item includes the service job ID along with a code and message that describe why the service job wasn't terminated.

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

    The result of a TerminateServiceJobs request, including the service jobs whose termination request was accepted and the errors for service jobs that couldn't be terminated.

    " + }, "Tmpfs":{ "type":"structure", "required":[ @@ -6181,6 +6664,10 @@ "context":{ "shape":"String", "documentation":"

    Reserved.

    " + }, + "ecsSettings":{ + "shape":"EcsSettings", + "documentation":"

    The Amazon ECS settings for the compute environment. These settings control CloudWatch Container Insights collection for the compute environment.

    " } }, "documentation":"

    Contains the parameters for UpdateComputeEnvironment.

    " @@ -6290,6 +6777,28 @@ } } }, + "UpdateManagedInstancesProviderConfiguration":{ + "type":"structure", + "members":{ + "propagateTags":{ + "shape":"String", + "documentation":"

    Specifies whether tags on the capacity provider are propagated to the Amazon EC2 instances it launches. Valid values:

    • CAPACITY_PROVIDER — Propagates tags to instances.

    • NONE — Does not propagate tags to instances.

    " + }, + "infrastructureRoleArn":{ + "shape":"String", + "documentation":"

    The updated Amazon Resource Name (ARN) of the IAM role that Amazon ECS assumes to manage Amazon EC2 instances on your behalf.

    " + }, + "instanceLaunchTemplate":{ + "shape":"InstanceLaunchTemplateUpdate", + "documentation":"

    The updated instance launch configuration for the Amazon ECS Managed Instances capacity provider.

    " + }, + "infrastructureOptimization":{ + "shape":"InfrastructureOptimization", + "documentation":"

    The updated infrastructure optimization configuration.

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

    The configuration for updating an Amazon ECS Managed Instances capacity provider. Used in UpdateComputeEnvironment requests. The capacityOptionType and fipsEnabled fields cannot be changed on update.

    " + }, "UpdatePolicy":{ "type":"structure", "members":{ @@ -6302,7 +6811,7 @@ "documentation":"

    Specifies the job timeout (in minutes) when the compute environment infrastructure is updated. The default value is 30. The maximum value is 7200.

    Increasing jobExecutionTimeoutMinutes during infrastructure updates delays the replacement of instances with new instances that include updates such as security patches, but provides more time for jobs to execute. Consider the security implications of this tradeoff when setting timeout values.

    " } }, - "documentation":"

    Specifies the infrastructure update policy for the Amazon EC2 compute environment. For more information about infrastructure updates, see Updating compute environments in the Batch User Guide.

    " + "documentation":"

    Specifies the infrastructure update policy for the Amazon EC2 compute environment. For more information about infrastructure updates, see Updating compute environments in the Batch User Guide.

    The updatePolicy property applies only to Amazon EC2 managed compute environments. Batch doesn't support updatePolicy for Fargate compute environments. If you specify it for a Fargate compute environment, Batch ignores it.

    " }, "UpdateQuotaShareRequest":{ "type":"structure", diff --git a/services/bcmdashboards/pom.xml b/services/bcmdashboards/pom.xml index a70a32e4d9f5..434998d5a842 100644 --- a/services/bcmdashboards/pom.xml +++ b/services/bcmdashboards/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bcmdashboards AWS Java SDK :: Services :: BCM Dashboards diff --git a/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2bdb4ebb47c6 --- /dev/null +++ b/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,118 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-dashboards-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-dashboards.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 62d9215159fe..000000000000 --- a/services/bcmdashboards/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://bcm-dashboards-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://bcm-dashboards.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bcmdataexports/pom.xml b/services/bcmdataexports/pom.xml index 1e5b5bcd0ffb..0c8737f43d72 100644 --- a/services/bcmdataexports/pom.xml +++ b/services/bcmdataexports/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bcmdataexports AWS Java SDK :: Services :: BCM Data Exports diff --git a/services/bcmdataexports/src/main/resources/codegen-resources/customization.config b/services/bcmdataexports/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/bcmdataexports/src/main/resources/codegen-resources/customization.config +++ b/services/bcmdataexports/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4c1df3a6c105 --- /dev/null +++ b/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,242 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports.eu-isoe-west-1.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports.us-isof-south-1.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-data-exports.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 10, + "nodes": "/////wAAAAH/////AAAAAAAAAAoAAAADAAAAAQAAAAQF9eEJAAAAAgAAAAUF9eEJAAAAAwX14QcAAAAGAAAABAX14QMAAAAHAAAABQX14QQAAAAIAAAABgX14QUAAAAJAAAABwX14QYF9eEIAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d362c5ace7a1..000000000000 --- a/services/bcmdataexports/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,315 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://bcm-data-exports.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://bcm-data-exports.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://bcm-data-exports.eu-isoe-west-1.cloud.adc-e.uk", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eu-isoe-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://bcm-data-exports.us-isof-south-1.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://bcm-data-exports-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://bcm-data-exports.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bcmdataexports/src/main/resources/codegen-resources/service-2.json b/services/bcmdataexports/src/main/resources/codegen-resources/service-2.json index ef51faf32acb..4bd214173416 100644 --- a/services/bcmdataexports/src/main/resources/codegen-resources/service-2.json +++ b/services/bcmdataexports/src/main/resources/codegen-resources/service-2.json @@ -265,7 +265,8 @@ "type":"string", "enum":[ "GZIP", - "PARQUET" + "PARQUET", + "ZIP" ] }, "CreateExportRequest":{ @@ -401,7 +402,8 @@ "enum":[ "INSUFFICIENT_PERMISSION", "BILL_OWNER_CHANGED", - "INTERNAL_FAILURE" + "INTERNAL_FAILURE", + "DEPRECATED" ] }, "Export":{ @@ -855,7 +857,7 @@ }, "S3BucketOwner":{ "shape":"AccountId", - "documentation":"

    The AWS Account ID that owns the S3 bucket used as the destination for the data export.

    " + "documentation":"

    The Amazon Web Services account ID that owns the S3 bucket used as the destination for the data export.

    " }, "S3Prefix":{ "shape":"GenericString", diff --git a/services/bcmpricingcalculator/pom.xml b/services/bcmpricingcalculator/pom.xml index 65be35c55a8a..fab47abf966e 100644 --- a/services/bcmpricingcalculator/pom.xml +++ b/services/bcmpricingcalculator/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bcmpricingcalculator AWS Java SDK :: Services :: BCM Pricing Calculator diff --git a/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e8831bcf49b1 --- /dev/null +++ b/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,118 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-pricing-calculator-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-pricing-calculator.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5fa8c9c9edd8..000000000000 --- a/services/bcmpricingcalculator/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://bcm-pricing-calculator-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://bcm-pricing-calculator.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bcmrecommendedactions/pom.xml b/services/bcmrecommendedactions/pom.xml index ffb75d84d0d9..32d5a67d3a77 100644 --- a/services/bcmrecommendedactions/pom.xml +++ b/services/bcmrecommendedactions/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bcmrecommendedactions AWS Java SDK :: Services :: BCM Recommended Actions diff --git a/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fe9b2c5d46ad --- /dev/null +++ b/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,118 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-recommended-actions-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bcm-recommended-actions.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8f88d8031d22..000000000000 --- a/services/bcmrecommendedactions/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://bcm-recommended-actions-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://bcm-recommended-actions.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrock/pom.xml b/services/bedrock/pom.xml index 6b1d0aede83a..2a5981a9d834 100644 --- a/services/bedrock/pom.xml +++ b/services/bedrock/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrock AWS Java SDK :: Services :: Bedrock diff --git a/services/bedrock/src/main/resources/codegen-resources/customization.config b/services/bedrock/src/main/resources/codegen-resources/customization.config index 42aa381cf2ea..2edb12c857bc 100644 --- a/services/bedrock/src/main/resources/codegen-resources/customization.config +++ b/services/bedrock/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "enableEnvironmentBearerToken": true } diff --git a/services/bedrock/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrock/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..499dd913401b --- /dev/null +++ b/services/bedrock/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrock/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrock/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b215ea692529..000000000000 --- a/services/bedrock/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrock/src/main/resources/codegen-resources/service-2.json b/services/bedrock/src/main/resources/codegen-resources/service-2.json index c172d91495d3..666368fdc953 100644 --- a/services/bedrock/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrock/src/main/resources/codegen-resources/service-2.json @@ -2331,6 +2331,12 @@ }, "documentation":"

    Contains a summary of an advanced prompt optimization job.

    " }, + "AdvancedPromptOptimizationModelIdentifier":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"(([a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63}([a-z0-9-]{1,63}[.]){0,2}[a-z0-9-]{1,63}([:][a-z0-9-]{1,63}){0,2}(/[a-z0-9]{12}|))|(arn:aws(|-us-gov|-cn|-iso|-iso-b|-iso-f):bedrock:[a-z0-9-]{1,20}:[0-9]{12}:application-inference-profile/[a-zA-Z0-9-:.]+)|(arn:aws(|-us-gov|-cn|-iso|-iso-b|-iso-f):bedrock:[a-z0-9-]{1,20}:([0-9]{12})?:inference-profile/[a-zA-Z0-9-:.]+)|(arn:aws(-[^:]+)?:bedrock:[a-z0-9-]{1,20}::foundation-model/[a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63}([.:]?[a-z0-9-]{1,63})))" + }, "AdvancedPromptOptimizationOutputConfig":{ "type":"structure", "required":["s3Uri"], @@ -6282,10 +6288,11 @@ }, "DataRetentionMode":{ "type":"string", - "documentation":"

    The data retention mode for the account. Valid values are:

    • default – The standard data handling for the model applies.

    • none – Zero data retention.

    • provider_data_share – Data may be shared with the model provider.

    • inherit – No data retention mode is set at this scope.

    ", + "documentation":"

    The data retention mode for the account. Valid values are:

    • default – The standard data handling for the model applies.

    • none – Zero data retention.

    • aws_review – Amazon Web Services may review the request data. The data is not shared with the model provider. A model must support this mode to be invoked under it.

    • provider_data_share – Data may be shared with the model provider.

    • inherit – No data retention mode is set at this scope.

    ", "enum":[ "default", "none", + "aws_review", "provider_data_share", "inherit" ] @@ -12169,8 +12176,8 @@ "required":["modelId"], "members":{ "modelId":{ - "shape":"BedrockModelId", - "documentation":"

    The ID of the model to use for optimization.

    " + "shape":"AdvancedPromptOptimizationModelIdentifier", + "documentation":"

    The model to use for optimization. The value depends on the resource that you use:

    • If you use a base model, specify the model ID or its ARN. For a list of model IDs, see Models at a glance in the Amazon Bedrock User Guide.

    • If you use a cross-Region (system-defined) inference profile, specify the inference profile ID or its ARN. For a list of inference profile IDs, see Supported Regions and models for inference profiles in the Amazon Bedrock User Guide.

    • If you use an application inference profile, specify its full ARN, including the account ID and Region.

    " }, "inferenceConfig":{ "shape":"InferenceConfiguration", @@ -13560,7 +13567,7 @@ }, "listContains":{ "shape":"FilterAttribute", - "documentation":"

    Knowledge base data sources are returned if they contain a metadata attribute whose name matches the key and whose value is a list that contains the value as one of its members.

    The following example would return data sources with an animals attribute that is a list containing a cat member (for example, [\"dog\", \"cat\"]): \"listContains\": { \"key\": \"animals\", \"value\": \"cat\" }

    " + "documentation":"

    Knowledge base data sources are returned if they contain a metadata attribute whose name matches the key and whose value is a list that contains the value as one of its members.

    The following example would return data sources with an animals attribute that is a list containing a cat member (for example, [\"dog\", \"cat\"] ): \"listContains\": { \"key\": \"animals\", \"value\": \"cat\" }

    " }, "stringContains":{ "shape":"FilterAttribute", diff --git a/services/bedrockagent/pom.xml b/services/bedrockagent/pom.xml index 8a2e669f6a65..1ed980ec3966 100644 --- a/services/bedrockagent/pom.xml +++ b/services/bedrockagent/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockagent AWS Java SDK :: Services :: Bedrock Agent diff --git a/services/bedrockagent/src/main/resources/codegen-resources/customization.config b/services/bedrockagent/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/bedrockagent/src/main/resources/codegen-resources/customization.config +++ b/services/bedrockagent/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/bedrockagent/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockagent/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..79325cc283f4 --- /dev/null +++ b/services/bedrockagent/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockagent/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockagent/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 445857f1e0a2..000000000000 --- a/services/bedrockagent/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockagent/src/main/resources/codegen-resources/service-2.json b/services/bedrockagent/src/main/resources/codegen-resources/service-2.json index e33548b71870..ca7e6120d517 100644 --- a/services/bedrockagent/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockagent/src/main/resources/codegen-resources/service-2.json @@ -72,7 +72,7 @@ {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Creates an agent that orchestrates interactions between foundation models, data sources, software applications, user conversations, and APIs to carry out tasks to help customers.

    • Specify the following fields for security purposes.

      • agentResourceRoleArn – The Amazon Resource Name (ARN) of the role with permissions to invoke API operations on an agent.

      • (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 InvokeAgent request begins a new session.

    • To enable your agent to retain conversational context across multiple sessions, include a memoryConfiguration object. For more information, see Configure memory.

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

    • If your agent fails to be created, the response returns a list of failureReasons alongside a list of recommendedActions for you to troubleshoot.

    • 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.

    ", + "documentation":"

    Amazon Bedrock Agents (now Amazon Bedrock Agents Classic) is no longer open to new customers. For capabilities similar to Bedrock Agents Classic, explore Amazon Bedrock AgentCore. Existing customers can continue to use the service as normal. For more information, see Amazon Bedrock Agents Classic availability change.

    Creates an agent that orchestrates interactions between foundation models, data sources, software applications, user conversations, and APIs to carry out tasks to help customers.

    • Specify the following fields for security purposes.

      • agentResourceRoleArn – The Amazon Resource Name (ARN) of the role with permissions to invoke API operations on an agent.

      • (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 InvokeAgent request begins a new session.

    • To enable your agent to retain conversational context across multiple sessions, include a memoryConfiguration object. For more information, see Configure memory.

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

    • If your agent fails to be created, the response returns a list of failureReasons alongside a list of recommendedActions for you to troubleshoot.

    • 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.

    ", "idempotent":true }, "CreateAgentActionGroup":{ @@ -2645,11 +2645,21 @@ }, "audio":{ "shape":"AudioConfigurations", - "documentation":"

    Configuration settings for processing audio content in multimodal knowledge bases.

    " + "documentation":"

    Configuration settings for processing audio content in multimodal knowledge bases.

    This field is deprecated. Use modelConfiguration instead.

    ", + "deprecated":true, + "deprecatedMessage":"Use Managed Knowledge Base's modelConfiguration field. https://docs.aws.amazon.com/bedrock/latest/userguide/kb-build-managed.html", + "deprecatedSince":"2026-09-01" }, "video":{ "shape":"VideoConfigurations", - "documentation":"

    Configuration settings for processing video content in multimodal knowledge bases.

    " + "documentation":"

    Configuration settings for processing video content in multimodal knowledge bases.

    This field is deprecated. Use modelConfiguration instead.

    ", + "deprecated":true, + "deprecatedMessage":"Use Managed Knowledge Base's modelConfiguration field. https://docs.aws.amazon.com/bedrock/latest/userguide/kb-build-managed.html", + "deprecatedSince":"2026-09-01" + }, + "modelConfiguration":{ + "shape":"Document", + "documentation":"

    Model-specific configuration for the embedding model, provided as a JSON object. Use this field to specify settings that apply to the embedding model that you selected, such as how audio and video files are divided into segments.

    The fields that this object accepts depend on the embedding model. For the settings that each model accepts, see the documentation for that model.

    " } }, "documentation":"

    The vector configuration details for the Bedrock embeddings model.

    " @@ -3864,6 +3874,11 @@ }, "documentation":"

    Details about a cyclic connection detected in the flow.

    " }, + "DailySchedule":{ + "type":"structure", + "members":{}, + "documentation":"

    A daily sync. The run time is system-chosen (off-peak) and not configurable.

    " + }, "Data":{ "type":"string", "max":5242880, @@ -4044,6 +4059,41 @@ "type":"timestamp", "timestampFormat":"iso8601" }, + "DayOfMonth":{ + "type":"structure", + "members":{ + "dayNumber":{ + "shape":"DayOfMonthNumber", + "documentation":"

    A specific day of the month, from 1 to 28. Values are capped at 28, so a monthly sync runs in every month, including February.

    " + }, + "lastDayOfMonth":{ + "shape":"LastDayOfMonth", + "documentation":"

    Set this option to run the monthly sync on the last calendar day of each month.

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

    The day of the month on which a monthly sync runs. Specify exactly one of dayNumber or lastDayOfMonth.

    ", + "union":true + }, + "DayOfMonthNumber":{ + "type":"integer", + "documentation":"

    A specific day of the month, from 1 to 28.

    ", + "box":true, + "max":28, + "min":1 + }, + "DayOfWeek":{ + "type":"string", + "documentation":"

    The day of the week on which a weekly sync runs. Valid values are the standard English day names, for example, MONDAY or TUESDAY.

    ", + "enum":[ + "SUNDAY", + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY" + ] + }, "DeleteAgentActionGroupRequest":{ "type":"structure", "required":[ @@ -7128,7 +7178,10 @@ "shape":"VectorKnowledgeBaseConfiguration", "documentation":"

    Contains details about the model that's used to convert the data source into vector embeddings.

    " }, - "managedKnowledgeBaseConfiguration":{"shape":"ManagedKnowledgeBaseConfiguration"}, + "managedKnowledgeBaseConfiguration":{ + "shape":"ManagedKnowledgeBaseConfiguration", + "documentation":"

    Contains configuration details for a knowledge base that uses a vector store fully managed by Amazon Bedrock. Specify this object when the knowledge base type is MANAGED.

    " + }, "kendraKnowledgeBaseConfiguration":{ "shape":"KendraKnowledgeBaseConfiguration", "documentation":"

    Settings for an Amazon Kendra knowledge base.

    " @@ -7392,6 +7445,11 @@ }, "documentation":"

    Contains configurations for a Lambda function node in the flow. You specify the Lambda function to invoke and the inputs into the function. The output is the response that is defined in the Lambda function. For more information, see Node types in a flow in the Amazon Bedrock User Guide.

    " }, + "LastDayOfMonth":{ + "type":"structure", + "members":{}, + "documentation":"

    The option to run the monthly sync on the last calendar day of each month.

    " + }, "LexFlowNodeConfiguration":{ "type":"structure", "required":[ @@ -8063,13 +8121,26 @@ "ManagedKnowledgeBaseConfiguration":{ "type":"structure", "members":{ - "embeddingModelType":{"shape":"EmbeddingModelType"}, + "embeddingModelType":{ + "shape":"EmbeddingModelType", + "documentation":"

    Choose CUSTOM to provide your own Bedrock embedding model ARN. Choose MANAGED to use a service-managed embedding model.

    " + }, "embeddingModelArn":{ "shape":"BedrockEmbeddingModelArn", "documentation":"

    The ARN for the embeddings model.

    " }, - "embeddingModelConfiguration":{"shape":"EmbeddingModelConfiguration"}, - "serverSideEncryptionConfiguration":{"shape":"ServerSideEncryptionConfiguration"} + "embeddingModelConfiguration":{ + "shape":"EmbeddingModelConfiguration", + "documentation":"

    The configuration details for the embeddings model. Not required when choosing the MANAGED embeddingModelType.

    " + }, + "serverSideEncryptionConfiguration":{ + "shape":"ServerSideEncryptionConfiguration", + "documentation":"

    Contains the configuration for server-side encryption for your managed knowledge base.

    " + }, + "supplementalDataStorageConfiguration":{ + "shape":"SupplementalDataStorageConfiguration", + "documentation":"

    Use this object to specify the Amazon S3 location that the knowledge base uses to process and ingest multimodal content. This field is required when you use a native multimodal embedding model.

    " + } }, "documentation":"

    Configurations for a managed knowledge base.

    " }, @@ -8087,6 +8158,10 @@ "connectorParameters":{ "shape":"Document", "documentation":"

    Connector-specific parameters. For more information, see Connect a data source.

    " + }, + "syncSchedule":{ + "shape":"SyncSchedule", + "documentation":"

    The recurring schedule on which the connector automatically syncs this data source. If not specified, the data source is not synced automatically and you start each sync yourself. Not supported for the Custom connector.

    " } }, "documentation":"

    Configuration for managed knowledge base connector data sources.

    " @@ -8510,6 +8585,17 @@ "min":0, "pattern":".*" }, + "MonthlySchedule":{ + "type":"structure", + "required":["dayOfMonth"], + "members":{ + "dayOfMonth":{ + "shape":"DayOfMonth", + "documentation":"

    The day of the month on which the monthly sync runs.

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

    A monthly sync on a specified day of the month.

    " + }, "MultipleLoopControllerNodesFlowValidationDetails":{ "type":"structure", "required":["loopNode"], @@ -8804,7 +8890,7 @@ "members":{ "parsingStrategy":{ "shape":"ParsingStrategy", - "documentation":"

    The parsing strategy for the data source. Only SMART_PARSING can be selected for managed knowledge bases. For more information, see Customize ingestion for managed knowledge bases.

    " + "documentation":"

    The parsing strategy for the data source.

    For managed knowledge bases, the strategy that you can select depends on the embedding model that your knowledge base uses:

    • If your knowledge base uses a native multimodal embedding model, specify MULTI_MODAL_EMBEDDINGS. With this strategy, files are sent directly to the embedding model instead of being parsed into text. This is the only strategy that is supported for these knowledge bases.

    • Otherwise, specify SMART_PARSING.

    For more information, see Customize ingestion for managed knowledge bases.

    " }, "bedrockFoundationModelConfiguration":{ "shape":"BedrockFoundationModelConfiguration", @@ -8842,7 +8928,8 @@ "enum":[ "BEDROCK_FOUNDATION_MODEL", "BEDROCK_DATA_AUTOMATION", - "SMART_PARSING" + "SMART_PARSING", + "MULTI_MODAL_EMBEDDINGS" ] }, "PatternObjectFilter":{ @@ -10650,6 +10737,25 @@ "type":"string", "enum":["Python_3"] }, + "SyncSchedule":{ + "type":"structure", + "members":{ + "daily":{ + "shape":"DailySchedule", + "documentation":"

    A daily sync that runs once a day at a system-chosen off-peak time. The run time is not configurable.

    " + }, + "weekly":{ + "shape":"WeeklySchedule", + "documentation":"

    A weekly sync that runs once a week on the specified day of the week.

    " + }, + "monthly":{ + "shape":"MonthlySchedule", + "documentation":"

    A monthly sync that runs once a month on the specified day of the month.

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

    The recurring schedule on which a managed knowledge base connector automatically syncs its data source. Specify exactly one of daily, weekly, or monthly.

    ", + "union":true + }, "SystemContentBlock":{ "type":"structure", "members":{ @@ -10870,7 +10976,7 @@ }, "strict":{ "shape":"Boolean", - "documentation":"

    Whether to enforce strict JSON schema adherence for the tool input

    " + "documentation":"

    Whether the tool schema is strictly enforced.

    " } }, "documentation":"

    Contains a specification for a tool. For more information, see Use a tool to complete an Amazon Bedrock model response.

    " @@ -12111,10 +12217,21 @@ }, "documentation":"

    The configuration of the URL/URLs for the web content that you want to crawl. You should be authorized to crawl the URLs.

    " }, + "WeeklySchedule":{ + "type":"structure", + "required":["dayOfWeek"], + "members":{ + "dayOfWeek":{ + "shape":"DayOfWeek", + "documentation":"

    The day of the week on which the weekly sync runs.

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

    A weekly sync on a specified day of the week.

    " + }, "WorkgroupArn":{ "type":"string", "pattern":"(arn:(aws(-[a-z]+)*):redshift-serverless:[a-z]{2}(-gov)?-[a-z]+-\\d{1}:\\d{12}:workgroup/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})" } }, - "documentation":"

    Describes the API operations for creating and managing Amazon Bedrock agents.

    " + "documentation":"

    Amazon Bedrock Agents (now Amazon Bedrock Agents Classic) is no longer open to new customers. For capabilities similar to Bedrock Agents Classic, explore Amazon Bedrock AgentCore. Existing customers can continue to use the service as normal. For more information, see Amazon Bedrock Agents Classic availability change.

    Describes the API operations for creating and managing Amazon Bedrock agents.

    " } diff --git a/services/bedrockagentcore/pom.xml b/services/bedrockagentcore/pom.xml index 55c604c71379..cb5163cda905 100644 --- a/services/bedrockagentcore/pom.xml +++ b/services/bedrockagentcore/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockagentcore AWS Java SDK :: Services :: Bedrock Agent Core diff --git a/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3948ca4722fc --- /dev/null +++ b/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 23281d945f46..000000000000 --- a/services/bedrockagentcore/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockagentcore/src/main/resources/codegen-resources/service-2.json b/services/bedrockagentcore/src/main/resources/codegen-resources/service-2.json index df7005ce28da..518355e9ee24 100644 --- a/services/bedrockagentcore/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockagentcore/src/main/resources/codegen-resources/service-2.json @@ -147,7 +147,9 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"SubscriptionRequiredException"} ], "documentation":"

    Create a new payment instrument for a connector.

    ", "idempotent":true @@ -167,7 +169,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"} + {"shape":"InternalServerException"}, + {"shape":"SubscriptionRequiredException"} ], "documentation":"

    Create a new payment session.

    ", "idempotent":true @@ -214,6 +217,25 @@ "documentation":"

    Deletes a batch evaluation and its associated results.

    ", "idempotent":true }, + "DeleteCapacityProviderSession":{ + "name":"DeleteCapacityProviderSession", + "http":{ + "method":"DELETE", + "requestUri":"/capacity-providers/{capacityProviderId}/sessions/{sessionId}", + "responseCode":202 + }, + "input":{"shape":"DeleteCapacityProviderSessionRequest"}, + "output":{"shape":"DeleteCapacityProviderSessionResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes a session associated with a capacity provider in Amazon Bedrock AgentCore and makes the session unavailable for further use. To delete a capacity provider session, specify both the capacity provider identifier and the session ID. After you delete a session, you cannot restart it.

    ", + "idempotent":true + }, "DeleteEvent":{ "name":"DeleteEvent", "http":{ @@ -668,6 +690,26 @@ ], "documentation":"

    Obtains a workload access token for agentic workloads acting on behalf of a user, using the user's ID.

    " }, + "IngestData":{ + "name":"IngestData", + "http":{ + "method":"POST", + "requestUri":"/memories/{memoryId}/ingest", + "responseCode":202 + }, + "input":{"shape":"IngestDataInput"}, + "output":{"shape":"IngestDataOutput"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottledException"}, + {"shape":"ServiceException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Submits content directly for ingestion to generate long-term memory records in a AgentCore Memory resource.

    To use this operation, you must have the bedrock-agentcore:IngestData permission.

    ", + "idempotent":true + }, "InvokeAgentRuntime":{ "name":"InvokeAgentRuntime", "http":{ @@ -1016,8 +1058,10 @@ {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, - {"shape":"InternalServerException"} + {"shape":"InternalServerException"}, + {"shape":"SubscriptionRequiredException"} ], "documentation":"

    Processes a payment using a payment instrument within a payment session.

    ", "idempotent":true @@ -1574,6 +1618,10 @@ "batchEvaluation":{ "shape":"BatchEvaluationTraceConfig", "documentation":"

    Use a completed batch evaluation as the source of agent traces.

    " + }, + "onlineEvaluation":{ + "shape":"OnlineEvaluationTraceConfig", + "documentation":"

    Agent traces from an online evaluation configuration over a specified time range.

    " } }, "documentation":"

    The configuration specifying where to read agent traces from for recommendation analysis.

    ", @@ -2185,6 +2233,28 @@ "max":512, "min":10 }, + "CapacityProviderArn":{ + "type":"string", + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:capacity-provider/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" + }, + "CapacityProviderId":{ + "type":"string", + "documentation":"

    Capacity provider identifier. Pattern matches MiskiModel definition.

    ", + "max":59, + "min":12, + "pattern":"[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" + }, + "CapacityProviderSessionStatus":{ + "type":"string", + "enum":[ + "Provisioning", + "Deprovisioning", + "Active", + "Deleting", + "Deleted", + "Stopped" + ] + }, "Certificate":{ "type":"structure", "required":["location"], @@ -2229,6 +2299,10 @@ "timeRange":{ "shape":"SessionFilterConfig", "documentation":"

    The time range filter for selecting sessions to evaluate.

    " + }, + "sessionTraceIds":{ + "shape":"SessionTraceIdsList", + "documentation":"

    A list of session and trace ID pairs that restrict evaluation to specific traces within a session. If specified, only the listed traces are evaluated instead of the entire session.

    " } }, "documentation":"

    Filter configuration for narrowing down CloudWatch Logs sessions for evaluation.

    " @@ -2298,10 +2372,7 @@ }, "CloudWatchLogsSource":{ "type":"structure", - "required":[ - "serviceNames", - "logGroupNames" - ], + "required":["serviceNames"], "members":{ "serviceNames":{ "shape":"CloudWatchLogsSourceServiceNamesList", @@ -2309,7 +2380,11 @@ }, "logGroupNames":{ "shape":"CloudWatchLogsSourceLogGroupNamesList", - "documentation":"

    The list of CloudWatch log group names to read agent traces from. Maximum of 5 log groups.

    " + "documentation":"

    The list of CloudWatch log group names to read agent traces from. Maximum of 10 log groups.

    " + }, + "logGroupNamePrefixes":{ + "shape":"CloudWatchLogsSourceLogGroupNamePrefixesList", + "documentation":"

    The list of CloudWatch log group name prefixes to read agent traces from. Specify this instead of logGroupNames to match log groups by prefix. Maximum of 5 prefixes. Specify either logGroupNames or logGroupNamePrefixes, not both. One of the two is required.

    " }, "filterConfig":{ "shape":"CloudWatchFilterConfig", @@ -2318,12 +2393,20 @@ }, "documentation":"

    The configuration for reading agent traces from CloudWatch Logs.

    " }, - "CloudWatchLogsSourceLogGroupNamesList":{ + "CloudWatchLogsSourceLogGroupNamePrefixesList":{ "type":"list", - "member":{"shape":"String"}, + "member":{"shape":"LogGroupNamePrefix"}, + "documentation":"

    List of CloudWatch Logs log group name prefixes to source trace data from.

    ", "max":5, "min":1 }, + "CloudWatchLogsSourceLogGroupNamesList":{ + "type":"list", + "member":{"shape":"LogGroupName"}, + "documentation":"

    Length is constrained per member, because members relaxed from @required carry @default([]).

    ", + "max":10, + "min":0 + }, "CloudWatchLogsSourceServiceNamesList":{ "type":"list", "member":{"shape":"String"}, @@ -2370,18 +2453,22 @@ }, "CloudWatchOutputConfig":{ "type":"structure", - "required":[ - "logGroupName", - "logStreamName" - ], "members":{ "logGroupName":{ - "shape":"String", - "documentation":"

    The name of the CloudWatch log group where evaluation results will be written.

    " + "shape":"OptionalLogGroupName", + "documentation":"

    The name of the CloudWatch log group where evaluation results will be written. This value doesn't apply when resultDestination is SOURCE_LOG_GROUP, because results are written back to the trace source log group. The name can't be under the service-reserved /aws/bedrock-agentcore/evaluations/ namespace, apart from the service-managed default group.

    " }, "logStreamName":{ - "shape":"String", + "shape":"LogStreamName", "documentation":"

    The name of the CloudWatch log stream where evaluation results will be written.

    " + }, + "metricsNamespace":{ + "shape":"MetricsNamespace", + "documentation":"

    The CloudWatch metrics namespace where evaluation result metrics are published. If you omit this value, the service publishes metrics to Bedrock-AgentCore/Evaluations. This value can't begin with AWS/.

    " + }, + "resultDestination":{ + "shape":"ResultDestination", + "documentation":"

    The destination where evaluation results are written. Valid values:

    • DEDICATED_LOG_GROUP (default) – Writes results to a dedicated result log group.

    • SOURCE_LOG_GROUP – Writes results back to the log group that the agent traces were read from. If you use this value, don't specify logGroupName.

    " } }, "documentation":"

    CloudWatch Logs destination for batch evaluation results.

    " @@ -2719,6 +2806,17 @@ }, "documentation":"

    An event that contains incremental output from a command execution. This event streams standard output and standard error content as it becomes available during command execution.

    " }, + "ContentSource":{ + "type":"structure", + "members":{ + "inline":{ + "shape":"InlineMemoryContent", + "documentation":"

    The content included directly in the request.

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

    The source of the content to ingest. Only inline content is supported.

    ", + "union":true + }, "ContentStartEvent":{ "type":"structure", "members":{}, @@ -2918,7 +3016,7 @@ }, "payload":{ "shape":"PayloadTypeList", - "documentation":"

    The content payload of the event. This can include conversational data or binary content.

    " + "documentation":"

    The content payload of the event. This can include conversational data, JSON data, or binary content.

    " }, "branch":{ "shape":"Branch", @@ -2936,6 +3034,10 @@ "extractionMode":{ "shape":"ExtractionMode", "documentation":"

    Controls long-term memory extraction for this event. When set to SKIP, the event is stored in short-term memory but is excluded from long-term memory extraction. If not specified, the event is processed for extraction as usual.

    " + }, + "extractionConfig":{ + "shape":"ExtractionConfig", + "documentation":"

    The extraction configuration for long-term memory records. Use this parameter to specify namespace variable keys and their values for namespace substitution during extraction.

    " } } }, @@ -3089,6 +3191,10 @@ "payload":{ "shape":"PaymentDocument", "documentation":"

    The X402 payment payload.

    " + }, + "permit2AllowanceLimit":{ + "shape":"Permit2AllowanceLimit", + "documentation":"

    The maximum on-chain Permit2 allowance to grant before signing the payment authorization, in the asset's smallest denomination. This field is valid only for the upto (metered) scheme; supplying it for the exact scheme returns a validation error.

    When set, the service approves an ERC-20 allowance for this amount before processing the payment. The approval sets, rather than adds to, the wallet's allowance. Set this field only when the wallet needs approving, for example on its first upto payment, to avoid a redundant on-chain transaction. Omit the field to skip allowance handling. This is the default, and the only behavior for the exact scheme.

    " } }, "documentation":"

    The input for a crypto X402 payment.

    " @@ -3230,6 +3336,49 @@ } } }, + "DeleteCapacityProviderSessionRequest":{ + "type":"structure", + "required":[ + "capacityProviderId", + "sessionId" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider associated with the session.

    ", + "location":"uri", + "locationName":"capacityProviderId" + }, + "sessionId":{ + "shape":"SessionId", + "documentation":"

    The unique identifier of the capacity provider session to delete.

    ", + "location":"uri", + "locationName":"sessionId" + } + } + }, + "DeleteCapacityProviderSessionResponse":{ + "type":"structure", + "required":[ + "capacityProviderArn", + "sessionId", + "status" + ], + "members":{ + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider associated with the deleted session.

    " + }, + "sessionId":{ + "shape":"SessionId", + "documentation":"

    The unique identifier of the deleted capacity provider session.

    " + }, + "status":{ + "shape":"CapacityProviderSessionStatus", + "documentation":"

    The current status of the capacity provider session. When the status is Deleting, the session is being deleted and is not available. When the status is Deleted, the session is no longer available.

    " + } + } + }, "DeleteEventInput":{ "type":"structure", "required":[ @@ -3293,6 +3442,12 @@ "documentation":"

    The identifier of the memory record to delete.

    ", "location":"uri", "locationName":"memoryRecordId" + }, + "namespace":{ + "shape":"Namespace", + "documentation":"

    The namespace of the memory record to delete. This value is used for IAM condition key authorization.

    ", + "location":"querystring", + "locationName":"namespace" } } }, @@ -3481,6 +3636,42 @@ }, "exception":true }, + "EfsAccessPointArn":{ + "type":"string", + "max":128, + "min":0, + "pattern":"arn:aws[-a-z]*:elasticfilesystem:[0-9a-z-:]+:access-point/fsap-[0-9a-f]{8,40}" + }, + "EfsConfiguration":{ + "type":"structure", + "required":[ + "accessPointArn", + "mountPath", + "fileSystemArn" + ], + "members":{ + "accessPointArn":{ + "shape":"EfsAccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Elastic File System (Amazon EFS) access point to mount.

    " + }, + "mountPath":{ + "shape":"MountPath", + "documentation":"

    The absolute path within the session at which the access point is mounted, for example /mnt/efs. Each mount path must be unique across all file system configurations in the session.

    " + }, + "fileSystemArn":{ + "shape":"EfsFileSystemArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Elastic File System (Amazon EFS) file system that owns the access point.

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

    The configuration for mounting an Amazon Elastic File System (Amazon EFS) access point that you own into a session.

    " + }, + "EfsFileSystemArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Elastic File System (Amazon EFS) file system. The access points you specify must belong to this file system.

    ", + "max":256, + "min":0, + "pattern":"arn:aws[-a-z]*:elasticfilesystem:[a-z0-9-]+:[0-9]{12}:file-system/fs-[0-9a-f]{8,40}" + }, "Email":{ "type":"string", "documentation":"

    Email address with validation for standard email format.

    ", @@ -3799,11 +3990,13 @@ }, "EvaluatorArn":{ "type":"string", - "pattern":"arn:aws[a-zA-Z-]*:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:evaluator\\/[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10}$|^arn:aws[a-zA-Z-]*:bedrock-agentcore:::evaluator/Builtin.[a-zA-Z0-9_-]+" + "pattern":"arn:aws[a-zA-Z-]*:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:evaluator\\/[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10}$|^arn:aws[a-zA-Z-]*:bedrock-agentcore:::evaluator/(Builtin|ThirdParty)\\.[a-zA-Z0-9._-]+" }, "EvaluatorId":{ "type":"string", - "pattern":"(Builtin.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10})" + "max":111, + "min":1, + "pattern":"(Builtin\\.[a-zA-Z0-9._-]+|ThirdParty\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10})" }, "EvaluatorList":{ "type":"list", @@ -3838,7 +4031,9 @@ }, "EvaluatorName":{ "type":"string", - "pattern":"(Builtin.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9_]{0,47})" + "max":48, + "min":1, + "pattern":"(Builtin\\.[a-zA-Z0-9._-]+|ThirdParty\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9_]{0,47})" }, "EvaluatorStatistics":{ "type":"structure", @@ -4072,6 +4267,16 @@ "max":65535, "min":1 }, + "ExtractionConfig":{ + "type":"structure", + "members":{ + "namespaceVariables":{ + "shape":"NamespaceVariablesMap", + "documentation":"

    A map of namespaceKeys to their values. The service substitutes these values into namespaceTemplates during long-term memory extraction to control namespace hierarchy.

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

    The configuration for extraction behavior. Use this structure to specify namespace variable keys and their values for namespace substitution during long-term memory extraction.

    " + }, "ExtractionJob":{ "type":"structure", "required":["jobId"], @@ -4655,6 +4860,10 @@ "shape":"Certificates", "documentation":"

    The list of certificates installed in the browser session.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations for the browser session. Each entry describes an access point and its mount path.

    " + }, "sessionReplayArtifact":{ "shape":"String", "documentation":"

    The artifact containing the session replay information.

    " @@ -4721,6 +4930,10 @@ "certificates":{ "shape":"Certificates", "documentation":"

    The list of certificates installed in the code interpreter session.

    " + }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations for the code interpreter session. Each entry describes an access point and its mount path.

    " } } }, @@ -4787,6 +5000,12 @@ "documentation":"

    The identifier of the memory record to retrieve.

    ", "location":"uri", "locationName":"memoryRecordId" + }, + "namespace":{ + "shape":"Namespace", + "documentation":"

    The namespace of the memory record to retrieve. This value is used for IAM condition key authorization.

    ", + "location":"querystring", + "locationName":"namespace" } } }, @@ -5419,6 +5638,10 @@ "reasoningContent":{ "shape":"HarnessReasoningContentBlockDelta", "documentation":"

    A reasoning content delta.

    " + }, + "toolResultMetadata":{ + "shape":"HarnessToolResultMetadataBlockDelta", + "documentation":"

    A tool result metadata delta.

    " } }, "documentation":"

    A delta update to a content block.

    ", @@ -5553,10 +5776,77 @@ "topK":{ "shape":"TopK", "documentation":"

    The topK set when calling the model.

    " + }, + "additionalParams":{ + "shape":"Document", + "documentation":"

    Provider-specific parameters passed through to the Gemini model provider unchanged.

    " } }, "documentation":"

    Configuration for a Google Gemini model provider. Requires an API key stored in AgentCore Identity.

    " }, + "HarnessHookDecision":{ + "type":"string", + "enum":[ + "allow", + "deny" + ] + }, + "HarnessHookEvent":{ + "type":"structure", + "required":[ + "hookEventId", + "name", + "type" + ], + "members":{ + "hookEventId":{ + "shape":"HarnessHookEventId", + "documentation":"

    The unique identifier for this hook event.

    " + }, + "name":{ + "shape":"HarnessHookName", + "documentation":"

    The name of the hook that ran.

    " + }, + "type":{ + "shape":"HarnessHookEventType", + "documentation":"

    The type of lifecycle hook event.

    " + }, + "decision":{ + "shape":"HarnessHookDecision", + "documentation":"

    The decision applied to the hook event. This field is present only for blocking Lambda targets.

    " + }, + "reason":{ + "shape":"HarnessHookEventReasonString", + "documentation":"

    The optional reason for the applied decision.

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

    A lifecycle hook event emitted in the invocation stream for visibility into hook decisions.

    ", + "event":true + }, + "HarnessHookEventId":{ + "type":"string", + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "HarnessHookEventReasonString":{ + "type":"string", + "max":1024, + "min":0 + }, + "HarnessHookEventType":{ + "type":"string", + "enum":[ + "before_tool_call", + "after_tool_call", + "before_invocation", + "after_invocation" + ] + }, + "HarnessHookName":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, "HarnessInlineFunctionConfig":{ "type":"structure", "required":[ @@ -5710,6 +6000,12 @@ "documentation":"

    Specification of which model to use.

    ", "union":true }, + "HarnessOpenAiApiBase":{ + "type":"string", + "max":16383, + "min":1, + "sensitive":true + }, "HarnessOpenAiApiFormat":{ "type":"string", "enum":[ @@ -5732,6 +6028,10 @@ "shape":"ApiKeyArn", "documentation":"

    The ARN of your OpenAI API key on AgentCore Identity.

    " }, + "apiBase":{ + "shape":"HarnessOpenAiApiBase", + "documentation":"

    Optional custom endpoint URL for an OpenAI-compatible endpoint.

    " + }, "maxTokens":{ "shape":"MaxTokens", "documentation":"

    The maximum number of tokens to allow in the generated response per iteration.

    " @@ -5897,11 +6197,13 @@ }, "HarnessSkillGitUrl":{ "type":"string", + "max":16383, "min":8, "pattern":"https://[^#@]+" }, "HarnessSkillPath":{ "type":"string", + "max":4096, "min":1 }, "HarnessSkillS3Source":{ @@ -5917,6 +6219,7 @@ }, "HarnessSkillS3Uri":{ "type":"string", + "max":16383, "min":5, "pattern":"s3://.*" }, @@ -5940,7 +6243,8 @@ "model_context_window_exceeded", "max_iterations_exceeded", "max_output_tokens_exceeded", - "timeout_exceeded" + "timeout_exceeded", + "hook_stopped" ] }, "HarnessStreamMetrics":{ @@ -6156,6 +6460,17 @@ "type":"list", "member":{"shape":"HarnessToolResultContentBlock"} }, + "HarnessToolResultMetadataBlockDelta":{ + "type":"structure", + "required":["metadata"], + "members":{ + "metadata":{ + "shape":"SensitiveText", + "documentation":"

    The partial JSON-string fragment of the tool result metadata.

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

    Delta payload for a tool result metadata.

    " + }, "HarnessToolType":{ "type":"string", "enum":[ @@ -6299,6 +6614,83 @@ "max":100, "min":0 }, + "IngestDataInput":{ + "type":"structure", + "required":[ + "memoryId", + "source", + "contentTimestamp", + "actorId" + ], + "members":{ + "memoryId":{ + "shape":"MemoryId", + "documentation":"

    The identifier of the AgentCore Memory resource to ingest content into.

    ", + "location":"uri", + "locationName":"memoryId" + }, + "source":{ + "shape":"ContentSource", + "documentation":"

    The content to ingest. Only inline content is supported.

    " + }, + "contentTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of when the content occurred.

    " + }, + "actorId":{ + "shape":"ActorId", + "documentation":"

    The identifier of the actor associated with this content. An actor represents an entity that participates in sessions and generates content.

    " + }, + "sessionId":{ + "shape":"SessionId", + "documentation":"

    The identifier of the session that the content belongs to. If not provided, a session identifier is generated and returned in the response.

    " + }, + "extractionConfig":{ + "shape":"ExtractionConfig", + "documentation":"

    The extraction configuration for long-term memory records. Use this parameter to specify namespace variable keys and their values for namespace substitution during extraction.

    " + }, + "metadata":{ + "shape":"MetadataMap", + "documentation":"

    The key-value metadata to attach to the content.

    " + }, + "clientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, AgentCore ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "IngestDataOutput":{ + "type":"structure", + "required":["sessionId"], + "members":{ + "sessionId":{ + "shape":"SessionId", + "documentation":"

    The identifier of the session that the service ingested the content into. This value echoes the session identifier from the request, or the identifier that the service generated when you did not provide one.

    " + } + } + }, + "IngestPayloadList":{ + "type":"list", + "member":{"shape":"IngestPayloadType"}, + "max":100, + "min":1 + }, + "IngestPayloadType":{ + "type":"structure", + "members":{ + "conversational":{ + "shape":"Conversational", + "documentation":"

    The conversational content for this payload item.

    " + }, + "json":{ + "shape":"MemoryJsonData", + "documentation":"

    The JSON content for this payload item.

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

    A single content payload item to ingest. A payload item contains either conversational or JSON content.

    ", + "union":true + }, "InlineContent":{ "type":"string", "max":409600, @@ -6327,6 +6719,17 @@ "member":{"shape":"GroundTruthTurn"}, "min":1 }, + "InlineMemoryContent":{ + "type":"structure", + "required":["payload"], + "members":{ + "payload":{ + "shape":"IngestPayloadList", + "documentation":"

    The list of content payload items to ingest.

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

    The content included directly in the request as one or more payload items.

    " + }, "InputContentBlock":{ "type":"structure", "required":["path"], @@ -6706,6 +7109,18 @@ "location":"header", "locationName":"Mcp-Protocol-Version" }, + "mcpMethod":{ + "shape":"StringType", + "documentation":"

    The MCP method being invoked. For example, tools/call, resources/read, or prompts/get.

    ", + "location":"header", + "locationName":"Mcp-Method" + }, + "mcpName":{ + "shape":"StringType", + "documentation":"

    The name of the MCP resource, tool, or prompt being accessed. The value depends on the method:

    • tools/call – The tool name.

    • resources/read – The resource URI.

    • prompts/get – The prompt name.

    ", + "location":"header", + "locationName":"Mcp-Name" + }, "runtimeUserId":{ "shape":"StringType", "documentation":"

    The identifier of the runtime user.

    ", @@ -6996,6 +7411,30 @@ "location":"header", "locationName":"X-Amzn-Bedrock-AgentCore-Runtime-User-Id" }, + "traceParent":{ + "shape":"InvokeHarnessRequestTraceParentString", + "documentation":"

    W3C trace context parent header containing version, trace ID, parent span ID, and trace flags.

    ", + "location":"header", + "locationName":"traceparent" + }, + "traceState":{ + "shape":"InvokeHarnessRequestTraceStateString", + "documentation":"

    W3C trace context state header for vendor-specific trace information.

    ", + "location":"header", + "locationName":"tracestate" + }, + "traceId":{ + "shape":"InvokeHarnessRequestTraceIdString", + "documentation":"

    Trace ID for maintaining observability through the operation.

    ", + "location":"header", + "locationName":"X-Amzn-Trace-Id" + }, + "baggage":{ + "shape":"InvokeHarnessRequestBaggageString", + "documentation":"

    W3C Baggage header for user-defined context propagation. Format: key1=value1,key2=value2

    ", + "location":"header", + "locationName":"baggage" + }, "messages":{ "shape":"HarnessMessages", "documentation":"

    The messages to send to the agent.

    " @@ -7038,12 +7477,32 @@ } } }, + "InvokeHarnessRequestBaggageString":{ + "type":"string", + "max":8192, + "min":0 + }, "InvokeHarnessRequestRuntimeSessionIdString":{ "type":"string", "max":100, "min":33, "pattern":"[a-zA-Z0-9][a-zA-Z0-9-_]*" }, + "InvokeHarnessRequestTraceIdString":{ + "type":"string", + "max":1024, + "min":0 + }, + "InvokeHarnessRequestTraceParentString":{ + "type":"string", + "max":1024, + "min":0 + }, + "InvokeHarnessRequestTraceStateString":{ + "type":"string", + "max":512, + "min":0 + }, "InvokeHarnessResponse":{ "type":"structure", "required":["stream"], @@ -7087,6 +7546,10 @@ "runtimeClientError":{ "shape":"RuntimeClientError", "documentation":"

    An error returned by the runtime container during agent execution.

    " + }, + "hookEvent":{ + "shape":"HarnessHookEvent", + "documentation":"

    A lifecycle hook event emitted when a configured hook runs.

    " } }, "documentation":"

    The streaming events returned by a harness invocation.

    ", @@ -7861,6 +8324,22 @@ }, "documentation":"

    The configuration for a stream that provides a visual representation of a browser session in Amazon Bedrock AgentCore. This stream enables agents to observe the current state of the browser, including rendered web pages, visual elements, and the results of interactions.

    " }, + "LogGroupName":{ + "type":"string", + "pattern":"[.\\-_/#A-Za-z0-9]+" + }, + "LogGroupNamePrefix":{ + "type":"string", + "documentation":"

    Prefix of a CloudWatch Logs log group name.

    ", + "max":512, + "min":1, + "pattern":"[.\\-_/#A-Za-z0-9]+" + }, + "LogStreamName":{ + "type":"string", + "documentation":"

    A log stream name. The pattern is CloudWatch Logs' own log stream name pattern, which already admits the empty string; empty is the @default of members relaxed from @required and means "no log stream". No @length is applied, because CloudWatch's min of 1 would reject that default.

    ", + "pattern":"[^:*]*" + }, "Long":{ "type":"long", "box":true @@ -7927,6 +8406,24 @@ "min":12, "pattern":"(arn:(aws|aws-cn|aws-us-gov):bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:memory/)?[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10}" }, + "MemoryJsonData":{ + "type":"structure", + "required":["content"], + "members":{ + "content":{ + "shape":"MemoryJsonDataContent", + "documentation":"

    The JSON content of the payload. Accepts any JSON value, including objects, arrays, strings, numbers, booleans, and null. The maximum size is 100 KB.

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

    Contains non-conversational, JSON-formatted content for an event payload. JSON payloads are extracted into long-term memory.

    ", + "sensitive":true + }, + "MemoryJsonDataContent":{ + "type":"structure", + "members":{}, + "document":true, + "sensitive":true + }, "MemoryMetadataFilterExpression":{ "type":"structure", "required":[ @@ -8035,6 +8532,10 @@ "memoryRecordId":{ "shape":"MemoryRecordId", "documentation":"

    The unique ID of the memory record to be deleted.

    " + }, + "namespace":{ + "shape":"Namespace", + "documentation":"

    The namespace of the memory record being deleted. This value is used for IAM condition key authorization.

    " } }, "documentation":"

    Input structure to delete an existing memory record.

    " @@ -8217,6 +8718,10 @@ "shape":"NamespacesList", "documentation":"

    The updated list of namespace identifiers for categorizing the memory record.

    " }, + "sourceNamespaces":{ + "shape":"NamespacesList", + "documentation":"

    The namespaces of the source memory record being updated. This value is used for IAM condition key authorization.

    " + }, "memoryStrategyId":{ "shape":"MemoryStrategyId", "documentation":"

    The updated ID of the memory strategy that defines how this memory record is grouped.

    " @@ -8314,12 +8819,25 @@ "min":0, "pattern":"[a-zA-Z0-9\\s._:/=+@-]*" }, + "MetricsNamespace":{ + "type":"string", + "documentation":"

    CloudWatch metrics namespace for evaluation result metrics.

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9._#/:-]+" + }, "MimeType":{ "type":"string", "max":256, "min":1 }, "ModelId":{"type":"string"}, + "MountPath":{ + "type":"string", + "max":200, + "min":6, + "pattern":"/mnt/[a-zA-Z0-9._-]+/?" + }, "MouseButton":{ "type":"string", "documentation":"

    The mouse button to use for a browser mouse action.

    ", @@ -8509,6 +9027,63 @@ }, "documentation":"

    The result of a mouse scroll action.

    " }, + "MppPaymentCredential":{ + "type":"string", + "documentation":"

    Ready-to-send Authorization: Payment <base64url-token> value. This is a bearer-like payment credential and must not appear in logs, traces, or error messages.

    ", + "max":32768, + "min":1, + "sensitive":true + }, + "MppPaymentInput":{ + "type":"structure", + "required":[ + "version", + "wwwAuthenticateHeaders" + ], + "members":{ + "version":{ + "shape":"Version", + "documentation":"

    The MPP protocol version, for example \"1\" or \"2\".

    " + }, + "wwwAuthenticateHeaders":{ + "shape":"WwwAuthenticateHeaderList", + "documentation":"

    The raw WWW-Authenticate: Payment header value from the 402 response, passed verbatim. Provide exactly one entry. The service uses this value to generate the payment credential.

    " + }, + "buyerPaysGasFees":{ + "shape":"Boolean", + "documentation":"

    Authorizes the service to sign a payment whose blockchain network (gas) fees are charged to your wallet, on top of the payment amount.

    The challenge indicates who sponsors the network fees. When the challenge does not sponsor them, the service signs the payment only if this field is true. Otherwise it returns a validation error, so you can decide whether to pay the fees or obtain a challenge that sponsors them.

    Optional. When omitted or false, you decline to pay network fees. This field has no effect on challenges that already sponsor the fees.

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

    Contains the payment challenge from a 402 Payment Required response. Forward the raw WWW-Authenticate: Payment header value verbatim. In response, you receive a payment credential that satisfies the challenge. Provide exactly one challenge per request.

    " + }, + "MppPaymentOutput":{ + "type":"structure", + "required":[ + "version", + "selectedPaymentId", + "paymentCredential" + ], + "members":{ + "version":{ + "shape":"Version", + "documentation":"

    The MPP protocol version, for example \"1\" or \"2\".

    " + }, + "selectedPaymentId":{ + "shape":"MppPaymentOutputSelectedPaymentIdString", + "documentation":"

    The id of the challenge that was paid, echoed from the input challenge so you can correlate the result without decoding the credential.

    " + }, + "paymentCredential":{ + "shape":"MppPaymentCredential", + "documentation":"

    Ready-to-send value for the Authorization header, in the form \"Payment <base64url-token>\". Attach this header and retry the original request. To inspect the full credential, base64url-decode the token.

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

    Contains the payment credential, ready to retry the request.

    " + }, + "MppPaymentOutputSelectedPaymentIdString":{ + "type":"string", + "max":512, + "min":1 + }, "Name":{ "type":"string", "max":100, @@ -8520,6 +9095,28 @@ "min":1, "pattern":"[a-zA-Z0-9/*][a-zA-Z0-9-_/*]*(?::[a-zA-Z0-9-_/*]+)*[a-zA-Z0-9-_/*]*" }, + "NamespaceVariableName":{ + "type":"string", + "documentation":"

    The name of the namespace variable key. The name cannot be a built-in variable name (actorId, sessionId, or memoryStrategyId).

    ", + "max":32, + "min":1, + "pattern":"(?!memoryStrategyId$|actorId$|sessionId$)[a-z][a-z0-9]*" + }, + "NamespaceVariableValue":{ + "type":"string", + "documentation":"

    The value of a namespace variable key.

    ", + "max":64, + "min":1, + "pattern":"[a-z0-9][a-z0-9-_]*" + }, + "NamespaceVariablesMap":{ + "type":"map", + "key":{"shape":"NamespaceVariableName"}, + "value":{"shape":"NamespaceVariableValue"}, + "documentation":"

    A map of namespaceKeys to their values for namespace substitution.

    ", + "max":5, + "min":1 + }, "NamespacesList":{ "type":"list", "member":{"shape":"Namespace"}, @@ -8679,6 +9276,29 @@ }, "documentation":"

    A reference to an existing online evaluation configuration to use as the data source for batch evaluation.

    " }, + "OnlineEvaluationTraceConfig":{ + "type":"structure", + "required":[ + "onlineEvaluationConfigArn", + "startTime", + "endTime" + ], + "members":{ + "onlineEvaluationConfigArn":{ + "shape":"OnlineEvaluationConfigArn", + "documentation":"

    The ARN of the online evaluation configuration to reuse sessions from.

    " + }, + "startTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The start time of the time range. Only sessions evaluated at or after this timestamp are included.

    " + }, + "endTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The end time of the time range. Only sessions evaluated before this timestamp are included.

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

    Contains the configuration for reusing agent traces from an online evaluation configuration for recommendation analysis. Because online evaluation is a continuous stream, a time range specifies which evaluated sessions the recommendation includes.

    " + }, "OperatorType":{ "type":"string", "enum":[ @@ -8687,6 +9307,11 @@ "NOT_EXISTS" ] }, + "OptionalLogGroupName":{ + "type":"string", + "documentation":"

    A log group name that may also be empty. The empty string is the @default of members that were relaxed from @required, and carries the meaning "no log group" for that member.

    ", + "pattern":"$|^[.\\-_/#A-Za-z0-9]+" + }, "OutputConfig":{ "type":"structure", "members":{ @@ -8714,6 +9339,10 @@ "blob":{ "shape":"MemoryDocument", "documentation":"

    The binary content of the payload.

    " + }, + "json":{ + "shape":"MemoryJsonData", + "documentation":"

    The JSON content of the payload. Use this type to store non-conversational, JSON-formatted data, such as behavioral events, activity logs, or system events.

    " } }, "documentation":"

    Contains the payload content for an event.

    ", @@ -8760,7 +9389,8 @@ "cryptoX402":{ "shape":"CryptoX402PaymentInput", "documentation":"

    Input for a crypto X402 payment.

    " - } + }, + "mpp":{"shape":"MppPaymentInput"} }, "documentation":"

    The payment input details, which vary by payment type.

    ", "union":true @@ -8842,7 +9472,8 @@ "INITIATED", "ACTIVE", "FAILED", - "DELETED" + "DELETED", + "BLOCKED" ] }, "PaymentInstrumentSummary":{ @@ -8914,7 +9545,8 @@ "cryptoX402":{ "shape":"CryptoX402PaymentOutput", "documentation":"

    Output from a crypto X402 payment.

    " - } + }, + "mpp":{"shape":"MppPaymentOutput"} }, "documentation":"

    The payment output details, which vary by payment type.

    ", "union":true @@ -9072,7 +9704,10 @@ "PaymentType":{ "type":"string", "documentation":"

    Payment type enum.

    ", - "enum":["CRYPTO_X402"] + "enum":[ + "CRYPTO_X402", + "MPP" + ] }, "PerVariantOnlineEvaluationConfig":{ "type":"structure", @@ -9098,6 +9733,13 @@ "max":2, "min":2 }, + "Permit2AllowanceLimit":{ + "type":"string", + "documentation":"

    The maximum on-chain Permit2 allowance to grant, in the asset's smallest denomination. Pass the value as a numeric string. For example, \"1000000\" is 1 USDC at 6 decimals. To grant an unlimited allowance, pass the uint256 maximum, which is a 78-digit number.

    ", + "max":78, + "min":1, + "pattern":"[0-9]+" + }, "PhoneNumber":{ "type":"string", "documentation":"

    Phone number in E.164 format (e.g., +1234567890).

    ", @@ -9683,6 +10325,14 @@ "sensitive":true, "streaming":true }, + "ResultDestination":{ + "type":"string", + "documentation":"

    Where evaluation results are written: dedicated results log group (default) or the source log group.

    ", + "enum":[ + "DEDICATED_LOG_GROUP", + "SOURCE_LOG_GROUP" + ] + }, "RetrieveMemoryRecordsInput":{ "type":"structure", "required":[ @@ -9827,6 +10477,42 @@ }, "exception":true }, + "S3FilesAccessPointArn":{ + "type":"string", + "max":256, + "min":0, + "pattern":"arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}/access-point/fsap-[0-9a-f]{17,40}" + }, + "S3FilesConfiguration":{ + "type":"structure", + "required":[ + "accessPointArn", + "mountPath", + "fileSystemArn" + ], + "members":{ + "accessPointArn":{ + "shape":"S3FilesAccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Simple Storage Service (Amazon S3) Files access point to mount.

    " + }, + "mountPath":{ + "shape":"MountPath", + "documentation":"

    The absolute path within the session at which the access point is mounted, for example /mnt/s3data. Each mount path must be unique across all file system configurations in the session.

    " + }, + "fileSystemArn":{ + "shape":"S3FilesFileSystemArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Simple Storage Service (Amazon S3) Files file system that owns the access point.

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

    The configuration for mounting an Amazon Simple Storage Service (Amazon S3) Files access point that you own into a session.

    " + }, + "S3FilesFileSystemArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Simple Storage Service (Amazon S3) Files file system. The access points you specify must belong to this file system.

    ", + "max":256, + "min":0, + "pattern":"arn:aws[-a-z]*:s3files:[a-z0-9-]+:[0-9]{12}:file-system/fs-[0-9a-f]{17,40}" + }, "S3Location":{ "type":"structure", "required":[ @@ -10257,6 +10943,30 @@ "type":"list", "member":{"shape":"SessionSummary"} }, + "SessionTraceIds":{ + "type":"structure", + "required":[ + "sessionId", + "traceIds" + ], + "members":{ + "sessionId":{ + "shape":"String", + "documentation":"

    The unique identifier of the session that contains the traces to evaluate.

    " + }, + "traceIds":{ + "shape":"TraceIdList", + "documentation":"

    The list of trace IDs within the session to evaluate.

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

    A pairing of a session with the specific trace IDs to evaluate within that session. Use this to evaluate individual traces rather than an entire session.

    " + }, + "SessionTraceIdsList":{ + "type":"list", + "member":{"shape":"SessionTraceIds"}, + "max":500, + "min":1 + }, "SessionType":{ "type":"string", "max":256, @@ -10324,7 +11034,7 @@ "Spans":{ "type":"list", "member":{"shape":"Span"}, - "max":1000, + "max":20000, "min":1, "sensitive":true }, @@ -10371,7 +11081,8 @@ "description":{ "shape":"BatchEvaluationDescription", "documentation":"

    The description of the batch evaluation.

    " - } + }, + "outputConfig":{"shape":"OutputConfig"} } }, "StartBatchEvaluationRequestEvaluatorsList":{ @@ -10496,6 +11207,10 @@ "shape":"Certificates", "documentation":"

    A list of certificates to install in the browser session.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations to mount into the browser session. Use these configurations to mount your own Amazon Simple Storage Service (Amazon S3) Files or Amazon Elastic File System (Amazon EFS) access points. Your session can then read and write your data. If you don't specify this field, no additional file systems are mounted.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If this token matches a previous request, Amazon Bedrock AgentCore ignores the request, but does not return an error. This parameter helps prevent the creation of duplicate sessions if there are temporary network issues.

    ", @@ -10573,6 +11288,10 @@ "shape":"Certificates", "documentation":"

    A list of certificates to install in the code interpreter session.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations to mount into the code interpreter session. Use these configurations to mount your own Amazon Simple Storage Service (Amazon S3) Files or Amazon Elastic File System (Amazon EFS) access points. Your session can then read and write your data. If you don't specify this field, no additional file systems are mounted.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If this token matches a previous request, Amazon Bedrock AgentCore ignores the request, but does not return an error. This parameter helps prevent the creation of duplicate sessions if there are temporary network issues.

    ", @@ -11101,6 +11820,37 @@ }, "documentation":"

    Stripe Privy token response containing appId, basicAuthToken, and optionally authorizationSignature.

    " }, + "SubscriptionRequiredException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "subscriptionUrl":{ + "shape":"SubscriptionRequiredExceptionSubscriptionUrlString", + "documentation":"

    The URL to the Marketplace listing where you can subscribe.

    " + }, + "productName":{ + "shape":"SubscriptionRequiredExceptionProductNameString", + "documentation":"

    The name of the product that requires a Marketplace subscription.

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

    Returned when you attempt a wallet operation against a Coinbase Marketplace connector whose account does not hold an active Marketplace subscription and is not within the legacy exception period. Subscribe to the Marketplace listing before you retry the operation.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "SubscriptionRequiredExceptionProductNameString":{ + "type":"string", + "max":256, + "min":1 + }, + "SubscriptionRequiredExceptionSubscriptionUrlString":{ + "type":"string", + "max":2048, + "min":1 + }, "SyntheticTimestamp_date_time":{ "type":"timestamp", "timestampFormat":"iso8601" @@ -11586,6 +12336,28 @@ }, "documentation":"

    The MCP tools definition with a protocol version and inline content. The protocolVersion identifies the MCP protocol version that the tools conform to. This differs from schemaVersion in the server definition, which identifies the server configuration schema format.

    " }, + "ToolsFileSystemConfiguration":{ + "type":"structure", + "members":{ + "s3FilesConfiguration":{ + "shape":"S3FilesConfiguration", + "documentation":"

    The configuration for mounting your own Amazon Simple Storage Service (Amazon S3) Files access point into the session.

    " + }, + "efsConfiguration":{ + "shape":"EfsConfiguration", + "documentation":"

    The configuration for mounting your own Amazon Elastic File System (Amazon EFS) access point into the session.

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

    Specifies a file system to mount into the session by providing exactly one of the following:

    • s3FilesConfiguration - Mounts an Amazon Simple Storage Service (Amazon S3) Files access point.

    • efsConfiguration - Mounts an Amazon Elastic File System (Amazon EFS) access point.

    ", + "union":true + }, + "ToolsFileSystemConfigurations":{ + "type":"list", + "member":{"shape":"ToolsFileSystemConfiguration"}, + "documentation":"

    The file system configurations to mount into the session. Each configuration maps an access point to a path inside the session. You can specify up to 4 configurations. The maximum is 2 Amazon Simple Storage Service (Amazon S3) Files access points and 2 Amazon Elastic File System (Amazon EFS) access points.

    ", + "max":10, + "min":0 + }, "TopK":{ "type":"integer", "box":true, @@ -11603,6 +12375,12 @@ "max":32, "min":32 }, + "TraceIdList":{ + "type":"list", + "member":{"shape":"TraceId"}, + "max":100, + "min":1 + }, "TraceIds":{ "type":"list", "member":{"shape":"TraceId"}, @@ -12018,6 +12796,13 @@ "max":100, "min":1 }, + "Version":{ + "type":"string", + "documentation":"

    A protocol version identifier, as a bare numeric string. For example, \"1\" or \"2\".

    ", + "max":10, + "min":1, + "pattern":"[0-9]+" + }, "ViewPort":{ "type":"structure", "required":[ @@ -12059,6 +12844,19 @@ "max":131072, "min":1, "sensitive":true + }, + "WwwAuthenticateHeader":{ + "type":"string", + "documentation":"

    A raw WWW-Authenticate: Payment header value from a 402 response, containing RFC 9110 auth-params such as id, realm, method, intent, and request. Pass this value in the request body, not as an HTTP header.

    ", + "max":16384, + "min":1 + }, + "WwwAuthenticateHeaderList":{ + "type":"list", + "member":{"shape":"WwwAuthenticateHeader"}, + "documentation":"

    The raw WWW-Authenticate header value to fulfill. Provide exactly one entry.

    ", + "max":1, + "min":1 } }, "documentation":"

    Welcome to the Amazon Bedrock AgentCore Data Plane API reference. Data Plane actions process and handle data or workloads within Amazon Web Services services.

    " diff --git a/services/bedrockagentcorecontrol/pom.xml b/services/bedrockagentcorecontrol/pom.xml index 5ff59fc7908d..a10020e3c99c 100644 --- a/services/bedrockagentcorecontrol/pom.xml +++ b/services/bedrockagentcorecontrol/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockagentcorecontrol AWS Java SDK :: Services :: Bedrock Agent Core Control diff --git a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ba10753ce24f --- /dev/null +++ b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-control-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-control-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-control.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agentcore-control.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9f3c71ea9a72..000000000000 --- a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-control-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-control-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-control.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agentcore-control.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/paginators-1.json b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/paginators-1.json index d0ab8a000f47..f0332f564b39 100644 --- a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/paginators-1.json +++ b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/paginators-1.json @@ -12,6 +12,12 @@ "limit_key": "maxResults", "result_key": "agentRuntimes" }, + "ListAgentRuntimeVersionsByCapacityProvider": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "agentRuntimes" + }, "ListAgentRuntimes": { "input_token": "nextToken", "output_token": "nextToken", @@ -36,6 +42,12 @@ "limit_key": "maxResults", "result_key": "browserSummaries" }, + "ListCapacityProviders": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "capacityProviders" + }, "ListCodeInterpreters": { "input_token": "nextToken", "output_token": "nextToken", @@ -54,6 +66,12 @@ "limit_key": "maxResults", "result_key": "bundles" }, + "ListConsentPortals": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "consentPortals" + }, "ListDatasetExamples": { "input_token": "nextToken", "output_token": "nextToken", @@ -78,6 +96,12 @@ "limit_key": "maxResults", "result_key": "evaluators" }, + "ListGatewayRateLimits": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "rateLimits" + }, "ListGatewayRules": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/service-2.json b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/service-2.json index 1cc7cb106a88..4e8588311127 100644 --- a/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockagentcorecontrol/src/main/resources/codegen-resources/service-2.json @@ -33,6 +33,27 @@ ], "documentation":"

    Adds examples to the dataset's DRAFT. All examples are validated against the dataset's schema type before any writes occur. If any example fails validation, the entire batch is rejected (all-or-nothing semantics).

    " }, + "BatchPutGatewayRateLimits":{ + "name":"BatchPutGatewayRateLimits", + "http":{ + "method":"PUT", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits/batch", + "responseCode":200 + }, + "input":{"shape":"BatchPutGatewayRateLimitsRequest"}, + "output":{"shape":"BatchPutGatewayRateLimitsResponse"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Atomically creates or updates multiple rate limits for a gateway. The operation updates existing limits with matching keys and creates new limits for new keys. If the operation fails, the service applies no changes. Retry the request after resolving the issue.

    ", + "idempotent":true + }, "CreateAgentRuntime":{ "name":"CreateAgentRuntime", "http":{ @@ -139,6 +160,28 @@ "documentation":"

    Creates a browser profile in Amazon Bedrock AgentCore. A browser profile stores persistent browser data such as cookies, local storage, session storage, and browsing history that can be saved from browser sessions and reused in subsequent sessions.

    ", "idempotent":true }, + "CreateCapacityProvider":{ + "name":"CreateCapacityProvider", + "http":{ + "method":"PUT", + "requestUri":"/capacity-providers", + "responseCode":202 + }, + "input":{"shape":"CreateCapacityProviderInput"}, + "output":{"shape":"CreateCapacityProviderOutput"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"RetryableConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates a capacity provider. A capacity provider defines the Amazon EC2 infrastructure for AgentCore Runtime, including the operating system, allowed instance types, networking, and storage. It also specifies the IAM permissions that AgentCore uses to manage those instances.

    The capacity provider name must be unique within your account. After you create the capacity provider, it enters a CREATING state and transitions to READY when it is available for use.

    ", + "idempotent":true + }, "CreateCodeInterpreter":{ "name":"CreateCodeInterpreter", "http":{ @@ -178,6 +221,27 @@ ], "documentation":"

    Creates a new configuration bundle resource. A configuration bundle stores versioned component configurations for agent evaluation workflows.

    " }, + "CreateConsentPortal":{ + "name":"CreateConsentPortal", + "http":{ + "method":"POST", + "requestUri":"/identities/CreateConsentPortal", + "responseCode":202 + }, + "input":{"shape":"CreateConsentPortalRequest"}, + "output":{"shape":"CreateConsentPortalResponse"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates a new consent portal.

    " + }, "CreateDataset":{ "name":"CreateDataset", "http":{ @@ -256,6 +320,27 @@ "documentation":"

    Creates a gateway for Amazon Bedrock Agent. A gateway serves as an integration point between your agent and external services.

    If you specify CUSTOM_JWT as the authorizerType, you must provide an authorizerConfiguration.

    ", "idempotent":true }, + "CreateGatewayRateLimit":{ + "name":"CreateGatewayRateLimit", + "http":{ + "method":"POST", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits", + "responseCode":201 + }, + "input":{"shape":"CreateGatewayRateLimitRequest"}, + "output":{"shape":"CreateGatewayRateLimitResponse"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates a rate limit for a gateway. Rate limits define throttling rules for each dimension that control request rates, token consumption rates, and concurrent connections through the gateway.

    ", + "idempotent":true + }, "CreateGatewayRule":{ "name":"CreateGatewayRule", "http":{ @@ -415,6 +500,7 @@ "output":{"shape":"CreatePaymentConnectorResponse"}, "errors":[ {"shape":"ServiceQuotaExceededException"}, + {"shape":"SubscriptionRequiredException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"}, @@ -488,7 +574,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Creates a policy within the AgentCore Policy system. Policies provide real-time, deterministic control over agentic interactions with AgentCore Gateway. Using the Cedar policy language, you can define fine-grained policies that specify which interactions with Gateway tools are permitted based on input parameters and OAuth claims, ensuring agents operate within defined boundaries and business rules. The policy is validated during creation against the Cedar schema generated from the Gateway's tools' input schemas, which defines the available tools, their parameters, and expected data types. This is an asynchronous operation. Use the GetPolicy operation to poll the status field to track completion.

    " + "documentation":"

    Creates a policy within the AgentCore Policy system. Policies provide real-time, deterministic control over agentic interactions with AgentCore Gateway. Using Cedar or Dogwood, you can define fine-grained policies that specify which interactions with Gateway tools are permitted based on input parameters and OAuth claims, ensuring agents operate within defined boundaries and business rules. The policy is validated during creation against the Cedar schema generated from the Gateway's tools' input schemas, which defines the available tools, their parameters, and expected data types. This is an asynchronous operation. Use the GetPolicy operation to poll the status field to track completion.

    If the new policy is a temporal policy, creating it invalidates the policy engine's active temporal sessions. For more information about temporal policy sessions, see session-based temporal policies. The policy engine returns an HTTP 409 ConflictException to in-flight sessions. To resume, you must start a new session with a new session ID.

    " }, "CreatePolicyEngine":{ "name":"CreatePolicyEngine", @@ -586,7 +672,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Deletes an Amazon Bedrock AgentCore Runtime.

    ", + "documentation":"

    Deletes an Amazon Bedrock AgentCore Runtime, or a single version of an AgentCore Runtime when you provide the version qualifier.

    ", "idempotent":true }, "DeleteAgentRuntimeEndpoint":{ @@ -605,7 +691,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Deletes an AAgentCore Runtime endpoint.

    ", + "documentation":"

    Deletes an AgentCore Runtime endpoint.

    ", "idempotent":true }, "DeleteApiKeyCredentialProvider":{ @@ -669,6 +755,27 @@ "documentation":"

    Deletes a browser profile.

    ", "idempotent":true }, + "DeleteCapacityProvider":{ + "name":"DeleteCapacityProvider", + "http":{ + "method":"DELETE", + "requestUri":"/capacity-providers/{capacityProviderId}", + "responseCode":202 + }, + "input":{"shape":"DeleteCapacityProviderInput"}, + "output":{"shape":"DeleteCapacityProviderOutput"}, + "errors":[ + {"shape":"RetryableConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes a capacity provider. Before you delete a capacity provider, disassociate all agent runtimes and runtime versions that reference it. If any references remain, the operation fails.

    ", + "idempotent":true + }, "DeleteCodeInterpreter":{ "name":"DeleteCodeInterpreter", "http":{ @@ -710,6 +817,27 @@ "documentation":"

    Deletes a configuration bundle and all of its versions.

    ", "idempotent":true }, + "DeleteConsentPortal":{ + "name":"DeleteConsentPortal", + "http":{ + "method":"POST", + "requestUri":"/identities/DeleteConsentPortal", + "responseCode":204 + }, + "input":{"shape":"DeleteConsentPortalRequest"}, + "output":{"shape":"DeleteConsentPortalResponse"}, + "errors":[ + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes a consent portal.

    ", + "idempotent":true + }, "DeleteDataset":{ "name":"DeleteDataset", "http":{ @@ -789,6 +917,26 @@ "documentation":"

    Deletes a gateway.

    ", "idempotent":true }, + "DeleteGatewayRateLimit":{ + "name":"DeleteGatewayRateLimit", + "http":{ + "method":"DELETE", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}", + "responseCode":200 + }, + "input":{"shape":"DeleteGatewayRateLimitRequest"}, + "output":{"shape":"DeleteGatewayRateLimitResponse"}, + "errors":[ + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes a gateway rate limit.

    ", + "idempotent":true + }, "DeleteGatewayRule":{ "name":"DeleteGatewayRule", "http":{ @@ -886,7 +1034,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottledException"} ], - "documentation":"

    Deletes an Amazon Bedrock AgentCore Memory resource.

    ", + "documentation":"

    Deletes an Amazon Bedrock AgentCore Memory resource. When you delete a memory resource, it is permanently removed.

    ", "idempotent":true }, "DeleteOauth2CredentialProvider":{ @@ -1204,6 +1352,25 @@ "documentation":"

    Gets information about a browser profile.

    ", "readonly":true }, + "GetCapacityProvider":{ + "name":"GetCapacityProvider", + "http":{ + "method":"GET", + "requestUri":"/capacity-providers/{capacityProviderId}", + "responseCode":200 + }, + "input":{"shape":"GetCapacityProviderInput"}, + "output":{"shape":"GetCapacityProviderOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves information about a capacity provider, including its status, permissions configuration, and compute configuration.

    ", + "readonly":true + }, "GetCodeInterpreter":{ "name":"GetCodeInterpreter", "http":{ @@ -1261,6 +1428,26 @@ "documentation":"

    Gets a specific version of a configuration bundle by its version identifier.

    ", "readonly":true }, + "GetConsentPortal":{ + "name":"GetConsentPortal", + "http":{ + "method":"POST", + "requestUri":"/identities/GetConsentPortal", + "responseCode":200 + }, + "input":{"shape":"GetConsentPortalRequest"}, + "output":{"shape":"GetConsentPortalResponse"}, + "errors":[ + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves information about a consent portal.

    ", + "readonly":true + }, "GetDataset":{ "name":"GetDataset", "http":{ @@ -1319,6 +1506,25 @@ "documentation":"

    Retrieves information about a specific Gateway.

    ", "readonly":true }, + "GetGatewayRateLimit":{ + "name":"GetGatewayRateLimit", + "http":{ + "method":"GET", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}", + "responseCode":200 + }, + "input":{"shape":"GetGatewayRateLimitRequest"}, + "output":{"shape":"GetGatewayRateLimitResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves information about a gateway rate limit.

    ", + "readonly":true + }, "GetGatewayRule":{ "name":"GetGatewayRule", "http":{ @@ -1586,7 +1792,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Retrieves information about a policy generation request within the AgentCore Policy system. Policy generation converts natural language descriptions into Cedar policy statements using AI-powered translation, enabling non-technical users to create policies.

    ", + "documentation":"

    Retrieves information about a policy generation request within the AgentCore Policy system. Policy generation converts natural language descriptions into Dogwood policy statements using AI-powered translation, enabling non-technical users to create policies.

    ", "readonly":true }, "GetPolicyGenerationSummary":{ @@ -1762,6 +1968,24 @@ "documentation":"

    Lists all versions of a specific Amazon Secure Agent.

    ", "readonly":true }, + "ListAgentRuntimeVersionsByCapacityProvider":{ + "name":"ListAgentRuntimeVersionsByCapacityProvider", + "http":{ + "method":"POST", + "requestUri":"/capacity-providers/{capacityProviderId}/runtime-versions", + "responseCode":200 + }, + "input":{"shape":"ListAgentRuntimeVersionsByCapacityProviderInput"}, + "output":{"shape":"ListAgentRuntimeVersionsByCapacityProviderOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the agent runtime versions that are associated with a capacity provider. Use this operation to identify the runtimes you must disassociate before you can delete the capacity provider. Results are paginated; use the nextToken parameter to retrieve additional results.

    ", + "readonly":true + }, "ListAgentRuntimes":{ "name":"ListAgentRuntimes", "http":{ @@ -1836,6 +2060,24 @@ "documentation":"

    Lists all custom browsers in your account.

    ", "readonly":true }, + "ListCapacityProviders":{ + "name":"ListCapacityProviders", + "http":{ + "method":"POST", + "requestUri":"/capacity-providers", + "responseCode":200 + }, + "input":{"shape":"ListCapacityProvidersInput"}, + "output":{"shape":"ListCapacityProvidersOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the capacity providers in your account and returns summary information for each one. To retrieve the full configuration for a specific capacity provider, use GetCapacityProvider. Results are paginated; use the nextToken parameter to retrieve additional results.

    ", + "readonly":true + }, "ListCodeInterpreters":{ "name":"ListCodeInterpreters", "http":{ @@ -1891,6 +2133,25 @@ "documentation":"

    Lists all configuration bundles in the account.

    ", "readonly":true }, + "ListConsentPortals":{ + "name":"ListConsentPortals", + "http":{ + "method":"POST", + "requestUri":"/identities/ListConsentPortals", + "responseCode":200 + }, + "input":{"shape":"ListConsentPortalsRequest"}, + "output":{"shape":"ListConsentPortalsResponse"}, + "errors":[ + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists all of the consent portals in your account.

    ", + "readonly":true + }, "ListDatasetExamples":{ "name":"ListDatasetExamples", "http":{ @@ -1966,6 +2227,25 @@ "documentation":"

    Lists all available evaluators, including both builtin evaluators provided by the service and custom evaluators created by the user.

    ", "readonly":true }, + "ListGatewayRateLimits":{ + "name":"ListGatewayRateLimits", + "http":{ + "method":"GET", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits", + "responseCode":200 + }, + "input":{"shape":"ListGatewayRateLimitsRequest"}, + "output":{"shape":"ListGatewayRateLimitsResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists all rate limits for a gateway. Results are paginated. Use the nextToken parameter to retrieve additional results.

    ", + "readonly":true + }, "ListGatewayRules":{ "name":"ListGatewayRules", "http":{ @@ -2262,7 +2542,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Retrieves a list of generated policy assets from a policy generation request within the AgentCore Policy system. This operation returns the actual Cedar policies and related artifacts produced by the AI-powered policy generation process, allowing users to review and select from multiple generated policy options.

    ", + "documentation":"

    Retrieves a list of generated policy assets from a policy generation request within the AgentCore Policy system. This operation returns the actual Dogwood policies and related artifacts produced by the AI-powered policy generation process, allowing users to review and select from multiple generated policy options.

    ", "readonly":true }, "ListPolicyGenerationSummaries":{ @@ -2456,7 +2736,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Initiates the AI-powered generation of Cedar policies from natural language descriptions within the AgentCore Policy system. This feature enables both technical and non-technical users to create policies by describing their authorization requirements in plain English, which is then automatically translated into formal Cedar policy statements. The generation process analyzes the natural language input along with the Gateway's tool context to produce validated policy options. Generated policy assets are automatically deleted after 7 days, so you should review and create policies from the generated assets within this timeframe. Once created, policies are permanent and not subject to this expiration. Generated policies should be reviewed and tested in log-only mode before deploying to production. Use this when you want to describe policy intent naturally rather than learning Cedar syntax, though generated policies may require refinement for complex scenarios.

    " + "documentation":"

    Initiates the AI-powered generation of Dogwood policies from natural language descriptions within the AgentCore Policy system. This feature enables both technical and non-technical users to create policies by describing their authorization requirements in plain English, which is then automatically translated into formal Dogwood policy statements. The generation process analyzes the natural language input along with the Gateway's tool context to produce validated policy options. Generated policy assets are automatically deleted after 7 days, so you should review and create policies from the generated assets within this timeframe. Once created, policies are permanent and not subject to this expiration. Generated policies should be reviewed and tested in log-only mode before deploying to production. Use this when you want to describe policy intent naturally rather than learning Dogwood syntax, though generated policies may require refinement for complex scenarios.

    " }, "SubmitRegistryRecordForApproval":{ "name":"SubmitRegistryRecordForApproval", @@ -2602,6 +2882,27 @@ "documentation":"

    Updates an existing API key credential provider.

    ", "idempotent":true }, + "UpdateCapacityProvider":{ + "name":"UpdateCapacityProvider", + "http":{ + "method":"PUT", + "requestUri":"/capacity-providers/{capacityProviderId}", + "responseCode":202 + }, + "input":{"shape":"UpdateCapacityProviderInput"}, + "output":{"shape":"UpdateCapacityProviderOutput"}, + "errors":[ + {"shape":"RetryableConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Updates a capacity provider. Only the description can be changed. To change other configuration, such as instance types, networking, or storage, create a new capacity provider.

    ", + "idempotent":true + }, "UpdateConfigurationBundle":{ "name":"UpdateConfigurationBundle", "http":{ @@ -2621,6 +2922,27 @@ ], "documentation":"

    Updates a configuration bundle by creating a new version with the specified changes. Each update creates a new version in the version history.

    " }, + "UpdateConsentPortal":{ + "name":"UpdateConsentPortal", + "http":{ + "method":"POST", + "requestUri":"/identities/UpdateConsentPortal", + "responseCode":202 + }, + "input":{"shape":"UpdateConsentPortalRequest"}, + "output":{"shape":"UpdateConsentPortalResponse"}, + "errors":[ + {"shape":"UnauthorizedException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Updates an existing consent portal.

    ", + "idempotent":true + }, "UpdateDataset":{ "name":"UpdateDataset", "http":{ @@ -2703,6 +3025,25 @@ "documentation":"

    Updates an existing gateway.

    ", "idempotent":true }, + "UpdateGatewayRateLimit":{ + "name":"UpdateGatewayRateLimit", + "http":{ + "method":"PATCH", + "requestUri":"/gateways/{gatewayIdentifier}/rate-limits/{rateLimitId}", + "responseCode":200 + }, + "input":{"shape":"UpdateGatewayRateLimitRequest"}, + "output":{"shape":"UpdateGatewayRateLimitResponse"}, + "errors":[ + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Updates the entries of a gateway rate limit. The dimension keys are immutable after creation.

    " + }, "UpdateGatewayRule":{ "name":"UpdateGatewayRule", "http":{ @@ -2754,6 +3095,7 @@ "input":{"shape":"UpdateHarnessRequest"}, "output":{"shape":"UpdateHarnessResponse"}, "errors":[ + {"shape":"ServiceQuotaExceededException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"}, @@ -2861,6 +3203,7 @@ "output":{"shape":"UpdatePaymentConnectorResponse"}, "errors":[ {"shape":"ServiceQuotaExceededException"}, + {"shape":"SubscriptionRequiredException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"}, @@ -2925,6 +3268,7 @@ "input":{"shape":"UpdatePolicyRequest"}, "output":{"shape":"UpdatePolicyResponse"}, "errors":[ + {"shape":"ServiceQuotaExceededException"}, {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"ConflictException"}, @@ -2932,7 +3276,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Updates an existing policy within the AgentCore Policy system. This operation allows modification of the policy description and definition while maintaining the policy's identity. The updated policy is validated against the Cedar schema before being applied. This is an asynchronous operation. Use the GetPolicy operation to poll the status field to track completion.

    ", + "documentation":"

    Updates an existing policy within the AgentCore Policy system. This operation allows modification of the policy description and definition while maintaining the policy's identity. The updated policy is validated against the Cedar schema before being applied. This is an asynchronous operation. Use the GetPolicy operation to poll the status field to track completion.

    If the updated policy is a temporal policy, the policy engine invalidates all active temporal sessions. If the update adds or removes temporal operators, the policy engine also invalidates active temporal sessions. For more information about temporal policy sessions, see session-based temporal policies. The policy engine returns an HTTP 409 ConflictException to in-flight sessions. To resume, you must start a new session with a new session ID.

    ", "idempotent":true }, "UpdatePolicyEngine":{ @@ -3147,6 +3491,25 @@ } } }, + "AdditionalClaimName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[A-Za-z0-9_.:#-]+" + }, + "AdditionalClaimValue":{ + "type":"string", + "max":2048, + "min":1, + "sensitive":true + }, + "AdditionalClaims":{ + "type":"map", + "key":{"shape":"AdditionalClaimName"}, + "value":{"shape":"AdditionalClaimValue"}, + "max":10, + "min":1 + }, "AdditionalModelRequestFields":{ "type":"structure", "members":{}, @@ -3235,7 +3598,7 @@ }, "AgentRuntimeArn":{ "type":"string", - "pattern":"arn:(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:agent/[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}:([0-9]{0,4}[1-9][0-9]{0,4})" + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:runtime/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" }, "AgentRuntimeArtifact":{ "type":"structure", @@ -3309,7 +3672,7 @@ }, "AgentRuntimeEndpointArn":{ "type":"string", - "pattern":"arn:(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:agentEndpoint/[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}" + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:runtime/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}/runtime-endpoint/[a-zA-Z][a-zA-Z0-9_]{0,47}" }, "AgentRuntimeEndpointId":{ "type":"string", @@ -3323,7 +3686,8 @@ "UPDATING", "UPDATE_FAILED", "READY", - "DELETING" + "DELETING", + "DELETE_FAILED" ] }, "AgentRuntimeEndpoints":{ @@ -3346,8 +3710,9 @@ "UPDATING", "UPDATE_FAILED", "READY", - "DELETING" - ] + "DELETING", + "DELETE_FAILED" + ] }, "AgentRuntimeVersion":{ "type":"string", @@ -3355,6 +3720,33 @@ "min":1, "pattern":"([1-9][0-9]{0,4})" }, + "AgentRuntimeVersionSummary":{ + "type":"structure", + "required":[ + "agentRuntimeArn", + "agentRuntimeVersion", + "status" + ], + "members":{ + "agentRuntimeArn":{ + "shape":"AgentRuntimeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the agent runtime.

    " + }, + "agentRuntimeVersion":{ + "shape":"AgentRuntimeVersion", + "documentation":"

    The version of the agent runtime.

    " + }, + "status":{ + "shape":"AgentRuntimeStatus", + "documentation":"

    The current status of the agent runtime version.

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

    Summary information about an agent runtime version associated with a capacity provider. This is returned by ListAgentRuntimeVersionsByCapacityProvider.

    " + }, + "AgentRuntimeVersionSummaryList":{ + "type":"list", + "member":{"shape":"AgentRuntimeVersionSummary"} + }, "AgentRuntimes":{ "type":"list", "member":{"shape":"AgentRuntime"} @@ -3379,6 +3771,7 @@ "member":{"shape":"AllowedAudience"}, "min":1 }, + "AllowedAudienceType":{"type":"string"}, "AllowedClient":{"type":"string"}, "AllowedClientsList":{ "type":"list", @@ -3742,6 +4135,72 @@ "type":"string", "pattern":"[0-9]{12}" }, + "BatchPutGatewayRateLimitsRequest":{ + "type":"structure", + "required":[ + "gatewayIdentifier", + "rateLimits" + ], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "rateLimits":{ + "shape":"BatchPutLimitEntries", + "documentation":"

    The complete set of rate limits for this gateway. This operation replaces all existing rate limits in a single request. If the operation fails, no rate limits are changed.

    " + } + } + }, + "BatchPutGatewayRateLimitsResponse":{ + "type":"structure", + "required":["rateLimits"], + "members":{ + "rateLimits":{ + "shape":"GatewayRateLimits", + "documentation":"

    The resulting set of rate limits after the batch operation.

    " + } + } + }, + "BatchPutLimitEntries":{ + "type":"list", + "member":{"shape":"BatchPutLimitEntry"}, + "max":50, + "min":1 + }, + "BatchPutLimitEntry":{ + "type":"structure", + "required":[ + "dimensionKeys", + "entries" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit. If provided, the service uses it for upsert matching against existing rate limits.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    An optional human-readable description for this rate limit. If not provided, the rate limit is created without a description.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The list of rule entries that map dimension values to rate configurations.

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

    A rate limit definition within a batch put request. If you provide a rateLimitId, the service uses it for upsert matching against existing rate limits.

    " + }, "BedrockAgentcoreResourceArn":{ "type":"string", "max":1011, @@ -3836,7 +4295,7 @@ }, "BrowserProfileArn":{ "type":"string", - "pattern":"arn:(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:browser-profile/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:browser-profile/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" }, "BrowserProfileId":{ "type":"string", @@ -3995,6 +4454,166 @@ }, "documentation":"

    Contains summary information about a browser. A browser enables Amazon Bedrock AgentCore Agent to interact with web content.

    " }, + "CapacityProviderArn":{ + "type":"string", + "pattern":"arn:aws(-[^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:capacity-provider/[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" + }, + "CapacityProviderConfiguration":{ + "type":"structure", + "required":["capacityProviderArn"], + "members":{ + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider to use for the AgentCore Runtime.

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

    Configuration for customer-managed compute capacity for the AgentCore Runtime. A capacity provider runs the AgentCore Runtime on the Instances compute type, using Amazon Web Services managed compute in your account.

    " + }, + "CapacityProviderId":{ + "type":"string", + "max":59, + "min":12, + "pattern":"[a-zA-Z][a-zA-Z0-9_]{0,47}-[a-zA-Z0-9]{10}" + }, + "CapacityProviderList":{ + "type":"list", + "member":{"shape":"CapacityProviderSummary"} + }, + "CapacityProviderName":{ + "type":"string", + "max":48, + "min":1, + "pattern":"[a-zA-Z][a-zA-Z0-9_]{0,47}" + }, + "CapacityProviderStatus":{ + "type":"string", + "documentation":"

    The status of a capacity provider. Possible values:

    • CREATING – The service is creating the capacity provider and validating its configuration.

    • CREATE_FAILED – The service could not create the capacity provider. For details, see statusCode and statusReason.

    • UPDATING – The service is updating the capacity provider.

    • UPDATE_FAILED – The service could not update the capacity provider. For details, see statusCode and statusReason.

    • READY – The capacity provider is available for use.

    • DELETING – The service is deleting the capacity provider.

    • DELETE_FAILED – The service could not delete the capacity provider. You can retry the deletion.

    ", + "enum":[ + "CREATING", + "CREATE_FAILED", + "UPDATING", + "UPDATE_FAILED", + "READY", + "DELETING", + "DELETE_FAILED" + ] + }, + "CapacityProviderStatusCode":{ + "type":"string", + "documentation":"

    A reason code for a capacity provider that is not in the READY state. Possible values:

    • VALIDATION_ERROR – A configuration error prevented the operation. For example, missing permissions, invalid parameters, or a naming conflict.

    • QUOTA_EXCEEDED – An Amazon EC2 resource quota was exceeded. Request a limit increase or remove unused resources.

    • THROTTLED – The request was throttled. Retry after a short delay.

    • INTERNAL_SERVER_EXCEPTION – An internal error occurred.

    ", + "enum":[ + "VALIDATION_ERROR", + "QUOTA_EXCEEDED", + "THROTTLED", + "INTERNAL_SERVER_EXCEPTION" + ] + }, + "CapacityProviderSummary":{ + "type":"structure", + "required":[ + "capacityProviderId", + "capacityProviderArn", + "name", + "status", + "lastUpdatedAt" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider.

    " + }, + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider.

    " + }, + "name":{ + "shape":"CapacityProviderName", + "documentation":"

    The name of the capacity provider.

    " + }, + "status":{ + "shape":"CapacityProviderStatus", + "documentation":"

    The current status of the capacity provider. For possible values, see CapacityProviderStatus.

    " + }, + "lastUpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the capacity provider was last updated.

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

    A summary of a capacity provider, as returned by ListCapacityProviders. Each summary includes the capacity provider identifier, Amazon Resource Name (ARN), name, status, and last-updated timestamp.

    " + }, + "CapacityProviderVolumeConfiguration":{ + "type":"structure", + "required":[ + "volumeName", + "mountPath" + ], + "members":{ + "volumeName":{ + "shape":"CapacityProviderVolumeName", + "documentation":"

    The logical name of the capacity provider volume to mount. This name must match a volume that is defined in the capacity provider's list of volumes.

    " + }, + "mountPath":{ + "shape":"MountPath", + "documentation":"

    The mount path for the capacity provider volume inside the AgentCore Runtime. The path must be under /mnt with exactly one subdirectory level (for example, /mnt/data).

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

    Configuration for a capacity provider volume mounted into the AgentCore Runtime. This references a persistent volume by its logical name, as defined in the capacity provider's list of volumes.

    " + }, + "CapacityProviderVolumeName":{ + "type":"string", + "documentation":"

    The logical name of a capacity provider volume. This name must match a volume that is defined in the capacity provider's list of volumes.

    ", + "max":48, + "min":1, + "pattern":"[a-zA-Z][a-zA-Z0-9_-]{0,47}" + }, + "CapacityReservationId":{ + "type":"string", + "max":255, + "min":1, + "pattern":"cr-[0-9a-z]+" + }, + "CapacityReservationPreference":{ + "type":"string", + "enum":[ + "capacity-reservations-only", + "open", + "none" + ] + }, + "CapacityReservationResourceGroupArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:resource-groups:[a-z0-9-]+:[0-9]{12}:group/[a-zA-Z0-9_-]+" + }, + "CapacityReservationSpecification":{ + "type":"structure", + "members":{ + "capacityReservationPreference":{ + "shape":"CapacityReservationPreference", + "documentation":"

    The Capacity Reservation preference for the instances.

    " + }, + "capacityReservationTarget":{ + "shape":"CapacityReservationTarget", + "documentation":"

    The target Capacity Reservation or Capacity Reservation group for the instances.

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

    The Capacity Reservation targeting option for the instances.

    " + }, + "CapacityReservationTarget":{ + "type":"structure", + "members":{ + "capacityReservationId":{ + "shape":"CapacityReservationId", + "documentation":"

    The ID of the Capacity Reservation in which to run the instances.

    " + }, + "capacityReservationResourceGroupArn":{ + "shape":"CapacityReservationResourceGroupArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Capacity Reservation resource group in which to run the instances.

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

    Information about the target Capacity Reservation or Capacity Reservation group for the instances.

    " + }, "CategoricalScaleDefinition":{ "type":"structure", "required":[ @@ -4089,7 +4708,8 @@ "enum":[ "CLIENT_SECRET_BASIC", "CLIENT_SECRET_POST", - "AWS_IAM_ID_TOKEN_JWT" + "AWS_IAM_ID_TOKEN_JWT", + "PRIVATE_KEY_JWT" ] }, "ClientIdType":{ @@ -4105,15 +4725,16 @@ }, "CloudWatchLogsInputConfig":{ "type":"structure", - "required":[ - "logGroupNames", - "serviceNames" - ], + "required":["serviceNames"], "members":{ "logGroupNames":{ "shape":"CloudWatchLogsInputConfigLogGroupNamesList", "documentation":"

    The list of CloudWatch log group names to monitor for agent traces.

    " }, + "logGroupNamePrefixes":{ + "shape":"CloudWatchLogsInputConfigLogGroupNamePrefixesList", + "documentation":"

    The list of CloudWatch log group name prefixes to monitor for agent traces. Specify this instead of logGroupNames to match log groups by prefix. Specify either logGroupNames or logGroupNamePrefixes, not both. One of the two is required.

    " + }, "serviceNames":{ "shape":"CloudWatchLogsInputConfigServiceNamesList", "documentation":"

    The list of service names to filter traces within the specified log groups. Used to identify relevant agent sessions.

    " @@ -4121,12 +4742,19 @@ }, "documentation":"

    The configuration for reading agent traces from CloudWatch logs as input for online evaluation.

    " }, - "CloudWatchLogsInputConfigLogGroupNamesList":{ + "CloudWatchLogsInputConfigLogGroupNamePrefixesList":{ "type":"list", - "member":{"shape":"LogGroupName"}, + "member":{"shape":"LogGroupNamePrefix"}, + "documentation":"

    List of CloudWatch Logs log group name prefixes to source trace data from.

    ", "max":5, "min":1 }, + "CloudWatchLogsInputConfigLogGroupNamesList":{ + "type":"list", + "member":{"shape":"LogGroupName"}, + "max":10, + "min":0 + }, "CloudWatchLogsInputConfigServiceNamesList":{ "type":"list", "member":{"shape":"ServiceName"}, @@ -4135,11 +4763,18 @@ }, "CloudWatchOutputConfig":{ "type":"structure", - "required":["logGroupName"], "members":{ "logGroupName":{ - "shape":"LogGroupName", - "documentation":"

    The name of the CloudWatch log group where evaluation results will be written. The log group will be created if it doesn't exist.

    " + "shape":"OptionalLogGroupName", + "documentation":"

    The name of the CloudWatch log group where evaluation results will be written. An existing log group is used as-is; otherwise the service creates it, which requires the evaluation execution role to grant logs:CreateLogGroup on the log group. Don't specify this value when resultDestination is SOURCE_LOG_GROUP. The name can't be under the service-reserved /aws/bedrock-agentcore/evaluations/ namespace, apart from this configuration's own service-managed default group.

    " + }, + "metricsNamespace":{ + "shape":"MetricsNamespace", + "documentation":"

    The CloudWatch metrics namespace where evaluation result metrics are published. If you omit this value, the service publishes metrics to Bedrock-AgentCore/Evaluations. This value can't begin with AWS/.

    " + }, + "resultDestination":{ + "shape":"ResultDestination", + "documentation":"

    The destination where evaluation results are written. Valid values:

    • DEDICATED_LOG_GROUP (default) – Writes results to a dedicated result log group.

    • SOURCE_LOG_GROUP – Writes results back to the log group that the agent traces were read from. If you use this value, don't specify logGroupName.

    " } }, "documentation":"

    The configuration for writing evaluation results to CloudWatch logs with embedded metric format (EMF) for monitoring.

    " @@ -4403,6 +5038,28 @@ "min":1, "pattern":"[a-zA-Z][a-zA-Z0-9_:/.\\-]{0,2047}" }, + "CompositeIdentifierEntry":{ + "type":"string", + "max":256, + "min":1 + }, + "CompositeIdentifierList":{ + "type":"list", + "member":{"shape":"CompositeIdentifierEntry"}, + "max":5, + "min":1 + }, + "ComputeConfiguration":{ + "type":"structure", + "members":{ + "ec2Configuration":{ + "shape":"Ec2Configuration", + "documentation":"

    The Amazon EC2 compute configuration for the capacity provider.

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

    The compute configuration for a capacity provider. This structure defines the type and settings of the compute resources used to launch instances.

    ", + "union":true + }, "ConcurrentModificationException":{ "type":"structure", "required":["message"], @@ -4639,6 +5296,13 @@ "max":256, "min":1 }, + "ConnectorParameterName":{ + "type":"string", + "documentation":"

    The name of a connector parameter (for example, memoryId). The name must start with a letter and contain only letters, digits, underscores, and hyphens.

    ", + "max":128, + "min":1, + "pattern":"[a-zA-Z][a-zA-Z0-9_-]*" + }, "ConnectorParameterOverride":{ "type":"structure", "required":["path"], @@ -4662,6 +5326,12 @@ "type":"list", "member":{"shape":"ConnectorParameterOverride"} }, + "ConnectorParameterValue":{ + "type":"string", + "documentation":"

    The value of a connector parameter. Length: 1–1,024 characters.

    ", + "max":1024, + "min":1 + }, "ConnectorSource":{ "type":"structure", "required":["connectorId"], @@ -4669,6 +5339,10 @@ "connectorId":{ "shape":"ConnectorId", "documentation":"

    The identifier for the connector integration (for example, bedrock-knowledge-bases).

    " + }, + "version":{ + "shape":"ConnectorVersion", + "documentation":"

    The version of the connector to use (for example, 1.1.0). If you don't specify a version, the service uses the latest available version.

    " } }, "documentation":"

    The source identifying the connector integration.

    " @@ -4692,6 +5366,159 @@ }, "documentation":"

    Configuration for a connector integration target. Connectors provide pre-built integrations with Amazon Web Services services and third-party tools.

    " }, + "ConnectorVersion":{ + "type":"string", + "max":32, + "min":5, + "pattern":"(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)" + }, + "ConsentPortalArnType":{ + "type":"string", + "pattern":"arn:aws[^:]*:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:consent-portal/[a-zA-Z0-9\\-_]{1,50}-[A-Za-z0-9]{10}" + }, + "ConsentPortalDescriptionType":{ + "type":"string", + "max":512, + "min":0 + }, + "ConsentPortalIdType":{ + "type":"string", + "pattern":"[a-zA-Z0-9\\-_]{1,50}-[A-Za-z0-9]{10}" + }, + "ConsentPortalIdentifier":{ + "type":"string", + "pattern":"[a-zA-Z0-9\\-_]{1,50}-[A-Za-z0-9]{10}" + }, + "ConsentPortalIdpConfig":{ + "type":"structure", + "required":[ + "credentialProviderArn", + "scopes" + ], + "members":{ + "credentialProviderArn":{ + "shape":"OAuth2CredentialProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the OAuth2 credential provider used to authenticate end users to the consent portal.

    " + }, + "scopes":{ + "shape":"AllowedScopesType", + "documentation":"

    The OAuth2 scopes that the consent portal requests when authenticating end users.

    " + }, + "audience":{ + "shape":"AllowedAudienceType", + "documentation":"

    The audience value that the consent portal includes when requesting tokens from the identity provider.

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

    The identity provider configuration used to authenticate end users to the consent portal.

    " + }, + "ConsentPortalNameType":{ + "type":"string", + "max":50, + "min":1, + "pattern":"[a-zA-Z0-9_-]{1,50}" + }, + "ConsentPortalSource":{ + "type":"structure", + "required":[ + "identifier", + "type" + ], + "members":{ + "identifier":{ + "shape":"ConsentPortalSourceIdentifierType", + "documentation":"

    The identifier of the source resource. For an agentcore-gateway source, this is the gateway ID or its Amazon Resource Name (ARN).

    " + }, + "type":{ + "shape":"ConsentPortalSourceType", + "documentation":"

    The type of the source resource.

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

    A resource served by the consent portal.

    " + }, + "ConsentPortalSourceIdentifierType":{ + "type":"string", + "pattern":"([0-9a-z][-]?){1,100}-[0-9a-z]{10}$|^arn:aws(-[a-z-]+)?:bedrock-agentcore:[a-z0-9-]{1,20}:[0-9]{12}:gateway/([0-9a-z][-]?){1,48}-[a-z0-9]{10}" + }, + "ConsentPortalSourceType":{ + "type":"string", + "documentation":"

    The type of a consent portal source. Currently, we only support type agentcore-gateway.

    ", + "enum":["agentcore-gateway"] + }, + "ConsentPortalSources":{ + "type":"list", + "member":{"shape":"ConsentPortalSource"}, + "documentation":"

    The list of resources served by the consent portal.

    ", + "max":1, + "min":1 + }, + "ConsentPortalStatus":{ + "type":"string", + "documentation":"

    The lifecycle status of a consent portal.

    ", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "UPDATE_FAILED", + "DELETING", + "FAILED" + ] + }, + "ConsentPortalSummaries":{ + "type":"list", + "member":{"shape":"ConsentPortalSummary"}, + "documentation":"

    A list of consent portal summaries.

    " + }, + "ConsentPortalSummary":{ + "type":"structure", + "required":[ + "sources", + "consentPortalArn", + "consentPortalId", + "createdAt", + "name", + "status", + "updatedAt" + ], + "members":{ + "sources":{ + "shape":"ConsentPortalSources", + "documentation":"

    The resources served by the consent portal.

    " + }, + "consentPortalArn":{ + "shape":"ConsentPortalArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the consent portal.

    " + }, + "consentPortalId":{ + "shape":"ConsentPortalIdType", + "documentation":"

    The unique identifier of the consent portal.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was created.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + }, + "name":{ + "shape":"ConsentPortalNameType", + "documentation":"

    The name of the consent portal.

    " + }, + "portalUrl":{ + "shape":"PortalUrlType", + "documentation":"

    The URL used to access the consent portal.

    " + }, + "status":{ + "shape":"ConsentPortalStatus", + "documentation":"

    The current status of the consent portal.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was last updated.

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

    Summary information about a consent portal.

    " + }, "ConsolidationConfiguration":{ "type":"structure", "members":{ @@ -4719,7 +5546,7 @@ "members":{ "rawText":{ "shape":"NaturalLanguage", - "documentation":"

    The raw text content containing natural language descriptions of desired policy behavior. This text is processed by AI to generate corresponding Cedar policy statements that match the described intent.

    " + "documentation":"

    The raw text content containing natural language descriptions of desired policy behavior. This text is processed by AI to generate corresponding Dogwood policy statements that match the described intent.

    " } }, "documentation":"

    Represents content input for policy generation operations. This structure encapsulates the natural language descriptions or other content formats that are used as input for AI-powered policy generation.

    ", @@ -4832,8 +5659,7 @@ "required":[ "agentRuntimeName", "agentRuntimeArtifact", - "roleArn", - "networkConfiguration" + "roleArn" ], "members":{ "agentRuntimeName":{ @@ -4882,9 +5708,17 @@ "shape":"FilesystemConfigurations", "documentation":"

    The filesystem configurations to mount into the AgentCore Runtime. Use filesystem configurations to provide persistent storage to your AgentCore Runtime sessions.

    " }, + "capacityProviderConfiguration":{ + "shape":"CapacityProviderConfiguration", + "documentation":"

    The capacity provider configuration for the AgentCore Runtime. Use a capacity provider to run the AgentCore Runtime on the Instances compute type, which provisions Amazon Web Services managed compute in your account.

    " + }, "tags":{ "shape":"TagsMap", "documentation":"

    A map of tag keys and values to assign to the agent runtime. Tags enable you to categorize your resources in different ways, for example, by purpose, owner, or environment.

    " + }, + "platformVersion":{ + "shape":"PlatformVersion", + "documentation":"

    The version of the runtime platform to use for the AgentCore Runtime.

    " } } }, @@ -5069,6 +5903,10 @@ "shape":"Certificates", "documentation":"

    A list of certificates to install in the browser.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations to mount into the browser. Use these configurations to mount your own Amazon Simple Storage Service (Amazon S3) Files or Amazon Elastic File System (Amazon EFS) access points. Your sessions can then access your data. If you don't specify this field, no file systems are mounted.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, Amazon Bedrock AgentCore ignores the request but does not return an error.

    ", @@ -5107,6 +5945,68 @@ } } }, + "CreateCapacityProviderInput":{ + "type":"structure", + "required":[ + "name", + "permissionsConfiguration", + "computeConfiguration" + ], + "members":{ + "name":{ + "shape":"CapacityProviderName", + "documentation":"

    The name of the capacity provider. The name must be unique within your account.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    An optional description of the capacity provider. If you don't specify a description, the service creates the capacity provider without one.

    " + }, + "permissionsConfiguration":{ + "shape":"PermissionsConfiguration", + "documentation":"

    The permissions configuration for the capacity provider. This specifies the IAM role that AgentCore uses to manage the Amazon EC2 instances on your behalf.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    A map of tag keys and values to associate with the capacity provider. If you don't specify tags, the capacity provider is created with no tags.

    " + }, + "computeConfiguration":{ + "shape":"ComputeConfiguration", + "documentation":"

    The compute configuration for the capacity provider. This defines the Amazon EC2 compute resources used to launch instances: the operating system, allowed instance types, networking, and storage.

    " + } + } + }, + "CreateCapacityProviderOutput":{ + "type":"structure", + "required":[ + "capacityProviderId", + "capacityProviderArn", + "name", + "status" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the created capacity provider.

    " + }, + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider.

    " + }, + "name":{ + "shape":"CapacityProviderName", + "documentation":"

    The name of the capacity provider.

    " + }, + "status":{ + "shape":"CapacityProviderStatus", + "documentation":"

    The current status of the capacity provider. For possible values, see CapacityProviderStatus.

    " + } + } + }, "CreateCodeInterpreterRequest":{ "type":"structure", "required":[ @@ -5134,6 +6034,10 @@ "shape":"Certificates", "documentation":"

    A list of certificates to install in the code interpreter.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations to mount into the code interpreter. Use these configurations to mount your own Amazon Simple Storage Service (Amazon S3) Files or Amazon Elastic File System (Amazon EFS) access points. Your sessions can then access your data. If you don't specify this field, no file systems are mounted.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, Amazon Bedrock AgentCore ignores the request but does not return an error.

    ", @@ -5250,6 +6154,105 @@ } } }, + "CreateConsentPortalRequest":{ + "type":"structure", + "required":[ + "executionRoleArn", + "idpConfig", + "name", + "sources" + ], + "members":{ + "executionRoleArn":{ + "shape":"ExecutionRoleArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that the consent portal assumes to access the resources defined in its sources.

    " + }, + "idpConfig":{ + "shape":"ConsentPortalIdpConfig", + "documentation":"

    The identity provider configuration that the consent portal uses to authenticate end users.

    " + }, + "name":{ + "shape":"ConsentPortalNameType", + "documentation":"

    The name of the consent portal. The name must be unique within your account.

    " + }, + "sources":{ + "shape":"ConsentPortalSources", + "documentation":"

    The resources served by the consent portal. Currently, we only support type agentcore-gateway.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    A map of tag keys and values to assign to the consent portal. Tags enable you to categorize your resources in different ways, for example, by purpose, owner, or environment.

    " + } + } + }, + "CreateConsentPortalResponse":{ + "type":"structure", + "required":[ + "sources", + "consentPortalArn", + "consentPortalId", + "createdAt", + "executionRoleArn", + "idpConfig", + "name", + "status", + "updatedAt" + ], + "members":{ + "sources":{ + "shape":"ConsentPortalSources", + "documentation":"

    The resources served by the consent portal.

    " + }, + "consentPortalArn":{ + "shape":"ConsentPortalArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the consent portal.

    " + }, + "consentPortalId":{ + "shape":"ConsentPortalIdType", + "documentation":"

    The unique identifier of the consent portal.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was created.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + }, + "executionRoleArn":{ + "shape":"ExecutionRoleArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that the consent portal assumes to access the resources defined in its sources.

    " + }, + "idpConfig":{ + "shape":"ConsentPortalIdpConfig", + "documentation":"

    The identity provider configuration that the consent portal uses to authenticate end users.

    " + }, + "name":{ + "shape":"ConsentPortalNameType", + "documentation":"

    The name of the consent portal.

    " + }, + "portalUrl":{ + "shape":"PortalUrlType", + "documentation":"

    The URL used to access the consent portal.

    " + }, + "status":{ + "shape":"ConsentPortalStatus", + "documentation":"

    The current status of the consent portal.

    " + }, + "statusReason":{ + "shape":"StatusReasonType", + "documentation":"

    A message that provides additional information about the current status of the consent portal.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was last updated.

    " + } + } + }, "CreateDatasetRequest":{ "type":"structure", "required":[ @@ -5436,6 +6439,90 @@ } } }, + "CreateGatewayRateLimitRequest":{ + "type":"structure", + "required":[ + "gatewayIdentifier", + "dimensionKeys", + "entries" + ], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway to create the rate limit for.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    An optional customer-defined identifier for the rate limit. If not provided, the system generates one.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    An optional human-readable description for this rate limit. If not provided, the rate limit is created without a description.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit. Must be unique per gateway—no two rate limits can share the same dimension keys.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The rule entries that map dimension values to rate configurations.

    " + } + } + }, + "CreateGatewayRateLimitResponse":{ + "type":"structure", + "required":[ + "rateLimitId", + "gatewayIdentifier", + "dimensionKeys", + "entries", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the created rate limit.

    " + }, + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    The human-readable description of the rate limit.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The list of rule entries that map dimension values to rate configurations.

    " + }, + "status":{ + "shape":"GatewayRateLimitStatus", + "documentation":"

    The current status of the rate limit.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was last updated.

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

    Shared fields for GatewayRateLimit responses.

    " + }, "CreateGatewayRequest":{ "type":"structure", "required":[ @@ -5917,6 +7004,10 @@ "shape":"HarnessTruncationConfiguration", "documentation":"

    The truncation configuration for managing conversation context when it exceeds model limits.

    " }, + "hooks":{ + "shape":"HarnessHooks", + "documentation":"

    The lifecycle hooks to run at defined points in the agent loop.

    " + }, "maxIterations":{ "shape":"Integer", "documentation":"

    The maximum number of iterations the agent loop can execute per invocation.

    " @@ -5985,6 +7076,10 @@ "shape":"IndexedKeysList", "documentation":"

    Metadata keys to index for filtering. Once declared, indexed keys cannot be removed.

    " }, + "namespaceKeys":{ + "shape":"NamespaceKeysList", + "documentation":"

    The namespace variable key definitions with optional validation rules. Use these namespaceKeys in namespaceTemplates to control namespace hierarchy.

    " + }, "streamDeliveryResources":{ "shape":"StreamDeliveryResources", "documentation":"

    Configuration for streaming memory record data to external resources.

    " @@ -6123,6 +7218,7 @@ "shape":"ClusteringConfig", "documentation":"

    Configuration for periodic batch evaluation clustering of insight results.

    " }, + "outputConfig":{"shape":"OutputConfig"}, "evaluationExecutionRoleArn":{ "shape":"RoleArn", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that grants permissions to read from CloudWatch logs, write evaluation results, and invoke Amazon Bedrock models for evaluation. If the configuration references evaluators encrypted with a customer managed KMS key, this role must also have kms:Decrypt permission on the KMS key. The service validates this permission at configuration creation time. For more information, see Encryption at rest for AgentCore Evaluations.

    " @@ -6205,6 +7301,10 @@ "shape":"CredentialsProviderConfigurations", "documentation":"

    The credential provider configurations for the payment connector. These configurations specify how the connector authenticates with the payment provider.

    " }, + "provisionMode":{ + "shape":"PaymentConnectorProvisionMode", + "documentation":"

    The provision mode for creating the payment connector. If you don't specify a value, the default is MANUAL.

    • MANUAL - You provide the credential provider configurations directly.

    • QUICK_CREATE - The service orchestrates OAuth consent and provisions the credential provider for you.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", @@ -6251,6 +7351,10 @@ "status":{ "shape":"PaymentConnectorStatus", "documentation":"

    The current status of the payment connector. Possible values include CREATING, READY, UPDATING, DELETING, CREATE_FAILED, UPDATE_FAILED, and DELETE_FAILED.

    " + }, + "authorizationUrl":{ + "shape":"PaymentConnectorAuthorizationUrl", + "documentation":"

    The URL that the user must open to complete OAuth consent. This field is only present when the payment connector status is PENDING_AUTHENTICATION.

    " } } }, @@ -6343,6 +7447,10 @@ "tags":{ "shape":"TagsMap", "documentation":"

    A map of tag keys and values to assign to the payment manager.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the customer managed KMS key to use for encrypting sensitive payment manager data at rest. If you don't specify a key, the data is encrypted with an Amazon Web Services owned key.

    " } } }, @@ -6391,6 +7499,10 @@ "tags":{ "shape":"TagsMap", "documentation":"

    The tags associated with the created payment manager.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key used to encrypt sensitive payment manager data at rest, if configured.

    " } } }, @@ -6485,7 +7597,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The Cedar policy statement that defines the access control rules. This contains the actual policy logic written in Cedar policy language, specifying effect (permit or forbid), principals, actions, resources, and conditions for agent behavior control.

    " + "documentation":"

    The Cedar or Dogwood policy statement that defines the access control rules. This contains the actual policy logic written in Cedar or Dogwood, specifying effect (permit or forbid), principals, actions, resources, and conditions for agent behavior control.

    " }, "description":{ "shape":"Description", @@ -6560,7 +7672,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The Cedar policy statement that was created. This is the validated policy definition that will be used for agent behavior control and access decisions.

    " + "documentation":"

    The Cedar or Dogwood policy statement that was created. This is the validated policy definition that will be used for agent behavior control and access decisions.

    " }, "description":{ "shape":"Description", @@ -6833,7 +7945,7 @@ "type":"list", "member":{"shape":"CredentialsProviderConfiguration"}, "max":1, - "min":1 + "min":0 }, "CustomClaimValidationType":{ "type":"structure", @@ -7098,6 +8210,10 @@ "shape":"ClientAuthenticationMethodType", "documentation":"

    The client authentication method to use when authenticating with the token endpoint.

    " }, + "privateKeyJwtConfig":{ + "shape":"PrivateKeyJwtConfig", + "documentation":"

    The private_key_jwt client authentication configuration for this credential provider. When specified, the credential provider uses JWT client assertions to authenticate with the token endpoint.

    " + }, "privateEndpoint":{ "shape":"PrivateEndpoint", "documentation":"

    The default private endpoint for the custom OAuth2 provider, enabling secure connectivity through a VPC Lattice resource configuration.

    " @@ -7121,21 +8237,25 @@ "shape":"ClientIdType", "documentation":"

    The client ID for the custom OAuth2 provider.

    " }, + "onBehalfOfTokenExchangeConfig":{ + "shape":"OnBehalfOfTokenExchangeConfigType", + "documentation":"

    The configuration for on-behalf-of token exchange.

    " + }, + "clientAuthenticationMethod":{ + "shape":"ClientAuthenticationMethodType", + "documentation":"

    The client authentication method used when authenticating with the token endpoint.

    " + }, "privateEndpoint":{ "shape":"PrivateEndpoint", "documentation":"

    The default private endpoint for the custom OAuth2 provider, enabling secure connectivity through a VPC Lattice resource configuration.

    " }, - "privateEndpointOverrides":{ - "shape":"PrivateEndpointOverrides", - "documentation":"

    The private endpoint overrides for the custom OAuth2 provider configuration.

    " - }, - "onBehalfOfTokenExchangeConfig":{ - "shape":"OnBehalfOfTokenExchangeConfigType", - "documentation":"

    The configuration for on-behalf-of token exchange.

    " + "privateEndpointOverrides":{ + "shape":"PrivateEndpointOverrides", + "documentation":"

    The private endpoint overrides for the custom OAuth2 provider configuration.

    " }, - "clientAuthenticationMethod":{ - "shape":"ClientAuthenticationMethodType", - "documentation":"

    The client authentication method used when authenticating with the token endpoint.

    " + "privateKeyJwtConfig":{ + "shape":"PrivateKeyJwtConfig", + "documentation":"

    The configuration for private_key_jwt client authentication used by this OAuth2 credential provider.

    " } }, "documentation":"

    Output configuration for a custom OAuth2 provider.

    " @@ -7225,7 +8345,8 @@ "documentation":"

    Versioned schema type for dataset examples. Each value identifies both the source format and the version of that format's schema.

    ", "enum":[ "AGENTCORE_EVALUATION_PREDEFINED_V1", - "AGENTCORE_EVALUATION_SIMULATED_V1" + "AGENTCORE_EVALUATION_SIMULATED_V1", + "THIRD_PARTY_EVALUATION_V1" ] }, "DatasetStatus":{ @@ -7457,6 +8578,12 @@ "location":"uri", "locationName":"agentRuntimeId" }, + "agentRuntimeVersion":{ + "shape":"AgentRuntimeVersion", + "documentation":"

    The version of the AgentCore Runtime to delete. When you provide this value, only that version is deleted. When you omit it, the entire AgentCore Runtime and all of its versions are deleted.

    ", + "location":"querystring", + "locationName":"version" + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request but does not return an error.

    ", @@ -7477,6 +8604,10 @@ "agentRuntimeId":{ "shape":"AgentRuntimeId", "documentation":"

    The unique identifier of the AgentCore Runtime.

    " + }, + "agentRuntimeVersion":{ + "shape":"AgentRuntimeVersion", + "documentation":"

    The version of the AgentCore Runtime that was deleted. This value is present only when you delete a single version.

    " } } }, @@ -7585,6 +8716,42 @@ } } }, + "DeleteCapacityProviderInput":{ + "type":"structure", + "required":["capacityProviderId"], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider to delete.

    ", + "location":"uri", + "locationName":"capacityProviderId" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true, + "location":"querystring", + "locationName":"clientToken" + } + } + }, + "DeleteCapacityProviderOutput":{ + "type":"structure", + "required":[ + "capacityProviderId", + "status" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the deleted capacity provider.

    " + }, + "status":{ + "shape":"CapacityProviderStatus", + "documentation":"

    The current status of the capacity provider. For possible values, see CapacityProviderStatus.

    " + } + } + }, "DeleteCodeInterpreterRequest":{ "type":"structure", "required":["codeInterpreterId"], @@ -7655,6 +8822,20 @@ } } }, + "DeleteConsentPortalRequest":{ + "type":"structure", + "required":["consentPortalIdentifier"], + "members":{ + "consentPortalIdentifier":{ + "shape":"ConsentPortalIdentifier", + "documentation":"

    The identifier of the consent portal. You can specify either the consent portal ID or its Amazon Resource Name (ARN).

    " + } + } + }, + "DeleteConsentPortalResponse":{ + "type":"structure", + "members":{} + }, "DeleteDatasetExamplesRequest":{ "type":"structure", "required":[ @@ -7801,6 +8982,44 @@ } } }, + "DeleteGatewayRateLimitRequest":{ + "type":"structure", + "required":[ + "gatewayIdentifier", + "rateLimitId" + ], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit to delete.

    ", + "location":"uri", + "locationName":"rateLimitId" + } + } + }, + "DeleteGatewayRateLimitResponse":{ + "type":"structure", + "required":[ + "rateLimitId", + "status" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the deleted rate limit.

    " + }, + "status":{ + "shape":"GatewayRateLimitStatus", + "documentation":"

    The current status of the rate limit deletion.

    " + } + } + }, "DeleteGatewayRequest":{ "type":"structure", "required":["gatewayIdentifier"], @@ -8398,6 +9617,24 @@ "type":"structure", "members":{} }, + "DerivedEvaluatorConfig":{ + "type":"structure", + "required":[ + "baseEvaluatorId", + "modelConfig" + ], + "members":{ + "baseEvaluatorId":{ + "shape":"EvaluatorId", + "documentation":"

    The identifier of the base evaluator whose logic to run (a Builtin.* or ThirdParty.* evaluator).

    " + }, + "modelConfig":{ + "shape":"EvaluatorModelConfig", + "documentation":"

    The configuration of the evaluator model that you supply.

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

    The configuration for a derived evaluator. It reuses an existing evaluator's logic on your own model.

    " + }, "Description":{ "type":"string", "max":4096, @@ -8435,6 +9672,32 @@ }, "documentation":"

    Contains descriptor-type-specific configurations for a registry record. Only the descriptor matching the record's descriptorType should be populated.

    " }, + "DeviceName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9/._-]+" + }, + "DimensionKey":{ + "type":"string", + "documentation":"

    A dimension key specifying the scope dimension for rate limiting.

    Allowed values: targetName, toolName, qualifiedModelId, or context-path expressions: $.context.iam.principal, $.context.iam.sourceIdentity, $.context.jwt.<claim> where <claim> is a JWT claim name (for example, $.context.jwt.sub). Validated server-side to enforce allowed prefixes and patterns.

    ", + "max":80, + "min":1, + "pattern":"(targetName|toolName|qualifiedModelId|\\$\\.context\\.iam\\.principal|\\$\\.context\\.iam\\.sourceIdentity|\\$\\.context\\.jwt\\.[a-zA-Z_][a-zA-Z0-9_\\-\\.]{0,61}[a-zA-Z0-9_])" + }, + "DimensionKeys":{ + "type":"list", + "member":{"shape":"DimensionKey"}, + "documentation":"

    An ordered list of dimension key names defining the scope of a limit.

    ", + "max":10, + "min":1 + }, + "DimensionValue":{ + "type":"string", + "documentation":"

    A dimension value in a rule entry (exact value or * wildcard).

    ", + "max":256, + "min":1 + }, "DiscoveryUrl":{ "type":"string", "pattern":".+/\\.well-known/openid-configuration" @@ -8465,6 +9728,113 @@ "UNMODIFIED" ] }, + "EC2InstanceType":{ + "type":"string", + "max":255, + "min":1 + }, + "EbsCardIndex":{ + "type":"integer", + "box":true, + "min":0 + }, + "EbsSnapshotId":{ + "type":"string", + "max":64, + "min":13, + "pattern":"snap-[a-f0-9]{8,17}" + }, + "EbsVolumeConfiguration":{ + "type":"structure", + "required":[ + "name", + "sizeGiB" + ], + "members":{ + "name":{ + "shape":"VolumeName", + "documentation":"

    The logical name of the volume. Use this name to reference the volume when you mount it into an agent runtime.

    " + }, + "sizeGiB":{ + "shape":"VolumeSizeGiB", + "documentation":"

    The size of the volume, in GiB.

    " + }, + "volumeType":{ + "shape":"EbsVolumeType", + "documentation":"

    The Amazon EBS volume type. If you do not specify a type, the default is gp3.

    " + }, + "iops":{ + "shape":"VolumeIops", + "documentation":"

    The number of IOPS to provision. Valid only for gp3, io1, and io2 volumes.

    " + }, + "throughput":{ + "shape":"VolumeThroughput", + "documentation":"

    The throughput, in MiB/s. Valid only for gp3 volumes.

    " + }, + "encrypted":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to encrypt the volume. If true, the service encrypts the volume with the KMS key that you specify in kmsKeyId, or the default KMS key for Amazon EBS if you do not specify one. The default is true.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The identifier of the KMS key to use for encryption.

    " + }, + "snapshotId":{ + "shape":"EbsSnapshotId", + "documentation":"

    An optional Amazon EBS snapshot ID. If provided, the volume is initialized from this snapshot the first time it is created. On subsequent restarts, the existing volume is used and the snapshot is ignored.

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

    The configuration for an Amazon EBS-backed persistent volume. The service creates persistent volumes when a session first launches, and the volumes survive instance termination. The volumes persist until you delete the session.

    " + }, + "EbsVolumeInitializationRate":{ + "type":"integer", + "box":true, + "max":300, + "min":100 + }, + "EbsVolumeType":{ + "type":"string", + "documentation":"

    The type of Amazon EBS volume.

    ", + "enum":[ + "standard", + "io1", + "io2", + "gp2", + "sc1", + "st1", + "gp3" + ] + }, + "Ec2Configuration":{ + "type":"structure", + "required":[ + "launchTemplateSource", + "vpcConfiguration" + ], + "members":{ + "launchTemplateSource":{ + "shape":"LaunchTemplateSource", + "documentation":"

    The source of the launch template configuration that defines how instances are launched.

    " + }, + "vpcConfiguration":{ + "shape":"VpcConfiguration", + "documentation":"

    The VPC configuration for launching instances, including subnets and security groups.

    " + }, + "volumes":{ + "shape":"VolumeConfigurationList", + "documentation":"

    The named persistent Amazon EBS volumes for the capacity provider. A capacity provider can define up to five volumes.

    " + }, + "lifecycleConfiguration":{ + "shape":"InstanceLifecycleConfiguration", + "documentation":"

    The lifecycle configuration for instances in the capacity provider.

    " + }, + "rootVolume":{ + "shape":"RootVolumeConfiguration", + "documentation":"

    The configuration for the instance root volume. Specify the amount of free space to guarantee and, optionally, the Amazon EBS performance and encryption settings. The device name and delete-on-termination behavior are not configurable.

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

    The configuration for Amazon EC2-based compute, including the launch template source, networking, storage volumes, and instance lifecycle settings.

    " + }, "EfsAccessPointArn":{ "type":"string", "max":128, @@ -8489,6 +9859,36 @@ }, "documentation":"

    Configuration for an Amazon EFS access point filesystem mounted into the AgentCore Runtime. EFS access points provide shared file storage accessible from your AgentCore Runtime sessions.

    " }, + "EfsConfiguration":{ + "type":"structure", + "required":[ + "accessPointArn", + "mountPath", + "fileSystemArn" + ], + "members":{ + "accessPointArn":{ + "shape":"EfsAccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Elastic File System (Amazon EFS) access point to mount.

    " + }, + "mountPath":{ + "shape":"MountPath", + "documentation":"

    The absolute path within the session at which the access point is mounted, for example /mnt/efs. Each mount path must be unique across all file system configurations in the session.

    " + }, + "fileSystemArn":{ + "shape":"EfsFileSystemArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Elastic File System (Amazon EFS) file system that owns the access point.

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

    The configuration for mounting an Amazon Elastic File System (Amazon EFS) access point that you own into a session.

    " + }, + "EfsFileSystemArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Elastic File System (Amazon EFS) file system. The access points you specify must belong to this file system.

    ", + "max":256, + "min":0, + "pattern":"arn:aws[-a-z]*:elasticfilesystem:[a-z0-9-]+:[0-9]{12}:file-system/fs-[0-9a-f]{8,40}" + }, "EnabledConnectors":{ "type":"list", "member":{"shape":"String"}, @@ -8546,6 +9946,75 @@ "min":0, "sensitive":true }, + "EphemeralBlockDeviceMapping":{ + "type":"structure", + "members":{ + "deviceName":{ + "shape":"DeviceName", + "documentation":"

    The device name, for example /dev/sdh or xvdh.

    " + }, + "virtualName":{ + "shape":"VirtualDeviceName", + "documentation":"

    The virtual device name (ephemeralN). Instance store volumes are numbered starting from 0. The number of available instance store volumes depends on the instance type. After you connect to the instance, you must mount the volume.

    " + }, + "ebs":{"shape":"EphemeralEBSVolumeConfiguration"} + }, + "documentation":"

    A block device mapping for an instance store (ephemeral) volume.

    " + }, + "EphemeralEBSVolumeConfiguration":{ + "type":"structure", + "members":{ + "volumeType":{ + "shape":"EbsVolumeType", + "documentation":"

    The Amazon EBS volume type. If you do not specify a type, the default is gp3.

    " + }, + "iops":{ + "shape":"VolumeIops", + "documentation":"

    The number of IOPS to provision. For gp3, io1, and io2 volumes, this is the number of IOPS provisioned for the volume. For gp2 volumes, this sets the baseline IOPS performance. It also controls the rate at which the volume accumulates I/O credits for bursting. Supported values: gp3, 3,000–80,000; io1, 100–64,000; io2, 100–256,000.

    " + }, + "throughput":{ + "shape":"EphemeralEBSVolumeConfigurationThroughputInteger", + "documentation":"

    The throughput to provision, in MiB/s. Valid only for gp3 volumes. Valid range: 125–2,000 MiB/s.

    " + }, + "encrypted":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to encrypt the volume. Encrypted volumes can be attached only to instances that support Amazon EBS encryption. If you create a volume from a snapshot, you cannot specify an encryption value.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The identifier (key ID, key alias, key ARN, or alias ARN) of the customer managed KMS key to use for Amazon EBS encryption.

    " + }, + "snapshotId":{ + "shape":"EbsSnapshotId", + "documentation":"

    The ID of the snapshot.

    " + }, + "volumeSize":{ + "shape":"EphemeralEBSVolumeConfigurationVolumeSizeInteger", + "documentation":"

    The size of the volume, in GiB. You must specify either a snapshot ID or a volume size. Supported sizes: gp2, 1–16,384; gp3, 1–65,536; io1, 4–16,384; io2, 4–65,536.

    " + }, + "volumeInitializationRate":{ + "shape":"EbsVolumeInitializationRate", + "documentation":"

    The rate at which the volume is initialized after creation, in MiB/s. Supported only for volumes created from snapshots. Valid range: 100–300 MiB/s.

    " + }, + "ebsCardIndex":{ + "shape":"EbsCardIndex", + "documentation":"

    The index of the Amazon EBS card. Applies to instances with multiple Amazon EBS cards.

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

    The shared Amazon EBS performance and encryption properties for a volume. These properties are common across the different volume configurations for a capacity provider.

    " + }, + "EphemeralEBSVolumeConfigurationThroughputInteger":{ + "type":"integer", + "box":true, + "max":2000, + "min":125 + }, + "EphemeralEBSVolumeConfigurationVolumeSizeInteger":{ + "type":"integer", + "box":true, + "max":65536, + "min":1 + }, "EpisodicConsolidationOverride":{ "type":"structure", "required":[ @@ -8791,7 +10260,7 @@ }, "EvaluatorArn":{ "type":"string", - "pattern":"arn:aws[a-zA-Z-]*:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:evaluator\\/[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10}$|^arn:aws[a-zA-Z-]*:bedrock-agentcore:::evaluator/Builtin.[a-zA-Z0-9_-]+" + "pattern":"arn:aws[a-zA-Z-]*:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:evaluator\\/[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10}$|^arn:aws[a-zA-Z-]*:bedrock-agentcore:::evaluator/(Builtin|ThirdParty)\\.[a-zA-Z0-9._-]+" }, "EvaluatorConfig":{ "type":"structure", @@ -8803,6 +10272,10 @@ "codeBased":{ "shape":"CodeBasedEvaluatorConfig", "documentation":"

    Configuration for a code-based evaluator that uses a customer-managed Lambda function to programmatically assess agent performance.

    " + }, + "derived":{ + "shape":"DerivedEvaluatorConfig", + "documentation":"

    The configuration for an evaluator derived from an existing base evaluator (a built-in or third-party evaluator), run on your own model. The base evaluator supplies the prompt and scoring.

    " } }, "documentation":"

    The configuration that defines how an evaluator assesses agent performance, including the evaluation method and parameters.

    ", @@ -8816,7 +10289,9 @@ }, "EvaluatorId":{ "type":"string", - "pattern":"(Builtin.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10})" + "max":111, + "min":1, + "pattern":"(Builtin\\.[a-zA-Z0-9._-]+|ThirdParty\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9-_]{0,99}-[a-zA-Z0-9]{10})" }, "EvaluatorInstructions":{ "type":"string", @@ -8833,7 +10308,7 @@ "EvaluatorList":{ "type":"list", "member":{"shape":"EvaluatorReference"}, - "max":10, + "max":25, "min":0 }, "EvaluatorModelConfig":{ @@ -8842,6 +10317,10 @@ "bedrockEvaluatorModelConfig":{ "shape":"BedrockEvaluatorModelConfig", "documentation":"

    The Amazon Bedrock model configuration for evaluation.

    " + }, + "responsesEvaluatorModelConfig":{ + "shape":"OpenResponsesEvaluatorModelConfig", + "documentation":"

    The OpenResponses model configuration for evaluation.

    " } }, "documentation":"

    The model configuration that specifies which foundation model to use for evaluation and how to configure it.

    ", @@ -8849,7 +10328,9 @@ }, "EvaluatorName":{ "type":"string", - "pattern":"(Builtin.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9_]{0,47})" + "max":48, + "min":1, + "pattern":"(Builtin\\.[a-zA-Z0-9._-]+|ThirdParty\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+|[a-zA-Z][a-zA-Z0-9_]{0,47})" }, "EvaluatorReference":{ "type":"structure", @@ -8905,6 +10386,10 @@ "shape":"EvaluatorType", "documentation":"

    The type of evaluator, indicating whether it is a built-in evaluator provided by the service or a custom evaluator created by the user.

    " }, + "provider":{ + "shape":"Provider", + "documentation":"

    The source of the evaluator's logic: Amazon Web Services, a third-party library, or you.

    " + }, "level":{ "shape":"EvaluatorLevel", "documentation":"

    The evaluation level (TOOL_CALL, TRACE, or SESSION) that determines the scope of evaluation.

    " @@ -8940,8 +10425,10 @@ "type":"string", "enum":[ "Builtin", + "ThirdParty", "Custom", - "CustomCode" + "CustomCode", + "CustomDerived" ] }, "ExampleId":{ @@ -8958,6 +10445,10 @@ "type":"string", "enum":["DEBUG"] }, + "ExecutionRoleArnType":{ + "type":"string", + "pattern":"arn:aws(-[a-z-]+)?:iam::[0-9]{12}:role/[a-zA-Z0-9+=,.@\\-_/]+" + }, "ExtractionConfig":{ "type":"structure", "members":{ @@ -9002,6 +10493,10 @@ "efsAccessPoint":{ "shape":"EfsAccessPointConfiguration", "documentation":"

    Configuration for an Amazon EFS access point to mount into the AgentCore Runtime.

    " + }, + "capacityProviderVolume":{ + "shape":"CapacityProviderVolumeConfiguration", + "documentation":"

    Configuration for a capacity provider volume to mount into the AgentCore Runtime. This mounts a persistent volume that is defined on the capacity provider, referenced by its logical name.

    " } }, "documentation":"

    Configuration for a filesystem that can be mounted into the AgentCore Runtime.

    ", @@ -9228,7 +10723,7 @@ "members":{ "arn":{ "shape":"GatewayPolicyEngineArn", - "documentation":"

    The ARN of the policy engine. The policy engine contains Cedar policies that define fine-grained authorization rules specifying who can perform what actions on which resources as agents interact through the gateway.

    " + "documentation":"

    The ARN of the policy engine. The policy engine contains Cedar or Dogwood policies that define fine-grained authorization rules specifying who can perform what actions on which resources as agents interact through the gateway.

    " }, "mode":{ "shape":"GatewayPolicyEngineMode", @@ -9259,6 +10754,92 @@ "type":"string", "enum":["MCP"] }, + "GatewayRateLimitDescription":{ + "type":"string", + "documentation":"

    An optional human-readable description for a gateway limit.

    ", + "max":512, + "min":0 + }, + "GatewayRateLimitDetail":{ + "type":"structure", + "required":[ + "rateLimitId", + "gatewayIdentifier", + "dimensionKeys", + "entries", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit.

    " + }, + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    The human-readable description of the rate limit.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The list of rule entries that map dimension values to rate configurations.

    " + }, + "status":{ + "shape":"GatewayRateLimitStatus", + "documentation":"

    The current status of the rate limit.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was last updated.

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

    Contains detailed information about a gateway rate limit, including its configuration and current status.

    " + }, + "GatewayRateLimitId":{ + "type":"string", + "documentation":"

    The limit identifier. Optional on create (the system generates it if not provided by the customer). Always present in responses.

    ", + "max":64, + "min":2, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9\\-_\\.]{0,62}[a-zA-Z0-9]" + }, + "GatewayRateLimitMaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "GatewayRateLimitNextToken":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"\\S*" + }, + "GatewayRateLimitStatus":{ + "type":"string", + "documentation":"

    The status of a gateway limit.

    ", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING" + ] + }, + "GatewayRateLimits":{ + "type":"list", + "member":{"shape":"GatewayRateLimitDetail"} + }, "GatewayRuleDescription":{ "type":"string", "max":256, @@ -9606,7 +11187,6 @@ "createdAt", "lastUpdatedAt", "roleArn", - "networkConfiguration", "status", "lifecycleConfiguration" ], @@ -9687,6 +11267,14 @@ "filesystemConfigurations":{ "shape":"FilesystemConfigurations", "documentation":"

    The filesystem configurations mounted into the AgentCore Runtime.

    " + }, + "capacityProviderConfiguration":{ + "shape":"CapacityProviderConfiguration", + "documentation":"

    The capacity provider configuration for the AgentCore Runtime.

    " + }, + "platformVersion":{ + "shape":"PlatformVersion", + "documentation":"

    The version of the runtime platform used by the AgentCore Runtime.

    " } } }, @@ -9863,6 +11451,10 @@ "shape":"Certificates", "documentation":"

    The list of certificates configured for the browser.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations mounted into the browser. Each entry describes an access point and its mount path.

    " + }, "status":{ "shape":"BrowserStatus", "documentation":"

    The current status of the browser.

    " @@ -9881,6 +11473,77 @@ } } }, + "GetCapacityProviderInput":{ + "type":"structure", + "required":["capacityProviderId"], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider.

    ", + "location":"uri", + "locationName":"capacityProviderId" + } + } + }, + "GetCapacityProviderOutput":{ + "type":"structure", + "required":[ + "capacityProviderId", + "capacityProviderArn", + "name", + "status", + "permissionsConfiguration", + "computeConfiguration", + "createdAt", + "lastUpdatedAt" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider.

    " + }, + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider.

    " + }, + "name":{ + "shape":"CapacityProviderName", + "documentation":"

    The name of the capacity provider.

    " + }, + "status":{ + "shape":"CapacityProviderStatus", + "documentation":"

    The current status of the capacity provider. For possible values, see CapacityProviderStatus.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the capacity provider, if one was provided.

    " + }, + "statusCode":{ + "shape":"CapacityProviderStatusCode", + "documentation":"

    A reason code for a capacity provider that is not in the READY state. Use this code for programmatic error handling.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable message that describes why the capacity provider is not in the READY state. Because these messages can change, use statusCode for programmatic error handling.

    " + }, + "permissionsConfiguration":{ + "shape":"PermissionsConfiguration", + "documentation":"

    The permissions configuration for the capacity provider.

    " + }, + "computeConfiguration":{ + "shape":"ComputeConfiguration", + "documentation":"

    The compute configuration for the capacity provider.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the capacity provider was created.

    " + }, + "lastUpdatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the capacity provider was last updated.

    " + } + } + }, "GetCodeInterpreterRequest":{ "type":"structure", "required":["codeInterpreterId"], @@ -9934,6 +11597,10 @@ "shape":"Certificates", "documentation":"

    The list of certificates configured for the code interpreter.

    " }, + "filesystemConfigurations":{ + "shape":"ToolsFileSystemConfigurations", + "documentation":"

    The file system configurations mounted into the code interpreter. Each entry describes an access point and its mount path.

    " + }, "failureReason":{ "shape":"String", "documentation":"

    The reason for failure if the code interpreter is in a failed state.

    " @@ -10095,6 +11762,80 @@ } } }, + "GetConsentPortalRequest":{ + "type":"structure", + "required":["consentPortalIdentifier"], + "members":{ + "consentPortalIdentifier":{ + "shape":"ConsentPortalIdentifier", + "documentation":"

    The identifier of the consent portal. You can specify either the consent portal ID or its Amazon Resource Name (ARN).

    " + } + } + }, + "GetConsentPortalResponse":{ + "type":"structure", + "required":[ + "sources", + "consentPortalArn", + "consentPortalId", + "createdAt", + "executionRoleArn", + "idpConfig", + "name", + "status", + "updatedAt" + ], + "members":{ + "sources":{ + "shape":"ConsentPortalSources", + "documentation":"

    The resources served by the consent portal.

    " + }, + "consentPortalArn":{ + "shape":"ConsentPortalArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the consent portal.

    " + }, + "consentPortalId":{ + "shape":"ConsentPortalIdType", + "documentation":"

    The unique identifier of the consent portal.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was created.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + }, + "executionRoleArn":{ + "shape":"ExecutionRoleArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that the consent portal assumes to access the resources defined in its sources.

    " + }, + "idpConfig":{ + "shape":"ConsentPortalIdpConfig", + "documentation":"

    The identity provider configuration that the consent portal uses to authenticate end users.

    " + }, + "name":{ + "shape":"ConsentPortalNameType", + "documentation":"

    The name of the consent portal.

    " + }, + "portalUrl":{ + "shape":"PortalUrlType", + "documentation":"

    The URL used to access the consent portal.

    " + }, + "status":{ + "shape":"ConsentPortalStatus", + "documentation":"

    The current status of the consent portal.

    " + }, + "statusReason":{ + "shape":"StatusReasonType", + "documentation":"

    A message that provides additional information about the current status of the consent portal.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was last updated.

    " + } + } + }, "GetDatasetRequest":{ "type":"structure", "required":["datasetId"], @@ -10244,6 +11985,14 @@ "shape":"EvaluatorConfig", "documentation":"

    The configuration of the evaluator, including LLM-as-a-Judge or code-based settings.

    " }, + "evaluatorType":{ + "shape":"EvaluatorType", + "documentation":"

    The kind of evaluator resource. Valid values:

    • Builtin – An Amazon Web Services-managed global evaluator.

    • ThirdParty – An Amazon Web Services-managed global evaluator from a third-party provider.

    • Custom – A customer-created evaluator.

    • CustomCode – A customer-created code-based evaluator.

    • CustomDerived – A customer-created evaluator derived from an existing base evaluator.

    " + }, + "provider":{ + "shape":"Provider", + "documentation":"

    The source of the evaluator's logic: Amazon Web Services, a third-party library, or you.

    " + }, "level":{ "shape":"EvaluatorLevel", "documentation":"

    The evaluation level (TOOL_CALL, TRACE, or SESSION) that determines the scope of evaluation.

    " @@ -10270,6 +12019,74 @@ } } }, + "GetGatewayRateLimitRequest":{ + "type":"structure", + "required":[ + "gatewayIdentifier", + "rateLimitId" + ], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit to retrieve.

    ", + "location":"uri", + "locationName":"rateLimitId" + } + } + }, + "GetGatewayRateLimitResponse":{ + "type":"structure", + "required":[ + "rateLimitId", + "gatewayIdentifier", + "dimensionKeys", + "entries", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit.

    " + }, + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    The human-readable description of the rate limit.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The list of rule entries that map dimension values to rate configurations.

    " + }, + "status":{ + "shape":"GatewayRateLimitStatus", + "documentation":"

    The current status of the rate limit.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was last updated.

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

    Shared fields for GatewayRateLimit responses.

    " + }, "GetGatewayRequest":{ "type":"structure", "required":["gatewayIdentifier"], @@ -10868,6 +12685,10 @@ "status":{ "shape":"PaymentConnectorStatus", "documentation":"

    The current status of the payment connector. Possible values include CREATING, READY, UPDATING, DELETING, CREATE_FAILED, UPDATE_FAILED, and DELETE_FAILED.

    " + }, + "authorizationUrl":{ + "shape":"PaymentConnectorAuthorizationUrl", + "documentation":"

    The URL that the user must open to complete OAuth consent. This field is only present when the payment connector status is PENDING_AUTHENTICATION.

    " } } }, @@ -10988,6 +12809,10 @@ "tags":{ "shape":"TagsMap", "documentation":"

    The tags associated with the payment manager.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key used to encrypt sensitive payment manager data at rest, if configured.

    " } } }, @@ -11324,7 +13149,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The Cedar policy statement that defines the access control rules. This contains the actual policy logic used for agent behavior control and access decisions.

    " + "documentation":"

    The Cedar or Dogwood policy statement that defines the access control rules. This contains the actual policy logic used for agent behavior control and access decisions.

    " }, "description":{ "shape":"Description", @@ -11826,6 +13651,10 @@ "shape":"HarnessMemoryConfiguration", "documentation":"

    AgentCore Memory instance configuration for short and long term memory.

    " }, + "hooks":{ + "shape":"HarnessHooks", + "documentation":"

    The lifecycle hooks configured for the harness.

    " + }, "maxIterations":{ "shape":"Integer", "documentation":"

    The maximum number of iterations in the agent loop allowed before exiting per invocation.

    " @@ -11845,6 +13674,42 @@ }, "documentation":"

    Representation of a harness.

    " }, + "HarnessAfterInvocationHook":{ + "type":"structure", + "required":[ + "name", + "target" + ], + "members":{ + "name":{ + "shape":"HarnessHookName", + "documentation":"

    The name of the hook.

    " + }, + "target":{ + "shape":"HarnessHookTarget", + "documentation":"

    The target that receives the hook event.

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

    The configuration for a hook that runs after an invocation completes.

    " + }, + "HarnessAfterToolCallHook":{ + "type":"structure", + "required":[ + "name", + "target" + ], + "members":{ + "name":{ + "shape":"HarnessHookName", + "documentation":"

    The name of the hook.

    " + }, + "target":{ + "shape":"HarnessHookTarget", + "documentation":"

    The target that receives the hook event.

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

    The configuration for a hook that runs after a tool call completes.

    " + }, "HarnessAgentCoreBrowserConfig":{ "type":"structure", "members":{ @@ -12032,6 +13897,42 @@ }, "documentation":"

    Configuration for an Amazon Bedrock model provider.

    " }, + "HarnessBeforeInvocationHook":{ + "type":"structure", + "required":[ + "name", + "target" + ], + "members":{ + "name":{ + "shape":"HarnessHookName", + "documentation":"

    The name of the hook.

    " + }, + "target":{ + "shape":"HarnessHookTarget", + "documentation":"

    The target that receives the hook event.

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

    The configuration for a hook that runs before an invocation begins.

    " + }, + "HarnessBeforeToolCallHook":{ + "type":"structure", + "required":[ + "name", + "target" + ], + "members":{ + "name":{ + "shape":"HarnessHookName", + "documentation":"

    The name of the hook.

    " + }, + "target":{ + "shape":"HarnessHookTarget", + "documentation":"

    The target that receives the hook event.

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

    The configuration for a hook that runs before the agent calls a tool.

    " + }, "HarnessBrowserArn":{ "type":"string", "documentation":"

    Browser ARN for Harness tool configuration. Accepts both managed (aws.browser.v1) and custom browser ARNs.

    ", @@ -12108,7 +14009,7 @@ }, "HarnessEndpointArn":{ "type":"string", - "pattern":"arn:([^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:harness/[a-zA-Z][a-zA-Z0-9_]{0,39}-[a-zA-Z0-9]{10}/endpoint/[a-zA-Z][a-zA-Z0-9_]{0,47}" + "pattern":"arn:([^:]+)?:bedrock-agentcore:[a-z0-9-]+:[0-9]{12}:harness/[a-zA-Z][a-zA-Z0-9_]{0,39}-[a-zA-Z0-9]{10}/harness-endpoint/[a-zA-Z][a-zA-Z0-9_]{0,47}" }, "HarnessEndpointDescription":{ "type":"string", @@ -12165,6 +14066,13 @@ "documentation":"

    The environment provider request configuration.

    ", "union":true }, + "HarnessEventBridgeBusArn":{ + "type":"string", + "documentation":"

    The ARN of an Amazon EventBridge event bus.

    ", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:events:[a-z0-9-]+:[0-9]{12}:event-bus/.+" + }, "HarnessGatewayOutboundAuth":{ "type":"structure", "members":{ @@ -12181,42 +14089,157 @@ "documentation":"

    Use OAuth credentials for outbound authentication to the gateway.

    " } }, - "documentation":"

    Authentication method for calling a Gateway.

    ", - "union":true + "documentation":"

    Authentication method for calling a Gateway.

    ", + "union":true + }, + "HarnessGeminiModelConfig":{ + "type":"structure", + "required":[ + "modelId", + "apiKeyArn" + ], + "members":{ + "modelId":{ + "shape":"ModelId", + "documentation":"

    The Gemini model ID.

    " + }, + "apiKeyArn":{ + "shape":"ApiKeyArn", + "documentation":"

    The ARN of your Gemini API key on AgentCore Identity.

    " + }, + "maxTokens":{ + "shape":"MaxTokens", + "documentation":"

    The maximum number of tokens to allow in the generated response per model call.

    " + }, + "temperature":{ + "shape":"Temperature", + "documentation":"

    The temperature to set when calling the model.

    " + }, + "topP":{ + "shape":"TopP", + "documentation":"

    The topP set when calling the model.

    " + }, + "topK":{ + "shape":"TopK", + "documentation":"

    The topK set when calling the model.

    " + }, + "additionalParams":{ + "shape":"Document", + "documentation":"

    Provider-specific parameters passed through to the Gemini model provider unchanged.

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

    Configuration for a Google Gemini model provider. Requires an API key stored in AgentCore Identity.

    " + }, + "HarnessHook":{ + "type":"structure", + "members":{ + "beforeInvocation":{ + "shape":"HarnessBeforeInvocationHook", + "documentation":"

    A hook that runs before an invocation begins.

    " + }, + "afterInvocation":{ + "shape":"HarnessAfterInvocationHook", + "documentation":"

    A hook that runs after an invocation completes.

    " + }, + "beforeToolCall":{ + "shape":"HarnessBeforeToolCallHook", + "documentation":"

    A hook that runs before the agent calls a tool.

    " + }, + "afterToolCall":{ + "shape":"HarnessAfterToolCallHook", + "documentation":"

    A hook that runs after a tool call completes.

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

    A lifecycle hook configuration. Specify one hook type.

    ", + "union":true + }, + "HarnessHookEventBridgeTarget":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"HarnessEventBridgeBusArn", + "documentation":"

    The ARN of the Amazon EventBridge event bus to send hook events to.

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

    The configuration for an Amazon EventBridge hook target.

    " + }, + "HarnessHookFailureMode":{ + "type":"string", + "documentation":"

    The behavior when a synchronous hook target fails.

    ", + "enum":[ + "allow", + "deny" + ] + }, + "HarnessHookLambdaTarget":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"HarnessLambdaFunctionArn", + "documentation":"

    The ARN of the Lambda function to invoke.

    " + }, + "timeoutSeconds":{ + "shape":"HarnessHookLambdaTargetTimeoutSecondsInteger", + "documentation":"

    The maximum number of seconds to wait for the Lambda function response. The default is 60 seconds.

    " + }, + "failureMode":{ + "shape":"HarnessHookFailureMode", + "documentation":"

    The behavior when the Lambda function times out, returns an error, or returns an invalid response. The default is DENY.

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

    The configuration for an AWS Lambda hook target.

    " + }, + "HarnessHookLambdaTargetTimeoutSecondsInteger":{ + "type":"integer", + "box":true, + "max":900, + "min":1 + }, + "HarnessHookName":{ + "type":"string", + "documentation":"

    The name of a lifecycle hook.

    ", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "HarnessHookSnsTarget":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"HarnessSnsTopicArn", + "documentation":"

    The ARN of the Amazon SNS topic to publish hook events to.

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

    The configuration for an Amazon SNS hook target.

    " }, - "HarnessGeminiModelConfig":{ + "HarnessHookTarget":{ "type":"structure", - "required":[ - "modelId", - "apiKeyArn" - ], "members":{ - "modelId":{ - "shape":"ModelId", - "documentation":"

    The Gemini model ID.

    " - }, - "apiKeyArn":{ - "shape":"ApiKeyArn", - "documentation":"

    The ARN of your Gemini API key on AgentCore Identity.

    " - }, - "maxTokens":{ - "shape":"MaxTokens", - "documentation":"

    The maximum number of tokens to allow in the generated response per model call.

    " - }, - "temperature":{ - "shape":"Temperature", - "documentation":"

    The temperature to set when calling the model.

    " + "lambda":{ + "shape":"HarnessHookLambdaTarget", + "documentation":"

    A Lambda hook target that invokes an AWS Lambda function synchronously and waits for its response.

    " }, - "topP":{ - "shape":"TopP", - "documentation":"

    The topP set when calling the model.

    " + "sns":{ + "shape":"HarnessHookSnsTarget", + "documentation":"

    An Amazon SNS hook target that publishes the hook event without waiting for a response.

    " }, - "topK":{ - "shape":"TopK", - "documentation":"

    The topK set when calling the model.

    " + "eventBridge":{ + "shape":"HarnessHookEventBridgeTarget", + "documentation":"

    An Amazon EventBridge hook target that sends the hook event without waiting for a response.

    " } }, - "documentation":"

    Configuration for a Google Gemini model provider. Requires an API key stored in AgentCore Identity.

    " + "documentation":"

    The target that receives lifecycle hook events. Specify one target type.

    ", + "union":true + }, + "HarnessHooks":{ + "type":"list", + "member":{"shape":"HarnessHook"}, + "documentation":"

    The lifecycle hooks configured to run at defined points in the agent loop.

    ", + "max":20, + "min":0 }, "HarnessId":{ "type":"string", @@ -12246,6 +14269,13 @@ "min":1, "sensitive":true }, + "HarnessLambdaFunctionArn":{ + "type":"string", + "documentation":"

    The ARN of an AWS Lambda function.

    ", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:lambda:[a-z0-9-]+:[0-9]{12}:function:.+" + }, "HarnessLiteLlmApiBase":{ "type":"string", "max":16383, @@ -12376,6 +14406,12 @@ "type":"string", "pattern":"[a-zA-Z][a-zA-Z0-9_]{0,39}" }, + "HarnessOpenAiApiBase":{ + "type":"string", + "max":16383, + "min":1, + "sensitive":true + }, "HarnessOpenAiApiFormat":{ "type":"string", "enum":[ @@ -12398,6 +14434,10 @@ "shape":"ApiKeyArn", "documentation":"

    The ARN of your OpenAI API key on AgentCore Identity.

    " }, + "apiBase":{ + "shape":"HarnessOpenAiApiBase", + "documentation":"

    Optional custom endpoint URL for an OpenAI-compatible endpoint.

    " + }, "maxTokens":{ "shape":"MaxTokens", "documentation":"

    The maximum number of tokens to allow in the generated response per model call.

    " @@ -12511,11 +14551,13 @@ }, "HarnessSkillGitUrl":{ "type":"string", + "max":16383, "min":8, "pattern":"https://[^#@]+" }, "HarnessSkillPath":{ "type":"string", + "max":4096, "min":1 }, "HarnessSkillS3Source":{ @@ -12531,6 +14573,7 @@ }, "HarnessSkillS3Uri":{ "type":"string", + "max":16383, "min":5, "pattern":"s3://.*" }, @@ -12548,6 +14591,13 @@ }, "documentation":"

    Configuration for sliding window truncation strategy.

    " }, + "HarnessSnsTopicArn":{ + "type":"string", + "documentation":"

    The ARN of an Amazon SNS topic.

    ", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:sns:[a-z0-9-]+:[0-9]{12}:.+" + }, "HarnessStatus":{ "type":"string", "enum":[ @@ -12831,6 +14881,40 @@ }, "documentation":"

    The API schema configuration for an HTTP target. This schema defines the API structure that the target exposes.

    " }, + "HttpConnectorParameters":{ + "type":"map", + "key":{"shape":"ConnectorParameterName"}, + "value":{"shape":"ConnectorParameterValue"}, + "documentation":"

    A map of resource parameters for an HTTP connector target. Each entry maps a parameter name to its value.

    ", + "max":10, + "min":0 + }, + "HttpConnectorSource":{ + "type":"structure", + "required":["connectorId"], + "members":{ + "connectorId":{ + "shape":"ConnectorId", + "documentation":"

    The identifier for the HTTP connector integration.

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

    The source identifying the HTTP connector integration.

    " + }, + "HttpConnectorTargetConfiguration":{ + "type":"structure", + "required":["source"], + "members":{ + "source":{ + "shape":"HttpConnectorSource", + "documentation":"

    The source configuration identifying which HTTP connector to use.

    " + }, + "parameters":{ + "shape":"HttpConnectorParameters", + "documentation":"

    The resource parameters for this connector (for example, memoryId). The service validates these parameters against the request path at runtime.

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

    The configuration for an HTTP connector target. Use this configuration when you want to route HTTP requests through a managed connector.

    " + }, "HttpHeaderKey":{ "type":"string", "documentation":"

    The key of an HTTP header.

    ", @@ -12870,6 +14954,10 @@ "passthrough":{ "shape":"PassthroughTargetConfiguration", "documentation":"

    The passthrough configuration for the HTTP target. A passthrough target forwards requests directly to an external HTTP endpoint.

    " + }, + "connector":{ + "shape":"HttpConnectorTargetConfiguration", + "documentation":"

    The connector-based configuration for the HTTP target. Use this configuration when you want to route HTTP requests through a managed connector.

    " } }, "documentation":"

    The HTTP target configuration for a gateway target. Contains the configuration for HTTP-based target endpoints.

    ", @@ -13218,6 +15306,55 @@ "max":10, "min":0 }, + "InstanceLifecycleConfiguration":{ + "type":"structure", + "members":{ + "idleInstanceTimeout":{ + "shape":"InstanceLifecycleConfigurationIdleInstanceTimeoutInteger", + "documentation":"

    The number of seconds an instance can remain idle before it is stopped. An instance is considered idle when all of its agents are idle. The default is 900 seconds (15 minutes).

    " + }, + "maxLifetime":{ + "shape":"InstanceLifecycleConfigurationMaxLifetimeInteger", + "documentation":"

    The maximum lifetime of an instance, in seconds. When an instance reaches this limit, the service terminates it regardless of activity. The default is 28800 seconds (8 hours). The maximum is 1209600 seconds (14 days).

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

    The configuration that manages the lifecycle of instances in a capacity provider, including idle timeout and maximum lifetime.

    " + }, + "InstanceLifecycleConfigurationIdleInstanceTimeoutInteger":{ + "type":"integer", + "box":true, + "max":1209600, + "min":60 + }, + "InstanceLifecycleConfigurationMaxLifetimeInteger":{ + "type":"integer", + "box":true, + "max":1209600, + "min":60 + }, + "InstanceProfileArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:iam::[0-9]{12}:instance-profile/([!-~]{1,510}/)?([\\w+=,.@-]{1,128})" + }, + "InstanceRequirements":{ + "type":"structure", + "required":["allowedInstanceTypes"], + "members":{ + "allowedInstanceTypes":{ + "shape":"InstanceRequirementsAllowedInstanceTypesList", + "documentation":"

    The list of allowed instance types. You can specify up to 30 instance types.

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

    The requirements for Amazon EC2 instance types in a capacity provider.

    " + }, + "InstanceRequirementsAllowedInstanceTypesList":{ + "type":"list", + "member":{"shape":"EC2InstanceType"}, + "max":30, + "min":1 + }, "Integer":{ "type":"integer", "box":true @@ -13383,6 +15520,23 @@ "min":1, "pattern":"arn:aws(|-cn|-us-gov):kms:[a-zA-Z0-9-]*:[0-9]{12}:key/[a-zA-Z0-9-]{36}" }, + "KmsKeyId":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:kms:[a-z0-9-]+:[0-9]{12}:key/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" + }, + "KmsKeySourceType":{ + "type":"structure", + "required":["kmsKeyArn"], + "members":{ + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key used to sign the JWT client assertion. The key must be an asymmetric key with key usage SIGN_VERIFY and a key spec compatible with the configured signing algorithm.

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

    Contains the KMS key configuration for a JWT client assertion.

    " + }, "LambdaArn":{ "type":"string", "pattern":"arn:(aws[a-zA-Z-]*)?:lambda:([a-z]{2}(-gov)?-[a-z]+-\\d{1}):(\\d{12}):function:([a-zA-Z0-9-_.]+)(:(\\$LATEST|[a-zA-Z0-9-_]+))?" @@ -13435,6 +15589,92 @@ }, "documentation":"

    The Lambda configuration for custom transformations. This structure defines the Lambda function that the gateway invokes to transform data.

    " }, + "LaunchParameters":{ + "type":"structure", + "required":[ + "operatingSystem", + "instanceRequirements" + ], + "members":{ + "operatingSystem":{ + "shape":"OperatingSystem", + "documentation":"

    The operating system and CPU architecture for the instances.

    " + }, + "instanceRequirements":{ + "shape":"InstanceRequirements", + "documentation":"

    The requirements that determine which instance types can be launched.

    " + }, + "ephemeralVolumes":{ + "shape":"LaunchParametersEphemeralVolumesList", + "documentation":"

    The block device mappings for instance store (ephemeral) volumes. You can specify up to five mappings.

    " + }, + "monitoring":{ + "shape":"Monitoring", + "documentation":"

    The monitoring level for the instances.

    " + }, + "licenseSpecifications":{ + "shape":"LaunchParametersLicenseSpecificationsList", + "documentation":"

    The license configurations to associate with the instances. You can specify up to five configurations.

    " + }, + "capacityReservationSpecification":{ + "shape":"CapacityReservationSpecification", + "documentation":"

    The Capacity Reservation targeting option for the instances.

    " + }, + "sshKeyName":{ + "shape":"SSHKeyName", + "documentation":"

    The name of the SSH key pair to configure on the instances for SSH connectivity.

    " + }, + "instanceProfileArn":{ + "shape":"InstanceProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM instance profile to associate with launched instances. If provided, this overrides the default instance profile.

    " + }, + "propagatedTags":{ + "shape":"TagsMap", + "documentation":"

    The tags to propagate to all Amazon EC2 resources (instances, volumes, and network interfaces) that the capacity provider creates.

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

    The parameters for launching Amazon EC2 instances in a capacity provider.

    " + }, + "LaunchParametersEphemeralVolumesList":{ + "type":"list", + "member":{"shape":"EphemeralBlockDeviceMapping"}, + "max":5, + "min":0 + }, + "LaunchParametersLicenseSpecificationsList":{ + "type":"list", + "member":{"shape":"LicenseSpecification"}, + "max":5, + "min":0 + }, + "LaunchTemplateSource":{ + "type":"structure", + "members":{ + "launchParameters":{ + "shape":"LaunchParameters", + "documentation":"

    The parameters that AgentCore uses to create the launch template.

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

    The source of the launch template configuration for a capacity provider. The launchParameters member specifies the operating system, instance requirements, and other settings used to launch instances.

    ", + "union":true + }, + "LicenseConfigurationArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[^:]+)?:license-manager:[a-z0-9-]+:[0-9]{12}:license-configuration:[a-zA-Z0-9_-]+" + }, + "LicenseSpecification":{ + "type":"structure", + "required":["licenseConfigurationArn"], + "members":{ + "licenseConfigurationArn":{ + "shape":"LicenseConfigurationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the license configuration.

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

    A license configuration to associate with the instances.

    " + }, "LifecycleConfiguration":{ "type":"structure", "members":{ @@ -13452,15 +15692,53 @@ "LifecycleConfigurationIdleRuntimeSessionTimeoutInteger":{ "type":"integer", "box":true, - "max":28800, + "max":1209600, "min":60 }, "LifecycleConfigurationMaxLifetimeInteger":{ "type":"integer", "box":true, - "max":28800, + "max":1209600, "min":60 }, + "LimitEntries":{ + "type":"list", + "member":{"shape":"LimitEntry"}, + "documentation":"

    A list of rule entries within a limit.

    ", + "max":1000, + "min":1 + }, + "LimitEntry":{ + "type":"structure", + "required":["dimensions"], + "members":{ + "dimensions":{ + "shape":"LimitEntryDimensionsMap", + "documentation":"

    A map of dimension names to dimension values for this rule entry. Keys must match the parent rate limit's dimension keys. Values may use * as a wildcard, but only in trailing positions based on the dimension keys ordering.

    " + }, + "requests":{ + "shape":"RateConfigs", + "documentation":"

    The request rate limit configuration. Specifies the maximum number of requests allowed per time period.

    " + }, + "tokens":{ + "shape":"RateConfigs", + "documentation":"

    The token rate limit configuration. Specifies the maximum number of tokens allowed per time period.

    " + }, + "connections":{ + "shape":"RateConfigs", + "documentation":"

    The connection rate limit configuration. Specifies the maximum number of concurrent connections allowed.

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

    A single rule entry within a rate limit that maps dimension values to rate configurations. Each entry defines the rate limits for a specific combination of dimension values.

    " + }, + "LimitEntryDimensionsMap":{ + "type":"map", + "key":{"shape":"DimensionKey"}, + "value":{"shape":"DimensionValue"}, + "documentation":"

    A map of dimension name to dimension value for a rule entry.

    ", + "max":10, + "min":1 + }, "LinkedinOauth2ProviderConfigInput":{ "type":"structure", "required":["clientId"], @@ -13534,6 +15812,44 @@ } } }, + "ListAgentRuntimeVersionsByCapacityProviderInput":{ + "type":"structure", + "required":["capacityProviderId"], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider.

    ", + "location":"uri", + "locationName":"capacityProviderId" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in the response. If the total number of results is greater than this value, use the token returned in the response in the nextToken field when making another request to return the next batch of results.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    If the total number of results is greater than the maxResults value provided in the request, enter the token returned in the nextToken field in the response in this field to return the next batch of results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAgentRuntimeVersionsByCapacityProviderOutput":{ + "type":"structure", + "required":["agentRuntimes"], + "members":{ + "agentRuntimes":{ + "shape":"AgentRuntimeVersionSummaryList", + "documentation":"

    The list of agent runtime versions that are associated with the capacity provider.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    If the total number of results is greater than the maxResults value provided in the request, use this token when making another request in the nextToken field to return the next batch of results.

    " + } + } + }, "ListAgentRuntimeVersionsRequest":{ "type":"structure", "required":["agentRuntimeId"], @@ -13702,6 +16018,37 @@ } } }, + "ListCapacityProvidersInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in the response. If the total number of results is greater than this value, use the token returned in the response in the nextToken field when making another request to return the next batch of results.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    If the total number of results is greater than the maxResults value provided in the request, enter the token returned in the nextToken field in the response in this field to return the next batch of results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListCapacityProvidersOutput":{ + "type":"structure", + "required":["capacityProviders"], + "members":{ + "capacityProviders":{ + "shape":"CapacityProviderList", + "documentation":"

    The list of capacity provider summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    If the total number of results is greater than the maxResults value provided in the request, use this token when making another request in the nextToken field to return the next batch of results.

    " + } + } + }, "ListCodeInterpretersRequest":{ "type":"structure", "members":{ @@ -13804,23 +16151,56 @@ } } }, - "ListConfigurationBundlesRequestMaxResultsInteger":{ + "ListConfigurationBundlesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListConfigurationBundlesResponse":{ + "type":"structure", + "required":["bundles"], + "members":{ + "bundles":{ + "shape":"ConfigurationBundleSummaryList", + "documentation":"

    The list of configuration bundle summaries.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    If the total number of results is greater than the maxResults value provided in the request, use this token when making another request in the nextToken field to return the next batch of results.

    " + } + } + }, + "ListConsentPortalsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListConsentPortalsRequestMaxResultsInteger", + "documentation":"

    The maximum number of consent portals to return in a single call.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results. Use the value returned in a previous response to request the next page.

    " + } + } + }, + "ListConsentPortalsRequestMaxResultsInteger":{ "type":"integer", "box":true, "max":100, "min":1 }, - "ListConfigurationBundlesResponse":{ + "ListConsentPortalsResponse":{ "type":"structure", - "required":["bundles"], + "required":["consentPortals"], "members":{ - "bundles":{ - "shape":"ConfigurationBundleSummaryList", - "documentation":"

    The list of configuration bundle summaries.

    " + "consentPortals":{ + "shape":"ConsentPortalSummaries", + "documentation":"

    The list of consent portals.

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

    If the total number of results is greater than the maxResults value provided in the request, use this token when making another request in the nextToken field to return the next batch of results.

    " + "documentation":"

    The token to use in a subsequent request to retrieve the next page of results. This value is null when there are no more results to return.

    " } } }, @@ -14019,6 +16399,44 @@ } } }, + "ListGatewayRateLimitsRequest":{ + "type":"structure", + "required":["gatewayIdentifier"], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "maxResults":{ + "shape":"GatewayRateLimitMaxResults", + "documentation":"

    The maximum number of results to return in the response. If the total number of results is greater than this value, use the token returned in the response in the nextToken field when making another request to return the next batch of results.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"GatewayRateLimitNextToken", + "documentation":"

    The token to use to retrieve the next page of results. Use the value returned in a previous ListGatewayRateLimits response.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListGatewayRateLimitsResponse":{ + "type":"structure", + "required":["rateLimits"], + "members":{ + "rateLimits":{ + "shape":"GatewayRateLimits", + "documentation":"

    The list of rate limits for the gateway.

    " + }, + "nextToken":{ + "shape":"GatewayRateLimitNextToken", + "documentation":"

    The token for the next page of results. If this value is absent, there are no more results to retrieve.

    " + } + } + }, "ListGatewayRulesRequest":{ "type":"structure", "required":["gatewayIdentifier"], @@ -14582,7 +17000,7 @@ "members":{ "policyGenerationAssets":{ "shape":"PolicyGenerationAssets", - "documentation":"

    An array of generated policy assets including Cedar policies and related artifacts from the AI-powered policy generation process. Each asset represents a different policy option or variation generated from the original natural language input.

    " + "documentation":"

    An array of generated policy assets including Dogwood policies and related artifacts from the AI-powered policy generation process. Each asset represents a different policy option or variation generated from the original natural language input.

    " }, "nextToken":{ "shape":"NextToken", @@ -14922,6 +17340,13 @@ "type":"string", "pattern":"[.\\-_/#A-Za-z0-9]+" }, + "LogGroupNamePrefix":{ + "type":"string", + "documentation":"

    Prefix of a CloudWatch Logs log group name.

    ", + "max":512, + "min":1, + "pattern":"[.\\-_/#A-Za-z0-9]+" + }, "Long":{ "type":"long", "box":true @@ -15264,6 +17689,10 @@ "shape":"IndexedKeysList", "documentation":"

    The indexed metadata keys for this memory. Only indexed keys can be used in metadata filters.

    " }, + "namespaceKeys":{ + "shape":"NamespaceKeysList", + "documentation":"

    The namespace variable key definitions for this memory. Namespace keys define custom variables used in namespaceTemplates with optional validation rules.

    " + }, "streamDeliveryResources":{ "shape":"StreamDeliveryResources", "documentation":"

    Configuration for streaming memory record data to external resources.

    " @@ -15561,6 +17990,13 @@ "NUMBER" ] }, + "MetricsNamespace":{ + "type":"string", + "documentation":"

    CloudWatch metrics namespace for evaluation result metrics.

    ", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9._#/:-]+" + }, "MicrosoftOauth2ProviderConfigInput":{ "type":"structure", "required":["clientId"], @@ -15794,6 +18230,13 @@ }, "documentation":"

    Contains information for modifying a strategy configuration.

    " }, + "Monitoring":{ + "type":"string", + "enum":[ + "BASIC", + "DETAILED" + ] + }, "MountPath":{ "type":"string", "max":200, @@ -15808,7 +18251,65 @@ "type":"string", "max":512, "min":1, - "pattern":"[a-zA-Z0-9\\-_\\/]*(\\{(actorId|sessionId|memoryStrategyId)\\}[a-zA-Z0-9\\-_\\/]*)*" + "pattern":"[a-zA-Z0-9\\-_\\/]*(\\{[a-zA-Z][a-zA-Z0-9]*\\}[a-zA-Z0-9\\-_\\/]*)*" + }, + "NamespaceAllowedValue":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9][a-z0-9-_]*" + }, + "NamespaceAllowedValuesList":{ + "type":"list", + "member":{"shape":"NamespaceAllowedValue"}, + "max":10, + "min":1 + }, + "NamespaceKeyEntry":{ + "type":"structure", + "required":["key"], + "members":{ + "key":{ + "shape":"NamespaceVariableKey", + "documentation":"

    The namespace variable key name.

    " + }, + "validation":{ + "shape":"NamespaceKeyValidation", + "documentation":"

    The validation rules that constrain values for this namespace variable at runtime (CreateEvent API).

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

    A namespace variable key definition with optional NamespaceKeyValidation rules.

    " + }, + "NamespaceKeyValidation":{ + "type":"structure", + "members":{ + "allowedValues":{ + "shape":"NamespaceAllowedValuesList", + "documentation":"

    The allowed values for this namespace variable key.

    " + }, + "regexPattern":{ + "shape":"NamespaceRegexPattern", + "documentation":"

    A regex pattern that the namespace variable key-value must match.

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

    The validation rules for namespace variable values. When you specify multiple rules, the service enforces a logical AND across all provided key-value pairs.

    " + }, + "NamespaceKeysList":{ + "type":"list", + "member":{"shape":"NamespaceKeyEntry"}, + "max":5, + "min":1 + }, + "NamespaceRegexPattern":{ + "type":"string", + "max":64, + "min":1 + }, + "NamespaceVariableKey":{ + "type":"string", + "max":32, + "min":1, + "pattern":"(?!memoryStrategyId$|actorId$|sessionId$)[a-z][a-z0-9]*" }, "NamespacesList":{ "type":"list", @@ -15932,6 +18433,10 @@ "max":128, "min":1 }, + "OAuth2CredentialProviderArn":{ + "type":"string", + "pattern":"arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b|aws-iso-e|aws-iso-f|aws-eusc):bedrock-agentcore:[a-z0-9-]{1,32}:[0-9]{12}:token-vault/[a-zA-Z0-9_-]{1,64}/oauth2credentialprovider/[a-zA-Z0-9_-]{1,128}" + }, "OAuthCredentialProvider":{ "type":"structure", "required":[ @@ -16290,6 +18795,63 @@ "DISABLED" ] }, + "OpenResponsesEvaluatorModelConfig":{ + "type":"structure", + "required":["modelId"], + "members":{ + "modelId":{ + "shape":"ModelId", + "documentation":"

    The identifier of the model to use for evaluation.

    " + }, + "maxOutputTokens":{ + "shape":"OpenResponsesEvaluatorModelConfigMaxOutputTokensInteger", + "documentation":"

    The maximum number of tokens to generate in the model response, including visible output and reasoning tokens.

    " + }, + "temperature":{ + "shape":"OpenResponsesEvaluatorModelConfigTemperatureFloat", + "documentation":"

    The temperature value that controls randomness in the model's responses. Lower values produce more deterministic outputs.

    " + }, + "topP":{ + "shape":"OpenResponsesEvaluatorModelConfigTopPFloat", + "documentation":"

    The top-p sampling parameter that controls the diversity of the model's responses by limiting the cumulative probability of token choices.

    " + }, + "reasoning":{ + "shape":"ReasoningConfiguration", + "documentation":"

    The reasoning configuration for reasoning models. Non-reasoning models ignore this configuration.

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

    The configuration for using models served through the OpenResponses API in evaluator assessments, including model selection and inference parameters.

    " + }, + "OpenResponsesEvaluatorModelConfigMaxOutputTokensInteger":{ + "type":"integer", + "box":true, + "min":1 + }, + "OpenResponsesEvaluatorModelConfigTemperatureFloat":{ + "type":"float", + "box":true, + "max":2, + "min":0 + }, + "OpenResponsesEvaluatorModelConfigTopPFloat":{ + "type":"float", + "box":true, + "max":1, + "min":0 + }, + "OperatingSystem":{ + "type":"string", + "documentation":"

    The operating system and CPU architecture for capacity provider instances.

    ", + "enum":[ + "LINUX_X86_64", + "LINUX_ARM64" + ] + }, + "OptionalLogGroupName":{ + "type":"string", + "documentation":"

    A log group name that may also be empty. The empty string is the @default of members that were relaxed from @required, and carries the meaning "no log group" for that member.

    ", + "pattern":"$|^[.\\-_/#A-Za-z0-9]+" + }, "OutputConfig":{ "type":"structure", "required":["cloudWatchConfig"], @@ -16348,15 +18910,29 @@ "stickinessConfiguration":{ "shape":"StickinessConfiguration", "documentation":"

    The session stickiness configuration for the passthrough target. This configuration routes requests within the same session to the same target.

    " + }, + "staticQueryParameters":{ + "shape":"StaticQueryParameters", + "documentation":"

    A map of static query parameters that the gateway always appends to the outbound URL when forwarding requests to the target. The total outbound URL length, which includes the endpoint and the percent-encoded query parameters, is enforced by the service.

    " + }, + "staticQueryParameterConflictResolution":{ + "shape":"StaticQueryParameterConflictResolution", + "documentation":"

    Controls precedence when a client request supplies a query parameter whose name matches a configured static query parameter. If not set, defaults to CLIENT_OVERRIDE:

    • CLIENT_OVERRIDE - The client-supplied value overrides the configured static value for that parameter name.

    • STATIC_OVERRIDE - The configured static value is retained, overriding the client-supplied value for that parameter name.

    " } }, "documentation":"

    The configuration for an HTTP passthrough target. A passthrough target forwards requests directly to an external HTTP endpoint.

    " }, + "PaymentConnectorAuthorizationUrl":{ + "type":"string", + "max":4096, + "min":1, + "pattern":"https://[^\\p{C}]*" + }, "PaymentConnectorId":{ "type":"string", "max":211, "min":12, - "pattern":"([0-9a-z][-]?){1,100}-[0-9a-z]{10}" + "pattern":"([0-9a-z_][-]?){1,100}-[0-9a-z]{10}" }, "PaymentConnectorName":{ "type":"string", @@ -16364,6 +18940,13 @@ "min":1, "pattern":"[a-zA-Z][a-zA-Z0-9_]{0,47}" }, + "PaymentConnectorProvisionMode":{ + "type":"string", + "enum":[ + "MANUAL", + "QUICK_CREATE" + ] + }, "PaymentConnectorStatus":{ "type":"string", "enum":[ @@ -16373,7 +18956,12 @@ "READY", "CREATE_FAILED", "UPDATE_FAILED", - "DELETE_FAILED" + "DELETE_FAILED", + "AWS_MARKETPLACE_SUBSCRIPTION_REQUIRED", + "PENDING_AUTHENTICATION", + "PROVISIONING", + "AUTHENTICATION_EXPIRED", + "AUTHENTICATION_FAILED" ] }, "PaymentConnectorSummaries":{ @@ -16567,6 +19155,10 @@ "lastUpdatedAt":{ "shape":"DateTimestamp", "documentation":"

    The timestamp when the payment manager was last updated.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key used to encrypt sensitive payment manager data at rest, if configured.

    " } }, "documentation":"

    Contains summary information about a payment manager.

    " @@ -16612,7 +19204,32 @@ "type":"string", "max":4096, "min":1, - "pattern":"[a-zA-Z0-9\\s]+" + "pattern":"[^\\p{C}]*" + }, + "Period":{ + "type":"string", + "documentation":"

    The time period for rate limiting.

    ", + "enum":[ + "second", + "minute" + ] + }, + "PermissionsConfiguration":{ + "type":"structure", + "required":["capacityProviderOperatorRoleArn"], + "members":{ + "capacityProviderOperatorRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that AgentCore assumes to manage the capacity provider, including launching, tagging, and terminating instances and their network interfaces. We recommend scoping this role to the minimum permissions that your workloads require.

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

    The permissions configuration for a capacity provider. This specifies the IAM role that AgentCore uses to manage the Amazon EC2 instances for the capacity provider on your behalf.

    " + }, + "PlatformVersion":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[^\\s]+" }, "Policies":{ "type":"list", @@ -16668,7 +19285,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The Cedar policy statement that defines the access control rules. This contains the actual policy logic used for agent behavior control and access decisions.

    " + "documentation":"

    The Cedar or Dogwood policy statement that defines the access control rules. This contains the actual policy logic used for agent behavior control and access decisions.

    " }, "description":{ "shape":"Description", @@ -16679,7 +19296,7 @@ "documentation":"

    Additional information about the policy status. This provides details about any failures or the current state of the policy lifecycle.

    " } }, - "documentation":"

    Represents a complete policy resource within the AgentCore Policy system. Policies are ARN-able resources that contain Cedar policy statements and associated metadata for controlling agent behavior and access decisions. Each policy belongs to a policy engine and defines fine-grained authorization rules that are evaluated in real-time as agents interact with tools through Gateway. Policies use the Cedar policy language to specify who (principals based on OAuth claims like username, role, or scope) can perform what actions (tool calls) on which resources (Gateways), with optional conditions for attribute-based access control. Multiple policies can apply to a single request, with Cedar's forbid-wins semantics ensuring that security restrictions are never accidentally overridden.

    " + "documentation":"

    Represents a complete policy resource within the AgentCore Policy system. Policies are ARN-able resources that contain Cedar or Dogwood policy statements and associated metadata for controlling agent behavior and access decisions. Each policy belongs to a policy engine and defines fine-grained authorization rules that are evaluated in real-time as agents interact with tools through Gateway. Policies use Cedar or Dogwood to specify who (principals based on OAuth claims like username, role, or scope) can perform what actions (tool calls) on which resources (Gateways), with optional conditions for attribute-based access control. Multiple policies can apply to a single request, with forbid-wins semantics ensuring that security restrictions are never accidentally overridden.

    " }, "PolicyArn":{ "type":"string", @@ -16696,11 +19313,11 @@ }, "policyGeneration":{ "shape":"PolicyGenerationDetails", - "documentation":"

    The generated policy asset information within the policy definition structure. This contains information identifying a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Cedar policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " + "documentation":"

    The generated policy asset information within the policy definition structure. This contains information identifying a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Dogwood policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " }, "policy":{ "shape":"PolicyStatement", - "documentation":"

    An AgentCore policy statement that defines the access control rules. The statement can be a Cedar policy or a guardrails definition.

    " + "documentation":"

    The Dogwood policy statement that defines the access control rules. This policy definition can include Dogwood policies and supports temporal conditions and information providers such as guardrails.

    " } }, "documentation":"

    Represents the definition structure for policies within the AgentCore Policy system. This structure encapsulates different policy formats and languages that can be used to define access control rules.

    ", @@ -16890,7 +19507,7 @@ "documentation":"

    Additional information about the generation status.

    " } }, - "documentation":"

    Represents a policy generation request within the AgentCore Policy system. Tracks the AI-powered conversion of natural language descriptions into Cedar policy statements, enabling users to author policies by describing authorization requirements in plain English. The generation process analyzes the natural language input along with the Gateway's tool context and Cedar schema to produce one or more validated policy options. Each generation request tracks the status of the conversion process and maintains findings about the generated policies, including validation results and potential issues. Generated policy assets remain available for one week after successful generation, allowing time to review and create policies from the generated options.

    " + "documentation":"

    Represents a policy generation request within the AgentCore Policy system. Tracks the AI-powered conversion of natural language descriptions into Dogwood policy statements, enabling users to author policies by describing authorization requirements in plain English. The generation process analyzes the natural language input along with the Gateway's tool context and Cedar schema to produce one or more validated policy options. Each generation request tracks the status of the conversion process and maintains findings about the generated policies, including validation results and potential issues. Generated policy assets remain available for one week after successful generation, allowing time to review and create policies from the generated options.

    " }, "PolicyGenerationArn":{ "type":"string", @@ -16913,14 +19530,14 @@ "definition":{"shape":"PolicyDefinition"}, "rawTextFragment":{ "shape":"NaturalLanguage", - "documentation":"

    The portion of the original natural language input that this generated policy asset addresses. This helps users understand which part of their policy description was translated into this specific Cedar policy statement, enabling better policy selection and refinement. When a single natural language input describes multiple authorization requirements, the generation process creates separate policy assets for each requirement, with each asset's rawTextFragment showing which requirement it addresses. Use this mapping to verify that all parts of your natural language input were correctly translated into Cedar policies.

    " + "documentation":"

    The portion of the original natural language input that this generated policy asset addresses. This helps users understand which part of their policy description was translated into this specific Dogwood policy statement, enabling better policy selection and refinement. When a single natural language input describes multiple authorization requirements, the generation process creates separate policy assets for each requirement, with each asset's rawTextFragment showing which requirement it addresses. Use this mapping to verify that all parts of your natural language input were correctly translated into Dogwood policies.

    " }, "findings":{ "shape":"Findings", "documentation":"

    Analysis findings and insights related to this specific generated policy asset. These findings may include validation results, potential issues, or recommendations for improvement to help users evaluate the quality and appropriateness of the generated policy.

    " } }, - "documentation":"

    Represents a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Cedar policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " + "documentation":"

    Represents a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Dogwood policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " }, "PolicyGenerationAssets":{ "type":"list", @@ -16942,7 +19559,7 @@ "documentation":"

    The unique identifier for this generated policy asset within the policy generation request.

    " } }, - "documentation":"

    Represents the information identifying a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Cedar policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " + "documentation":"

    Represents the information identifying a generated policy asset from the AI-powered policy generation process within the AgentCore Policy system. Each asset contains a Dogwood policy statement generated from natural language input, along with associated metadata and analysis findings to help users evaluate and select the most appropriate policy option.

    " }, "PolicyGenerationName":{ "type":"string", @@ -17035,10 +19652,10 @@ "members":{ "statement":{ "shape":"Statement", - "documentation":"

    The body of the AgentCore policy statement. Contains the policy logic, which can be a Cedar policy or a guardrails definition.

    " + "documentation":"

    The body of the AgentCore Cedar or Dogwood policy statement. Contains the policy logic, which can be a Cedar policy, a temporal policy, or a guardrails definition.

    " } }, - "documentation":"

    An AgentCore policy statement, which supports plain Cedar policies as well as guardrails definitions.

    " + "documentation":"

    An AgentCore Cedar or Dogwood policy statement, which supports plain Cedar policies, temporal policies, and guardrails definitions.

    " }, "PolicyStatus":{ "type":"string", @@ -17116,6 +19733,11 @@ "IGNORE_ALL_FINDINGS" ] }, + "PortalUrlType":{ + "type":"string", + "max":2000, + "min":1 + }, "PrincipalMatchOperator":{ "type":"string", "enum":[ @@ -17172,6 +19794,39 @@ "max":5, "min":0 }, + "PrivateKeyJwtConfig":{ + "type":"structure", + "members":{ + "privateKeySource":{ + "shape":"PrivateKeySource", + "documentation":"

    The private key source for the JWT client assertion.

    " + }, + "signingAlgorithm":{ + "shape":"SigningAlgorithm", + "documentation":"

    The algorithm used to sign the JWT client assertion. Valid values are RS256, PS256, and ES256.

    " + }, + "additionalHeaderClaims":{ + "shape":"AdditionalClaims", + "documentation":"

    A map of additional claims to include in the JWT client assertion header. Standard header claims such as alg and typ cannot be added.

    " + }, + "additionalPayloadClaims":{ + "shape":"AdditionalClaims", + "documentation":"

    A map of additional claims to include in the JWT client assertion payload. Payload claims generated by the service, such as iss, sub, jti, and exp, cannot be added.

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

    The private key configuration for private_key_jwt client authentication.

    " + }, + "PrivateKeySource":{ + "type":"structure", + "members":{ + "kmsKeySource":{ + "shape":"KmsKeySourceType", + "documentation":"

    The KMS key source for the JWT client assertion.

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

    Contains the private key source configuration for a JWT client assertion.

    ", + "union":true + }, "Prompt":{ "type":"string", "max":30000, @@ -17189,6 +19844,15 @@ }, "documentation":"

    The protocol configuration for an agent runtime. This structure defines how the agent runtime communicates with clients.

    " }, + "Provider":{ + "type":"string", + "enum":[ + "AWS", + "DeepEval", + "AutoEval", + "Custom" + ] + }, "ProviderPrefix":{ "type":"structure", "members":{ @@ -17237,6 +19901,37 @@ } } }, + "RateConfig":{ + "type":"structure", + "required":[ + "rate", + "period" + ], + "members":{ + "rate":{ + "shape":"RateConfigRateDouble", + "documentation":"

    The rate value for the limit. For request limits, this is the number of requests allowed per period. For token limits, this is the number of tokens allowed per period. For connection limits, this is the number of concurrent connections allowed.

    " + }, + "period":{ + "shape":"Period", + "documentation":"

    The time period for the rate limit. Valid values:

    • second—Measures the rate limit over a one-second window.

    • minute—Measures the rate limit over a one-minute window.

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

    Contains the rate configuration for a rate limit metric, specifying the allowed rate and time period.

    " + }, + "RateConfigRateDouble":{ + "type":"double", + "box":true, + "max":10000000, + "min":0 + }, + "RateConfigs":{ + "type":"list", + "member":{"shape":"RateConfig"}, + "documentation":"

    A list of rate configurations for the limit. Currently supports one entry per limit.

    ", + "max":1, + "min":1 + }, "RatingScale":{ "type":"structure", "members":{ @@ -17253,6 +19948,21 @@ "sensitive":true, "union":true }, + "ReasoningConfiguration":{ + "type":"structure", + "members":{ + "effort":{ + "shape":"ReasoningConfigurationEffortString", + "documentation":"

    The level of reasoning effort the model applies when generating a response. For supported values, see the model provider's documentation.

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

    The reasoning configuration that controls how a reasoning model allocates effort during evaluation.

    " + }, + "ReasoningConfigurationEffortString":{ + "type":"string", + "max":64, + "min":1 + }, "RecordIdentifier":{ "type":"string", "max":2048, @@ -17700,12 +20410,76 @@ "type":"list", "member":{"shape":"RestApiMethod"} }, + "ResultDestination":{ + "type":"string", + "documentation":"

    Where evaluation results are written: dedicated results log group (default) or the source log group.

    ", + "enum":[ + "DEDICATED_LOG_GROUP", + "SOURCE_LOG_GROUP" + ] + }, + "RetryableConflictException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The operation failed because of a conflicting request. Retry the request.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true, + "retryable":{"throttling":false} + }, "RoleArn":{ "type":"string", "max":2048, "min":1, "pattern":"arn:aws(-[^:]+)?:iam::([0-9]{12})?:role/.+" }, + "RootVolumeConfiguration":{ + "type":"structure", + "members":{ + "volumeType":{ + "shape":"EbsVolumeType", + "documentation":"

    The Amazon EBS volume type. If you do not specify a type, the default is gp3.

    " + }, + "iops":{ + "shape":"VolumeIops", + "documentation":"

    The number of IOPS to provision. For gp3, io1, and io2 volumes, this is the number of IOPS provisioned for the volume. For gp2 volumes, this sets the baseline IOPS performance. It also controls the rate at which the volume accumulates I/O credits for bursting. Supported values: gp3, 3,000–80,000; io1, 100–64,000; io2, 100–256,000.

    " + }, + "throughput":{ + "shape":"RootVolumeConfigurationThroughputInteger", + "documentation":"

    The throughput to provision, in MiB/s. Valid only for gp3 volumes. Valid range: 125–2,000 MiB/s.

    " + }, + "encrypted":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to encrypt the volume. Encrypted volumes can be attached only to instances that support Amazon EBS encryption. If you create a volume from a snapshot, you cannot specify an encryption value.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The identifier (key ID, key alias, key ARN, or alias ARN) of the customer managed KMS key to use for Amazon EBS encryption.

    " + }, + "freeSpaceGiB":{ + "shape":"RootVolumeConfigurationFreeSpaceGiBInteger", + "documentation":"

    The free space guaranteed on the root volume, in GiB. AgentCore adds the operating system overhead on top of this value. The default is 8 GiB.

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

    The configuration for the root volume of a capacity provider instance. Specify the amount of free space to guarantee on the root volume. The device name and delete-on-termination settings are fixed and cannot be changed.

    " + }, + "RootVolumeConfigurationFreeSpaceGiBInteger":{ + "type":"integer", + "box":true, + "max":65000, + "min":2 + }, + "RootVolumeConfigurationThroughputInteger":{ + "type":"integer", + "box":true, + "max":2000, + "min":125 + }, "RouteToTargetAction":{ "type":"structure", "members":{ @@ -17813,23 +20587,53 @@ "min":0, "pattern":"arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}/access-point/fsap-[0-9a-f]{17,40}" }, - "S3FilesAccessPointConfiguration":{ + "S3FilesAccessPointConfiguration":{ + "type":"structure", + "required":[ + "accessPointArn", + "mountPath" + ], + "members":{ + "accessPointArn":{ + "shape":"S3FilesAccessPointArn", + "documentation":"

    The ARN of the S3 Files access point to mount into the AgentCore Runtime.

    " + }, + "mountPath":{ + "shape":"MountPath", + "documentation":"

    The mount path for the S3 Files access point inside the AgentCore Runtime. The path must be under /mnt with exactly one subdirectory level (for example, /mnt/data).

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

    Configuration for an Amazon S3 Files access point filesystem mounted into the AgentCore Runtime. S3 Files access points provide shared file storage accessible from your AgentCore Runtime sessions.

    " + }, + "S3FilesConfiguration":{ "type":"structure", "required":[ "accessPointArn", - "mountPath" + "mountPath", + "fileSystemArn" ], "members":{ "accessPointArn":{ "shape":"S3FilesAccessPointArn", - "documentation":"

    The ARN of the S3 Files access point to mount into the AgentCore Runtime.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Simple Storage Service (Amazon S3) Files access point to mount.

    " }, "mountPath":{ "shape":"MountPath", - "documentation":"

    The mount path for the S3 Files access point inside the AgentCore Runtime. The path must be under /mnt with exactly one subdirectory level (for example, /mnt/data).

    " + "documentation":"

    The absolute path within the session at which the access point is mounted, for example /mnt/s3data. Each mount path must be unique across all file system configurations in the session.

    " + }, + "fileSystemArn":{ + "shape":"S3FilesFileSystemArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Simple Storage Service (Amazon S3) Files file system that owns the access point.

    " } }, - "documentation":"

    Configuration for an Amazon S3 Files access point filesystem mounted into the AgentCore Runtime. S3 Files access points provide shared file storage accessible from your AgentCore Runtime sessions.

    " + "documentation":"

    The configuration for mounting an Amazon Simple Storage Service (Amazon S3) Files access point that you own into a session.

    " + }, + "S3FilesFileSystemArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Simple Storage Service (Amazon S3) Files file system. The access points you specify must belong to this file system.

    ", + "max":256, + "min":0, + "pattern":"arn:aws[-a-z]*:s3files:[a-z0-9-]+:[0-9]{12}:file-system/fs-[0-9a-f]{17,40}" }, "S3Location":{ "type":"structure", @@ -17883,6 +20687,12 @@ "documentation":"

    Amazon S3 URI string in the format s3://bucket/key.

    ", "pattern":"s3://[a-z0-9][a-z0-9.\\-]{1,61}[a-z0-9]/.{1,1024}" }, + "SSHKeyName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[!-~][ -~]*[!-~]$|^[!-~]" + }, "SalesforceOauth2ProviderConfigInput":{ "type":"structure", "required":["clientId"], @@ -18403,6 +21213,14 @@ } } }, + "SigningAlgorithm":{ + "type":"string", + "enum":[ + "RS256", + "PS256", + "ES256" + ] + }, "SkillDefinition":{ "type":"structure", "members":{ @@ -18486,7 +21304,7 @@ }, "content":{ "shape":"Content", - "documentation":"

    The natural language description of the desired policy behavior. This content is processed by AI to generate corresponding Cedar policy statements that match the described intent.

    " + "documentation":"

    The natural language description of the desired policy behavior. This content is processed by AI to generate corresponding Dogwood policy statements that match the described intent.

    " }, "name":{ "shape":"PolicyGenerationName", @@ -18582,6 +21400,33 @@ "type":"string", "pattern":"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" }, + "StaticQueryParameterConflictResolution":{ + "type":"string", + "documentation":"

    The precedence used when a client-supplied query parameter has the same name as a configured static query parameter:

    • CLIENT_OVERRIDE - The client-supplied value overrides the configured static value for that parameter name. This is the default.

    • STATIC_OVERRIDE - The configured static value is retained, overriding the client-supplied value for that parameter name.

    ", + "enum":[ + "CLIENT_OVERRIDE", + "STATIC_OVERRIDE" + ] + }, + "StaticQueryParameterName":{ + "type":"string", + "documentation":"

    The name of a static query parameter. Allowed characters are letters, digits, _, ., and -.

    ", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9_.-]+" + }, + "StaticQueryParameterValue":{ + "type":"string", + "documentation":"

    The value of a static query parameter. Control characters (ASCII 0x00-0x1F and 0x7F) are not permitted. URI-reserved characters are allowed and are percent-encoded by the gateway. Empty values are allowed.

    ", + "pattern":"[^\\x00-\\x1F\\x7F]*", + "sensitive":true + }, + "StaticQueryParameters":{ + "type":"map", + "key":{"shape":"StaticQueryParameterName"}, + "value":{"shape":"StaticQueryParameterValue"}, + "documentation":"

    A map of static query parameter names to values that the gateway always appends to the outbound URL. The total outbound URL length, which includes the endpoint and the percent-encoded query parameters, is enforced by the service.

    " + }, "StaticRoute":{ "type":"structure", "required":["targetName"], @@ -18610,6 +21455,11 @@ "max":2048, "min":0 }, + "StatusReasonType":{ + "type":"string", + "max":1024, + "min":1 + }, "StatusReasons":{ "type":"list", "member":{"shape":"StatusReason"}, @@ -18627,6 +21477,10 @@ "timeout":{ "shape":"StickinessTimeout", "documentation":"

    The session stickiness timeout, in seconds. After this duration of inactivity, the session affinity expires. Valid values range from 1 to 86400.

    " + }, + "compositeIdentifier":{ + "shape":"CompositeIdentifierList", + "documentation":"

    Additional headers to include in session affinity routing. When set, requests are only considered part of the same session if both the identifier and all composite identifier values match.

    " } }, "documentation":"

    The configuration for session-sticky routing to a target. Session stickiness routes requests that share a session identifier to the same target.

    " @@ -18897,6 +21751,27 @@ "max":16, "min":1 }, + "SubscriptionRequiredException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "subscriptionUrl":{ + "shape":"String", + "documentation":"

    URL to the Marketplace listing for subscription

    " + }, + "productName":{ + "shape":"String", + "documentation":"

    The product requiring subscription

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

    The request failed because it requires an active Amazon Web Services Marketplace subscription that is not present. Subscribe to the required product in Amazon Web Services Marketplace and try again.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, "SummaryConsolidationOverride":{ "type":"structure", "required":[ @@ -19284,7 +22159,8 @@ "CONNECTOR", "AGENTCORE_RUNTIME", "PASSTHROUGH", - "PROVIDER" + "PROVIDER", + "HTTP_CONNECTOR" ] }, "Temperature":{ @@ -19473,6 +22349,28 @@ }, "documentation":"

    The tools definition for an MCP descriptor. Contains the protocol version and inline content describing the available tools.

    " }, + "ToolsFileSystemConfiguration":{ + "type":"structure", + "members":{ + "s3FilesConfiguration":{ + "shape":"S3FilesConfiguration", + "documentation":"

    The configuration for mounting your own Amazon Simple Storage Service (Amazon S3) Files access point into the session.

    " + }, + "efsConfiguration":{ + "shape":"EfsConfiguration", + "documentation":"

    The configuration for mounting your own Amazon Elastic File System (Amazon EFS) access point into the session.

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

    Specifies a file system to mount into the session by providing exactly one of the following:

    • s3FilesConfiguration - Mounts an Amazon Simple Storage Service (Amazon S3) Files access point.

    • efsConfiguration - Mounts an Amazon Elastic File System (Amazon EFS) access point.

    ", + "union":true + }, + "ToolsFileSystemConfigurations":{ + "type":"list", + "member":{"shape":"ToolsFileSystemConfiguration"}, + "documentation":"

    The file system configurations to mount into the session. Each configuration maps an access point to a path inside the session. You can specify up to 4 configurations. The maximum is 2 Amazon Simple Storage Service (Amazon S3) Files access points and 2 Amazon Elastic File System (Amazon EFS) access points.

    ", + "max":10, + "min":0 + }, "TopK":{ "type":"integer", "box":true, @@ -19724,8 +22622,7 @@ "required":[ "agentRuntimeId", "agentRuntimeArtifact", - "roleArn", - "networkConfiguration" + "roleArn" ], "members":{ "agentRuntimeId":{ @@ -19775,6 +22672,14 @@ "shape":"FilesystemConfigurations", "documentation":"

    The updated filesystem configurations to mount into the AgentCore Runtime.

    " }, + "capacityProviderConfiguration":{ + "shape":"CapacityProviderConfiguration", + "documentation":"

    The updated capacity provider configuration for the AgentCore Runtime.

    " + }, + "platformVersion":{ + "shape":"PlatformVersion", + "documentation":"

    The updated version of the runtime platform to use for the AgentCore Runtime.

    " + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure idempotency of the request.

    ", @@ -19885,9 +22790,70 @@ } } }, + "UpdateCapacityProviderInput":{ + "type":"structure", + "required":["capacityProviderId"], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider to update.

    ", + "location":"uri", + "locationName":"capacityProviderId" + }, + "description":{ + "shape":"UpdatedDescription", + "documentation":"

    The updated description of the capacity provider.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + } + } + }, + "UpdateCapacityProviderOutput":{ + "type":"structure", + "required":[ + "capacityProviderId", + "capacityProviderArn", + "name", + "status", + "createdAt", + "lastUpdatedAt" + ], + "members":{ + "capacityProviderId":{ + "shape":"CapacityProviderId", + "documentation":"

    The unique identifier of the capacity provider.

    " + }, + "capacityProviderArn":{ + "shape":"CapacityProviderArn", + "documentation":"

    The Amazon Resource Name (ARN) of the capacity provider.

    " + }, + "name":{ + "shape":"CapacityProviderName", + "documentation":"

    The name of the capacity provider.

    " + }, + "status":{ + "shape":"CapacityProviderStatus", + "documentation":"

    The current status of the capacity provider. For possible values, see CapacityProviderStatus.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the capacity provider was created.

    " + }, + "lastUpdatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the capacity provider was last updated.

    " + } + } + }, "UpdateConfigurationBundleRequest":{ "type":"structure", - "required":["bundleId"], + "required":[ + "bundleId", + "parentVersionIds" + ], "members":{ "clientToken":{ "shape":"ClientToken", @@ -19966,6 +22932,92 @@ } } }, + "UpdateConsentPortalRequest":{ + "type":"structure", + "required":["consentPortalIdentifier"], + "members":{ + "consentPortalIdentifier":{ + "shape":"ConsentPortalIdentifier", + "documentation":"

    The identifier of the consent portal. You can specify either the consent portal ID or its Amazon Resource Name (ARN).

    " + }, + "executionRoleArn":{ + "shape":"ExecutionRoleArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that the consent portal assumes to access the resources defined in its sources.

    " + }, + "idpConfig":{ + "shape":"ConsentPortalIdpConfig", + "documentation":"

    The identity provider configuration that the consent portal uses to authenticate end users.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + } + } + }, + "UpdateConsentPortalResponse":{ + "type":"structure", + "required":[ + "sources", + "consentPortalArn", + "consentPortalId", + "createdAt", + "executionRoleArn", + "idpConfig", + "name", + "status", + "updatedAt" + ], + "members":{ + "sources":{ + "shape":"ConsentPortalSources", + "documentation":"

    The resources served by the consent portal.

    " + }, + "consentPortalArn":{ + "shape":"ConsentPortalArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the consent portal.

    " + }, + "consentPortalId":{ + "shape":"ConsentPortalIdType", + "documentation":"

    The unique identifier of the consent portal.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was created.

    " + }, + "description":{ + "shape":"ConsentPortalDescriptionType", + "documentation":"

    The description of the consent portal.

    " + }, + "executionRoleArn":{ + "shape":"ExecutionRoleArnType", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that the consent portal assumes to access the resources defined in its sources.

    " + }, + "idpConfig":{ + "shape":"ConsentPortalIdpConfig", + "documentation":"

    The identity provider configuration that the consent portal uses to authenticate end users.

    " + }, + "name":{ + "shape":"ConsentPortalNameType", + "documentation":"

    The name of the consent portal.

    " + }, + "portalUrl":{ + "shape":"PortalUrlType", + "documentation":"

    The URL used to access the consent portal.

    " + }, + "status":{ + "shape":"ConsentPortalStatus", + "documentation":"

    The current status of the consent portal.

    " + }, + "statusReason":{ + "shape":"StatusReasonType", + "documentation":"

    A message that provides additional information about the current status of the consent portal.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the consent portal was last updated.

    " + } + } + }, "UpdateDatasetExamplesRequest":{ "type":"structure", "required":[ @@ -20137,6 +23189,83 @@ } } }, + "UpdateGatewayRateLimitRequest":{ + "type":"structure", + "required":[ + "gatewayIdentifier", + "rateLimitId", + "entries" + ], + "members":{ + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    ", + "location":"uri", + "locationName":"gatewayIdentifier" + }, + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit to update.

    ", + "location":"uri", + "locationName":"rateLimitId" + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    The updated human-readable description for this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The updated rule entries. The dimension keys are immutable after creation and cannot be changed.

    " + } + } + }, + "UpdateGatewayRateLimitResponse":{ + "type":"structure", + "required":[ + "rateLimitId", + "gatewayIdentifier", + "dimensionKeys", + "entries", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "rateLimitId":{ + "shape":"GatewayRateLimitId", + "documentation":"

    The unique identifier of the rate limit.

    " + }, + "gatewayIdentifier":{ + "shape":"GatewayIdentifier", + "documentation":"

    The unique identifier of the gateway.

    " + }, + "description":{ + "shape":"GatewayRateLimitDescription", + "documentation":"

    The human-readable description of the rate limit.

    " + }, + "dimensionKeys":{ + "shape":"DimensionKeys", + "documentation":"

    The ordered list of dimension key names that define the scope of this rate limit.

    " + }, + "entries":{ + "shape":"LimitEntries", + "documentation":"

    The list of rule entries that map dimension values to rate configurations.

    " + }, + "status":{ + "shape":"GatewayRateLimitStatus", + "documentation":"

    The current status of the rate limit.

    " + }, + "createdAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was created.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The timestamp when the rate limit was last updated.

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

    Shared fields for GatewayRateLimit responses.

    " + }, "UpdateGatewayRequest":{ "type":"structure", "required":[ @@ -20616,6 +23745,10 @@ "shape":"HarnessTruncationConfiguration", "documentation":"

    The truncation configuration for managing conversation context. If not specified, the existing value is retained.

    " }, + "hooks":{ + "shape":"HarnessHooks", + "documentation":"

    The lifecycle hooks to run at defined points in the agent loop. If specified, this replaces all existing hooks. If not specified, the existing hooks are retained.

    " + }, "maxIterations":{ "shape":"Integer", "documentation":"

    The maximum number of iterations the agent loop can execute per invocation. If not specified, the existing value is retained.

    " @@ -20675,6 +23808,10 @@ "shape":"IndexedKeysList", "documentation":"

    Additional metadata keys to index. Previously indexed keys cannot be removed.

    " }, + "namespaceKeys":{ + "shape":"NamespaceKeysList", + "documentation":"

    The namespace variable key definitions with validation rules for this memory. This value fully replaces the existing set — any key you omit is removed. Any referenced namespaceKey omission will throw ValidationException.

    " + }, "streamDeliveryResources":{ "shape":"StreamDeliveryResources", "documentation":"

    Configuration for streaming memory record data to external resources.

    " @@ -20820,6 +23957,7 @@ "shape":"ClusteringConfig", "documentation":"

    The updated clustering configuration for periodic batch evaluation.

    " }, + "outputConfig":{"shape":"OutputConfig"}, "evaluationExecutionRoleArn":{ "shape":"RoleArn", "documentation":"

    The updated Amazon Resource Name (ARN) of the IAM role used for evaluation execution.

    " @@ -20943,6 +24081,10 @@ "status":{ "shape":"PaymentConnectorStatus", "documentation":"

    The current status of the updated payment connector. Possible values include CREATING, READY, UPDATING, DELETING, CREATE_FAILED, UPDATE_FAILED, and DELETE_FAILED.

    " + }, + "authorizationUrl":{ + "shape":"PaymentConnectorAuthorizationUrl", + "documentation":"

    The URL that the user must open to complete OAuth consent. This field is only present when the payment connector status is PENDING_AUTHENTICATION.

    " } } }, @@ -21035,6 +24177,10 @@ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier to ensure that the API request completes no more than one time. If you don't specify this field, a value is randomly generated for you. If this token matches a previous request, the service ignores the request, but doesn't return an error. For more information, see Ensuring idempotency.

    ", "idempotencyToken":true + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The updated Amazon Resource Name (ARN) of the customer managed KMS key used to encrypt sensitive payment manager data at rest.

    " } } }, @@ -21078,6 +24224,10 @@ "status":{ "shape":"PaymentManagerStatus", "documentation":"

    The current status of the updated payment manager. Possible values include CREATING, READY, UPDATING, DELETING, CREATE_FAILED, UPDATE_FAILED, and DELETE_FAILED.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key used to encrypt sensitive payment manager data at rest, if configured.

    " } } }, @@ -21172,7 +24322,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The new Cedar policy statement that defines the access control rules. This replaces the existing policy definition with new logic while maintaining the policy's identity.

    " + "documentation":"

    The new Cedar or Dogwood policy statement that defines the access control rules. This replaces the existing policy definition with new logic while maintaining the policy's identity.

    " }, "validationMode":{ "shape":"PolicyValidationMode", @@ -21232,7 +24382,7 @@ }, "definition":{ "shape":"PolicyDefinition", - "documentation":"

    The updated Cedar policy statement.

    " + "documentation":"

    The updated Cedar or Dogwood policy statement.

    " }, "description":{ "shape":"Description", @@ -22018,6 +25168,53 @@ "max":500, "min":1 }, + "VirtualDeviceName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"ephemeral[0-9]+" + }, + "VolumeConfiguration":{ + "type":"structure", + "members":{ + "ebsConfiguration":{ + "shape":"EbsVolumeConfiguration", + "documentation":"

    The configuration for an Amazon EBS-backed persistent volume.

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

    The configuration for a persistent volume attached to a capacity provider. This structure defines the storage backing for the persistent volumes used by agents that run on capacity provider instances.

    ", + "union":true + }, + "VolumeConfigurationList":{ + "type":"list", + "member":{"shape":"VolumeConfiguration"}, + "max":5, + "min":0 + }, + "VolumeIops":{ + "type":"integer", + "box":true, + "max":256000, + "min":100 + }, + "VolumeName":{ + "type":"string", + "max":48, + "min":1, + "pattern":"[a-zA-Z][a-zA-Z0-9_-]{0,47}" + }, + "VolumeSizeGiB":{ + "type":"integer", + "box":true, + "max":65536, + "min":1 + }, + "VolumeThroughput":{ + "type":"integer", + "box":true, + "max":2000, + "min":125 + }, "VpcConfig":{ "type":"structure", "required":[ @@ -22040,6 +25237,36 @@ }, "documentation":"

    VpcConfig for the Agent.

    " }, + "VpcConfiguration":{ + "type":"structure", + "required":[ + "subnets", + "securityGroups" + ], + "members":{ + "subnets":{ + "shape":"VpcConfigurationSubnetsList", + "documentation":"

    The IDs of the subnets in which to launch instances. You must specify at least one subnet.

    " + }, + "securityGroups":{ + "shape":"VpcConfigurationSecurityGroupsList", + "documentation":"

    The IDs of the security groups to associate with the instances. You must specify at least one security group.

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

    The VPC configuration for launching Amazon EC2 instances.

    " + }, + "VpcConfigurationSecurityGroupsList":{ + "type":"list", + "member":{"shape":"SecurityGroupId"}, + "max":16, + "min":1 + }, + "VpcConfigurationSubnetsList":{ + "type":"list", + "member":{"shape":"SubnetId"}, + "max":16, + "min":1 + }, "VpcIdentifier":{ "type":"string", "pattern":"vpc-(([0-9a-z]{8})|([0-9a-z]{17}))" diff --git a/services/bedrockagentruntime/pom.xml b/services/bedrockagentruntime/pom.xml index 634f2b099afe..b0ddee000403 100644 --- a/services/bedrockagentruntime/pom.xml +++ b/services/bedrockagentruntime/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockagentruntime AWS Java SDK :: Services :: Bedrock Agent Runtime diff --git a/services/bedrockagentruntime/src/main/resources/codegen-resources/customization.config b/services/bedrockagentruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/bedrockagentruntime/src/main/resources/codegen-resources/customization.config +++ b/services/bedrockagentruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..230ccd64c166 --- /dev/null +++ b/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-agent-runtime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bf251bce1f4e..000000000000 --- a/services/bedrockagentruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-agent-runtime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file 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 9b8e530740e1..40c2a0dcffc8 100644 --- a/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json @@ -36,6 +36,24 @@ ], "documentation":"

    Retrieves information from one or more knowledge bases using an agentic approach. Agentic retrieval uses a foundation model to intelligently decompose complex queries into sub-queries and iteratively retrieve relevant information from your knowledge bases. This approach improves retrieval accuracy for complex, multi-step questions that a single retrieval pass might not fully address.

    The operation returns results through a stream that includes retrieval results, trace events for visibility into the process, and a generated response synthesized from the results by default, which can be turned off.

    " }, + "CheckIngestedDocumentAcl":{ + "name":"CheckIngestedDocumentAcl", + "http":{ + "method":"POST", + "requestUri":"/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/check-ingested-document-acl", + "responseCode":200 + }, + "input":{"shape":"CheckIngestedDocumentAclRequest"}, + "output":{"shape":"CheckIngestedDocumentAclResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Checks whether a user has access to a specific document by verifying against the ingested access control list (ACL) in a knowledge base. Use this operation to validate that document-level access control is working as expected after ingestion. To use this operation, you must have the bedrock:CheckIngestedDocumentAcl permission.

    " + }, "CreateInvocation":{ "name":"CreateInvocation", "http":{ @@ -238,6 +256,24 @@ ], "documentation":"

    Retrieves details about a specific flow execution, including its status, start and end times, and any errors that occurred during execution.

    " }, + "GetIngestedDocumentAcl":{ + "name":"GetIngestedDocumentAcl", + "http":{ + "method":"POST", + "requestUri":"/knowledgebases/{knowledgeBaseId}/datasources/{dataSourceId}/get-ingested-document-acl", + "responseCode":200 + }, + "input":{"shape":"GetIngestedDocumentAclRequest"}, + "output":{"shape":"GetIngestedDocumentAclResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Retrieves the ingested access control list (ACL) for a specific document in a knowledge base. Use this operation to inspect the allow and deny lists that were ingested for a document to troubleshoot access control issues. To use this operation, you must have the bedrock:GetIngestedDocumentAcl permission.

    " + }, "GetInvocationStep":{ "name":"GetInvocationStep", "http":{ @@ -295,7 +331,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], - "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.

    • 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.

    " + "documentation":"

    Amazon Bedrock Agents (now Amazon Bedrock Agents Classic) is no longer open to new customers. For capabilities similar to Bedrock Agents Classic, explore Amazon Bedrock AgentCore. Existing customers can continue to use the service as normal. For more information, see Amazon Bedrock Agents Classic availability change.

    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.

    • 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", @@ -974,6 +1010,27 @@ "type":"string", "sensitive":true }, + "AgentCoreMemoryActorId":{ + "type":"string", + "documentation":"

    The identifier of an end user or agent that a session belongs to. This value scopes session history so that one actor's history is never returned for another.

    ", + "max":255, + "min":1, + "pattern":"^[a-zA-Z0-9][a-zA-Z0-9\\-_/]*(?::[a-zA-Z0-9\\-_/]+)*[a-zA-Z0-9\\-_/]*$" + }, + "AgentCoreMemoryId":{ + "type":"string", + "documentation":"

    The identifier of an AgentCore Memory resource used with this retrieval.

    ", + "max":111, + "min":12, + "pattern":"^[a-zA-Z][a-zA-Z0-9\\-_]{0,99}-[a-zA-Z0-9]{10}$" + }, + "AgentCoreMemorySessionId":{ + "type":"string", + "documentation":"

    The identifier of a session in an AgentCore Memory resource.

    ", + "max":100, + "min":1, + "pattern":"^[a-zA-Z0-9][a-zA-Z0-9\\-_]*$" + }, "AgentId":{ "type":"string", "max":10, @@ -997,6 +1054,10 @@ "shape":"AgenticRetrieveFullDocExpansionDetails", "documentation":"

    Details of a full document expansion action.

    " }, + "memoryRetrieve":{ + "shape":"AgenticRetrieveMemoryRetrieveDetails", + "documentation":"

    The details of a long-term memory retrieval that the agent chose to perform.

    " + }, "retrieve":{ "shape":"AgenticRetrieveActionDetails", "documentation":"

    Details of the retrieve action.

    " @@ -1233,6 +1294,235 @@ }, "documentation":"

    A warning generated by a guardrail during agentic retrieval.

    " }, + "AgenticRetrieveMemoryConfiguration":{ + "type":"structure", + "required":["memoryId"], + "members":{ + "memoryId":{ + "shape":"AgentCoreMemoryId", + "documentation":"

    The identifier of the AgentCore Memory resource to use. The resource must exist in your account and be in the ACTIVE state.

    " + }, + "persistenceMode":{ + "shape":"AgenticRetrieveMemoryPersistenceMode", + "documentation":"

    Specifies whether the agent-generated answer is written back to the given short-term memory session, and applies only when sessionBinding is set. Valid values:

    • DEFAULT (default) – Specifies that the question and the agent-generated answer are persisted to the session as a single event. This value requires generateResponse to be true.

    • NONE – Specifies that the session is left unchanged.

    " + }, + "retrievalConfigs":{ + "shape":"AgenticRetrieveMemoryRetrievalConfigList", + "documentation":"

    Specifies the long-term memory configuration the agent can retrieve from. The agent decides whether to retrieve and composes its own query. This field currently accepts at most one entry.

    " + }, + "sessionBinding":{ + "shape":"AgenticRetrieveMemorySessionBinding", + "documentation":"

    The short-term memory session whose history is restored for this retrieval. To persist the agent-generated answer to the session, omit persistenceMode or set it to DEFAULT. To leave the session unchanged, set persistenceMode to NONE. Supply session history through the existing messages parameter or through short-term memory, but not both.

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

    Specifies an AgentCore Memory resource and how this retrieval uses it. Set sessionBinding to restore and continue a session. Set retrievalConfigs to let the agent retrieve from long-term memory. You must specify at least one of the two.

    " + }, + "AgenticRetrieveMemoryMetadataFilter":{ + "type":"structure", + "required":[ + "left", + "operator" + ], + "members":{ + "left":{ + "shape":"AgenticRetrieveMemoryMetadataFilterLeft", + "documentation":"

    The metadata key that the expression evaluates.

    " + }, + "operator":{ + "shape":"AgenticRetrieveMemoryMetadataFilterOperator", + "documentation":"

    The relationship that the metadata key and value must have for a memory record to match.

    " + }, + "right":{ + "shape":"AgenticRetrieveMemoryMetadataFilterRight", + "documentation":"

    The value that the expression compares the metadata key against. Supply this value for every operator except EXISTS and NOT_EXISTS.

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

    A metadata filter expression, in the form accepted by the AgentCore Memory RetrieveMemoryRecords operation. The expression has a left operand that names the metadata key, an operator, and a right operand. For the EXISTS and NOT_EXISTS operators, omit the right operand.

    " + }, + "AgenticRetrieveMemoryMetadataFilterLeft":{ + "type":"structure", + "members":{ + "metadataKey":{ + "shape":"AgenticRetrieveMemoryMetadataKey", + "documentation":"

    The metadata key to filter on.

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

    The left operand of a metadata filter expression. Set exactly one member.

    ", + "union":true + }, + "AgenticRetrieveMemoryMetadataFilterList":{ + "type":"list", + "member":{ + "shape":"AgenticRetrieveMemoryMetadataFilter", + "documentation":"

    A metadata filter expression.

    " + }, + "documentation":"

    The metadata filter expressions applied to long-term memory retrieval.

    " + }, + "AgenticRetrieveMemoryMetadataFilterOperator":{ + "type":"string", + "documentation":"

    Specifies the relationship that a metadata key and value must have for a memory record to match a filter expression.

    ", + "enum":[ + "EQUALS_TO", + "EXISTS", + "NOT_EXISTS", + "BEFORE", + "AFTER", + "CONTAINS", + "GREATER_THAN", + "GREATER_THAN_OR_EQUALS", + "LESS_THAN", + "LESS_THAN_OR_EQUALS" + ] + }, + "AgenticRetrieveMemoryMetadataFilterRight":{ + "type":"structure", + "members":{ + "metadataValue":{ + "shape":"AgenticRetrieveMemoryMetadataValue", + "documentation":"

    The value to compare the metadata key against.

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

    The right operand of a metadata filter expression. Set exactly one member.

    ", + "union":true + }, + "AgenticRetrieveMemoryMetadataKey":{ + "type":"string", + "documentation":"

    The metadata key that a filter expression evaluates.

    ", + "max":128, + "min":1, + "pattern":"^[a-zA-Z0-9\\s._:/=+@-]*$" + }, + "AgenticRetrieveMemoryMetadataStringList":{ + "type":"list", + "member":{ + "shape":"AgenticRetrieveMemoryMetadataStringListItem", + "documentation":"

    A string value within the list.

    " + }, + "documentation":"

    The string values that a filter expression compares against.

    " + }, + "AgenticRetrieveMemoryMetadataStringListItem":{ + "type":"string", + "documentation":"

    A single string value within a metadata string list.

    ", + "max":64, + "min":1, + "pattern":"^[a-zA-Z0-9\\s._:/=+@-]*$" + }, + "AgenticRetrieveMemoryMetadataStringValue":{ + "type":"string", + "documentation":"

    A single string metadata value that a filter expression compares against.

    ", + "max":256, + "min":1, + "pattern":"^[a-zA-Z0-9\\s._:/=+@-]*$" + }, + "AgenticRetrieveMemoryMetadataValue":{ + "type":"structure", + "members":{ + "dateTimeValue":{ + "shape":"Timestamp", + "documentation":"

    A timestamp value in ISO 8601 UTC format.

    " + }, + "numberValue":{ + "shape":"Double", + "documentation":"

    A numeric value.

    " + }, + "stringListValue":{ + "shape":"AgenticRetrieveMemoryMetadataStringList", + "documentation":"

    A list of string values.

    " + }, + "stringValue":{ + "shape":"AgenticRetrieveMemoryMetadataStringValue", + "documentation":"

    A string value.

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

    A metadata value that a filter expression compares against. Set exactly one member.

    ", + "union":true + }, + "AgenticRetrieveMemoryPersistenceMode":{ + "type":"string", + "documentation":"

    Specifies whether the agent-generated answer is written back to a short-term memory session.

    ", + "enum":[ + "DEFAULT", + "NONE" + ] + }, + "AgenticRetrieveMemoryRetrievalConfig":{ + "type":"structure", + "members":{ + "metadataFilters":{ + "shape":"AgenticRetrieveMemoryMetadataFilterList", + "documentation":"

    The metadata filter expressions that restrict retrieval to matching memory records. You can specify a maximum of 5 expressions.

    " + }, + "namespace":{ + "shape":"MemoryNamespace", + "documentation":"

    The namespace prefix to filter memory records by. The agent retrieves memory records in namespaces that start with the provided prefix. You must specify either namespace or namespacePath.

    " + }, + "namespacePath":{ + "shape":"MemoryNamespace", + "documentation":"

    The parent namespace to use for hierarchical retrievals. The agent retrieves all memory records whose namespace falls under the same parent hierarchy. You must specify either namespace or namespacePath.

    " + }, + "strategyId":{ + "shape":"MemoryStrategyId", + "documentation":"

    The extraction strategy ID that restricts retrieval to memory records produced by a single strategy. Omit this parameter to retrieve records from every strategy on the memory resource.

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

    The long-term memory namespace that the agent might retrieve memory records from, and the filters applied to that retrieval. You must specify either namespace or namespacePath.

    " + }, + "AgenticRetrieveMemoryRetrievalConfigList":{ + "type":"list", + "member":{ + "shape":"AgenticRetrieveMemoryRetrievalConfig", + "documentation":"

    A long-term memory namespace that the agent might retrieve memory records from.

    " + }, + "documentation":"

    The long-term memory namespaces that the agent might retrieve memory records from.

    " + }, + "AgenticRetrieveMemoryRetrieveDetails":{ + "type":"structure", + "required":[ + "inputQuery", + "memoryId" + ], + "members":{ + "inputQuery":{ + "shape":"AgenticRetrieveMessageContent", + "documentation":"

    The query that the agent composed.

    " + }, + "memoryId":{ + "shape":"String", + "documentation":"

    The identifier of the AgentCore Memory resource retrieved from.

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    The namespace prefix retrieved from, as supplied in the request. This field is present when the request specified namespace.

    " + }, + "namespacePath":{ + "shape":"String", + "documentation":"

    The parent namespace retrieved from hierarchically, as supplied in the request. This field is present when the request specified namespacePath.

    " + }, + "strategyId":{ + "shape":"String", + "documentation":"

    The extraction strategy that restricted retrieval, if the request specified one.

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

    A long-term memory retrieval that the agent chose to perform. The record reports the query and the namespace. The corresponding Retrieval step reports the results.

    " + }, + "AgenticRetrieveMemorySessionBinding":{ + "type":"structure", + "required":[ + "actorId", + "sessionId" + ], + "members":{ + "actorId":{ + "shape":"AgentCoreMemoryActorId", + "documentation":"

    The identifier of the end user or agent that the session belongs to. This identifier scopes session history so that one actor's history is never returned for another. You are responsible for sending the correct actor value.

    " + }, + "sessionId":{ + "shape":"AgentCoreMemorySessionId", + "documentation":"

    The identifier of the session to restore and continue. You are responsible for sending the correct session value.

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

    The short-term memory session that this retrieval reads from and writes to.

    " + }, "AgenticRetrieveMessage":{ "type":"structure", "required":[ @@ -1432,7 +1722,8 @@ "Planning", "Retrieval", "SpeculativeRetrieval", - "FullDocumentExpansion" + "FullDocumentExpansion", + "SessionHistoryLoad" ] }, "AgenticRetrieveStreamRequest":{ @@ -1451,6 +1742,10 @@ "shape":"Boolean", "documentation":"

    Whether to generate a response based on the retrieved results.

    " }, + "memoryConfiguration":{ + "shape":"AgenticRetrieveMemoryConfiguration", + "documentation":"

    The configuration for using an Amazon Bedrock AgentCore Memory resource with this retrieval.

    " + }, "messages":{ "shape":"AgenticRetrieveStreamRequestMessagesList", "documentation":"

    The list of messages for the agentic retrieval conversation.

    " @@ -1655,7 +1950,10 @@ "AgenticRetrieveType":{ "type":"string", "documentation":"

    The type of retrieval source.

    ", - "enum":["BedrockKnowledgeBase"] + "enum":[ + "BedrockKnowledgeBase", + "BedrockAgentCoreMemory" + ] }, "AgenticRetrieveWarning":{ "type":"structure", @@ -2068,6 +2366,47 @@ "type":"list", "member":{"shape":"Caller"} }, + "CheckIngestedDocumentAclRequest":{ + "type":"structure", + "required":[ + "dataSourceId", + "documentId", + "knowledgeBaseId", + "userContext" + ], + "members":{ + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

    The unique identifier of the data source that contains the document.

    ", + "location":"uri", + "locationName":"dataSourceId" + }, + "documentId":{ + "shape":"DocumentId", + "documentation":"

    The unique identifier of the document to check access for.

    " + }, + "knowledgeBaseId":{ + "shape":"KnowledgeBaseIdentifier", + "documentation":"

    The unique identifier of the knowledge base that contains the document.

    ", + "location":"uri", + "locationName":"knowledgeBaseId" + }, + "userContext":{ + "shape":"UserContext", + "documentation":"

    The context object containing identity information for access control filtering, including user ID and optional group memberships used to evaluate the document access control list (ACL).

    " + } + } + }, + "CheckIngestedDocumentAclResponse":{ + "type":"structure", + "required":["hasAccess"], + "members":{ + "hasAccess":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the user has access to the document based on the ingested access control list (ACL). Returns true if the user is allowed access, and false otherwise.

    " + } + } + }, "Citation":{ "type":"structure", "members":{ @@ -2558,6 +2897,135 @@ "members":{}, "document":true }, + "DocumentAcl":{ + "type":"structure", + "members":{ + "allowList":{ + "shape":"DocumentAclMembership", + "documentation":"

    The list of principals allowed access to the document.

    " + }, + "denyList":{ + "shape":"DocumentAclMembership", + "documentation":"

    The list of principals denied access to the document.

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

    The access control list for a document, containing allow and deny membership lists. Each list specifies conditions that determine which users and groups are granted or denied access.

    ", + "sensitive":true + }, + "DocumentAclCondition":{ + "type":"structure", + "members":{ + "conditionOperator":{ + "shape":"DocumentAclMemberRelation", + "documentation":"

    The logical operator for combining users and groups within this condition. Valid values: AND – Both a user match and a group match are required. OR – Either a user match or a group match is sufficient.

    " + }, + "groups":{ + "shape":"DocumentAclConditionGroupsList", + "documentation":"

    The list of group entries in this condition.

    " + }, + "users":{ + "shape":"DocumentAclConditionUsersList", + "documentation":"

    The list of user entries in this condition.

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

    A condition within a document access control list (ACL) membership, specifying users and groups that are evaluated together.

    " + }, + "DocumentAclConditionGroupsList":{ + "type":"list", + "member":{"shape":"DocumentAclGroup"}, + "max":3000, + "min":0 + }, + "DocumentAclConditionUsersList":{ + "type":"list", + "member":{"shape":"DocumentAclUser"}, + "max":3000, + "min":0 + }, + "DocumentAclGroup":{ + "type":"structure", + "required":[ + "id", + "type" + ], + "members":{ + "id":{ + "shape":"DocumentAclGroupIdString", + "documentation":"

    The identifier of the group.

    " + }, + "type":{ + "shape":"DocumentAclMembershipType", + "documentation":"

    The membership type indicating the scope of the group entry.

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

    A group entry within a document access control list (ACL) condition.

    " + }, + "DocumentAclGroupIdString":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"^\\P{C}*$" + }, + "DocumentAclMemberRelation":{ + "type":"string", + "documentation":"

    The logical relation for combining access control list (ACL) membership conditions.

    ", + "enum":[ + "AND", + "OR" + ] + }, + "DocumentAclMembership":{ + "type":"structure", + "members":{ + "conditions":{ + "shape":"DocumentAclMembershipConditionsList", + "documentation":"

    The list of conditions that determine membership.

    " + }, + "memberRelation":{ + "shape":"DocumentAclMemberRelation", + "documentation":"

    The logical relation between conditions. Valid values: AND – All conditions must match. OR – At least one condition must match.

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

    The membership entry for a document access control list (ACL), containing conditions and their logical relation.

    " + }, + "DocumentAclMembershipConditionsList":{ + "type":"list", + "member":{"shape":"DocumentAclCondition"}, + "max":100, + "min":0 + }, + "DocumentAclMembershipType":{ + "type":"string", + "documentation":"

    The scope type for a document access control list (ACL) membership condition. Valid values: KNOWLEDGE_BASE – The entry applies at the knowledge base level. DATA_SOURCE – The entry applies at the data source level.

    ", + "enum":[ + "KNOWLEDGE_BASE", + "DATA_SOURCE" + ] + }, + "DocumentAclUser":{ + "type":"structure", + "required":[ + "id", + "type" + ], + "members":{ + "id":{ + "shape":"DocumentAclUserIdString", + "documentation":"

    The identifier of the user.

    " + }, + "type":{ + "shape":"DocumentAclMembershipType", + "documentation":"

    The membership type indicating the scope of the user entry.

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

    A user entry within a document access control list (ACL) condition.

    " + }, + "DocumentAclUserIdString":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"^\\P{C}*$" + }, "DocumentId":{ "type":"string", "max":1825, @@ -4105,7 +4573,10 @@ "shape":"DocumentOutputFormat", "documentation":"

    The output format for the document content. RAW returns the original file. EXTRACTED returns parsed text as JSON. Defaults to RAW.

    " }, - "userContext":{"shape":"UserContext"} + "userContext":{ + "shape":"UserContext", + "documentation":"

    Contains information about the user making the request. This is used for access control filtering to ensure that results only include documents the user is authorized to access.

    " + } } }, "GetDocumentContentResponse":{ @@ -4266,6 +4737,42 @@ } } }, + "GetIngestedDocumentAclRequest":{ + "type":"structure", + "required":[ + "dataSourceId", + "documentId", + "knowledgeBaseId" + ], + "members":{ + "dataSourceId":{ + "shape":"DataSourceId", + "documentation":"

    The unique identifier of the data source that contains the document.

    ", + "location":"uri", + "locationName":"dataSourceId" + }, + "documentId":{ + "shape":"DocumentId", + "documentation":"

    The unique identifier of the document to retrieve the ingested access control list (ACL) for.

    " + }, + "knowledgeBaseId":{ + "shape":"KnowledgeBaseIdentifier", + "documentation":"

    The unique identifier of the knowledge base that contains the document.

    ", + "location":"uri", + "locationName":"knowledgeBaseId" + } + } + }, + "GetIngestedDocumentAclResponse":{ + "type":"structure", + "required":["documentAcl"], + "members":{ + "documentAcl":{ + "shape":"DocumentAcl", + "documentation":"

    The ingested document access control list (ACL) containing allow and deny membership information.

    " + } + } + }, "GetInvocationStepRequest":{ "type":"structure", "required":[ @@ -6219,7 +6726,10 @@ "ManagedSearchConfiguration":{ "type":"structure", "members":{ - "filter":{"shape":"RetrievalFilter"}, + "filter":{ + "shape":"RetrievalFilter", + "documentation":"

    Filters the metadata of the retrieved results so that Amazon Bedrock returns only results that match the filter.

    " + }, "numberOfResults":{ "shape":"ManagedSearchConfigurationNumberOfResultsInteger", "documentation":"

    The number of results to retrieve.

    " @@ -6301,6 +6811,13 @@ "min":2, "pattern":"^[0-9a-zA-Z._:-]+$" }, + "MemoryNamespace":{ + "type":"string", + "documentation":"

    A namespace in an AgentCore Memory resource, supplied exactly as configured on the memory strategy. The service does not accept placeholder templates such as {actorId}. Supply the resolved value.

    ", + "max":1024, + "min":1, + "pattern":"^[a-zA-Z0-9/*][a-zA-Z0-9\\-_/*]*(?::[a-zA-Z0-9\\-_/*]+)*[a-zA-Z0-9\\-_/*]*$" + }, "MemorySessionSummary":{ "type":"structure", "members":{ @@ -6327,6 +6844,13 @@ }, "documentation":"

    Contains details of a session summary.

    " }, + "MemoryStrategyId":{ + "type":"string", + "documentation":"

    The identifier of an extraction strategy configured on the memory resource. Omit this value to retrieve records from every strategy on the memory resource.

    ", + "max":100, + "min":1, + "pattern":"^[a-zA-Z0-9][a-zA-Z0-9\\-_]*$" + }, "MemoryType":{ "type":"string", "enum":["SESSION_SUMMARY"] @@ -8458,7 +8982,10 @@ "shape":"SessionId", "documentation":"

    The unique identifier of the session. When you first make a RetrieveAndGenerate request, Amazon Bedrock automatically generates this value. You must reuse this value for all subsequent requests in the same conversational session. This value allows Amazon Bedrock to maintain context and knowledge from previous interactions. You can't explicitly set the sessionId yourself.

    " }, - "userContext":{"shape":"UserContext"} + "userContext":{ + "shape":"UserContext", + "documentation":"

    Contains information about the user making the request. This is used for access control filtering to ensure that retrieval results only include documents the user is authorized to access.

    " + } } }, "RetrieveAndGenerateResponse":{ @@ -8517,7 +9044,10 @@ "shape":"SessionId", "documentation":"

    The unique identifier of the session. When you first make a RetrieveAndGenerate request, Amazon Bedrock automatically generates this value. You must reuse this value for all subsequent requests in the same conversational session. This value allows Amazon Bedrock to maintain context and knowledge from previous interactions. You can't explicitly set the sessionId yourself.

    " }, - "userContext":{"shape":"UserContext"} + "userContext":{ + "shape":"UserContext", + "documentation":"

    Contains information about the user making the request. This is used for access control filtering to ensure that retrieval results only include documents the user is authorized to access.

    " + } } }, "RetrieveAndGenerateStreamResponse":{ @@ -8631,7 +9161,10 @@ "shape":"KnowledgeBaseQuery", "documentation":"

    Contains the query to send the knowledge base.

    " }, - "userContext":{"shape":"UserContext"} + "userContext":{ + "shape":"UserContext", + "documentation":"

    Contains information about the user making the request. This is used for access control filtering to ensure that retrieval results only include documents the user is authorized to access.

    " + } } }, "RetrieveResponse":{ @@ -9307,6 +9840,7 @@ }, "exception":true }, + "Timestamp":{"type":"timestamp"}, "TopK":{ "type":"integer", "box":true, @@ -9647,5 +10181,5 @@ "min":1 } }, - "documentation":"

    Contains APIs related to model invocation and querying of knowledge bases.

    " + "documentation":"

    Amazon Bedrock Agents (now Amazon Bedrock Agents Classic) is no longer open to new customers. For capabilities similar to Bedrock Agents Classic, explore Amazon Bedrock AgentCore. Existing customers can continue to use the service as normal. For more information, see Amazon Bedrock Agents Classic availability change.

    Contains APIs related to model invocation and querying of knowledge bases.

    " } diff --git a/services/bedrockdataautomation/pom.xml b/services/bedrockdataautomation/pom.xml index a29a7bef0cd5..448265120e2c 100644 --- a/services/bedrockdataautomation/pom.xml +++ b/services/bedrockdataautomation/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockdataautomation AWS Java SDK :: Services :: Bedrock Data Automation diff --git a/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..149079e0fff4 --- /dev/null +++ b/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d2f8a351c694..000000000000 --- a/services/bedrockdataautomation/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockdataautomationruntime/pom.xml b/services/bedrockdataautomationruntime/pom.xml index 74cfd4eb7240..674dabf24411 100644 --- a/services/bedrockdataautomationruntime/pom.xml +++ b/services/bedrockdataautomationruntime/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockdataautomationruntime AWS Java SDK :: Services :: Bedrock Data Automation Runtime diff --git a/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f9289839dcaa --- /dev/null +++ b/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-data-automation-runtime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d5e69c7159a0..000000000000 --- a/services/bedrockdataautomationruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-data-automation-runtime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockruntime/pom.xml b/services/bedrockruntime/pom.xml index 3c8eec144e35..175a143fa2fc 100644 --- a/services/bedrockruntime/pom.xml +++ b/services/bedrockruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT bedrockruntime AWS Java SDK :: Services :: Bedrock Runtime diff --git a/services/bedrockruntime/src/main/resources/codegen-resources/customization.config b/services/bedrockruntime/src/main/resources/codegen-resources/customization.config index 42aa381cf2ea..2edb12c857bc 100644 --- a/services/bedrockruntime/src/main/resources/codegen-resources/customization.config +++ b/services/bedrockruntime/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "enableEnvironmentBearerToken": true } diff --git a/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a99ec852d5e0 --- /dev/null +++ b/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://bedrock-runtime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b34ad4d3f1cb..000000000000 --- a/services/bedrockruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://bedrock-runtime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/bedrockruntime/src/main/resources/codegen-resources/service-2.json b/services/bedrockruntime/src/main/resources/codegen-resources/service-2.json index d2eab7497aa5..431a3fcf1fae 100644 --- a/services/bedrockruntime/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockruntime/src/main/resources/codegen-resources/service-2.json @@ -850,7 +850,9 @@ "searchResult":{ "shape":"SearchResultBlock", "documentation":"

    Search result to include in the message.

    " - } + }, + "toolAddition":{"shape":"ToolAdditionBlock"}, + "toolRemoval":{"shape":"ToolRemovalBlock"} }, "documentation":"

    A block of content for a message that you pass to, or receive from, a model with the Converse or ConverseStream API operations.

    ", "union":true @@ -4072,10 +4074,19 @@ "textFormat":{ "shape":"OutputFormat", "documentation":"

    Structured output parameters to control the model's text response.

    " + }, + "effort":{ + "shape":"OutputConfigEffortString", + "documentation":"

    The effort level for the model to use when generating a response. Higher effort levels allow the model to spend more time reasoning before responding. Supported values are low, medium, high, xhigh, and max.

    When extended thinking is disabled, the effort level is capped at high. Use effort high or below, or enable thinking to use higher effort levels.

    " } }, "documentation":"

    Output configuration for a model response in a call to Converse or ConverseStream.

    " }, + "OutputConfigEffortString":{ + "type":"string", + "max":16, + "min":0 + }, "OutputFormat":{ "type":"structure", "required":[ @@ -4699,6 +4710,17 @@ "documentation":"

    Information about a tool that you can use with the Converse API. For more information, see Call a tool with the Converse API in the Amazon Bedrock User Guide.

    ", "union":true }, + "ToolAdditionBlock":{ + "type":"structure", + "required":["tool"], + "members":{ + "tool":{ + "shape":"ToolReference", + "documentation":"

    A reference to the tool to add to the available tool set.

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

    A content block for adding a tool to the available tool set mid-conversation. Each block references a single tool via its tool field. Use within a system role message to make a tool available without re-sending the full tool configuration.

    " + }, "ToolChoice":{ "type":"structure", "members":{ @@ -4755,6 +4777,50 @@ "min":1, "pattern":"[a-zA-Z0-9_-]+" }, + "ToolReference":{ + "type":"structure", + "members":{ + "type":{ + "shape":"ToolReferenceTypeString", + "documentation":"

    The type of tool reference.

    " + }, + "name":{ + "shape":"ToolReferenceNameString", + "documentation":"

    The name of the tool. Must match the name of a tool declared in the top-level tool configuration.

    " + }, + "serverName":{ + "shape":"ToolReferenceServerNameString", + "documentation":"

    The name of the MCP server that provides the tool. Required when referencing an MCP tool.

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

    A reference to a tool in the tool configuration. Used with ToolAdditionBlock and ToolRemovalBlock to identify which tool to add or remove mid-conversation.

    " + }, + "ToolReferenceNameString":{ + "type":"string", + "max":128, + "min":1 + }, + "ToolReferenceServerNameString":{ + "type":"string", + "max":128, + "min":1 + }, + "ToolReferenceTypeString":{ + "type":"string", + "max":64, + "min":1 + }, + "ToolRemovalBlock":{ + "type":"structure", + "required":["tool"], + "members":{ + "tool":{ + "shape":"ToolReference", + "documentation":"

    A reference to the tool to remove from the available tool set.

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

    A content block for removing a tool from the available tool set mid-conversation. Each block references a single tool via its tool field. Use within a system role message to remove a tool without re-sending the full tool configuration.

    " + }, "ToolResultBlock":{ "type":"structure", "required":[ diff --git a/services/billing/pom.xml b/services/billing/pom.xml index 31ddab81540a..b252aabcfcd2 100644 --- a/services/billing/pom.xml +++ b/services/billing/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT billing AWS Java SDK :: Services :: Billing diff --git a/services/billing/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/billing/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..883acd0799ec --- /dev/null +++ b/services/billing/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,247 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billing.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAX14QQAAAAHAAAABQAAAAgF9eELAAAABgX14QkF9eEKAAAABQAAAAsAAAAKAAAABwX14QcF9eEIAAAABgAAAAwF9eEGAAAABwX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/billing/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/billing/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 38da1de8c89a..000000000000 --- a/services/billing/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,472 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://billing.us-east-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://billing.us-east-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://billing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/billing/src/main/resources/codegen-resources/paginators-1.json b/services/billing/src/main/resources/codegen-resources/paginators-1.json index 65fac08b7b89..c967ea7b63f5 100644 --- a/services/billing/src/main/resources/codegen-resources/paginators-1.json +++ b/services/billing/src/main/resources/codegen-resources/paginators-1.json @@ -6,12 +6,24 @@ "limit_key": "maxResults", "result_key": "creditAllocationHistoryList" }, + "ListBillingViewSegments": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, "ListBillingViews": { "input_token": "nextToken", "output_token": "nextToken", "limit_key": "maxResults", "result_key": "billingViews" }, + "ListEnterpriseSupportLinkedAccountCharges": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "linkedAccount" + }, "ListSourceViewsForBillingView": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/billing/src/main/resources/codegen-resources/service-2.json b/services/billing/src/main/resources/codegen-resources/service-2.json index 621fd99842f5..b8e20027e07d 100644 --- a/services/billing/src/main/resources/codegen-resources/service-2.json +++ b/services/billing/src/main/resources/codegen-resources/service-2.json @@ -161,6 +161,42 @@ ], "documentation":"

    Returns the list of Amazon Web Services account credits for the specified account. Each credit includes its identifier, type, monetary amounts, applicable products, expiration, sharing configuration, and current enabled status.

    When the caller is the management account of a consolidated billing family and payerAccountFlag is true, the response aggregates credits across the entire family. Otherwise, the response includes only credits owned by the account specified in accountId.

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

    Returns a summary of Enterprise Support data aggregated across all accounts in the Enterprise Support profile.

    ", + "readonly":true + }, + "GetEnterpriseSupportContractDetails":{ + "name":"GetEnterpriseSupportContractDetails", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetEnterpriseSupportContractDetailsRequest"}, + "output":{"shape":"GetEnterpriseSupportContractDetailsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns Enterprise Support contract details.

    ", + "readonly":true + }, "GetResourcePolicy":{ "name":"GetResourcePolicy", "http":{ @@ -179,6 +215,25 @@ "documentation":"

    Returns the resource-based policy document attached to the resource in JSON format.

    ", "readonly":true }, + "ListBillingViewSegments":{ + "name":"ListBillingViewSegments", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListBillingViewSegmentsRequest"}, + "output":{"shape":"ListBillingViewSegmentsResponse"}, + "errors":[ + {"shape":"BillingViewHealthStatusException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the segments of a billing view over a given time period. Each segment identifies the billing domain (PRO_FORMA or BILLABLE) and the account relationships that apply during its time range.

    If you don't provide an arn, the response includes segments for the caller's PRIMARY billing view.

    If a mid-period change occurs, the response includes multiple segments, each with its own time range. The response omits hidden segments, so the segments it returns might not cover the entire requested time period.

    ", + "readonly":true + }, "ListBillingViews":{ "name":"ListBillingViews", "http":{ @@ -196,6 +251,24 @@ "documentation":"

    Lists the billing views available for a given time period.

    Every Amazon Web Services account has a unique PRIMARY billing view that represents the billing data available by default. Accounts that use Billing Conductor also have BILLING_GROUP billing views representing pro forma costs associated with each created billing group.

    ", "readonly":true }, + "ListEnterpriseSupportLinkedAccountCharges":{ + "name":"ListEnterpriseSupportLinkedAccountCharges", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListEnterpriseSupportLinkedAccountChargesRequest"}, + "output":{"shape":"ListEnterpriseSupportLinkedAccountChargesResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns Support-eligible spend broken down at linked account level.

    ", + "readonly":true + }, "ListSourceViewsForBillingView":{ "name":"ListSourceViewsForBillingView", "http":{ @@ -357,6 +430,32 @@ }, "documentation":"

    A time range with a start and end time.

    " }, + "AdditionalCharge":{ + "type":"structure", + "required":["description"], + "members":{ + "description":{ + "shape":"String", + "documentation":"

    A description of the additional charge.

    " + }, + "amount":{ + "shape":"String", + "documentation":"

    The charge amount.

    " + }, + "chargeType":{ + "shape":"String", + "documentation":"

    The type of additional charge.

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

    An additional charge applied to an Enterprise Support contract.

    " + }, + "AdditionalChargeList":{ + "type":"list", + "member":{"shape":"AdditionalCharge"}, + "documentation":"

    A list of additional charges.

    ", + "max":50, + "min":0 + }, "Amount":{ "type":"structure", "required":[ @@ -409,6 +508,14 @@ } } }, + "BillingDomain":{ + "type":"string", + "documentation":"

    The billing domain for a billing view segment. The following values are valid:

    • PRO_FORMA - Data shaped by Billing Conductor that doesn't reflect the final charges owed to Amazon Web Services.

    • BILLABLE - Data that represents the final charges owed to Amazon Web Services.

    ", + "enum":[ + "BILLABLE", + "PRO_FORMA" + ] + }, "BillingFeature":{ "type":"string", "enum":[ @@ -679,6 +786,51 @@ "pattern":"[ a-zA-Z0-9_\\+=\\.\\-@]+", "sensitive":true }, + "BillingViewSegmentTimeRange":{ + "type":"structure", + "members":{ + "beginDateInclusive":{ + "shape":"Timestamp", + "documentation":"

    The inclusive start of the time range. This value can't be in the future.

    " + }, + "endDateExclusive":{ + "shape":"Timestamp", + "documentation":"

    The exclusive end of the time range. This value must be after beginDateInclusive.

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

    Specifies a time range with an inclusive begin date and an exclusive end date.

    " + }, + "BillingViewSegmentsList":{ + "type":"list", + "member":{"shape":"BillingViewSegmentsListElement"}, + "documentation":"

    A list of billing view segments.

    " + }, + "BillingViewSegmentsListElement":{ + "type":"structure", + "members":{ + "domain":{ + "shape":"BillingDomain", + "documentation":"

    The billing domain for this segment. The following values are valid:

    • PRO_FORMA - Data shaped by Billing Conductor that doesn't reflect the final charges owed to Amazon Web Services.

    • BILLABLE - Data that represents the final charges owed to Amazon Web Services.

    " + }, + "timeRange":{ + "shape":"BillingViewSegmentTimeRange", + "documentation":"

    The time range during which this segment is effective.

    " + }, + "billingTransferAccountId":{ + "shape":"AccountId", + "documentation":"

    The billing transfer account ID. The response includes this field only when the caller is a billing transfer source account. The response omits this field for billing group billing views.

    " + }, + "managementAccountId":{ + "shape":"AccountId", + "documentation":"

    The management account ID of the organization. The response includes this field for organization member accounts.

    " + }, + "billingGroupPrimaryAccountId":{ + "shape":"AccountId", + "documentation":"

    The billing group primary account ID. The response includes this field for billing group members. Compare this value to your own account ID to determine whether you are the primary account.

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

    A billing view segment. A segment represents a time range during which the billing domain and account relationships for a billing view remained unchanged.

    " + }, "BillingViewSourceViewsList":{ "type":"list", "member":{"shape":"BillingViewArn"}, @@ -741,6 +893,31 @@ "type":"boolean", "box":true }, + "ChargeAccount":{ + "type":"structure", + "required":[ + "accountId", + "chargePercentage" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The account ID.

    " + }, + "chargePercentage":{ + "shape":"String", + "documentation":"

    The percentage of the total Support charge allocated to this account. This is 0.0 when supportAllocationMethod = Proportional.

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

    An account that is charged all or a portion of the total Support charge and the percentage of the charge allocated to it.

    " + }, + "ChargeAccountList":{ + "type":"list", + "member":{"shape":"ChargeAccount"}, + "documentation":"

    A list of charge accounts.

    ", + "max":1000, + "min":0 + }, "ClientToken":{ "type":"string", "pattern":"[a-zA-Z0-9-]+" @@ -766,6 +943,31 @@ "documentation":"

    The requested operation would cause a conflict with the current state of a service resource associated with the request. Resolve the conflict before retrying this request.

    ", "exception":true }, + "ContractAccount":{ + "type":"structure", + "required":[ + "accountId", + "isGdn" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The account ID.

    " + }, + "isGdn":{ + "shape":"Boolean", + "documentation":"

    When true, Support charges are calculated on charges before private discounts. When false, they are calculated after private discounts.

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

    An account that is covered by the Enterprise Support contract.

    " + }, + "ContractAccountList":{ + "type":"list", + "member":{"shape":"ContractAccount"}, + "documentation":"

    A list of accounts that appear in the Enterprise Support Contract.

    ", + "max":2000, + "min":0 + }, "CostCategoryName":{ "type":"string", "max":50, @@ -1086,6 +1288,26 @@ } } }, + "EnterpriseSupportBillingMonth":{ + "type":"string", + "documentation":"

    The billing month in YYYY-MM format. This must be a month in the past.

    ", + "pattern":"\\d{4}-(0[1-9]|1[0-2])" + }, + "EnterpriseSupportTimePeriod":{ + "type":"structure", + "required":["beginDate"], + "members":{ + "beginDate":{ + "shape":"Timestamp", + "documentation":"

    The begin date of the time period.

    " + }, + "endDate":{ + "shape":"Timestamp", + "documentation":"

    The end date of the time period.

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

    A time period for Enterprise Support billing.

    " + }, "ErrorMessage":{ "type":"string", "max":1024, @@ -1292,6 +1514,171 @@ } } }, + "GetEnterpriseSupportChargeSummaryRequest":{ + "type":"structure", + "required":["billingMonth"], + "members":{ + "billingMonth":{ + "shape":"EnterpriseSupportBillingMonth", + "documentation":"

    The billing month in YYYY-MM format. This must be a month in the past.

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

    The request structure for GetEnterpriseSupportChargeSummary.

    " + }, + "GetEnterpriseSupportChargeSummaryResponse":{ + "type":"structure", + "required":[ + "payerAccountId", + "billingMonth", + "billingPeriodStartDate", + "billingPeriodEndDate", + "isEstimated", + "billDate", + "supportCharge", + "totalSupportCharge", + "supportDiscount", + "totalSupportEligibleSpend", + "totalSupportEligibleUsageSpend", + "totalSupportEligibleReservedInstanceSpend", + "totalSupportEligibleSavingsPlanSpend", + "supportChargePercentage", + "supportEffectivePricingPlan" + ], + "members":{ + "payerAccountId":{ + "shape":"AccountId", + "documentation":"

    The payer account ID that is authorized to view Enterprise Support data for all accounts in its Support profile.

    " + }, + "billingMonth":{ + "shape":"EnterpriseSupportBillingMonth", + "documentation":"

    The billing month in YYYY-MM format. This must be a month in the past.

    " + }, + "billingPeriodStartDate":{ + "shape":"Timestamp", + "documentation":"

    The start date of the billing period.

    " + }, + "billingPeriodEndDate":{ + "shape":"Timestamp", + "documentation":"

    The end date of the billing period.

    " + }, + "isEstimated":{ + "shape":"Boolean", + "documentation":"

    When true, the Support charge amount is estimated. When false, the Support charge amount is finalized.

    " + }, + "billDate":{ + "shape":"Timestamp", + "documentation":"

    The date the bill was generated.

    " + }, + "supportCharge":{ + "shape":"String", + "documentation":"

    The Support charge amount for the account.

    " + }, + "totalSupportCharge":{ + "shape":"String", + "documentation":"

    The total Support charge amount for all accounts in the Support profile.

    " + }, + "supportDiscount":{ + "shape":"String", + "documentation":"

    The support discount amount.

    " + }, + "totalSupportEligibleSpend":{ + "shape":"String", + "documentation":"

    The total Support-eligible Spend from all accounts in the Support profile. This includes eligible spend from usage of Amazon Web Services, Reserved Instances, and Savings Plans.

    " + }, + "totalSupportEligibleUsageSpend":{ + "shape":"String", + "documentation":"

    The total Support-eligible spend from usage of Amazon Web Services from all accounts in the Support profile.

    " + }, + "totalSupportEligibleReservedInstanceSpend":{ + "shape":"String", + "documentation":"

    The total Support-eligible Reserved Instance spend from all accounts in the Support profile.

    " + }, + "totalSupportEligibleSavingsPlanSpend":{ + "shape":"String", + "documentation":"

    The total Support-eligible Savings Plan spend from all accounts in the Support profile.

    " + }, + "supportChargePercentage":{ + "shape":"String", + "documentation":"

    The percentage applied to the total Support-eligible spend to calculate the total Support charge across all accounts in the Support profile.

    " + }, + "supportEffectivePricingPlan":{ + "shape":"PricingPlan", + "documentation":"

    The effective pricing plan used for the support charge calculation.

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

    The response structure for GetEnterpriseSupportChargeSummary.

    " + }, + "GetEnterpriseSupportContractDetailsRequest":{ + "type":"structure", + "required":["billingMonth"], + "members":{ + "billingMonth":{ + "shape":"EnterpriseSupportBillingMonth", + "documentation":"

    The billing month in YYYY-MM format. This must be a month in the past.

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

    The request structure for GetEnterpriseSupportContractDetails.

    " + }, + "GetEnterpriseSupportContractDetailsResponse":{ + "type":"structure", + "required":[ + "supportAllocationMethod", + "contractPayerAccountIds", + "chargedPayerAccountIds", + "pricingPlans" + ], + "members":{ + "isContractActive":{ + "shape":"Boolean", + "documentation":"

    When true, the Enterprise Support contract is active. When false, the Enterprise Support Contract is inactive.

    " + }, + "supportAllocationMethod":{ + "shape":"String", + "documentation":"

    The method used to distribute the total Support charge amount across each account in the Support profile. Valid values: Proportional, Fixed_Percentage. Proportional means support charges are distributed to each account in proportion to its eligible Spend. Fixed_Percentage means support charges are distributed across accounts according to pre-configured percentages from the contract.

    " + }, + "supportReservedInstanceAmortizationStartDate":{ + "shape":"Timestamp", + "documentation":"

    When supportReservedInstanceTreatmentMethod = AmortizedCustom, only amortized fees for Reserved Instances purchased on or after this date are included in the calculation. This field is Null for all other treatment methods.

    " + }, + "supportReservedInstanceTreatmentMethod":{ + "shape":"String", + "documentation":"

    The method used to include Reserved Instance (RI) fees in the Enterprise Support charge calculation. Valid values: None (RI fees excluded from Support-eligible spend), Upfront (full upfront RI fees included in month of purchase), Amortized (RI fees spread over commitment term for RIs purchased on or after Support subscription start date), AmortizedCustom (same as Amortized but only for RIs purchased on or after a specified custom start date), AmortizedAll (RI fees amortized for all active RIs including those purchased before Support subscription started).

    " + }, + "supportSavingsPlansAmortizationStartDate":{ + "shape":"Timestamp", + "documentation":"

    This is applicable when supportSavingsPlansTreatmentMethod = Amortized and is Null for all other methods. It shows the start date from which Savings Plan fees are included in Support Eligible Spend.

    " + }, + "supportSavingsPlansTreatmentMethod":{ + "shape":"String", + "documentation":"

    The method used to include Savings Plans fees in Enterprise Support charge calculations. Valid values: None (Savings Plan fees excluded from Support-eligible spend), Upfront (full upfront Savings Plan fees included in month of purchase), Amortized (Savings Plan fees spread over commitment term for Savings Plans purchased on or after Support subscription start date), AmortizedCustom (same as Amortized but only for Savings Plans purchased on or after a specified custom start date), AmortizedAll (Savings Plan fees amortized for all active Savings Plans including those purchased before Support subscription started).

    " + }, + "supportProrateStartDate":{ + "shape":"Timestamp", + "documentation":"

    The start date for accounts subscribed or unsubscribed to Support billing during the billing month.

    " + }, + "contractPayerAccountIds":{ + "shape":"ContractAccountList", + "documentation":"

    The list of accounts covered by the Enterprise Support contract.

    " + }, + "chargedPayerAccountIds":{ + "shape":"ChargeAccountList", + "documentation":"

    The list of payer accounts and their charge allocation percentages.

    " + }, + "additionalSupportCharge":{ + "shape":"AdditionalChargeList", + "documentation":"

    Any Additional support charges applied to the contract.

    " + }, + "additionalSupportEligibleUsageSpend":{ + "shape":"AdditionalChargeList", + "documentation":"

    Any Additional support-eligible usage spend charges.

    " + }, + "pricingPlans":{ + "shape":"PricingPlanList", + "documentation":"

    The pricing plans associated with this Enterprise Support contract.

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

    The response structure for GetEnterpriseSupportContractDetails.

    " + }, "GetResourcePolicyRequest":{ "type":"structure", "required":["resourceArn"], @@ -1330,6 +1717,110 @@ "exception":true, "fault":true }, + "LinkedAccountCharge":{ + "type":"structure", + "required":[ + "accountId", + "payerAccountId", + "billableSeconds", + "totalSeconds", + "totalSupportEligibleSpend", + "proratedTotalSupportEligibleSpend" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The linked account ID.

    " + }, + "payerAccountId":{ + "shape":"AccountId", + "documentation":"

    The payer account ID that is authorized to view Enterprise Support data for all accounts in its Support profile.

    " + }, + "accountType":{ + "shape":"String", + "documentation":"

    The type of account.

    " + }, + "billableSeconds":{ + "shape":"Long", + "documentation":"

    The number of billable seconds in the billing period based on when the account was subscribed to Enterprise Support.

    " + }, + "totalSeconds":{ + "shape":"Long", + "documentation":"

    The total number of seconds in the billing period.

    " + }, + "totalSupportEligibleSpend":{ + "shape":"String", + "documentation":"

    The total support-eligible spend for this account.

    " + }, + "proratedTotalSupportEligibleSpend":{ + "shape":"String", + "documentation":"

    The prorated total support-eligible spend based on when the account was subscribed to Enterprise Support.

    " + }, + "linkedTimePeriods":{ + "shape":"TimePeriodList", + "documentation":"

    The time periods during which this account was linked.

    " + }, + "subscriptionTimePeriods":{ + "shape":"TimePeriodList", + "documentation":"

    The subscription time periods for this account.

    " + }, + "totalSupportEligibleReservedInstanceSpend":{ + "shape":"String", + "documentation":"

    The total support-eligible Reserved Instance spend for this account.

    " + }, + "totalSupportEligibleSavingsPlanSpend":{ + "shape":"String", + "documentation":"

    The total support-eligible Savings Plan spend for this account.

    " + }, + "supportEligibleSpendByService":{ + "shape":"ServiceLevelAccountUsageList", + "documentation":"

    The support-eligible spend broken down by service.

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

    Enterprise Support charges for a linked account.

    " + }, + "LinkedAccountChargeList":{ + "type":"list", + "member":{"shape":"LinkedAccountCharge"}, + "documentation":"

    A list of linked account charges.

    ", + "max":100, + "min":0 + }, + "ListBillingViewSegmentsRequest":{ + "type":"structure", + "members":{ + "timeRange":{ + "shape":"BillingViewSegmentTimeRange", + "documentation":"

    The billing period to query. If you don't provide a time range, the current billing period, which is the calendar month in UTC, is used.

    " + }, + "arn":{ + "shape":"BillingViewArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the billing view to query. If you don't provide an ARN, the caller's PRIMARY billing view is used. The ARN must reference a primary billing view. Custom billing views aren't supported.

    " + }, + "maxResults":{ + "shape":"BillingViewsMaxResults", + "documentation":"

    The number of entries a paginated response contains. Valid values range from 1 to 100. The default is 100.

    " + }, + "nextToken":{ + "shape":"PageToken", + "documentation":"

    The pagination token that is used on subsequent calls to list billing view segments.

    " + } + } + }, + "ListBillingViewSegmentsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"BillingViewSegmentsList", + "documentation":"

    A list of billing view segments. Each segment covers a portion of the requested time period. The response omits hidden segments, so the segments it returns might not cover the entire requested time period.

    " + }, + "nextToken":{ + "shape":"PageToken", + "documentation":"

    The pagination token that is used on subsequent calls to list billing view segments.

    " + } + } + }, "ListBillingViewsRequest":{ "type":"structure", "members":{ @@ -1381,6 +1872,50 @@ } } }, + "ListEnterpriseSupportLinkedAccountChargesRequest":{ + "type":"structure", + "required":["billingMonth"], + "members":{ + "billingMonth":{ + "shape":"EnterpriseSupportBillingMonth", + "documentation":"

    The billing month in YYYY-MM format. This must be a month in the past.

    " + }, + "accountId":{ + "shape":"AccountId", + "documentation":"

    An optional linked account ID to filter results to a specific account.

    " + }, + "maxResults":{ + "shape":"ListEnterpriseSupportLinkedAccountChargesRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return per page.

    " + }, + "nextToken":{ + "shape":"PageToken", + "documentation":"

    The pagination token for the next page of results.

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

    The request structure for ListEnterpriseSupportLinkedAccountCharges.

    " + }, + "ListEnterpriseSupportLinkedAccountChargesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListEnterpriseSupportLinkedAccountChargesResponse":{ + "type":"structure", + "required":["linkedAccount"], + "members":{ + "linkedAccount":{ + "shape":"LinkedAccountChargeList", + "documentation":"

    The list of Enterprise Support charges per linked account.

    " + }, + "nextToken":{ + "shape":"PageToken", + "documentation":"

    The pagination token for the next page of results.

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

    The response structure for ListEnterpriseSupportLinkedAccountCharges.

    " + }, "ListSourceViewsForBillingViewRequest":{ "type":"structure", "required":["arn"], @@ -1462,6 +1997,112 @@ "DISABLED" ] }, + "PricingPlan":{ + "type":"structure", + "required":["tiers"], + "members":{ + "pricingPlanId":{ + "shape":"String", + "documentation":"

    The unique identifier for the pricing plan.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the pricing plan.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    A description of the pricing plan.

    " + }, + "startDate":{ + "shape":"Timestamp", + "documentation":"

    The start date of the pricing plan.

    " + }, + "endDate":{ + "shape":"Timestamp", + "documentation":"

    The end date of the pricing plan.

    " + }, + "planDiscountPercent":{ + "shape":"String", + "documentation":"

    The discount percentage applied by this pricing plan.

    " + }, + "discountAppliesToMinimumCharge":{ + "shape":"Boolean", + "documentation":"

    Whether the discount applies to the minimum Support charge.

    " + }, + "minimumCharge":{ + "shape":"String", + "documentation":"

    The minimum Support charge amount for this pricing plan.

    " + }, + "tiered":{ + "shape":"String", + "documentation":"

    Whether the pricing plan uses tiered pricing.

    " + }, + "tiers":{ + "shape":"PricingPlanTierList", + "documentation":"

    The pricing tiers within this plan.

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

    A pricing plan for Enterprise Support billing.

    " + }, + "PricingPlanList":{ + "type":"list", + "member":{"shape":"PricingPlan"}, + "documentation":"

    A list of pricing plans.

    ", + "max":10, + "min":0 + }, + "PricingPlanTier":{ + "type":"structure", + "required":[ + "tierMinimum", + "baseCharge", + "additionalPercentageOfAggregateCharges", + "aggregateChargesAdjustment", + "incremental" + ], + "members":{ + "tierMinimum":{ + "shape":"String", + "documentation":"

    The minimum spend threshold for this tier.

    " + }, + "tierMaximum":{ + "shape":"String", + "documentation":"

    The maximum spend threshold for this tier.

    " + }, + "baseCharge":{ + "shape":"String", + "documentation":"

    The base charge for this tier.

    " + }, + "additionalPercentageOfAggregateCharges":{ + "shape":"String", + "documentation":"

    The additional percentage applied to aggregate charges in this tier.

    " + }, + "aggregateChargesAdjustment":{ + "shape":"String", + "documentation":"

    The adjustment applied to aggregate charges.

    " + }, + "incremental":{ + "shape":"Boolean", + "documentation":"

    Whether the tier charges are calculated incrementally.

    " + }, + "increment":{ + "shape":"String", + "documentation":"

    The increment amount for incremental tier calculations.

    " + }, + "incrementCharge":{ + "shape":"String", + "documentation":"

    The charge per increment.

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

    A tier within an Enterprise Support pricing plan.

    " + }, + "PricingPlanTierList":{ + "type":"list", + "member":{"shape":"PricingPlanTier"}, + "documentation":"

    A list of pricing plan tiers.

    ", + "max":20, + "min":0 + }, "ProductName":{ "type":"string", "max":128, @@ -1596,6 +2237,27 @@ "max":1024, "min":1 }, + "ServiceLevelAccountUsage":{ + "type":"structure", + "members":{ + "serviceCode":{ + "shape":"String", + "documentation":"

    The service code for which to return Support-eligible spend data.

    " + }, + "totalSupportEligibleSpend":{ + "shape":"String", + "documentation":"

    The total support-eligible spend for the service.

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

    Service-level usage details by account.

    " + }, + "ServiceLevelAccountUsageList":{ + "type":"list", + "member":{"shape":"ServiceLevelAccountUsage"}, + "documentation":"

    A list of service-level account usages.

    ", + "max":200, + "min":0 + }, "ServiceQuotaExceededException":{ "type":"structure", "required":[ @@ -1710,6 +2372,13 @@ "documentation":"

    The request was denied due to request throttling.

    ", "exception":true }, + "TimePeriodList":{ + "type":"list", + "member":{"shape":"EnterpriseSupportTimePeriod"}, + "documentation":"

    A list of time periods.

    ", + "max":500, + "min":0 + }, "TimeRange":{ "type":"structure", "members":{ diff --git a/services/billingconductor/pom.xml b/services/billingconductor/pom.xml index e2b406feff52..5ec4d9e18d57 100644 --- a/services/billingconductor/pom.xml +++ b/services/billingconductor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT billingconductor AWS Java SDK :: Services :: Billingconductor diff --git a/services/billingconductor/src/main/resources/codegen-resources/customization.config b/services/billingconductor/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/billingconductor/src/main/resources/codegen-resources/customization.config +++ b/services/billingconductor/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/billingconductor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/billingconductor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5547fbca651c --- /dev/null +++ b/services/billingconductor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,220 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billingconductor.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "billingconductor", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billingconductor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billingconductor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billingconductor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://billingconductor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABQAAAAgAAAAHAAAABwX14QQF9eELAAAABgX14QkF9eEKAAAABAAAAAsAAAAKAAAABQX14QYF9eEIAAAABQAAAAwF9eEHAAAABgX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/billingconductor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/billingconductor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8b0944e45089..000000000000 --- a/services/billingconductor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://billingconductor.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "billingconductor", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billingconductor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billingconductor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://billingconductor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://billingconductor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/billingconductor/src/main/resources/codegen-resources/service-2.json b/services/billingconductor/src/main/resources/codegen-resources/service-2.json index 3dfe1b4b2575..7ee89b065746 100644 --- a/services/billingconductor/src/main/resources/codegen-resources/service-2.json +++ b/services/billingconductor/src/main/resources/codegen-resources/service-2.json @@ -310,6 +310,25 @@ "documentation":"

    Retrieves the margin summary report, which includes the Amazon Web Services cost and charged amount (pro forma cost) by Amazon Web Services service for a specific billing group.

    ", "readonly":true }, + "GetBillingTransferPreference":{ + "name":"GetBillingTransferPreference", + "http":{ + "method":"POST", + "requestUri":"/get-billing-transfer-preference", + "responseCode":200 + }, + "input":{"shape":"GetBillingTransferPreferenceInput"}, + "output":{"shape":"GetBillingTransferPreferenceOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Retrieves the auto billing group creation preference for a billing transfer.

    ", + "readonly":true + }, "ListAccountAssociations":{ "name":"ListAccountAssociations", "http":{ @@ -571,6 +590,26 @@ "documentation":"

    This updates an existing billing group.

    ", "idempotent":true }, + "UpdateBillingTransferPreference":{ + "name":"UpdateBillingTransferPreference", + "http":{ + "method":"PUT", + "requestUri":"/update-billing-transfer-preference", + "responseCode":200 + }, + "input":{"shape":"UpdateBillingTransferPreferenceInput"}, + "output":{"shape":"UpdateBillingTransferPreferenceOutput"}, + "errors":[ + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Sets the auto billing group creation preference for a billing transfer. When the preference is enabled, Billing Conductor automatically creates an indirect billing transfer billing group in your account, with the pricing plan that you specify, for each account that transfers its bill to the bill source account of this billing transfer. The preference applies only to billing groups that are created after you enable it.

    Enabling the preference requires the iam:CreateServiceLinkedRole permission. While a pricing plan is specified in an enabled preference, you can't delete that pricing plan.

    ", + "idempotent":true + }, "UpdateCustomLineItem":{ "name":"UpdateCustomLineItem", "http":{ @@ -849,6 +888,21 @@ "type":"list", "member":{"shape":"Attribute"} }, + "AutoTransferBillingGroupCreationPreference":{ + "type":"structure", + "required":["Enabled"], + "members":{ + "Enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether Billing Conductor automatically creates billing groups for the billing transfer. The preference is disabled by default.

    " + }, + "PricingPlanArn":{ + "shape":"PricingPlanArn", + "documentation":"

    The Amazon Resource Name (ARN) of the pricing plan to apply to the automatically created billing groups. This value is required when Enabled is true, and must be omitted when Enabled is false.

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

    The auto billing group creation preference for a billing transfer. When the preference is enabled, Billing Conductor automatically creates an indirect billing transfer billing group, with the specified pricing plan, for each account that transfers its bill to the bill source account of the billing transfer.

    " + }, "BatchAssociateResourcesToCustomLineItemInput":{ "type":"structure", "required":[ @@ -1183,6 +1237,7 @@ "RESOURCE_NAME_CONFLICT", "PRICING_RULE_IN_PRICING_PLAN_CONFLICT", "PRICING_PLAN_ATTACHED_TO_BILLING_GROUP_DELETE_CONFLICT", + "PRICING_PLAN_REFERENCED_BY_PREFERENCE_DELETE_CONFLICT", "PRICING_RULE_ATTACHED_TO_PRICING_PLAN_DELETE_CONFLICT", "WRITE_CONFLICT_RETRY" ] @@ -1421,11 +1476,14 @@ }, "CreateTieringInput":{ "type":"structure", - "required":["FreeTier"], "members":{ "FreeTier":{ "shape":"CreateFreeTierConfig", "documentation":"

    The possible Amazon Web Services Free Tier configurations.

    " + }, + "CustomTiers":{ + "shape":"CustomTiersList", + "documentation":"

    The set of custom tiers for the pricing rule.

    " } }, "documentation":"

    The set of tiering configurations for the pricing rule.

    " @@ -1717,6 +1775,49 @@ }, "documentation":"

    A representation of a custom line item version.

    " }, + "CustomTier":{ + "type":"structure", + "required":[ + "BeginRangeInclusive", + "RateValue" + ], + "members":{ + "BeginRangeInclusive":{ + "shape":"CustomTierBeginRangeInclusive", + "documentation":"

    The inclusive start of the usage range that this tier applies to.

    " + }, + "EndRangeExclusive":{ + "shape":"CustomTierEndRangeExclusive", + "documentation":"

    The exclusive end of the usage range that this tier applies to. If you don't specify a value, this tier applies to all usage that is greater than or equal to BeginRangeInclusive.

    " + }, + "RateValue":{ + "shape":"CustomTierRateValue", + "documentation":"

    The rate that's applied to the usage that falls within this tier.

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

    A custom tier for the pricing rule. Each custom tier applies a rate to the usage that falls within the tier's range.

    " + }, + "CustomTierBeginRangeInclusive":{ + "type":"double", + "box":true, + "min":0 + }, + "CustomTierEndRangeExclusive":{ + "type":"double", + "box":true, + "min":0 + }, + "CustomTierRateValue":{ + "type":"double", + "box":true, + "min":0 + }, + "CustomTiersList":{ + "type":"list", + "member":{"shape":"CustomTier"}, + "max":10, + "min":1 + }, "DeleteBillingGroupInput":{ "type":"structure", "required":["Arn"], @@ -1914,6 +2015,38 @@ } } }, + "GetBillingTransferPreferenceInput":{ + "type":"structure", + "required":["ResponsibilityTransferArn"], + "members":{ + "ResponsibilityTransferArn":{ + "shape":"ResponsibilityTransferArn", + "documentation":"

    The Amazon Resource Name (ARN) of the billing transfer whose preference you want to retrieve.

    " + } + } + }, + "GetBillingTransferPreferenceOutput":{ + "type":"structure", + "required":[ + "ResponsibilityTransferArn", + "AutoBillingTransferBillingGroupCreation" + ], + "members":{ + "ResponsibilityTransferArn":{ + "shape":"ResponsibilityTransferArn", + "documentation":"

    The Amazon Resource Name (ARN) of the billing transfer that the preference applies to.

    " + }, + "AutoBillingTransferBillingGroupCreation":{ + "shape":"AutoTransferBillingGroupCreationPreference", + "documentation":"

    The auto billing group creation preference for the billing transfer.

    " + }, + "LastModifiedTime":{ + "shape":"Instant", + "documentation":"

    The most recent time when the preference was modified. This value is empty if the preference has never been set for the billing transfer.

    ", + "box":true + } + } + }, "GroupByAttributeName":{ "type":"string", "enum":[ @@ -3048,11 +3181,14 @@ }, "Tiering":{ "type":"structure", - "required":["FreeTier"], "members":{ "FreeTier":{ "shape":"FreeTierConfig", "documentation":"

    The possible Amazon Web Services Free Tier configurations.

    " + }, + "CustomTiers":{ + "shape":"CustomTiersList", + "documentation":"

    The set of custom tiers for the pricing rule.

    " } }, "documentation":"

    The set of tiering configurations for the pricing rule.

    " @@ -3176,6 +3312,52 @@ } } }, + "UpdateBillingTransferPreferenceInput":{ + "type":"structure", + "required":[ + "ResponsibilityTransferArn", + "AutoBillingTransferBillingGroupCreation" + ], + "members":{ + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you specify to ensure idempotency of the request. Idempotency ensures that an API request completes no more than one time. With an idempotent request, if the original request completes successfully, any subsequent retries complete successfully without performing any further actions.

    ", + "idempotencyToken":true, + "location":"header", + "locationName":"X-Amzn-Client-Token" + }, + "ResponsibilityTransferArn":{ + "shape":"ResponsibilityTransferArn", + "documentation":"

    The Amazon Resource Name (ARN) of the billing transfer whose preference you want to set.

    " + }, + "AutoBillingTransferBillingGroupCreation":{ + "shape":"AutoTransferBillingGroupCreationPreference", + "documentation":"

    The auto billing group creation preference to set for the billing transfer.

    " + } + } + }, + "UpdateBillingTransferPreferenceOutput":{ + "type":"structure", + "required":[ + "ResponsibilityTransferArn", + "AutoBillingTransferBillingGroupCreation", + "LastModifiedTime" + ], + "members":{ + "ResponsibilityTransferArn":{ + "shape":"ResponsibilityTransferArn", + "documentation":"

    The Amazon Resource Name (ARN) of the billing transfer that the preference applies to.

    " + }, + "AutoBillingTransferBillingGroupCreation":{ + "shape":"AutoTransferBillingGroupCreationPreference", + "documentation":"

    The updated auto billing group creation preference for the billing transfer.

    " + }, + "LastModifiedTime":{ + "shape":"Instant", + "documentation":"

    The most recent time when the preference was modified.

    " + } + } + }, "UpdateCustomLineItemChargeDetails":{ "type":"structure", "members":{ @@ -3415,11 +3597,14 @@ }, "UpdateTieringInput":{ "type":"structure", - "required":["FreeTier"], "members":{ "FreeTier":{ "shape":"UpdateFreeTierConfig", "documentation":"

    The possible Amazon Web Services Free Tier configurations.

    " + }, + "CustomTiers":{ + "shape":"CustomTiersList", + "documentation":"

    The set of custom tiers for the pricing rule.

    " } }, "documentation":"

    The set of tiering configurations for the pricing rule.

    " diff --git a/services/braket/pom.xml b/services/braket/pom.xml index b7ca5ac3e782..8c31e403133b 100644 --- a/services/braket/pom.xml +++ b/services/braket/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT braket AWS Java SDK :: Services :: Braket diff --git a/services/braket/src/main/resources/codegen-resources/customization.config b/services/braket/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/braket/src/main/resources/codegen-resources/customization.config +++ b/services/braket/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/braket/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/braket/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b1ad8764815f --- /dev/null +++ b/services/braket/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://braket-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://braket-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://braket.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://braket.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/braket/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/braket/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a05400f8a7f2..000000000000 --- a/services/braket/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://braket-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://braket-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://braket.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://braket.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/budgets/pom.xml b/services/budgets/pom.xml index 18732540e5ff..7860d755402a 100644 --- a/services/budgets/pom.xml +++ b/services/budgets/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT budgets AWS Java SDK :: Services :: AWS Budgets diff --git a/services/budgets/src/main/resources/codegen-resources/customization.config b/services/budgets/src/main/resources/codegen-resources/customization.config index 6afa5b2bbf61..98db9ee2f344 100644 --- a/services/budgets/src/main/resources/codegen-resources/customization.config +++ b/services/budgets/src/main/resources/codegen-resources/customization.config @@ -9,6 +9,5 @@ } ] } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/budgets/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/budgets/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9cde5c082eec --- /dev/null +++ b/services/budgets/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,371 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.global.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.global.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.global.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.eusc-de-east-1.api.amazonwebservices.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets-fips.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets-fips.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://budgets.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 19, + "nodes": "/////wAAAAH/////AAAAAAAAABIAAAADAAAAAQAAAAQF9eEQAAAAAgAAAAUF9eEQAAAAAwAAAA4AAAAGAAAABQAAAAsAAAAHAAAABgX14QUAAAAIAAAABwX14QYAAAAJAAAACQX14QcAAAAKAAAACgX14QgF9eEPAAAACAX14QQAAAAMAAAACgX14QgAAAANAAAACwX14Q0F9eEOAAAABAAAABAAAAAPAAAABQX14QoF9eEMAAAABQAAABEF9eELAAAACwX14QkF9eEKAAAAAwX14QEAAAATAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/budgets/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/budgets/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f73b0320a292..000000000000 --- a/services/budgets/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,672 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://budgets.us-east-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://budgets.global.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://budgets.global.cloud.adc-e.uk", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eu-isoe-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://budgets.global.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://budgets.eusc-de-east-1.api.amazonwebservices.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://budgets.eusc-de-east-1.api.amazonwebservices.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://budgets-fips.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://budgets-fips.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://budgets.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://budgets.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/chatbot/pom.xml b/services/chatbot/pom.xml index fab08e0664e0..415881ea6372 100644 --- a/services/chatbot/pom.xml +++ b/services/chatbot/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chatbot AWS Java SDK :: Services :: Chatbot diff --git a/services/chatbot/src/main/resources/codegen-resources/customization.config b/services/chatbot/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chatbot/src/main/resources/codegen-resources/customization.config +++ b/services/chatbot/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chatbot/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chatbot/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3a96601c5d55 --- /dev/null +++ b/services/chatbot/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chatbot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chatbot-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chatbot.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chatbot.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chatbot/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chatbot/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a07bd9a2ca05..000000000000 --- a/services/chatbot/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chatbot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chatbot-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chatbot.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chatbot.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/chime/pom.xml b/services/chime/pom.xml index bc859c9db1a7..c6c24920cb42 100644 --- a/services/chime/pom.xml +++ b/services/chime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chime AWS Java SDK :: Services :: Chime diff --git a/services/chime/src/main/resources/codegen-resources/customization.config b/services/chime/src/main/resources/codegen-resources/customization.config index 0e77f570c68a..4be2534ecac2 100644 --- a/services/chime/src/main/resources/codegen-resources/customization.config +++ b/services/chime/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "listAccounts" ], - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/chime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d8603fad2be7 --- /dev/null +++ b/services/chime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,220 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chime.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "chime", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABQAAAAgAAAAHAAAABwX14QQF9eELAAAABgX14QkF9eEKAAAABAAAAAsAAAAKAAAABQX14QYF9eEIAAAABQAAAAwF9eEHAAAABgX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/chime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 25eec8e91e7d..000000000000 --- a/services/chime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,365 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://chime.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "chime", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkidentity/pom.xml b/services/chimesdkidentity/pom.xml index 1a43463529b3..4b55d0469adc 100644 --- a/services/chimesdkidentity/pom.xml +++ b/services/chimesdkidentity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chimesdkidentity AWS Java SDK :: Services :: Chime SDK Identity diff --git a/services/chimesdkidentity/src/main/resources/codegen-resources/customization.config b/services/chimesdkidentity/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chimesdkidentity/src/main/resources/codegen-resources/customization.config +++ b/services/chimesdkidentity/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..80b6b0eee788 --- /dev/null +++ b/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identity-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identity-chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identity-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identity-chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2e2afb08b2bc..000000000000 --- a/services/chimesdkidentity/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://identity-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://identity-chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://identity-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://identity-chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkmediapipelines/pom.xml b/services/chimesdkmediapipelines/pom.xml index fc4cec365f4a..337d659964a4 100644 --- a/services/chimesdkmediapipelines/pom.xml +++ b/services/chimesdkmediapipelines/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chimesdkmediapipelines AWS Java SDK :: Services :: Chime SDK Media Pipelines diff --git a/services/chimesdkmediapipelines/src/main/resources/codegen-resources/customization.config b/services/chimesdkmediapipelines/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chimesdkmediapipelines/src/main/resources/codegen-resources/customization.config +++ b/services/chimesdkmediapipelines/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1322a017e9ee --- /dev/null +++ b/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://media-pipelines-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://media-pipelines-chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://media-pipelines-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://media-pipelines-chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8bffe9a5ad89..000000000000 --- a/services/chimesdkmediapipelines/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://media-pipelines-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://media-pipelines-chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://media-pipelines-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://media-pipelines-chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkmeetings/pom.xml b/services/chimesdkmeetings/pom.xml index 846671d2ad7e..ed1521d95dee 100644 --- a/services/chimesdkmeetings/pom.xml +++ b/services/chimesdkmeetings/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chimesdkmeetings AWS Java SDK :: Services :: Chime SDK Meetings diff --git a/services/chimesdkmeetings/src/main/resources/codegen-resources/customization.config b/services/chimesdkmeetings/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chimesdkmeetings/src/main/resources/codegen-resources/customization.config +++ b/services/chimesdkmeetings/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b10716bdbefe --- /dev/null +++ b/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://meetings-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://meetings-chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://meetings-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://meetings-chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f96fa75c7ddb..000000000000 --- a/services/chimesdkmeetings/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://meetings-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://meetings-chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://meetings-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://meetings-chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkmessaging/pom.xml b/services/chimesdkmessaging/pom.xml index b85ebd859442..dc92a27ea8f4 100644 --- a/services/chimesdkmessaging/pom.xml +++ b/services/chimesdkmessaging/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chimesdkmessaging AWS Java SDK :: Services :: Chime SDK Messaging diff --git a/services/chimesdkmessaging/src/main/resources/codegen-resources/customization.config b/services/chimesdkmessaging/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chimesdkmessaging/src/main/resources/codegen-resources/customization.config +++ b/services/chimesdkmessaging/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4d7669729e33 --- /dev/null +++ b/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://messaging-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://messaging-chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://messaging-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://messaging-chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6232bfbb1973..000000000000 --- a/services/chimesdkmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://messaging-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://messaging-chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://messaging-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://messaging-chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkvoice/pom.xml b/services/chimesdkvoice/pom.xml index 034aba218231..d02311d92715 100644 --- a/services/chimesdkvoice/pom.xml +++ b/services/chimesdkvoice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT chimesdkvoice AWS Java SDK :: Services :: Chime SDK Voice diff --git a/services/chimesdkvoice/src/main/resources/codegen-resources/customization.config b/services/chimesdkvoice/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/chimesdkvoice/src/main/resources/codegen-resources/customization.config +++ b/services/chimesdkvoice/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3a453c81fb5d --- /dev/null +++ b/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voice-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voice-chime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voice-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voice-chime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 42c0181d06b1..000000000000 --- a/services/chimesdkvoice/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voice-chime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voice-chime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voice-chime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voice-chime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/chimesdkvoice/src/main/resources/codegen-resources/service-2.json b/services/chimesdkvoice/src/main/resources/codegen-resources/service-2.json index 56b19e62ccbe..ccfc63ed4f11 100644 --- a/services/chimesdkvoice/src/main/resources/codegen-resources/service-2.json +++ b/services/chimesdkvoice/src/main/resources/codegen-resources/service-2.json @@ -134,7 +134,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Creates a proxy session for the specified Amazon Chime SDK Voice Connector for the specified participant phone numbers.

    " + "documentation":"

    Creates a proxy session for the specified Amazon Chime SDK Voice Connector for the specified participant phone numbers.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_CreateProxySession.html", + "deprecatedSince":"2026-04-07" }, "CreateSipMediaApplication":{ "name":"CreateSipMediaApplication", @@ -233,6 +236,7 @@ "output":{"shape":"CreateVoiceConnectorGroupResponse"}, "errors":[ {"shape":"BadRequestException"}, + {"shape":"NotFoundException"}, {"shape":"ForbiddenException"}, {"shape":"AccessDeniedException"}, {"shape":"UnauthorizedClientException"}, @@ -325,7 +329,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Deletes the specified proxy session from the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Deletes the specified proxy session from the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_DeleteProxySession.html", + "deprecatedSince":"2026-04-07" }, "DeleteSipMediaApplication":{ "name":"DeleteSipMediaApplication", @@ -482,7 +489,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Deletes the proxy configuration from the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Deletes the proxy configuration from the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_DeleteVoiceConnectorProxy.html", + "deprecatedSince":"2026-04-07" }, "DeleteVoiceConnectorStreamingConfiguration":{ "name":"DeleteVoiceConnectorStreamingConfiguration", @@ -716,7 +726,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Retrieves the specified proxy session details for the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Retrieves the specified proxy session details for the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_GetProxySession.html", + "deprecatedSince":"2026-04-07" }, "GetSipMediaApplication":{ "name":"GetSipMediaApplication", @@ -752,6 +765,7 @@ {"shape":"NotFoundException"}, {"shape":"ForbiddenException"}, {"shape":"BadRequestException"}, + {"shape":"GoneException"}, {"shape":"ThrottledClientException"}, {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} @@ -960,7 +974,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Retrieves the proxy configuration details for the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Retrieves the proxy configuration details for the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_GetVoiceConnectorProxy.html", + "deprecatedSince":"2026-04-07" }, "GetVoiceConnectorStreamingConfiguration":{ "name":"GetVoiceConnectorStreamingConfiguration", @@ -1160,7 +1177,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Lists the proxy sessions for the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Lists the proxy sessions for the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_ListProxySessions.html", + "deprecatedSince":"2026-04-07" }, "ListSipMediaApplications":{ "name":"ListSipMediaApplications", @@ -1192,6 +1212,7 @@ "output":{"shape":"ListSipRulesResponse"}, "errors":[ {"shape":"UnauthorizedClientException"}, + {"shape":"NotFoundException"}, {"shape":"ForbiddenException"}, {"shape":"BadRequestException"}, {"shape":"ThrottledClientException"}, @@ -1350,6 +1371,7 @@ {"shape":"NotFoundException"}, {"shape":"ForbiddenException"}, {"shape":"BadRequestException"}, + {"shape":"GoneException"}, {"shape":"ThrottledClientException"}, {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} @@ -1455,6 +1477,7 @@ {"shape":"ForbiddenException"}, {"shape":"BadRequestException"}, {"shape":"ThrottledClientException"}, + {"shape":"AccessDeniedException"}, {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], @@ -1478,7 +1501,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Puts the specified proxy configuration to the specified Amazon Chime SDK Voice Connector.

    " + "documentation":"

    Puts the specified proxy configuration to the specified Amazon Chime SDK Voice Connector.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_PutVoiceConnectorProxy.html", + "deprecatedSince":"2026-04-07" }, "PutVoiceConnectorStreamingConfiguration":{ "name":"PutVoiceConnectorStreamingConfiguration", @@ -1786,7 +1812,10 @@ {"shape":"ServiceUnavailableException"}, {"shape":"ServiceFailureException"} ], - "documentation":"

    Updates the specified proxy session details, such as voice or SMS capabilities.

    " + "documentation":"

    Updates the specified proxy session details, such as voice or SMS capabilities.

    End of support notice: On April 7, 2026, AWS will end support for Amazon Chime SDK proxy sessions.

    ", + "deprecated":true, + "deprecatedMessage":"End of support notice: On April 7, 2026, AWS ended support for Amazon Chime SDK proxy sessions. For more information, refer to https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_voice-chime_UpdateProxySession.html", + "deprecatedSince":"2026-04-07" }, "UpdateSipMediaApplication":{ "name":"UpdateSipMediaApplication", @@ -2087,7 +2116,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2161,7 +2190,7 @@ "type":"structure", "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    " }, "TransactionId":{ @@ -2175,6 +2204,13 @@ }, "documentation":"

    The details of an Amazon Chime SDK Voice Connector call.

    " }, + "CallDistributionType":{ + "type":"string", + "enum":[ + "PriorityWeightedDistribution", + "LoadBalancedDistribution" + ] + }, "CallLegType":{ "type":"string", "enum":[ @@ -2332,7 +2368,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2457,7 +2493,8 @@ "required":[ "Name", "TriggerType", - "TriggerValue" + "TriggerValue", + "TargetApplications" ], "members":{ "Name":{ @@ -2502,7 +2539,8 @@ "VoiceConnectorItems":{ "shape":"VoiceConnectorItemList", "documentation":"

    Lists the Voice Connectors that inbound calls are routed to.

    " - } + }, + "CallDistributionType":{"shape":"CallDistributionType"} } }, "CreateVoiceConnectorGroupResponse":{ @@ -2539,11 +2577,11 @@ }, "IntegrationType":{ "shape":"VoiceConnectorIntegrationType", - "documentation":"

    The connectors for use with Connect Customer.

    The following options are available:

    • CONNECT_CALL_TRANSFER_CONNECTOR - Enables enterprises to integrate Connect Customer with other voice systems to directly transfer voice calls and metadata without using the public telephone network. They can use Connect Customer telephony and Interactive Voice Response (IVR) with their existing voice systems to modernize the IVR experience of their existing contact center and their enterprise and branch voice systems. Additionally, enterprises migrating their contact center to Connect Customer can start with Connect telephony and IVR for immediate modernization ahead of agent migration.

    • CONNECT_ANALYTICS_CONNECTOR - Enables enterprises to integrate Connect Customer with other voice systems for real-time and post-call analytics. They can use Connect Customer Contact Lens with their existing voice systems to provides call recordings, conversational analytics (including contact transcript, sensitive data redaction, content categorization, theme detection, sentiment analysis, real-time alerts, and post-contact summary), and agent performance evaluations (including evaluation forms, automated evaluation, supervisor review) with a rich user experience to display, search and filter customer interactions, and programmatic access to data streams and the data lake. Additionally, enterprises migrating their contact center to Connect Customer can start with Contact Lens analytics and performance insights ahead of agent migration.

    " + "documentation":"

    The connectors for use with Connect Customer.

    The following options are available:

    • CONNECT_CALL_TRANSFER_CONNECTOR - Enables enterprises to integrate Connect Customer with other voice systems to directly transfer voice calls and metadata without using the public telephone network. They can use Connect Customer telephony and Interactive Voice Response (IVR) with their existing voice systems to modernize the IVR experience of their existing contact center and their enterprise and branch voice systems. Additionally, enterprises migrating their contact center to Connect Customer can start with Connect telephony and IVR for immediate modernization ahead of agent migration.

      This integration is a gated feature. Please reach out to your account team to discuss this feature with a Connect Specialist.

    • CONNECT_ANALYTICS_CONNECTOR - Enables enterprises to integrate Connect Customer with other voice systems for real-time and post-call analytics. They can use Connect Customer Contact Lens with their existing voice systems to provides call recordings, conversational analytics (including contact transcript, sensitive data redaction, content categorization, theme detection, sentiment analysis, real-time alerts, and post-contact summary), and agent performance evaluations (including evaluation forms, automated evaluation, supervisor review) with a rich user experience to display, search and filter customer interactions, and programmatic access to data streams and the data lake. Additionally, enterprises migrating their contact center to Connect Customer can start with Contact Lens analytics and performance insights ahead of agent migration.

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

    The type of network for the Voice Connector. Either IPv4 only or dual-stack (IPv4 and IPv6).

    " + "documentation":"

    The type of network for the Voice Connector.

    " } } }, @@ -2681,7 +2719,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2723,7 +2761,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2735,7 +2773,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The ID of the Voice Connector for which to delete the external system configuration.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2759,7 +2797,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2771,7 +2809,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2783,7 +2821,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2795,7 +2833,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2810,7 +2848,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2826,7 +2864,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2893,7 +2931,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -2950,7 +2988,8 @@ "Unprocessable", "VoiceConnectorGroupAssociationsExist", "PhoneNumberAssociationsExist", - "Gone" + "Gone", + "Validation" ] }, "ExternalSystemsConfiguration":{ @@ -3077,7 +3116,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3191,7 +3230,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -3218,7 +3257,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3239,7 +3278,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The ID of the Voice Connector for which to return information about the external system configuration.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3281,7 +3320,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3302,7 +3341,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3323,7 +3362,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3344,7 +3383,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3365,7 +3404,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3386,7 +3425,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3407,7 +3446,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3474,7 +3513,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -3535,7 +3574,7 @@ "type":"structure", "members":{ "NextToken":{ - "shape":"String", + "shape":"NextTokenString", "documentation":"

    The token used to retrieve the next page of results.

    ", "location":"querystring", "locationName":"next-token" @@ -3620,7 +3659,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -3801,7 +3840,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4119,6 +4158,7 @@ "shape":"E164PhoneNumber", "documentation":"

    The phone number, in E.164 format.

    " }, + "PhoneNumberArn":{"shape":"NonEmptyString"}, "Country":{ "shape":"Alpha2CountryCode", "documentation":"

    The phone number's country. Format: ISO 3166-1 alpha-2.

    " @@ -4322,7 +4362,7 @@ "documentation":"

    The updated phone number order time stamp, in ISO 8601 format.

    " }, "FocDate":{ - "shape":"Iso8601Timestamp", + "shape":"String", "documentation":"

    The Firm Order Commitment (FOC) date for phone number porting orders. This field is null if a phone number order is not a porting order.

    " } }, @@ -4424,7 +4464,7 @@ "type":"structure", "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    " }, "ProxySessionId":{ @@ -4553,7 +4593,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4578,7 +4618,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The ID of the Voice Connector for which to add the external system configuration.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4610,7 +4650,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4638,7 +4678,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4667,7 +4707,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4707,7 +4747,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4732,7 +4772,7 @@ "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4751,7 +4791,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -4804,6 +4844,12 @@ "max":100, "min":1 }, + "S3BucketName":{ + "type":"string", + "max":64, + "min":1, + "pattern":"(?!(^xn--|.+-s3alias$))^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$" + }, "SMACreateCallArgumentsMap":{ "type":"map", "key":{"shape":"SensitiveString"}, @@ -5205,7 +5251,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -5246,7 +5292,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -5282,7 +5328,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -5303,7 +5349,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"VoiceConnectorId" @@ -5512,6 +5558,7 @@ }, "UpdateGlobalSettingsRequest":{ "type":"structure", + "required":["VoiceConnector"], "members":{ "VoiceConnector":{ "shape":"VoiceConnectorSettings", @@ -5598,7 +5645,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString128", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -5749,7 +5796,8 @@ "VoiceConnectorItems":{ "shape":"VoiceConnectorItemList", "documentation":"

    The VoiceConnectorItems to associate with the Voice Connector group.

    " - } + }, + "CallDistributionType":{"shape":"CallDistributionType"} } }, "UpdateVoiceConnectorGroupResponse":{ @@ -5770,7 +5818,7 @@ ], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    ", "location":"uri", "locationName":"voiceConnectorId" @@ -5923,7 +5971,7 @@ "type":"structure", "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector's ID.

    " }, "AwsRegion":{ @@ -5960,7 +6008,7 @@ }, "NetworkType":{ "shape":"NetworkType", - "documentation":"

    The type of network of the Voice Connector. Either IPv4 only or dual-stack (IPv4 and IPv6).

    " + "documentation":"

    The type of network for the Voice Connector.

    " } }, "documentation":"

    The Amazon Chime SDK Voice Connector configuration, including outbound host name and encryption settings.

    " @@ -6010,7 +6058,8 @@ "VoiceConnectorGroupArn":{ "shape":"NonEmptyString", "documentation":"

    The ARN of the Voice Connector group.

    " - } + }, + "CallDistributionType":{"shape":"CallDistributionType"} }, "documentation":"

    The Amazon Chime SDK Voice Connector group configuration, including associated Voice Connectors. You can include Voice Connectors from different AWS Regions in a group. This creates a fault tolerant mechanism for fallback in case of availability events.

    " }, @@ -6024,6 +6073,10 @@ "min":1, "pattern":"[a-zA-Z0-9 _.-]+" }, + "VoiceConnectorId":{ + "type":"string", + "pattern":"([a-z0-9]{21,22}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})" + }, "VoiceConnectorIntegrationType":{ "type":"string", "enum":[ @@ -6033,13 +6086,10 @@ }, "VoiceConnectorItem":{ "type":"structure", - "required":[ - "VoiceConnectorId", - "Priority" - ], + "required":["VoiceConnectorId"], "members":{ "VoiceConnectorId":{ - "shape":"NonEmptyString", + "shape":"VoiceConnectorId", "documentation":"

    The Voice Connector ID.

    " }, "Priority":{ @@ -6072,7 +6122,7 @@ "type":"structure", "members":{ "CdrBucket":{ - "shape":"String", + "shape":"S3BucketName", "documentation":"

    The S3 bucket that stores the Voice Connector's call detail records.

    " } }, diff --git a/services/cleanrooms/pom.xml b/services/cleanrooms/pom.xml index 0758b2e474a6..44ae2ff4d8f4 100644 --- a/services/cleanrooms/pom.xml +++ b/services/cleanrooms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cleanrooms AWS Java SDK :: Services :: Clean Rooms diff --git a/services/cleanrooms/src/main/resources/codegen-resources/customization.config b/services/cleanrooms/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/cleanrooms/src/main/resources/codegen-resources/customization.config +++ b/services/cleanrooms/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/cleanrooms/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cleanrooms/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0721d6b7c466 --- /dev/null +++ b/services/cleanrooms/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cleanrooms/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cleanrooms/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e0f845d018c8..000000000000 --- a/services/cleanrooms/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/cleanrooms/src/main/resources/codegen-resources/paginators-1.json b/services/cleanrooms/src/main/resources/codegen-resources/paginators-1.json index e1bffdaa906b..570e6eb53d1b 100644 --- a/services/cleanrooms/src/main/resources/codegen-resources/paginators-1.json +++ b/services/cleanrooms/src/main/resources/codegen-resources/paginators-1.json @@ -1,5 +1,11 @@ { "pagination": { + "ListAnalysisLogExports": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "analysisLogExports" + }, "ListAnalysisTemplates": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/cleanrooms/src/main/resources/codegen-resources/service-2.json b/services/cleanrooms/src/main/resources/codegen-resources/service-2.json index 1a69b58a250e..e60bb65deb87 100644 --- a/services/cleanrooms/src/main/resources/codegen-resources/service-2.json +++ b/services/cleanrooms/src/main/resources/codegen-resources/service-2.json @@ -288,7 +288,7 @@ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Creates an intermediate table in a membership. An intermediate table stores a query definition that you can execute later using PopulateIntermediateTable to materialize cached results. The intermediate table is owned by the member with the CAN_QUERY ability. This operation does not execute the stored query.

    " + "documentation":"

    Creates an intermediate table in a membership. The intermediate table is owned by the member with the CAN_QUERY ability. To populate the table with results, use PopulateIntermediateTable.

    " }, "CreateIntermediateTableAnalysisRule":{ "name":"CreateIntermediateTableAnalysisRule", @@ -308,7 +308,7 @@ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Creates an analysis rule for an intermediate table. Only the CUSTOM analysis rule type is supported. The service automatically determines whether the rule is first-party or multi-party restricted based on the intermediate table's inherited constraints. Only the intermediate table owner can call this operation.

    ", + "documentation":"

    Creates an analysis rule for an intermediate table. Only the CUSTOM analysis rule type is supported. Only the intermediate table owner can call this operation.

    ", "idempotent":true }, "CreateMembership":{ @@ -542,7 +542,7 @@ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Deletes an intermediate table. When you delete the table, the service marks it as DELETED, removes its analysis rule and schema, and triggers storage cleanup. This operation is idempotent. Only the intermediate table owner can call this operation.

    ", + "documentation":"

    Deletes an intermediate table. The delete is idempotent. Only the intermediate table owner can call this operation.

    ", "idempotent":true }, "DeleteIntermediateTableAnalysisRule":{ @@ -641,9 +641,28 @@ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Invalidates a specific intermediate table that references the caller's base table. The data provider (base table owner) calls this operation, not the intermediate table owner. By default, invalidation cascades to descendant intermediate tables.

    ", + "documentation":"

    Marks an intermediate table as invalid when it references the caller's base table. The data provider (base table owner) calls this operation, not the intermediate table owner. By default, the operation also marks all descendant intermediate tables as invalid.

    ", "idempotent":true }, + "GetAnalysisLogExport":{ + "name":"GetAnalysisLogExport", + "http":{ + "method":"GET", + "requestUri":"/memberships/{membershipIdentifier}/analysislogexports/{analysisLogExportIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetAnalysisLogExportInput"}, + "output":{"shape":"GetAnalysisLogExportOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns information about an analysis log export, including its current status and, if the export failed, the reason for the failure.

    Poll this operation until the status is SUCCESS or FAILED. An export can't be canceled after it starts.

    ", + "readonly":true + }, "GetAnalysisTemplate":{ "name":"GetAnalysisTemplate", "http":{ @@ -1061,6 +1080,25 @@ "documentation":"

    Retrieves a schema analysis rule.

    ", "readonly":true }, + "ListAnalysisLogExports":{ + "name":"ListAnalysisLogExports", + "http":{ + "method":"GET", + "requestUri":"/memberships/{membershipIdentifier}/analysislogexports", + "responseCode":200 + }, + "input":{"shape":"ListAnalysisLogExportsInput"}, + "output":{"shape":"ListAnalysisLogExportsOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists analysis log exports, sorted by the most recent export. Results are paginated. Use the nextToken parameter to retrieve additional results.

    ", + "readonly":true + }, "ListAnalysisTemplates":{ "name":"ListAnalysisTemplates", "http":{ @@ -1530,7 +1568,7 @@ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Executes the stored query of an intermediate table to materialize data into managed storage. With this operation, you can perform initial population and subsequent refreshes. Each call creates a new version. The returned analysis ID can be tracked using GetProtectedQuery. Only the intermediate table owner can call this operation.

    " + "documentation":"

    Runs the stored query of an intermediate table and makes the results available for querying. Each call creates a new version. Use GetProtectedQuery with the returned analysis ID to track progress. Only the intermediate table owner can call this operation.

    " }, "PreviewPrivacyImpact":{ "name":"PreviewPrivacyImpact", @@ -1550,6 +1588,25 @@ ], "documentation":"

    An estimate of the number of aggregation functions that the member who can query can run given epsilon and noise parameters.

    " }, + "StartAnalysisLogExport":{ + "name":"StartAnalysisLogExport", + "http":{ + "method":"POST", + "requestUri":"/memberships/{membershipIdentifier}/analysislogexports", + "responseCode":200 + }, + "input":{"shape":"StartAnalysisLogExportInput"}, + "output":{"shape":"StartAnalysisLogExportOutput"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Starts an export of the Apache Spark logs for a protected query to an Amazon S3 bucket that you own. Use the exported logs to diagnose a query that failed or that ran more slowly than you expected.

    Clean Rooms exports a redacted copy of the Spark logs instead of the raw logs. Analyze the exported logs with the tooling of your choice, such as Spark History Server. For details about what the exported logs contain, see https://docs.aws.amazon.com/clean-rooms/latest/userguide/export-analysis-logs-contents.html.

    The export runs asynchronously and returns with a status of IN_PROGRESS. Call GetAnalysisLogExport to poll for the final status.

    To use this operation, you must have the CAN_EXPORT_QUERY_ANALYSIS_LOG ability for your membership. You must also be the query runner or the query payer. Having the ability alone is not sufficient.

    The query must have reached a terminal state, and it must have reached the execution stage. A query that failed validation or that was canceled before it started produces no Spark logs.

    Log export isn't supported for queries that use differential privacy, and isn't supported for PySpark jobs.

    The destination bucket must be in the same Amazon Web Services Region as the collaboration. Cross-Region export isn't supported.

    For more information, see https://docs.aws.amazon.com/clean-rooms/latest/userguide/export-analysis-logs.html.

    " + }, "StartProtectedJob":{ "name":"StartProtectedJob", "http":{ @@ -1721,6 +1778,7 @@ "output":{"shape":"UpdateConfiguredTableAnalysisRuleOutput"}, "errors":[ {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, {"shape":"ValidationException"}, @@ -2152,6 +2210,60 @@ "member":{"shape":"AggregationConstraint"}, "min":1 }, + "AggregationThreshold":{ + "type":"structure", + "required":[ + "identityColumns", + "minimumIdentityCount", + "type", + "allowedAggregateExpressionType" + ], + "members":{ + "identityColumns":{ + "shape":"AggregationThresholdIdentityColumnsList", + "documentation":"

    The identity column, such as user_id, whose distinct values Clean Rooms counts to enforce minimum aggregation thresholds. Currently, you can specify only one column, and its data type must be string, varchar, or char.

    " + }, + "minimumIdentityCount":{ + "shape":"AggregationThresholdMinimumIdentityCountInteger", + "documentation":"

    The minimum number of distinct identities that each query output group must represent. This threshold applies to all output columns in the table. To override this threshold for a specific column, use outputColumnThresholds.

    " + }, + "type":{ + "shape":"AggregationThresholdType", + "documentation":"

    The type of aggregation that the threshold enforces. Currently, the only supported value is COUNT_DISTINCT, which counts the distinct values in the identity column.

    " + }, + "outputColumnThresholds":{ + "shape":"OutputColumnThresholdList", + "documentation":"

    The per-column overrides of minimumIdentityCount. An output column without an override uses minimumIdentityCount.

    " + }, + "allowedAggregateExpressionType":{ + "shape":"AllowedAggregateExpressionType", + "documentation":"

    Specifies whether a query can aggregate a transformed column. This applies to the arguments of both aggregate and window functions. Valid values are:

    COLUMNS_ONLY – A query can aggregate only a direct column reference, such as SUM(amount), or a constant. Clean Rooms rejects a query that transforms a column and then aggregates it, such as SUM(amount * 2) or SUM(ROUND(amount)).

    ANY_EXPRESSION – A query can aggregate any expression. This includes arithmetic, such as SUM(price * quantity); a cast, such as SUM(CAST(amount AS DECIMAL)); a nested function call, such as SUM(COALESCE(amount, 0)); and a conditional, such as SUM(CASE WHEN region = 'EU' THEN amount ELSE 0 END).

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

    Specifies the minimum number of distinct identities that each query output group must represent.

    " + }, + "AggregationThresholdIdentityColumnsList":{ + "type":"list", + "member":{"shape":"AnalysisRuleColumnName"}, + "max":1, + "min":1 + }, + "AggregationThresholdList":{ + "type":"list", + "member":{"shape":"AggregationThreshold"}, + "max":1, + "min":1 + }, + "AggregationThresholdMinimumIdentityCountInteger":{ + "type":"integer", + "box":true, + "max":100000, + "min":2 + }, + "AggregationThresholdType":{ + "type":"string", + "enum":["COUNT_DISTINCT"] + }, "AggregationType":{ "type":"string", "enum":["COUNT_DISTINCT"] @@ -2162,6 +2274,13 @@ "max":25, "min":0 }, + "AllowedAggregateExpressionType":{ + "type":"string", + "enum":[ + "COLUMNS_ONLY", + "ANY_EXPRESSION" + ] + }, "AllowedAnalysesList":{ "type":"list", "member":{"shape":"AnalysisTemplateArnOrQueryWildcard"} @@ -2196,6 +2315,170 @@ "min":36, "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" }, + "AnalysisLogExport":{ + "type":"structure", + "required":[ + "analysisLogExportId", + "analysisId", + "analysisType", + "membershipId", + "status", + "resultConfiguration", + "createTime", + "updateTime" + ], + "members":{ + "analysisLogExportId":{ + "shape":"AnalysisLogExportIdentifier", + "documentation":"

    The unique identifier of the analysis log export.

    " + }, + "analysisId":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the protected query that the analysis logs were exported for.

    " + }, + "analysisType":{ + "shape":"LogExportAnalysisType", + "documentation":"

    The type of analysis that the logs were exported for. Currently, only PROTECTED_QUERY is supported.

    " + }, + "membershipId":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the membership that the analysis log export belongs to.

    " + }, + "status":{ + "shape":"AnalysisLogExportStatus", + "documentation":"

    The status of the analysis log export. Possible values are:

    • IN_PROGRESS – The export is currently running.

    • SUCCESS – The export completed successfully.

    • FAILED – The export failed. See the error field for details.

    " + }, + "resultConfiguration":{ + "shape":"AnalysisLogExportResultConfiguration", + "documentation":"

    Contains the details needed to write the exported analysis logs.

    " + }, + "createTime":{ + "shape":"Timestamp", + "documentation":"

    The time the analysis log export was created.

    " + }, + "updateTime":{ + "shape":"Timestamp", + "documentation":"

    The time the analysis log export was last updated.

    " + }, + "error":{ + "shape":"AnalysisLogExportError", + "documentation":"

    The analysis log export error. This is present only when the export status is FAILED.

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

    An export of the redacted Apache Spark logs for a protected query.

    " + }, + "AnalysisLogExportError":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"String", + "documentation":"

    The error code for the analysis log export.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    The message for the analysis log export error.

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

    The analysis log export error.

    " + }, + "AnalysisLogExportIdentifier":{ + "type":"string", + "max":36, + "min":36, + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "AnalysisLogExportOutputConfiguration":{ + "type":"structure", + "required":["s3"], + "members":{ + "s3":{ + "shape":"AnalysisLogExportS3OutputConfiguration", + "documentation":"

    Required configuration for an analysis log export with an s3 output type.

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

    Contains configuration details for analysis log export output.

    " + }, + "AnalysisLogExportResultConfiguration":{ + "type":"structure", + "required":["outputConfiguration"], + "members":{ + "outputConfiguration":{ + "shape":"AnalysisLogExportOutputConfiguration", + "documentation":"

    The configuration for analysis log export results.

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

    Contains configurations for analysis log export results.

    " + }, + "AnalysisLogExportS3OutputConfiguration":{ + "type":"structure", + "required":["bucket"], + "members":{ + "bucket":{ + "shape":"AnalysisLogExportS3OutputConfigurationBucketString", + "documentation":"

    The S3 bucket that the exported analysis logs are written to. The bucket must be in the same Amazon Web Services Region as the collaboration.

    " + }, + "keyPrefix":{ + "shape":"KeyPrefix", + "documentation":"

    The S3 key prefix under which the exported analysis logs are written.

    Only one export can be in progress at a time for a given query and destination. To export the same query twice at once, use a different key prefix for the second export.

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

    Contains output information for an analysis log export with an S3 output type.

    The exported logs are written under the bucket and key prefix that you specify. The path includes the collaboration ID, the protected query ID, and the analysis log export ID. Because the path includes the export ID, exporting the same query more than once doesn't overwrite the logs from an earlier export.

    The exported logs are encrypted using the default encryption configuration of the destination bucket. Clean Rooms doesn't accept a KMS key for log export. To encrypt the exported logs with a customer managed key, configure the bucket's default encryption to use that key before you export.

    " + }, + "AnalysisLogExportS3OutputConfigurationBucketString":{ + "type":"string", + "max":63, + "min":3, + "pattern":".*(?!^(\\d+\\.)+\\d+$)(^(([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])$).*" + }, + "AnalysisLogExportStatus":{ + "type":"string", + "enum":[ + "IN_PROGRESS", + "SUCCESS", + "FAILED" + ] + }, + "AnalysisLogExportSummary":{ + "type":"structure", + "required":[ + "analysisLogExportId", + "analysisId", + "analysisType", + "status", + "createTime" + ], + "members":{ + "analysisLogExportId":{ + "shape":"AnalysisLogExportIdentifier", + "documentation":"

    The unique identifier of the analysis log export.

    " + }, + "analysisId":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the protected query that the analysis logs were exported for.

    " + }, + "analysisType":{ + "shape":"LogExportAnalysisType", + "documentation":"

    The type of analysis that the logs were exported for. Currently, only PROTECTED_QUERY is supported.

    " + }, + "status":{ + "shape":"AnalysisLogExportStatus", + "documentation":"

    The status of the analysis log export. Possible values are:

    • IN_PROGRESS – The export is currently running.

    • SUCCESS – The export completed successfully.

    • FAILED – The export failed.

    " + }, + "createTime":{ + "shape":"Timestamp", + "documentation":"

    The time the analysis log export was created.

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

    A summary of an analysis log export, including its identifier, status, analysis type, and creation time. Returned by ListAnalysisLogExports.

    " + }, + "AnalysisLogExportSummaryList":{ + "type":"list", + "member":{"shape":"AnalysisLogExportSummary"} + }, "AnalysisMethod":{ "type":"string", "enum":[ @@ -2364,6 +2647,14 @@ "shape":"DifferentialPrivacyConfiguration", "documentation":"

    The differential privacy configuration.

    " }, + "aggregationThresholds":{ + "shape":"AggregationThresholdList", + "documentation":"

    The aggregation thresholds that each query output group must satisfy. Clean Rooms filters out any group that represents fewer than the specified number of distinct identities. You can specify at most one threshold. You can't use aggregation thresholds with differential privacy, or when allowedAnalyses allows only jobs.

    " + }, + "comparisonControls":{ + "shape":"ComparisonControls", + "documentation":"

    The controls that restrict how a query can compare the columns in the configured table. You can't use comparison controls with differential privacy, or when allowedAnalyses allows only jobs.

    " + }, "allowedResultReceivers":{ "shape":"AllowedResultReceivers", "documentation":"

    The list of Amazon Web Services account IDs that are allowed to receive results from queries run on the configured table.

    " @@ -2373,7 +2664,7 @@ "documentation":"

    The list of allowed additional analyses for the custom analysis rule.

    " } }, - "documentation":"

    A type of analysis rule that enables the table owner to approve custom SQL queries on their configured tables. It supports differential privacy.

    " + "documentation":"

    A type of analysis rule that enables the table owner to approve custom SQL queries on their configured tables. It supports differential privacy, minimum aggregation thresholds, and comparison controls.

    " }, "AnalysisRuleCustomAllowedAnalysesList":{ "type":"list", @@ -2931,7 +3222,9 @@ "enum":[ "ADD_MEMBER", "GRANT_RECEIVE_RESULTS_ABILITY", - "REVOKE_RECEIVE_RESULTS_ABILITY" + "REVOKE_RECEIVE_RESULTS_ABILITY", + "GRANT_EXPORT_QUERY_ANALYSIS_LOG_ABILITY", + "REVOKE_EXPORT_QUERY_ANALYSIS_LOG_ABILITY" ] }, "AutoApprovedChangeTypeList":{ @@ -3332,7 +3625,9 @@ "GRANT_CAN_RECEIVE_MODEL_OUTPUT", "GRANT_CAN_RECEIVE_INFERENCE_OUTPUT", "REVOKE_CAN_RECEIVE_MODEL_OUTPUT", - "REVOKE_CAN_RECEIVE_INFERENCE_OUTPUT" + "REVOKE_CAN_RECEIVE_INFERENCE_OUTPUT", + "GRANT_EXPORT_QUERY_ANALYSIS_LOG_ABILITY", + "REVOKE_EXPORT_QUERY_ANALYSIS_LOG_ABILITY" ] }, "ChangeTypeList":{ @@ -4387,6 +4682,24 @@ "ap-east-2" ] }, + "ComparisonControls":{ + "type":"structure", + "required":[ + "allowedLiteralComparisonColumns", + "allowedColumnComparisonColumns" + ], + "members":{ + "allowedLiteralComparisonColumns":{ + "shape":"AnalysisRuleColumnList", + "documentation":"

    The columns that a query can compare to literal values, for example, in a WHERE clause. Clean Rooms rejects a query that compares any other column to a literal value. Specify an empty list to block literal comparison on every column. You can't specify a column that you also use as an identity column in an aggregation threshold.

    " + }, + "allowedColumnComparisonColumns":{ + "shape":"AnalysisRuleColumnList", + "documentation":"

    The columns that a query can compare to another column, for example, in a join, a WHERE clause, a GROUP BY clause, or a window function. Clean Rooms rejects a query that uses any other column in a column-to-column comparison. Specify an empty list to block column-to-column comparison on every column.

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

    Specifies how a query can compare the columns in a table, including literal comparisons and column-to-column comparisons.

    " + }, "ComputeConfiguration":{ "type":"structure", "members":{ @@ -5168,6 +5481,14 @@ "documentation":"

    Disallowed output columns

    " }, "differentialPrivacy":{"shape":"DifferentialPrivacyConfiguration"}, + "aggregationThresholds":{ + "shape":"AggregationThresholdList", + "documentation":"

    The aggregation thresholds for the consolidated policy.

    " + }, + "comparisonControls":{ + "shape":"ComparisonControls", + "documentation":"

    The comparison controls for the consolidated policy.

    " + }, "allowedResultReceivers":{ "shape":"AllowedResultReceivers", "documentation":"

    The allowed result receivers.

    " @@ -5790,7 +6111,7 @@ }, "populationAnalysisConfiguration":{ "shape":"PopulationAnalysisConfiguration", - "documentation":"

    The configuration that defines the analysis used to populate the intermediate table. This configuration contains the SQL query or analysis template reference.

    " + "documentation":"

    The configuration that defines the analysis used to populate the intermediate table.

    " }, "kmsKeyArn":{ "shape":"KMSKeyArn", @@ -5798,7 +6119,7 @@ }, "retentionInDays":{ "shape":"CreateIntermediateTableInputRetentionInDaysInteger", - "documentation":"

    The number of days to retain populated data versions. Minimum value of 1, maximum value of 365.

    " + "documentation":"

    The number of days to retain populated data versions.

    " }, "tags":{ "shape":"TagMap", @@ -6641,6 +6962,37 @@ "min":1, "pattern":"(?!\\s*$)[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDBFF-\\uDC00\\uDFFF\\t]*" }, + "GetAnalysisLogExportInput":{ + "type":"structure", + "required":[ + "membershipIdentifier", + "analysisLogExportIdentifier" + ], + "members":{ + "membershipIdentifier":{ + "shape":"MembershipIdentifier", + "documentation":"

    A unique identifier for the membership that the analysis log export belongs to. Currently accepts the membership ID.

    ", + "location":"uri", + "locationName":"membershipIdentifier" + }, + "analysisLogExportIdentifier":{ + "shape":"AnalysisLogExportIdentifier", + "documentation":"

    The unique identifier of the analysis log export to retrieve.

    ", + "location":"uri", + "locationName":"analysisLogExportIdentifier" + } + } + }, + "GetAnalysisLogExportOutput":{ + "type":"structure", + "required":["analysisLogExport"], + "members":{ + "analysisLogExport":{ + "shape":"AnalysisLogExport", + "documentation":"

    The analysis log export processing metadata.

    " + } + } + }, "GetAnalysisTemplateInput":{ "type":"structure", "required":[ @@ -8206,6 +8558,14 @@ "disallowedOutputColumns":{ "shape":"AnalysisRuleColumnList", "documentation":"

    The list of columns that are not allowed in the query output.

    " + }, + "aggregationThresholds":{ + "shape":"AggregationThresholdList", + "documentation":"

    The aggregation thresholds that each query output group must satisfy. Clean Rooms filters out any group that represents fewer than the specified number of distinct identities. You can specify at most one threshold. You can't use aggregation thresholds with differential privacy, or when allowedAnalyses allows only jobs.

    " + }, + "comparisonControls":{ + "shape":"ComparisonControls", + "documentation":"

    The controls that restrict how a query can compare the columns in the intermediate table. You can't use comparison controls with differential privacy, or when allowedAnalyses allows only jobs.

    " } }, "documentation":"

    Contains the custom analysis rule configuration for an intermediate table.

    " @@ -8279,7 +8639,7 @@ "members":{ "queryComputeConfiguration":{"shape":"WorkerComputeConfiguration"} }, - "documentation":"

    The compute configuration for an intermediate table population operation.

    ", + "documentation":"

    Contains the compute configuration for an intermediate table population operation.

    ", "union":true }, "IntermediateTableDependency":{ @@ -8306,7 +8666,7 @@ }, "parentType":{ "shape":"BaseTableParentType", - "documentation":"

    Whether the dependency is direct or indirect. A direct dependency is a table explicitly referenced in the stored query, while an indirect dependency is referenced through another intermediate table.

    " + "documentation":"

    The type of dependency, either direct or indirect. A direct dependency is a table explicitly referenced in the stored query. An indirect dependency is a table referenced through another intermediate table.

    " }, "creatorAccountId":{ "shape":"AccountId", @@ -8608,6 +8968,56 @@ "min":0, "pattern":"[\\w!.=*/-]*" }, + "ListAnalysisLogExportsInput":{ + "type":"structure", + "required":["membershipIdentifier"], + "members":{ + "membershipIdentifier":{ + "shape":"MembershipIdentifier", + "documentation":"

    A unique identifier for the membership to list analysis log exports for. Currently accepts the membership ID.

    ", + "location":"uri", + "locationName":"membershipIdentifier" + }, + "analysisIdentifier":{ + "shape":"UUID", + "documentation":"

    A filter on the unique identifier of the protected query that the analysis logs were exported for.

    ", + "location":"querystring", + "locationName":"analysisIdentifier" + }, + "status":{ + "shape":"AnalysisLogExportStatus", + "documentation":"

    A filter on the status of the analysis log export.

    ", + "location":"querystring", + "locationName":"status" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The pagination token that's used to fetch the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results that are returned for an API request call. The service chooses a default number if you don't set one. The service might return a nextToken even if the maxResults value has not been met.

    ", + "location":"querystring", + "locationName":"maxResults" + } + } + }, + "ListAnalysisLogExportsOutput":{ + "type":"structure", + "required":["analysisLogExports"], + "members":{ + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The pagination token that's used to fetch the next set of results.

    " + }, + "analysisLogExports":{ + "shape":"AnalysisLogExportSummaryList", + "documentation":"

    A list of analysis log exports.

    " + } + } + }, "ListAnalysisTemplatesInput":{ "type":"structure", "required":["membershipIdentifier"], @@ -9520,6 +9930,10 @@ } } }, + "LogExportAnalysisType":{ + "type":"string", + "enum":["PROTECTED_QUERY"] + }, "Long":{ "type":"long", "box":true @@ -9603,7 +10017,8 @@ "enum":[ "CAN_QUERY", "CAN_RECEIVE_RESULTS", - "CAN_RUN_JOB" + "CAN_RUN_JOB", + "CAN_EXPORT_QUERY_ANALYSIS_LOG" ] }, "MemberChangeSpecification":{ @@ -9619,7 +10034,7 @@ }, "memberAbilities":{ "shape":"MemberAbilities", - "documentation":"

    The abilities granted to the collaboration member. These determine what actions the member can perform within the collaboration.

    The following values are currently not supported: CAN_QUERY and CAN_RUN_JOB.

    Set the value of memberAbilities to [] to allow a member to contribute data.

    Set the value of memberAbilities to [CAN_RECEIVE_RESULTS] to allow a member to contribute data and receive results.

    " + "documentation":"

    The abilities granted to the collaboration member. These determine what actions the member can perform within the collaboration.

    The following values are currently not supported: CAN_QUERY and CAN_RUN_JOB.

    Set the value of memberAbilities to [] to allow a member to contribute data.

    Set the value of memberAbilities to [CAN_RECEIVE_RESULTS] to allow a member to contribute data and receive results.

    Set the value of memberAbilities to [CAN_EXPORT_QUERY_ANALYSIS_LOG] so that the member can export the analysis logs for a protected query. Having this ability isn't sufficient on its own: You can export logs only for queries that you ran or paid for.

    " }, "mlMemberAbilities":{"shape":"MLMemberAbilities"}, "paymentConfiguration":{"shape":"PaymentConfiguration"}, @@ -10103,6 +10518,34 @@ }, "documentation":"

    An object representing the collaboration member's model training payment responsibilities set by the collaboration creator.

    " }, + "OutputColumnThreshold":{ + "type":"structure", + "required":[ + "outputColumnName", + "minimumIdentityCount" + ], + "members":{ + "outputColumnName":{ + "shape":"AnalysisRuleColumnName", + "documentation":"

    The name of the output column that the override applies to. You can specify each column only once.

    " + }, + "minimumIdentityCount":{ + "shape":"OutputColumnThresholdMinimumIdentityCountInteger", + "documentation":"

    The minimum number of distinct identities that each query output group must represent for this column. Specify 0 to exempt the column from the threshold, or a value of 2 or greater to enforce a threshold.

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

    Specifies the minimum number of distinct identities for an individual output column. This value overrides the table-wide minimumIdentityCount that you set in AggregationThreshold.

    " + }, + "OutputColumnThresholdList":{ + "type":"list", + "member":{"shape":"OutputColumnThreshold"} + }, + "OutputColumnThresholdMinimumIdentityCountInteger":{ + "type":"integer", + "box":true, + "max":100000, + "min":0 + }, "PaginationToken":{ "type":"string", "max":10240, @@ -10259,7 +10702,7 @@ "members":{ "analysisId":{ "shape":"AnalysisIdentifier", - "documentation":"

    The identifier for the protected query execution. Use this value with GetProtectedQuery to track the population progress.

    " + "documentation":"

    The identifier for the protected query execution that populated the intermediate table.

    " }, "analysisType":{ "shape":"PopulateIntermediateTableAnalysisType", @@ -10287,7 +10730,7 @@ "members":{ "queryString":{ "shape":"PopulationAnalysisSqlParametersQueryStringString", - "documentation":"

    The SQL query string used to populate the intermediate table. Maximum length of 500,000 characters.

    " + "documentation":"

    The SQL query string used to populate the intermediate table.

    " }, "analysisTemplateArn":{ "shape":"AnalysisTemplateArn", @@ -12092,6 +12535,45 @@ "max":500, "min":0 }, + "StartAnalysisLogExportInput":{ + "type":"structure", + "required":[ + "membershipIdentifier", + "analysisId", + "analysisType", + "resultConfiguration" + ], + "members":{ + "membershipIdentifier":{ + "shape":"MembershipIdentifier", + "documentation":"

    A unique identifier for the membership to export the analysis logs for. Currently accepts a membership ID.

    ", + "location":"uri", + "locationName":"membershipIdentifier" + }, + "analysisId":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the protected query that you want to export the analysis logs for.

    " + }, + "analysisType":{ + "shape":"LogExportAnalysisType", + "documentation":"

    The type of analysis that the logs are exported for. Currently, only PROTECTED_QUERY is supported.

    " + }, + "resultConfiguration":{ + "shape":"AnalysisLogExportResultConfiguration", + "documentation":"

    The details needed to write the exported analysis logs.

    You don't need to create an IAM role for log export. Clean Rooms writes the exported logs using your own identity, so Clean Rooms writes the exported logs only where your existing permissions allow.

    " + } + } + }, + "StartAnalysisLogExportOutput":{ + "type":"structure", + "required":["analysisLogExport"], + "members":{ + "analysisLogExport":{ + "shape":"AnalysisLogExport", + "documentation":"

    The analysis log export that was started. The status is IN_PROGRESS.

    " + } + } + }, "StartProtectedJobInput":{ "type":"structure", "required":[ @@ -13142,7 +13624,8 @@ "type":"string", "enum":[ "CR.1X", - "CR.4X" + "CR.4X", + "CR.8X" ] } }, diff --git a/services/cleanroomsml/pom.xml b/services/cleanroomsml/pom.xml index bf355cfb4723..21076bfc778c 100644 --- a/services/cleanroomsml/pom.xml +++ b/services/cleanroomsml/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cleanroomsml AWS Java SDK :: Services :: Clean Rooms ML diff --git a/services/cleanroomsml/src/main/resources/codegen-resources/customization.config b/services/cleanroomsml/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/cleanroomsml/src/main/resources/codegen-resources/customization.config +++ b/services/cleanroomsml/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..13cfedce5c18 --- /dev/null +++ b/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-ml-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-ml-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-ml.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cleanrooms-ml.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d2c576e1fcbf..000000000000 --- a/services/cleanroomsml/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-ml-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-ml-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-ml.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cleanrooms-ml.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/cleanroomsml/src/main/resources/codegen-resources/service-2.json b/services/cleanroomsml/src/main/resources/codegen-resources/service-2.json index a3e0804626e5..1a3dc802d176 100644 --- a/services/cleanroomsml/src/main/resources/codegen-resources/service-2.json +++ b/services/cleanroomsml/src/main/resources/codegen-resources/service-2.json @@ -63,6 +63,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceQuotaExceededException"} ], "documentation":"

    Defines the information necessary to create an audience model. An audience model is a machine learning model that Clean Rooms ML trains to measure similarity between users. Clean Rooms ML manages training and storing the audience model. The audience model can be used in multiple calls to the StartAudienceGenerationJob API.

    ", @@ -82,6 +83,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceQuotaExceededException"} ], "documentation":"

    Defines the information necessary to create a configured audience model.

    ", @@ -100,6 +102,7 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceQuotaExceededException"} ], "documentation":"

    Creates a configured model algorithm using a container image stored in an ECR repository.

    ", @@ -178,7 +181,8 @@ "errors":[ {"shape":"ConflictException"}, {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Defines the information necessary to create a training dataset. In Clean Rooms ML, the TrainingDataset is metadata that points to a Glue table, which is read only during AudienceModel creation.

    ", "idempotent":true @@ -195,7 +199,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Deletes the specified audience generation job, and removes all data associated with the job.

    ", "idempotent":true @@ -212,7 +217,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Specifies an audience model that you want to delete. You can't delete an audience model if there are any configured audience models that depend on the audience model.

    ", "idempotent":true @@ -229,7 +235,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Deletes the specified configured audience model. You can't delete a configured audience model if there are any lookalike models that use the configured audience model. If you delete a configured audience model, it will be removed from any collaborations that it is associated to.

    ", "idempotent":true @@ -245,7 +252,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Deletes the specified configured audience model policy.

    ", "idempotent":true @@ -262,7 +270,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Deletes a configured model algorithm.

    ", "idempotent":true @@ -350,7 +359,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Specifies a training dataset that you want to delete. You can't delete a training dataset if there are any audience models that depend on the training dataset. In Clean Rooms ML, the TrainingDataset is metadata that points to a Glue table, which is read only during AudienceModel creation. This action deletes the metadata.

    ", "idempotent":true @@ -367,7 +377,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about an audience generation job.

    ", "readonly":true @@ -384,7 +395,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about an audience model

    ", "readonly":true @@ -455,7 +467,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about a specified configured audience model.

    ", "readonly":true @@ -472,7 +485,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about a configured audience model policy.

    ", "readonly":true @@ -489,7 +503,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about a configured model algorithm.

    ", "readonly":true @@ -596,7 +611,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns information about a training dataset.

    ", "readonly":true @@ -612,7 +628,8 @@ "output":{"shape":"ListAudienceExportJobsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of the audience export jobs.

    ", "readonly":true @@ -628,7 +645,8 @@ "output":{"shape":"ListAudienceGenerationJobsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of audience generation jobs.

    ", "readonly":true @@ -644,7 +662,8 @@ "output":{"shape":"ListAudienceModelsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of audience models.

    ", "readonly":true @@ -745,7 +764,8 @@ "output":{"shape":"ListConfiguredAudienceModelsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of the configured audience models.

    ", "readonly":true @@ -778,7 +798,8 @@ "output":{"shape":"ListConfiguredModelAlgorithmsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of configured model algorithms.

    ", "readonly":true @@ -880,7 +901,8 @@ "output":{"shape":"ListTrainingDatasetsResponse"}, "errors":[ {"shape":"ValidationException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Returns a list of training datasets.

    ", "readonly":true @@ -897,7 +919,8 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Create or update the resource policy for a configured audience model.

    ", "idempotent":true @@ -931,6 +954,7 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceQuotaExceededException"} ], "documentation":"

    Export an audience of a specified size after you have generated an audience.

    ", @@ -1040,7 +1064,8 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"}, {"shape":"AccessDeniedException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Provides the information necessary to update a configured audience model. Updates that impact audience generation jobs take effect when a new job starts, but do not impact currently running jobs.

    ", "idempotent":true @@ -5674,7 +5699,8 @@ "ParameterMap":{ "type":"map", "key":{"shape":"ParameterName"}, - "value":{"shape":"ParameterValue"} + "value":{"shape":"ParameterValue"}, + "sensitive":true }, "ParameterName":{ "type":"string", @@ -6941,7 +6967,8 @@ "type":"string", "enum":[ "CR.1X", - "CR.4X" + "CR.4X", + "CR.8X" ] } }, diff --git a/services/cloud9/pom.xml b/services/cloud9/pom.xml index ecb77d924282..b1edd1e19816 100644 --- a/services/cloud9/pom.xml +++ b/services/cloud9/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 cloud9 diff --git a/services/cloud9/src/main/resources/codegen-resources/customization.config b/services/cloud9/src/main/resources/codegen-resources/customization.config index 8255336b5f6b..ff8d543ed75c 100644 --- a/services/cloud9/src/main/resources/codegen-resources/customization.config +++ b/services/cloud9/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "describeEnvironmentMemberships", "listEnvironments" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloud9/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloud9/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..840be2339d71 --- /dev/null +++ b/services/cloud9/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloud9-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloud9-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloud9.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloud9.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloud9/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloud9/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c1f1547d073a..000000000000 --- a/services/cloud9/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloud9-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloud9-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloud9.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloud9.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudcontrol/pom.xml b/services/cloudcontrol/pom.xml index 2d804973773e..3a7ee129bca4 100644 --- a/services/cloudcontrol/pom.xml +++ b/services/cloudcontrol/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudcontrol AWS Java SDK :: Services :: Cloud Control diff --git a/services/cloudcontrol/src/main/resources/codegen-resources/customization.config b/services/cloudcontrol/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/cloudcontrol/src/main/resources/codegen-resources/customization.config +++ b/services/cloudcontrol/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9d3a79bf56bf --- /dev/null +++ b/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudcontrolapi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudcontrolapi-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudcontrolapi.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudcontrolapi.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 104e95e8e374..000000000000 --- a/services/cloudcontrol/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudcontrolapi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudcontrolapi-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudcontrolapi.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudcontrolapi.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/clouddirectory/pom.xml b/services/clouddirectory/pom.xml index f2b91e6732bb..9212167a251d 100644 --- a/services/clouddirectory/pom.xml +++ b/services/clouddirectory/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT clouddirectory AWS Java SDK :: Services :: Amazon CloudDirectory diff --git a/services/clouddirectory/src/main/resources/codegen-resources/customization.config b/services/clouddirectory/src/main/resources/codegen-resources/customization.config index 45b9f344391b..82734c9532b0 100644 --- a/services/clouddirectory/src/main/resources/codegen-resources/customization.config +++ b/services/clouddirectory/src/main/resources/codegen-resources/customization.config @@ -9,6 +9,5 @@ "TypedAttributeValue": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/clouddirectory/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/clouddirectory/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c5c27e3e7bc1 --- /dev/null +++ b/services/clouddirectory/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://clouddirectory-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://clouddirectory.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://clouddirectory-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://clouddirectory.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://clouddirectory.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/clouddirectory/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/clouddirectory/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6bcba06d6009..000000000000 --- a/services/clouddirectory/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://clouddirectory-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://clouddirectory.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://clouddirectory-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://clouddirectory.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://clouddirectory.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/clouddirectory/src/main/resources/codegen-resources/service-2.json b/services/clouddirectory/src/main/resources/codegen-resources/service-2.json index 21cd4e413d11..cf79b2b74521 100644 --- a/services/clouddirectory/src/main/resources/codegen-resources/service-2.json +++ b/services/clouddirectory/src/main/resources/codegen-resources/service-2.json @@ -6032,5 +6032,5 @@ "pattern":"^[a-zA-Z0-9._-]*$" } }, - "documentation":"Amazon Cloud Directory

    Amazon Cloud Directory is a component of the AWS Directory Service that simplifies the development and management of cloud-scale web, mobile, and IoT applications. This guide describes the Cloud Directory operations that you can call programmatically and includes detailed information on data types and errors. For information about Cloud Directory features, see AWS Directory Service and the Amazon Cloud Directory Developer Guide.

    " + "documentation":"Amazon Cloud Directory

    Amazon Cloud Directory is a component of the AWS Directory Service that simplifies the development and management of cloud-scale web, mobile, and IoT applications. This guide describes the Cloud Directory operations that you can call programmatically and includes detailed information on data types and errors. For information about Cloud Directory features, see AWS Directory Service and the Amazon Cloud Directory Developer Guide.

    Amazon Cloud Directory is no longer open to new customers and will reach end of support on July 24, 2027. For alternatives to Amazon Cloud Directory, explore Amazon DynamoDB and Amazon Neptune. If you need help choosing the right alternative for your use case, or for any other questions, contact AWS Support.

    " } diff --git a/services/cloudformation/pom.xml b/services/cloudformation/pom.xml index 0b72cbd2ec84..9bbfdd0ad492 100644 --- a/services/cloudformation/pom.xml +++ b/services/cloudformation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudformation AWS Java SDK :: Services :: AWS CloudFormation diff --git a/services/cloudformation/src/main/resources/codegen-resources/customization.config b/services/cloudformation/src/main/resources/codegen-resources/customization.config index 9705395f0d1c..07c7ef265ee4 100644 --- a/services/cloudformation/src/main/resources/codegen-resources/customization.config +++ b/services/cloudformation/src/main/resources/codegen-resources/customization.config @@ -24,8 +24,6 @@ "describeStackResources", "describeStackEvents", "getTemplateSummary" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudformation/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudformation/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..59b0b30501df --- /dev/null +++ b/services/cloudformation/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudformation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudformation.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudformation-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudformation.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudformation.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudformation/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudformation/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e2cf617eaa85..000000000000 --- a/services/cloudformation/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudformation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://cloudformation.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudformation-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudformation.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudformation.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudformation/src/main/resources/codegen-resources/service-2.json b/services/cloudformation/src/main/resources/codegen-resources/service-2.json index ecc9dd33edf6..27bdc1e034ba 100644 --- a/services/cloudformation/src/main/resources/codegen-resources/service-2.json +++ b/services/cloudformation/src/main/resources/codegen-resources/service-2.json @@ -3791,7 +3791,8 @@ "type":"string", "enum":[ "MANAGED_BY_AWS", - "WRITE_ONLY_PROPERTY" + "WRITE_ONLY_PROPERTY", + "SENSITIVE_PROPERTY" ] }, "DriftedStackInstancesCount":{ @@ -6422,7 +6423,7 @@ }, "Reason":{ "shape":"DriftIgnoredReason", - "documentation":"

    Reason why drift was ignored for the attribute, can have 2 possible values:

    • WRITE_ONLY_PROPERTY - Property is not included in read response for the resource’s live state.

    • MANAGED_BY_AWS - Property is managed by an Amazon Web Services service and is expected to be dynamically modified.

    " + "documentation":"

    Reason why drift was ignored for the attribute, can have 3 possible values:

    • WRITE_ONLY_PROPERTY – Property is not included in read response for the resource’s live state.

    • MANAGED_BY_AWS – Property is managed by an Amazon Web Services service and is expected to be dynamically modified.

    • SENSITIVE_PROPERTY – Property has a sensitive value, such as an Amazon Web Services Secrets Manager value.

    " } }, "documentation":"

    The ResourceDriftIgnoredAttribute data type.

    " diff --git a/services/cloudfront/pom.xml b/services/cloudfront/pom.xml index 64430e904102..4778f89f60a2 100644 --- a/services/cloudfront/pom.xml +++ b/services/cloudfront/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudfront AWS Java SDK :: Services :: Amazon CloudFront diff --git a/services/cloudfront/src/main/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilities.java b/services/cloudfront/src/main/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilities.java index 0faae68a0194..63868419b262 100644 --- a/services/cloudfront/src/main/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilities.java +++ b/services/cloudfront/src/main/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilities.java @@ -34,6 +34,7 @@ import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest; import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest; import software.amazon.awssdk.services.cloudfront.url.SignedUrl; +import software.amazon.awssdk.services.cloudfront.utils.SigningHashAlgorithm; /** * @@ -57,6 +58,7 @@ public final class CloudFrontUtilities { private static final String SIGNATURE_KEY = "CloudFront-Signature"; private static final String EXPIRES_KEY = "CloudFront-Expires"; private static final String POLICY_KEY = "CloudFront-Policy"; + private static final String HASH_ALGORITHM_KEY = "CloudFront-Hash-Algorithm"; private CloudFrontUtilities() { } @@ -141,7 +143,7 @@ public SignedUrl getSignedUrlWithCannedPolicy(CannedSignerRequest request) { try { String resourceUrl = request.resourceUrl(); String cannedPolicy = SigningUtils.buildCannedPolicy(resourceUrl, request.expirationDate()); - byte[] signatureBytes = signPolicy(cannedPolicy.getBytes(UTF_8), request.privateKey()); + byte[] signatureBytes = signPolicy(cannedPolicy.getBytes(UTF_8), request.privateKey(), request.hashAlgorithm()); String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes); URI uri = URI.create(resourceUrl); String protocol = uri.getScheme(); @@ -149,7 +151,8 @@ public SignedUrl getSignedUrlWithCannedPolicy(CannedSignerRequest request) { + (uri.getQuery() != null ? "?" + uri.getRawQuery() + "&" : "?") + "Expires=" + request.expirationDate().getEpochSecond() + "&Signature=" + urlSafeSignature - + "&Key-Pair-Id=" + request.keyPairId(); + + "&Key-Pair-Id=" + request.keyPairId() + + hashAlgorithmUrlParam(request.hashAlgorithm()); return DefaultSignedUrl.builder() .protocol(protocol) .domain(uri.getHost()) @@ -267,7 +270,7 @@ public SignedUrl getSignedUrlWithCustomPolicy(CustomSignerRequest request) { request.expirationDate(), request.ipRange()); - byte[] signatureBytes = signPolicy(policy.getBytes(UTF_8), request.privateKey()); + byte[] signatureBytes = signPolicy(policy.getBytes(UTF_8), request.privateKey(), request.hashAlgorithm()); String urlSafePolicy = SigningUtils.makeStringUrlSafe(policy); String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes); URI uri = URI.create(resourceUrl); @@ -276,7 +279,8 @@ public SignedUrl getSignedUrlWithCustomPolicy(CustomSignerRequest request) { + (uri.getQuery() != null ? "?" + uri.getRawQuery() + "&" : "?") + "Policy=" + urlSafePolicy + "&Signature=" + urlSafeSignature - + "&Key-Pair-Id=" + request.keyPairId(); + + "&Key-Pair-Id=" + request.keyPairId() + + hashAlgorithmUrlParam(request.hashAlgorithm()); return DefaultSignedUrl.builder() .protocol(protocol) .domain(uri.getHost()) @@ -369,14 +373,18 @@ public CookiesForCannedPolicy getCookiesForCannedPolicy(Consumer + * CloudFront supports SHA-1 (default) and SHA-256 for signed URLs and signed cookies. + * When using SHA-256, the signed URL will include a {@code Hash-Algorithm=SHA256} query parameter, + * and signed cookies will include a {@code CloudFront-Hash-Algorithm=SHA256} cookie. + */ +@SdkPublicApi +public enum SigningHashAlgorithm { + SHA1("SHA1"), + SHA256("SHA256"); + + private final String id; + + SigningHashAlgorithm(String id) { + this.id = id; + } + + /** + * The algorithm identifier used in CloudFront's {@code Hash-Algorithm} parameter + * and in Java Security algorithm name construction (e.g., {@code "SHA256withRSA"}). + */ + public String id() { + return id; + } +} diff --git a/services/cloudfront/src/main/resources/codegen-resources/customization.config b/services/cloudfront/src/main/resources/codegen-resources/customization.config index 9a89481aed0a..b4178dad30d3 100644 --- a/services/cloudfront/src/main/resources/codegen-resources/customization.config +++ b/services/cloudfront/src/main/resources/codegen-resources/customization.config @@ -10,8 +10,6 @@ "utilitiesMethod": { "returnType": "software.amazon.awssdk.services.cloudfront.CloudFrontUtilities", "createMethodParams": [] - }, - - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/cloudfront/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudfront/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..481bb44824e7 --- /dev/null +++ b/services/cloudfront/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,310 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront-fips.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront.cn-northwest-1.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront-fips.cn-northwest-1.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront-fips.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront-fips.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudfront.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAAoAAAAGAAAABAAAAAgAAAAHAAAABgX14QYF9eEOAAAABQX14QQAAAAJAAAABwX14QwF9eENAAAABAAAAA0AAAALAAAABgX14QcAAAAMAAAACAX14QoF9eELAAAABQX14QUAAAAOAAAABwAAAA8F9eEJAAAACAX14QgF9eEJAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudfront/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudfront/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f53c5b914b38..000000000000 --- a/services/cloudfront/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,572 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://cloudfront.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://cloudfront-fips.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://cloudfront.cn-northwest-1.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://cloudfront-fips.cn-northwest-1.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudfront-fips.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudfront-fips.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudfront.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudfront.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/cloudfront/src/main/resources/codegen-resources/service-2.json b/services/cloudfront/src/main/resources/codegen-resources/service-2.json index 5e85bb3293cb..99d8844f0ad0 100644 --- a/services/cloudfront/src/main/resources/codegen-resources/service-2.json +++ b/services/cloudfront/src/main/resources/codegen-resources/service-2.json @@ -12001,7 +12001,7 @@ }, "SigningProtocol":{ "shape":"OriginAccessControlSigningProtocols", - "documentation":"

    The signing protocol of the origin access control, which determines how CloudFront signs (authenticates) requests. The only valid value is sigv4.

    " + "documentation":"

    The signing protocol of the origin access control, which determines how CloudFront signs (authenticates) requests. The only valid values are sigv4 and sigv4a.

    " }, "SigningBehavior":{ "shape":"OriginAccessControlSigningBehaviors", @@ -12081,7 +12081,10 @@ }, "OriginAccessControlSigningProtocols":{ "type":"string", - "enum":["sigv4"] + "enum":[ + "sigv4", + "sigv4a" + ] }, "OriginAccessControlSummary":{ "type":"structure", @@ -12108,7 +12111,7 @@ }, "SigningProtocol":{ "shape":"OriginAccessControlSigningProtocols", - "documentation":"

    The signing protocol of the origin access control. The signing protocol determines how CloudFront signs (authenticates) requests. The only valid value is sigv4.

    " + "documentation":"

    The signing protocol of the origin access control. The signing protocol determines how CloudFront signs (authenticates) requests. The only valid values are sigv4 and sigv4a.

    " }, "SigningBehavior":{ "shape":"OriginAccessControlSigningBehaviors", @@ -16344,7 +16347,7 @@ }, "SSLSupportMethod":{ "shape":"SSLSupportMethod", - "documentation":"

    If the distribution uses Aliases (alternate domain names or CNAMEs), specify which viewers the distribution accepts HTTPS connections from.

    • sni-only – The distribution accepts HTTPS connections from only viewers that support server name indication (SNI). This is recommended. Most browsers and clients support SNI.

    • vip – The distribution accepts HTTPS connections from all viewers including those that don't support SNI. This is not recommended, and results in additional monthly charges from CloudFront.

    • static-ip - Do not specify this value unless your distribution has been enabled for this feature by the CloudFront team. If you have a use case that requires static IP addresses for a distribution, contact CloudFront through the Amazon Web Services Support Center.

    If the distribution uses the CloudFront domain name such as d111111abcdef8.cloudfront.net, don't set a value for this field.

    " + "documentation":"

    If the distribution uses Aliases (alternate domain names or CNAMEs), specify which viewers the distribution accepts HTTPS connections from.

    • sni-only – The distribution accepts HTTPS connections from only viewers that support server name indication (SNI). This is recommended. Most browsers and clients support SNI.

    • vip – The distribution accepts HTTPS connections from all viewers including those that don't support SNI. This is not recommended, and results in additional monthly charges from CloudFront.

    • static-ip - Do not specify this value unless your distribution has been enabled for this feature by the CloudFront team. If you have a use case that requires static IP addresses for a distribution, contact CloudFront through the Amazon Web ServicesSupport Center.

    If the distribution uses the CloudFront domain name such as d111111abcdef8.cloudfront.net, don't set a value for this field.

    " }, "MinimumProtocolVersion":{ "shape":"MinimumProtocolVersion", diff --git a/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesIntegrationTest.java b/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesIntegrationTest.java index fcfaee5b8dc4..24fc5476e3a9 100644 --- a/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesIntegrationTest.java +++ b/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesIntegrationTest.java @@ -61,6 +61,7 @@ import software.amazon.awssdk.services.cloudfront.model.CreatePublicKeyResponse; import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest; import software.amazon.awssdk.services.cloudfront.model.DefaultCacheBehavior; +import software.amazon.awssdk.services.cloudfront.utils.SigningHashAlgorithm; import software.amazon.awssdk.services.cloudfront.model.Distribution; import software.amazon.awssdk.services.cloudfront.model.DistributionConfig; import software.amazon.awssdk.services.cloudfront.model.DistributionSummary; @@ -89,7 +90,6 @@ public class CloudFrontUtilitiesIntegrationTest extends IntegrationTestBase { private static final String S3_OBJECT_KEY_ON_SUB_PATH = "foo/specific-file"; private static final String S3_OBJECT_KEY_ON_SUB_PATH_OTHER = "foo/other-file"; - private static String bucket; private static String domainName; private static String resourceUrl; @@ -98,18 +98,15 @@ public class CloudFrontUtilitiesIntegrationTest extends IntegrationTestBase { private static File rsaKeyFile; private static Path rsaKeyFilePath; private static String keyGroupId; - private static String ecKeyPairId; private static PrivateKey ecPrivateKey; private static File ecKeyFile; private static Path ecKeyFilePath; - private static String originAccessId; - private static String distributionId; @BeforeAll public static void init() throws Exception { - IntegrationTestBase.setUp(); + setUp(); initStaticFields(); } @@ -132,13 +129,35 @@ public String toString() { } } - static Stream keyCases() throws Exception { + static Stream keyCases() { return Stream.of( new KeyTestCase("RSA", rsaKeyPairId, rsaPrivateKey, rsaKeyFilePath), new KeyTestCase("ECDSA", ecKeyPairId, ecPrivateKey, ecKeyFilePath) ); } + private static class SigningTestCase { + final KeyTestCase keyTestCase; + final SigningHashAlgorithm hashAlgorithm; + + SigningTestCase(KeyTestCase keyTestCase, SigningHashAlgorithm hashAlgorithm) { + this.keyTestCase = keyTestCase; + this.hashAlgorithm = hashAlgorithm; + } + + @Override + public String toString() { + return keyTestCase.name + "_" + hashAlgorithm; + } + } + + static Stream signingCases() { + return keyCases().flatMap(k -> Stream.of( + new SigningTestCase(k, SigningHashAlgorithm.SHA1), + new SigningTestCase(k, SigningHashAlgorithm.SHA256) + )); + } + @Test void unsignedUrl_shouldReturn403Response() throws Exception { @@ -157,15 +176,16 @@ void unsignedUrl_shouldReturn403Response() throws Exception { } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCannedPolicy_producesValidUrl(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCannedPolicy_producesValidUrl(SigningTestCase testCase) throws Exception { InputStream originalBucketContent = s3Client.getObject(r -> r.bucket(bucket).key(S3_OBJECT_KEY)); Instant expirationDate = LocalDate.of(2050, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); CannedSignerRequest request = CannedSignerRequest.builder() .resourceUrl(resourceUrl) - .privateKey(testCase.keyFilePath) - .keyPairId(testCase.keyPairId) - .expirationDate(expirationDate).build(); + .privateKey(testCase.keyTestCase.keyFilePath) + .keyPairId(testCase.keyTestCase.keyPairId) + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm).build(); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCannedPolicy(request); SdkHttpClient client = Apache5HttpClient.create(); HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() @@ -179,13 +199,14 @@ void getSignedUrlWithCannedPolicy_producesValidUrl(KeyTestCase testCase) throws } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCannedPolicy_withExpiredDate_shouldReturn403Response(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCannedPolicy_withExpiredDate_shouldReturn403Response(SigningTestCase testCase) throws Exception { Instant expirationDate = LocalDate.of(2020, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCannedPolicy(r -> r.resourceUrl(resourceUrl) - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) - .expirationDate(expirationDate)); + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm)); SdkHttpClient client = Apache5HttpClient.create(); HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() .request(signedUrl.createHttpGetRequest()) @@ -195,17 +216,18 @@ void getSignedUrlWithCannedPolicy_withExpiredDate_shouldReturn403Response(KeyTes } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCustomPolicy_producesValidUrl(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCustomPolicy_producesValidUrl(SigningTestCase testCase) throws Exception { InputStream originalBucketContent = s3Client.getObject(r -> r.bucket(bucket).key(S3_OBJECT_KEY)); Instant activeDate = LocalDate.of(2022, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); Instant expirationDate = LocalDate.of(2050, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); CustomSignerRequest request = CustomSignerRequest.builder() .resourceUrl(resourceUrl) - .privateKey(testCase.keyFilePath) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.keyFilePath) + .keyPairId(testCase.keyTestCase.keyPairId) .expirationDate(expirationDate) - .activeDate(activeDate).build(); + .activeDate(activeDate) + .hashAlgorithm(testCase.hashAlgorithm).build(); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCustomPolicy(request); SdkHttpClient client = Apache5HttpClient.create(); HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() @@ -236,14 +258,15 @@ void getSignedUrlWithCustomPolicy_withFutureActiveDate_shouldReturn403Response() } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getCookiesForCannedPolicy_producesValidCookies(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getCookiesForCannedPolicy_producesValidCookies(SigningTestCase testCase) throws Exception { InputStream originalBucketContent = s3Client.getObject(r -> r.bucket(bucket).key(S3_OBJECT_KEY)); Instant expirationDate = LocalDate.of(2050, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); CookiesForCannedPolicy cookies = cloudFrontUtilities.getCookiesForCannedPolicy(r -> r.resourceUrl(resourceUrl) - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) - .expirationDate(expirationDate)); + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm)); SdkHttpClient client = Apache5HttpClient.create(); HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() @@ -275,16 +298,17 @@ void getCookiesForCannedPolicy_withExpiredDate_shouldReturn403Response() throws } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getCookiesForCustomPolicy_producesValidCookies(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getCookiesForCustomPolicy_producesValidCookies(SigningTestCase testCase) throws Exception { InputStream originalBucketContent = s3Client.getObject(r -> r.bucket(bucket).key(S3_OBJECT_KEY)); Instant activeDate = LocalDate.of(2022, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); Instant expirationDate = LocalDate.of(2050, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy(r -> r.resourceUrl(resourceUrl) - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) .expirationDate(expirationDate) - .activeDate(activeDate)); + .activeDate(activeDate) + .hashAlgorithm(testCase.hashAlgorithm)); SdkHttpClient client = Apache5HttpClient.create(); HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() @@ -318,8 +342,8 @@ void getCookiesForCustomPolicy_withFutureActiveDate_shouldReturn403Response() th } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getCookiesForCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getCookiesForCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(SigningTestCase testCase) throws Exception { Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() .toInstant(ZoneOffset.of("Z")); @@ -329,30 +353,33 @@ void getCookiesForCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(KeyTe .toInstant(ZoneOffset.of("Z")); CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy(r -> r.resourceUrl(resourceUrl) - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern(resourceUrl + "*") .activeDate(activeDate) - .expirationDate(expirationDate)); + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm)); // Request the same resource with an additional query parameter - should still be allowed by the wildcard policy URI uri = URI.create(resourceUrl + "?foo=bar"); SdkHttpClient client = Apache5HttpClient.create(); + SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() + .uri(uri) + .appendHeader("Cookie", cookies.policyHeaderValue()) + .appendHeader("Cookie", cookies.signatureHeaderValue()) + .appendHeader("Cookie", cookies.keyPairIdHeaderValue()); + if (cookies.hashAlgorithmHeaderValue() != null) { + requestBuilder.appendHeader("Cookie", cookies.hashAlgorithmHeaderValue()); + } HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() - .request(SdkHttpRequest.builder() - .uri(uri) - .appendHeader("Cookie", cookies.policyHeaderValue()) - .appendHeader("Cookie", cookies.signatureHeaderValue()) - .appendHeader("Cookie", cookies.keyPairIdHeaderValue()) - .method(SdkHttpMethod.GET) - .build()) + .request(requestBuilder.method(SdkHttpMethod.GET).build()) .build()).call(); assertThat(response.httpResponse().statusCode()).isEqualTo(200); } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getCookiesForCustomPolicy_wildCardPath(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getCookiesForCustomPolicy_wildCardPath(SigningTestCase testCase) throws Exception { String resourceUri = "https://" + domainName; Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() @@ -364,30 +391,33 @@ void getCookiesForCustomPolicy_wildCardPath(KeyTestCase testCase) throws Excepti CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy( r -> r.resourceUrl(resourceUri + "/foo/specific-file") - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern(resourceUri + "/foo/*") .activeDate(activeDate) - .expirationDate(expirationDate)); + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm)); // Use the cookies to access a different file under the same wildcard path URI otherFileUri = URI.create(resourceUri + "/foo/other-file"); SdkHttpClient client = Apache5HttpClient.create(); + SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() + .uri(otherFileUri) + .appendHeader("Cookie", cookies.policyHeaderValue()) + .appendHeader("Cookie", cookies.signatureHeaderValue()) + .appendHeader("Cookie", cookies.keyPairIdHeaderValue()); + if (cookies.hashAlgorithmHeaderValue() != null) { + requestBuilder.appendHeader("Cookie", cookies.hashAlgorithmHeaderValue()); + } HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() - .request(SdkHttpRequest.builder() - .uri(otherFileUri) - .appendHeader("Cookie", cookies.policyHeaderValue()) - .appendHeader("Cookie", cookies.signatureHeaderValue()) - .appendHeader("Cookie", cookies.keyPairIdHeaderValue()) - .method(SdkHttpMethod.GET) - .build()) + .request(requestBuilder.method(SdkHttpMethod.GET).build()) .build()).call(); assertThat(response.httpResponse().statusCode()).isEqualTo(200); } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getCookiesForCustomPolicy_wildCardPolicyResource_allowsAnyPath(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getCookiesForCustomPolicy_wildCardPolicyResource_allowsAnyPath(SigningTestCase testCase) throws Exception { Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() .toInstant(ZoneOffset.of("Z")); @@ -398,30 +428,33 @@ void getCookiesForCustomPolicy_wildCardPolicyResource_allowsAnyPath(KeyTestCase CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy( r -> r.resourceUrl(resourceUrl) - .privateKey(testCase.privateKey) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.privateKey) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern("*") .activeDate(activeDate) - .expirationDate(expirationDate)); + .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm)); // Use the cookies to access a completely different path - the "*" pattern should allow any path URI differentPathUri = URI.create(resourceUrl.replace("/s3ObjectKey", "/foo/other-file")); SdkHttpClient client = Apache5HttpClient.create(); + SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder() + .uri(differentPathUri) + .appendHeader("Cookie", cookies.policyHeaderValue()) + .appendHeader("Cookie", cookies.signatureHeaderValue()) + .appendHeader("Cookie", cookies.keyPairIdHeaderValue()); + if (cookies.hashAlgorithmHeaderValue() != null) { + requestBuilder.appendHeader("Cookie", cookies.hashAlgorithmHeaderValue()); + } HttpExecuteResponse response = client.prepareRequest(HttpExecuteRequest.builder() - .request(SdkHttpRequest.builder() - .uri(differentPathUri) - .appendHeader("Cookie", cookies.policyHeaderValue()) - .appendHeader("Cookie", cookies.signatureHeaderValue()) - .appendHeader("Cookie", cookies.keyPairIdHeaderValue()) - .method(SdkHttpMethod.GET) - .build()) + .request(requestBuilder.method(SdkHttpMethod.GET).build()) .build()).call(); assertThat(response.httpResponse().statusCode()).isEqualTo(200); } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(SigningTestCase testCase) throws Exception { Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() .toInstant(ZoneOffset.of("Z")); @@ -432,11 +465,12 @@ void getSignedUrlWithCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(Ke CustomSignerRequest request = CustomSignerRequest.builder() .resourceUrl(resourceUrl) - .privateKey(testCase.keyFilePath) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.keyFilePath) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern(resourceUrl + "*") .activeDate(activeDate) .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm) .build(); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCustomPolicy(request); @@ -458,8 +492,8 @@ void getSignedUrlWithCustomPolicy_shouldAllowQueryParametersWhenUsingWildcard(Ke } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCustomPolicy_wildCardPath(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCustomPolicy_wildCardPath(SigningTestCase testCase) throws Exception { String resourceUri = "https://" + domainName; Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() @@ -471,11 +505,12 @@ void getSignedUrlWithCustomPolicy_wildCardPath(KeyTestCase testCase) throws Exce CustomSignerRequest request = CustomSignerRequest.builder() .resourceUrl(resourceUri + "/foo/specific-file") - .privateKey(testCase.keyFilePath) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.keyFilePath) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern(resourceUri + "/foo/*") .activeDate(activeDate) .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm) .build(); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCustomPolicy(request); @@ -495,8 +530,8 @@ void getSignedUrlWithCustomPolicy_wildCardPath(KeyTestCase testCase) throws Exce } @ParameterizedTest(name = "{0}") - @MethodSource("keyCases") - void getSignedUrlWithCustomPolicy_wildCardPolicyResource_allowsAnyPath(KeyTestCase testCase) throws Exception { + @MethodSource("signingCases") + void getSignedUrlWithCustomPolicy_wildCardPolicyResource_allowsAnyPath(SigningTestCase testCase) throws Exception { Instant expirationDate = LocalDate.of(2050, 1, 1) .atStartOfDay() .toInstant(ZoneOffset.of("Z")); @@ -507,11 +542,12 @@ void getSignedUrlWithCustomPolicy_wildCardPolicyResource_allowsAnyPath(KeyTestCa CustomSignerRequest request = CustomSignerRequest.builder() .resourceUrl(resourceUrl) - .privateKey(testCase.keyFilePath) - .keyPairId(testCase.keyPairId) + .privateKey(testCase.keyTestCase.keyFilePath) + .keyPairId(testCase.keyTestCase.keyPairId) .resourceUrlPattern("*") .activeDate(activeDate) .expirationDate(expirationDate) + .hashAlgorithm(testCase.hashAlgorithm) .build(); SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCustomPolicy(request); @@ -541,7 +577,6 @@ private static void initStaticFields() throws Exception { domainName = distribution.domainName; resourceUrl = "https://" + domainName + "/" + S3_OBJECT_KEY; - distributionId = distribution.id; } private static void initializeRsaKeyFileAndPair() throws Exception { diff --git a/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesTest.java b/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesTest.java index b6fe99ff9ddf..db1c0b9d4498 100644 --- a/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesTest.java +++ b/services/cloudfront/src/test/java/software/amazon/awssdk/services/cloudfront/CloudFrontUtilitiesTest.java @@ -53,6 +53,7 @@ import software.amazon.awssdk.services.cloudfront.internal.utils.SigningUtils; import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest; import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest; +import software.amazon.awssdk.services.cloudfront.utils.SigningHashAlgorithm; import software.amazon.awssdk.services.cloudfront.url.SignedUrl; @@ -525,4 +526,134 @@ void customSignerRequest_nullResourceUrlShouldThrow(){ assertThatNullPointerException().isThrownBy(() -> CustomSignerRequest.builder().build()) .withMessageContaining("resourceUrl must not be null"); } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getSignedURLWithCannedPolicy_sha256_includesSigningHashAlgorithmParam(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + SignedUrl signedUrl = + cloudFrontUtilities.getSignedUrlWithCannedPolicy(r -> r + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA256)); + String url = signedUrl.url(); + assertThat(url).contains("&Hash-Algorithm=SHA256"); + assertThat(url).endsWith("&Hash-Algorithm=SHA256"); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getSignedURLWithCannedPolicy_sha1Default_doesNotIncludeSigningHashAlgorithmParam(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + SignedUrl signedUrl = + cloudFrontUtilities.getSignedUrlWithCannedPolicy(r -> r + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate)); + String url = signedUrl.url(); + assertThat(url).doesNotContain("Hash-Algorithm"); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getSignedURLWithCustomPolicy_sha256_includesSigningHashAlgorithmParam(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + SignedUrl signedUrl = + cloudFrontUtilities.getSignedUrlWithCustomPolicy(r -> r + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA256)); + String url = signedUrl.url(); + assertThat(url).contains("&Hash-Algorithm=SHA256"); + assertThat(url).endsWith("&Hash-Algorithm=SHA256"); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getCookiesForCannedPolicy_sha256_includesSigningHashAlgorithmHeader(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + CannedSignerRequest request = CannedSignerRequest.builder() + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA256) + .build(); + CookiesForCannedPolicy cookies = cloudFrontUtilities.getCookiesForCannedPolicy(request); + assertThat(cookies.hashAlgorithmHeaderValue()).isEqualTo("CloudFront-Hash-Algorithm=SHA256"); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getCookiesForCannedPolicy_sha1Default_hashAlgorithmHeaderIsNull(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + CannedSignerRequest request = CannedSignerRequest.builder() + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .build(); + CookiesForCannedPolicy cookies = cloudFrontUtilities.getCookiesForCannedPolicy(request); + assertThat(cookies.hashAlgorithmHeaderValue()).isNull(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getCookiesForCustomPolicy_sha256_includesSigningHashAlgorithmHeader(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + CustomSignerRequest request = CustomSignerRequest.builder() + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA256) + .build(); + CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy(request); + assertThat(cookies.hashAlgorithmHeaderValue()).isEqualTo("CloudFront-Hash-Algorithm=SHA256"); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getCookiesForCustomPolicy_sha1Default_hashAlgorithmHeaderIsNull(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + CustomSignerRequest request = CustomSignerRequest.builder() + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .build(); + CookiesForCustomPolicy cookies = cloudFrontUtilities.getCookiesForCustomPolicy(request); + assertThat(cookies.hashAlgorithmHeaderValue()).isNull(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("keyCases") + void getSignedURLWithCannedPolicy_sha256_producesDifferentSignatureThanSha1(KeyTestCase testCase) { + Instant expirationDate = LocalDate.of(2024, 1, 1).atStartOfDay().toInstant(ZoneOffset.of("Z")); + SignedUrl sha1Url = + cloudFrontUtilities.getSignedUrlWithCannedPolicy(r -> r + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA1)); + SignedUrl sha256Url = + cloudFrontUtilities.getSignedUrlWithCannedPolicy(r -> r + .resourceUrl(RESOURCE_URL) + .privateKey(testCase.keyPair.getPrivate()) + .keyPairId("keyPairId") + .expirationDate(expirationDate) + .hashAlgorithm(SigningHashAlgorithm.SHA256)); + + String sha1Sig = sha1Url.url().substring( + sha1Url.url().indexOf("&Signature=") + 11, sha1Url.url().indexOf("&Key-Pair-Id")); + String sha256Sig = sha256Url.url().substring( + sha256Url.url().indexOf("&Signature=") + 11, sha256Url.url().indexOf("&Key-Pair-Id")); + assertThat(sha1Sig).isNotEqualTo(sha256Sig); + } } diff --git a/services/cloudfrontkeyvaluestore/pom.xml b/services/cloudfrontkeyvaluestore/pom.xml index f2b5dade5e94..58aaf2856e84 100644 --- a/services/cloudfrontkeyvaluestore/pom.xml +++ b/services/cloudfrontkeyvaluestore/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudfrontkeyvaluestore AWS Java SDK :: Services :: Cloud Front Key Value Store diff --git a/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/customization.config b/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/customization.config index 3388694e6427..7ad0bbabcc1f 100644 --- a/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/customization.config +++ b/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "enableEndpointAuthSchemeParams": true } diff --git a/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f21cd877020d --- /dev/null +++ b/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,280 @@ +{ + "version": "1.1", + "parameters": { + "KvsARN": { + "required": false, + "documentation": "The ARN of the Key Value Store", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "KvsARN" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "KvsARN" + } + ], + "assign": "parsedArn" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedArn" + }, + "service" + ] + }, + "cloudfront" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedArn" + }, + "region" + ] + }, + "" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedArn" + }, + "resourceId[0]" + ], + "assign": "arnType" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "key-value-store" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedArn" + }, + "partition" + ] + }, + "aws" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "partitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedArn" + }, + "partition" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "url" + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{parsedArn#accountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "cloudfront-keyvaluestore", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Provided endpoint is not a valid URL", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{parsedArn#accountId}.cloudfront-kvs.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "cloudfront-keyvaluestore", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but Kvs ARN has `{parsedArn#partition}`", + "type": "error" + }, + { + "conditions": [], + "error": "CloudFront-KeyValueStore is not supported in partition `{parsedArn#partition}`", + "type": "error" + }, + { + "conditions": [], + "error": "ARN resource type is invalid. Expected `key-value-store`, found: `{arnType}`", + "type": "error" + }, + { + "conditions": [], + "error": "No resource type found in the KVS ARN. Resource type must be `key-value-store`.", + "type": "error" + }, + { + "conditions": [], + "error": "Provided ARN must be a global resource ARN. Found: `{parsedArn#region}`", + "type": "error" + }, + { + "conditions": [], + "error": "Provided ARN is not a valid CloudFront Service ARN. Found: `{parsedArn#service}`", + "type": "error" + }, + { + "conditions": [], + "error": "KVS ARN must be a valid ARN", + "type": "error" + }, + { + "conditions": [], + "error": "KVS ARN must be provided to use this service", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS is not supported with CloudFront-KeyValueStore.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAX14QwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eEKAAAAAwAAAAYF9eEJAAAABAAAAAcF9eEIAAAABQAAAAgF9eEHAAAABgX14QcAAAAJAAAABwAAAAoF9eEGAAAACAAAAAsF9eEFAAAACQAAAAwAAAAOAAAACgAAAA0AAAAOAAAACwAAAA4F9eEEAAAADAAAAA8F9eEDAAAADQX14QEF9eEC" +} \ No newline at end of file diff --git a/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 070acd6ce458..000000000000 --- a/services/cloudfrontkeyvaluestore/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,449 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "KvsARN": { - "required": false, - "documentation": "The ARN of the Key Value Store", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "KvsARN" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "KvsARN" - } - ], - "assign": "parsedArn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "parsedArn" - }, - "service" - ] - }, - "cloudfront" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "parsedArn" - }, - "region" - ] - }, - "" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "parsedArn" - }, - "resourceId[0]" - ], - "assign": "arnType" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "key-value-store" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "parsedArn" - }, - "partition" - ] - }, - "aws" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - }, - "{parsedArn#partition}" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{parsedArn#accountId}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "cloudfront-keyvaluestore", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Provided endpoint is not a valid URL", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{parsedArn#accountId}.cloudfront-kvs.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "cloudfront-keyvaluestore", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but Kvs ARN has `{parsedArn#partition}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{parsedArn#accountId}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "cloudfront-keyvaluestore", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Provided endpoint is not a valid URL", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{parsedArn#accountId}.cloudfront-kvs.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "cloudfront-keyvaluestore", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "CloudFront-KeyValueStore is not supported in partition `{parsedArn#partition}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "ARN resource type is invalid. Expected `key-value-store`, found: `{arnType}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "No resource type found in the KVS ARN. Resource type must be `key-value-store`.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "No resource type found in the KVS ARN. Resource type must be `key-value-store`.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Provided ARN must be a global resource ARN. Found: `{parsedArn#region}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Provided ARN is not a valid CloudFront Service ARN. Found: `{parsedArn#service}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "KVS ARN must be a valid ARN", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "KVS ARN must be provided to use this service", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: FIPS is not supported with CloudFront-KeyValueStore.", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudhsm/pom.xml b/services/cloudhsm/pom.xml index 61cc78d0be71..ebae1a4e2d6f 100644 --- a/services/cloudhsm/pom.xml +++ b/services/cloudhsm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudhsm AWS Java SDK :: Services :: AWS CloudHSM diff --git a/services/cloudhsm/src/main/resources/codegen-resources/customization.config b/services/cloudhsm/src/main/resources/codegen-resources/customization.config index 6652e711eac8..187b67c0492a 100644 --- a/services/cloudhsm/src/main/resources/codegen-resources/customization.config +++ b/services/cloudhsm/src/main/resources/codegen-resources/customization.config @@ -29,6 +29,5 @@ "listHapgs", "listHsms", "listLunaClients" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudhsm/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudhsm/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..170d12dacab4 --- /dev/null +++ b/services/cloudhsm/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsm-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsm.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsm.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudhsm/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudhsm/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 355e14f6258c..000000000000 --- a/services/cloudhsm/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsm-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsm.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsm.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudhsmv2/pom.xml b/services/cloudhsmv2/pom.xml index a7a41d887cfe..86f6d4dd67dd 100644 --- a/services/cloudhsmv2/pom.xml +++ b/services/cloudhsmv2/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 cloudhsmv2 diff --git a/services/cloudhsmv2/src/main/resources/codegen-resources/customization.config b/services/cloudhsmv2/src/main/resources/codegen-resources/customization.config index 945a45b4b737..520d4370a713 100644 --- a/services/cloudhsmv2/src/main/resources/codegen-resources/customization.config +++ b/services/cloudhsmv2/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "describeBackups", "describeClusters" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cad6f28e7b80 --- /dev/null +++ b/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,227 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsmv2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsmv2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsmv2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsmv2.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudhsmv2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAABwX14QoAAAAIAAAACAX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAwAAAALAAAABgX14QYF9eEHAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 973129dfa650..000000000000 --- a/services/cloudhsmv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsmv2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsmv2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsmv2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://cloudhsmv2.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://cloudhsmv2.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudhsmv2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudsearch/pom.xml b/services/cloudsearch/pom.xml index 3a64dd9e140b..fc4936ec5276 100644 --- a/services/cloudsearch/pom.xml +++ b/services/cloudsearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudsearch AWS Java SDK :: Services :: Amazon CloudSearch diff --git a/services/cloudsearch/src/main/resources/codegen-resources/customization.config b/services/cloudsearch/src/main/resources/codegen-resources/customization.config index 4401302928b5..285ba78e6734 100644 --- a/services/cloudsearch/src/main/resources/codegen-resources/customization.config +++ b/services/cloudsearch/src/main/resources/codegen-resources/customization.config @@ -2,8 +2,6 @@ "verifiedSimpleMethods": [ "describeDomains", "listDomainNames" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6a6c06795907 --- /dev/null +++ b/services/cloudsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearch-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearch.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearch.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudsearch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudsearch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1739b4525c5a..000000000000 --- a/services/cloudsearch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearch-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearch-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearch.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearch.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudsearchdomain/pom.xml b/services/cloudsearchdomain/pom.xml index 1c0c0f2306dd..67c105b6aeb9 100644 --- a/services/cloudsearchdomain/pom.xml +++ b/services/cloudsearchdomain/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudsearchdomain AWS Java SDK :: Services :: Amazon CloudSearch Domain diff --git a/services/cloudsearchdomain/src/main/resources/codegen-resources/customization.config b/services/cloudsearchdomain/src/main/resources/codegen-resources/customization.config index 1636188d7d29..46273cc3325c 100644 --- a/services/cloudsearchdomain/src/main/resources/codegen-resources/customization.config +++ b/services/cloudsearchdomain/src/main/resources/codegen-resources/customization.config @@ -23,6 +23,5 @@ }, "interceptors": [ "software.amazon.awssdk.services.cloudsearchdomain.internal.SwitchToPostInterceptor" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cab755c3ba3a --- /dev/null +++ b/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearchdomain-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearchdomain-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearchdomain.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudsearchdomain.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 456d6fa72990..000000000000 --- a/services/cloudsearchdomain/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearchdomain-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearchdomain-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearchdomain.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudsearchdomain.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudtrail/pom.xml b/services/cloudtrail/pom.xml index 486641d9ed38..b94c37174c61 100644 --- a/services/cloudtrail/pom.xml +++ b/services/cloudtrail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudtrail AWS Java SDK :: Services :: AWS CloudTrail diff --git a/services/cloudtrail/src/main/resources/codegen-resources/customization.config b/services/cloudtrail/src/main/resources/codegen-resources/customization.config index 2608a329c80e..50cea27f118f 100644 --- a/services/cloudtrail/src/main/resources/codegen-resources/customization.config +++ b/services/cloudtrail/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ "describeTrails", "listPublicKeys", "lookupEvents" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudtrail/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudtrail/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..89fc0df21acf --- /dev/null +++ b/services/cloudtrail/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudtrail/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudtrail/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 67f946f9b287..000000000000 --- a/services/cloudtrail/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://cloudtrail.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://cloudtrail.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudtrail/src/main/resources/codegen-resources/service-2.json b/services/cloudtrail/src/main/resources/codegen-resources/service-2.json index fa52bfd1f915..382818621c20 100644 --- a/services/cloudtrail/src/main/resources/codegen-resources/service-2.json +++ b/services/cloudtrail/src/main/resources/codegen-resources/service-2.json @@ -64,7 +64,7 @@ {"shape":"NoManagementAccountSLRExistsException"}, {"shape":"ConflictException"} ], - "documentation":"

    Cancels a query if the query is not in a terminated state, such as CANCELLED, FAILED, TIMED_OUT, or FINISHED. You must specify an ARN value for EventDataStore. The ID of the query that you want to cancel is also required. When you run CancelQuery, the query status might show as CANCELLED even if the operation is not yet finished.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Cancels a query if the query is not in a terminated state, such as CANCELLED, FAILED, TIMED_OUT, or FINISHED. You must specify an ARN value for EventDataStore. The ID of the query that you want to cancel is also required. When you run CancelQuery, the query status might show as CANCELLED even if the operation is not yet finished.

    ", "idempotent":true }, "CreateChannel":{ @@ -89,7 +89,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Creates a channel for CloudTrail to ingest events from a partner or external source. After you create a channel, a CloudTrail Lake event data store can log events from the partner or source that you specify.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Creates a channel for CloudTrail to ingest events from a partner or external source. After you create a channel, a CloudTrail Lake event data store can log events from the partner or source that you specify.

    " }, "CreateDashboard":{ "name":"CreateDashboard", @@ -109,7 +109,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Creates a custom dashboard or the Highlights dashboard.

    • Custom dashboards - Custom dashboards allow you to query events in any event data store type. You can add up to 10 widgets to a custom dashboard. You can manually refresh a custom dashboard, or you can set a refresh schedule.

    • Highlights dashboard - You can create the Highlights dashboard to see a summary of key user activities and API usage across all your event data stores. CloudTrail Lake manages the Highlights dashboard and refreshes the dashboard every 6 hours. To create the Highlights dashboard, you must set and enable a refresh schedule.

    CloudTrail runs queries to populate the dashboard's widgets during a manual or scheduled refresh. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    To set a refresh schedule, CloudTrail must be granted permissions to run the StartDashboardRefresh operation to refresh the dashboard on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to the dashboard. For more information, see Resource-based policy example for a dashboard in the CloudTrail User Guide.

    For more information about dashboards, see CloudTrail Lake dashboards in the CloudTrail User Guide.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Creates a custom dashboard or the Highlights dashboard.

    • Custom dashboards - Custom dashboards allow you to query events in any event data store type. You can add up to 10 widgets to a custom dashboard. You can manually refresh a custom dashboard, or you can set a refresh schedule.

    • Highlights dashboard - You can create the Highlights dashboard to see a summary of key user activities and API usage across all your event data stores. CloudTrail Lake manages the Highlights dashboard and refreshes the dashboard every 6 hours. To create the Highlights dashboard, you must set and enable a refresh schedule.

    CloudTrail runs queries to populate the dashboard's widgets during a manual or scheduled refresh. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    To set a refresh schedule, CloudTrail must be granted permissions to run the StartDashboardRefresh operation to refresh the dashboard on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to the dashboard. For more information, see Resource-based policy example for a dashboard in the CloudTrail User Guide.

    For more information about dashboards, see CloudTrail Lake dashboards in the CloudTrail User Guide.

    ", "idempotent":true }, "CreateEventDataStore":{ @@ -141,7 +141,7 @@ {"shape":"NoManagementAccountSLRExistsException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Creates a new event data store.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Creates a new event data store.

    " }, "CreateTrail":{ "name":"CreateTrail", @@ -203,7 +203,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Deletes a channel.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Deletes a channel.

    " }, "DeleteDashboard":{ "name":"DeleteDashboard", @@ -218,7 +218,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Deletes the specified dashboard. You cannot delete a dashboard that has termination protection enabled.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Deletes the specified dashboard. You cannot delete a dashboard that has termination protection enabled.

    ", "idempotent":true }, "DeleteEventDataStore":{ @@ -245,7 +245,7 @@ {"shape":"ConflictException"}, {"shape":"EventDataStoreFederationEnabledException"} ], - "documentation":"

    Disables the event data store specified by EventDataStore, which accepts an event data store ARN. After you run DeleteEventDataStore, the event data store enters a PENDING_DELETION state, and is automatically deleted after a wait period of seven days. TerminationProtectionEnabled must be set to False on the event data store and the FederationStatus must be DISABLED. You cannot delete an event data store if TerminationProtectionEnabled is True or the FederationStatus is ENABLED.

    After you run DeleteEventDataStore on an event data store, you cannot run ListQueries, DescribeQuery, or GetQueryResults on queries that are using an event data store in a PENDING_DELETION state. An event data store in the PENDING_DELETION state does not incur costs.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Disables the event data store specified by EventDataStore, which accepts an event data store ARN. After you run DeleteEventDataStore, the event data store enters a PENDING_DELETION state, and is automatically deleted after a wait period of seven days. TerminationProtectionEnabled must be set to False on the event data store and the FederationStatus must be DISABLED. You cannot delete an event data store if TerminationProtectionEnabled is True or the FederationStatus is ENABLED.

    After you run DeleteEventDataStore on an event data store, you cannot run ListQueries, DescribeQuery, or GetQueryResults on queries that are using an event data store in a PENDING_DELETION state. An event data store in the PENDING_DELETION state does not incur costs.

    " }, "DeleteResourcePolicy":{ "name":"DeleteResourcePolicy", @@ -333,7 +333,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Returns metadata about a query, including query run time in milliseconds, number of events scanned and matched, and query status. If the query results were delivered to an S3 bucket, the response also provides the S3 URI and the delivery status.

    You must specify either QueryId or QueryAlias. Specifying the QueryAlias parameter returns information about the last query run for the alias. You can provide RefreshId along with QueryAlias to view the query results of a dashboard query for the specified RefreshId.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns metadata about a query, including query run time in milliseconds, number of events scanned and matched, and query status. If the query results were delivered to an S3 bucket, the response also provides the S3 URI and the delivery status.

    You must specify either QueryId or QueryAlias. Specifying the QueryAlias parameter returns information about the last query run for the alias. You can provide RefreshId along with QueryAlias to view the query results of a dashboard query for the specified RefreshId.

    ", "idempotent":true }, "DescribeTrails":{ @@ -378,7 +378,7 @@ {"shape":"ConcurrentModificationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Disables Lake query federation on the specified event data store. When you disable federation, CloudTrail disables the integration with Glue, Lake Formation, and Amazon Athena. After disabling Lake query federation, you can no longer query your event data in Amazon Athena.

    No CloudTrail Lake data is deleted when you disable federation and you can continue to run queries in CloudTrail Lake.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Disables Lake query federation on the specified event data store. When you disable federation, CloudTrail disables the integration with Glue, Lake Formation, and Amazon Athena. After disabling Lake query federation, you can no longer query your event data in Amazon Athena.

    No CloudTrail Lake data is deleted when you disable federation and you can continue to run queries in CloudTrail Lake.

    " }, "EnableFederation":{ "name":"EnableFederation", @@ -405,7 +405,7 @@ {"shape":"AccessDeniedException"}, {"shape":"EventDataStoreFederationEnabledException"} ], - "documentation":"

    Enables Lake query federation on the specified event data store. Federating an event data store lets you view the metadata associated with the event data store in the Glue Data Catalog and run SQL queries against your event data using Amazon Athena. The table metadata stored in the Glue Data Catalog lets the Athena query engine know how to find, read, and process the data that you want to query.

    When you enable Lake query federation, CloudTrail creates a managed database named aws:cloudtrail (if the database doesn't already exist) and a managed federated table in the Glue Data Catalog. The event data store ID is used for the table name. CloudTrail registers the role ARN and event data store in Lake Formation, the service responsible for allowing fine-grained access control of the federated resources in the Glue Data Catalog.

    For more information about Lake query federation, see Federate an event data store.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Enables Lake query federation on the specified event data store. Federating an event data store lets you view the metadata associated with the event data store in the Glue Data Catalog and run SQL queries against your event data using Amazon Athena. The table metadata stored in the Glue Data Catalog lets the Athena query engine know how to find, read, and process the data that you want to query.

    When you enable Lake query federation, CloudTrail creates a managed database named aws:cloudtrail (if the database doesn't already exist) and a managed federated table in the Glue Data Catalog. The event data store ID is used for the table name. CloudTrail registers the role ARN and event data store in Lake Formation, the service responsible for allowing fine-grained access control of the federated resources in the Glue Data Catalog.

    For more information about Lake query federation, see Federate an event data store.

    " }, "GenerateQuery":{ "name":"GenerateQuery", @@ -425,7 +425,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Generates a query from a natural language prompt. This operation uses generative artificial intelligence (generative AI) to produce a ready-to-use SQL query from the prompt.

    The prompt can be a question or a statement about the event data in your event data store. For example, you can enter prompts like \"What are my top errors in the past month?\" and “Give me a list of users that used SNS.”

    The prompt must be in English. For information about limitations, permissions, and supported Regions, see Create CloudTrail Lake queries from natural language prompts in the CloudTrail user guide.

    Do not include any personally identifying, confidential, or sensitive information in your prompts.

    This feature uses generative AI large language models (LLMs); we recommend double-checking the LLM response.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Generates a query from a natural language prompt. This operation uses generative artificial intelligence (generative AI) to produce a ready-to-use SQL query from the prompt.

    The prompt can be a question or a statement about the event data in your event data store. For example, you can enter prompts like \"What are my top errors in the past month?\" and “Give me a list of users that used SNS.”

    The prompt must be in English. For information about limitations, permissions, and supported Regions, see Create CloudTrail Lake queries from natural language prompts in the CloudTrail user guide.

    Do not include any personally identifying, confidential, or sensitive information in your prompts.

    This feature uses generative AI large language models (LLMs); we recommend double-checking the LLM response.

    ", "idempotent":true }, "GetChannel":{ @@ -442,7 +442,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns information about a specific channel.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information about a specific channel.

    ", "idempotent":true }, "GetDashboard":{ @@ -457,7 +457,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns the specified dashboard.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns the specified dashboard.

    ", "idempotent":true }, "GetEventConfiguration":{ @@ -501,7 +501,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Returns information about an event data store specified as either an ARN or the ID portion of the ARN.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information about an event data store specified as either an ARN or the ID portion of the ARN.

    ", "idempotent":true }, "GetEventSelectors":{ @@ -537,7 +537,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns information about a specific import.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information about a specific import.

    " }, "GetInsightSelectors":{ "name":"GetInsightSelectors", @@ -583,7 +583,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Gets event data results of a query. You must specify the QueryID value returned by the StartQuery operation.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Gets event data results of a query. You must specify the QueryID value returned by the StartQuery operation.

    " }, "GetResourcePolicy":{ "name":"GetResourcePolicy", @@ -653,7 +653,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Lists the channels in the current account, and their source names.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Lists the channels in the current account, and their source names.

    ", "idempotent":true }, "ListDashboards":{ @@ -667,7 +667,7 @@ "errors":[ {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns information about all dashboards in the account, in the current Region.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information about all dashboards in the account, in the current Region.

    ", "idempotent":true }, "ListEventDataStores":{ @@ -685,7 +685,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Returns information about all event data stores in the account, in the current Region.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information about all event data stores in the account, in the current Region.

    ", "idempotent":true }, "ListImportFailures":{ @@ -702,7 +702,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"InvalidParameterException"} ], - "documentation":"

    Returns a list of failures for the specified import.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns a list of failures for the specified import.

    ", "idempotent":true }, "ListImports":{ @@ -720,7 +720,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns information on all imports, or a select set of imports by ImportStatus or Destination.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns information on all imports, or a select set of imports by ImportStatus or Destination.

    ", "idempotent":true }, "ListInsightsData":{ @@ -736,7 +736,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns Insights events generated on a trail that logs data events. You can list Insights events that occurred in a Region within the last 90 days.

    ListInsightsData supports the following Dimensions for Insights events:

    • Event ID

    • Event name

    • Event source

    All dimensions are optional. The default number of results returned is 50, with a maximum of 50 possible. The response includes a token that you can use to get the next page of results.

    The rate of ListInsightsData requests is limited to two per second, per account, per Region. If this limit is exceeded, a throttling error occurs.

    ", + "documentation":"

    Returns Insights events generated on a trail that logs data events. You can list Insights events that occurred in a Region within the last 90 days.

    ListInsightsData supports the following Dimensions for Insights events:

    • Event ID

    • Event name

    • Event source

    All dimensions are optional. The default number of results returned is 50, with a maximum of 50 possible. The response includes a token that you can use to get the next page of results.

    The rate of ListInsightsData requests is limited to two per second, per account, per Region. If this limit is exceeded, a throttling error occurs.

    For data event Insights on organization trails, only the management account and delegated administrator accounts can call ListInsightsData. For these callers, the API returns Insights events only for the caller's own account. Member accounts cannot call this API on organization trails.

    ", "idempotent":true }, "ListInsightsMetricData":{ @@ -753,7 +753,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Returns Insights metrics data for trails that have enabled Insights. The request must include the EventSource, EventName, and InsightType parameters.

    If the InsightType is set to ApiErrorRateInsight, the request must also include the ErrorCode parameter.

    The following are the available time periods for ListInsightsMetricData. Each cutoff is inclusive.

    • Data points with a period of 60 seconds (1-minute) are available for 15 days.

    • Data points with a period of 300 seconds (5-minute) are available for 63 days.

    • Data points with a period of 3600 seconds (1 hour) are available for 90 days.

    To use ListInsightsMetricData operation, you must have the following permissions:

    • If ListInsightsMetricData is invoked with TrailName parameter, access to the ListInsightsMetricData API operation is linked to the cloudtrail:LookupEvents action and cloudtrail:ListInsightsData. To use this operation, you must have permissions to perform the cloudtrail:LookupEvents and cloudtrail:ListInsightsData action on the specific trail.

    • If ListInsightsMetricData is invoked without TrailName parameter, access to the ListInsightsMetricData API operation is linked to the cloudtrail:LookupEvents action only. To use this operation, you must have permissions to perform the cloudtrail:LookupEvents action.

    ", + "documentation":"

    Returns Insights metrics data for trails that have enabled Insights. The request must include the EventSource, EventName, and InsightType parameters.

    If the InsightType is set to ApiErrorRateInsight, the request must also include the ErrorCode parameter.

    The following are the available time periods for ListInsightsMetricData. Each cutoff is inclusive.

    • Data points with a period of 60 seconds (1-minute) are available for 15 days.

    • Data points with a period of 300 seconds (5-minute) are available for 63 days.

    • Data points with a period of 3600 seconds (1 hour) are available for 90 days.

    To use ListInsightsMetricData operation, you must have the following permissions:

    • If ListInsightsMetricData is invoked with TrailName parameter, access to the ListInsightsMetricData API operation is linked to the cloudtrail:LookupEvents action and cloudtrail:ListInsightsData. To use this operation, you must have permissions to perform the cloudtrail:LookupEvents and cloudtrail:ListInsightsData action on the specific trail.

    • If ListInsightsMetricData is invoked without TrailName parameter, access to the ListInsightsMetricData API operation is linked to the cloudtrail:LookupEvents action only. To use this operation, you must have permissions to perform the cloudtrail:LookupEvents action.

    For data event Insights on organization trails, only the management account and delegated administrator accounts can call ListInsightsMetricData. For these callers, the API returns Insights metrics only for the caller's own account. Member accounts cannot call this API on organization trails.

    ", "idempotent":true }, "ListPublicKeys":{ @@ -794,7 +794,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Returns a list of queries and query statuses for the past seven days. You must specify an ARN value for EventDataStore. Optionally, to shorten the list of results, you can specify a time range, formatted as timestamps, by adding StartTime and EndTime parameters, and a QueryStatus value. Valid values for QueryStatus include QUEUED, RUNNING, FINISHED, FAILED, TIMED_OUT, or CANCELLED.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Returns a list of queries and query statuses for the past seven days. You must specify an ARN value for EventDataStore. Optionally, to shorten the list of results, you can specify a time range, formatted as timestamps, by adding StartTime and EndTime parameters, and a QueryStatus value. Valid values for QueryStatus include QUEUED, RUNNING, FINISHED, FAILED, TIMED_OUT, or CANCELLED.

    ", "idempotent":true }, "ListTags":{ @@ -938,6 +938,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"NotOrganizationMasterAccountException"}, {"shape":"NoManagementAccountSLRExistsException"}, + {"shape":"ConflictException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Lets you enable Insights event logging on specific event categories by specifying the Insights selectors that you want to enable on an existing trail or event data store. You also use PutInsightSelectors to turn off Insights event logging, by passing an empty list of Insights types. The valid Insights event types are ApiErrorRateInsight and ApiCallRateInsight, and valid EventCategories are Management and Data.

    Insights on data events are not supported on event data stores. For event data stores, you can only enable Insights on management events.

    To enable Insights on an event data store, you must specify the ARNs (or ID suffix of the ARNs) for the source event data store (EventDataStore) and the destination event data store (InsightsDestination). The source event data store logs management events and enables Insights. The destination event data store logs Insights events based upon the management event activity of the source event data store. The source and destination event data stores must belong to the same Amazon Web Services account.

    To log Insights events for a trail, you must specify the name (TrailName) of the CloudTrail trail for which you want to change or add Insights selectors.

    • For Management events Insights: To log CloudTrail Insights on the API call rate, the trail or event data store must log write management events. To log CloudTrail Insights on the API error rate, the trail or event data store must log read or write management events.

    • For Data events Insights: To log CloudTrail Insights on the API call rate or API error rate, the trail must log read or write data events. Data events Insights are not supported on event data store.

    To log CloudTrail Insights events on API call volume, the trail or event data store must log write management events. To log CloudTrail Insights events on API error rate, the trail or event data store must log read or write management events. You can call GetEventSelectors on a trail to check whether the trail logs management events. You can call GetEventDataStore on an event data store to check whether the event data store logs management events.

    For more information, see Working with CloudTrail Insights in the CloudTrail User Guide.

    ", @@ -1041,7 +1042,7 @@ {"shape":"NoManagementAccountSLRExistsException"}, {"shape":"OrganizationNotInAllFeaturesModeException"} ], - "documentation":"

    Restores a deleted event data store specified by EventDataStore, which accepts an event data store ARN. You can only restore a deleted event data store within the seven-day wait period after deletion. Restoring an event data store can take several minutes, depending on the size of the event data store.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Restores a deleted event data store specified by EventDataStore, which accepts an event data store ARN. You can only restore a deleted event data store within the seven-day wait period after deletion. Restoring an event data store can take several minutes, depending on the size of the event data store.

    " }, "SearchSampleQueries":{ "name":"SearchSampleQueries", @@ -1056,7 +1057,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"OperationNotPermittedException"} ], - "documentation":"

    Searches sample queries and returns a list of sample queries that are sorted by relevance. To search for sample queries, provide a natural language SearchPhrase in English.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Searches sample queries and returns a list of sample queries that are sorted by relevance. To search for sample queries, provide a natural language SearchPhrase in English.

    ", "idempotent":true }, "StartDashboardRefresh":{ @@ -1074,7 +1075,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Starts a refresh of the specified dashboard.

    Each time a dashboard is refreshed, CloudTrail runs queries to populate the dashboard's widgets. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Starts a refresh of the specified dashboard.

    Each time a dashboard is refreshed, CloudTrail runs queries to populate the dashboard's widgets. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    ", "idempotent":true }, "StartEventDataStoreIngestion":{ @@ -1098,7 +1099,7 @@ {"shape":"InsufficientDependencyServiceAccessPermissionException"}, {"shape":"ConflictException"} ], - "documentation":"

    Starts the ingestion of live events on an event data store specified as either an ARN or the ID portion of the ARN. To start ingestion, the event data store Status must be STOPPED_INGESTION and the eventCategory must be Management, Data, NetworkActivity, or ConfigurationItem.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Starts the ingestion of live events on an event data store specified as either an ARN or the ID portion of the ARN. To start ingestion, the event data store Status must be STOPPED_INGESTION and the eventCategory must be Management, Data, NetworkActivity, or ConfigurationItem.

    " }, "StartImport":{ "name":"StartImport", @@ -1124,7 +1125,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Starts an import of logged trail events from a source S3 bucket to a destination event data store. By default, CloudTrail only imports events contained in the S3 bucket's CloudTrail prefix and the prefixes inside the CloudTrail prefix, and does not check prefixes for other Amazon Web Services services. If you want to import CloudTrail events contained in another prefix, you must include the prefix in the S3LocationUri. For more considerations about importing trail events, see Considerations for copying trail events in the CloudTrail User Guide.

    When you start a new import, the Destinations and ImportSource parameters are required. Before starting a new import, disable any access control lists (ACLs) attached to the source S3 bucket. For more information about disabling ACLs, see Controlling ownership of objects and disabling ACLs for your bucket.

    When you retry an import, the ImportID parameter is required.

    If the destination event data store is for an organization, you must use the management account to import trail events. You cannot use the delegated administrator account for the organization.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Starts an import of logged trail events from a source S3 bucket to a destination event data store. By default, CloudTrail only imports events contained in the S3 bucket's CloudTrail prefix and the prefixes inside the CloudTrail prefix, and does not check prefixes for other Amazon Web Services services. If you want to import CloudTrail events contained in another prefix, you must include the prefix in the S3LocationUri. For more considerations about importing trail events, see Considerations for copying trail events in the CloudTrail User Guide.

    When you start a new import, the Destinations and ImportSource parameters are required. Before starting a new import, disable any access control lists (ACLs) attached to the source S3 bucket. For more information about disabling ACLs, see Controlling ownership of objects and disabling ACLs for your bucket.

    When you retry an import, the ImportID parameter is required.

    If the destination event data store is for an organization, you must use the management account to import trail events. You cannot use the delegated administrator account for the organization.

    " }, "StartLogging":{ "name":"StartLogging", @@ -1174,7 +1175,7 @@ {"shape":"UnsupportedOperationException"}, {"shape":"NoManagementAccountSLRExistsException"} ], - "documentation":"

    Starts a CloudTrail Lake query. Use the QueryStatement parameter to provide your SQL query, enclosed in single quotation marks. Use the optional DeliveryS3Uri parameter to deliver the query results to an S3 bucket.

    StartQuery requires you specify either the QueryStatement parameter, or a QueryAlias and any QueryParameters. In the current release, the QueryAlias and QueryParameters parameters are used only for the queries that populate the CloudTrail Lake dashboards.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Starts a CloudTrail Lake query. Use the QueryStatement parameter to provide your SQL query, enclosed in single quotation marks. Use the optional DeliveryS3Uri parameter to deliver the query results to an S3 bucket.

    StartQuery requires you specify either the QueryStatement parameter, or a QueryAlias and any QueryParameters. In the current release, the QueryAlias and QueryParameters parameters are used only for the queries that populate the CloudTrail Lake dashboards.

    ", "idempotent":true }, "StopEventDataStoreIngestion":{ @@ -1198,7 +1199,7 @@ {"shape":"InsufficientDependencyServiceAccessPermissionException"}, {"shape":"ConflictException"} ], - "documentation":"

    Stops the ingestion of live events on an event data store specified as either an ARN or the ID portion of the ARN. To stop ingestion, the event data store Status must be ENABLED and the eventCategory must be Management, Data, NetworkActivity, or ConfigurationItem.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Stops the ingestion of live events on an event data store specified as either an ARN or the ID portion of the ARN. To stop ingestion, the event data store Status must be ENABLED and the eventCategory must be Management, Data, NetworkActivity, or ConfigurationItem.

    " }, "StopImport":{ "name":"StopImport", @@ -1214,7 +1215,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Stops a specified import.

    " + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Stops a specified import.

    " }, "StopLogging":{ "name":"StopLogging", @@ -1260,7 +1261,7 @@ {"shape":"OperationNotPermittedException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Updates a channel specified by a required channel ARN or UUID.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Updates a channel specified by a required channel ARN or UUID.

    ", "idempotent":true }, "UpdateDashboard":{ @@ -1281,7 +1282,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"UnsupportedOperationException"} ], - "documentation":"

    Updates the specified dashboard.

    To set a refresh schedule, CloudTrail must be granted permissions to run the StartDashboardRefresh operation to refresh the dashboard on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to the dashboard. For more information, see Resource-based policy example for a dashboard in the CloudTrail User Guide.

    CloudTrail runs queries to populate the dashboard's widgets during a manual or scheduled refresh. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Updates the specified dashboard.

    To set a refresh schedule, CloudTrail must be granted permissions to run the StartDashboardRefresh operation to refresh the dashboard on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to the dashboard. For more information, see Resource-based policy example for a dashboard in the CloudTrail User Guide.

    CloudTrail runs queries to populate the dashboard's widgets during a manual or scheduled refresh. CloudTrail must be granted permissions to run the StartQuery operation on your behalf. To provide permissions, run the PutResourcePolicy operation to attach a resource-based policy to each event data store. For more information, see Example: Allow CloudTrail to run queries to populate a dashboard in the CloudTrail User Guide.

    ", "idempotent":true }, "UpdateEventDataStore":{ @@ -1316,7 +1317,7 @@ {"shape":"ConflictException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Updates an event data store. The required EventDataStore value is an ARN or the ID portion of the ARN. Other parameters are optional, but at least one optional parameter must be specified, or CloudTrail throws an error. RetentionPeriod is in days, and valid values are integers between 7 and 3653 if the BillingMode is set to EXTENDABLE_RETENTION_PRICING, or between 7 and 2557 if BillingMode is set to FIXED_RETENTION_PRICING. By default, TerminationProtection is enabled.

    For event data stores for CloudTrail events, AdvancedEventSelectors includes or excludes management, data, or network activity events in your event data store. For more information about AdvancedEventSelectors, see AdvancedEventSelectors.

    For event data stores for CloudTrail Insights events, Config configuration items, Audit Manager evidence, or non-Amazon Web Services events, AdvancedEventSelectors includes events of that type in your event data store.

    ", + "documentation":"

    CloudTrail Lake will no longer be open to new customers starting May 31, 2026. If you would like to use CloudTrail Lake, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see CloudTrail Lake availability change.

    Updates an event data store. The required EventDataStore value is an ARN or the ID portion of the ARN. Other parameters are optional, but at least one optional parameter must be specified, or CloudTrail throws an error. RetentionPeriod is in days, and valid values are integers between 7 and 3653 if the BillingMode is set to EXTENDABLE_RETENTION_PRICING, or between 7 and 2557 if BillingMode is set to FIXED_RETENTION_PRICING. By default, TerminationProtection is enabled.

    For event data stores for CloudTrail events, AdvancedEventSelectors includes or excludes management, data, or network activity events in your event data store. For more information about AdvancedEventSelectors, see AdvancedEventSelectors.

    For event data stores for CloudTrail Insights events, Config configuration items, Audit Manager evidence, or non-Amazon Web Services events, AdvancedEventSelectors includes events of that type in your event data store.

    ", "idempotent":true }, "UpdateTrail":{ @@ -1903,7 +1904,7 @@ }, "IncludeGlobalServiceEvents":{ "shape":"Boolean", - "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files.

    " + "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files. Setting this value to true only delivers global service events to the trail if the trail is multi-Region or if the trail's home Region is the partition leader Region (for example, us-east-1).

    " }, "IsMultiRegionTrail":{ "shape":"Boolean", @@ -1929,7 +1930,11 @@ "shape":"Boolean", "documentation":"

    Specifies whether the trail is created for all accounts in an organization in Organizations, or only for the current Amazon Web Services account. The default is false, and cannot be true unless the call is made on behalf of an Amazon Web Services account that is the management account or delegated administrator account for an organization in Organizations.

    " }, - "TagsList":{"shape":"TagsList"} + "TagsList":{"shape":"TagsList"}, + "RecursiveLogging":{ + "shape":"Boolean", + "documentation":"

    Specifies whether recursive logging is enabled for the trail. If you set RecursiveLogging to false, CloudTrail suppresses events generated by CloudTrail when it delivers log files to your trail's destinations, including Amazon S3 and CloudWatch Logs. The default value is true.

    " + } }, "documentation":"

    Specifies the settings for each trail.

    " }, @@ -1959,7 +1964,7 @@ }, "IncludeGlobalServiceEvents":{ "shape":"Boolean", - "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files.

    " + "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files. Setting this value to true only delivers global service events to the trail if the trail is multi-Region or if the trail's home Region is the partition leader Region (for example, us-east-1).

    " }, "IsMultiRegionTrail":{ "shape":"Boolean", @@ -1988,6 +1993,10 @@ "IsOrganizationTrail":{ "shape":"Boolean", "documentation":"

    Specifies whether the trail is an organization trail.

    " + }, + "RecursiveLogging":{ + "shape":"Boolean", + "documentation":"

    Specifies whether recursive logging is enabled for the trail.

    " } }, "documentation":"

    Returns the objects or data listed below if successful. Otherwise, returns an error.

    " @@ -5370,7 +5379,7 @@ }, "IncludeGlobalServiceEvents":{ "shape":"Boolean", - "documentation":"

    Set to True to include Amazon Web Services API calls from Amazon Web Services global services such as IAM. Otherwise, False.

    " + "documentation":"

    Set to True to include Amazon Web Services API calls from Amazon Web Services global services such as IAM. Otherwise, False. Setting this value to true only delivers global service events to the trail if the trail is multi-Region or if the trail's home Region is the partition leader Region (for example, us-east-1).

    " }, "IsMultiRegionTrail":{ "shape":"Boolean", @@ -5411,6 +5420,10 @@ "IsOrganizationTrail":{ "shape":"Boolean", "documentation":"

    Specifies whether the trail is an organization trail.

    " + }, + "RecursiveLogging":{ + "shape":"Boolean", + "documentation":"

    Specifies whether recursive logging is enabled for the trail. If you set RecursiveLogging to false, CloudTrail suppresses events generated by CloudTrail when it delivers log files to your trail's destinations, including Amazon S3 and CloudWatch Logs. The default value is true.

    " } }, "documentation":"

    The settings for a trail.

    " @@ -5705,7 +5718,7 @@ }, "IncludeGlobalServiceEvents":{ "shape":"Boolean", - "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files.

    " + "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files. Setting this value to true only delivers global service events to the trail if the trail is multi-Region or if the trail's home Region is the partition leader Region (for example, us-east-1).

    " }, "IsMultiRegionTrail":{ "shape":"Boolean", @@ -5730,6 +5743,10 @@ "IsOrganizationTrail":{ "shape":"Boolean", "documentation":"

    Specifies whether the trail is applied to all accounts in an organization in Organizations, or only for the current Amazon Web Services account. The default is false, and cannot be true unless the call is made on behalf of an Amazon Web Services account that is the management account for an organization in Organizations. If the trail is not an organization trail and this is set to true, the trail will be created in all Amazon Web Services accounts that belong to the organization. If the trail is an organization trail and this is set to false, the trail will remain in the current Amazon Web Services account but be deleted from all member accounts in the organization.

    Only the management account for the organization can convert an organization trail to a non-organization trail, or convert a non-organization trail to an organization trail.

    " + }, + "RecursiveLogging":{ + "shape":"Boolean", + "documentation":"

    Specifies whether recursive logging is enabled for the trail. If you set RecursiveLogging to false, CloudTrail suppresses events generated by CloudTrail when it delivers log files to your trail's destinations, including Amazon S3 and CloudWatch Logs. The default value is true.

    " } }, "documentation":"

    Specifies settings to update for the trail.

    " @@ -5760,7 +5777,7 @@ }, "IncludeGlobalServiceEvents":{ "shape":"Boolean", - "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files.

    " + "documentation":"

    Specifies whether the trail is publishing events from global services such as IAM to the log files. Setting this value to true only delivers global service events to the trail if the trail is multi-Region or if the trail's home Region is the partition leader Region (for example, us-east-1).

    " }, "IsMultiRegionTrail":{ "shape":"Boolean", @@ -5789,6 +5806,10 @@ "IsOrganizationTrail":{ "shape":"Boolean", "documentation":"

    Specifies whether the trail is an organization trail.

    " + }, + "RecursiveLogging":{ + "shape":"Boolean", + "documentation":"

    Specifies whether recursive logging is enabled for the trail.

    " } }, "documentation":"

    Returns the objects or data listed below if successful. Otherwise, returns an error.

    " diff --git a/services/cloudtraildata/pom.xml b/services/cloudtraildata/pom.xml index 550ddfd72b8f..1c0689a6dca3 100644 --- a/services/cloudtraildata/pom.xml +++ b/services/cloudtraildata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudtraildata AWS Java SDK :: Services :: Cloud Trail Data diff --git a/services/cloudtraildata/src/main/resources/codegen-resources/customization.config b/services/cloudtraildata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/cloudtraildata/src/main/resources/codegen-resources/customization.config +++ b/services/cloudtraildata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4b4aa23c44fb --- /dev/null +++ b/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-data-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-data.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudtrail-data.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index dc3f1fddab79..000000000000 --- a/services/cloudtraildata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-data-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-data.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cloudtrail-data.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/cloudwatch/pom.xml b/services/cloudwatch/pom.xml index ab6e0566ccc9..1897767c293c 100644 --- a/services/cloudwatch/pom.xml +++ b/services/cloudwatch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudwatch AWS Java SDK :: Services :: Amazon CloudWatch diff --git a/services/cloudwatch/src/it/java/software/amazon/awssdk/services/cloudwatch/CloudWatchIntegrationTest.java b/services/cloudwatch/src/it/java/software/amazon/awssdk/services/cloudwatch/CloudWatchIntegrationTest.java index 763d820f3f17..de492783d219 100644 --- a/services/cloudwatch/src/it/java/software/amazon/awssdk/services/cloudwatch/CloudWatchIntegrationTest.java +++ b/services/cloudwatch/src/it/java/software/amazon/awssdk/services/cloudwatch/CloudWatchIntegrationTest.java @@ -27,7 +27,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static software.amazon.awssdk.testutils.service.AwsTestBase.isValidSdkServiceException; import java.io.IOException; import java.time.Duration; @@ -42,7 +41,6 @@ import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.CompressionConfiguration; import software.amazon.awssdk.core.SdkGlobalTime; -import software.amazon.awssdk.core.exception.SdkServiceException; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; import software.amazon.awssdk.regions.Region; @@ -368,9 +366,15 @@ private List createTwoNewAlarms(String metricName) { */ @Test public void testExceptionHandling() throws Exception { + Instant endTime = Instant.now(); try { cloudwatch.getMetricStatistics(GetMetricStatisticsRequest.builder() - .namespace("fake-namespace").build()); + .namespace("fake-namespace") + .startTime(endTime.minus(Duration.ofMinutes(5))) + .endTime(endTime) + .period(60) + .statistics(Statistic.AVERAGE) + .build()); fail("Expected an SdkServiceException, but wasn't thrown"); } catch (MissingRequiredParameterException e) { // There is a strong contract on the value of these fields, and they should never change unexpectedly diff --git a/services/cloudwatch/src/main/resources/codegen-resources/customization.config b/services/cloudwatch/src/main/resources/codegen-resources/customization.config index 7bd64efb5af9..427cfcda0dc0 100644 --- a/services/cloudwatch/src/main/resources/codegen-resources/customization.config +++ b/services/cloudwatch/src/main/resources/codegen-resources/customization.config @@ -9,8 +9,6 @@ "deleteDashboards", "putDashboard", "getDashboard" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudwatch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudwatch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d7be0eb4f720 --- /dev/null +++ b/services/cloudwatch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,203 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://monitoring.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://monitoring.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://monitoring-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://monitoring-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEEAAAABwX14QUF9eEKAAAABAAAAAsAAAAJAAAABQX14QQAAAAKAAAABgX14QgF9eEJAAAABQX14QUAAAAMAAAABgAAAA0F9eEHAAAABwX14QYF9eEHAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudwatch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudwatch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 75ed3cafdecf..000000000000 --- a/services/cloudwatch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,430 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://monitoring.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://monitoring.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://monitoring-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://monitoring-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://monitoring.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://monitoring.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/cloudwatch/src/main/resources/codegen-resources/service-2.json b/services/cloudwatch/src/main/resources/codegen-resources/service-2.json index 77ac08d97945..e340c3aa977e 100644 --- a/services/cloudwatch/src/main/resources/codegen-resources/service-2.json +++ b/services/cloudwatch/src/main/resources/codegen-resources/service-2.json @@ -39,7 +39,7 @@ {"shape":"KmsKeyDisabledException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Associates an Amazon Web Services Key Management Service (Amazon Web Services KMS) customer managed key with the specified dataset. After this operation completes, all data published to the dataset is encrypted at rest using the specified KMS key. Callers must have kms:Decrypt permission on the key to read the encrypted data.

    Only the default dataset is supported. The default dataset is implicit for every account in every Region — you do not need to create it before calling this operation.

    You can call AssociateDatasetKmsKey on a dataset that is already associated with a KMS key to replace the existing key with a different one. To replace a key, the caller must have kms:Decrypt permission on both the current key and the new key.

    The KMS key that you specify must meet all of the following requirements:

    • It must be a symmetric encryption KMS key (key spec SYMMETRIC_DEFAULT, key usage ENCRYPT_DECRYPT). Asymmetric keys, HMAC keys, and key material types other than SYMMETRIC_DEFAULT are not supported.

    • It must be enabled and not pending deletion.

    • Its key policy must grant the CloudWatch service principal (cloudwatch.amazonaws.com) these permissions: kms:DescribeKey, kms:GenerateDataKey, kms:Encrypt, kms:Decrypt, and kms:ReEncrypt*. Amazon CloudWatch requires these permissions to manage the data on your behalf.

    • The calling principal must have kms:Decrypt permission on the key.

    • It must be specified as a fully qualified key ARN. Key IDs, aliases, and alias ARNs are not accepted.

    • It must be in the same Amazon Web Services Region as the dataset.

    Before completing the association, Amazon CloudWatch validates the key by performing a series of dry-run KMS operations. Service-principal checks run first to verify that the key policy grants the required access to Amazon CloudWatch. These checks include kms:DescribeKey, kms:GenerateDataKey, kms:Encrypt, kms:Decrypt, and kms:ReEncrypt*. After those succeed, a kms:Decrypt dry-run is run with the caller's credentials to verify that the calling principal can use the key. When you are replacing an existing key, the caller's kms:Decrypt dry-run is run on the current key first, and only then on the new key.

    If any of these checks fails, the operation fails and the existing key association (if any) remains unchanged. Common failure causes include the key being disabled, the key policy not granting the required permissions to Amazon CloudWatch, or the caller lacking kms:Decrypt permission on the key.

    For more information about using customer managed keys with Amazon CloudWatch, see Encryption at rest with customer managed keys in the Amazon CloudWatch User Guide.

    " + "documentation":"

    Associates an Amazon Web Services Key Management Service (Amazon Web Services KMS) customer managed key with the specified dataset. After this operation completes, all data published to the dataset is encrypted at rest using the specified KMS key. Callers must have kms:Decrypt permission on the key to read the encrypted data.

    Only the default dataset is supported. The default dataset is implicit for every account in every Region — you do not need to create it before calling this operation.

    You can call AssociateDatasetKmsKey on a dataset that is already associated with a KMS key to replace the existing key with a different one. The caller must have kms:Decrypt permission on both the current key and the new key.

    If the currently associated key has been deleted, is scheduled for deletion, is pending import, is unavailable, or has been disabled, Amazon CloudWatch does not require kms:Decrypt permission on the current key and the rotation proceeds. If the key was only disabled, consider re-enabling it instead of rotating, because re-enabling allows Amazon CloudWatch to resume decrypting your existing metric data encrypted with that key.

    The KMS key that you specify must meet all of the following requirements:

    • It must be a symmetric encryption KMS key (key spec SYMMETRIC_DEFAULT, key usage ENCRYPT_DECRYPT). Asymmetric keys, HMAC keys, and key material types other than SYMMETRIC_DEFAULT are not supported.

    • It must be enabled and not pending deletion.

    • Its key policy must grant the CloudWatch service principal (cloudwatch.amazonaws.com) these permissions: kms:DescribeKey, kms:GenerateDataKey, kms:Encrypt, kms:Decrypt, and kms:ReEncrypt*. Amazon CloudWatch requires these permissions to manage the data on your behalf.

    • The calling principal must have kms:Decrypt permission on the key.

    • It must be specified as a fully qualified key ARN. Key IDs, aliases, and alias ARNs are not accepted.

    • It must be in the same Amazon Web Services Region as the dataset.

    Before completing the association, Amazon CloudWatch validates the key by performing a series of dry-run KMS operations. Service-principal checks run first to verify that the key policy grants the required access to Amazon CloudWatch. These checks include kms:DescribeKey, kms:GenerateDataKey, kms:Encrypt, kms:Decrypt, and kms:ReEncrypt*. After those succeed, a kms:Decrypt dry-run is run with the caller's credentials to verify that the calling principal can use the new key. When you are replacing an existing key, the caller's kms:Decrypt dry-run is also run on the current key.

    If any of these checks on the new key fails, the operation fails and the existing key association (if any) remains unchanged. Common failure causes include the new key being disabled, the key policy not granting the required permissions to Amazon CloudWatch, or the caller lacking kms:Decrypt permission on the new key.

    For more information about using customer managed keys with Amazon CloudWatch, see Encryption at rest with customer managed keys in the Amazon CloudWatch User Guide.

    " }, "DeleteAlarmMuteRule":{ "name":"DeleteAlarmMuteRule", @@ -274,7 +274,7 @@ {"shape":"ConflictException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Removes the customer managed Amazon Web Services Key Management Service (Amazon Web Services KMS) key association from the specified dataset. After this operation completes, data that you publish to the dataset is encrypted at rest using an Amazon Web Services owned key managed by Amazon CloudWatch.

    Only the default dataset is supported. To call this operation, the dataset must currently have a customer managed KMS key associated with it. If the dataset has no associated KMS key, the operation fails with ResourceNotFoundException.

    Amazon CloudWatch performs a dry-run kms:Decrypt call on the key as part of this operation. This verifies that the caller is authorized to use the currently associated key. The caller must have kms:Decrypt permission on the currently associated key, and the key must be enabled and accessible. If the key has been disabled or scheduled for deletion, you must first re-enable or restore it before you can disassociate it from the dataset.

    Disassociating a KMS key from a dataset does not immediately remove the kms:Decrypt requirement on data plane operations. For up to three hours after disassociation, callers must continue to have kms:Decrypt permission on the previously associated key. Some data may still be encrypted with that key during this window. After this enforcement window elapses, the kms:Decrypt requirement is lifted.

    For more information about using customer managed keys with Amazon CloudWatch, see Encryption at rest with customer managed keys in the Amazon CloudWatch User Guide.

    ", + "documentation":"

    Removes the customer managed Amazon Web Services Key Management Service (Amazon Web Services KMS) key association from the specified dataset. After this operation completes, data that you publish to the dataset is encrypted at rest using an Amazon Web Services owned key managed by Amazon CloudWatch.

    Only the default dataset is supported. To call this operation, the dataset must currently have a customer managed KMS key associated with it. If the dataset has no associated KMS key, the operation fails with ResourceNotFoundException.

    Amazon CloudWatch performs a dry-run kms:Decrypt call on the currently associated key as part of this operation. The caller must have kms:Decrypt permission on the currently associated key. If the key is accessible but the caller lacks kms:Decrypt permission, the operation fails with AccessDeniedException.

    If the currently associated key has been deleted, is scheduled for deletion, is pending import, is unavailable, or has been disabled, Amazon CloudWatch does not require kms:Decrypt permission on that key and the disassociation proceeds. If the key was only disabled, consider re-enabling it instead of disassociating, because re-enabling allows Amazon CloudWatch to resume decrypting your existing metric data.

    Disassociating a KMS key from a dataset does not immediately remove the kms:Decrypt requirement on data plane operations. For up to three hours after disassociation, callers must continue to have kms:Decrypt permission on the previously associated key. Some data might still be encrypted with that key during this window. After this enforcement window elapses, the kms:Decrypt requirement is lifted.

    For more information about using customer managed keys with Amazon CloudWatch, see Encryption at rest with customer managed keys in the Amazon CloudWatch User Guide.

    ", "idempotent":true }, "EnableAlarmActions":{ @@ -863,7 +863,7 @@ }, "AggregationExpression":{ "type":"string", - "max":256, + "max":2048, "min":1 }, "AlarmArn":{ @@ -1056,6 +1056,10 @@ "AnomalyDetector":{ "type":"structure", "members":{ + "AnomalyDetectorId":{ + "shape":"AnomalyDetectorId", + "documentation":"

    The unique identifier of the anomaly detector.

    The identifier does not restrict access to a specific anomaly detector in an IAM policy. Permissions for anomaly detector operations apply to all anomaly detectors in the account.

    " + }, "Namespace":{ "shape":"Namespace", "documentation":"

    The namespace of the metric associated with the anomaly detection model.

    ", @@ -1121,6 +1125,17 @@ "type":"list", "member":{"shape":"Range"} }, + "AnomalyDetectorId":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[A-Za-z0-9_./:%()+-]+" + }, + "AnomalyDetectorIds":{ + "type":"list", + "member":{"shape":"AnomalyDetectorId"}, + "max":50 + }, "AnomalyDetectorMetricStat":{ "type":"string", "max":50, @@ -1539,6 +1554,10 @@ "DeleteAnomalyDetectorInput":{ "type":"structure", "members":{ + "AnomalyDetectorId":{ + "shape":"AnomalyDetectorId", + "documentation":"

    Specifies the unique identifier of the anomaly detector to delete. If you specify this parameter, you do not need to specify a metric to identify the detector.

    " + }, "Namespace":{ "shape":"Namespace", "documentation":"

    The namespace associated with the anomaly detection model to delete.

    ", @@ -1817,6 +1836,10 @@ "DescribeAnomalyDetectorsInput":{ "type":"structure", "members":{ + "AnomalyDetectorIds":{ + "shape":"AnomalyDetectorIds", + "documentation":"

    Specifies the unique identifiers of the anomaly detectors to describe. You can specify up to 50 identifiers. If you specify this parameter, you cannot also specify the Namespace, MetricName, Dimensions, or AnomalyDetectorTypes metric filters.

    " + }, "NextToken":{ "shape":"NextToken", "documentation":"

    Use the token returned by the previous operation to request the next page of results.

    " @@ -2016,7 +2039,11 @@ } } }, - "EndTimeOffset":{"type":"long"}, + "EndTimeOffset":{ + "type":"long", + "max":2592000, + "min":0 + }, "Entity":{ "type":"structure", "members":{ @@ -2507,7 +2534,7 @@ }, "StatisticsConfigurations":{ "shape":"MetricStreamStatisticsConfigurations", - "documentation":"

    Each entry in this array displays information about one or more metrics that include additional statistics in the metric stream. For more information about the additional statistics, see CloudWatch statistics definitions.

    " + "documentation":"

    Each entry in this array displays information about one or more metrics that include additional statistics in the metric stream. For more information about the additional statistics, see CloudWatch statistics definitions.

    " }, "IncludeLinkedAccountsMetrics":{ "shape":"IncludeLinkedAccountsMetrics", @@ -3205,6 +3232,10 @@ "ActionLogLineRoleArn":{ "shape":"ActionLogLineRoleArn", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that CloudWatch assumes to retrieve log events for inclusion in alarm action notifications. Set when ActionLogLineCount is greater than 0.

    " + }, + "WarmUpConfiguration":{ + "shape":"WarmUpConfiguration", + "documentation":"

    The warm-up configuration for the alarm. A warm-up period delays alarm evaluation after you create or update the alarm. During the warm-up period, the alarm stays in INSUFFICIENT_DATA and does not perform alarm actions.

    For more information, see Alarm warm-up periods in the Amazon CloudWatch User Guide.

    " } }, "documentation":"

    The details about a log alarm.

    ", @@ -3230,7 +3261,8 @@ "TreatMissingData", "EvaluationState", "ActionLogLineCount", - "ActionLogLineRoleArn" + "ActionLogLineRoleArn", + "WarmUpConfiguration" ] }, "LogAlarms":{ @@ -3481,6 +3513,10 @@ "shape":"EvaluationWindow", "documentation":"

    The evaluation window that the alarm uses to select the range of metric data that it evaluates. This is either a sliding window or a wall clock window. For more information, see Alarm evaluation windows in the CloudWatch User Guide.

    " }, + "WarmUpConfiguration":{ + "shape":"WarmUpConfiguration", + "documentation":"

    The warm-up configuration for the alarm. A warm-up period delays alarm evaluation after you create or update the alarm. During the warm-up period, the alarm stays in INSUFFICIENT_DATA and does not perform alarm actions.

    For more information, see Alarm warm-up periods in the Amazon CloudWatch User Guide.

    " + }, "EvaluationCriteria":{ "shape":"EvaluationCriteria", "documentation":"

    The evaluation criteria for the alarm.

    " @@ -3522,6 +3558,7 @@ "EvaluationState", "StateTransitionedTimestamp", "EvaluationWindow", + "WarmUpConfiguration", "EvaluationCriteria", "EvaluationInterval" ] @@ -3815,10 +3852,10 @@ }, "AdditionalStatistics":{ "shape":"MetricStreamStatisticsAdditionalStatistics", - "documentation":"

    The list of additional statistics that are to be streamed for the metrics listed in the IncludeMetrics array in this structure. This list can include as many as 20 statistics.

    If the OutputFormat for the stream is opentelemetry1.0 or opentelemetry0.7, the only valid values are p?? percentile statistics such as p90, p99 and so on.

    If the OutputFormat for the stream is json, the valid values include the abbreviations for all of the statistics listed in CloudWatch statistics definitions. For example, this includes tm98, wm90, PR(:300), and so on.

    " + "documentation":"

    The list of additional statistics that are to be streamed for the metrics listed in the IncludeMetrics array in this structure. This list can include as many as 20 statistics.

    If the OutputFormat for the stream is opentelemetry1.0 or opentelemetry0.7, the only valid values are p?? percentile statistics such as p90, p99 and so on.

    If the OutputFormat for the stream is json, the valid values include the abbreviations for all of the statistics listed in CloudWatch statistics definitions. For example, this includes tm98, wm90, PR(:300), and so on.

    " } }, - "documentation":"

    By default, a metric stream always sends the MAX, MIN, SUM, and SAMPLECOUNT statistics for each metric that is streamed. This structure contains information for one metric that includes additional statistics in the stream. For more information about statistics, see CloudWatch, listed in CloudWatch statistics definitions.

    " + "documentation":"

    By default, a metric stream always sends the MAX, MIN, SUM, and SAMPLECOUNT statistics for each metric that is streamed. This structure contains information for one metric that includes additional statistics in the stream. For more information about statistics, see CloudWatch, listed in CloudWatch statistics definitions.

    " }, "MetricStreamStatisticsConfigurations":{ "type":"list", @@ -3906,6 +3943,7 @@ "Stopped" ] }, + "OnlyStartEvaluatingAfterWarmUpPeriodEnds":{"type":"boolean"}, "OutputFormat":{"type":"string"}, "OwningAccounts":{ "type":"list", @@ -4027,7 +4065,12 @@ }, "PutAnomalyDetectorOutput":{ "type":"structure", - "members":{} + "members":{ + "AnomalyDetectorId":{ + "shape":"AnomalyDetectorId", + "documentation":"

    The unique identifier of the anomaly detector that you created or updated.

    " + } + } }, "PutCompositeAlarmInput":{ "type":"structure", @@ -4215,6 +4258,10 @@ "Tags":{ "shape":"TagList", "documentation":"

    A list of key-value pairs to associate with the alarm. You can use tags to categorize and manage your alarms.

    " + }, + "WarmUpConfiguration":{ + "shape":"WarmUpConfiguration", + "documentation":"

    The warm-up configuration for the alarm. A warm-up period delays alarm evaluation after you create or update the alarm. The warm-up period reduces alarm noise from missing data while a new resource or service starts publishing data.

    For more information, see Alarm warm-up periods in the Amazon CloudWatch User Guide.

    " } } }, @@ -4333,6 +4380,10 @@ "shape":"EvaluationWindow", "documentation":"

    The evaluation window that the alarm uses to select the range of metric data that it evaluates. Specify either a sliding window or a wall clock window. If you omit this parameter, the alarm uses a sliding window.

    A sliding window advances each time the alarm is evaluated, forming a rolling time window. A wall clock window aligns the evaluated range to fixed clock boundaries, such as the top of the hour or the start of the day.

    You can use EvaluationWindow with any type of metric alarm except alarms that are based on a PromQL query.

    For more information, see Alarm evaluation windows in the CloudWatch User Guide.

    " }, + "WarmUpConfiguration":{ + "shape":"WarmUpConfiguration", + "documentation":"

    The warm-up configuration for the alarm. A warm-up period delays alarm evaluation after you create or update the alarm. The warm-up period reduces alarm noise from missing data while a new resource or service starts publishing metrics.

    For more information, see Alarm warm-up periods in the Amazon CloudWatch User Guide.

    " + }, "EvaluationCriteria":{ "shape":"EvaluationCriteria", "documentation":"

    The evaluation criteria for the alarm. For each PutMetricAlarm operation, you must specify either MetricName, a Metrics array, or an EvaluationCriteria.

    If you use the EvaluationCriteria parameter, you cannot include the Namespace, MetricName, Dimensions, Period, Unit, Statistic, ExtendedStatistic, Metrics, Threshold, ComparisonOperator, ThresholdMetricId, EvaluationPeriods, or DatapointsToAlarm parameters of PutMetricAlarm in the same operation. Instead, all evaluation parameters are defined within this structure.

    For an example of how to use this parameter, see the PromQL alarm example on this page.

    " @@ -4405,7 +4456,7 @@ }, "StatisticsConfigurations":{ "shape":"MetricStreamStatisticsConfigurations", - "documentation":"

    By default, a metric stream always sends the MAX, MIN, SUM, and SAMPLECOUNT statistics for each metric that is streamed. You can use this parameter to have the metric stream also send additional statistics in the stream. This array can have up to 100 members.

    For each entry in this array, you specify one or more metrics and the list of additional statistics to stream for those metrics. The additional statistics that you can stream depend on the stream's OutputFormat. If the OutputFormat is json, you can stream any additional statistic that is supported by CloudWatch, listed in CloudWatch statistics definitions. If the OutputFormat is opentelemetry1.0 or opentelemetry0.7, you can stream percentile statistics such as p95, p99.9, and so on.

    " + "documentation":"

    By default, a metric stream always sends the MAX, MIN, SUM, and SAMPLECOUNT statistics for each metric that is streamed. You can use this parameter to have the metric stream also send additional statistics in the stream. This array can have up to 100 members.

    For each entry in this array, you specify one or more metrics and the list of additional statistics to stream for those metrics. The additional statistics that you can stream depend on the stream's OutputFormat. If the OutputFormat is json, you can stream any additional statistic that is supported by CloudWatch, listed in CloudWatch statistics definitions. If the OutputFormat is opentelemetry1.0 or opentelemetry0.7, you can stream percentile statistics such as p95, p99.9, and so on.

    " }, "IncludeLinkedAccountsMetrics":{ "shape":"IncludeLinkedAccountsMetrics", @@ -4569,7 +4620,10 @@ }, "ScheduleConfiguration":{ "type":"structure", - "required":["ScheduleExpression"], + "required":[ + "ScheduleExpression", + "StartTimeOffset" + ], "members":{ "ScheduleExpression":{ "shape":"ScheduleExpression", @@ -4743,7 +4797,11 @@ "type":"structure", "members":{} }, - "StartTimeOffset":{"type":"long"}, + "StartTimeOffset":{ + "type":"long", + "max":2592000, + "min":1 + }, "Stat":{"type":"string"}, "StateReason":{ "type":"string", @@ -4958,6 +5016,26 @@ } }, "documentation":"

    An evaluation window that aligns the evaluated range to fixed clock boundaries that match the alarm's period, such as the top of the hour, midnight, or the start of the calendar week, optionally in a specific time zone.

    When you use a wall clock window, the alarm's period must be 1 minute (60 seconds), 5 minutes (300 seconds), 1 hour (3,600 seconds), 1 day (86,400 seconds), or 1 week (604,800 seconds). Other period values aren't supported with a wall clock window.

    Choose a wall clock window when your monitoring is tied to a business or calendar period, such as daily reports, batch jobs, or backups, or when you want alarm evaluations to match the periods shown on a metric dashboard.

    " + }, + "WarmUpConfiguration":{ + "type":"structure", + "required":["WarmUpPeriodDurationInMinutes"], + "members":{ + "WarmUpPeriodDurationInMinutes":{ + "shape":"WarmUpPeriodDurationInMinutes", + "documentation":"

    The length of the warm-up period, in minutes. After you create or update the alarm, the alarm stays in INSUFFICIENT_DATA for this duration. During this time, the alarm does not perform alarm actions.

    You can change this value at any time, including after the warm-up period ends. If you change it after the warm-up period ends, the new value does not restart the warm-up period.

    " + }, + "OnlyStartEvaluatingAfterWarmUpPeriodEnds":{ + "shape":"OnlyStartEvaluatingAfterWarmUpPeriodEnds", + "documentation":"

    Specifies whether the alarm waits for the full warm-up period before it starts to evaluate. The default is false. If true, the alarm waits the entire WarmUpPeriodDurationInMinutes before it starts to evaluate, even if metric data arrives earlier. If false, the alarm ends the warm-up period early. Evaluation begins as soon as the alarm has enough metric data to fill its evaluation window.

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

    The configuration settings that define the warm-up behavior for an alarm. Use these settings to delay alarm evaluation after you create or update the alarm, which reduces alarm noise while a new resource or service starts publishing data.

    During the warm-up period, the alarm stays in INSUFFICIENT_DATA and does not perform alarm actions.

    " + }, + "WarmUpPeriodDurationInMinutes":{ + "type":"integer", + "max":2880, + "min":1 } }, "documentation":"

    Amazon CloudWatch enables you to publish, monitor, and manage various metrics, as well as configure alarm actions based on data from metrics. This guide provides detailed information about CloudWatch actions, data types, parameters, and errors. For more information about CloudWatch features, see Amazon CloudWatch and the Amazon CloudWatch User Guide.

    For information about the metrics that other Amazon Web Services products send to CloudWatch, see the Amazon CloudWatch Metrics and Dimensions Reference in the Amazon CloudWatch User Guide.

    Use the following links to get started using the CloudWatch Query API:

    : An alphabetical list of all CloudWatch actions.

    : An alphabetical list of all CloudWatch data types.

    CommonParameters: Parameters that all Query actions can use.

    CommonErrors: Client and server errors that all actions can return.

    Regions and Endpoints: Supported regions and endpoints for all Amazon Web Services products.

    Alternatively, you can use one of the Amazon Web Services SDKs to access CloudWatch using an API tailored to your programming language or platform.

    Developers in the Amazon Web Services developer community also provide their own libraries, which you can find at the following Amazon Web Services developer centers:

    Java Developer Center

    JavaScript Developer Center

    Amazon Web Services Mobile Services

    PHP Developer Center

    Python Developer Center

    Ruby Developer Center

    Windows and .NET Developer Center

    " diff --git a/services/cloudwatchevents/pom.xml b/services/cloudwatchevents/pom.xml index bac48b0dd57d..c5af27d4eb70 100644 --- a/services/cloudwatchevents/pom.xml +++ b/services/cloudwatchevents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudwatchevents AWS Java SDK :: Services :: Amazon CloudWatch Events diff --git a/services/cloudwatchevents/src/main/resources/codegen-resources/customization.config b/services/cloudwatchevents/src/main/resources/codegen-resources/customization.config index fbfefb027d8e..6c893ecd4525 100644 --- a/services/cloudwatchevents/src/main/resources/codegen-resources/customization.config +++ b/services/cloudwatchevents/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "describeEventBus", "listRules" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..30d0a1e01506 --- /dev/null +++ b/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 38a217b8f946..000000000000 --- a/services/cloudwatchevents/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://events.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://events.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://events-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://events.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://events.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudwatchlogs/pom.xml b/services/cloudwatchlogs/pom.xml index 1076f34c3a69..ce94e0e892d1 100644 --- a/services/cloudwatchlogs/pom.xml +++ b/services/cloudwatchlogs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cloudwatchlogs AWS Java SDK :: Services :: Amazon CloudWatch Logs diff --git a/services/cloudwatchlogs/src/main/resources/codegen-resources/customization.config b/services/cloudwatchlogs/src/main/resources/codegen-resources/customization.config index beec95efc1d2..b4f9db4aacfc 100644 --- a/services/cloudwatchlogs/src/main/resources/codegen-resources/customization.config +++ b/services/cloudwatchlogs/src/main/resources/codegen-resources/customization.config @@ -13,6 +13,5 @@ ], "paginationCustomization": { "GetLogEvents": "LastPageHasPreviousToken" - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cb30e70a31fc --- /dev/null +++ b/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://logs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 77b01e015752..000000000000 --- a/services/cloudwatchlogs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://logs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://logs.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://logs.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://logs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://logs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://logs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cloudwatchlogs/src/main/resources/codegen-resources/service-2.json b/services/cloudwatchlogs/src/main/resources/codegen-resources/service-2.json index 7ed6af8c2495..5f29f434c664 100644 --- a/services/cloudwatchlogs/src/main/resources/codegen-resources/service-2.json +++ b/services/cloudwatchlogs/src/main/resources/codegen-resources/service-2.json @@ -198,7 +198,7 @@ {"shape":"ValidationException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    Creates a lookup table by uploading CSV data. You can use lookup tables to enrich log data in CloudWatch Logs Insights queries with reference data such as user details, application names, or error descriptions.

    The table name must be unique within your account and Region. The CSV content must include a header row with column names, use UTF-8 encoding, and not exceed 10 MB.

    " + "documentation":"

    Creates a lookup table by uploading CSV data or from CloudWatch Logs query results. You can use lookup tables to enrich log data in CloudWatch Logs queries with reference data such as user details, application names, or error descriptions.

    The table name must be unique within your account and Region. You must specify either tableBody or queryId, but not both. If you use tableBody, the CSV content must include a header row with column names, use UTF-8 encoding, and not exceed 10 MB.

    " }, "CreateScheduledQuery":{ "name":"CreateScheduledQuery", @@ -674,7 +674,7 @@ {"shape":"OperationAbortedException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    Returns a list of custom and default field indexes which are discovered in log data. For more information about field index policies, see PutIndexPolicy.

    " + "documentation":"

    Returns a list of field indexes discovered in log data. By default, the response includes the DEFAULT, CUSTOM, and INACTIVE index categories. To return indexes from other categories, use the indexCategories parameter.

    For more information about field index policies, see PutIndexPolicy.

    " }, "DescribeImportTaskBatches":{ "name":"DescribeImportTaskBatches", @@ -1166,7 +1166,7 @@ {"shape":"OperationAbortedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Returns the storage tier policy for your account.

    " + "documentation":"

    Returns the storage tier policy for the account.

    " }, "GetTransformer":{ "name":"GetTransformer", @@ -1636,7 +1636,7 @@ {"shape":"OperationAbortedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Sets the storage tier policy for your account. When you set the storage tier to INTELLIGENT_TIERING, CloudWatch Logs automatically moves your log data between storage tiers based on access patterns to optimize costs.

    " + "documentation":"

    Sets the storage tier policy for the account. When you set the storage tier to INTELLIGENT_TIERING, the service automatically moves log data to the most cost-effective storage tier based on access frequency.

    " }, "PutSubscriptionFilter":{ "name":"PutSubscriptionFilter", @@ -1890,7 +1890,7 @@ {"shape":"ValidationException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    Updates an existing lookup table by replacing all of its CSV content. After the update completes, queries that use this table will use the new data.

    This is a full replacement operation. All existing content is replaced with the new CSV data.

    " + "documentation":"

    Updates an existing lookup table by replacing all of its content with new CSV data or CloudWatch Logs query results. After the update completes, queries that use this table use the new data.

    This is a full replacement operation. All existing content is replaced. You must specify either tableBody or queryId, but not both.

    " }, "UpdateScheduledQuery":{ "name":"UpdateScheduledQuery", @@ -2718,10 +2718,7 @@ }, "CreateLookupTableRequest":{ "type":"structure", - "required":[ - "lookupTableName", - "tableBody" - ], + "required":["lookupTableName"], "members":{ "lookupTableName":{ "shape":"LookupTableName", @@ -2733,7 +2730,11 @@ }, "tableBody":{ "shape":"TableBody", - "documentation":"

    The CSV content of the lookup table. The first row must be a header row with column names. The content must use UTF-8 encoding and not exceed 10 MB.

    " + "documentation":"

    The CSV content of the lookup table. The first row must be a header row with column names. The content must use UTF-8 encoding and not exceed 10 MB.

    You must specify either tableBody or queryId, but not both.

    " + }, + "queryId":{ + "shape":"QueryId", + "documentation":"

    The ID of a completed or cancelled CloudWatch Logs query whose results populate the lookup table. A cancelled query populates the table with the partial results that were available when the query was stopped.

    You must specify either tableBody or queryId, but not both.

    " }, "kmsKeyId":{ "shape":"KmsKeyId", @@ -2806,7 +2807,7 @@ }, "destinationConfiguration":{ "shape":"DestinationConfiguration", - "documentation":"

    Configuration for where to deliver query results. Currently supports Amazon S3 destinations for storing query output.

    " + "documentation":"

    Configuration for where to deliver query results. Supports Amazon S3 destinations for storing query output and lookup table destinations for automatically refreshing lookup tables with query results. You can configure one or both destination types.

    " }, "scheduleStartTime":{ "shape":"Timestamp", @@ -3719,6 +3720,10 @@ "shape":"DescribeFieldIndexesLogGroupIdentifiers", "documentation":"

    An array containing the names or ARNs of the log groups that you want to retrieve field indexes for.

    " }, + "indexCategories":{ + "shape":"IndexCategories", + "documentation":"

    The index categories to return. The following values are supported:

    • DEFAULT: Fields that CloudWatch Logs indexes by default. Examples include @logStream and @data_format.

    • CUSTOM: Fields that you added manually to the field index policy. CloudWatch Logs always indexes these fields. These fields count toward the quota of 20 fields for each log group.

    • AUTO: Fields that CloudWatch Logs indexes automatically based on your query patterns and usage. These fields do not count toward the field index quota. CloudWatch Logs might update these fields based on changes in your query patterns. To keep a field indexed permanently, add it to an account-level or log-group level field index policy.

    • INACTIVE: Fields that CloudWatch Logs indexed before but does not index now. This happens if you remove a field from the field index policy or if CloudWatch Logs automatically selects a different field based on your queries.

    If you omit this parameter, the response includes the DEFAULT, CUSTOM, and INACTIVE categories.

    For more information about automatically indexed fields and using the AUTO category, see Automatically indexed fields.

    " + }, "nextToken":{"shape":"NextToken"} } }, @@ -4179,11 +4184,14 @@ }, "DestinationConfiguration":{ "type":"structure", - "required":["s3Configuration"], "members":{ "s3Configuration":{ "shape":"S3Configuration", "documentation":"

    Configuration for delivering query results to Amazon S3.

    " + }, + "lookupTableConfiguration":{ + "shape":"LookupTableConfiguration", + "documentation":"

    Configuration for delivering query results to a lookup table. The query results automatically populate or refresh the specified lookup table on each scheduled execution.

    " } }, "documentation":"

    Configuration for where to deliver scheduled query results. Specifies the destination type and associated settings for result delivery.

    " @@ -4544,6 +4552,10 @@ "type":{ "shape":"IndexType", "documentation":"

    The type of index. Specify FACET for facet-based indexing or FIELD_INDEX for field-based indexing. This determines how the field is indexed and can be queried.

    " + }, + "indexCategory":{ + "shape":"IndexCategory", + "documentation":"

    The category of the field index:

    • DEFAULT: Fields that CloudWatch Logs indexes by default. Examples include @logStream and @data_format.

    • CUSTOM: Fields that you added manually to the field index policy. CloudWatch Logs always indexes these fields. These fields count toward the quota of 20 fields for each log group.

    • AUTO: Fields that CloudWatch Logs indexes automatically based on your query patterns and usage. These fields do not count toward the field index quota. CloudWatch Logs might update these fields based on changes in your query patterns. To keep a field indexed permanently, add it to an account-level or log-group level field index policy.

    • INACTIVE: Fields that CloudWatch Logs indexed before but does not index now. This happens if you remove a field from the field index policy or if CloudWatch Logs automatically selects a different field based on your queries.

    For more information about automatically indexed fields, see Automatically indexed fields.

    " } }, "documentation":"

    This structure describes one log event field that is used as an index in at least one index policy in this account.

    " @@ -4602,7 +4614,7 @@ }, "startTime":{ "shape":"Timestamp", - "documentation":"

    The start of the time range, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC. Events with a timestamp before this time are not returned.

    " + "documentation":"

    The start of the time range, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC. Events with a timestamp before this time are not returned.

    Set startTime explicitly to reduce the chances of empty pages in the response.

    " }, "endTime":{ "shape":"Timestamp", @@ -4910,7 +4922,7 @@ }, "startTime":{ "shape":"Timestamp", - "documentation":"

    The start of the time range, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC. Events with a timestamp equal to this time or later than this time are included. Events with a timestamp earlier than this time are not included.

    " + "documentation":"

    The start of the time range, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC. Events with a timestamp equal to this time or later than this time are included. Events with a timestamp earlier than this time are not included.

    Set startTime explicitly to reduce the chances of empty pages in the response.

    " }, "endTime":{ "shape":"Timestamp", @@ -5324,7 +5336,7 @@ }, "lastUpdatedTime":{ "shape":"Timestamp", - "documentation":"

    The time when the storage tier policy was last updated, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC.

    " + "documentation":"

    The time when the storage tier policy was last updated, expressed as the number of milliseconds after January 1, 1970 00:00:00 UTC.

    " } } }, @@ -5520,6 +5532,20 @@ "member":{"shape":"ImportStatus"} }, "IncludeLinkedAccounts":{"type":"boolean"}, + "IndexCategories":{ + "type":"list", + "member":{"shape":"IndexCategory"}, + "max":4 + }, + "IndexCategory":{ + "type":"string", + "enum":[ + "DEFAULT", + "CUSTOM", + "AUTO", + "INACTIVE" + ] + }, "IndexPolicies":{ "type":"list", "member":{"shape":"IndexPolicy"} @@ -6548,6 +6574,36 @@ }, "documentation":"

    Contains metadata about a lookup table returned by DescribeLookupTables.

    " }, + "LookupTableConfiguration":{ + "type":"structure", + "required":[ + "tableName", + "roleArn" + ], + "members":{ + "tableName":{ + "shape":"LookupTableName", + "documentation":"

    The name of the lookup table to create or update with query results. The name can contain only alphanumeric characters and underscores.

    " + }, + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM role that grants permissions to create or update the lookup table with query results.

    " + }, + "description":{ + "shape":"LookupTableDescription", + "documentation":"

    A description of the lookup table.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The ARN of the KMS key to use to encrypt the lookup table data. If you don't specify a key, the data is encrypted with an Amazon Web Services-owned key.

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

    Key-value pairs to associate with the lookup table for resource management and cost allocation. The service applies tags only during initial table creation.

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

    Configuration for a lookup table destination. Use it to automatically refresh a lookup table with query results on a schedule.

    " + }, "LookupTableDescription":{ "type":"string", "max":1024, @@ -7567,7 +7623,7 @@ }, "logType":{ "shape":"LogType", - "documentation":"

    Defines the type of log that the source is sending.

    • For Amazon Bedrock Agents, the valid values are APPLICATION_LOGS and EVENT_LOGS.

    • For Amazon Bedrock Knowledge Bases, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Runtime, the valid values are APPLICATION_LOGS, USAGE_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Tools, the valid values are APPLICATION_LOGS, USAGE_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Identity, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Memory, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Gateway, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Payments, the valid values are APPLICATION_LOGS and TRACES.

    • For CloudFront, the valid value is ACCESS_LOGS.

    • For DevOps Agent, the valid value is APPLICATION_LOGS.

    • For Amazon CodeWhisperer, the valid value is EVENT_LOGS.

    • For Elemental MediaPackage, the valid values are EGRESS_ACCESS_LOGS and INGRESS_ACCESS_LOGS.

    • For Elemental MediaTailor, the valid values are AD_DECISION_SERVER_LOGS, MANIFEST_SERVICE_LOGS, and TRANSCODE_LOGS.

    • For Amazon EKS Auto Mode, the valid values are AUTO_MODE_BLOCK_STORAGE_LOGS, AUTO_MODE_COMPUTE_LOGS, AUTO_MODE_IPAM_LOGS, and AUTO_MODE_LOAD_BALANCING_LOGS.

    • For Amazon EKS Capability Logs, the valid values are EKS_CAPABILITY_ACK_LOGS, EKS_CAPABILITY_ARGOCD_APPLICATION_LOGS, EKS_CAPABILITY_ARGOCD_APPLICATIONSET_LOGS, EKS_CAPABILITY_ARGOCD_COMMITSERVER_LOGS, EKS_CAPABILITY_ARGOCD_REPOSERVER_LOGS, EKS_CAPABILITY_ARGOCD_SERVER_LOGS, and EKS_CAPABILITY_KRO_LOGS.

    • For Entity Resolution, the valid value is WORKFLOW_LOGS.

    • For IAM Identity Center, the valid value is ERROR_LOGS.

    • For Network Firewall Proxy, the valid values are ALERT_LOGS, ALLOW_LOGS, and DENY_LOGS.

    • For Network Load Balancer, the valid value is NLB_ACCESS_LOGS.

    • For PCS, the valid values are PCS_SCHEDULER_LOGS, PCS_JOBCOMP_LOGS, and PCS_SCHEDULER_AUDIT_LOGS.

    • For Quick, the valid values are AGENT_HOURS_LOGS, CHAT_LOGS, FEEDBACK_LOGS, and INDEX_USAGE_LOGS.

    • For Amazon Web Services RTB Fabric, the valid values is APPLICATION_LOGS.

    • For Amazon Q, the valid values are EVENT_LOGS and SYNC_JOB_LOGS.

    • For Amazon S3, the valid value is S3_SERVER_ACCESS_LOGS.

    • For Amazon Web Services Security Hub CSPM, the valid value is SECURITY_FINDING_LOGS.

    • For Amazon Web Services Security Hub, the valid value is SECURITY_FINDING_LOGS.

    • For Amazon SES mail manager, the valid values are APPLICATION_LOGS and TRAFFIC_POLICY_DEBUG_LOGS.

    • For Amazon WorkMail, the valid values are ACCESS_CONTROL_LOGS, AUTHENTICATION_LOGS, WORKMAIL_AVAILABILITY_PROVIDER_LOGS, WORKMAIL_MAILBOX_ACCESS_LOGS, and WORKMAIL_PERSONAL_ACCESS_TOKEN_LOGS.

    • For Amazon VPC Route Server, the valid value is EVENT_LOGS.

    " + "documentation":"

    Defines the type of log that the source is sending.

    • For Application Load Balancer, the valid values are ALB_ACCESS_LOGS, ALB_CONNECTION_LOGS, and ALB_HEALTH_CHECK_LOGS.

    • For Amazon Bedrock Agents, the valid values are APPLICATION_LOGS and EVENT_LOGS.

    • For Amazon Bedrock Knowledge Bases, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Runtime, the valid values are APPLICATION_LOGS, USAGE_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Tools, the valid values are APPLICATION_LOGS, USAGE_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Identity, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Memory, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Gateway, the valid values are APPLICATION_LOGS and TRACES.

    • For Amazon Bedrock AgentCore Payments, the valid values are APPLICATION_LOGS and TRACES.

    • For CloudFront, the valid value is ACCESS_LOGS.

    • For DevOps Agent, the valid value is APPLICATION_LOGS.

    • For Amazon CodeWhisperer, the valid value is EVENT_LOGS.

    • For Elemental MediaPackage, the valid values are EGRESS_ACCESS_LOGS and INGRESS_ACCESS_LOGS.

    • For Elemental MediaTailor, the valid values are AD_DECISION_SERVER_LOGS, MANIFEST_SERVICE_LOGS, and TRANSCODE_LOGS.

    • For Amazon EKS Auto Mode, the valid values are AUTO_MODE_BLOCK_STORAGE_LOGS, AUTO_MODE_COMPUTE_LOGS, AUTO_MODE_IPAM_LOGS, and AUTO_MODE_LOAD_BALANCING_LOGS.

    • For Amazon EKS Capability Logs, the valid values are EKS_CAPABILITY_ACK_LOGS, EKS_CAPABILITY_ARGOCD_APPLICATION_LOGS, EKS_CAPABILITY_ARGOCD_APPLICATIONSET_LOGS, EKS_CAPABILITY_ARGOCD_COMMITSERVER_LOGS, EKS_CAPABILITY_ARGOCD_REPOSERVER_LOGS, EKS_CAPABILITY_ARGOCD_SERVER_LOGS, and EKS_CAPABILITY_KRO_LOGS.

    • For Entity Resolution, the valid value is WORKFLOW_LOGS.

    • For IAM Identity Center, the valid value is ERROR_LOGS.

    • For Network Firewall Proxy, the valid values are ALERT_LOGS, ALLOW_LOGS, and DENY_LOGS.

    • For Network Load Balancer, the valid value is NLB_ACCESS_LOGS.

    • For PCS, the valid values are PCS_SCHEDULER_LOGS, PCS_JOBCOMP_LOGS, and PCS_SCHEDULER_AUDIT_LOGS.

    • For Quick, the valid values are AGENT_HOURS_LOGS, CHAT_LOGS, FEEDBACK_LOGS, and INDEX_USAGE_LOGS.

    • For Amazon Web Services RTB Fabric, the valid values is APPLICATION_LOGS.

    • For Amazon Q, the valid values are EVENT_LOGS and SYNC_JOB_LOGS.

    • For Amazon S3, the valid value is S3_SERVER_ACCESS_LOGS.

    • For Amazon Web Services Security Hub CSPM, the valid value is SECURITY_FINDING_LOGS.

    • For Amazon Web Services Security Hub, the valid value is SECURITY_FINDING_LOGS.

    • For Amazon SES mail manager, the valid values are APPLICATION_LOGS and TRAFFIC_POLICY_DEBUG_LOGS.

    • For Amazon WorkMail, the valid values are ACCESS_CONTROL_LOGS, AUTHENTICATION_LOGS, WORKMAIL_AVAILABILITY_PROVIDER_LOGS, WORKMAIL_MAILBOX_ACCESS_LOGS, and WORKMAIL_PERSONAL_ACCESS_TOKEN_LOGS.

    • For Amazon VPC Route Server, the valid value is EVENT_LOGS.

    " }, "tags":{ "shape":"Tags", @@ -7909,7 +7965,7 @@ "members":{ "storageTier":{ "shape":"StorageTier", - "documentation":"

    The storage tier to set for the account. Valid values are STANDARD and INTELLIGENT_TIERING.

    " + "documentation":"

    The storage tier to set for the account. Use INTELLIGENT_TIERING to automatically optimize storage costs by moving log data to the appropriate tier based on access frequency.

    " } } }, @@ -7918,11 +7974,11 @@ "members":{ "storageTier":{ "shape":"StorageTier", - "documentation":"

    The storage tier that was set.

    " + "documentation":"

    The storage tier for the account.

    " }, "lastUpdatedTime":{ "shape":"Timestamp", - "documentation":"

    The time when the storage tier policy was last updated, expressed as the number of milliseconds after Jan 1, 1970 00:00:00 UTC.

    " + "documentation":"

    The time when the storage tier policy was last updated, expressed as the number of milliseconds after January 1, 1970 00:00:00 UTC.

    " } } }, @@ -7969,7 +8025,7 @@ }, "emitSystemFields":{ "shape":"EmitSystemFields", - "documentation":"

    A list of system fields to include in the log events sent to the subscription destination. Valid values are @aws.account and @aws.region. These fields provide source information for centralized log data in the forwarded payload.

    " + "documentation":"

    A list of system fields to include in the log events sent to the subscription destination. Valid values are @aws.account, @aws.region, and @source.log. These fields provide source information for centralized log data in the forwarded payload.

    " } } }, @@ -8214,6 +8270,10 @@ "logGroupsScanned":{ "shape":"StatsValue", "documentation":"

    The number of log groups that were scanned by this query.

    " + }, + "resultCount":{ + "shape":"StatsValue", + "documentation":"

    The number of rows in the final query result set. This value represents the total number of output rows across all pages. For queries that include post-aggregation filters (such as stats count(*) by field | filter count > threshold), this value might be less than recordsMatched. It reflects only the rows that survived all operations in the query.

    " } }, "documentation":"

    Contains the number of log events scanned by the query, the number of log events that matched the query criteria, and the total number of bytes in the log events that were scanned.

    If the query involved log groups that have field index policies, the estimated number of skipped log events and the total bytes of those skipped log events are included. Using field indexes to skip log events in queries reduces scan volume and improves performance. For more information, see Create field indexes to improve query performance and reduce scan volume.

    " @@ -8616,7 +8676,10 @@ }, "ScheduledQueryDestinationType":{ "type":"string", - "enum":["S3"] + "enum":[ + "S3", + "LOOKUP_TABLE" + ] }, "ScheduledQueryIdentifier":{ "type":"string", @@ -9615,10 +9678,7 @@ }, "UpdateLookupTableRequest":{ "type":"structure", - "required":[ - "lookupTableArn", - "tableBody" - ], + "required":["lookupTableArn"], "members":{ "lookupTableArn":{ "shape":"Arn", @@ -9630,7 +9690,11 @@ }, "tableBody":{ "shape":"TableBody", - "documentation":"

    The new CSV content to replace the existing data. The first row must be a header row with column names. The content must use UTF-8 encoding and not exceed 10 MB.

    " + "documentation":"

    The new CSV content to replace the existing data. The first row must be a header row with column names. The content must use UTF-8 encoding and not exceed 10 MB.

    You must specify either tableBody or queryId, but not both.

    " + }, + "queryId":{ + "shape":"QueryId", + "documentation":"

    The ID of a completed or cancelled CloudWatch Logs query whose results replace the lookup table content. A cancelled query replaces the content with the partial results that were available when the query was stopped.

    You must specify either tableBody or queryId, but not both.

    " }, "kmsKeyId":{ "shape":"KmsKeyId", diff --git a/services/cloudwatchomni/pom.xml b/services/cloudwatchomni/pom.xml new file mode 100644 index 000000000000..1681bd4dd0ff --- /dev/null +++ b/services/cloudwatchomni/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + cloudwatchomni + AWS Java SDK :: Services :: Cloud Watch Omni + The AWS Java SDK for Cloud Watch Omni module holds the client classes that are used for + communicating with Cloud Watch Omni. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.cloudwatchomni + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + diff --git a/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3682165f3104 --- /dev/null +++ b/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudwatch-omni-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cloudwatch-omni.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-tests.json b/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..3c4709a04642 --- /dev/null +++ b/services/cloudwatchomni/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,105 @@ +{ + "testCases": [ + { + "documentation": "For custom endpoint with region not set and fips disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": false + } + }, + { + "documentation": "For custom endpoint with fips enabled", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni-fips.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": true + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": false + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni-fips.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://cloudwatch-omni.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false + } + }, + { + "documentation": "Missing region", + "expect": { + "error": "Invalid Configuration: Missing Region" + } + } + ], + "version": "1.0" +} \ No newline at end of file diff --git a/services/cloudwatchomni/src/main/resources/codegen-resources/paginators-1.json b/services/cloudwatchomni/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..d676489f1bfc --- /dev/null +++ b/services/cloudwatchomni/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,97 @@ +{ + "pagination": { + "GetContextGraph": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "nodes" + }, + "GetTelemetryQueryResults": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "rows", + "non_aggregate_keys": [ + "statistics", + "status" + ] + }, + "ListAccessGrants": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAccessProfiles": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAlerts": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListDomainAccessGrantsForOrganization": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListDomains": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListIntegrations": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListOmniDashboards": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListSpaces": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListSpacesForOrganization": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListTelemetryFields": { + "input_token": "nextToken", + "output_token": "nextToken", + "result_key": "fields" + }, + "ListTelemetryQuerySessions": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "sessions" + }, + "ListViews": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "SearchPrincipals": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "results" + } + } +} diff --git a/services/cloudwatchomni/src/main/resources/codegen-resources/service-2.json b/services/cloudwatchomni/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..ea35a53fa078 --- /dev/null +++ b/services/cloudwatchomni/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,6618 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2025-01-01", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"cloudwatch-omni", + "protocol":"smithy-rpc-v2-cbor", + "protocols":["smithy-rpc-v2-cbor"], + "serviceFullName":"CloudWatch Omni", + "serviceId":"CloudWatchOmni", + "signatureVersion":"v4", + "signingName":"cloudwatch", + "targetPrefix":"CloudWatchOmniFrontend", + "uid":"cloudwatchomni-2025-01-01" + }, + "operations":{ + "CreateAccessGrant":{ + "name":"CreateAccessGrant", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateAccessGrantInput"}, + "output":{"shape":"CreateAccessGrantOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates an AccessGrant that authorizes a principal to perform a set of actions on resources in a space.

    Optionally narrow the grant with scoped actions that limit it to specific resources and fields. Use ListAccessGrants and GetAccessGrant to retrieve grants, and DeleteAccessGrant to remove them.

    " + }, + "CreateAccessProfile":{ + "name":"CreateAccessProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateAccessProfileInput"}, + "output":{"shape":"CreateAccessProfileOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates an access profile in a space.

    Use GetAccessProfile and ListAccessProfiles to retrieve profiles, and UpdateAccessProfile to modify one.

    " + }, + "CreateAlert":{ + "name":"CreateAlert", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateAlertInput"}, + "output":{"shape":"CreateAlertOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates a new alert within a space.

    Use GetAlert and ListAlerts to retrieve alerts, UpdateAlert to modify one, and DeleteAlert to remove it.

    " + }, + "CreateDomain":{ + "name":"CreateDomain", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateDomainInput"}, + "output":{"shape":"CreateDomainOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates a domain with identity provider configuration.

    Use GetDomain to retrieve the domain, UpdateDomain to change its configuration, and CreateSpace to add spaces within it.

    " + }, + "CreateDomainAccessGrantForOrganization":{ + "name":"CreateDomainAccessGrantForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateDomainAccessGrantForOrganizationInput"}, + "output":{"shape":"CreateDomainAccessGrantForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates an AccessGrant that authorizes a principal to administer an organization domain.

    " + }, + "CreateDomainForOrganization":{ + "name":"CreateDomainForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateDomainForOrganizationInput"}, + "output":{"shape":"CreateDomainForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates an organization-scoped domain for the caller's AWS Organization. Only the organization's management account can call this operation.

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

    Creates an integration with a third-party provider. Returns the integration identifier and its initial status; when the provider requires interactive consent, an authorization URL is returned for the user to complete setup.

    " + }, + "CreateOmniDashboard":{ + "name":"CreateOmniDashboard", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateOmniDashboardInput"}, + "output":{"shape":"CreateOmniDashboardOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates a new dashboard within a space.

    Use GetOmniDashboard and ListOmniDashboards to retrieve dashboards, UpdateOmniDashboard to modify one, and DeleteOmniDashboard to remove it.

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

    Generates a one-time code for deep-link authentication.

    Direct the user's browser to the returned deepLinkUrl before it expires. The code is exchanged for an authenticated, domain-scoped session and can be used only once.

    " + }, + "CreateSpace":{ + "name":"CreateSpace", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateSpaceInput"}, + "output":{"shape":"CreateSpaceOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates a space in a domain.

    Use GetSpace to retrieve the space, ListSpaces to enumerate spaces, UpdateSpace to modify it, and DeleteSpace to remove it.

    " + }, + "CreateView":{ + "name":"CreateView", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateViewRequest"}, + "output":{"shape":"CreateViewResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates a new SQL view.

    A view is a named, reusable SQL query that can be referenced from telemetry queries. View names must be unique within the account and region. Only USER views can be created — MANAGED views are provisioned by AWS.

    " + }, + "DeleteAccessGrant":{ + "name":"DeleteAccessGrant", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteAccessGrantInput"}, + "output":{"shape":"DeleteAccessGrantOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Removes an existing AccessGrant, revoking the access it granted.

    A service-managed grant cannot be deleted.

    ", + "idempotent":true + }, + "DeleteAccessProfile":{ + "name":"DeleteAccessProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteAccessProfileInput"}, + "output":{"shape":"DeleteAccessProfileOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Removes an access profile.

    An access profile cannot be deleted while access grants reference it.

    ", + "idempotent":true + }, + "DeleteAlert":{ + "name":"DeleteAlert", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteAlertInput"}, + "output":{"shape":"DeleteAlertOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes an alert by its identifier.

    Idempotent: deleting an alert that has already been removed succeeds without error.

    ", + "idempotent":true + }, + "DeleteDomain":{ + "name":"DeleteDomain", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteDomainInput"}, + "output":{"shape":"DeleteDomainOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Removes a domain and all of its resources. Call this operation in the Region where the domain was created.

    A domain cannot be deleted while it contains spaces.

    ", + "idempotent":true + }, + "DeleteDomainAccessGrantForOrganization":{ + "name":"DeleteDomainAccessGrantForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteDomainAccessGrantForOrganizationInput"}, + "output":{"shape":"DeleteDomainAccessGrantForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Removes an existing organization access grant, revoking the access it granted.

    A service-managed grant cannot be deleted.

    ", + "idempotent":true + }, + "DeleteDomainForOrganization":{ + "name":"DeleteDomainForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteDomainForOrganizationInput"}, + "output":{"shape":"DeleteDomainForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Removes an organization domain and all of its resources. Call this operation in the Region where the domain was created.

    A domain cannot be deleted while it contains spaces.

    ", + "idempotent":true + }, + "DeleteIntegration":{ + "name":"DeleteIntegration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteIntegrationInput"}, + "output":{"shape":"DeleteIntegrationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes an integration. Returns the resulting status.

    ", + "idempotent":true + }, + "DeleteOmniDashboard":{ + "name":"DeleteOmniDashboard", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteOmniDashboardInput"}, + "output":{"shape":"DeleteOmniDashboardOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Removes a dashboard from a space.

    ", + "idempotent":true + }, + "DeleteSpace":{ + "name":"DeleteSpace", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteSpaceInput"}, + "output":{"shape":"DeleteSpaceOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Removes a space and all of its resources.

    ", + "idempotent":true + }, + "DeleteView":{ + "name":"DeleteView", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteViewRequest"}, + "output":{"shape":"DeleteViewResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes the specified view.

    Queries that reference the view fail after it is deleted. Managed views cannot be deleted.

    ", + "idempotent":true + }, + "GetAccessGrant":{ + "name":"GetAccessGrant", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAccessGrantInput"}, + "output":{"shape":"GetAccessGrantOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the full detail of a single AccessGrant by ID.

    ", + "readonly":true + }, + "GetAccessProfile":{ + "name":"GetAccessProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAccessProfileInput"}, + "output":{"shape":"GetAccessProfileOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves an access profile by ID.

    The response indicates whether the calling principal is currently allowed to assume the profile.

    ", + "readonly":true + }, + "GetAlert":{ + "name":"GetAlert", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAlertInput"}, + "output":{"shape":"GetAlertOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves a single alert by its identifier.

    Use ListAlerts to enumerate alerts in the space.

    ", + "readonly":true + }, + "GetContextGraph":{ + "name":"GetContextGraph", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetContextGraphInput"}, + "output":{"shape":"GetContextGraphOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Queries the context graph with filtering, traversal, and pagination support.

    Pagination note: nodes and edges are returned together as a coherent subgraph. Pagination cursors advance over nodes (the primary collection); each page includes all edges connecting nodes within that page. Callers should treat nodes as the paginated collection and edges as supplementary relationship data attached to those nodes.

    ", + "readonly":true + }, + "GetDomain":{ + "name":"GetDomain", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetDomainInput"}, + "output":{"shape":"GetDomainOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the details of a domain by ID.

    ", + "readonly":true + }, + "GetDomainAccessGrantForOrganization":{ + "name":"GetDomainAccessGrantForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetDomainAccessGrantForOrganizationInput"}, + "output":{"shape":"GetDomainAccessGrantForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the full detail of a single organization access grant by ID.

    ", + "readonly":true + }, + "GetDomainForOrganization":{ + "name":"GetDomainForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetDomainForOrganizationInput"}, + "output":{"shape":"GetDomainForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the details of an organization domain by ID.

    ", + "readonly":true + }, + "GetIntegration":{ + "name":"GetIntegration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIntegrationInput"}, + "output":{"shape":"GetIntegrationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the details of a single integration, identified by its identifier, Amazon Resource Name, or name.

    ", + "readonly":true + }, + "GetIntelligenceConfiguration":{ + "name":"GetIntelligenceConfiguration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIntelligenceConfigurationInput"}, + "output":{"shape":"GetIntelligenceConfigurationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the intelligence configuration for the calling account. Account is identified via FAS (caller identity). Returns the default configuration if none exists yet.

    ", + "readonly":true + }, + "GetOmniDashboard":{ + "name":"GetOmniDashboard", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetOmniDashboardInput"}, + "output":{"shape":"GetOmniDashboardOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves a dashboard by ID within a space.

    ", + "readonly":true + }, + "GetSpace":{ + "name":"GetSpace", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetSpaceInput"}, + "output":{"shape":"GetSpaceOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the details of a space by ID.

    ", + "readonly":true + }, + "GetSpaceCredentialsForOrganization":{ + "name":"GetSpaceCredentialsForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetSpaceCredentialsForOrganizationInput"}, + "output":{"shape":"GetSpaceCredentialsForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns temporary credentials for a space in an organization member account. The credentials are valid for one hour.

    The caller must be the organization's management account or a delegated administrator with access to the target space. The target account must be an active member of the same organization as the domain, and the space must already exist.

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

    Returns the results for the specified query.

    " + }, + "GetView":{ + "name":"GetView", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetViewRequest"}, + "output":{"shape":"GetViewResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the definition and metadata of the specified view.

    ", + "readonly":true + }, + "ListAccessGrants":{ + "name":"ListAccessGrants", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListAccessGrantsInput"}, + "output":{"shape":"ListAccessGrantsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns AccessGrants, with optional filtering by domain, space, principal, or permission. A grant is returned only when it matches every filter supplied. With no filters, returns the grants for the current account and Region.

    ", + "readonly":true + }, + "ListAccessProfiles":{ + "name":"ListAccessProfiles", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListAccessProfilesInput"}, + "output":{"shape":"ListAccessProfilesOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the access profiles in a space.

    ", + "readonly":true + }, + "ListAlerts":{ + "name":"ListAlerts", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListAlertsInput"}, + "output":{"shape":"ListAlertsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists alerts within a space, optionally filtered by exact name(s), a single name prefix, or exact alertId(s), with pagination.

    Use GetAlert to retrieve a single alert's full detail.

    ", + "readonly":true + }, + "ListDomainAccessGrantsForOrganization":{ + "name":"ListDomainAccessGrantsForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDomainAccessGrantsForOrganizationInput"}, + "output":{"shape":"ListDomainAccessGrantsForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns organization-level domain access grants, with optional filtering by domain, principal, or permission. A grant is returned only when it matches every filter supplied. With no filters, returns the grants for the caller's organization.

    ", + "readonly":true + }, + "ListDomains":{ + "name":"ListDomains", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDomainsInput"}, + "output":{"shape":"ListDomainsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the caller's domains: the account-scoped domain and the organization-scoped domain, if either exists. At most two domains are returned.

    ", + "readonly":true + }, + "ListIntegrations":{ + "name":"ListIntegrations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListIntegrationsInput"}, + "output":{"shape":"ListIntegrationsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the integrations in the account, optionally filtered by type, status, or name. Results are paginated.

    ", + "readonly":true + }, + "ListOmniDashboards":{ + "name":"ListOmniDashboards", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListOmniDashboardsInput"}, + "output":{"shape":"ListOmniDashboardsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the dashboards in a space, optionally filtered by name prefix.

    ", + "readonly":true + }, + "ListSpaces":{ + "name":"ListSpaces", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListSpacesInput"}, + "output":{"shape":"ListSpacesOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the spaces in the account, optionally filtered by domain.

    ", + "readonly":true + }, + "ListSpacesForOrganization":{ + "name":"ListSpacesForOrganization", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListSpacesForOrganizationInput"}, + "output":{"shape":"ListSpacesForOrganizationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the spaces across all member accounts in the organization.

    ", + "readonly":true + }, + "ListTelemetryFields":{ + "name":"ListTelemetryFields", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListTelemetryFieldsRequest"}, + "output":{"shape":"ListTelemetryFieldsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists fields available for telemetry queries.

    Returns a list of fields included in the specified dataset, granular to telemetry type. Returned field names reflect the exact stored casing and are case-sensitive when referenced in query expressions; the query engine does not normalize identifier case.

    " + }, + "ListTelemetryQuerySessions":{ + "name":"ListTelemetryQuerySessions", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListTelemetryQuerySessionsRequest"}, + "output":{"shape":"ListTelemetryQuerySessionsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists telemetry query sessions.

    Returns a list of telemetry query sessions owned by the caller.

    " + }, + "ListViews":{ + "name":"ListViews", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListViewsRequest"}, + "output":{"shape":"ListViewsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the views in the caller's account and region.

    Returns a summary for each view, optionally filtered by view type. View definitions are not included — use GetView to retrieve them.

    ", + "readonly":true + }, + "PutIntelligenceConfiguration":{ + "name":"PutIntelligenceConfiguration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"PutIntelligenceConfigurationInput"}, + "output":{"shape":"PutIntelligenceConfigurationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates or updates the intelligence configuration for the calling account. Account is identified via FAS (caller identity).

    ", + "idempotent":true + }, + "SearchPrincipals":{ + "name":"SearchPrincipals", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"SearchPrincipalsInput"}, + "output":{"shape":"SearchPrincipalsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Searches Identity Center for users and groups in a domain. The domain must be configured with Identity Center.

    To grant access to a result, pass its principalId to CreateAccessGrant with a principalType of IDC_USER for a user or IDC_GROUP for a group.

    ", + "readonly":true + }, + "StartTelemetryQuery":{ + "name":"StartTelemetryQuery", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"StartTelemetryQueryRequest"}, + "output":{"shape":"StartTelemetryQueryResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Starts a telemetry query within a session.

    Submits the provided query string for execution in the specified session. Use GetTelemetryQueryResults to poll for results and check query status.

    " + }, + "StartTelemetryQuerySession":{ + "name":"StartTelemetryQuerySession", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"StartTelemetryQuerySessionRequest"}, + "output":{"shape":"StartTelemetryQuerySessionResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Starts a new telemetry query session.

    A session provides a logical grouping for one or more telemetry queries. The returned session ID is required when starting queries via StartTelemetryQuery.

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

    Stops a running telemetry query.

    ", + "idempotent":true + }, + "StopTelemetryQuerySession":{ + "name":"StopTelemetryQuerySession", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"StopTelemetryQuerySessionRequest"}, + "output":{"shape":"StopTelemetryQuerySessionResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Stops a telemetry query session.

    Terminates the specified session. After a session is stopped it cannot be reused.

    ", + "idempotent":true + }, + "UpdateAccessProfile":{ + "name":"UpdateAccessProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateAccessProfileInput"}, + "output":{"shape":"UpdateAccessProfileOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Updates the name or description of an access profile.

    Only the provided fields are changed; omitted fields are left unchanged.

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

    Updates an existing alert.

    Only non-null fields overwrite existing values.

    ", + "idempotent":true + }, + "UpdateDomain":{ + "name":"UpdateDomain", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateDomainInput"}, + "output":{"shape":"UpdateDomainOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Updates a domain's name or identity provider configuration.

    Only the provided fields are changed; omitted fields are left unchanged. Renaming a domain also changes the endpoint URLs derived from its name.

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

    Updates an organization domain's name or identity provider configuration. Call this operation in the Region where the domain was created.

    Only the provided fields are changed; omitted fields are left unchanged. Renaming a domain also changes the endpoint URLs derived from its name.

    ", + "idempotent":true + }, + "UpdateIntegration":{ + "name":"UpdateIntegration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateIntegrationInput"}, + "output":{"shape":"UpdateIntegrationOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Updates an existing integration, identified by its id, ARN, or name. Only the fields you provide are changed.

    ", + "idempotent":true + }, + "UpdateOmniDashboard":{ + "name":"UpdateOmniDashboard", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateOmniDashboardInput"}, + "output":{"shape":"UpdateOmniDashboardOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Updates an existing dashboard within a space.

    Only the provided fields are changed; omitted fields are left unchanged.

    ", + "idempotent":true + }, + "UpdateSpace":{ + "name":"UpdateSpace", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateSpaceInput"}, + "output":{"shape":"UpdateSpaceOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Updates a space.

    Only the provided fields are changed; omitted fields are left unchanged.

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

    Updates an existing view's definition and/or description.

    Only the fields you provide are changed. Managed views cannot be updated.

    ", + "idempotent":true + } + }, + "shapes":{ + "AccessDeniedException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The caller is not authorized to perform this action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "AccessGrant":{ + "type":"structure", + "required":[ + "grantId", + "grantArn", + "accountId", + "domainId", + "principal", + "permission", + "grantType", + "createdBy", + "createdAt", + "updatedAt", + "spaceId" + ], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The unique ID of the access grant.

    " + }, + "grantArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the access grant.

    " + }, + "name":{ + "shape":"AccessGrantNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID that owns the grant.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain the grant belongs to.

    " + }, + "principal":{ + "shape":"AccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"AccessGrantPermission", + "documentation":"

    The permission granted.

    " + }, + "grantType":{ + "shape":"AccessGrantType", + "documentation":"

    Who manages the grant.

    " + }, + "createdBy":{ + "shape":"String", + "documentation":"

    The principal that created the grant.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the grant was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the grant was last updated.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The space this grant applies to. Domain-scoped grants are returned by ListDomainAccessGrantsForOrganization instead.

    " + }, + "scopedActions":{ + "shape":"ScopedActionsList", + "documentation":"

    Groups of actions allowed by the grant, each with the resource scopes and conditions that limit those actions.

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

    Full AccessGrant structure returned by API operations.

    " + }, + "AccessGrantNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "AccessGrantPermission":{ + "type":"string", + "documentation":"

    Permission levels for AccessGrants. SPACE_ADMIN can manage grants within a space but cannot create spaces.

    ", + "enum":[ + "SPACE_ADMIN", + "READ", + "READ_WRITE_DELETE", + "CUSTOM" + ] + }, + "AccessGrantPrincipal":{ + "type":"structure", + "required":["principalType"], + "members":{ + "principalType":{ + "shape":"AccessGrantPrincipalType", + "documentation":"

    The type of principal receiving the grant.

    " + }, + "principalId":{ + "shape":"PrincipalId", + "documentation":"

    The ID of the principal receiving the grant.

    " + }, + "principalAttributes":{ + "shape":"AccessGrantPrincipalAttributeList", + "documentation":"

    Attribute conditions for attribute-based access. When provided, the grant targets any principal matching all specified conditions. Supported only for IDC_USER principals.

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

    The principal receiving the grant. Specify principalId, principalAttributes, or both.

    " + }, + "AccessGrantPrincipalAttribute":{ + "type":"structure", + "required":[ + "key", + "value" + ], + "members":{ + "key":{ + "shape":"AccessGrantPrincipalAttributeKeyString", + "documentation":"

    The Identity Center user attribute to match on. One of userName, active, userStatus, displayName, email, name.givenName, name.familyName, enterprise.department, enterprise.division, enterprise.organization, enterprise.costCenter, or enterprise.employeeNumber. Each key may appear only once per grant.

    " + }, + "value":{ + "shape":"AccessGrantPrincipalAttributeValueString", + "documentation":"

    The attribute value.

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

    A single attribute condition used to match principals for attribute-based access.

    " + }, + "AccessGrantPrincipalAttributeKeyString":{ + "type":"string", + "max":128, + "min":1 + }, + "AccessGrantPrincipalAttributeList":{ + "type":"list", + "member":{"shape":"AccessGrantPrincipalAttribute"}, + "documentation":"

    List of principal attribute conditions.

    ", + "max":10, + "min":0 + }, + "AccessGrantPrincipalAttributeValueString":{ + "type":"string", + "max":512, + "min":1 + }, + "AccessGrantPrincipalType":{ + "type":"string", + "documentation":"

    Type of principal receiving the grant.

    ", + "enum":[ + "IDC_USER", + "IDC_GROUP", + "IAM_USER", + "IAM_ROLE", + "IAM_ROOT", + "ACCESS_PROFILE", + "ALERT", + "AGENT" + ] + }, + "AccessGrantSummary":{ + "type":"structure", + "required":[ + "grantId", + "grantArn", + "domainId", + "principal", + "permission", + "grantType", + "spaceId" + ], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The unique ID of the access grant.

    " + }, + "grantArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the access grant.

    " + }, + "name":{ + "shape":"AccessGrantSummaryNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain the grant belongs to.

    " + }, + "principal":{ + "shape":"AccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"AccessGrantPermission", + "documentation":"

    The permission granted.

    " + }, + "grantType":{ + "shape":"AccessGrantType", + "documentation":"

    Who manages the grant.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The space this grant applies to. Domain-scoped grants are returned by ListDomainAccessGrantsForOrganization instead.

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

    Summary of an AccessGrant. Call GetAccessGrant for the full grant.

    " + }, + "AccessGrantSummaryList":{ + "type":"list", + "member":{"shape":"AccessGrantSummary"}, + "documentation":"

    List of AccessGrant summaries.

    " + }, + "AccessGrantSummaryNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "AccessGrantType":{ + "type":"string", + "documentation":"

    Who manages an access grant.

    ", + "enum":[ + "SERVICE_MANAGED", + "CUSTOMER_MANAGED" + ] + }, + "AccessKeyId":{ + "type":"string", + "documentation":"

    An AWS access key ID.

    ", + "sensitive":true + }, + "AccessProfile":{ + "type":"structure", + "required":[ + "profileId", + "spaceId", + "arn", + "name", + "createdAt", + "updatedAt" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique ID of the access profile.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The ID of the space the profile belongs to.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The ARN of this access profile.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the access profile.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the access profile.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the access profile was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the access profile was last updated.

    " + }, + "assumeStatus":{ + "shape":"AssumeStatus", + "documentation":"

    The calling principal's authorization to assume this access profile.

    " + }, + "profileType":{ + "shape":"AccessProfileType", + "documentation":"

    Who manages the access profile.

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

    An Access Profile.

    " + }, + "AccessProfileName":{ + "type":"string", + "documentation":"

    A name that identifies an access profile. Must be 1-256 characters: letters, numbers, spaces, and the characters _ . : / = + @ -

    ", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9 _.:/=+@-]+" + }, + "AccessProfileSummary":{ + "type":"structure", + "required":[ + "profileId", + "arn", + "name" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique ID of the access profile.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The ARN of this access profile.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the access profile.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the access profile.

    " + }, + "profileType":{ + "shape":"AccessProfileType", + "documentation":"

    Who manages the access profile.

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

    Summary of an access profile. Call GetAccessProfile for the full profile.

    " + }, + "AccessProfileSummaryList":{ + "type":"list", + "member":{"shape":"AccessProfileSummary"}, + "documentation":"

    List of Access Profile summaries.

    " + }, + "AccessProfileType":{ + "type":"string", + "documentation":"

    Who manages an access profile.

    ", + "enum":[ + "SERVICE_MANAGED", + "CUSTOMER_MANAGED" + ] + }, + "AccountId":{ + "type":"string", + "documentation":"

    12-digit AWS account id.

    ", + "max":12, + "min":12, + "pattern":"[0-9]{12}" + }, + "Alert":{ + "type":"structure", + "required":[ + "name", + "accountId", + "rule", + "createdAt", + "updatedAt", + "alertArn" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the alert.

    " + }, + "alertId":{ + "shape":"AlertId", + "documentation":"

    The stable alert identifier (see {@link AlertId}), minted on create and immutable across updates. Use it (not {@code name}) to address the alert on GetAlert/UpdateAlert/DeleteAlert; it is also the ARN's resource id.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the alert.

    " + }, + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID that owns the alert.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The ID of the space the alert belongs to.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The ID of the access profile associated with the alert.

    " + }, + "rule":{ + "shape":"Rule", + "documentation":"

    The rule that defines how the alert is evaluated.

    " + }, + "notificationStatus":{ + "shape":"NotificationStatus", + "documentation":"

    Whether notifications are enabled.

    " + }, + "state":{ + "shape":"AlertStateInfo", + "documentation":"

    Live evaluation state (read-only, system-managed). Populated by GetAlert. ListAlerts reports state on AlertSummary instead, where it stays required.

    Absent on CreateAlert: a newly created alert has never been evaluated, so any state reported there would be a default rather than an observation. Call GetAlert for live state. Not @required for that reason — GetAlert always populates it.

    contributorSummary is nested inside this member, so it too is absent on CreateAlert.

    " + }, + "notificationRules":{ + "shape":"NotificationRuleList", + "documentation":"

    The notification rules for the alert.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the alert was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the alert was last updated.

    " + }, + "alertArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the alert.

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

    Full alert entity, returned by both CreateAlert and GetAlert. A create and a read of the same alert describe it identically except for {@code state}, which only the read paths populate. UpdateAlert returns an empty response.

    " + }, + "AlertCondition":{ + "type":"structure", + "members":{ + "thresholdMode":{ + "shape":"ThresholdMode", + "documentation":"

    How the threshold is applied to query results.

    " + }, + "thresholdField":{ + "shape":"AlertConditionThresholdFieldString", + "documentation":"

    The field the threshold is evaluated against.

    " + }, + "comparator":{ + "shape":"Comparator", + "documentation":"

    The comparison operator applied to the threshold.

    " + }, + "warningThreshold":{ + "shape":"Double", + "documentation":"

    The value at which the alert enters the WARNING state.

    " + }, + "criticalThreshold":{ + "shape":"Double", + "documentation":"

    The value at which the alert enters the CRITICAL state.

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

    The condition that determines when the alert fires.

    On UpdateAlert a supplied condition is replaced whole, not merged: an omitted {@code warningThreshold} or {@code criticalThreshold} removes that tier, and an omitted {@code thresholdField} clears it. A condition must keep at least one tier. {@code thresholdMode} and {@code comparator} are optional at the Smithy level (so a single-tier condition is expressible) but are required whenever a threshold is present; enforced by the service-side validator.

    " + }, + "AlertConditionThresholdFieldString":{ + "type":"string", + "max":256, + "min":0 + }, + "AlertEvaluation":{ + "type":"structure", + "required":["intervalSeconds"], + "members":{ + "intervalSeconds":{ + "shape":"Integer", + "documentation":"

    The interval between evaluations, in seconds.

    " + }, + "pendingDurationSeconds":{ + "shape":"Integer", + "documentation":"

    The duration a breach must persist before the alert fires, in seconds.

    " + }, + "recoveryDurationSeconds":{ + "shape":"Integer", + "documentation":"

    The duration a recovery must persist before the alert clears, in seconds.

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

    Evaluation cadence. {@code intervalSeconds} must be one of {30, 60, 120, 300, 600, 900, 1800, 3600}; {@code pendingDurationSeconds} and {@code recoveryDurationSeconds} must be multiples of {@code intervalSeconds}. A duration of 0 means fire/clear immediately with no delay.

    On UpdateAlert a supplied evaluation block is replaced whole, not merged: an omitted {@code pendingDurationSeconds} or {@code recoveryDurationSeconds} is cleared to unset (no such duration), not preserved and not defaulted to 0. {@code intervalSeconds} is required whenever the block is present. All enforced server-side / by the front-door validator.

    " + }, + "AlertFilterCriteria":{ + "type":"structure", + "members":{ + "names":{ + "shape":"AlertNameFilterList", + "documentation":"

    Filter to alerts whose name exactly matches any entry (OR semantics). Mutually exclusive with {@code namePrefix} and {@code ids}.

    " + }, + "namePrefix":{ + "shape":"AlertFilterCriteriaNamePrefixString", + "documentation":"

    Filter to alerts whose name starts with this prefix. Mutually exclusive with {@code names} and {@code ids}.

    " + }, + "ids":{ + "shape":"AlertIdFilterList", + "documentation":"

    Filter to alerts whose {@link AlertId} exactly matches any entry (OR semantics). Mutually exclusive with {@code names} and {@code namePrefix}.

    " + }, + "stateValue":{ + "shape":"AlertStateList", + "documentation":"

    Filter to alerts currently in any of these states (OR semantics).

    " + }, + "notificationsEnabled":{ + "shape":"Boolean", + "documentation":"

    Filter to alerts by whether notifications are enabled.

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

    Filter criteria for ListAlerts. All members are optional; each omitted member is unconstrained. At most one of {@code names}, {@code namePrefix}, {@code ids} may be provided (mutually exclusive; the service rejects more than one). The remaining members combine with AND.

    " + }, + "AlertFilterCriteriaNamePrefixString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "AlertId":{ + "type":"string", + "documentation":"

    The stable alert identifier: a 32-character lowercase hex uuid, minted by the backend on create and immutable across updates.

    It deliberately carries no name, so that a future rename cannot change an alert's identity and break the ARNs, saved links and IAM policies pointing at it. Use {@code name} to display an alert and {@code alertId} to address one.

    ", + "max":32, + "min":32, + "pattern":"[0-9a-f]{32}" + }, + "AlertIdFilterList":{ + "type":"list", + "member":{"shape":"AlertId"}, + "documentation":"

    Exact alertId match list. Members reuse the {@link AlertId} type so the charset/cap stay in sync with it.

    ", + "max":50, + "min":1 + }, + "AlertNameFilterList":{ + "type":"list", + "member":{"shape":"AlertNameFilterListMemberString"}, + "documentation":"

    List of exact alert names to filter by.

    ", + "max":50, + "min":1 + }, + "AlertNameFilterListMemberString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "AlertRuleQuery":{ + "type":"structure", + "required":[ + "language", + "expression" + ], + "members":{ + "language":{ + "shape":"QueryLanguage", + "documentation":"

    The query language of the expression.

    " + }, + "expression":{ + "shape":"AlertRuleQueryExpressionString", + "documentation":"

    The query expression to evaluate.

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

    Query expression and the language it's written in.

    " + }, + "AlertRuleQueryExpressionString":{ + "type":"string", + "max":10000, + "min":1 + }, + "AlertSortField":{ + "type":"string", + "documentation":"

    Field by which alerts can be sorted.

    ", + "enum":[ + "NAME", + "STATE" + ] + }, + "AlertSortOrder":{ + "type":"string", + "documentation":"

    Sort order for list results.

    ", + "enum":[ + "ASC", + "DESC" + ] + }, + "AlertState":{ + "type":"string", + "documentation":"

    Flat alert state. Severity is folded in: a WARNING/CRITICAL alert reports that state directly. {@code NODATA} indicates the evaluation produced no data (subject to the rule's noData.treatAs handling).

    ", + "enum":[ + "OK", + "WARNING", + "CRITICAL", + "NODATA" + ] + }, + "AlertStateData":{ + "type":"structure", + "members":{ + "thresholdBreached":{ + "shape":"Double", + "documentation":"

    For COUNT_OF_RESULTS alerts, the row count that breached; null for FIELD_VALUE (multi-contributor) alerts.

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

    Structured detail about the current evaluation.

    " + }, + "AlertStateInfo":{ + "type":"structure", + "required":["value"], + "members":{ + "value":{ + "shape":"AlertState", + "documentation":"

    Current flat state.

    " + }, + "transitionedAt":{ + "shape":"Timestamp", + "documentation":"

    When the alert transitioned to its current state.

    " + }, + "contributorSummary":{ + "shape":"ContributorSummary", + "documentation":"

    Counts of contributors currently breaching each severity threshold. Present only when contributor-level tracking is active; absent until the first contributor breaches a {@code WARNING} or {@code CRITICAL} threshold.

    " + }, + "data":{ + "shape":"AlertStateData", + "documentation":"

    Structured detail about why the alert is in its current state.

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

    Live evaluation state for an alert. Read-only, system-managed.

    " + }, + "AlertStateList":{ + "type":"list", + "member":{"shape":"AlertState"}, + "documentation":"

    List of alert states.

    ", + "max":4, + "min":0 + }, + "AlertSummary":{ + "type":"structure", + "required":[ + "name", + "state", + "createdAt", + "updatedAt", + "alertArn" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the alert.

    " + }, + "alertId":{ + "shape":"AlertId", + "documentation":"

    The stable alert identifier (see {@link Alert#alertId}). Use it to address the alert; it is also the ARN's resource id.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The ID of the space the alert belongs to.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The ID of the access profile associated with the alert.

    " + }, + "notificationStatus":{ + "shape":"NotificationStatus", + "documentation":"

    Whether notifications are enabled.

    " + }, + "state":{ + "shape":"AlertStateInfo", + "documentation":"

    Live evaluation state (read-only, system-managed).

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the alert was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the alert was last updated.

    " + }, + "alertArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the alert.

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

    Summary representation of an alert used in list responses.

    " + }, + "AlertSummaryList":{ + "type":"list", + "member":{"shape":"AlertSummary"}, + "documentation":"

    List of alert summaries.

    " + }, + "ApiKeyCredential":{ + "type":"structure", + "required":["apiKeyValue"], + "members":{ + "apiKeyValue":{ + "shape":"ApiKeyCredentialApiKeyValueString", + "documentation":"

    The API key value used to authenticate with the external system.

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

    An API key used to authenticate an integration with its external system.

    ", + "sensitive":true + }, + "ApiKeyCredentialApiKeyValueString":{ + "type":"string", + "min":1, + "sensitive":true + }, + "Arn":{ + "type":"string", + "documentation":"

    An Amazon Resource Name (ARN).

    ", + "max":2048, + "min":1, + "pattern":"arn:.+" + }, + "AssumeStatus":{ + "type":"string", + "documentation":"

    The calling principal's authorization to assume an access profile.

    ", + "enum":[ + "ALLOWED", + "DENIED" + ] + }, + "AuthType":{ + "type":"string", + "documentation":"

    The authentication method that an integration uses to connect to its external system.

    ", + "enum":[ + "NONE", + "OAUTH2", + "API_KEY" + ] + }, + "AwsCredentials":{ + "type":"structure", + "required":[ + "accessKeyId", + "secretAccessKey", + "sessionToken", + "expiration" + ], + "members":{ + "accessKeyId":{ + "shape":"AccessKeyId", + "documentation":"

    The AWS access key ID.

    " + }, + "secretAccessKey":{ + "shape":"SecretAccessKey", + "documentation":"

    The AWS secret access key.

    " + }, + "sessionToken":{ + "shape":"SessionToken", + "documentation":"

    The AWS session token.

    " + }, + "expiration":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the credentials expire.

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

    A set of temporary AWS credentials.

    ", + "sensitive":true + }, + "Boolean":{ + "type":"boolean", + "box":true + }, + "ClientToken":{ + "type":"string", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "max":64, + "min":1, + "pattern":"[!-~]+" + }, + "Comparator":{ + "type":"string", + "documentation":"

    Comparison operator for a threshold.

    ", + "enum":[ + "GT", + "LT", + "GTE", + "LTE" + ] + }, + "ConflictException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{ + "shape":"String", + "documentation":"

    A human-readable description of the conflict.

    " + }, + "conflictType":{ + "shape":"String", + "documentation":"

    The type of conflict that caused the request to fail. Not always present.

    " + }, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource that is in conflict. Not always present.

    " + }, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource that is in conflict. Not always present.

    " + }, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code associated with the conflict. Not always present.

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

    The operation could not be completed because of a conflict with the current state of the resource.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "ContextConditionsMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"StringList"}, + "documentation":"

    Map of context condition keys to lists of allowed values. Used for fine-grained access control on integrations.

    ", + "max":10, + "min":0 + }, + "ContextGraphAttributeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    Attribute map for the unpromoted tail on a context graph node or edge. Holds only the keys that did not land on a typed properties member, so a value is never reported in two places.

    ", + "max":100, + "min":0 + }, + "ContextGraphId":{ + "type":"string", + "documentation":"

    Context graph node identifier.

    ", + "max":256, + "min":1 + }, + "ContextGraphName":{ + "type":"string", + "documentation":"

    Context graph node name.

    ", + "max":512, + "min":1 + }, + "ContributorSummary":{ + "type":"structure", + "members":{ + "warningCount":{ + "shape":"Integer", + "documentation":"

    Number of contributors currently breaching the warning threshold.

    " + }, + "criticalCount":{ + "shape":"Integer", + "documentation":"

    Number of contributors currently breaching the critical threshold.

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

    Counts of contributors currently breaching each severity threshold.

    " + }, + "CreateAccessGrantInput":{ + "type":"structure", + "required":[ + "domainId", + "spaceId", + "name", + "principal", + "permission" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain that contains the space.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The ID of the space to scope the grant to.

    " + }, + "name":{ + "shape":"CreateAccessGrantInputNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "principal":{ + "shape":"AccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"AccessGrantPermission", + "documentation":"

    The permission to grant. Exactly one permission is granted per request.

    " + }, + "scopedActions":{ + "shape":"ScopedActionsList", + "documentation":"

    Groups of actions to allow, each with the resource scopes and conditions that limit those actions.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the access grant.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateAccessGrantInputNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "CreateAccessGrantOutput":{ + "type":"structure", + "required":["accessGrant"], + "members":{ + "accessGrant":{ + "shape":"AccessGrant", + "documentation":"

    The details of the created access grant.

    " + } + } + }, + "CreateAccessProfileInput":{ + "type":"structure", + "required":[ + "spaceId", + "name" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space to create the profile in.

    " + }, + "name":{ + "shape":"AccessProfileName", + "documentation":"

    A name that identifies the access profile.

    " + }, + "description":{ + "shape":"CreateAccessProfileInputDescriptionString", + "documentation":"

    An optional description of the access profile.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the access profile.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateAccessProfileInputDescriptionString":{ + "type":"string", + "max":1024, + "min":0 + }, + "CreateAccessProfileOutput":{ + "type":"structure", + "required":["accessProfile"], + "members":{ + "accessProfile":{ + "shape":"AccessProfile", + "documentation":"

    The access profile.

    " + } + } + }, + "CreateAlertInput":{ + "type":"structure", + "required":[ + "spaceId", + "profileId", + "name", + "rule" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space to create the alert in.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The ID of the access profile the alert uses to evaluate its query and execute notifications. The caller supplies it: there is no managed alert profile, and the service does not pick one on the caller's behalf.

    " + }, + "name":{ + "shape":"CreateAlertInputNameString", + "documentation":"

    Alert name, for display. Max 256 (the AlarmName budget). Not the alert's identity: the backend mints a separate uuid as the {@link AlertId}, so the name need not be unique within a space and addressing an alert never depends on it. UpdateAlert accepts a new name to rename the alert.

    " + }, + "description":{ + "shape":"CreateAlertInputDescriptionString", + "documentation":"

    An optional description of the alert.

    " + }, + "rule":{ + "shape":"Rule", + "documentation":"

    The rule that defines how the alert is evaluated.

    " + }, + "notificationsEnabled":{ + "shape":"Boolean", + "documentation":"

    Whether actions (notifications) are enabled for this alert. Defaults to true when omitted.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the alert.

    " + }, + "notificationRules":{ + "shape":"NotificationRuleList", + "documentation":"

    The notification rules that determine when and where notifications are sent.

    " + }, + "clientToken":{ + "shape":"CreateAlertInputClientTokenString", + "documentation":"

    Idempotency token for safe retries. Retrying with the same token within the idempotency window returns the original alert instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateAlertInputClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\u0021-\\u007E]+" + }, + "CreateAlertInputDescriptionString":{ + "type":"string", + "max":1024, + "min":0 + }, + "CreateAlertInputNameString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "CreateAlertOutput":{ + "type":"structure", + "required":["alert"], + "members":{ + "alertArn":{ + "shape":"Arn", + "documentation":"

    Deprecated. Use alert.alertArn, which carries the same value. Kept so an existing caller keeps working while it moves to alert.

    " + }, + "alert":{ + "shape":"Alert", + "documentation":"

    The alert that was created. The same Alert shape GetAlert returns, so a caller need not read the alert back to learn its timestamps or its minted alert id.

    {@code alert.state} is absent here — see the state member of Alert. Every other member is populated exactly as GetAlert populates it.

    " + } + } + }, + "CreateDomainAccessGrantForOrganizationInput":{ + "type":"structure", + "required":[ + "domainId", + "name", + "principal", + "permission" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain to create the grant on.

    " + }, + "name":{ + "shape":"CreateDomainAccessGrantForOrganizationInputNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "principal":{ + "shape":"OrganizationAccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"OrganizationGrantPermission", + "documentation":"

    The permission to grant.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the access grant.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateDomainAccessGrantForOrganizationInputNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "CreateDomainAccessGrantForOrganizationOutput":{ + "type":"structure", + "required":["accessGrant"], + "members":{ + "accessGrant":{ + "shape":"OrganizationAccessGrant", + "documentation":"

    The details of the created organization access grant.

    " + } + } + }, + "CreateDomainForOrganizationInput":{ + "type":"structure", + "required":[ + "name", + "identityProviders", + "domainAccessRoleArn" + ], + "members":{ + "name":{ + "shape":"CreateDomainForOrganizationInputNameString", + "documentation":"

    A name that identifies the organization domain. Must be 3-63 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers to configure for the domain.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the domain.

    " + }, + "domainAccessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of an IAM role in the management account used for domain access. You must create this role, and its trust policy must allow the service principal to assume it.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the domain.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateDomainForOrganizationInputNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "CreateDomainForOrganizationOutput":{ + "type":"structure", + "required":["organizationDomain"], + "members":{ + "organizationDomain":{ + "shape":"OrganizationDomain", + "documentation":"

    The details of the created organization domain.

    " + } + } + }, + "CreateDomainInput":{ + "type":"structure", + "required":[ + "name", + "identityProviders" + ], + "members":{ + "name":{ + "shape":"CreateDomainInputNameString", + "documentation":"

    A name that identifies the domain. Must be 3-63 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers to configure for the domain.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the domain.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the domain.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateDomainInputNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "CreateDomainOutput":{ + "type":"structure", + "required":["domain"], + "members":{ + "domain":{ + "shape":"Domain", + "documentation":"

    The details of the created domain.

    " + } + } + }, + "CreateIntegrationInput":{ + "type":"structure", + "required":[ + "integrationType", + "name" + ], + "members":{ + "integrationType":{ + "shape":"IntegrationType", + "documentation":"

    The type of third-party provider to integrate with.

    " + }, + "name":{ + "shape":"CreateIntegrationInputNameString", + "documentation":"

    The name for the new integration; unique within the account.

    " + }, + "credential":{ + "shape":"IntegrationCredential", + "documentation":"

    The credential used to authenticate with the third-party provider.

    " + }, + "integrationAttributes":{ + "shape":"CreateIntegrationInputIntegrationAttributesMap", + "documentation":"

    Provider-specific attributes to associate with the integration.

    " + }, + "roleArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name of the IAM role assumed to access the integration.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    Tags to apply to the integration at creation time (Tagris tag-on-create).

    " + }, + "clientToken":{ + "shape":"CreateIntegrationInputClientTokenString", + "documentation":"

    Idempotency token for safe retries. Retrying with the same token returns the original integration instead of creating a duplicate.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    The request for creating an integration with a third-party provider.

    " + }, + "CreateIntegrationInputClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[!-~]+" + }, + "CreateIntegrationInputIntegrationAttributesMap":{ + "type":"map", + "key":{"shape":"CreateIntegrationInputIntegrationAttributesMapKeyString"}, + "value":{"shape":"CreateIntegrationInputIntegrationAttributesMapValueString"}, + "max":50, + "min":0 + }, + "CreateIntegrationInputIntegrationAttributesMapKeyString":{ + "type":"string", + "max":128, + "min":0 + }, + "CreateIntegrationInputIntegrationAttributesMapValueString":{ + "type":"string", + "max":4096, + "min":0 + }, + "CreateIntegrationInputNameString":{ + "type":"string", + "max":256, + "min":1 + }, + "CreateIntegrationOutput":{ + "type":"structure", + "required":["integration"], + "members":{ + "integration":{ + "shape":"Integration", + "documentation":"

    The details of the created integration. This is the same object returned by GetIntegration and UpdateIntegration.

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

    The response from creating an integration.

    " + }, + "CreateOmniDashboardInput":{ + "type":"structure", + "required":[ + "spaceId", + "name", + "body" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space to create the dashboard in.

    " + }, + "name":{ + "shape":"CreateOmniDashboardInputNameString", + "documentation":"

    A name that identifies the dashboard.

    " + }, + "body":{ + "shape":"CreateOmniDashboardInputBodyString", + "documentation":"

    The dashboard definition, as a JSON document. Maximum 1 MiB.

    " + }, + "description":{ + "shape":"CreateOmniDashboardInputDescriptionString", + "documentation":"

    An optional description of the dashboard.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the dashboard.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateOmniDashboardInputBodyString":{ + "type":"string", + "max":1048576, + "min":1 + }, + "CreateOmniDashboardInputDescriptionString":{ + "type":"string", + "max":1024, + "min":1 + }, + "CreateOmniDashboardInputNameString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "CreateOmniDashboardOutput":{ + "type":"structure", + "required":["omniDashboard"], + "members":{ + "omniDashboard":{ + "shape":"OmniDashboard", + "documentation":"

    The dashboard.

    " + } + } + }, + "CreateOneTimeDeepLinkCodeInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain to generate the code for.

    " + }, + "ttlSeconds":{ + "shape":"CreateOneTimeDeepLinkCodeInputTtlSecondsInteger", + "documentation":"

    How long the code remains valid, in seconds. Defaults to 300.

    " + }, + "redirectUrl":{ + "shape":"String", + "documentation":"

    The URL to redirect to after the deep-link code is used. Must be an HTTPS URL in the domain with a path of /auth/callback, and cannot include a query string or fragment. If omitted, no redirect is applied.

    " + } + } + }, + "CreateOneTimeDeepLinkCodeInputTtlSecondsInteger":{ + "type":"integer", + "box":true, + "max":600, + "min":60 + }, + "CreateOneTimeDeepLinkCodeOutput":{ + "type":"structure", + "required":[ + "code", + "deepLinkUrl", + "expiresAt" + ], + "members":{ + "code":{ + "shape":"DeepLinkCode", + "documentation":"

    The one-time deep-link code.

    " + }, + "deepLinkUrl":{ + "shape":"DeepLinkUrl", + "documentation":"

    The deep-link URL containing the one-time code.

    " + }, + "expiresAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the code expires.

    " + } + } + }, + "CreateSpaceInput":{ + "type":"structure", + "required":[ + "name", + "domainId", + "dataAccessRoleArn" + ], + "members":{ + "name":{ + "shape":"CreateSpaceInputNameString", + "documentation":"

    A name that identifies the space. Must be 3-64 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain to create the space in.

    " + }, + "dataAccessRoleArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the IAM role used for data access. The role must be in the caller's account.

    " + }, + "agentCoreEvaluationRoleArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the IAM role used by AgentCore online evaluation. Must be in the caller's account. Omit if the space does not use AgentCore online evaluation.

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    How to encrypt the space's data at rest. Omit for service owned encryption, which is equivalent to passing encryptionStrategy AWS_OWNED.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to associate with the space.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeated requests with the same token return the original result instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateSpaceInputNameString":{ + "type":"string", + "max":64, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "CreateSpaceOutput":{ + "type":"structure", + "required":["space"], + "members":{ + "space":{ + "shape":"Space", + "documentation":"

    The details of the created space.

    " + } + } + }, + "CreateViewRequest":{ + "type":"structure", + "required":[ + "name", + "definition" + ], + "members":{ + "name":{ + "shape":"ViewName", + "documentation":"

    The name of the view. Must begin with the "view." prefix. View names must be unique within the account and region.

    " + }, + "definition":{ + "shape":"ViewDefinition", + "documentation":"

    The SQL query that defines the view.

    " + }, + "description":{ + "shape":"ViewDescription", + "documentation":"

    A description of the view.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    Resource tags.

    " + }, + "clientToken":{ + "shape":"CreateViewRequestClientTokenString", + "documentation":"

    Idempotency token for safe retries. Retrying with the same token returns the original view instead of creating a duplicate.

    ", + "idempotencyToken":true + } + } + }, + "CreateViewRequestClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[!-~]+" + }, + "CreateViewResponse":{ + "type":"structure", + "required":[ + "name", + "type", + "definition", + "createdAt", + "updatedAt", + "arn" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the view.

    " + }, + "type":{ + "shape":"ViewType", + "documentation":"

    The ownership category of the view.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the view.

    " + }, + "definition":{ + "shape":"String", + "documentation":"

    The SQL query that defines the view.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was last updated.

    " + }, + "arn":{ + "shape":"String", + "documentation":"

    The ARN of the view.

    " + } + } + }, + "DashboardId":{ + "type":"string", + "documentation":"

    Dashboard identifier — a lowercase v4 UUID assigned when the dashboard is created.

    ", + "max":36, + "min":36, + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "DeepLinkCode":{ + "type":"string", + "documentation":"

    A one-time deep-link code exchanged for a domain-scoped session. Sensitive: it can be redeemed for a session token, so it is redacted from request logs and CloudTrail.

    ", + "sensitive":true + }, + "DeepLinkUrl":{ + "type":"string", + "documentation":"

    A deep-link URL that embeds the one-time deep-link code. Sensitive: it carries the same redeemable code, so it is redacted from request logs and CloudTrail.

    ", + "sensitive":true + }, + "DeleteAccessGrantInput":{ + "type":"structure", + "required":["grantId"], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The ID of the access grant to delete.

    " + } + } + }, + "DeleteAccessGrantOutput":{ + "type":"structure", + "members":{} + }, + "DeleteAccessProfileInput":{ + "type":"structure", + "required":[ + "spaceId", + "profileId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique ID of the access profile to delete.

    " + } + } + }, + "DeleteAccessProfileOutput":{ + "type":"structure", + "members":{} + }, + "DeleteAlertInput":{ + "type":"structure", + "required":[ + "spaceId", + "alertId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "alertId":{ + "shape":"AlertId", + "documentation":"

    The alert to delete.

    " + } + } + }, + "DeleteAlertOutput":{ + "type":"structure", + "members":{} + }, + "DeleteDomainAccessGrantForOrganizationInput":{ + "type":"structure", + "required":["grantId"], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The ID of the access grant to delete.

    " + } + } + }, + "DeleteDomainAccessGrantForOrganizationOutput":{ + "type":"structure", + "members":{} + }, + "DeleteDomainForOrganizationInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain to delete.

    " + } + } + }, + "DeleteDomainForOrganizationOutput":{ + "type":"structure", + "members":{} + }, + "DeleteDomainInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the domain to delete.

    " + } + } + }, + "DeleteDomainOutput":{ + "type":"structure", + "members":{} + }, + "DeleteIntegrationInput":{ + "type":"structure", + "required":["identifier"], + "members":{ + "identifier":{ + "shape":"IntegrationIdentifier", + "documentation":"

    Identifies the integration to delete — exactly one of integrationId, integrationArn, or integrationName.

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

    The request for deleting an integration.

    " + }, + "DeleteIntegrationOutput":{ + "type":"structure", + "members":{}, + "documentation":"

    The response from deleting an integration. Empty by contract — a successful call indicates the deletion was accepted (DeleteIntegration is idempotent).

    " + }, + "DeleteOmniDashboardInput":{ + "type":"structure", + "required":[ + "spaceId", + "dashboardId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "dashboardId":{ + "shape":"DashboardId", + "documentation":"

    The unique ID of the dashboard.

    " + } + } + }, + "DeleteOmniDashboardOutput":{ + "type":"structure", + "members":{} + }, + "DeleteSpaceInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space to delete.

    " + } + } + }, + "DeleteSpaceOutput":{ + "type":"structure", + "members":{} + }, + "DeleteViewRequest":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"ViewName", + "documentation":"

    The name of the view to delete.

    " + } + } + }, + "DeleteViewResponse":{ + "type":"structure", + "members":{} + }, + "Domain":{ + "type":"structure", + "required":[ + "domainId", + "domainArn", + "identityProviders", + "domainEndpointUrl", + "region", + "createdAt", + "updatedAt", + "status" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the domain.

    " + }, + "domainArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the domain.

    " + }, + "name":{ + "shape":"DomainNameString", + "documentation":"

    A name that identifies the domain.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers configured for the domain.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the domain.

    " + }, + "domainEndpointUrl":{ + "shape":"String", + "documentation":"

    The HTTPS endpoint URL for accessing the domain.

    " + }, + "customEndpointUrls":{ + "shape":"StringList", + "documentation":"

    Additional endpoint URLs derived from the domain name.

    " + }, + "identityCenterApplicationArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the Identity Center application. Absent for IAM-only domains.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The Region where this domain was created.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the domain was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the domain was last updated.

    " + }, + "status":{ + "shape":"DomainStatus", + "documentation":"

    Current status of the domain.

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

    Detailed information about a domain.

    " + }, + "DomainId":{ + "type":"string", + "documentation":"

    Domain identifier in "d-{base36}" format, e.g. "d-5h2neqbcpc4sk6gswog". Minted by the backend as "d-" + base36(UUID) — at most "d-" plus 25 chars. Note: not a bare UUID (unlike space/grant ids), so a UUID pattern would wrongly reject valid domain ids.

    ", + "pattern":"d-[0-9a-z]{1,25}" + }, + "DomainNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "DomainStatus":{ + "type":"string", + "documentation":"

    Current status of a domain.

    ", + "enum":["ACTIVE"] + }, + "DomainSummary":{ + "type":"structure", + "required":[ + "domainId", + "createdAt", + "updatedAt", + "status" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the domain.

    " + }, + "domainArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the domain.

    " + }, + "name":{ + "shape":"DomainSummaryNameString", + "documentation":"

    A name that identifies the domain.

    " + }, + "identityCenterInstanceArn":{ + "shape":"IdentityCenterInstanceArn", + "documentation":"

    Identity Center instance ARN configured for the domain. Absent for IAM-only domains.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The Region where this domain was created.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the domain was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the domain was last updated.

    " + }, + "status":{ + "shape":"DomainStatus", + "documentation":"

    Current status of the domain.

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

    Summary of a domain. Call GetDomain for the full domain.

    " + }, + "DomainSummaryList":{ + "type":"list", + "member":{"shape":"DomainSummary"}, + "documentation":"

    List of domain summaries.

    " + }, + "DomainSummaryNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "Double":{ + "type":"double", + "box":true + }, + "Edge":{ + "type":"structure", + "members":{ + "edgeId":{ + "shape":"ContextGraphId", + "documentation":"

    The unique identifier of the edge within the context graph.

    " + }, + "from":{ + "shape":"ContextGraphId", + "documentation":"

    The node identifier the edge originates from.

    " + }, + "to":{ + "shape":"ContextGraphId", + "documentation":"

    The node identifier the edge points to.

    " + }, + "edgeType":{ + "shape":"EdgeType", + "documentation":"

    The kind of relationship the edge represents.

    " + }, + "operations":{ + "shape":"StringSet", + "documentation":"

    The operations observed on this edge.

    " + }, + "edgeProperties":{ + "shape":"EdgeProperties", + "documentation":"

    Attributes promoted out of the flat attribute map onto typed members. Which members are present depends on what produced the edge.

    " + }, + "telemetryAttributes":{ + "shape":"ContextGraphAttributeMap", + "documentation":"

    The edge's OpenTelemetry (OTel) attributes, as emitted by telemetry. A key promoted onto an edgeProperties member is removed here, so no value appears twice.

    " + }, + "signalTypes":{ + "shape":"SignalSet", + "documentation":"

    The kinds of telemetry signal observed on this edge.

    " + }, + "sources":{ + "shape":"SourceSet", + "documentation":"

    The discovery sources that contributed this edge.

    " + }, + "metadata":{ + "shape":"Metadata", + "documentation":"

    Descriptive metadata about the edge. Present only when the request sets includeMetadata.

    " + }, + "firstObservedAt":{ + "shape":"Timestamp", + "documentation":"

    When this edge was first observed (UTC), at minute granularity. For an edge that merged across sources, this is the earliest value any source reported.

    " + }, + "lastObservedAt":{ + "shape":"Timestamp", + "documentation":"

    When this edge was most recently observed (UTC), at minute granularity. For an edge that merged across sources, this is the latest value any source reported.

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

    A directed edge in the context graph connecting two nodes.

    " + }, + "EdgeFilters":{ + "type":"structure", + "members":{ + "edgeId":{ + "shape":"ContextGraphId", + "documentation":"

    Match only the edge with this identifier.

    " + }, + "from":{ + "shape":"ContextGraphId", + "documentation":"

    Match only edges originating from this node identifier.

    " + }, + "to":{ + "shape":"ContextGraphId", + "documentation":"

    Match only edges pointing to this node identifier.

    " + }, + "edgeType":{ + "shape":"EdgeType", + "documentation":"

    Match only edges of this relationship kind.

    " + }, + "operations":{ + "shape":"StringSet", + "documentation":"

    Match edges carrying any of these operations.

    " + }, + "telemetryAttributes":{ + "shape":"KeyFilterList", + "documentation":"

    Match edges by their OpenTelemetry (OTel) telemetry attributes. Not yet enforced: currently accepted but ignored (does not filter), matching nodeFilters.telemetryAttributes.

    " + }, + "sources":{ + "shape":"SourceSet", + "documentation":"

    Match edges contributed by any of these discovery sources.

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

    Criteria for filtering edges in a context graph query.

    " + }, + "EdgeList":{ + "type":"list", + "member":{"shape":"Edge"}, + "documentation":"

    List of context graph edges returned by GetContextGraph. Bounded to allow up to maxResults nodes each with up to maxEdgesPerNode edges, with a practical upper cap to guarantee predictable response sizes.

    ", + "max":5000, + "min":0 + }, + "EdgeProperties":{ + "type":"structure", + "members":{ + "protocol":{ + "shape":"String", + "documentation":"

    The IANA protocol name for the observed network traffic, such as "tcp".

    " + }, + "sourcePort":{ + "shape":"String", + "documentation":"

    The source port of the observed traffic. May be a placeholder when the port is unknown.

    " + }, + "destinationPort":{ + "shape":"String", + "documentation":"

    The destination port of the observed traffic. May be a placeholder when the port is unknown.

    " + }, + "blocked":{ + "shape":"Boolean", + "documentation":"

    Whether the observed network flow was denied. Absent means the edge was not derived from network flow data, which is not the same as allowed.

    " + }, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code returned when the call was attempted and refused. Its presence means the edge exists but the dependency is failing.

    " + }, + "httpStatusCode":{ + "shape":"String", + "documentation":"

    The HTTP status code observed on the request. Distinct from errorCode.

    " + }, + "httpMethod":{ + "shape":"String", + "documentation":"

    The HTTP method observed on the request.

    " + }, + "serviceInitiated":{ + "shape":"Boolean", + "documentation":"

    Whether the caller was an AWS service principal rather than a user or role. Absent means the edge was not derived from a source that reports it.

    " + }, + "trafficStats":{ + "shape":"EdgeTrafficStats", + "documentation":"

    Traffic counters accumulated over the edge's observation window.

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

    Edge attributes promoted out of the flat attribute map onto typed members. Which members are present depends entirely on what produced the edge, so most edges carry only a few of them.

    " + }, + "EdgeTrafficStats":{ + "type":"structure", + "members":{ + "bytes":{ + "shape":"EdgeTrafficStatsBytesLong", + "documentation":"

    Total bytes observed across the edge.

    " + }, + "packets":{ + "shape":"EdgeTrafficStatsPacketsLong", + "documentation":"

    Total packets observed across the edge.

    " + }, + "flows":{ + "shape":"EdgeTrafficStatsFlowsLong", + "documentation":"

    Total network flows observed across the edge.

    " + }, + "sentBytes":{ + "shape":"EdgeTrafficStatsSentBytesLong", + "documentation":"

    Total bytes sent to the destination.

    " + }, + "receivedBytes":{ + "shape":"EdgeTrafficStatsReceivedBytesLong", + "documentation":"

    Total bytes received from the destination.

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

    Additive traffic counters accumulated over an edge's observation window. Which counters are populated depends on what produced the edge.

    " + }, + "EdgeTrafficStatsBytesLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EdgeTrafficStatsFlowsLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EdgeTrafficStatsPacketsLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EdgeTrafficStatsReceivedBytesLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EdgeTrafficStatsSentBytesLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EdgeType":{ + "type":"string", + "documentation":"

    Context graph edge types.

    ", + "enum":[ + "CALLS", + "ACCESSES", + "RUNS_ON" + ] + }, + "EncryptionConfiguration":{ + "type":"structure", + "required":["encryptionStrategy"], + "members":{ + "encryptionStrategy":{ + "shape":"EncryptionStrategy", + "documentation":"

    Which kind of key to use. Required.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    Customer managed KMS key ARN. Required when encryptionStrategy is CUSTOMER_MANAGED, and must be omitted when it is AWS_OWNED. Must be a symmetric ENCRYPT_DECRYPT key in the caller's account and region.

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

    How a resource's data at rest is encrypted.

    kmsKeyArn is required when encryptionStrategy is CUSTOMER_MANAGED and must be absent when it is AWS_OWNED; a mismatch is a ValidationException rather than a silently ignored field, so a caller that selects AWS_OWNED while still passing a key learns that the key was not applied.

    " + }, + "EncryptionStrategy":{ + "type":"string", + "documentation":"

    Which kind of KMS key protects a resource's data at rest.

    ", + "enum":[ + "AWS_OWNED", + "CUSTOMER_MANAGED" + ] + }, + "Field":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the field. Field names are case-sensitive and must be used exactly as returned when referencing them in query expressions.

    " + }, + "children":{ + "shape":"FieldChildrenList", + "documentation":"

    Child fields nested under this field.

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

    A telemetry field available for use in query expressions.

    " + }, + "FieldChildrenList":{ + "type":"list", + "member":{"shape":"Field"}, + "max":1000, + "min":0 + }, + "FieldList":{ + "type":"list", + "member":{"shape":"Field"} + }, + "GetAccessGrantInput":{ + "type":"structure", + "required":["grantId"], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The ID of the access grant to retrieve.

    " + } + } + }, + "GetAccessGrantOutput":{ + "type":"structure", + "required":["accessGrant"], + "members":{ + "accessGrant":{ + "shape":"AccessGrant", + "documentation":"

    The full details of the access grant.

    " + } + } + }, + "GetAccessProfileInput":{ + "type":"structure", + "required":[ + "spaceId", + "profileId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique ID of the access profile.

    " + } + } + }, + "GetAccessProfileOutput":{ + "type":"structure", + "required":["accessProfile"], + "members":{ + "accessProfile":{ + "shape":"AccessProfile", + "documentation":"

    The access profile.

    " + } + } + }, + "GetAlertInput":{ + "type":"structure", + "required":[ + "spaceId", + "alertId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "alertId":{ + "shape":"AlertId", + "documentation":"

    The alert to retrieve.

    " + } + } + }, + "GetAlertOutput":{ + "type":"structure", + "required":["alert"], + "members":{ + "alert":{ + "shape":"Alert", + "documentation":"

    The full alert entity.

    " + } + } + }, + "GetContextGraphInput":{ + "type":"structure", + "required":[ + "startTime", + "endTime" + ], + "members":{ + "nodeFilters":{ + "shape":"NodeFilters", + "documentation":"

    Criteria restricting which nodes are returned.

    " + }, + "edgeFilters":{ + "shape":"EdgeFilters", + "documentation":"

    Criteria restricting which edges are returned.

    " + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    Start of the time range (UTC), inclusive.

    " + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    End of the time range (UTC), inclusive.

    " + }, + "depth":{ + "shape":"GetContextGraphInputDepthInteger", + "documentation":"

    How many hops to traverse out from the nodes matched by nodeFilters. 0 returns only the matched nodes themselves.

    " + }, + "maxResults":{ + "shape":"GetContextGraphInputMaxResultsInteger", + "documentation":"

    The maximum number of nodes to return in a single page.

    " + }, + "maxEdgesPerNode":{ + "shape":"GetContextGraphInputMaxEdgesPerNodeInteger", + "documentation":"

    The maximum number of edges to return per node, bounding the fan-out of a densely connected node.

    " + }, + "includeMetadata":{ + "shape":"Boolean", + "documentation":"

    Whether to return the metadata block, semantics included, on each node and edge. Off by default because it costs an extra lookup per returned node.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    Pagination token from a previous response, to retrieve the next page.

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

    The request for retrieving a slice of the context graph.

    " + }, + "GetContextGraphInputDepthInteger":{ + "type":"integer", + "box":true, + "max":3, + "min":0 + }, + "GetContextGraphInputMaxEdgesPerNodeInteger":{ + "type":"integer", + "box":true, + "max":50, + "min":1 + }, + "GetContextGraphInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "GetContextGraphOutput":{ + "type":"structure", + "required":["nodes"], + "members":{ + "nodes":{ + "shape":"NodeList", + "documentation":"

    The page of nodes matching the request. This is the paginated collection.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    Pagination token for the next page; absent when there are no more results.

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

    The response containing the requested slice of the context graph.

    " + }, + "GetDomainAccessGrantForOrganizationInput":{ + "type":"structure", + "required":["grantId"], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The ID of the access grant to retrieve.

    " + } + } + }, + "GetDomainAccessGrantForOrganizationOutput":{ + "type":"structure", + "required":["accessGrant"], + "members":{ + "accessGrant":{ + "shape":"OrganizationAccessGrant", + "documentation":"

    The retrieved organization access grant.

    " + } + } + }, + "GetDomainForOrganizationInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain.

    " + } + } + }, + "GetDomainForOrganizationOutput":{ + "type":"structure", + "required":["organizationDomain"], + "members":{ + "organizationDomain":{ + "shape":"OrganizationDomain", + "documentation":"

    The details of the organization domain.

    " + } + } + }, + "GetDomainInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the domain.

    " + } + } + }, + "GetDomainOutput":{ + "type":"structure", + "required":["domain"], + "members":{ + "domain":{ + "shape":"Domain", + "documentation":"

    The details of the domain.

    " + } + } + }, + "GetIntegrationInput":{ + "type":"structure", + "required":["identifier"], + "members":{ + "identifier":{ + "shape":"IntegrationIdentifier", + "documentation":"

    Identifies the integration to return — exactly one of integrationId, integrationArn, or integrationName.

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

    The request for retrieving a single integration.

    " + }, + "GetIntegrationOutput":{ + "type":"structure", + "required":["integration"], + "members":{ + "integration":{ + "shape":"Integration", + "documentation":"

    The details of the requested integration.

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

    The response containing the requested integration.

    " + }, + "GetIntelligenceConfigurationInput":{ + "type":"structure", + "members":{}, + "documentation":"

    The request for retrieving the intelligence configuration of the calling account.

    " + }, + "GetIntelligenceConfigurationOutput":{ + "type":"structure", + "required":[ + "accountId", + "updatedAt", + "createdAt" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID this configuration applies to.

    " + }, + "kmsKeyArn":{ + "shape":"IntelligenceKmsKeyArn", + "documentation":"

    The currently active KMS key ARN for customer-managed encryption, if configured.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    ISO-8601 timestamp of the last update.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    ISO-8601 timestamp of initial creation.

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

    The intelligence configuration for the calling account.

    " + }, + "GetOmniDashboardInput":{ + "type":"structure", + "required":[ + "spaceId", + "dashboardId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "dashboardId":{ + "shape":"DashboardId", + "documentation":"

    The unique ID of the dashboard.

    " + } + } + }, + "GetOmniDashboardOutput":{ + "type":"structure", + "required":["omniDashboard"], + "members":{ + "omniDashboard":{ + "shape":"OmniDashboard", + "documentation":"

    The dashboard.

    " + } + } + }, + "GetSpaceCredentialsForOrganizationInput":{ + "type":"structure", + "required":[ + "context", + "credentialType" + ], + "members":{ + "context":{ + "shape":"SpaceCredentialRequestContext", + "documentation":"

    Context for credential resolution.

    " + }, + "credentialType":{ + "shape":"OrganizationCredentialType", + "documentation":"

    Selects which member-account credential to return. Set this to SPACE_OPERATION.

    " + } + } + }, + "GetSpaceCredentialsForOrganizationOutput":{ + "type":"structure", + "required":["credentials"], + "members":{ + "credentials":{ + "shape":"AwsCredentials", + "documentation":"

    The temporary AWS credentials for the space.

    " + } + } + }, + "GetSpaceInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + } + } + }, + "GetSpaceOutput":{ + "type":"structure", + "required":["space"], + "members":{ + "space":{ + "shape":"Space", + "documentation":"

    The details of the space.

    " + } + } + }, + "GetTelemetryQueryResultsRequest":{ + "type":"structure", + "required":["queryId"], + "members":{ + "queryId":{ + "shape":"GetTelemetryQueryResultsRequestQueryIdString", + "documentation":"

    The unique ID of the query.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results.

    " + }, + "maxResults":{ + "shape":"GetTelemetryQueryResultsRequestMaxResultsInteger", + "documentation":"

    The maximum number of result rows to return per page.

    " + } + } + }, + "GetTelemetryQueryResultsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "GetTelemetryQueryResultsRequestQueryIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "GetTelemetryQueryResultsResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"QueryStatus", + "documentation":"

    The current execution status of the query.

    " + }, + "rows":{ + "shape":"RowList", + "documentation":"

    The result rows returned by the query.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + }, + "statistics":{ + "shape":"QueryStatistics", + "documentation":"

    Statistics about the query execution.

    " + } + } + }, + "GetViewRequest":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"ViewName", + "documentation":"

    The name of the view.

    " + } + } + }, + "GetViewResponse":{ + "type":"structure", + "required":[ + "name", + "type", + "definition", + "createdAt", + "updatedAt", + "arn" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the view.

    " + }, + "type":{ + "shape":"ViewType", + "documentation":"

    The ownership category of the view.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the view.

    " + }, + "definition":{ + "shape":"String", + "documentation":"

    The SQL query that defines the view.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was last updated.

    " + }, + "arn":{ + "shape":"String", + "documentation":"

    The ARN of the view.

    " + } + } + }, + "GrantId":{ + "type":"string", + "documentation":"

    AccessGrant identifier — a v4 UUID assigned when the grant is created.

    ", + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "IamRoleArn":{ + "type":"string", + "documentation":"

    IAM role ARN for backend delivery.

    ", + "max":2048, + "min":20, + "pattern":"arn:aws[a-zA-Z-]*:iam::[0-9]{12}:role/.+" + }, + "IdentityCenterConfiguration":{ + "type":"structure", + "members":{ + "identityCenterInstanceArn":{ + "shape":"IdentityCenterInstanceArn", + "documentation":"

    Identity Center instance ARN

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

    Identity Center specific configuration.

    " + }, + "IdentityCenterInstanceArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws[a-z-]*:sso:::instance/[a-zA-Z0-9-]+" + }, + "IdentityProvider":{ + "type":"string", + "documentation":"

    Identity provider type for a domain. Determines which identity mechanisms are active for authentication.

    ", + "enum":[ + "IAM", + "IDC" + ] + }, + "IdentityProviderConfiguration":{ + "type":"structure", + "members":{ + "identityCenterConfiguration":{ + "shape":"IdentityCenterConfiguration", + "documentation":"

    Identity Center configuration. Required when identityProviders includes IDC.

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

    Identity provider configuration for domain authentication. Contains provider-specific configuration blocks.

    " + }, + "IdentityProviderList":{ + "type":"list", + "member":{"shape":"IdentityProvider"}, + "documentation":"

    List of identity providers configured for a domain.

    ", + "max":2, + "min":1 + }, + "Integer":{ + "type":"integer", + "box":true + }, + "Integration":{ + "type":"structure", + "required":[ + "integrationId", + "integrationType", + "name", + "status" + ], + "members":{ + "integrationId":{ + "shape":"String", + "documentation":"

    The unique identifier of the integration.

    " + }, + "integrationArn":{ + "shape":"IntegrationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the integration.

    " + }, + "integrationType":{"shape":"IntegrationType"}, + "name":{ + "shape":"String", + "documentation":"

    The customer-provided name of the integration.

    " + }, + "status":{"shape":"IntegrationStatus"}, + "authType":{"shape":"AuthType"}, + "credentialArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the secret that stores the integration's credentials.

    " + }, + "roleArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that CloudWatch assumes to access the external system.

    " + }, + "integrationAttributes":{ + "shape":"StringMap", + "documentation":"

    Provider-specific key/value attributes that configure the integration.

    " + }, + "authorizationUrl":{ + "shape":"String", + "documentation":"

    The URL the customer visits to authorize the integration. Present while an OAuth authorization is pending.

    " + }, + "errorMessage":{ + "shape":"String", + "documentation":"

    A human-readable description of why the integration is in an ERROR or FAILED state. Present only when the integration has failed.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The time at which the integration was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The time at which the integration was last updated.

    " + }, + "scope":{ + "shape":"Scope", + "documentation":"

    Whether this integration is account-scoped (ACCOUNT, customer-created) or organization-scoped (ORGANIZATION, created by an org-enablement rule). Absent on legacy records is treated as ACCOUNT.

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

    A connection between CloudWatch and an external system — such as a source of telemetry or configuration data, a messaging destination, or a model provider.

    " + }, + "IntegrationArn":{"type":"string"}, + "IntegrationCredential":{ + "type":"structure", + "members":{ + "oauthCodeCredential":{ + "shape":"OAuthCodeCredential", + "documentation":"

    Credentials for an OAuth 2.0 authorization-code grant.

    " + }, + "oauthClientCredential":{ + "shape":"OAuthClientCredential", + "documentation":"

    Credentials for an OAuth 2.0 client-credentials grant.

    " + }, + "apiKeyCredential":{ + "shape":"ApiKeyCredential", + "documentation":"

    An API key credential.

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

    The credential that an integration uses to authenticate with its external system. Exactly one member is set, matching the integration's authentication type.

    ", + "union":true + }, + "IntegrationIdentifier":{ + "type":"structure", + "members":{ + "integrationId":{ + "shape":"String", + "documentation":"

    The unique identifier of the integration.

    " + }, + "integrationArn":{ + "shape":"IntegrationArn", + "documentation":"

    The Amazon Resource Name of the integration.

    " + }, + "integrationName":{ + "shape":"String", + "documentation":"

    The name of the integration; unique within the account.

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

    Identifies a single integration by exactly one of its unique keys: the integration id, the integration ARN, or the integration name.

    ", + "union":true + }, + "IntegrationList":{ + "type":"list", + "member":{"shape":"Integration"} + }, + "IntegrationStatus":{ + "type":"string", + "documentation":"

    The current lifecycle state of an integration.

    ", + "enum":[ + "ACTIVE", + "DELETED", + "PENDING", + "PENDING_OAUTH", + "ERROR", + "FAILED" + ] + }, + "IntegrationType":{ + "type":"string", + "documentation":"

    The type of external system that an integration connects to, such as a source of configuration data, a messaging destination, or a model provider.

    ", + "enum":[ + "AWS_CONFIG_SLREC", + "SLACK", + "EXTERNAL_AGENT", + "AWS_INTEGRATION" + ] + }, + "IntelligenceKmsKeyArn":{ + "type":"string", + "documentation":"

    Constrained KMS key ARN string matching the format arn:aws:kms:::key/.

    ", + "max":2048, + "min":1, + "pattern":"arn:(aws|aws-cn|aws-us-gov):kms:[a-z0-9-]+:[0-9]{12}:key/(?:mrk-)?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "IntelligenceTagMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    Tag map for Intelligence shapes (collision-avoidance renamed from TagMap).

    ", + "max":50, + "min":0 + }, + "InternalServerException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code associated with the internal error.

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

    An unexpected error occurred while processing the request.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, + "KeyFilter":{ + "type":"structure", + "required":["key"], + "members":{ + "key":{ + "shape":"KeyFilterKey", + "documentation":"

    The tag or attribute key to filter on.

    " + }, + "values":{ + "shape":"KeyFilterValues", + "documentation":"

    The values to match for this key, OR'ed together. Each supports exact, negation (!value), and wildcard (value, value*, *value) syntax.

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

    Key-value filter used for tags and attributes filtering. Multiple KeyFilters are AND'ed. Multiple values within a single KeyFilter are OR'ed. Values support pattern syntax: exact, negation (!value), wildcard (value, value*, *value).

    " + }, + "KeyFilterKey":{ + "type":"string", + "documentation":"

    Key filter key string.

    ", + "max":128, + "min":1 + }, + "KeyFilterList":{ + "type":"list", + "member":{"shape":"KeyFilter"}, + "documentation":"

    Key filter list for context graph queries.

    ", + "max":5, + "min":1 + }, + "KeyFilterValue":{ + "type":"string", + "documentation":"

    Key filter value string.

    ", + "max":259, + "min":0 + }, + "KeyFilterValues":{ + "type":"list", + "member":{"shape":"KeyFilterValue"}, + "documentation":"

    Key filter values list.

    ", + "max":50, + "min":0 + }, + "KmsKeyArn":{ + "type":"string", + "documentation":"

    KMS key ARN — must be a full key ARN (not an alias).

    ", + "pattern":"arn:aws[a-zA-Z-]*:kms:[a-z0-9-]+:[0-9]{12}:key/(mrk-)?[a-f0-9-]+" + }, + "ListAccessGrantsInput":{ + "type":"structure", + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    Filter by domain ID.

    " + }, + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    Filter by space ID.

    " + }, + "principalId":{ + "shape":"PrincipalId", + "documentation":"

    Filter by principal ID.

    " + }, + "principalType":{ + "shape":"AccessGrantPrincipalType", + "documentation":"

    Filter by principal type.

    " + }, + "permission":{ + "shape":"AccessGrantPermission", + "documentation":"

    Filter by permission level.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results. Supply the same filters used on the request that returned it. Tokens expire after 24 hours.

    " + }, + "maxResults":{ + "shape":"ListAccessGrantsInputMaxResultsInteger", + "documentation":"

    The maximum number of access grants to return per page. Defaults to 100. A page can contain fewer results than this value even when more results remain; continue while nextToken is present.

    " + } + } + }, + "ListAccessGrantsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListAccessGrantsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AccessGrantSummaryList", + "documentation":"

    The list of access grant summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListAccessProfilesInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results.

    " + }, + "maxResults":{ + "shape":"ListAccessProfilesInputMaxResultsInteger", + "documentation":"

    The maximum number of access profiles to return per page. Defaults to 100.

    " + } + } + }, + "ListAccessProfilesInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListAccessProfilesOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AccessProfileSummaryList", + "documentation":"

    The list of access profile summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListAlertsInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "filterCriteria":{ + "shape":"AlertFilterCriteria", + "documentation":"

    Filter criteria narrowing which alerts are returned. All members are optional; the three name/id filters are mutually exclusive.

    " + }, + "sortBy":{ + "shape":"AlertSortField", + "documentation":"

    The field to sort results by.

    " + }, + "sortOrder":{ + "shape":"AlertSortOrder", + "documentation":"

    The order in which to sort results.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results.

    " + }, + "maxResults":{ + "shape":"ListAlertsInputMaxResultsInteger", + "documentation":"

    The maximum number of alerts to return per page.

    " + } + } + }, + "ListAlertsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListAlertsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AlertSummaryList", + "documentation":"

    The list of alert summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListDomainAccessGrantsForOrganizationInput":{ + "type":"structure", + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    Filter by domain ID.

    " + }, + "principalId":{ + "shape":"PrincipalId", + "documentation":"

    Filter by principal ID.

    " + }, + "principalType":{ + "shape":"OrganizationGrantPrincipalType", + "documentation":"

    Filter by principal type.

    " + }, + "permission":{ + "shape":"OrganizationGrantPermission", + "documentation":"

    Filter by permission level.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results. Supply the same filters used on the request that returned it. Tokens expire after 24 hours.

    " + }, + "maxResults":{ + "shape":"ListDomainAccessGrantsForOrganizationInputMaxResultsInteger", + "documentation":"

    The maximum number of access grants to return per page. Defaults to 100. A page can contain fewer results than this value even when more results remain; continue while nextToken is present.

    " + } + } + }, + "ListDomainAccessGrantsForOrganizationInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListDomainAccessGrantsForOrganizationOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"OrganizationAccessGrantSummaryList", + "documentation":"

    The list of organization access grant summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListDomainsInput":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results. Tokens expire after 24 hours.

    " + }, + "maxResults":{ + "shape":"ListDomainsInputMaxResultsInteger", + "documentation":"

    The maximum number of domains to return per page. Defaults to 100.

    " + } + } + }, + "ListDomainsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListDomainsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"DomainSummaryList", + "documentation":"

    The list of domain summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListIntegrationsInput":{ + "type":"structure", + "members":{ + "integrationType":{ + "shape":"IntegrationType", + "documentation":"

    Returns only integrations of this provider type.

    " + }, + "status":{ + "shape":"IntegrationStatus", + "documentation":"

    Returns only integrations in this status.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    Returns only the integration with this exact name.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    Pagination token from a previous response; omit for the first page.

    " + }, + "maxResults":{ + "shape":"ListIntegrationsInputMaxResultsInteger", + "documentation":"

    Maximum number of integrations to return in one page.

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

    The request for listing the integrations in an account.

    " + }, + "ListIntegrationsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListIntegrationsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"IntegrationList", + "documentation":"

    The page of integrations.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    Pagination token for the next page; absent when there are no more results.

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

    The response containing a page of integrations.

    " + }, + "ListOmniDashboardsInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "namePrefix":{ + "shape":"ListOmniDashboardsInputNamePrefixString", + "documentation":"

    Filter to dashboards whose name starts with this prefix.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results.

    " + }, + "maxResults":{ + "shape":"ListOmniDashboardsInputMaxResultsInteger", + "documentation":"

    The maximum number of dashboards to return per page. Defaults to 100. A page can contain fewer results than this value even when more results remain; continue while nextToken is present.

    " + } + } + }, + "ListOmniDashboardsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListOmniDashboardsInputNamePrefixString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "ListOmniDashboardsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"OmniDashboardSummaryList", + "documentation":"

    The list of dashboard summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListSpacesForOrganizationInput":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results. Tokens expire after 24 hours.

    " + }, + "maxResults":{ + "shape":"ListSpacesForOrganizationInputMaxResultsInteger", + "documentation":"

    The maximum number of spaces to return per page. Defaults to 100.

    " + } + } + }, + "ListSpacesForOrganizationInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListSpacesForOrganizationOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"SpaceSummaryList", + "documentation":"

    The list of space summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListSpacesInput":{ + "type":"structure", + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    Filter by domain ID.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results. Supply the same filters used on the request that returned it. Tokens expire after 24 hours.

    " + }, + "maxResults":{ + "shape":"ListSpacesInputMaxResultsInteger", + "documentation":"

    The maximum number of spaces to return per page. Defaults to 100. A page can contain fewer results than this value even when more results remain; continue while nextToken is present.

    " + } + } + }, + "ListSpacesInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListSpacesOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"SpaceSummaryList", + "documentation":"

    The list of space summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListTelemetryFieldsRequest":{ + "type":"structure", + "required":["dataSetName"], + "members":{ + "dataSetName":{ + "shape":"ListTelemetryFieldsRequestDataSetNameString", + "documentation":"

    The name of the dataset to list fields for.

    " + }, + "telemetryType":{ + "shape":"TelemetryType", + "documentation":"

    The type of telemetry to filter fields by.

    " + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    Inclusive start of the lookback window. When omitted, the service defaults to the configured lookback before endTime.

    " + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    Inclusive end of the lookback window. When omitted, the service defaults to the current time.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results. Reserved for future pagination; the service does not paginate at this time and returns null.

    " + } + } + }, + "ListTelemetryFieldsRequestDataSetNameString":{ + "type":"string", + "max":128, + "min":1 + }, + "ListTelemetryFieldsResponse":{ + "type":"structure", + "required":["fields"], + "members":{ + "fields":{ + "shape":"FieldList", + "documentation":"

    The list of fields available for queries.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListTelemetryQuerySessionsRequest":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results.

    " + }, + "maxResults":{ + "shape":"ListTelemetryQuerySessionsRequestMaxResultsInteger", + "documentation":"

    The maximum number of sessions to return per page.

    " + } + } + }, + "ListTelemetryQuerySessionsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListTelemetryQuerySessionsResponse":{ + "type":"structure", + "required":["sessions"], + "members":{ + "sessions":{ + "shape":"SessionSummaryList", + "documentation":"

    The list of session summaries.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "ListViewsRequest":{ + "type":"structure", + "members":{ + "type":{ + "shape":"ViewType", + "documentation":"

    Return only views of this ownership category.

    " + }, + "maxResults":{ + "shape":"ListViewsRequestMaxResultsInteger", + "documentation":"

    The maximum number of views to return per page.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results.

    " + } + } + }, + "ListViewsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListViewsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"ViewSummaryList", + "documentation":"

    The list of view summaries.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "LogMetadata":{ + "type":"structure", + "members":{ + "attributes":{"shape":"LogMetadataAttributeMap"} + }, + "documentation":"

    One LOGS query selector block on a node. The attributes map's keys are AND'd; each selects with col = value. Deliberately RAW/un-normalized so the selector matches the store, not the node's merged identity.

    " + }, + "LogMetadataAttributeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    One LOGS query-selector block: EXACT store column -> raw SCALAR value (mirroring the scalar MetadataAttributeMap). Keyed by the store column that carries the value (e.g. resource.attributes['service.name'], attributes['aws.local.service'], @logGroupName) so the selector matches the emitted signal. A dimension seen under several values (a service under two namespaces, several log groups) becomes several blocks with the same columns and different values, which the console ORs. Dedicated to the LOGS selector so its cap evolves independently of the metric attribute map and the TRACES map. Selector caps are deliberately DISTINCT from the metric caps.

    ", + "max":10, + "min":0 + }, + "LogMetadataList":{ + "type":"list", + "member":{"shape":"LogMetadata"}, + "documentation":"

    Per-node log query selectors; the list ORs across blocks (e.g. an OTLP block vs a CloudWatch- VENDED block). Bound is a payload cap, not a selection rule.

    ", + "max":10, + "min":0 + }, + "Long":{ + "type":"long", + "box":true + }, + "Metadata":{ + "type":"structure", + "members":{ + "metrics":{ + "shape":"MetricMetadataList", + "documentation":"

    The metrics observed on the element.

    " + }, + "semantics":{ + "shape":"NodeSemantics", + "documentation":"

    Semantic description of the node. Absent on an edge, because semantics describe a service rather than a relationship.

    " + }, + "logs":{ + "shape":"LogMetadataList", + "documentation":"

    Per-signal LOGS query selectors: a LIST of blocks the console ORs, each an AND of exact store column -> raw values. Node-level (edges carry only traces). Populated when the request sets includeMetadata; derived labels (logSourceType) are added by the service projection, not stored here.

    " + }, + "traces":{ + "shape":"TraceMetadataList", + "documentation":"

    Per-signal TRACES query selectors (same block shape as logs). Present on both node and edge metadata. serviceName is derived at the service projection, not stored here.

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

    Descriptive information about a context graph node or edge, as opposed to its identity and structure. Returned only when the request sets includeMetadata.

    " + }, + "MetadataAttributeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    Per-metric qualifying attributes carried on MetricMetadata. A dedicated shape (not the shared IntelligenceAttributeMap) so its length cap can be tuned independently.

    ", + "max":50, + "min":0 + }, + "MetricMetadata":{ + "type":"structure", + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The metric name as emitted, such as "Duration".

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    DEPRECATED: read attributes["service.namespace"] instead. Retained (deprecated) for backward compatibility with existing consumers; will be removed once they migrate. The logical service grouping the metric belongs to.

    ", + "deprecated":true, + "deprecatedMessage":"Use attributes['service.namespace']; retained for backward compatibility.", + "deprecatedSince":"2026-08-19" + }, + "preferredStat":{ + "shape":"String", + "documentation":"

    The statistic to chart or alarm on, such as "p99" or "Sum". Free-form and frequently absent.

    " + }, + "metricType":{ + "shape":"String", + "documentation":"

    OTel metric kind: "gauge", "sum", "histogram", "exponential_histogram", or "summary" (CloudWatch-vended metrics carry the same kinds). Absent when the producer did not report one.

    " + }, + "attributes":{ + "shape":"MetadataAttributeMap", + "documentation":"

    Per-metric qualifying attributes the console uses to query this metric's telemetry. These are the RAW, store-matching values keyed by their OTel names ("service.name", "service.namespace", "cloud.provider", "cloud.account.id", "cloud.region", "instrumentation_scope") — deliberately NOT the node's normalized/merged identity, so the query selectors match the emitted series. A merged node can carry different values per metric, which is why they live here rather than on the node.

    " + }, + "semantics":{ + "shape":"MetricSemantics", + "documentation":"

    What the metric means and the unit it is reported in.

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

    A single metric observed on a context graph node.

    " + }, + "MetricMetadataList":{ + "type":"list", + "member":{"shape":"MetricMetadata"}, + "documentation":"

    Metrics observed on a context graph node. When more are observed than the cap, the backend keeps RED/OTel-semconv names (http/rpc server+client, span-metrics) ahead of the alphabetical remainder, so the metrics the console charts survive. Must match the backend MetricMetadataList cap or entries the backend kept get re-truncated here at the frontend boundary.

    ", + "max":50, + "min":0 + }, + "MetricSemantics":{ + "type":"structure", + "members":{ + "description":{ + "shape":"String", + "documentation":"

    Human-readable description of what the metric measures.

    " + }, + "unit":{ + "shape":"String", + "documentation":"

    The unit the metric is reported in.

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

    The meaning and unit of a single metric.

    " + }, + "NextToken":{ + "type":"string", + "documentation":"

    A token to retrieve the next page of results.

    ", + "max":2048, + "min":1 + }, + "NoData":{ + "type":"structure", + "required":["treatAs"], + "members":{ + "treatAs":{ + "shape":"AlertState", + "documentation":"

    The state to report when an evaluation produces no data.

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

    Configures how the alert reacts when an evaluation produces no data. {@code treatAs} carries the resulting state; defaults to {@code NODATA} when omitted.

    " + }, + "Node":{ + "type":"structure", + "members":{ + "nodeId":{ + "shape":"ContextGraphId", + "documentation":"

    The unique identifier of the node within the context graph.

    " + }, + "nodeType":{ + "shape":"NodeType", + "documentation":"

    Whether the node is a service, a resource, or a remote service.

    " + }, + "name":{ + "shape":"ContextGraphName", + "documentation":"

    The primary display name of the node.

    " + }, + "alternateNames":{ + "shape":"StringSet", + "documentation":"

    Other names this node was observed under. A node that merged across sources reports one resolved name, and the names it was merged away from appear here.

    " + }, + "tags":{ + "shape":"IntelligenceTagMap", + "documentation":"

    The tags observed on the underlying resource.

    " + }, + "nodeProperties":{ + "shape":"NodeProperties", + "documentation":"

    Identity attributes promoted out of the flat attribute map onto typed members.

    " + }, + "telemetryAttributes":{ + "shape":"ContextGraphAttributeMap", + "documentation":"

    The node's OpenTelemetry (OTel) attributes, as emitted by telemetry — the raw values, as opposed to the normalized nodeProperties. A key promoted onto a nodeProperties member is removed here, so no value appears twice.

    " + }, + "operationDetails":{ + "shape":"OperationDetails", + "documentation":"

    The operations observed on this node, keyed by operation name. Each value lists the dimension sets that identify the metric series for that operation.

    " + }, + "signalTypes":{ + "shape":"SignalSet", + "documentation":"

    The kinds of telemetry signal observed on this node.

    " + }, + "sources":{ + "shape":"SourceSet", + "documentation":"

    The discovery sources that contributed this node.

    " + }, + "metadata":{ + "shape":"Metadata", + "documentation":"

    Descriptive metadata about the node. Present only when the request sets includeMetadata.

    " + }, + "firstObservedAt":{ + "shape":"Timestamp", + "documentation":"

    When this node was first observed (UTC), at minute granularity. For a node that merged across sources, this is the earliest value any source reported.

    " + }, + "lastObservedAt":{ + "shape":"Timestamp", + "documentation":"

    When this node was most recently observed (UTC), at minute granularity. For a node that merged across sources, this is the latest value any source reported.

    " + }, + "edges":{ + "shape":"EdgeList", + "documentation":"

    Outbound edges originating from this node. Each edge carries its from.

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

    A node in the context graph representing a service, resource, or remote service.

    " + }, + "NodeCategory":{ + "type":"string", + "documentation":"

    Coarse classification of what a node is. Orthogonal to NodeType, which says whether the node is a service, a resource, or a remote service. Absent on most nodes today because few producers emit the source attribute.

    ", + "enum":[ + "GEN_AI_AGENT", + "GEN_AI_MODEL", + "DATABASE", + "MESSAGING_QUEUE", + "COMPUTE", + "STORAGE", + "NETWORK" + ] + }, + "NodeCategorySet":{ + "type":"list", + "member":{"shape":"NodeCategory"}, + "documentation":"

    Set of node categories to filter a context graph query by.

    ", + "max":4, + "min":0 + }, + "NodeFilters":{ + "type":"structure", + "members":{ + "nodeId":{ + "shape":"ContextGraphId", + "documentation":"

    Match only the node with this identifier.

    " + }, + "nodeType":{ + "shape":"NodeType", + "documentation":"

    Match only nodes of this type.

    " + }, + "name":{ + "shape":"ContextGraphName", + "documentation":"

    Match only nodes with this name.

    " + }, + "tags":{ + "shape":"KeyFilterList", + "documentation":"

    Match nodes by the tags on the underlying resource.

    " + }, + "telemetryAttributes":{ + "shape":"KeyFilterList", + "documentation":"

    Match nodes by their OpenTelemetry (OTel) telemetry attributes.

    " + }, + "region":{ + "shape":"StringSet", + "documentation":"

    Match nodes in any of these regions.

    " + }, + "cloudProvider":{ + "shape":"StringSet", + "documentation":"

    Match nodes on any of these cloud providers.

    " + }, + "sourceAccountId":{ + "shape":"StringSet", + "documentation":"

    Match nodes discovered from telemetry produced by any of these accounts.

    " + }, + "namespace":{ + "shape":"StringSet", + "documentation":"

    Match nodes in any of these logical service groupings.

    " + }, + "category":{ + "shape":"NodeCategorySet", + "documentation":"

    Match nodes of any of these categories.

    " + }, + "stage":{ + "shape":"StringSet", + "documentation":"

    Match nodes observed in any of these deployment environments.

    " + }, + "sources":{ + "shape":"SourceSet", + "documentation":"

    Match nodes contributed by any of these discovery sources.

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

    Criteria for selecting nodes in a context graph query.

    " + }, + "NodeList":{ + "type":"list", + "member":{"shape":"Node"}, + "documentation":"

    List of context graph nodes returned by GetContextGraph. Bounded to match GetContextGraphInput.maxResults cap.

    ", + "max":1000, + "min":0 + }, + "NodeProperties":{ + "type":"structure", + "members":{ + "region":{ + "shape":"String", + "documentation":"

    The region the node runs in. Falls back to the region the telemetry was ingested from when the node does not report one.

    " + }, + "cloudProvider":{ + "shape":"String", + "documentation":"

    The cloud provider hosting the node, resolved from the reported provider, platform, or vendor namespace, and defaulting to "aws".

    " + }, + "sourceAccountId":{ + "shape":"String", + "documentation":"

    The account that produced the telemetry this node was discovered from.

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    The logical service grouping the node belongs to. This is not a metric namespace.

    " + }, + "category":{ + "shape":"NodeCategory", + "documentation":"

    What kind of thing the node is, coarser than nodeType.

    " + }, + "stage":{ + "shape":"String", + "documentation":"

    The node's deployment environment. A node may be observed in several; this is the highest-precedence one. Match any of them with NodeFilters.stage.

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

    Node identity attributes promoted out of the flat attribute map onto typed members. The first four are part of the node's merge key, so a node that merged across sources reports one resolved value for each.

    " + }, + "NodeSemantics":{ + "type":"structure", + "members":{ + "purpose":{ + "shape":"String", + "documentation":"

    What the service does.

    " + }, + "language":{ + "shape":"String", + "documentation":"

    The primary programming language the service is written in.

    " + }, + "framework":{ + "shape":"String", + "documentation":"

    The application framework the service is built on.

    " + }, + "kind":{ + "shape":"String", + "documentation":"

    The kind of workload the service is.

    " + }, + "repository":{ + "shape":"String", + "documentation":"

    The source repository the service is built from.

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

    Semantic description of the service a context graph node represents.

    " + }, + "NodeType":{ + "type":"string", + "documentation":"

    Context graph node types.

    ", + "enum":[ + "SERVICE", + "RESOURCE", + "REMOTE_SERVICE" + ] + }, + "NotificationRule":{ + "type":"structure", + "required":[ + "trigger", + "target" + ], + "members":{ + "trigger":{ + "shape":"NotificationTrigger", + "documentation":"

    The conditions that trigger this notification rule.

    " + }, + "target":{ + "shape":"NotificationTarget", + "documentation":"

    The destination for notifications from this rule.

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

    Single notification rule: which transitions trigger this rule and where the resulting notification should be sent.

    " + }, + "NotificationRuleList":{ + "type":"list", + "member":{"shape":"NotificationRule"}, + "documentation":"

    List of notification rules. On UpdateAlert an omitted list leaves the stored rules unchanged, while an empty list clears them all (see notificationRules).

    ", + "max":5, + "min":0 + }, + "NotificationStatus":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, + "NotificationTarget":{ + "type":"structure", + "required":[ + "type", + "arn" + ], + "members":{ + "type":{ + "shape":"NotificationTargetType", + "documentation":"

    The type of notification target.

    " + }, + "arn":{ + "shape":"NotificationTargetArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the notification target. For {@code slack} and {@code pagerduty}, an integration ARN as returned by {@code ListIntegrations}.

    " + }, + "metadata":{ + "shape":"NotificationTargetMetadataMap", + "documentation":"

    Additional target-specific metadata.

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

    The destination for a notification.

    " + }, + "NotificationTargetArnString":{ + "type":"string", + "documentation":"

    An Amazon Resource Name (ARN).

    ", + "max":1024, + "min":1, + "pattern":"arn:.+" + }, + "NotificationTargetMetadataMap":{ + "type":"map", + "key":{"shape":"NotificationTargetMetadataMapKeyString"}, + "value":{"shape":"NotificationTargetMetadataMapValueString"}, + "documentation":"

    Map of target-specific metadata keys to values.

    ", + "max":20, + "min":0 + }, + "NotificationTargetMetadataMapKeyString":{ + "type":"string", + "max":128, + "min":1 + }, + "NotificationTargetMetadataMapValueString":{ + "type":"string", + "max":1024, + "min":0 + }, + "NotificationTargetType":{ + "type":"string", + "documentation":"

    Supported notification target type.

    ", + "enum":[ + "sns", + "slack", + "pagerduty" + ] + }, + "NotificationTrigger":{ + "type":"structure", + "members":{ + "stateValues":{ + "shape":"AlertStateList", + "documentation":"

    Alert state(s) that trigger this rule. Empty / omitted = any state.

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

    Trigger conditions for a notification rule. {@code stateValues} entries combine with OR semantics; empty / omitted = any state.

    " + }, + "OAuthClientCredential":{ + "type":"structure", + "required":[ + "clientId", + "clientSecret" + ], + "members":{ + "clientId":{ + "shape":"String", + "documentation":"

    The OAuth 2.0 client identifier registered with the external system.

    " + }, + "clientSecret":{ + "shape":"SensitiveString", + "documentation":"

    The OAuth 2.0 client secret that pairs with the client identifier.

    " + }, + "providerId":{ + "shape":"String", + "documentation":"

    The identifier of the OAuth provider that issued the client credentials.

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

    Credentials for an OAuth 2.0 client-credentials grant used to authenticate an integration with its external system.

    ", + "sensitive":true + }, + "OAuthCodeCredential":{ + "type":"structure", + "required":["authCode"], + "members":{ + "authCode":{ + "shape":"OAuthCodeCredentialAuthCodeString", + "documentation":"

    The OAuth 2.0 authorization code returned by the external system's authorization endpoint.

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

    Credentials for an OAuth 2.0 authorization-code grant, supplied when completing the authorization of an integration.

    ", + "sensitive":true + }, + "OAuthCodeCredentialAuthCodeString":{ + "type":"string", + "max":4096, + "min":1 + }, + "OmniDashboard":{ + "type":"structure", + "required":[ + "dashboardId", + "arn", + "name", + "body", + "createdBy", + "createdAt", + "updatedAt" + ], + "members":{ + "dashboardId":{ + "shape":"DashboardId", + "documentation":"

    The unique ID of the dashboard.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the dashboard.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the dashboard.

    " + }, + "body":{ + "shape":"String", + "documentation":"

    The dashboard definition.

    " + }, + "createdBy":{ + "shape":"String", + "documentation":"

    The principal that created the dashboard.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the dashboard.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags associated with the dashboard.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dashboard was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dashboard was last updated.

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

    A dashboard within a space, including its body.

    " + }, + "OmniDashboardSummary":{ + "type":"structure", + "required":[ + "dashboardId", + "arn", + "name", + "createdBy", + "createdAt", + "updatedAt" + ], + "members":{ + "dashboardId":{ + "shape":"DashboardId", + "documentation":"

    The unique ID of the dashboard.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the dashboard.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the dashboard.

    " + }, + "createdBy":{ + "shape":"String", + "documentation":"

    The principal that created the dashboard.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the dashboard.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags associated with the dashboard.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dashboard was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dashboard was last updated.

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

    Summary of a dashboard. Call GetOmniDashboard for the full dashboard.

    " + }, + "OmniDashboardSummaryList":{ + "type":"list", + "member":{"shape":"OmniDashboardSummary"}, + "documentation":"

    List of dashboard summaries.

    " + }, + "OperationDetails":{ + "type":"map", + "key":{"shape":"OperationName"}, + "value":{"shape":"OperationIdentifierSets"}, + "documentation":"

    Operations on a Node, keyed by operation name; value = list of identifier sets.

    ", + "max":50, + "min":0 + }, + "OperationIdentifierKey":{ + "type":"string", + "documentation":"

    OTel dimension key on an operation identifier set (e.g. "http.request.method").

    ", + "max":256, + "min":1 + }, + "OperationIdentifierSet":{ + "type":"map", + "key":{"shape":"OperationIdentifierKey"}, + "value":{"shape":"OperationIdentifierValue"}, + "documentation":"

    One OTel dimension set identifying a metric series for an operation.

    ", + "max":50, + "min":0 + }, + "OperationIdentifierSets":{ + "type":"list", + "member":{"shape":"OperationIdentifierSet"}, + "max":200, + "min":0 + }, + "OperationIdentifierValue":{ + "type":"string", + "documentation":"

    OTel dimension value on an operation identifier set.

    ", + "max":1024, + "min":0 + }, + "OperationName":{ + "type":"string", + "documentation":"

    Operation name on a context graph node (typically OTel span.name).

    ", + "max":256, + "min":1 + }, + "OrganizationAccessGrant":{ + "type":"structure", + "required":[ + "grantId", + "grantArn", + "domainId", + "principal", + "permission", + "grantType", + "createdBy", + "createdAt", + "updatedAt" + ], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The unique ID of the access grant.

    " + }, + "grantArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the access grant.

    " + }, + "name":{ + "shape":"OrganizationAccessGrantNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain the grant belongs to.

    " + }, + "principal":{ + "shape":"OrganizationAccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"OrganizationGrantPermission", + "documentation":"

    The permission granted.

    " + }, + "grantType":{ + "shape":"AccessGrantType", + "documentation":"

    Who manages the grant.

    " + }, + "createdBy":{ + "shape":"String", + "documentation":"

    The principal that created the grant.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the grant was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the grant was last updated.

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

    An organization-scoped access grant.

    " + }, + "OrganizationAccessGrantNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "OrganizationAccessGrantPrincipal":{ + "type":"structure", + "required":["principalType"], + "members":{ + "principalType":{ + "shape":"OrganizationGrantPrincipalType", + "documentation":"

    The type of principal receiving the grant.

    " + }, + "principalId":{ + "shape":"OrganizationPrincipalId", + "documentation":"

    The ID of the principal receiving the grant.

    " + }, + "principalAttributes":{ + "shape":"AccessGrantPrincipalAttributeList", + "documentation":"

    Attribute conditions for attribute-based access. When provided, the grant targets any principal matching all specified conditions. Supported only for IDC_USER principals.

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

    The principal receiving an organization-level domain access grant. Specify principalId, principalAttributes, or both.

    " + }, + "OrganizationAccessGrantSummary":{ + "type":"structure", + "required":[ + "grantId", + "grantArn", + "domainId", + "principal", + "permission", + "grantType", + "createdAt", + "updatedAt" + ], + "members":{ + "grantId":{ + "shape":"GrantId", + "documentation":"

    The unique ID of the access grant.

    " + }, + "grantArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the access grant.

    " + }, + "name":{ + "shape":"OrganizationAccessGrantSummaryNameString", + "documentation":"

    A name that identifies the access grant.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain the grant belongs to.

    " + }, + "principal":{ + "shape":"OrganizationAccessGrantPrincipal", + "documentation":"

    The principal receiving the grant.

    " + }, + "permission":{ + "shape":"OrganizationGrantPermission", + "documentation":"

    The permission granted.

    " + }, + "grantType":{ + "shape":"AccessGrantType", + "documentation":"

    Who manages the grant.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the access grant was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the access grant was last updated.

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

    Summary of an organization access grant. Call GetDomainAccessGrantForOrganization for the full grant.

    " + }, + "OrganizationAccessGrantSummaryList":{ + "type":"list", + "member":{"shape":"OrganizationAccessGrantSummary"}, + "documentation":"

    List of organization access grant summaries.

    " + }, + "OrganizationAccessGrantSummaryNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "OrganizationCredentialType":{ + "type":"string", + "documentation":"

    Selects which member-account credential GetSpaceCredentialsForOrganization returns.

    ", + "enum":["SPACE_OPERATION"] + }, + "OrganizationDomain":{ + "type":"structure", + "required":[ + "domainId", + "domainArn", + "domainEndpointUrl", + "organizationId", + "ownerAccountId", + "identityProviders", + "region", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the organization domain.

    " + }, + "domainArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the organization domain.

    " + }, + "name":{ + "shape":"OrganizationDomainNameString", + "documentation":"

    A name that identifies the organization domain.

    " + }, + "domainEndpointUrl":{ + "shape":"String", + "documentation":"

    The HTTPS endpoint URL for accessing the organization domain.

    " + }, + "customEndpointUrls":{ + "shape":"StringList", + "documentation":"

    Additional endpoint URLs derived from the domain name.

    " + }, + "organizationId":{ + "shape":"String", + "documentation":"

    The ID of the AWS Organization that owns the domain.

    " + }, + "ownerAccountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID that owns the organization domain.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers configured for the organization domain.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the organization domain.

    " + }, + "identityCenterApplicationArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the Identity Center application. Absent for IAM-only domains.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The Region where this organization domain was created.

    " + }, + "status":{ + "shape":"DomainStatus", + "documentation":"

    Current status of the organization domain.

    " + }, + "domainAccessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of the customer-provided IAM role in the management account used for domain access.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization domain was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization domain was last updated.

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

    Detailed information about an organization domain.

    " + }, + "OrganizationDomainNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "OrganizationGrantPermission":{ + "type":"string", + "documentation":"

    Permission level for an organization-scoped grant.

    ", + "enum":["ADMIN"] + }, + "OrganizationGrantPrincipalType":{ + "type":"string", + "documentation":"

    Principal types valid for organization-level domain access grants.

    ", + "enum":[ + "IDC_USER", + "IDC_GROUP", + "IAM_USER", + "IAM_ROLE", + "IAM_ROOT" + ] + }, + "OrganizationPrincipalId":{ + "type":"string", + "documentation":"

    Principal receiving an organization-level domain access grant. One field spans every OrganizationGrantPrincipalType: an IAM principal ARN (IAM_USER / IAM_ROLE / IAM_ROOT) or an IdC UUID (IDC_USER / IDC_GROUP). Must begin with an alphanumeric character.

    ", + "max":2048, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9:/_+=,.@-]*" + }, + "PaginationToken":{ + "type":"string", + "documentation":"

    Pagination token for context graph and insights.

    ", + "max":2048, + "min":1 + }, + "PartialResults":{ + "type":"structure", + "members":{ + "partialResultsDetected":{ + "shape":"Boolean", + "documentation":"

    True when the query returned partial results (some data could not be read).

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

    Indicates whether a query returned partial results.

    " + }, + "PrincipalId":{ + "type":"string", + "documentation":"

    Principal receiving a grant. One field spans every AccessGrantPrincipalType: an IAM principal ARN (IAM_USER / IAM_ROLE / IAM_ROOT), an IdC UUID (IDC_USER / IDC_GROUP), or a service-defined id for ACCESS_PROFILE, ALERT, or AGENT. Must begin with an alphanumeric character.

    Set to the reserved value ALL (case-sensitive) to apply the grant to every ALERT principal in the space. ALL is supported only for the ALERT principal type, and only on CUSTOM grants whose single action is AssumeAccessProfile.

    ", + "max":2048, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9:/_+=,.@-]*" + }, + "PrincipalSearchResult":{ + "type":"structure", + "required":[ + "principalId", + "principalType", + "displayName" + ], + "members":{ + "principalId":{ + "shape":"PrincipalId", + "documentation":"

    The unique ID of the principal.

    " + }, + "principalType":{ + "shape":"PrincipalType", + "documentation":"

    Whether the principal is a user or a group.

    " + }, + "displayName":{ + "shape":"String", + "documentation":"

    The display name of the principal.

    " + }, + "userName":{ + "shape":"String", + "documentation":"

    The user name of the principal. Present for users only.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    An optional description of the principal.

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

    A user or group matched by SearchPrincipals.

    " + }, + "PrincipalSearchResultList":{ + "type":"list", + "member":{"shape":"PrincipalSearchResult"}, + "documentation":"

    List of principal search results.

    " + }, + "PrincipalType":{ + "type":"string", + "documentation":"

    Whether a principal is a user or a group.

    ", + "enum":[ + "USER", + "GROUP" + ] + }, + "ProfileId":{ + "type":"string", + "documentation":"

    Access profile identifier — assigned when the profile is created.

    ", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "PutIntelligenceConfigurationInput":{ + "type":"structure", + "members":{ + "kmsKeyArn":{ + "shape":"IntelligenceKmsKeyArn", + "documentation":"

    Optional KMS key ARN to configure customer-managed encryption for anomaly data.

    " + }, + "removeKmsKey":{ + "shape":"Boolean", + "documentation":"

    Set to true to disassociate the configured KMS key. Mutually exclusive with kmsKeyArn; the service returns ValidationException if both are provided.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Idempotency token for safe retries. Repeating a request with the same token applies the update at most once instead of reprocessing it.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    The request for updating the intelligence configuration of the calling account.

    " + }, + "PutIntelligenceConfigurationOutput":{ + "type":"structure", + "required":[ + "accountId", + "updatedAt", + "createdAt" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID this configuration applies to.

    " + }, + "kmsKeyArn":{ + "shape":"IntelligenceKmsKeyArn", + "documentation":"

    The currently active KMS key ARN for customer-managed encryption, if configured.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    ISO-8601 timestamp of the last update.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    ISO-8601 timestamp of initial creation.

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

    The intelligence configuration for the calling account after the update.

    " + }, + "QueryLanguage":{ + "type":"string", + "documentation":"

    Query language for an alert rule expression.

    ", + "enum":[ + "SQL", + "PROMQL" + ] + }, + "QueryStatistics":{ + "type":"structure", + "members":{ + "bytesScanned":{ + "shape":"Double", + "documentation":"

    The number of bytes scanned by the query.

    " + }, + "percentComplete":{ + "shape":"Integer", + "documentation":"

    The percentage of the query that has completed.

    " + }, + "recordsScanned":{ + "shape":"Long", + "documentation":"

    The total number of records scanned.

    " + }, + "recordsMatched":{ + "shape":"Long", + "documentation":"

    The number of records that matched the query criteria.

    " + }, + "partialResults":{ + "shape":"PartialResults", + "documentation":"

    Information about whether the query returned partial results.

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

    Statistics about a telemetry query execution.

    " + }, + "QueryStatus":{ + "type":"string", + "documentation":"

    The current status of a telemetry query.

    ", + "enum":[ + "Running", + "Failed", + "Complete", + "Cancelled" + ] + }, + "ResourceArnList":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    List of resource ARNs or ARN patterns.

    ", + "max":5, + "min":0 + }, + "ResourceNotFoundException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource that could not be found. Not always present.

    " + }, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource that could not be found. Not always present.

    " + }, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code associated with the failure.

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

    The specified resource does not exist.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "ResourceScope":{ + "type":"structure", + "required":["resourceType"], + "members":{ + "resourceType":{ + "shape":"String", + "documentation":"

    Resource type name (e.g., "DataSet", "OmniDashboard").

    " + }, + "resourceArns":{ + "shape":"ResourceArnList", + "documentation":"

    Specific resource ARNs or ARN patterns. When set, actions are limited to these resources. When absent, defaults to "*".

    " + }, + "tags":{ + "shape":"ResourceScopeTagMap", + "documentation":"

    Tag-based conditions for dynamic resource scoping. Access applies only to resources carrying all of the specified tag key/value pairs.

    " + }, + "signalTypes":{ + "shape":"SignalTypeList", + "documentation":"

    Signal types this scope's row filtering applies to. Required when rowScopeGroups is set.

    " + }, + "rowScopeGroups":{ + "shape":"RowScopeGroupList", + "documentation":"

    Row-level filters for this scope, as an OR of AND-groups: a row is visible when it matches every filter in any one group. Requires signalTypes.

    Row filters are additive across a principal's matching grants. A signal type with no matching group is unrestricted, and when rowScopeGroups is omitted all rows are visible for all signal types.

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

    A single resource scope entry within an AccessGrant. Associates a resource type with optional ARN patterns, tag conditions, and row-level filters.

    " + }, + "ResourceScopeList":{ + "type":"list", + "member":{"shape":"ResourceScope"}, + "documentation":"

    List of resource scopes.

    ", + "max":10, + "min":0 + }, + "ResourceScopeTagMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    Map of tag keys to values for resource scoping.

    ", + "max":3, + "min":0 + }, + "Row":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "RowList":{ + "type":"list", + "member":{"shape":"Row"} + }, + "RowScope":{ + "type":"structure", + "required":[ + "field", + "operator", + "values" + ], + "members":{ + "field":{ + "shape":"RowScopeFieldString", + "documentation":"

    The field (column) the allowlist applies to (e.g., "serviceName", "accountId").

    " + }, + "operator":{ + "shape":"RowScopeOperator", + "documentation":"

    Match operator applied to this filter's values.

    " + }, + "values":{ + "shape":"RowScopeValueList", + "documentation":"

    The values the field is matched against.

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

    A single additive row-level filter on an AccessGrant. A row is visible when its value for the given field matches the filter's values. Row filters are additive: the visible rows are the union of all row filters across a principal's matching grants.

    " + }, + "RowScopeFieldString":{ + "type":"string", + "max":256, + "min":1 + }, + "RowScopeGroup":{ + "type":"list", + "member":{"shape":"RowScope"}, + "documentation":"

    A group of row filters that must all match. A row satisfies the group only when it matches every filter in it.

    ", + "max":20, + "min":1 + }, + "RowScopeGroupList":{ + "type":"list", + "member":{"shape":"RowScopeGroup"}, + "documentation":"

    Row filters as an OR of one or more RowScopeGroups: a row is visible when it matches every filter in any one group. Row filters remain additive across a principal's matching grants.

    ", + "max":20, + "min":1 + }, + "RowScopeOperator":{ + "type":"string", + "documentation":"

    Match operator for a row-scope filter. Only IN is supported.

    ", + "enum":["IN"] + }, + "RowScopeValue":{ + "type":"string", + "documentation":"

    A single allowlist value for a RowScope field.

    ", + "max":256, + "min":1 + }, + "RowScopeValueList":{ + "type":"list", + "member":{"shape":"RowScopeValue"}, + "documentation":"

    The values for a single RowScope field. Duplicates are not permitted.

    ", + "max":100, + "min":1 + }, + "Rule":{ + "type":"structure", + "members":{ + "telemetryRule":{ + "shape":"TelemetryRule", + "documentation":"

    The telemetry-based rule definition.

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

    Top-level rule definition.

    {@code telemetryRule} members are optional at the Smithy level to support PATCH semantics on UpdateAlert (send only the sub-blocks you want to change). On CreateAlert, presence is enforced by the service-side validator.

    ", + "union":true + }, + "Scope":{ + "type":"string", + "documentation":"

    Whether an integration is account-scoped (customer-created) or organization-scoped (created by an org-enablement rule on behalf of the destination account). Mirrors the {@code Scope} discriminator used by CloudWatch Centralization / Observability Admin.

    ", + "enum":[ + "ACCOUNT", + "ORGANIZATION" + ] + }, + "ScopedActionName":{ + "type":"string", + "documentation":"

    A single scoped action in "vendor-code:Action" form (e.g. "bedrock:InvokeModel"). Wildcards are not permitted.

    ", + "max":256, + "min":3, + "pattern":"[a-z0-9][a-z0-9-]*:[A-Za-z][A-Za-z0-9]*" + }, + "ScopedActionNameList":{ + "type":"list", + "member":{"shape":"ScopedActionName"}, + "documentation":"

    The actions for a ScopedActions entry (1-50 entries), each "vendor-code:Action".

    ", + "max":50, + "min":1 + }, + "ScopedActions":{ + "type":"structure", + "required":["actions"], + "members":{ + "actions":{ + "shape":"ScopedActionNameList", + "documentation":"

    The actions this group applies to.

    " + }, + "resources":{ + "shape":"ResourceScopeList", + "documentation":"

    Optional resource scopes constraining these actions to specific resources.

    " + }, + "contextConditions":{ + "shape":"ContextConditionsMap", + "documentation":"

    Optional context conditions for fine-grained access control on these actions.

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

    A group of actions within an access grant, together with the resource scopes and context conditions that apply to exactly those actions.

    " + }, + "ScopedActionsList":{ + "type":"list", + "member":{"shape":"ScopedActions"}, + "documentation":"

    Groups of scoped actions within an access grant.

    ", + "max":20, + "min":0 + }, + "SearchPrincipalsInput":{ + "type":"structure", + "required":[ + "domainId", + "searchQuery" + ], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain to search within.

    " + }, + "searchQuery":{ + "shape":"SearchPrincipalsInputSearchQueryString", + "documentation":"

    A search term to match against user names, display names, and IDs. Pass * to list all principals. Maximum 128 characters.

    " + }, + "maxResults":{ + "shape":"SearchPrincipalsInputMaxResultsInteger", + "documentation":"

    The maximum number of results to return. Defaults to 10. Valid only when searchQuery is *; other searches reject this parameter and return at most 10 results.

    " + }, + "nextToken":{ + "shape":"SearchPrincipalsNextToken", + "documentation":"

    A token to retrieve the next page of results. Valid only when searchQuery is *; other searches do not paginate and reject this parameter. Tokens expire after 24 hours.

    " + } + } + }, + "SearchPrincipalsInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":50, + "min":1 + }, + "SearchPrincipalsInputSearchQueryString":{ + "type":"string", + "max":128, + "min":1 + }, + "SearchPrincipalsNextToken":{ + "type":"string", + "documentation":"

    SearchPrincipals nextToken. Uncapped — wraps two Identity Store tokens (up to 65,535 chars each) inside a KMS-encrypted envelope.

    " + }, + "SearchPrincipalsOutput":{ + "type":"structure", + "required":["results"], + "members":{ + "results":{ + "shape":"PrincipalSearchResultList", + "documentation":"

    The list of matching principals.

    " + }, + "nextToken":{ + "shape":"SearchPrincipalsNextToken", + "documentation":"

    A token to retrieve the next page of results, or null if there are no more results.

    " + } + } + }, + "SecretAccessKey":{ + "type":"string", + "documentation":"

    An AWS secret access key.

    ", + "sensitive":true + }, + "SensitiveString":{ + "type":"string", + "sensitive":true + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    A service quota was exceeded.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "SessionSummary":{ + "type":"structure", + "required":["sessionId"], + "members":{ + "sessionId":{ + "shape":"String", + "documentation":"

    The unique ID of the session.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the session was created.

    " + }, + "lastActivityAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of the most recent activity in the session.

    " + }, + "sessionName":{ + "shape":"SessionSummarySessionNameString", + "documentation":"

    The human-readable name of the session. Names under /aws/ are reserved for service integrations.

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

    Summary information about a query session, including its identifier, name, and activity timestamps.

    " + }, + "SessionSummaryList":{ + "type":"list", + "member":{"shape":"SessionSummary"} + }, + "SessionSummarySessionNameString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"([a-zA-Z0-9_-]+|/aws/[a-zA-Z0-9_-]+(/[a-zA-Z0-9_-]+)?)" + }, + "SessionToken":{ + "type":"string", + "documentation":"

    A session token (IdC or deep-link scoped). Sensitive: carries a bearer credential, so it is redacted from request logs and CloudTrail requestParameters.

    ", + "sensitive":true + }, + "Signal":{ + "type":"string", + "documentation":"

    Signal enum for context graph queries.

    ", + "enum":[ + "LOGS", + "METRICS", + "TRACES", + "CONFIG", + "UNKNOWN" + ] + }, + "SignalSet":{ + "type":"list", + "member":{"shape":"Signal"}, + "documentation":"

    Signal set for context graph queries.

    ", + "max":5, + "min":0 + }, + "SignalType":{ + "type":"string", + "documentation":"

    Telemetry signal type that row-scoped access control applies to.

    ", + "enum":[ + "LOGS", + "TRACES" + ] + }, + "SignalTypeList":{ + "type":"list", + "member":{"shape":"SignalType"}, + "documentation":"

    The set of telemetry signal types a row scope applies to.

    ", + "max":3, + "min":1 + }, + "Source":{ + "type":"string", + "documentation":"

    Data source enum for context graph queries.

    ", + "enum":[ + "VPC_FLOW_LOG", + "CLOUDTRAIL", + "IAM_POLICY", + "CODE_SEMANTICS", + "TELEMETRY", + "AZURE_VNET_FLOW_LOG", + "ELB_ACCESS_LOG", + "CLOUDFRONT_ACCESS_LOG", + "S3_ACCESS_LOG", + "WAF_ACCESS_LOG", + "AWS_INTEGRATION", + "CONFIG" + ] + }, + "SourceSet":{ + "type":"list", + "member":{"shape":"Source"}, + "documentation":"

    Source set for context graph queries.

    ", + "max":20, + "min":0 + }, + "Space":{ + "type":"structure", + "required":[ + "spaceId", + "name", + "spaceArn", + "region", + "ownerAccountId", + "dataAccessRoleArn", + "createdAt", + "updatedAt", + "status" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the space.

    " + }, + "spaceArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the space.

    " + }, + "domainArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the domain the space belongs to. Absent when the space is not associated with a domain, so callers must tolerate its absence.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The region where this space was created.

    " + }, + "ownerAccountId":{ + "shape":"AccountId", + "documentation":"

    AWS account ID that owns this space.

    " + }, + "dataAccessRoleArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the IAM role used for data access.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the space was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the space was last updated.

    " + }, + "agentCoreEvaluationRoleArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the IAM role used by AgentCore online evaluation. Absent when the space was created without one.

    " + }, + "status":{ + "shape":"SpaceStatus", + "documentation":"

    The status of the space.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Reason for the current space status.

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    How the space's data at rest is encrypted. Always populated: a space with no customer managed key reports encryptionStrategy AWS_OWNED and no kmsKeyArn.

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

    Detailed information about a space.

    " + }, + "SpaceCredentialRequestContext":{ + "type":"structure", + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The ID of an existing space to return credentials for.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the domain, when returning credentials for a target account that does not yet have a space.

    " + }, + "targetAccountId":{ + "shape":"AccountId", + "documentation":"

    The ID of the target member account. Required when domainId is set.

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

    Identifies what the credentials are for: either an existing space, or a target account in a domain. Specify spaceId, or both domainId and targetAccountId.

    " + }, + "SpaceId":{ + "type":"string", + "documentation":"

    Space identifier — a v4 UUID minted by the backend.

    ", + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "SpaceStatus":{ + "type":"string", + "documentation":"

    Status of a space.

    ", + "enum":[ + "ACTIVE", + "SUSPENDED", + "MOVING" + ] + }, + "SpaceSummary":{ + "type":"structure", + "required":[ + "spaceId", + "name", + "spaceArn", + "region", + "ownerAccountId", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    A name that identifies the space.

    " + }, + "spaceArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the space.

    " + }, + "domainArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the domain the space belongs to. Absent when the space is not associated with a domain, so callers must tolerate its absence.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The region where this space was created.

    " + }, + "ownerAccountId":{ + "shape":"AccountId", + "documentation":"

    AWS account ID that owns this space.

    " + }, + "status":{ + "shape":"SpaceStatus", + "documentation":"

    The status of the space.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Reason for the current space status.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the space was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the space was last updated.

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

    Summary of a space. Call GetSpace for the full space.

    " + }, + "SpaceSummaryList":{ + "type":"list", + "member":{"shape":"SpaceSummary"}, + "documentation":"

    List of space summaries.

    " + }, + "StartTelemetryQueryRequest":{ + "type":"structure", + "required":[ + "queryString", + "sessionId" + ], + "members":{ + "queryString":{ + "shape":"StartTelemetryQueryRequestQueryStringString", + "documentation":"

    The query string to execute.

    " + }, + "sessionId":{ + "shape":"StartTelemetryQueryRequestSessionIdString", + "documentation":"

    The unique ID of the session.

    " + } + } + }, + "StartTelemetryQueryRequestQueryStringString":{ + "type":"string", + "max":64000, + "min":1 + }, + "StartTelemetryQueryRequestSessionIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StartTelemetryQueryResponse":{ + "type":"structure", + "required":[ + "queryId", + "sessionId" + ], + "members":{ + "queryId":{ + "shape":"StartTelemetryQueryResponseQueryIdString", + "documentation":"

    The unique ID of the query.

    " + }, + "sessionId":{ + "shape":"StartTelemetryQueryResponseSessionIdString", + "documentation":"

    The unique ID of the session.

    " + } + } + }, + "StartTelemetryQueryResponseQueryIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StartTelemetryQueryResponseSessionIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StartTelemetryQuerySessionRequest":{ + "type":"structure", + "members":{ + "sessionName":{ + "shape":"StartTelemetryQuerySessionRequestSessionNameString", + "documentation":"

    A human-readable name for the session. Names under /aws/ are reserved for service integrations.

    " + } + } + }, + "StartTelemetryQuerySessionRequestSessionNameString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"([a-zA-Z0-9_-]+|/aws/[a-zA-Z0-9_-]+(/[a-zA-Z0-9_-]+)?)" + }, + "StartTelemetryQuerySessionResponse":{ + "type":"structure", + "required":["sessionId"], + "members":{ + "sessionId":{ + "shape":"StartTelemetryQuerySessionResponseSessionIdString", + "documentation":"

    The unique ID of the session.

    " + } + } + }, + "StartTelemetryQuerySessionResponseSessionIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StopTelemetryQueryRequest":{ + "type":"structure", + "required":["queryId"], + "members":{ + "queryId":{ + "shape":"StopTelemetryQueryRequestQueryIdString", + "documentation":"

    The unique ID of the query.

    " + } + } + }, + "StopTelemetryQueryRequestQueryIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StopTelemetryQueryResponse":{ + "type":"structure", + "members":{} + }, + "StopTelemetryQuerySessionRequest":{ + "type":"structure", + "required":["sessionId"], + "members":{ + "sessionId":{ + "shape":"StopTelemetryQuerySessionRequestSessionIdString", + "documentation":"

    The unique ID of the session.

    " + } + } + }, + "StopTelemetryQuerySessionRequestSessionIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "StopTelemetryQuerySessionResponse":{ + "type":"structure", + "members":{} + }, + "String":{"type":"string"}, + "StringList":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    Generic list of strings.

    " + }, + "StringMap":{ + "type":"map", + "key":{"shape":"StringMapKeyString"}, + "value":{"shape":"StringMapValueString"} + }, + "StringMapKeyString":{ + "type":"string", + "max":128, + "min":0 + }, + "StringMapValueString":{ + "type":"string", + "max":4096, + "min":0 + }, + "StringSet":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    String set for context graph queries.

    ", + "max":50, + "min":0 + }, + "TagKey":{ + "type":"string", + "documentation":"

    Tag key. Must be non-empty; AWS-standard maximum length. Constraining the key (rather than a bare String) rejects empty-key payloads at the edge with a 400 ValidationException instead of faulting downstream as a 500.

    ", + "max":128, + "min":1 + }, + "TagMap":{ + "type":"map", + "key":{"shape":"TagKey"}, + "value":{"shape":"TagValue"}, + "max":50, + "min":0 + }, + "TagValue":{ + "type":"string", + "documentation":"

    Tag value. AWS-standard maximum length; may be empty.

    ", + "max":256, + "min":0 + }, + "TelemetryRule":{ + "type":"structure", + "members":{ + "query":{ + "shape":"AlertRuleQuery", + "documentation":"

    The query expression to evaluate.

    " + }, + "condition":{ + "shape":"AlertCondition", + "documentation":"

    The condition that determines when the alert fires.

    " + }, + "evaluation":{ + "shape":"AlertEvaluation", + "documentation":"

    The evaluation cadence and durations.

    " + }, + "noData":{ + "shape":"NoData", + "documentation":"

    How the alert behaves when a query produces no data.

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

    Telemetry-based rule: what to query, how to evaluate the result, what condition makes it fire, and what to do on missing data.

    " + }, + "TelemetryType":{ + "type":"string", + "documentation":"

    The type of telemetry data.

    ", + "enum":[ + "LOGS", + "TRACES" + ] + }, + "ThresholdMode":{ + "type":"string", + "documentation":"

    How a threshold is applied to query results.

    ", + "enum":[ + "COUNT_OF_RESULTS", + "FIELD_VALUE" + ] + }, + "ThrottlingException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "retryAfterSeconds":{ + "shape":"Integer", + "documentation":"

    The number of seconds to wait before retrying the request. Not always present.

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

    The request was throttled due to exceeding the allowed request rate.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true, + "retryable":{"throttling":true} + }, + "Timestamp":{"type":"timestamp"}, + "TraceMetadata":{ + "type":"structure", + "members":{ + "attributes":{"shape":"TraceMetadataAttributeMap"} + }, + "documentation":"

    One TRACES query selector block on a node/edge (see LogMetadata).

    " + }, + "TraceMetadataAttributeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    TRACES counterpart of LogMetadataAttributeMap — a dedicated per-signal map so the two evolve independently (same scalar shape and cap today).

    ", + "max":10, + "min":0 + }, + "TraceMetadataList":{ + "type":"list", + "member":{"shape":"TraceMetadata"}, + "documentation":"

    Per-node/per-edge trace query selectors; the list ORs across blocks. Bound is a payload cap.

    ", + "max":10, + "min":0 + }, + "UpdateAccessProfileInput":{ + "type":"structure", + "required":[ + "spaceId", + "profileId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique ID of the access profile to update.

    " + }, + "name":{ + "shape":"AccessProfileName", + "documentation":"

    A new name for the access profile. Omit to leave unchanged.

    " + }, + "description":{ + "shape":"UpdateAccessProfileInputDescriptionString", + "documentation":"

    A new description of the access profile. Omit to leave unchanged.

    " + } + } + }, + "UpdateAccessProfileInputDescriptionString":{ + "type":"string", + "max":1024, + "min":0 + }, + "UpdateAccessProfileOutput":{ + "type":"structure", + "required":["accessProfile"], + "members":{ + "accessProfile":{ + "shape":"AccessProfile", + "documentation":"

    The access profile.

    " + } + } + }, + "UpdateAlertInput":{ + "type":"structure", + "required":[ + "spaceId", + "alertId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "alertId":{ + "shape":"AlertId", + "documentation":"

    The alert to update.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The ID of the access profile associated with the alert.

    " + }, + "name":{ + "shape":"UpdateAlertInputNameString", + "documentation":"

    A new display name for the alert. Omit to leave the name unchanged (apply-if-present / PATCH). Same constraints as CreateAlert.name; the name is not the alert's identity, so a rename never changes the alertId.

    " + }, + "description":{ + "shape":"UpdateAlertInputDescriptionString", + "documentation":"

    A new description of the alert. Omit to leave unchanged.

    " + }, + "rule":{ + "shape":"Rule", + "documentation":"

    The rule that defines how the alert is evaluated. Omit to leave unchanged. Each sub-block is replaced whole when present: {@code query}, {@code condition}, {@code evaluation} and {@code noData} are applied only when supplied, and within a supplied block an omitted optional member is cleared to unset (null/absent) rather than preserved from the stored alert or defaulted. See {@link AlertCondition} and {@link AlertEvaluation}.

    " + }, + "notificationsEnabled":{ + "shape":"Boolean", + "documentation":"

    Whether actions (notifications) are enabled for this alert. Omitted = leave existing value unchanged.

    " + }, + "notificationRules":{ + "shape":"NotificationRuleList", + "documentation":"

    Replaces the entire notification rule list when present; full-replace, not merge. Omitted = leave existing rules unchanged. An empty list clears all rules (the alert keeps evaluating; only notifications stop).

    " + } + } + }, + "UpdateAlertInputDescriptionString":{ + "type":"string", + "max":1024, + "min":0 + }, + "UpdateAlertInputNameString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "UpdateAlertOutput":{ + "type":"structure", + "members":{} + }, + "UpdateDomainForOrganizationInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The ID of the organization domain to update.

    " + }, + "name":{ + "shape":"UpdateDomainForOrganizationInputNameString", + "documentation":"

    A new name for the organization domain. Omit to leave unchanged. Must be 3-63 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers to configure for the domain. Omit to leave unchanged.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the domain. Omit to leave unchanged.

    " + } + } + }, + "UpdateDomainForOrganizationInputNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "UpdateDomainForOrganizationOutput":{ + "type":"structure", + "required":["organizationDomain"], + "members":{ + "organizationDomain":{ + "shape":"OrganizationDomain", + "documentation":"

    The details of the updated organization domain.

    " + } + } + }, + "UpdateDomainInput":{ + "type":"structure", + "required":["domainId"], + "members":{ + "domainId":{ + "shape":"DomainId", + "documentation":"

    The unique ID of the domain to update.

    " + }, + "name":{ + "shape":"UpdateDomainInputNameString", + "documentation":"

    A new name for the domain. Omit to leave unchanged. Must be 3-63 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "identityProviders":{ + "shape":"IdentityProviderList", + "documentation":"

    The identity providers to configure for the domain.

    " + }, + "identityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    Identity provider configuration for the domain.

    " + } + } + }, + "UpdateDomainInputNameString":{ + "type":"string", + "max":63, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "UpdateDomainOutput":{ + "type":"structure", + "required":["domain"], + "members":{ + "domain":{ + "shape":"Domain", + "documentation":"

    The details of the updated domain.

    " + } + } + }, + "UpdateIntegrationInput":{ + "type":"structure", + "required":["identifier"], + "members":{ + "identifier":{ + "shape":"IntegrationIdentifier", + "documentation":"

    Identifies the integration to update — exactly one of integrationId, integrationArn, or integrationName.

    " + }, + "credential":{ + "shape":"IntegrationCredential", + "documentation":"

    The replacement credential used to authenticate with the provider.

    " + }, + "integrationAttributes":{ + "shape":"StringMap", + "documentation":"

    The provider-specific attributes to associate with the integration.

    " + }, + "roleArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name of the IAM role assumed to access the integration.

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

    The request for updating an existing integration.

    " + }, + "UpdateIntegrationOutput":{ + "type":"structure", + "members":{ + "integration":{ + "shape":"Integration", + "documentation":"

    The details of the updated integration. This is the same object returned by GetIntegration and CreateIntegration. Populated on a successful update; absent only if the post-update read-back of the resource did not complete.

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

    The response from updating an integration.

    " + }, + "UpdateOmniDashboardInput":{ + "type":"structure", + "required":[ + "spaceId", + "dashboardId" + ], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space.

    " + }, + "dashboardId":{ + "shape":"DashboardId", + "documentation":"

    The unique ID of the dashboard.

    " + }, + "body":{ + "shape":"UpdateOmniDashboardInputBodyString", + "documentation":"

    The new dashboard definition, as a JSON document. Maximum 1 MiB. Omit to leave unchanged.

    " + }, + "name":{ + "shape":"UpdateOmniDashboardInputNameString", + "documentation":"

    A new name for the dashboard. Omit to leave unchanged.

    " + }, + "description":{ + "shape":"UpdateOmniDashboardInputDescriptionString", + "documentation":"

    A new description of the dashboard. Omit to leave unchanged.

    " + } + } + }, + "UpdateOmniDashboardInputBodyString":{ + "type":"string", + "max":1048576, + "min":1 + }, + "UpdateOmniDashboardInputDescriptionString":{ + "type":"string", + "max":1024, + "min":1 + }, + "UpdateOmniDashboardInputNameString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9_.@~()-]+" + }, + "UpdateOmniDashboardOutput":{ + "type":"structure", + "required":["omniDashboard"], + "members":{ + "omniDashboard":{ + "shape":"OmniDashboard", + "documentation":"

    The dashboard.

    " + } + } + }, + "UpdateSpaceInput":{ + "type":"structure", + "required":["spaceId"], + "members":{ + "spaceId":{ + "shape":"SpaceId", + "documentation":"

    The unique ID of the space to update.

    " + }, + "name":{ + "shape":"UpdateSpaceInputNameString", + "documentation":"

    A new name for the space. Omit to leave unchanged. Must be 3-64 characters: lowercase letters, numbers, and hyphens. It must begin and end with a letter or number and cannot contain consecutive hyphens.

    " + }, + "encryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    How to encrypt the space's data at rest. Omit to leave encryption unchanged. Pass encryptionStrategy AWS_OWNED to stop using a customer managed key and revert to service owned encryption.

    " + } + } + }, + "UpdateSpaceInputNameString":{ + "type":"string", + "max":64, + "min":3, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "UpdateSpaceOutput":{ + "type":"structure", + "required":["space"], + "members":{ + "space":{ + "shape":"Space", + "documentation":"

    The updated details of the space.

    " + } + } + }, + "UpdateViewRequest":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"ViewName", + "documentation":"

    The name of the view to update.

    " + }, + "definition":{ + "shape":"ViewDefinition", + "documentation":"

    The new SQL query that defines the view. Omit to leave unchanged.

    " + }, + "description":{ + "shape":"ViewDescription", + "documentation":"

    The new description of the view. Omit to leave unchanged.

    " + } + } + }, + "UpdateViewResponse":{ + "type":"structure", + "required":[ + "name", + "type", + "definition", + "createdAt", + "updatedAt", + "arn" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the view.

    " + }, + "type":{ + "shape":"ViewType", + "documentation":"

    The ownership category of the view.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the view.

    " + }, + "definition":{ + "shape":"String", + "documentation":"

    The SQL query that defines the view.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was last updated.

    " + }, + "arn":{ + "shape":"String", + "documentation":"

    The ARN of the view.

    " + } + } + }, + "ValidationException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code associated with the validation failure.

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

    A parameter is specified incorrectly.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "ViewDefinition":{ + "type":"string", + "documentation":"

    View definition (SQL query). Maximum 10,000 characters.

    ", + "max":10000, + "min":1 + }, + "ViewDescription":{ + "type":"string", + "documentation":"

    Description of a view.

    ", + "max":1024, + "min":0 + }, + "ViewName":{ + "type":"string", + "documentation":"

    User view name: must start with "view." prefix followed by lowercase alphanumeric, hyphens, and underscores.

    ", + "max":256, + "min":6, + "pattern":"view\\.[a-z0-9][a-z0-9_-]{0,250}" + }, + "ViewSummary":{ + "type":"structure", + "required":[ + "name", + "type", + "createdAt", + "updatedAt" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the view.

    " + }, + "type":{ + "shape":"ViewType", + "documentation":"

    The ownership category of the view.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the view.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the view was last updated.

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

    Summary information about a view. Does not include the view definition.

    " + }, + "ViewSummaryList":{ + "type":"list", + "member":{"shape":"ViewSummary"} + }, + "ViewType":{ + "type":"string", + "documentation":"

    The ownership category of a view.

    ", + "enum":[ + "USER", + "MANAGED" + ] + } + }, + "documentation":"

    CloudWatch Omni is a unified observability experience built on Amazon CloudWatch. You work in a space, an isolated environment that holds your telemetry and controls who can access it, and your data is stored in the CloudWatch Dataset for correlated analysis of logs, metrics, and traces.

    " +} diff --git a/services/codeartifact/pom.xml b/services/codeartifact/pom.xml index 6a1aa0102900..e2ea0cf88c18 100644 --- a/services/codeartifact/pom.xml +++ b/services/codeartifact/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codeartifact AWS Java SDK :: Services :: Codeartifact diff --git a/services/codeartifact/src/main/resources/codegen-resources/customization.config b/services/codeartifact/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codeartifact/src/main/resources/codegen-resources/customization.config +++ b/services/codeartifact/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codeartifact/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codeartifact/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3663f8880961 --- /dev/null +++ b/services/codeartifact/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeartifact-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeartifact-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeartifact.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeartifact.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codeartifact/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codeartifact/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4a4819582bdb..000000000000 --- a/services/codeartifact/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeartifact-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeartifact-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeartifact.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codeartifact.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codebuild/pom.xml b/services/codebuild/pom.xml index 38307139facc..30c700ec1d1b 100644 --- a/services/codebuild/pom.xml +++ b/services/codebuild/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codebuild AWS Java SDK :: Services :: AWS Code Build diff --git a/services/codebuild/src/main/resources/codegen-resources/customization.config b/services/codebuild/src/main/resources/codegen-resources/customization.config index 14d6f6ce48c2..d08272ebe3a6 100644 --- a/services/codebuild/src/main/resources/codegen-resources/customization.config +++ b/services/codebuild/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ "listCuratedEnvironmentImages", "listProjects", "listSourceCredentials" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/codebuild/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codebuild/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b9982bcc4fbf --- /dev/null +++ b/services/codebuild/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codebuild-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codebuild-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codebuild.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codebuild.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codebuild/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codebuild/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bc81834b22f7..000000000000 --- a/services/codebuild/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codebuild-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codebuild-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codebuild.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codebuild.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codecatalyst/pom.xml b/services/codecatalyst/pom.xml index 53573685ad4d..c35f0293cc66 100644 --- a/services/codecatalyst/pom.xml +++ b/services/codecatalyst/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codecatalyst AWS Java SDK :: Services :: Code Catalyst diff --git a/services/codecatalyst/src/main/resources/codegen-resources/customization.config b/services/codecatalyst/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codecatalyst/src/main/resources/codegen-resources/customization.config +++ b/services/codecatalyst/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codecatalyst/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codecatalyst/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8351dbed0eee --- /dev/null +++ b/services/codecatalyst/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,154 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult_ssa_2" + }, + { + "fn": "aws.partition", + "argv": [ + "us-west-2" + ], + "assign": "PartitionResult_ssa_1" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult_ssa_1" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult_ssa_2" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Partition does not support FIPS.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecatalyst-fips.global.{PartitionResult_ssa_1#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecatalyst.global.{PartitionResult_ssa_1#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecatalyst-fips.global.{PartitionResult_ssa_2#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecatalyst.global.{PartitionResult_ssa_2#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAX14QEAAAADAAAAAQAAAAcAAAAEAAAAAwAAAAUF9eEAAAAABAAAAAYF9eEEAAAABQX14QMF9eECAAAAAgAAAAgF9eEAAAAABAAAAAkF9eEGAAAABgX14QUF9eEC" +} \ No newline at end of file diff --git a/services/codecatalyst/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codecatalyst/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 617c43081f33..000000000000 --- a/services/codecatalyst/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - "us-west-2" - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - false - ] - } - ], - "error": "Partition does not support FIPS.", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codecatalyst-fips.global.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codecatalyst.global.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - false - ] - } - ], - "error": "Partition does not support FIPS.", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codecatalyst-fips.global.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codecatalyst.global.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/codecommit/pom.xml b/services/codecommit/pom.xml index 2eea05712b67..a5254c76bbdb 100644 --- a/services/codecommit/pom.xml +++ b/services/codecommit/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codecommit AWS Java SDK :: Services :: AWS CodeCommit diff --git a/services/codecommit/src/main/resources/codegen-resources/customization.config b/services/codecommit/src/main/resources/codegen-resources/customization.config index 05c43b1144ac..5e0619c65a63 100644 --- a/services/codecommit/src/main/resources/codegen-resources/customization.config +++ b/services/codecommit/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "getBranch" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/codecommit/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codecommit/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..01ae6b27d648 --- /dev/null +++ b/services/codecommit/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecommit-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecommit-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecommit.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codecommit.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codecommit/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codecommit/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d900c758455e..000000000000 --- a/services/codecommit/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codecommit-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codecommit-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codecommit.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codecommit.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codecommit/src/main/resources/codegen-resources/paginators-1.json b/services/codecommit/src/main/resources/codegen-resources/paginators-1.json index f363a39f6e3b..8f17460c5bbc 100644 --- a/services/codecommit/src/main/resources/codegen-resources/paginators-1.json +++ b/services/codecommit/src/main/resources/codegen-resources/paginators-1.json @@ -10,6 +10,17 @@ "limit_key": "maxResults", "output_token": "nextToken" }, + "GetBlobDifferences": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "non_aggregate_keys": [ + "isBinary", + "beforeBlobSize", + "afterBlobSize" + ], + "output_token": "NextToken", + "result_key": "hunks" + }, "GetCommentReactions": { "input_token": "nextToken", "limit_key": "maxResults", diff --git a/services/codecommit/src/main/resources/codegen-resources/service-2.json b/services/codecommit/src/main/resources/codegen-resources/service-2.json index d869b7a3df29..6d5f563d9aa8 100644 --- a/services/codecommit/src/main/resources/codegen-resources/service-2.json +++ b/services/codecommit/src/main/resources/codegen-resources/service-2.json @@ -667,6 +667,33 @@ ], "documentation":"

    Returns the base-64 encoded content of an individual blob in a repository.

    " }, + "GetBlobDifferences":{ + "name":"GetBlobDifferences", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetBlobDifferencesInput"}, + "output":{"shape":"GetBlobDifferencesOutput"}, + "errors":[ + {"shape":"RepositoryNameRequiredException"}, + {"shape":"InvalidRepositoryNameException"}, + {"shape":"RepositoryDoesNotExistException"}, + {"shape":"BlobIdRequiredException"}, + {"shape":"InvalidBlobIdException"}, + {"shape":"BlobIdDoesNotExistException"}, + {"shape":"FileTooLargeException"}, + {"shape":"ValidationException"}, + {"shape":"InvalidContinuationTokenException"}, + {"shape":"InvalidMaxResultsException"}, + {"shape":"EncryptionIntegrityChecksFailedException"}, + {"shape":"EncryptionKeyAccessDeniedException"}, + {"shape":"EncryptionKeyDisabledException"}, + {"shape":"EncryptionKeyNotFoundException"}, + {"shape":"EncryptionKeyUnavailableException"} + ], + "documentation":"

    Returns a structured, line-level diff between two blob versions in a repository. The diff is returned as an ordered list of hunks, where each hunk represents a contiguous run of changed lines together with any surrounding unchanged context lines.

    Results are paginated. Use MaxResults and NextToken to retrieve additional pages.

    For the typical usage workflow, see GetDifferences.

    " + }, "GetBranch":{ "name":"GetBranch", "http":{ @@ -833,7 +860,7 @@ {"shape":"EncryptionKeyNotFoundException"}, {"shape":"EncryptionKeyUnavailableException"} ], - "documentation":"

    Returns information about the differences in a valid commit specifier (such as a branch, tag, HEAD, commit ID, or other fully qualified reference). Results can be limited to a specified path.

    " + "documentation":"

    Returns information about the differences in a valid commit specifier (such as a branch, tag, HEAD, commit ID, or other fully qualified reference). Results can be limited to a specified path.

    For line-level diff details, pass the beforeBlob.blobId and afterBlob.blobId values from a Difference object to GetBlobDifferences.

    " }, "GetFile":{ "name":"GetFile", @@ -3794,6 +3821,73 @@ "type":"string", "max":10240 }, + "DiffChange":{ + "type":"structure", + "members":{ + "type":{ + "shape":"DiffChangeType", + "documentation":"

    The type of change for this line. Possible values:

    • CONTEXT – Unchanged line included for surrounding context.

    • ADD – Line added in the after blob.

    • DELETE – Line removed from the before blob.

    " + }, + "beforeLineNumber":{ + "shape":"LineNumber", + "documentation":"

    The 1-based line number in the before blob. This field is omitted for ADD lines.

    " + }, + "afterLineNumber":{ + "shape":"LineNumber", + "documentation":"

    The 1-based line number in the after blob. This field is omitted for DELETE lines.

    " + }, + "content":{ + "shape":"LineContent", + "documentation":"

    The text content of the line, without the trailing newline.

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

    A single line-level entry in a diff hunk. Each DiffChange describes one line and its change type: unchanged context, an addition in the after blob, or a deletion from the before blob.

    " + }, + "DiffChangeList":{ + "type":"list", + "member":{"shape":"DiffChange"}, + "max":25000 + }, + "DiffChangeType":{ + "type":"string", + "enum":[ + "CONTEXT", + "ADD", + "DELETE" + ] + }, + "DiffContext":{"type":"integer"}, + "DiffHunk":{ + "type":"structure", + "members":{ + "beforeStartLine":{ + "shape":"LineNumber", + "documentation":"

    The 1-based line number in the before blob where this hunk begins. When the hunk consists entirely of additions, beforeLineCount is 0.

    " + }, + "beforeLineCount":{ + "shape":"Count", + "documentation":"

    The number of lines from the before blob covered by this hunk, including any context lines.

    " + }, + "afterStartLine":{ + "shape":"LineNumber", + "documentation":"

    The 1-based line number in the after blob where this hunk begins. When the hunk consists entirely of deletions, afterLineCount is 0.

    " + }, + "afterLineCount":{ + "shape":"Count", + "documentation":"

    The number of lines from the after blob covered by this hunk, including any context lines.

    " + }, + "changes":{ + "shape":"DiffChangeList", + "documentation":"

    An ordered list of line-level changes that make up this hunk. Each entry indicates whether the line is unchanged context, an addition, or a deletion.

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

    A contiguous run of changed lines from a blob diff, together with any surrounding unchanged context lines. Hunks are returned in order from the start of the file to the end. Adjacent or overlapping hunks are merged into a single hunk in the response.

    " + }, + "DiffHunkList":{ + "type":"list", + "member":{"shape":"DiffHunk"}, + "max":1000 + }, "Difference":{ "type":"structure", "members":{ @@ -4170,6 +4264,73 @@ } } }, + "GetBlobDifferencesInput":{ + "type":"structure", + "required":[ + "repositoryName", + "afterBlobId" + ], + "members":{ + "repositoryName":{ + "shape":"RepositoryName", + "documentation":"

    The name of the repository that contains the blobs to compare.

    " + }, + "afterBlobId":{ + "shape":"ObjectId", + "documentation":"

    The ID of the \"after\" (destination) blob in the diff. Typically the value of afterBlob.blobId from a Difference object returned by GetDifferences.

    " + }, + "beforeBlobId":{ + "shape":"ObjectId", + "documentation":"

    The ID of the \"before\" (source) blob in the diff. Typically the value of beforeBlob.blobId from a Difference object returned by GetDifferences.

    If you do not specify a value, the operation returns a diff against an empty before-state. This is equivalent to treating the file as newly added.

    " + }, + "contextLines":{ + "shape":"DiffContext", + "documentation":"

    The number of unchanged lines of context to include before and after each block of changes in a hunk. Valid values are 0 through 20. Defaults to 3.

    " + }, + "ignoreWhitespace":{ + "shape":"IgnoreWhiteSpaces", + "documentation":"

    Specifies whether to ignore whitespace-only changes when computing the diff. When true, the operation treats lines that differ only in whitespace as unchanged. Defaults to false.

    " + }, + "MaxResults":{ + "shape":"Limit", + "documentation":"

    The maximum number of DiffHunk entries to return in a single response page. Defaults to 100.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    An enumeration token that returns the next batch of results when present in a request.

    " + } + } + }, + "GetBlobDifferencesOutput":{ + "type":"structure", + "required":[ + "hunks", + "isBinary", + "afterBlobSize" + ], + "members":{ + "hunks":{ + "shape":"DiffHunkList", + "documentation":"

    An ordered list of diff hunks. Each hunk represents a contiguous run of changed and adjacent context lines. The list is empty when the blobs are identical or when the content is binary. The list is also empty when a paginated request has already returned all hunks in earlier pages, in which case NextToken is also null.

    " + }, + "isBinary":{ + "shape":"CapitalBoolean", + "documentation":"

    Specifies whether the operation treated the diff content as binary. When true, the operation does not compute a line-level diff and hunks is empty.

    " + }, + "beforeBlobSize":{ + "shape":"ObjectSize", + "documentation":"

    The size, in bytes, of the blob identified by beforeBlobId. Returns 0 when you do not specify beforeBlobId.

    " + }, + "afterBlobSize":{ + "shape":"ObjectSize", + "documentation":"

    The size, in bytes, of the blob identified by afterBlobId.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    An enumeration token that can be used in a request to return the next batch of DiffHunk entries. null when the response contains the final page of the diff.

    " + } + } + }, "GetBlobInput":{ "type":"structure", "required":[ @@ -4873,6 +5034,7 @@ "documentation":"

    The client request token is not valid. Either the token is not in a valid format, or the token has been used in a previous request and cannot be reused.

    ", "exception":true }, + "IgnoreWhiteSpaces":{"type":"boolean"}, "InvalidActorArnException":{ "type":"structure", "members":{}, @@ -5287,6 +5449,7 @@ "type":"integer", "box":true }, + "LineContent":{"type":"string"}, "LineNumber":{"type":"integer"}, "ListApprovalRuleTemplatesInput":{ "type":"structure", @@ -7861,7 +8024,13 @@ }, "documentation":"

    Information about the user who made a specified commit.

    " }, + "ValidationException":{ + "type":"structure", + "members":{}, + "documentation":"

    The specified input is either not valid, or it could not be validated.

    ", + "exception":true + }, "blob":{"type":"blob"} }, - "documentation":"CodeCommit

    This is the CodeCommit API Reference. This reference provides descriptions of the operations and data types for CodeCommit API along with usage examples.

    You can use the CodeCommit API to work with the following objects:

    Repositories, by calling the following:

    • BatchGetRepositories, which returns information about one or more repositories associated with your Amazon Web Services account.

    • CreateRepository, which creates an CodeCommit repository.

    • DeleteRepository, which deletes an CodeCommit repository.

    • GetRepository, which returns information about a specified repository.

    • ListRepositories, which lists all CodeCommit repositories associated with your Amazon Web Services account.

    • UpdateRepositoryDescription, which sets or updates the description of the repository.

    • UpdateRepositoryEncryptionKey, which updates the Key Management Service encryption key used to encrypt and decrypt a repository.

    • UpdateRepositoryName, which changes the name of the repository. If you change the name of a repository, no other users of that repository can access it until you send them the new HTTPS or SSH URL to use.

    Branches, by calling the following:

    • CreateBranch, which creates a branch in a specified repository.

    • DeleteBranch, which deletes the specified branch in a repository unless it is the default branch.

    • GetBranch, which returns information about a specified branch.

    • ListBranches, which lists all branches for a specified repository.

    • UpdateDefaultBranch, which changes the default branch for a repository.

    Files, by calling the following:

    • DeleteFile, which deletes the content of a specified file from a specified branch.

    • GetBlob, which returns the base-64 encoded content of an individual Git blob object in a repository.

    • GetFile, which returns the base-64 encoded content of a specified file.

    • GetFolder, which returns the contents of a specified folder or directory.

    • ListFileCommitHistory, which retrieves a list of commits and changes to a specified file.

    • PutFile, which adds or modifies a single file in a specified repository and branch.

    Commits, by calling the following:

    • BatchGetCommits, which returns information about one or more commits in a repository.

    • CreateCommit, which creates a commit for changes to a repository.

    • GetCommit, which returns information about a commit, including commit messages and author and committer information.

    • GetDifferences, which returns information about the differences in a valid commit specifier (such as a branch, tag, HEAD, commit ID, or other fully qualified reference).

    Merges, by calling the following:

    • BatchDescribeMergeConflicts, which returns information about conflicts in a merge between commits in a repository.

    • CreateUnreferencedMergeCommit, which creates an unreferenced commit between two branches or commits for the purpose of comparing them and identifying any potential conflicts.

    • DescribeMergeConflicts, which returns information about merge conflicts between the base, source, and destination versions of a file in a potential merge.

    • GetMergeCommit, which returns information about the merge between a source and destination commit.

    • GetMergeConflicts, which returns information about merge conflicts between the source and destination branch in a pull request.

    • GetMergeOptions, which returns information about the available merge options between two branches or commit specifiers.

    • MergeBranchesByFastForward, which merges two branches using the fast-forward merge option.

    • MergeBranchesBySquash, which merges two branches using the squash merge option.

    • MergeBranchesByThreeWay, which merges two branches using the three-way merge option.

    Pull requests, by calling the following:

    Approval rule templates, by calling the following:

    Comments in a repository, by calling the following:

    Tags used to tag resources in CodeCommit (not Git tags), by calling the following:

    • ListTagsForResource, which gets information about Amazon Web Servicestags for a specified Amazon Resource Name (ARN) in CodeCommit.

    • TagResource, which adds or updates tags for a resource in CodeCommit.

    • UntagResource, which removes tags for a resource in CodeCommit.

    Triggers, by calling the following:

    • GetRepositoryTriggers, which returns information about triggers configured for a repository.

    • PutRepositoryTriggers, which replaces all triggers for a repository and can be used to create or delete triggers.

    • TestRepositoryTriggers, which tests the functionality of a repository trigger by sending data to the trigger target.

    For information about how to use CodeCommit, see the CodeCommit User Guide.

    " + "documentation":"CodeCommit

    This is the CodeCommit API Reference. This reference provides descriptions of the operations and data types for CodeCommit API along with usage examples.

    You can use the CodeCommit API to work with the following objects:

    Repositories, by calling the following:

    • BatchGetRepositories, which returns information about one or more repositories associated with your Amazon Web Services account.

    • CreateRepository, which creates an CodeCommit repository.

    • DeleteRepository, which deletes an CodeCommit repository.

    • GetRepository, which returns information about a specified repository.

    • ListRepositories, which lists all CodeCommit repositories associated with your Amazon Web Services account.

    • UpdateRepositoryDescription, which sets or updates the description of the repository.

    • UpdateRepositoryEncryptionKey, which updates the Key Management Service encryption key used to encrypt and decrypt a repository.

    • UpdateRepositoryName, which changes the name of the repository. If you change the name of a repository, no other users of that repository can access it until you send them the new HTTPS or SSH URL to use.

    Branches, by calling the following:

    • CreateBranch, which creates a branch in a specified repository.

    • DeleteBranch, which deletes the specified branch in a repository unless it is the default branch.

    • GetBranch, which returns information about a specified branch.

    • ListBranches, which lists all branches for a specified repository.

    • UpdateDefaultBranch, which changes the default branch for a repository.

    Files, by calling the following:

    • DeleteFile, which deletes the content of a specified file from a specified branch.

    • GetBlob, which returns the base-64 encoded content of an individual Git blob object in a repository.

    • GetBlobDifferences, which returns a structured, line-level diff between two blob versions in a repository, with optional surrounding context lines.

    • GetFile, which returns the base-64 encoded content of a specified file.

    • GetFolder, which returns the contents of a specified folder or directory.

    • ListFileCommitHistory, which retrieves a list of commits and changes to a specified file.

    • PutFile, which adds or modifies a single file in a specified repository and branch.

    Commits, by calling the following:

    • BatchGetCommits, which returns information about one or more commits in a repository.

    • CreateCommit, which creates a commit for changes to a repository.

    • GetCommit, which returns information about a commit, including commit messages and author and committer information.

    • GetDifferences, which returns information about the differences in a valid commit specifier (such as a branch, tag, HEAD, commit ID, or other fully qualified reference).

    Merges, by calling the following:

    • BatchDescribeMergeConflicts, which returns information about conflicts in a merge between commits in a repository.

    • CreateUnreferencedMergeCommit, which creates an unreferenced commit between two branches or commits for the purpose of comparing them and identifying any potential conflicts.

    • DescribeMergeConflicts, which returns information about merge conflicts between the base, source, and destination versions of a file in a potential merge.

    • GetMergeCommit, which returns information about the merge between a source and destination commit.

    • GetMergeConflicts, which returns information about merge conflicts between the source and destination branch in a pull request.

    • GetMergeOptions, which returns information about the available merge options between two branches or commit specifiers.

    • MergeBranchesByFastForward, which merges two branches using the fast-forward merge option.

    • MergeBranchesBySquash, which merges two branches using the squash merge option.

    • MergeBranchesByThreeWay, which merges two branches using the three-way merge option.

    Pull requests, by calling the following:

    Approval rule templates, by calling the following:

    Comments in a repository, by calling the following:

    Tags used to tag resources in CodeCommit (not Git tags), by calling the following:

    • ListTagsForResource, which gets information about Amazon Web Servicestags for a specified Amazon Resource Name (ARN) in CodeCommit.

    • TagResource, which adds or updates tags for a resource in CodeCommit.

    • UntagResource, which removes tags for a resource in CodeCommit.

    Triggers, by calling the following:

    • GetRepositoryTriggers, which returns information about triggers configured for a repository.

    • PutRepositoryTriggers, which replaces all triggers for a repository and can be used to create or delete triggers.

    • TestRepositoryTriggers, which tests the functionality of a repository trigger by sending data to the trigger target.

    For information about how to use CodeCommit, see the CodeCommit User Guide.

    " } diff --git a/services/codeconnections/pom.xml b/services/codeconnections/pom.xml index 77c4e9373f2d..4f1d5e20acbf 100644 --- a/services/codeconnections/pom.xml +++ b/services/codeconnections/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codeconnections AWS Java SDK :: Services :: Code Connections diff --git a/services/codeconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codeconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..27d62015acba --- /dev/null +++ b/services/codeconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeconnections-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeconnections-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeconnections.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeconnections.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codeconnections/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codeconnections/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index dbfc0ad9f300..000000000000 --- a/services/codeconnections/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeconnections-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeconnections-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeconnections.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeconnections.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/codedeploy/pom.xml b/services/codedeploy/pom.xml index 3892fde69f4a..fd0e5cc5209f 100644 --- a/services/codedeploy/pom.xml +++ b/services/codedeploy/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codedeploy AWS Java SDK :: Services :: AWS CodeDeploy diff --git a/services/codedeploy/src/main/resources/codegen-resources/customization.config b/services/codedeploy/src/main/resources/codegen-resources/customization.config index 5fc15ca47f6f..9d1a857a011c 100644 --- a/services/codedeploy/src/main/resources/codegen-resources/customization.config +++ b/services/codedeploy/src/main/resources/codegen-resources/customization.config @@ -30,6 +30,5 @@ "InstanceIdRequiredException", "InstanceStatus", "InstanceSummary" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/codedeploy/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codedeploy/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fc8af8b5099c --- /dev/null +++ b/services/codedeploy/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codedeploy-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codedeploy-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codedeploy.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codedeploy.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codedeploy/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codedeploy/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 895ebe4e4f73..000000000000 --- a/services/codedeploy/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codedeploy-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codedeploy-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codedeploy.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codedeploy.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codedeploy/src/main/resources/codegen-resources/service-2.json b/services/codedeploy/src/main/resources/codegen-resources/service-2.json index e482d5ce1cb1..26a943757537 100644 --- a/services/codedeploy/src/main/resources/codegen-resources/service-2.json +++ b/services/codedeploy/src/main/resources/codegen-resources/service-2.json @@ -191,7 +191,8 @@ {"shape":"ApplicationAlreadyExistsException"}, {"shape":"ApplicationLimitExceededException"}, {"shape":"InvalidComputePlatformException"}, - {"shape":"InvalidTagsToAddException"} + {"shape":"InvalidTagsToAddException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Creates an application.

    " }, @@ -223,13 +224,16 @@ {"shape":"InvalidAutoRollbackConfigException"}, {"shape":"InvalidLoadBalancerInfoException"}, {"shape":"InvalidFileExistsBehaviorException"}, + {"shape":"InvalidComputePlatformException"}, {"shape":"InvalidRoleException"}, {"shape":"InvalidAutoScalingGroupException"}, {"shape":"ThrottlingException"}, {"shape":"InvalidUpdateOutdatedInstancesOnlyValueException"}, {"shape":"InvalidIgnoreApplicationStopFailuresValueException"}, {"shape":"InvalidGitHubAccountTokenException"}, - {"shape":"InvalidTrafficRoutingConfigurationException"} + {"shape":"InvalidTrafficRoutingConfigurationException"}, + {"shape":"InvalidECSServiceException"}, + {"shape":"InvalidInputException"} ], "documentation":"

    Deploys an application revision through the specified deployment group.

    " }, @@ -606,7 +610,9 @@ {"shape":"InvalidInstanceTypeException"}, {"shape":"InvalidDeploymentInstanceTypeException"}, {"shape":"InvalidTargetFilterNameException"}, - {"shape":"InvalidComputePlatformException"} + {"shape":"InvalidComputePlatformException"}, + {"shape":"ApplicationDoesNotExistException"}, + {"shape":"DeploymentGroupDoesNotExistException"} ], "documentation":"

    The newer BatchGetDeploymentTargets should be used instead because it works with all compute types. ListDeploymentInstances throws an exception if it is used with a compute platform other than EC2/On-premises or Lambda.

    Lists the instance for a deployment associated with the user or Amazon Web Services account.

    ", "deprecated":true, @@ -629,7 +635,9 @@ {"shape":"InvalidInstanceStatusException"}, {"shape":"InvalidInstanceTypeException"}, {"shape":"InvalidDeploymentInstanceTypeException"}, - {"shape":"InvalidTargetFilterNameException"} + {"shape":"InvalidTargetFilterNameException"}, + {"shape":"ApplicationDoesNotExistException"}, + {"shape":"DeploymentGroupDoesNotExistException"} ], "documentation":"

    Returns an array of target IDs that are associated a deployment.

    " }, @@ -1041,7 +1049,8 @@ "ApplicationName":{ "type":"string", "max":100, - "min":1 + "min":1, + "pattern":"[A-Za-z0-9+=,.@_-]*" }, "ApplicationNameRequiredException":{ "type":"structure", @@ -1638,6 +1647,10 @@ "shape":"FileExistsBehavior", "documentation":"

    Information about how CodeDeploy handles files that already exist in a deployment target location but weren't part of the previous successful deployment.

    The fileExistsBehavior parameter takes any of the following values:

    • DISALLOW: The deployment fails. This is also the default behavior if no option is specified.

    • OVERWRITE: The version of the file from the application revision currently being deployed replaces the version already on the instance.

    • RETAIN: The version of the file already on the instance is kept and used as part of the new deployment.

    " }, + "deploymentMode":{ + "shape":"DeploymentMode", + "documentation":"

    The type of deployment to create. Valid values are:

    • STANDARD: Deploys the specified revision. This is the default behavior if deploymentMode is not specified.

    • RESTART: Restarts the application on the target instances using the revision from the deployment group's last successful deployment, without downloading a new revision. RESTART is supported only for EC2/On-premises in-place deployments.

      When deploymentMode is RESTART, the following apply:

      • The call is rejected for Amazon ECS and Lambda deployments.

      • The revision parameter (including its s3Location and gitHubLocation) must not be specified, and is rejected if provided. The revision is resolved by the service from the deployment group's last successful deployment.

      • The updateOutdatedInstancesOnly parameter must not be set to true, and is rejected if provided.

    " + }, "overrideAlarmConfiguration":{ "shape":"AlarmConfiguration", "documentation":"

    Allows you to specify information about alarms associated with a deployment. The alarm configuration that you specify here will override the alarm configuration at the deployment group level. Consider overriding the alarm configuration if you have set up alarms at the deployment group level that are causing deployment failures. In this case, you would call CreateDeployment to create a new deployment that uses a previous application revision that is known to work, and set its alarm configuration to turn off alarm polling. Turning off alarm polling ensures that the new deployment proceeds without being blocked by the alarm that was generated by the previous, failed, deployment.

    If you specify an overrideAlarmConfiguration, you need the UpdateDeploymentGroup IAM permission when calling CreateDeployment.

    " @@ -1812,7 +1825,8 @@ "DeploymentConfigName":{ "type":"string", "max":100, - "min":1 + "min":1, + "pattern":"[A-Za-z0-9+=,.@_-]*" }, "DeploymentConfigNameRequiredException":{ "type":"structure", @@ -1967,7 +1981,8 @@ "DeploymentGroupName":{ "type":"string", "max":100, - "min":1 + "min":1, + "pattern":"[A-Za-z0-9+=,.@_-]*" }, "DeploymentGroupNameRequiredException":{ "type":"structure", @@ -2089,6 +2104,10 @@ "shape":"FileExistsBehavior", "documentation":"

    Information about how CodeDeploy handles files that already exist in a deployment target location but weren't part of the previous successful deployment.

    • DISALLOW: The deployment fails. This is also the default behavior if no option is specified.

    • OVERWRITE: The version of the file from the application revision currently being deployed replaces the version already on the instance.

    • RETAIN: The version of the file already on the instance is kept and used as part of the new deployment.

    " }, + "deploymentMode":{ + "shape":"DeploymentMode", + "documentation":"

    The deployment's type. Valid values are:

    • STANDARD: The deployment installed the specified revision.

    • RESTART: The deployment restarted the application on the target instances using the revision from the deployment group's last successful deployment, without downloading a new revision.

    This field is absent for deployments created before deploymentMode existed, and for STANDARD deployments. An absent value must not be interpreted as STANDARD; it simply means no value was recorded either way.

    " + }, "deploymentStatusMessages":{ "shape":"DeploymentStatusMessageList", "documentation":"

    Messages that contain information about the status of a deployment.

    " @@ -2118,6 +2137,13 @@ "documentation":"

    The number of allowed deployments was exceeded.

    ", "exception":true }, + "DeploymentMode":{ + "type":"string", + "enum":[ + "STANDARD", + "RESTART" + ] + }, "DeploymentNotStartedException":{ "type":"structure", "members":{}, diff --git a/services/codeguruprofiler/pom.xml b/services/codeguruprofiler/pom.xml index d81a15111756..56d6428c5b9a 100644 --- a/services/codeguruprofiler/pom.xml +++ b/services/codeguruprofiler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codeguruprofiler AWS Java SDK :: Services :: CodeGuruProfiler diff --git a/services/codeguruprofiler/src/main/resources/codegen-resources/customization.config b/services/codeguruprofiler/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codeguruprofiler/src/main/resources/codegen-resources/customization.config +++ b/services/codeguruprofiler/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..eecdfd6e9643 --- /dev/null +++ b/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-profiler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-profiler-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-profiler.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-profiler.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b3c38e72a4dc..000000000000 --- a/services/codeguruprofiler/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-profiler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-profiler-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-profiler.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-profiler.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codegurureviewer/pom.xml b/services/codegurureviewer/pom.xml index 483060544c28..5a9cfc357ece 100644 --- a/services/codegurureviewer/pom.xml +++ b/services/codegurureviewer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codegurureviewer AWS Java SDK :: Services :: CodeGuru Reviewer diff --git a/services/codegurureviewer/src/main/resources/codegen-resources/customization.config b/services/codegurureviewer/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codegurureviewer/src/main/resources/codegen-resources/customization.config +++ b/services/codegurureviewer/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2c58d43051fa --- /dev/null +++ b/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-reviewer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-reviewer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-reviewer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-reviewer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 830ac98ca634..000000000000 --- a/services/codegurureviewer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-reviewer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-reviewer-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-reviewer.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-reviewer.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codegurusecurity/pom.xml b/services/codegurusecurity/pom.xml index 862406666a33..0adfe30dc255 100644 --- a/services/codegurusecurity/pom.xml +++ b/services/codegurusecurity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codegurusecurity AWS Java SDK :: Services :: Code Guru Security diff --git a/services/codegurusecurity/src/main/resources/codegen-resources/customization.config b/services/codegurusecurity/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codegurusecurity/src/main/resources/codegen-resources/customization.config +++ b/services/codegurusecurity/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6160bd98b7a3 --- /dev/null +++ b/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-security-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-security-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-security.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codeguru-security.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f9588bc1c980..000000000000 --- a/services/codegurusecurity/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-security-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-security-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-security.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codeguru-security.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/codepipeline/pom.xml b/services/codepipeline/pom.xml index d45d9d1f829c..a3b3c0e0e31a 100644 --- a/services/codepipeline/pom.xml +++ b/services/codepipeline/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codepipeline AWS Java SDK :: Services :: AWS CodePipeline diff --git a/services/codepipeline/src/main/resources/codegen-resources/customization.config b/services/codepipeline/src/main/resources/codegen-resources/customization.config index 2c0df19be840..d8c129b542e1 100644 --- a/services/codepipeline/src/main/resources/codegen-resources/customization.config +++ b/services/codepipeline/src/main/resources/codegen-resources/customization.config @@ -7,6 +7,5 @@ "excludedSimpleMethods": [ "deregisterWebhookWithThirdParty", "registerWebhookWithThirdParty" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/codepipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codepipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..66ac3de3105c --- /dev/null +++ b/services/codepipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codepipeline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codepipeline-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codepipeline.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codepipeline.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codepipeline/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codepipeline/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 226078136968..000000000000 --- a/services/codepipeline/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codepipeline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codepipeline-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codepipeline.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codepipeline.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codestarconnections/pom.xml b/services/codestarconnections/pom.xml index 2a7263c03b98..271359187cfd 100644 --- a/services/codestarconnections/pom.xml +++ b/services/codestarconnections/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codestarconnections AWS Java SDK :: Services :: CodeStar connections diff --git a/services/codestarconnections/src/main/resources/codegen-resources/customization.config b/services/codestarconnections/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codestarconnections/src/main/resources/codegen-resources/customization.config +++ b/services/codestarconnections/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codestarconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codestarconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7f7603e0df8f --- /dev/null +++ b/services/codestarconnections/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-connections-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-connections-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-connections.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-connections.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codestarconnections/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codestarconnections/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d39710ee1265..000000000000 --- a/services/codestarconnections/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-connections-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-connections-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-connections.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codestar-connections.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/codestarnotifications/pom.xml b/services/codestarnotifications/pom.xml index 14f78c6b393d..00b39df5f053 100644 --- a/services/codestarnotifications/pom.xml +++ b/services/codestarnotifications/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT codestarnotifications AWS Java SDK :: Services :: Codestar Notifications diff --git a/services/codestarnotifications/src/main/resources/codegen-resources/customization.config b/services/codestarnotifications/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/codestarnotifications/src/main/resources/codegen-resources/customization.config +++ b/services/codestarnotifications/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..74b0efca025f --- /dev/null +++ b/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-notifications-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-notifications-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-notifications.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://codestar-notifications.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 506b94fdf945..000000000000 --- a/services/codestarnotifications/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-notifications-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-notifications-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://codestar-notifications.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://codestar-notifications.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cognitoidentity/pom.xml b/services/cognitoidentity/pom.xml index 96178cb85ee3..ea3a329ed3d8 100644 --- a/services/cognitoidentity/pom.xml +++ b/services/cognitoidentity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cognitoidentity AWS Java SDK :: Services :: Amazon Cognito Identity diff --git a/services/cognitoidentity/src/main/resources/codegen-resources/customization.config b/services/cognitoidentity/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/cognitoidentity/src/main/resources/codegen-resources/customization.config +++ b/services/cognitoidentity/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3e98c957776d --- /dev/null +++ b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,284 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.us-east-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.us-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.us-west-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-identity.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEQAAAAAgAAAAUF9eEQAAAAAwAAAAkAAAAGAAAABQAAAAcF9eEPAAAABgAAAAgF9eEOAAAABwX14QwF9eENAAAABAAAAAsAAAAKAAAABQX14QkF9eELAAAABQAAAAwF9eEKAAAABgAAAA0F9eEJAAAACAX14QQAAAAOAAAACQX14QUAAAAPAAAACgX14QYAAAAQAAAACwX14QcF9eEIAAAAAwX14QEAAAASAAAABQX14QIF9eED" +} \ No newline at end of file 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 deleted file mode 100644 index 773299c50c64..000000000000 --- a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,415 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "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": { - "url": "https://cognito-identity-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cognito-identity-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "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": { - "url": "https://cognito-identity.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cognito-identity.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cognitoidentityprovider/pom.xml b/services/cognitoidentityprovider/pom.xml index ab45d18c0cdc..a5b621d76bd9 100644 --- a/services/cognitoidentityprovider/pom.xml +++ b/services/cognitoidentityprovider/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cognitoidentityprovider AWS Java SDK :: Services :: Amazon Cognito Identity Provider Service diff --git a/services/cognitoidentityprovider/src/main/resources/codegen-resources/customization.config b/services/cognitoidentityprovider/src/main/resources/codegen-resources/customization.config index da9f806be319..4b9b86a42001 100644 --- a/services/cognitoidentityprovider/src/main/resources/codegen-resources/customization.config +++ b/services/cognitoidentityprovider/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "excludedSimpleMethods" : [ "associateSoftwareToken" ], diff --git a/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f5d1c4674681 --- /dev/null +++ b/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,284 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.us-east-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.us-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.us-west-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-idp.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEQAAAAAgAAAAUF9eEQAAAAAwAAAAkAAAAGAAAABQAAAAcF9eEPAAAABgAAAAgF9eEOAAAABwX14QwF9eENAAAABAAAAAsAAAAKAAAABQX14QkF9eELAAAABQAAAAwF9eEKAAAABgAAAA0F9eEJAAAACAX14QQAAAAOAAAACQX14QUAAAAPAAAACgX14QYAAAAQAAAACwX14QcF9eEIAAAAAwX14QEAAAASAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2f95bf9b1391..000000000000 --- a/services/cognitoidentityprovider/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,415 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://cognito-idp-fips.us-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-2" - ] - } - ], - "endpoint": { - "url": "https://cognito-idp-fips.us-east-2.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-1" - ] - } - ], - "endpoint": { - "url": "https://cognito-idp-fips.us-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-2" - ] - } - ], - "endpoint": { - "url": "https://cognito-idp-fips.us-west-2.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cognito-idp-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cognito-idp-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://cognito-idp.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cognito-idp.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cognito-idp.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/cognitoidentityprovider/src/main/resources/codegen-resources/service-2.json b/services/cognitoidentityprovider/src/main/resources/codegen-resources/service-2.json index ff615fd77d15..7175a098baa1 100644 --- a/services/cognitoidentityprovider/src/main/resources/codegen-resources/service-2.json +++ b/services/cognitoidentityprovider/src/main/resources/codegen-resources/service-2.json @@ -122,6 +122,26 @@ ], "documentation":"

    Creates a new user in the specified user pool.

    If MessageAction isn't set, the default is to send a welcome message via email or phone (SMS).

    This message is based on a template that you configured in your call to create or update a user pool. This template includes your custom sign-up instructions and placeholders for user name and temporary password.

    Alternatively, you can call AdminCreateUser with SUPPRESS for the MessageAction parameter, and Amazon Cognito won't send any email.

    In either case, if the user has a password, they will be in the FORCE_CHANGE_PASSWORD state until they sign in and set their password. Your invitation message template must have the {####} password placeholder if your users have passwords. If your template doesn't have this placeholder, Amazon Cognito doesn't deliver the invitation message. In this case, you must update your message template and resend the password with a new AdminCreateUser request with a MessageAction value of RESEND.

    This action might generate an SMS text message. Starting June 1, 2021, US telecom carriers require you to register an origination phone number before you can send SMS messages to US phone numbers. If you use SMS text messages in Amazon Cognito, you must register a phone number with Amazon Pinpoint. Amazon Cognito uses the registered number automatically. Otherwise, Amazon Cognito users who must receive SMS messages might not be able to sign up, activate their accounts, or sign in.

    If you have never used SMS text messages with Amazon Cognito or any other Amazon Web Services service, Amazon Simple Notification Service might place your account in the SMS sandbox. In sandbox mode , you can send messages only to verified phone numbers. After you test your app while in the sandbox environment, you can move out of the sandbox and into production. For more information, see SMS message settings for Amazon Cognito user pools in the Amazon Cognito Developer Guide.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " }, + "AdminDeleteSoftwareToken":{ + "name":"AdminDeleteSoftwareToken", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AdminDeleteSoftwareTokenRequest"}, + "output":{"shape":"AdminDeleteSoftwareTokenResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"NotAuthorizedException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"UserNotFoundException"}, + {"shape":"UserNotConfirmedException"}, + {"shape":"OperationNotEnabledException"}, + {"shape":"InternalErrorException"} + ], + "documentation":"

    Deletes a user's registered time-based one-time password (TOTP) multi-factor authentication (MFA) factor, also known as a software token. After this operation, the user can no longer sign in with TOTP MFA, and can register a new TOTP factor with AssociateSoftwareToken. Use this operation when a user loses access to their TOTP-generating device, for example, a lost or reset phone, and needs to register a new one.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " + }, "AdminDeleteUser":{ "name":"AdminDeleteUser", "http":{ @@ -274,6 +294,25 @@ ], "documentation":"

    Given a username, returns details about a user profile in a user pool. You can specify alias attributes in the Username request parameter.

    This operation contributes to your monthly active user (MAU) count for the purpose of billing.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " }, + "AdminGetUserAuthFactors":{ + "name":"AdminGetUserAuthFactors", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AdminGetUserAuthFactorsRequest"}, + "output":{"shape":"AdminGetUserAuthFactorsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"NotAuthorizedException"}, + {"shape":"OperationNotEnabledException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"UserNotFoundException"}, + {"shape":"InternalErrorException"} + ], + "documentation":"

    Lists the authentication options for a user in a user pool. Returns the following:

    1. The user's multi-factor authentication (MFA) preferences.

    2. The user's options for choice-based authentication with the USER_AUTH flow.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " + }, "AdminInitiateAuth":{ "name":"AdminInitiateAuth", "http":{ @@ -1335,6 +1374,24 @@ ], "documentation":"

    Returns details for the requested terms documents ID. For more information, see Terms documents.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " }, + "DescribeTermsByClient":{ + "name":"DescribeTermsByClient", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeTermsByClientRequest"}, + "output":{"shape":"DescribeTermsByClientResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"NotAuthorizedException"}, + {"shape":"OperationNotEnabledException"}, + {"shape":"InternalErrorException"} + ], + "documentation":"

    Returns details for the terms documents that are associated with an app client, identified by the app client ID, user pool ID, and terms name. For more information, see Terms documents.

    To call DescribeTermsByClient, you must have the cognito-idp:DescribeTermsByClient Identity and Access Management (IAM) permission. This operation additionally validates your permission for cognito-idp:DescribeTerms, the action for . As a result, an IAM policy that denies cognito-idp:DescribeTerms also denies requests to DescribeTermsByClient.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " + }, "DescribeUserImportJob":{ "name":"DescribeUserImportJob", "http":{ @@ -1405,7 +1462,7 @@ {"shape":"OperationNotEnabledException"}, {"shape":"InternalErrorException"} ], - "documentation":"

    Given a user pool domain name, returns information about the domain configuration.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " + "documentation":"

    Given a user pool domain name, returns information about the domain configuration.

    This operation doesn't return results when you query a prefix domain in a secondary Region. Prefix domains are Region-specific and can only be described in the Region where they were created. To describe a prefix domain for a replica user pool, make the request to the primary Region's endpoint.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " }, "ForgetDevice":{ "name":"ForgetDevice", @@ -1479,6 +1536,25 @@ ], "documentation":"

    Given a user pool ID, generates a comma-separated value (CSV) list populated with available user attributes in the user pool. This list is the header for the CSV file that determines the users in a user import job. Save the content of CSVHeader in the response as a .csv file and populate it with the usernames and attributes of users that you want to import. For more information about CSV user import, see Importing users from a CSV file.

    Amazon Cognito evaluates Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you must use IAM credentials to authorize requests, and you must grant yourself the corresponding IAM permission in a policy.

    Learn more

    " }, + "GetClientToken":{ + "name":"GetClientToken", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetClientTokenRequest"}, + "output":{"shape":"GetClientTokenResponse"}, + "errors":[ + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"NotAuthorizedException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"InternalErrorException"}, + {"shape":"OperationNotEnabledException"}, + {"shape":"ForbiddenException"} + ], + "documentation":"

    Issues an access token for machine-to-machine (M2M) authorization. Your app client provides its client ID and secret, and receives an access token that authorizes requests to your resource servers. GetClientToken provides the same functionality as the OAuth2 client-credentials grant; both authorize an application rather than a user.

    To use this operation, you must configure the app client with a client secret and enable the ALLOW_CLIENT_TOKEN_AUTH authentication flow. The ALLOW_CLIENT_TOKEN_AUTH flow is mutually exclusive with user authentication flows. It must be the only authentication flow that you configure for the app client. For more information, see Scopes, M2M, and resource servers.

    Amazon Cognito doesn't evaluate Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you can't use IAM credentials to authorize requests, and you can't grant IAM permissions in policies. For more information about authorization models in Amazon Cognito, see Using the Amazon Cognito user pools API and user pool endpoints.

    " + }, "GetDevice":{ "name":"GetDevice", "http":{ @@ -2998,6 +3074,27 @@ "max":365, "min":0 }, + "AdminDeleteSoftwareTokenRequest":{ + "type":"structure", + "required":[ + "UserPoolId", + "Username" + ], + "members":{ + "UserPoolId":{ + "shape":"UserPoolIdType", + "documentation":"

    The ID of the user pool where you want to delete the user's software token.

    " + }, + "Username":{ + "shape":"UsernameType", + "documentation":"

    The name of the user that you want to query or modify. The value of this parameter is typically your user's username, but it can be any of their alias attributes. If username isn't an alias attribute in your user pool, this value must be the sub of a local user or the username of a user from a third-party IdP.

    " + } + } + }, + "AdminDeleteSoftwareTokenResponse":{ + "type":"structure", + "members":{} + }, "AdminDeleteUserAttributesRequest":{ "type":"structure", "required":[ @@ -3168,6 +3265,45 @@ }, "documentation":"

    Gets the device response, as an administrator.

    " }, + "AdminGetUserAuthFactorsRequest":{ + "type":"structure", + "required":[ + "UserPoolId", + "Username" + ], + "members":{ + "UserPoolId":{ + "shape":"UserPoolIdType", + "documentation":"

    The ID of the user pool where you want to get information about the user's authentication factors.

    " + }, + "Username":{ + "shape":"UsernameType", + "documentation":"

    The name of the user that you want to query or modify. The value of this parameter is typically your user's username, but it can be any of their alias attributes. If username isn't an alias attribute in your user pool, this value must be the sub of a local user or the username of a user from a third-party IdP.

    " + } + } + }, + "AdminGetUserAuthFactorsResponse":{ + "type":"structure", + "required":["Username"], + "members":{ + "Username":{ + "shape":"UsernameType", + "documentation":"

    The name of the user who is eligible for the authentication factors in the response.

    " + }, + "PreferredMfaSetting":{ + "shape":"StringType", + "documentation":"

    The challenge method that Amazon Cognito returns to the user in response to sign-in requests. Users can prefer SMS message, email message, or TOTP MFA.

    " + }, + "UserMFASettingList":{ + "shape":"UserMFASettingListType", + "documentation":"

    The MFA options that are activated for the user. The possible values in this list are SMS_MFA, EMAIL_OTP, and SOFTWARE_TOKEN_MFA.

    " + }, + "ConfiguredUserAuthFactors":{ + "shape":"ConfiguredUserAuthFactorsListType", + "documentation":"

    The authentication types that are available to the user with USER_AUTH sign-in, for example [\"PASSWORD\", \"WEB_AUTHN\"].

    PASSWORD can only be used as a first authentication factor. SOFTWARE_TOKEN can only be used as an MFA factor. EMAIL_OTP, SMS_OTP, and WEB_AUTHN can be used as either a first authentication factor or an MFA factor. WEB_AUTHN is available as an MFA factor only when passkey MFA is enabled at the user pool level.

    " + } + } + }, "AdminGetUserRequest":{ "type":"structure", "required":[ @@ -3312,7 +3448,7 @@ }, "DestinationUser":{ "shape":"ProviderUserIdentifierType", - "documentation":"

    The existing user in the user pool that you want to assign to the external IdP user account. This user can be a local (Username + Password) Amazon Cognito user pools user or a federated user (for example, a SAML or Facebook user). If the user doesn't exist, Amazon Cognito generates an exception. Amazon Cognito returns this user when the new user (with the linked IdP attribute) signs in.

    For a native username + password user, the ProviderAttributeValue for the DestinationUser should be the username in the user pool. For a federated user, it should be the provider-specific user_id.

    The ProviderAttributeName of the DestinationUser is ignored.

    The ProviderName should be set to Cognito for users in Cognito user pools.

    All attributes in the DestinationUser profile must be mutable. If you have assigned the user any immutable custom attributes, the operation won't succeed.

    " + "documentation":"

    The existing user in the user pool that you want to assign to the external IdP user account. This user can be a local (Username + Password) Amazon Cognito user pools user or a federated user (for example, a SAML or Facebook user). If the user doesn't exist, Amazon Cognito generates an exception. Amazon Cognito returns this user when the new user (with the linked IdP attribute) signs in.

    For a native username + password user, the ProviderAttributeValue for the DestinationUser should be the username in the user pool. For a federated user, it should be the provider-specific user_id.

    The ProviderAttributeName of the DestinationUser is ignored.

    The ProviderName should be set to Cognito for users in Cognito user pools.

    " }, "SourceUser":{ "shape":"ProviderUserIdentifierType", @@ -3818,7 +3954,7 @@ "AllowedFirstAuthFactorsListType":{ "type":"list", "member":{"shape":"AuthFactorType"}, - "max":4, + "max":5, "min":1 }, "AnalyticsConfigurationType":{ @@ -4065,7 +4201,8 @@ "PASSWORD", "EMAIL_OTP", "SMS_OTP", - "WEB_AUTHN" + "WEB_AUTHN", + "SOFTWARE_TOKEN" ] }, "AuthFlowType":{ @@ -4235,6 +4372,24 @@ "members":{}, "documentation":"

    The response from the server to the change password request.

    " }, + "ClientAuthenticationResultType":{ + "type":"structure", + "members":{ + "AccessToken":{ + "shape":"TokenModelType", + "documentation":"

    The access token for the requested app client. Present this token to a resource server to authorize a request, using the scopes granted in the token.

    " + }, + "ExpiresIn":{ + "shape":"IntegerType", + "documentation":"

    The number of seconds until the access token expires.

    " + }, + "TokenType":{ + "shape":"StringType", + "documentation":"

    The type of the token. For example, Bearer.

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

    The access token and its metadata from a machine-to-machine (M2M) client credentials grant.

    " + }, "ClientIdType":{ "type":"string", "max":128, @@ -4837,6 +4992,10 @@ "CloudWatchLogsRoleArn":{ "shape":"ArnType", "documentation":"

    You must specify an IAM role that has permission to log import-job results to Amazon CloudWatch Logs. This parameter is the ARN of that role.

    " + }, + "PasswordHashingAlgorithm":{ + "shape":"PasswordHashingAlgorithmType", + "documentation":"

    The password hashing algorithm used to generate the hashes in the CSV file for this import job.

    Valid values: BCRYPT | SCRYPT | ARGON2ID | PBKDF2_SHA256

    " } }, "documentation":"

    Represents the request to create the user import job.

    " @@ -4984,7 +5143,7 @@ }, "ManagedLoginVersion":{ "shape":"WrappedIntegerType", - "documentation":"

    The version of managed login branding that you want to apply to your domain. A value of 1 indicates hosted UI (classic) and a version of 2 indicates managed login.

    Managed login requires that your user pool be configured for any feature plan other than Lite.

    " + "documentation":"

    The version of managed login branding that you want to apply to your domain. A value of 1 indicates hosted UI (classic) and a version of 2 indicates managed login.

    Managed login requires that your user pool be configured for any feature plan other than Lite.

    A ManagedLoginVersion value of 2 does not activate managed login pages for your app client. When you create an app client programmatically, your app client has no branding style. To use managed login, create a branding style using the CreateManagedLoginBranding operation. When you use the console, Amazon Cognito assigns a default branding style automatically. When you use the API or an SDK, you must create a branding style yourself.

    " }, "CustomDomainConfig":{ "shape":"CustomDomainConfigType", @@ -5097,7 +5256,7 @@ }, "MfaConfiguration":{ "shape":"UserPoolMfaType", - "documentation":"

    Sets multi-factor authentication (MFA) to be on, off, or optional. When ON, all users must set up MFA before they can sign in. When OPTIONAL, your application must make a client-side determination of whether a user wants to register an MFA device. For user pools with adaptive authentication with threat protection, choose OPTIONAL.

    When MfaConfiguration is OPTIONAL, managed login doesn't automatically prompt users to set up MFA. Amazon Cognito generates MFA prompts in API responses and in managed login for users who have chosen and configured a preferred MFA factor.

    " + "documentation":"

    Sets multi-factor authentication (MFA) to be on, off, or optional. When ON, all users must set up MFA before they can sign in. When OPTIONAL, your application must make a client-side determination of whether a user wants to register an MFA device. For user pools with adaptive authentication with threat protection, choose OPTIONAL.

    When MfaConfiguration is OPTIONAL, managed login doesn't automatically prompt users to set up MFA. Amazon Cognito generates MFA prompts in API responses and in managed login for users who have chosen and configured a preferred MFA factor.

    The CreateUserPool operation supports only SMS MFA configuration. If you set MfaConfiguration to either of these values, include an SmsConfiguration in the same request:

    • ON – Requires MFA for all users

    • OPTIONAL – Makes MFA optional for each user

    If you omit SmsConfiguration, the operation returns an InvalidParameterException. To configure TOTP or email MFA, use the SetUserPoolMfaConfig operation. You can also use SetUserPoolMfaConfig to add MFA factors later.

    " }, "UserAttributeUpdateSettings":{ "shape":"UserAttributeUpdateSettingsType", @@ -5186,7 +5345,7 @@ }, "SecurityPolicy":{ "shape":"SecurityPolicyType", - "documentation":"

    The security policy for the custom domain. Defines the minimum TLS version and cipher suites that CloudFront uses when communicating with viewers (clients). Valid values are as follows:

    • TLS_V1: Supports TLS 1.0 and later. Provides the broadest client compatibility.

    • TLS_V1_2_2021: Supports TLS 1.2 and later with 2021 cipher suites. Recommended minimum for most use cases.

    • TLS_V1_3_2025: Supports TLS 1.3 and later with 2025 cipher suites. Provides the strongest security posture.

    " + "documentation":"

    The security policy for the custom domain. Defines the minimum TLS version and cipher suites that Amazon CloudFront supports when communicating with clients. For specific guidance, see Supported protocols and ciphers between viewers and CloudFront. Valid values are as follows:

    • TLS_V1_3_2025 (strictest): A post-quantum-ready policy requiring TLS 1.3. It provides the strongest security posture and is ideal for workloads where all clients and browsers are updated to the latest versions. Supported protocols and ciphers for TLSv1.3_2025.

    • TLS_V1_2_2021 (recommended): A post-quantum-ready policy which prefers TLS 1.3 but allows fallback to TLS 1.2 to accommodate older clients. It is the recommended minimum for typical commercial-grade consumer applications. Supported protocols and ciphers for TLSv1.2_2021.

    • TLS_V1 (strongly discouraged): Permits fallback to TLS 1.0. It offers the broadest compatibility, including support for legacy clients that are more than a decade old. This compatibility comes at the expense of allowing TLS versions and cryptographic algorithms that are no longer considered safe for commercial use. Supported protocols and ciphers for TLSv1.

    " } }, "documentation":"

    The configuration for a custom domain, including the SSL certificate and TLS security policy.

    " @@ -5643,6 +5802,37 @@ } } }, + "DescribeTermsByClientRequest":{ + "type":"structure", + "required":[ + "ClientId", + "UserPoolId", + "TermsName" + ], + "members":{ + "ClientId":{ + "shape":"ClientIdType", + "documentation":"

    The ID of the app client that the terms documents are associated with.

    " + }, + "UserPoolId":{ + "shape":"UserPoolIdType", + "documentation":"

    The ID of the user pool that contains the terms documents that you want to describe.

    " + }, + "TermsName":{ + "shape":"TermsNameType", + "documentation":"

    The name of the terms documents that you want to describe.

    " + } + } + }, + "DescribeTermsByClientResponse":{ + "type":"structure", + "members":{ + "Terms":{ + "shape":"TermsType", + "documentation":"

    A summary of the requested terms documents. Includes a unique identifier for later changes to the terms documents.

    " + } + } + }, "DescribeTermsRequest":{ "type":"structure", "required":[ @@ -6071,6 +6261,41 @@ "CUSTOMER_MANAGED_KEY" ] }, + "EumsSmsConfigurationType":{ + "type":"structure", + "required":["CallerArn"], + "members":{ + "CallerArn":{ + "shape":"ArnType", + "documentation":"

    The ARN of the IAM role that Amazon Cognito assumes to send SMS messages through Amazon Web Services End User Messaging SMS. The role must grant permission to call the sms-voice:SendTextMessage operation.

    " + }, + "ExternalId":{ + "shape":"StringType", + "documentation":"

    The external ID that Amazon Cognito includes when it assumes the CallerArn role. Use this value as a condition in the role trust policy to prevent the confused deputy problem.

    " + }, + "OriginationIdentity":{ + "shape":"StringType", + "documentation":"

    The origination identity that Amazon Web Services End User Messaging SMS uses to send messages to your users. This value can be one of the following:

    • A phone number – A long code, toll-free number, or short code that is assigned to your account.

    • A sender ID – An alphabetic name that identifies the message sender in supported countries.

    • A phone pool – A group of phone numbers that Amazon Web Services End User Messaging SMS selects from when it sends messages.

    You can provide an E.164 phone number or the ARN of the phone number, sender ID, or phone pool. Amazon Web Services End User Messaging SMS evaluates IAM authorization with the value that you provide. If the permissions policy of your CallerArn role scopes the sms-voice:SendTextMessage resource to a specific ARN, provide that same ARN. If the formats do not match, requests fail with an InvalidSmsRoleAccessPolicyException.

    Depending on the destination country, you must provide an origination identity. For country-specific requirements, see Supported countries and regions for SMS messaging in the Amazon Web Services End User Messaging SMS User Guide.

    " + }, + "ConfigurationSetName":{ + "shape":"StringType", + "documentation":"

    The name of the Amazon Web Services End User Messaging SMS configuration set that Amazon Cognito applies to messages, for logging and event destinations. If you omit this member, Amazon Cognito sends messages without applying a configuration set.

    " + }, + "InEntityId":{ + "shape":"StringType", + "documentation":"

    The principal entity ID required by India's Distributed Ledger Technology (DLT) regulations for SMS messages.

    " + }, + "InTemplateId":{ + "shape":"StringType", + "documentation":"

    The registered template ID for the message template required by India's DLT regulations for SMS messages.

    " + }, + "Region":{ + "shape":"RegionCodeType", + "documentation":"

    The Amazon Web Services Region of the Amazon Web Services End User Messaging SMS resources that Amazon Cognito uses to send messages. Amazon Web Services End User Messaging SMS must be available in your user pool's Region.

    If you omit this parameter, Amazon Cognito uses the same Region as your user pool. You can also set this parameter to your user pool's Region explicitly. Amazon Cognito rejects any other value with an InvalidParameterException.

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

    The configuration that Amazon Cognito uses to send SMS messages through Amazon Web Services End User Messaging SMS. Provide this structure in the EumsSms member of SmsConfigurationType to use Amazon Web Services End User Messaging SMS instead of Amazon SNS.

    " + }, "EventContextDataType":{ "type":"structure", "members":{ @@ -6356,6 +6581,40 @@ }, "documentation":"

    Represents the response from the server to the request to get the header information of the CSV file for the user import job.

    " }, + "GetClientTokenRequest":{ + "type":"structure", + "required":[ + "ClientId", + "Secret" + ], + "members":{ + "ClientId":{ + "shape":"ClientIdType", + "documentation":"

    The ID of the app client that requests the access token. The app client must have a client secret and the ALLOW_CLIENT_TOKEN_AUTH authentication flow.

    " + }, + "Secret":{ + "shape":"ClientSecretType", + "documentation":"

    An active secret for the app client.

    " + }, + "Scopes":{ + "shape":"ScopeListType", + "documentation":"

    The custom scopes to authorize in the access token, in the format resource-server-identifier/scope-name. Each scope must belong to a resource server in your user pool. If you don't specify any scopes, Amazon Cognito authorizes the scopes that are configured for the app client.

    " + }, + "ClientMetadata":{ + "shape":"ClientMetadataType", + "documentation":"

    A map of custom key-value pairs that you can provide as input for any custom workflows that this action triggers. You create custom workflows by assigning Lambda functions to user pool triggers.

    When Amazon Cognito invokes any of these functions, it passes a JSON payload, which the function receives as input. This payload contains a clientMetadata attribute that provides the data that you assigned to the ClientMetadata parameter in your request. In your function code, you can process the clientMetadata value to enhance your workflow for your specific needs.

    To review the Lambda trigger types that Amazon Cognito invokes at runtime with API requests, see Connecting API actions to Lambda triggers in the Amazon Cognito Developer Guide.

    When you use the ClientMetadata parameter, note that Amazon Cognito won't do the following:

    • Store the ClientMetadata value. This data is available only to Lambda triggers that are assigned to a user pool to support custom workflows. If your user pool configuration doesn't include triggers, the ClientMetadata parameter serves no purpose.

    • Validate the ClientMetadata value.

    • Encrypt the ClientMetadata value. Don't send sensitive information in this parameter.

    " + } + } + }, + "GetClientTokenResponse":{ + "type":"structure", + "members":{ + "ClientAuthenticationResult":{ + "shape":"ClientAuthenticationResultType", + "documentation":"

    The access token that Amazon Cognito issues for the app client, and its metadata.

    " + } + } + }, "GetDeviceRequest":{ "type":"structure", "required":["DeviceKey"], @@ -6614,7 +6873,7 @@ }, "ConfiguredUserAuthFactors":{ "shape":"ConfiguredUserAuthFactorsListType", - "documentation":"

    The authentication types that are available to the user with USER_AUTH sign-in, for example [\"PASSWORD\", \"WEB_AUTHN\"].

    " + "documentation":"

    The authentication types that are available to the user with USER_AUTH sign-in, for example [\"PASSWORD\", \"WEB_AUTHN\"].

    PASSWORD can only be used as a first authentication factor. SOFTWARE_TOKEN can only be used as an MFA factor. EMAIL_OTP, SMS_OTP, and WEB_AUTHN can be used as either a first authentication factor or an MFA factor. WEB_AUTHN is available as an MFA factor only when passkey MFA is enabled at the user pool level.

    " } } }, @@ -7978,6 +8237,12 @@ "documentation":"

    This exception is thrown when an operation is not available in the current region or for the current user pool configuration. This can occur when attempting to perform operations that are not supported in secondary replica regions.

    ", "exception":true }, + "OptionalArnType":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"(arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:([\\w+=/,.@-]*)?:[0-9]+:[\\w+=/,.@-]+(:[\\w+=/,.@-]+)?(:[\\w+=/,.@-]+)?)?" + }, "PaginationKey":{ "type":"string", "max":131072, @@ -7989,6 +8254,15 @@ "min":1, "pattern":"[\\S]+" }, + "PasswordHashingAlgorithmType":{ + "type":"string", + "enum":[ + "BCRYPT", + "SCRYPT", + "ARGON2ID", + "PBKDF2_SHA256" + ] + }, "PasswordHistoryPolicyViolationException":{ "type":"structure", "members":{ @@ -8943,7 +9217,7 @@ "members":{ "AllowedFirstAuthFactors":{ "shape":"AllowedFirstAuthFactorsListType", - "documentation":"

    The sign-in methods that a user pool supports as the first factor. You can permit users to start authentication with a standard username and password, or with other one-time password and hardware factors.

    " + "documentation":"

    The sign-in methods that a user pool supports as the first factor. You can permit users to start authentication with a standard username and password, or with other one-time password and hardware factors.

    SOFTWARE_TOKEN is not currently supported as a first auth factor. Do not include this value in AllowedFirstAuthFactors.

    " } }, "documentation":"

    The policy for allowed types of authentication in a user pool. To activate this setting, your user pool must be in the Essentials tier or higher.

    " @@ -9027,10 +9301,9 @@ }, "SmsConfigurationType":{ "type":"structure", - "required":["SnsCallerArn"], "members":{ "SnsCallerArn":{ - "shape":"ArnType", + "shape":"OptionalArnType", "documentation":"

    The Amazon Resource Name (ARN) of the Amazon SNS caller. This is the ARN of the IAM role in your Amazon Web Services account that Amazon Cognito will use to send SMS messages. SMS messages are subject to a spending limit.

    " }, "ExternalId":{ @@ -9040,6 +9313,10 @@ "SnsRegion":{ "shape":"RegionCodeType", "documentation":"

    The Amazon Web Services Region to use with Amazon SNS integration. You can choose the same Region as your user pool, or a supported Legacy Amazon SNS alternate Region.

    Amazon Cognito resources in the Asia Pacific (Seoul) Amazon Web Services Region must use your Amazon SNS configuration in the Asia Pacific (Tokyo) Region. For more information, see SMS message settings for Amazon Cognito user pools.

    " + }, + "EumsSms":{ + "shape":"EumsSmsConfigurationType", + "documentation":"

    The configuration for sending SMS messages through Amazon Web Services End User Messaging SMS, as an alternative to Amazon SNS. In a user pool, provide either the Amazon SNS configuration (SnsCallerArn) or this configuration, but not both. In Amazon Web Services Regions where Amazon SNS is not available, this configuration is required.

    " } }, "documentation":"

    User pool configuration for delivery of SMS messages with Amazon Simple Notification Service. To send SMS messages with Amazon SNS in the Amazon Web Services Region that you want, the Amazon Cognito user pool uses an Identity and Access Management (IAM) role in your Amazon Web Services account.

    " @@ -10273,6 +10550,10 @@ "CompletionMessage":{ "shape":"CompletionMessageType", "documentation":"

    The message returned when the user import job is completed.

    " + }, + "PasswordHashingAlgorithm":{ + "shape":"PasswordHashingAlgorithmType", + "documentation":"

    The password hashing algorithm used to generate the hashes in the CSV file for this import job.

    Valid values: BCRYPT | SCRYPT | ARGON2ID | PBKDF2_SHA256

    " } }, "documentation":"

    A user import job in a user pool. Describes the status of user import with a CSV file. For more information, see Importing users into user pools from a CSV file.

    " diff --git a/services/cognitosync/pom.xml b/services/cognitosync/pom.xml index 30fe7d98c804..a854b29afe3c 100644 --- a/services/cognitosync/pom.xml +++ b/services/cognitosync/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT cognitosync AWS Java SDK :: Services :: Amazon Cognito Sync diff --git a/services/cognitosync/src/main/resources/codegen-resources/customization.config b/services/cognitosync/src/main/resources/codegen-resources/customization.config index ac7b0e0410a2..595d43ca94aa 100644 --- a/services/cognitosync/src/main/resources/codegen-resources/customization.config +++ b/services/cognitosync/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listIdentityPoolUsage" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/cognitosync/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/cognitosync/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..07a4838dc366 --- /dev/null +++ b/services/cognitosync/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-sync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-sync-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-sync.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cognito-sync.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/cognitosync/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cognitosync/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 50740ddd486d..000000000000 --- a/services/cognitosync/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cognito-sync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cognito-sync-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cognito-sync.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cognito-sync.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/comprehend/pom.xml b/services/comprehend/pom.xml index 21f7ae42c402..93eb4bc94169 100644 --- a/services/comprehend/pom.xml +++ b/services/comprehend/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 comprehend diff --git a/services/comprehend/src/main/resources/codegen-resources/customization.config b/services/comprehend/src/main/resources/codegen-resources/customization.config index eba942663a0a..9ffd764631c0 100644 --- a/services/comprehend/src/main/resources/codegen-resources/customization.config +++ b/services/comprehend/src/main/resources/codegen-resources/customization.config @@ -8,6 +8,5 @@ "listKeyPhrasesDetectionJobs", "listSentimentDetectionJobs", "listTopicsDetectionJobs" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/comprehend/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/comprehend/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b40718577eac --- /dev/null +++ b/services/comprehend/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehend-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehend-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehend.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehend.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/comprehend/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/comprehend/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 352ee742b9cf..000000000000 --- a/services/comprehend/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehend-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehend-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehend.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://comprehend.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/comprehendmedical/pom.xml b/services/comprehendmedical/pom.xml index 9f66659476a4..7eebb7a75a24 100644 --- a/services/comprehendmedical/pom.xml +++ b/services/comprehendmedical/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT comprehendmedical AWS Java SDK :: Services :: ComprehendMedical diff --git a/services/comprehendmedical/src/main/resources/codegen-resources/customization.config b/services/comprehendmedical/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/comprehendmedical/src/main/resources/codegen-resources/customization.config +++ b/services/comprehendmedical/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0c5ed79abf93 --- /dev/null +++ b/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehendmedical-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehendmedical-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehendmedical.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://comprehendmedical.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a5cd6d314de5..000000000000 --- a/services/comprehendmedical/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehendmedical-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehendmedical-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://comprehendmedical.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://comprehendmedical.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/computeoptimizer/pom.xml b/services/computeoptimizer/pom.xml index 14f1b500ea13..ed9e3368d5b8 100644 --- a/services/computeoptimizer/pom.xml +++ b/services/computeoptimizer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT computeoptimizer AWS Java SDK :: Services :: Compute Optimizer diff --git a/services/computeoptimizer/src/main/resources/codegen-resources/customization.config b/services/computeoptimizer/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/computeoptimizer/src/main/resources/codegen-resources/customization.config +++ b/services/computeoptimizer/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..379f35c62eae --- /dev/null +++ b/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://compute-optimizer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://compute-optimizer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://compute-optimizer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://compute-optimizer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c562c4607570..000000000000 --- a/services/computeoptimizer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://compute-optimizer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://compute-optimizer-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://compute-optimizer.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://compute-optimizer.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/computeoptimizerautomation/pom.xml b/services/computeoptimizerautomation/pom.xml index 25a8055e8489..e52e5576912b 100644 --- a/services/computeoptimizerautomation/pom.xml +++ b/services/computeoptimizerautomation/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT computeoptimizerautomation AWS Java SDK :: Services :: Compute Optimizer Automation diff --git a/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..25a14803cda4 --- /dev/null +++ b/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aco-automation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aco-automation-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aco-automation.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aco-automation.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f996a3c3a7ab..000000000000 --- a/services/computeoptimizerautomation/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aco-automation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aco-automation-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aco-automation.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aco-automation.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/config/pom.xml b/services/config/pom.xml index 51df3c968338..3069b7bf6d4a 100644 --- a/services/config/pom.xml +++ b/services/config/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT config AWS Java SDK :: Services :: AWS Config diff --git a/services/config/src/main/resources/codegen-resources/customization.config b/services/config/src/main/resources/codegen-resources/customization.config index f126840772d3..be1c14aa1401 100644 --- a/services/config/src/main/resources/codegen-resources/customization.config +++ b/services/config/src/main/resources/codegen-resources/customization.config @@ -18,6 +18,5 @@ ], "excludedSimpleMethods": [ "startConfigRulesEvaluation" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/config/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/config/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..35b33a67361f --- /dev/null +++ b/services/config/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://config-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://config.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://config-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://config.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://config.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/config/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/config/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ed4f7d60ac08..000000000000 --- a/services/config/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://config-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://config.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://config-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://config.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://config.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/connect/pom.xml b/services/connect/pom.xml index 89a21cbf69b1..94289ad5c52f 100644 --- a/services/connect/pom.xml +++ b/services/connect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connect AWS Java SDK :: Services :: Connect diff --git a/services/connect/src/main/resources/codegen-resources/customization.config b/services/connect/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/connect/src/main/resources/codegen-resources/customization.config +++ b/services/connect/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/connect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..157f1b1237d4 --- /dev/null +++ b/services/connect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c87dbf336b6d..000000000000 --- a/services/connect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://connect.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://connect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://connect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/connect/src/main/resources/codegen-resources/paginators-1.json b/services/connect/src/main/resources/codegen-resources/paginators-1.json index 39049255b423..9bd897d7084d 100644 --- a/services/connect/src/main/resources/codegen-resources/paginators-1.json +++ b/services/connect/src/main/resources/codegen-resources/paginators-1.json @@ -153,6 +153,12 @@ "output_token": "NextToken", "result_key": "EvaluationFormSummaryList" }, + "ListExtractionDefinitions": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "output_token": "NextToken", + "result_key": "ExtractionDefinitionSummaryList" + }, "ListFlowAssociations": { "input_token": "NextToken", "limit_key": "MaxResults", @@ -211,6 +217,12 @@ "output_token": "NextToken", "result_key": "LexBots" }, + "ListMetrics": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "output_token": "NextToken", + "result_key": "MetricSummaryList" + }, "ListPhoneNumbers": { "input_token": "NextToken", "limit_key": "MaxResults", @@ -300,6 +312,16 @@ "output_token": "NextToken", "result_key": "SecurityKeys" }, + "ListSecurityProfileAIAgents": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "non_aggregate_keys": [ + "LastModifiedRegion", + "LastModifiedTime" + ], + "output_token": "NextToken", + "result_key": "AllowedAIAgents" + }, "ListSecurityProfileApplications": { "input_token": "NextToken", "limit_key": "MaxResults", @@ -484,6 +506,15 @@ "output_token": "NextToken", "result_key": "HoursOfOperations" }, + "SearchMetrics": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "non_aggregate_keys": [ + "ApproximateTotalCount" + ], + "output_token": "NextToken", + "result_key": "Metrics" + }, "SearchPredefinedAttributes": { "input_token": "NextToken", "limit_key": "MaxResults", @@ -535,6 +566,15 @@ "output_token": "NextToken", "result_key": "RoutingProfiles" }, + "SearchRules": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "non_aggregate_keys": [ + "ApproximateTotalCount" + ], + "output_token": "NextToken", + "result_key": "Rules" + }, "SearchSecurityProfiles": { "input_token": "NextToken", "limit_key": "MaxResults", diff --git a/services/connect/src/main/resources/codegen-resources/service-2.json b/services/connect/src/main/resources/codegen-resources/service-2.json index e88a33582b6e..7849eb57cd34 100644 --- a/services/connect/src/main/resources/codegen-resources/service-2.json +++ b/services/connect/src/main/resources/codegen-resources/service-2.json @@ -101,7 +101,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServiceException"} ], - "documentation":"

    Associates a queued contact with an agent.

    Use cases

    Following are common uses cases for this API:

    • Programmatically assign queued contacts to available users.

    • Leverage the IAM context key connect:PreferredUserArn to restrict contact association to specific preferred user.

    Important things to know

    • Use this API with chat, email, and task contacts. It does not support voice contacts.

    • Use it to associate contacts with users regardless of their current state, including custom states. Ensure your application logic accounts for user availability before making associations.

    • It honors the IAM context key connect:PreferredUserArn to prevent unauthorized contact associations.

    • It respects the IAM context key connect:PreferredUserArn to enforce authorization controls and prevent unauthorized contact associations. Verify that your IAM policies are properly configured to support your intended use cases.

    • The service quota Queues per routing profile per instance applies to manually assigned queues, too. For more information about this quota, see Connect Customer quotas in the Connect Customer Administrator Guide.

    Endpoints: See Connect Customer endpoints and quotas.

    " + "documentation":"

    Associates a queued contact with an agent.

    Use cases

    Following are common uses cases for this API:

    • Programmatically assign queued contacts to available users.

    • Leverage the IAM context key connect:PreferredUserArn to restrict contact association to specific preferred user.

    Important things to know

    • Use this API with chat, email, task, and voice contacts. For voice callbacks, this API does not support customer-first mode.

    • This API can be used to offer a contact to an agent even if the agent is currently at maximum concurrency for the channel.

    • Use it to associate contacts with users regardless of their current state, including custom states. Ensure your application logic accounts for user availability before making associations.

    • It honors the IAM context key connect:PreferredUserArn to prevent unauthorized contact associations.

    • It respects the IAM context key connect:PreferredUserArn to enforce authorization controls and prevent unauthorized contact associations. Verify that your IAM policies are properly configured to support your intended use cases.

    • The service quota Queues per routing profile per instance applies to manually assigned queues, too. For more information about this quota, see Connect Customer quotas in the Connect Customer Administrator Guide.

    Endpoints: See Connect Customer endpoints and quotas.

    " }, "AssociateDefaultVocabulary":{ "name":"AssociateDefaultVocabulary", @@ -174,7 +174,7 @@ {"shape":"ConditionalOperationFailedException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Associates a set of hours of operations with another hours of operation. Refer to Administrator Guide here for more information on inheriting overrides from parent hours of operation(s).

    " + "documentation":"

    Associates a set of hours of operations with another hours of operation. For more information about inheriting overrides from parent hours of operation, see Hours of operation overrides in the Administrator Guide.

    " }, "AssociateInstanceStorageConfig":{ "name":"AssociateInstanceStorageConfig", @@ -847,6 +847,25 @@ "documentation":"

    Creates an evaluation form in the specified Connect Customer instance. The form can be used to define questions related to agent performance, and create sections to organize such questions. Question and section identifiers cannot be duplicated within the same evaluation form.

    ", "idempotent":true }, + "CreateExtractionDefinition":{ + "name":"CreateExtractionDefinition", + "http":{ + "method":"POST", + "requestUri":"/extraction-definitions/{InstanceId}" + }, + "input":{"shape":"CreateExtractionDefinitionRequest"}, + "output":{"shape":"CreateExtractionDefinitionResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceConflictException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates an extraction definition in the specified Connect Customer instance. An extraction definition specifies how structured data is extracted from customer interactions using generative AI, including the prompt hint that guides extraction and the behavior when a value cannot be found.

    " + }, "CreateHoursOfOperation":{ "name":"CreateHoursOfOperation", "http":{ @@ -920,6 +939,27 @@ ], "documentation":"

    Creates an Amazon Web Services resource association with an Connect Customer instance.

    " }, + "CreateMetric":{ + "name":"CreateMetric", + "http":{ + "method":"PUT", + "requestUri":"/metrics/definitions/{InstanceId}" + }, + "input":{"shape":"CreateMetricRequest"}, + "output":{"shape":"CreateMetricResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"DuplicateResourceException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Creates a new metric definition for the specified Connect Customer instance. You can create custom metrics that use formulas referencing existing Amazon Web Services-managed metrics, optionally with filters applied.

    ", + "idempotent":true + }, "CreateNotification":{ "name":"CreateNotification", "http":{ @@ -1395,7 +1435,7 @@ {"shape":"InternalServiceException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Deletes the specified fields containing personally identifiable information (PII) from a contact in the specified Connect Customer instance. This operation redacts PII (such as customer endpoints, additional email recipients, and the email subject) from the contact and its associated contact trace record (CTR). The contact must be in a terminated state.

    This operation performs a hard deletion of the specified PII and cannot be undone. There is no retention period; after the data is deleted, it cannot be recovered. Only fields that Connect Customer identifies and stores as PII are removed. Any PII that you place in fields outside the scope of this operation remains your responsibility to remove.

    " + "documentation":"

    Deletes the specified fields containing personally identifiable information (PII) from a contact in the specified Connect Customer instance. We redact PII (such as customer endpoints, additional email recipients, and the email subject) from the contact and its associated contact trace record (CTR). The contact must be in a terminated state.

    This deletion is permanent and cannot be undone. Performing this operation permanently deletes the specified PII. There is no retention period; you cannot recover the data after deletion. We remove only the fields that Connect Customer identifies and stores as PII. Any PII that you place in fields outside the scope of this operation remains your responsibility to remove.

    " }, "DeleteContactEvaluation":{ "name":"DeleteContactEvaluation", @@ -1578,6 +1618,23 @@ "documentation":"

    Deletes an evaluation form in the specified Connect Customer instance.

    • If the version property is provided, only the specified version of the evaluation form is deleted.

    • If no version is provided, then the full form (all versions) is deleted.

    ", "idempotent":true }, + "DeleteExtractionDefinition":{ + "name":"DeleteExtractionDefinition", + "http":{ + "method":"DELETE", + "requestUri":"/extraction-definitions/{InstanceId}/{ExtractionDefinitionId}" + }, + "input":{"shape":"DeleteExtractionDefinitionRequest"}, + "output":{"shape":"DeleteExtractionDefinitionResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes an extraction definition from the specified Connect Customer instance.

    " + }, "DeleteHoursOfOperation":{ "name":"DeleteHoursOfOperation", "http":{ @@ -1639,6 +1696,25 @@ ], "documentation":"

    Deletes an Amazon Web Services resource association from an Connect Customer instance. The association must not have any use cases associated with it.

    " }, + "DeleteMetric":{ + "name":"DeleteMetric", + "http":{ + "method":"DELETE", + "requestUri":"/metrics/definitions/{InstanceId}/{MetricId}" + }, + "input":{"shape":"DeleteMetricRequest"}, + "output":{"shape":"DeleteMetricResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceInUseException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Deletes an existing metric from the specified Connect Customer instance. This operation fails with ResourceConflictException if the metric is currently in use in a dashboard.

    " + }, "DeleteNotification":{ "name":"DeleteNotification", "http":{ @@ -2228,6 +2304,23 @@ ], "documentation":"

    Describes an evaluation form in the specified Connect Customer instance. If the version property is not provided, the latest version of the evaluation form is described.

    " }, + "DescribeExtractionDefinition":{ + "name":"DescribeExtractionDefinition", + "http":{ + "method":"GET", + "requestUri":"/extraction-definitions/{InstanceId}/{ExtractionDefinitionId}" + }, + "input":{"shape":"DescribeExtractionDefinitionRequest"}, + "output":{"shape":"DescribeExtractionDefinitionResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes an extraction definition in the specified Connect Customer instance.

    " + }, "DescribeHoursOfOperation":{ "name":"DescribeHoursOfOperation", "http":{ @@ -2311,6 +2404,25 @@ ], "documentation":"

    This API is in preview release for Connect Customer and is subject to change.

    Retrieves the current storage configurations for the specified resource type, association ID, and instance ID.

    " }, + "DescribeMetric":{ + "name":"DescribeMetric", + "http":{ + "method":"GET", + "requestUri":"/metrics/definitions/{InstanceId}/{MetricId}" + }, + "input":{"shape":"DescribeMetricRequest"}, + "output":{"shape":"DescribeMetricResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Retrieves the full definition of an existing metric from the specified Connect Customer instance.

    ", + "readonly":true + }, "DescribeNotification":{ "name":"DescribeNotification", "http":{ @@ -2703,7 +2815,7 @@ {"shape":"InternalServiceException"}, {"shape":"ConditionalOperationFailedException"} ], - "documentation":"

    Disassociates a set of hours of operations with another hours of operation. Refer to Administrator Guide here for more information on inheriting overrides from parent hours of operation(s).

    " + "documentation":"

    Disassociates a set of hours of operations with another hours of operation. For more information about inheriting overrides from parent hours of operation, see Hours of operation overrides in the Administrator Guide.

    " }, "DisassociateInstanceStorageConfig":{ "name":"DisassociateInstanceStorageConfig", @@ -2991,6 +3103,23 @@ ], "documentation":"

    Retrieves contact metric data for a specified contact.

    Use cases

    Following are common use cases for position in queue and estimated wait time:

    • Customer-Facing Wait Time Announcements - Display or announce the estimated wait time and position in queue to customers before or during their queue experience.

    • Callback Offerings - Offer customers a callback option when the estimated wait time or position in queue exceeds a defined threshold.

    • Queue Routing Decisions - Route incoming contacts to less congested queues by comparing estimated wait time and position in queue across multiple queues.

    • Self-Service Deflection - Redirect customers to self-service options like chatbots or FAQs when estimated wait time is high or position in queue is unfavorable.

    Important things to know

    • Metrics are only available while the contact is actively in queue.

    • For more information, see the Position in queue metric in the Connect Customer Administrator Guide.

    Endpoints: See Connect Customer endpoints and quotas.

    " }, + "GetCrossRegionRouting":{ + "name":"GetCrossRegionRouting", + "http":{ + "method":"GET", + "requestUri":"/cross-region-routing/{InstanceId}" + }, + "input":{"shape":"GetCrossRegionRoutingRequest"}, + "output":{"shape":"GetCrossRegionRoutingResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the current cross-region routing configuration for an Amazon Connect Global Resiliency instance enabled for global routing. This operation returns whether cross-region routing is currently enabled or disabled (isolated) for the instance.

    This operation is available only for Amazon Connect Global Resiliency instances enabled for global routing.

    " + }, "GetCurrentMetricData":{ "name":"GetCurrentMetricData", "http":{ @@ -3383,7 +3512,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServiceException"} ], - "documentation":"

    Provides information about the child hours of operations for the specified parent hours of operation.

    For more information about child hours of operations, see Link overrides from different hours of operation in the Administrator Guide.

    " + "documentation":"

    Provides information about the child hours of operations for the specified parent hours of operation.

    For more information about child hours of operations, see Link overrides from different hours of operation in the Administrator Guide.

    " }, "ListContactEvaluations":{ "name":"ListContactEvaluations", @@ -3612,6 +3741,22 @@ ], "documentation":"

    Lists all security profiles attached to a Q in Connect AIAgent Entity in an Amazon Connect instance.

    " }, + "ListEvaluationFormAIVersions":{ + "name":"ListEvaluationFormAIVersions", + "http":{ + "method":"GET", + "requestUri":"/instances/{InstanceId}/evaluation-form-ai-versions" + }, + "input":{"shape":"ListEvaluationFormAIVersionsRequest"}, + "output":{"shape":"ListEvaluationFormAIVersionsResponse"}, + "errors":[ + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Lists the available AI versions for evaluation forms in the specified Connect Customer instance.

    " + }, "ListEvaluationFormVersions":{ "name":"ListEvaluationFormVersions", "http":{ @@ -3644,6 +3789,23 @@ ], "documentation":"

    Lists evaluation forms in the specified Connect Customer instance.

    " }, + "ListExtractionDefinitions":{ + "name":"ListExtractionDefinitions", + "http":{ + "method":"GET", + "requestUri":"/extraction-definitions/{InstanceId}" + }, + "input":{"shape":"ListExtractionDefinitionsRequest"}, + "output":{"shape":"ListExtractionDefinitionsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Lists extraction definitions in the specified Connect Customer instance.

    " + }, "ListFlowAssociations":{ "name":"ListFlowAssociations", "http":{ @@ -3794,6 +3956,25 @@ ], "documentation":"

    This API is in preview release for Connect Customer and is subject to change.

    Returns a paginated list of all the Amazon Lex V1 bots currently associated with the instance. To return both Amazon Lex V1 and V2 bots, use the ListBots API.

    " }, + "ListMetrics":{ + "name":"ListMetrics", + "http":{ + "method":"GET", + "requestUri":"/metrics/definitions/{InstanceId}" + }, + "input":{"shape":"ListMetricsRequest"}, + "output":{"shape":"ListMetricsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Retrieves a paginated list of metric summaries for the specified Connect Customer instance. Use pagination to ensure that the operation returns quickly and successfully.

    ", + "readonly":true + }, "ListNotifications":{ "name":"ListNotifications", "http":{ @@ -4052,6 +4233,23 @@ ], "documentation":"

    This API is in preview release for Connect Customer and is subject to change.

    Returns a paginated list of all security keys associated with the instance.

    " }, + "ListSecurityProfileAIAgents":{ + "name":"ListSecurityProfileAIAgents", + "http":{ + "method":"GET", + "requestUri":"/security-profiles-ai-agents/{InstanceId}/{SecurityProfileId}" + }, + "input":{"shape":"ListSecurityProfileAIAgentsRequest"}, + "output":{"shape":"ListSecurityProfileAIAgentsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Returns a list of the allowed AI agents in a specific security profile.

    " + }, "ListSecurityProfileApplications":{ "name":"ListSecurityProfileApplications", "http":{ @@ -4733,6 +4931,24 @@ ], "documentation":"

    Searches the hours of operation in an Connect Customer instance, with optional filtering.

    " }, + "SearchMetrics":{ + "name":"SearchMetrics", + "http":{ + "method":"POST", + "requestUri":"/search-metrics" + }, + "input":{"shape":"SearchMetricsRequest"}, + "output":{"shape":"SearchMetricsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Searches for metrics in the specified Connect Customer instance using search criteria and optional tag-based filters. Use pagination to ensure that the operation returns quickly and successfully.

    " + }, "SearchNotifications":{ "name":"SearchNotifications", "http":{ @@ -4854,6 +5070,24 @@ ], "documentation":"

    Searches routing profiles in an Connect Customer instance, with optional filtering.

    SearchRoutingProfiles does not populate LastModifiedRegion, LastModifiedTime, MediaConcurrencies.CrossChannelBehavior, and AgentAvailabilityTimer in its response, but DescribeRoutingProfile does.

    " }, + "SearchRules":{ + "name":"SearchRules", + "http":{ + "method":"POST", + "requestUri":"/search-rules" + }, + "input":{"shape":"SearchRulesRequest"}, + "output":{"shape":"SearchRulesResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Searches rules in an Connect Customer instance, with optional filtering.

    " + }, "SearchSecurityProfiles":{ "name":"SearchSecurityProfiles", "http":{ @@ -5046,6 +5280,25 @@ ], "documentation":"

    Sends an outbound web notification to a customer's web browser for outbound campaigns. For more information about outbound campaigns, see Set up Connect Customer outbound campaigns.

    Only the Connect Customer outbound campaigns service principal is allowed to assume a role in your account and call this API.

    " }, + "StartAssistantContact":{ + "name":"StartAssistantContact", + "http":{ + "method":"PUT", + "requestUri":"/contact/assistant" + }, + "input":{"shape":"StartAssistantContactRequest"}, + "output":{"shape":"StartAssistantContactResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"}, + {"shape":"LimitExceededException"} + ], + "documentation":"

    Starts a chat contact with an AI agent.

    Use the returned ParticipantToken with the CreateParticipantConnection operation.

    For more information about chat, see the following topics in the Connect Customer Administrator Guide:

    " + }, "StartAttachedFileUpload":{ "name":"StartAttachedFileUpload", "http":{ @@ -5062,7 +5315,7 @@ {"shape":"ResourceConflictException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Provides a pre-signed Amazon S3 URL in response for uploading your content.

    You may only use this API to upload attachments to an Connect Customer Case or Connect Customer Email.

    " + "documentation":"

    Provides a pre-signed Amazon S3 URL in response for uploading your content.

    You may only use this API to upload attachments to a Connect Customer Case, Connect Customer Email, or Connect Customer Task.

    " }, "StartChatContact":{ "name":"StartChatContact", @@ -5115,7 +5368,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ResourceConflictException"} ], - "documentation":"

    Starts an empty evaluation in the specified Connect Customer instance, using the given evaluation form for the particular contact. The evaluation form version used for the contact evaluation corresponds to the currently activated version. If no version is activated for the evaluation form, the contact evaluation cannot be started.

    Evaluations created through the public API do not contain answer values suggested from automation.

    ", + "documentation":"

    Starts an empty evaluation in the specified Connect Customer instance, using the given evaluation form for the particular contact. The evaluation form version used for the contact evaluation corresponds to the currently activated version. If no version is activated for the evaluation form, the contact evaluation cannot be started.

    ", "idempotent":true }, "StartContactMediaProcessing":{ @@ -5333,7 +5586,8 @@ {"shape":"InvalidRequestException"}, {"shape":"InvalidParameterException"}, {"shape":"LimitExceededException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} ], "documentation":"

    Places an inbound in-app, web, or video call to a contact, and then initiates the flow. It performs the actions in the flow that are specified (in ContactFlowId) and present in the Connect Customer instance (specified as InstanceId).

    " }, @@ -5489,7 +5743,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Adds the specified tags to the specified resource.

    Some of the supported resource types are agents, routing profiles, queues, quick connects, flows, agent statuses, hours of operation, phone numbers, security profiles, and task templates. For a complete list, see Tagging resources in Connect Customer.

    For sample policies that use tags, see Connect Customer Identity-Based Policy Examples in the Connect Customer Administrator Guide.

    " + "documentation":"

    Adds the specified tags to the specified resource.

    Some of the supported resource types are agents, routing profiles, queues, quick connects, flows, agent statuses, hours of operation, phone numbers, security profiles, task templates, and custom metrics. For a complete list, see Tagging resources in Connect Customer.

    For sample policies that use tags, see Connect Customer Identity-Based Policy Examples in the Connect Customer Administrator Guide.

    " }, "TransferContact":{ "name":"TransferContact", @@ -5798,6 +6052,43 @@ ], "documentation":"

    Updates the scheduled time of a task contact that is already scheduled.

    " }, + "UpdateContactTaskTemplate":{ + "name":"UpdateContactTaskTemplate", + "http":{ + "method":"POST", + "requestUri":"/contact/task-template" + }, + "input":{"shape":"UpdateContactTaskTemplateRequest"}, + "output":{"shape":"UpdateContactTaskTemplateResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"PropertyValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"LimitExceededException"} + ], + "documentation":"

    Updates the task template association on an existing task contact. You can update the task template on a contact before assignment to support tasks that are created without a template (for example Rules or disconnect flows) or change the agent interaction form to represent the latest task data (for example an initial request that was submitted as a refund gets updated to an account cancellation and requires a new template).

    This operation can only be used with task contacts that are in progress and not connected to an agent. A task template can be updated a maximum of 5 times per contact.

    The task's references must be compatible with the fields of the target task template. If the target template has a required field, the task must have a corresponding reference with a matching name and compatible type. The following task template field types map to reference types:

    • TEXT, TEXT_AREA, BOOLEAN, and SINGLE_SELECT map to references of type STRING.

    • NUMBER maps to references of type NUMBER.

    • DATE_TIME maps to references of type DATE.

    • URL maps to references of type URL.

    • EMAIL maps to references of type EMAIL.

    References corresponding to TEXT fields must be fewer than 512 characters. TEXT_AREA fields must be fewer than 4,096 characters. BOOLEAN fields must have a value of true or false.

    An InvalidRequestException occurs when UpdateContactTaskTemplate is called on a connected or terminated task, when it is called on non-task contacts, and when the task contact already uses the provided task template. A PropertyValidationException occurs when the task's references conflict with the task template's fields, for example if the task is missing a reference that matches a required field, or if the task has a reference that matches a required field's name but not its datatype.

    " + }, + "UpdateCrossRegionRouting":{ + "name":"UpdateCrossRegionRouting", + "http":{ + "method":"PUT", + "requestUri":"/cross-region-routing/{InstanceId}" + }, + "input":{"shape":"UpdateCrossRegionRoutingRequest"}, + "output":{"shape":"UpdateCrossRegionRoutingResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Updates the cross-region routing configuration for an Amazon Connect Global Resiliency instance enabled for global routing. When invoked with IsolatedAll set to true, this operation disables cross-region routing, meaning contacts originating in one Region will no longer be routed to agents in another Region.

    This operation is available only for Amazon Connect Global Resiliency instances enabled for global routing. Reporting and contact search continue to operate globally after you use this operation.

    " + }, "UpdateDataTableAttribute":{ "name":"UpdateDataTableAttribute", "http":{ @@ -5896,6 +6187,24 @@ "documentation":"

    Updates details about a specific evaluation form version in the specified Connect Customer instance. Question and section identifiers cannot be duplicated within the same evaluation form.

    This operation does not support partial updates. Instead it does a full update of evaluation form content.

    ", "idempotent":true }, + "UpdateExtractionDefinition":{ + "name":"UpdateExtractionDefinition", + "http":{ + "method":"PUT", + "requestUri":"/extraction-definitions/{InstanceId}/{ExtractionDefinitionId}" + }, + "input":{"shape":"UpdateExtractionDefinitionRequest"}, + "output":{"shape":"UpdateExtractionDefinitionResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceConflictException"} + ], + "documentation":"

    Updates an extraction definition in the specified Connect Customer instance.

    " + }, "UpdateHoursOfOperation":{ "name":"UpdateHoursOfOperation", "http":{ @@ -5963,6 +6272,45 @@ ], "documentation":"

    This API is in preview release for Connect Customer and is subject to change.

    Updates an existing configuration for a resource type. This API is idempotent.

    " }, + "UpdateMetricContent":{ + "name":"UpdateMetricContent", + "http":{ + "method":"POST", + "requestUri":"/metrics/definitions/{InstanceId}/{MetricId}/content" + }, + "input":{"shape":"UpdateMetricContentRequest"}, + "output":{"shape":"UpdateMetricContentResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Updates the calculation, unit, and/or trend indicator of an existing metric in the specified Connect Customer instance.

    ", + "idempotent":true + }, + "UpdateMetricMetadata":{ + "name":"UpdateMetricMetadata", + "http":{ + "method":"POST", + "requestUri":"/metrics/definitions/{InstanceId}/{MetricId}/metadata" + }, + "input":{"shape":"UpdateMetricMetadataRequest"}, + "output":{"shape":"UpdateMetricMetadataResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"DuplicateResourceException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Updates the name and/or description of an existing metric in the specified Connect Customer instance.

    ", + "idempotent":true + }, "UpdateNotificationContent":{ "name":"UpdateNotificationContent", "http":{ @@ -6670,6 +7018,43 @@ } }, "shapes":{ + "ACGRInstanceArn":{ + "type":"string", + "pattern":"^arn:([a-zA-Z0-9-]+):connect:[a-z]+-[a-z-]+-[0-9]+:[0-9]+:instance/[a-zA-Z0-9_-]+$" + }, + "ACGRInstanceIdOrArn":{ + "type":"string", + "max":250, + "min":1, + "pattern":"^(arn:([a-zA-Z0-9-]+):connect:[a-z]+-[a-z-]+-[0-9]+:[0-9]+:instance/)?[a-zA-Z0-9_-]+$" + }, + "ACGRTrafficDistributionGroupArn":{ + "type":"string", + "pattern":"^arn:([a-zA-Z0-9-]+):connect:[a-z]+-[a-z-]+-[0-9]+:[0-9]+:traffic-distribution-group/[a-zA-Z0-9_-]+$" + }, + "ACGRTrafficDistributionGroupId":{ + "type":"string", + "pattern":"^[a-zA-Z0-9_-]+$" + }, + "AIAgent":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the AI agent.

    " + }, + "Type":{ + "shape":"AIAgentType", + "documentation":"

    The type of the AI agent. The valid value is THIRD_PARTY.

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

    Information about an AI agent that a security profile allows access to for Agent-to-Agent authorization.

    " + }, + "AIAgentType":{ + "type":"string", + "documentation":"

    The type of the AI agent.

    ", + "enum":["THIRD_PARTY"] + }, "ARN":{"type":"string"}, "AWSAccountId":{"type":"string"}, "AccessDeniedException":{ @@ -6717,7 +7102,8 @@ "UPDATE_CASE", "ASSIGN_SLA", "END_ASSOCIATED_TASKS", - "SUBMIT_AUTO_EVALUATION" + "SUBMIT_AUTO_EVALUATION", + "EXTRACT_INFORMATION" ] }, "ActivateEvaluationFormRequest":{ @@ -7001,6 +7387,10 @@ "VoiceEnhancementMode":{ "shape":"VoiceEnhancementMode", "documentation":"

    The voice enhancement mode used by the agent as the call is ending. Valid values: VOICE_ISOLATION | NOISE_SUPPRESSION | NONE. A value of null indicates this mode has not yet been set for this user.

    " + }, + "ActiveRegion":{ + "shape":"ActiveRegion", + "documentation":"

    The Region where the agent was active when they handled the contact. For Amazon Connect Global Resiliency instances enabled for global routing, this indicates the Region in which the agent's session was established at the time of the contact.

    " } }, "documentation":"

    Information about the agent who accepted the contact.

    " @@ -7248,7 +7638,8 @@ "AiAgentId":{ "type":"string", "max":128, - "min":0 + "min":0, + "pattern":"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}(:[A-Z0-9_$]+){0,1}$|^arn:[a-z-]*?:wisdom:[a-z0-9-]*?:[0-9]{12}:[a-z-]*?/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}(?:/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}){0,2}(:[A-Z0-9_$]+){0,1}" }, "AiAgentInfo":{ "type":"structure", @@ -7268,6 +7659,17 @@ }, "documentation":"

    Information of the AI agent involved in the contact.

    " }, + "AiAgentInput":{ + "type":"structure", + "required":["AiAgentId"], + "members":{ + "AiAgentId":{ + "shape":"AiAgentId", + "documentation":"

    The identifier of the AI agent that participates in the contact.

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

    The AI agent that participates in the contact, including its identifier.

    " + }, "AiAgentSearchCriteria":{ "type":"structure", "members":{ @@ -7346,6 +7748,11 @@ "member":{"shape":"AliasConfiguration"}, "max":1 }, + "AllowedAIAgents":{ + "type":"list", + "member":{"shape":"AIAgent"}, + "max":100 + }, "AllowedAccessControlTags":{ "type":"map", "key":{"shape":"SecurityProfilePolicyKey"}, @@ -8035,7 +8442,7 @@ }, "ManualAssignmentQueueConfigs":{ "shape":"RoutingProfileManualAssignmentQueueConfigList", - "documentation":"

    The manual assignment queues to associate with this routing profile.

    Note: Use this config for chat, email, and task contacts. It does not support voice contacts.

    " + "documentation":"

    The manual assignment queues to associate with this routing profile.

    For voice contacts, manual assignment supports only agent-first callback contacts. Chat, email, and task contacts are fully supported.

    " } } }, @@ -8295,7 +8702,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. Cases are the only current supported resource.

    This value must be a valid ARN.

    " + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    " }, "Tags":{ "shape":"TagMap", @@ -8810,6 +9217,32 @@ }, "documentation":"

    Information about automatic fail configuration for an evaluation form.

    " }, + "AvailableFilter":{ + "type":"structure", + "members":{ + "Id":{ + "shape":"FilterId", + "documentation":"

    The identifier of the filter.

    " + }, + "Type":{ + "shape":"AvailableFilterType", + "documentation":"

    The type of the filter. Valid values: METRIC_LEVEL | RESOURCE_LEVEL.

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

    A filter that is available for use with the metric. Part of an AvailableFilterList that describes the filters that are available for use with the metric.

    " + }, + "AvailableFilterList":{ + "type":"list", + "member":{"shape":"AvailableFilter"} + }, + "AvailableFilterType":{ + "type":"string", + "documentation":"

    The type of an available metric filter. Valid values: METRIC_LEVEL | RESOURCE_LEVEL.

    ", + "enum":[ + "METRIC_LEVEL", + "RESOURCE_LEVEL" + ] + }, "AvailableNumberSummary":{ "type":"structure", "members":{ @@ -9248,7 +9681,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases and Email.

    This value must be a valid ARN.

    ", + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    ", "location":"querystring", "locationName":"associatedResourceArn" } @@ -9485,6 +9918,40 @@ "max":128, "min":1 }, + "CalculationComponent":{ + "type":"structure", + "required":["Alias"], + "members":{ + "Alias":{ + "shape":"ComponentAlias", + "documentation":"

    The alias used to reference this component in the calculation expression.

    " + }, + "MetricName":{ + "shape":"MetricName", + "documentation":"

    The name of an AWS-managed metric used in this calculation component (for example, CONTACTS_HANDLED). Mutually exclusive with MetricId.

    " + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The ARN of an AWS-managed metric used in this calculation component. Mutually exclusive with MetricName.

    " + }, + "MetricFilters":{ + "shape":"MetricFilterList", + "documentation":"

    The filters applied to the calculation component.

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

    Represents a component metric referenced in a custom metric calculation formula.

    " + }, + "CalculationComponentList":{ + "type":"list", + "member":{"shape":"CalculationComponent"}, + "max":5, + "min":1 + }, + "CalculationExpression":{ + "type":"string", + "max":1024, + "min":1 + }, "Campaign":{ "type":"structure", "members":{ @@ -9549,6 +10016,14 @@ "key":{"shape":"Channel"}, "value":{"shape":"IntegerCount"} }, + "ChannelWorkloadBehaviorType":{ + "type":"string", + "enum":[ + "ROUTE_CURRENT_CHANNEL_CURRENT_WORKLOADTYPE_ONLY", + "ROUTE_CURRENT_CHANNEL_ANY_WORKLOADTYPE_ONLY", + "ROUTE_ANY_CHANNEL_ANY_WORKLOAD_TYPE" + ] + }, "Channels":{ "type":"list", "member":{"shape":"Channel"}, @@ -9867,7 +10342,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases and Email.

    This value must be a valid ARN.

    ", + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    ", "location":"querystring", "locationName":"associatedResourceArn" } @@ -9879,10 +10354,15 @@ "members":{}, "documentation":"Response from CompleteAttachedFileUpload API" }, + "ComponentAlias":{ + "type":"string", + "max":128, + "min":1 + }, "Concurrency":{ "type":"integer", "max":10, - "min":1 + "min":0 }, "Condition":{ "type":"structure", @@ -10147,6 +10627,36 @@ }, "documentation":"

    A structure that defines search criteria for contacts using analysis outputs from Connect Customer Contact Lens.

    " }, + "ContactAnalysisReference":{ + "type":"structure", + "members":{ + "Name":{ + "shape":"ReferenceKey", + "documentation":"

    Identifier of the contact analysis reference.

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

    The location path of the contact analysis reference.

    " + }, + "Status":{ + "shape":"ReferenceStatus", + "documentation":"

    Status of the contact analysis reference type.

    " + }, + "Arn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the contact analysis reference.

    " + }, + "AnalyticsMode":{ + "shape":"AnalyticsMode", + "documentation":"

    The analytics mode of the contact analysis.

    " + }, + "IsRedacted":{ + "shape":"NullableBoolean", + "documentation":"

    Indicates whether sensitive data has been redacted from the contact analysis.

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

    Information about a reference when the referenceType is CONTACT_ANALYSIS. Otherwise, null.

    " + }, "ContactConfiguration":{ "type":"structure", "required":["ContactId"], @@ -11003,7 +11513,7 @@ "members":{ "Message":{"shape":"Message"} }, - "documentation":"

    The contact has not been disconnected and is not in a terminated state. PII can be deleted only from a contact that has been disconnected. This error is returned with an HTTP 409 status code.

    ", + "documentation":"

    The contact has not been disconnected and is not in a terminated state. To delete PII, disconnect the contact first. Wait for it to reach the terminated state, then retry the request.

    ", "error":{"httpStatusCode":409}, "exception":true }, @@ -12041,6 +12551,10 @@ "LanguageConfiguration":{ "shape":"EvaluationFormLanguageConfiguration", "documentation":"

    Configuration for language settings of the evaluation form.

    " + }, + "AIVersion":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The AI version to use for the evaluation form. This specifies which AI model version is used for automated evaluations.

    " } } }, @@ -12061,6 +12575,60 @@ } } }, + "CreateExtractionDefinitionRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "Name", + "ExtractionConfiguration" + ], + "members":{ + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If not provided, the Amazon Web Services SDK populates this field.

    ", + "idempotencyToken":true + }, + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "Name":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    A unique name of the extraction definition.

    " + }, + "ExtractionConfiguration":{ + "shape":"ExtractionConfiguration", + "documentation":"

    The configuration that defines how data is extracted, including the prompt hint and not-found behavior.

    " + }, + "Display":{ + "shape":"ExtractionDefinitionDisplay", + "documentation":"

    The display settings for the extraction definition, including the label shown in the agent workspace.

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

    The tags used to organize, track, or control access for this resource.

    " + } + } + }, + "CreateExtractionDefinitionResponse":{ + "type":"structure", + "required":[ + "ExtractionDefinitionArn", + "ExtractionDefinitionId" + ], + "members":{ + "ExtractionDefinitionArn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the extraction definition.

    " + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition.

    " + } + } + }, "CreateHoursOfOperationOverrideRequest":{ "type":"structure", "required":[ @@ -12110,7 +12678,7 @@ }, "OverrideType":{ "shape":"OverrideType", - "documentation":"

    Whether the override will be defined as a standard or as a recurring event.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " + "documentation":"

    Whether the override will be defined as a standard or as a recurring event.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " } } }, @@ -12156,7 +12724,7 @@ }, "ParentHoursOfOperationConfigs":{ "shape":"ParentHoursOfOperationConfigList", - "documentation":"

    Configuration for parent hours of operations. Eg: ResourceArn.

    For more information about parent hours of operations, see Link overrides from different hours of operation in the Administrator Guide.

    " + "documentation":"

    Configuration for parent hours of operations. Eg: ResourceArn.

    For more information about parent hours of operations, see Link overrides from different hours of operation in the Administrator Guide.

    " }, "Tags":{ "shape":"TagMap", @@ -12282,6 +12850,73 @@ } } }, + "CreateMetricRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "Name", + "MetricCalculation", + "Unit" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "Name":{ + "shape":"MetricName", + "documentation":"

    The name of the metric.

    " + }, + "MetricCalculation":{ + "shape":"MetricCalculation", + "documentation":"

    The calculation definition for the metric, including the formula expression and the component metrics it references.

    " + }, + "Unit":{ + "shape":"MetricUnit", + "documentation":"

    The display unit for the metric's data.

    " + }, + "Status":{ + "shape":"MetricStatus", + "documentation":"

    The publish status of the metric. Set to PUBLISHED to make the metric available for use in dashboards and reports, or SAVED to keep it in draft state.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If not provided, the Amazon Web Services SDK populates this field. For more information about idempotency, see Making retries safe with idempotent APIs.

    ", + "idempotencyToken":true + }, + "Description":{ + "shape":"MetricDescription", + "documentation":"

    The description of the metric.

    " + }, + "PositiveTrendIndicator":{ + "shape":"TrendIndicator", + "documentation":"

    How an increase in the metric value should be interpreted. Valid values: POSITIVE, NEUTRAL, NEGATIVE.

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

    The tags used to organize, track, or control access for this resource. For example, { \"Tags\": {\"key1\":\"value1\", \"key2\":\"value2\"} }.

    " + } + } + }, + "CreateMetricResponse":{ + "type":"structure", + "required":[ + "MetricArn", + "MetricId" + ], + "members":{ + "MetricArn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the metric.

    " + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric.

    " + } + } + }, "CreateNotificationRequest":{ "type":"structure", "required":[ @@ -12700,7 +13335,7 @@ }, "ManualAssignmentQueueConfigs":{ "shape":"RoutingProfileManualAssignmentQueueConfigList", - "documentation":"

    The manual assignment queues associated with the routing profile. If no queue is added, agents and supervisors can't pick or assign any contacts from this routing profile. The limit of 10 array members applies to the maximum number of RoutingProfileManualAssignmentQueueConfig objects that can be passed during a CreateRoutingProfile API request. It is different from the quota of 50 queues per routing profile per instance that is listed in Connect Customer service quotas.

    Note: Use this config for chat, email, and task contacts. It does not support voice contacts.

    " + "documentation":"

    The manual assignment queues associated with the routing profile. If no queue is added, agents and supervisors can't pick or assign any contacts from this routing profile. The limit of 10 array members applies to the maximum number of RoutingProfileManualAssignmentQueueConfig objects that can be passed during a CreateRoutingProfile API request. It is different from the quota of 50 queues per routing profile per instance that is listed in Connect Customer service quotas.

    For voice contacts, manual assignment supports only agent-first callback contacts. Chat, email, and task contacts are fully supported.

    " }, "MediaConcurrencies":{ "shape":"MediaConcurrencies", @@ -12766,10 +13401,18 @@ "shape":"RulePublishStatus", "documentation":"

    The publish status of the rule.

    " }, + "PreEvaluationFilters":{ + "shape":"PreEvaluationFilters", + "documentation":"

    The pre-evaluation filters for the rule, that restrict the rule to be applied to only certain resources based on the resource's attributes, such as tags assigned to a contact. The pre-evaluation filters are applied even before rule conditions are evaluated and are used to enforce tag-based-access-control while applying rules.

    " + }, "ClientToken":{ "shape":"ClientToken", "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If not provided, the Amazon Web Services SDK populates this field. For more information about idempotency, see Making retries safe with idempotent APIs.

    ", "idempotencyToken":true + }, + "Tags":{ + "shape":"TagMap", + "documentation":"

    The tags used to organize, track, or control access for this resource. For example, { \"Tags\": {\"key1\":\"value1\", \"key2\":\"value2\"} }.

    " } } }, @@ -12849,6 +13492,10 @@ "shape":"AllowedFlowModules", "documentation":"

    A list of Flow Modules an AI Agent can invoke as a tool.

    " }, + "AllowedAIAgents":{ + "shape":"AllowedAIAgents", + "documentation":"

    A list of AI agents that the security profile will give access to.

    " + }, "GranularAccessControlConfiguration":{ "shape":"GranularAccessControlConfiguration", "documentation":"

    The granular access control configuration for the security profile, including data table permissions.

    " @@ -12892,7 +13539,7 @@ }, "ContactFlowId":{ "shape":"ContactFlowId", - "documentation":"

    The identifier of the flow that runs by default when a task is created by referencing this template.

    " + "documentation":"

    The identifier of the flow that runs by default when a task is created by referencing this template.

    Although this parameter is marked as optional, the request must contain either a ContactFlowId or a field of type QUICK_CONNECT.

    " }, "SelfAssignFlowId":{ "shape":"ContactFlowId", @@ -12900,7 +13547,7 @@ }, "Constraints":{ "shape":"TaskTemplateConstraints", - "documentation":"

    Constraints that are applicable to the fields listed.

    " + "documentation":"

    Constraints that are applicable to the fields listed. Although this parameter is marked as optional in the API model, the service requires it when calling CreateTaskTemplate or UpdateTaskTemplate. The RequiredFields array must contain at least one element, and the field of type NAME must be included in RequiredFields.

    " }, "Defaults":{ "shape":"TaskTemplateDefaults", @@ -12912,7 +13559,7 @@ }, "Fields":{ "shape":"TaskTemplateFields", - "documentation":"

    Fields that are part of the template.

    " + "documentation":"

    Fields that are part of the template.

    The request must contain exactly one field of type NAME. This field must also be listed in the RequiredFields array within the Constraints parameter.

    " }, "ClientToken":{ "shape":"ClientToken", @@ -13029,7 +13676,7 @@ "documentation":"

    A description for the traffic distribution group.

    " }, "InstanceId":{ - "shape":"InstanceIdOrArn", + "shape":"ACGRInstanceIdOrArn", "documentation":"

    The identifier of the Connect Customer instance that has been replicated. You can find the instanceId in the ARN of the instance.

    " }, "ClientToken":{ @@ -13047,11 +13694,11 @@ "type":"structure", "members":{ "Id":{ - "shape":"TrafficDistributionGroupId", + "shape":"ACGRTrafficDistributionGroupId", "documentation":"

    The identifier of the traffic distribution group. This can be the ID or the ARN of the traffic distribution group.

    " }, "Arn":{ - "shape":"TrafficDistributionGroupArn", + "shape":"ACGRTrafficDistributionGroupArn", "documentation":"

    The Amazon Resource Name (ARN) of the traffic distribution group.

    " } } @@ -13517,6 +14164,16 @@ }, "documentation":"

    Defines the cross-channel routing behavior that allows an agent working on a contact in one channel to be offered a contact from a different channel.

    " }, + "CrossChannelWorkloadBehavior":{ + "type":"structure", + "members":{ + "ChannelWorkloadBehaviorType":{ + "shape":"ChannelWorkloadBehaviorType", + "documentation":"

    Specifies the routing behavior for an agent handling their current channel and workload type.

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

    Defines the cross-channel and workload type routing behavior that allows an agent working on a contact to be offered a contact from a different channel or workload type.

    " + }, "CurrentMetric":{ "type":"structure", "members":{ @@ -14316,6 +14973,11 @@ }, "documentation":"

    A decimal search condition for Search APIs.

    " }, + "DefaultStat":{ + "type":"string", + "max":50, + "min":1 + }, "DefaultVocabulary":{ "type":"structure", "required":[ @@ -14375,7 +15037,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. Cases are the only current supported resource.

    This value must be a valid ARN.

    ", + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    ", "location":"querystring", "locationName":"associatedResourceArn" } @@ -14403,13 +15065,13 @@ }, "ContactId":{ "shape":"ContactId", - "documentation":"

    The identifier of the contact. PII can be deleted only from a contact that has been disconnected (is in a terminated state).

    ", + "documentation":"

    The identifier of the contact. You can delete PII only from a contact that has been disconnected (is in a terminated state).

    ", "location":"uri", "locationName":"ContactId" }, "ContactFields":{ "shape":"ContactFields", - "documentation":"

    The categories of PII to redact from the contact. Valid values are CUSTOMER_ENDPOINT, ADDITIONAL_EMAIL_RECIPIENTS, and EMAIL_SUBJECT. ADDITIONAL_EMAIL_RECIPIENTS and EMAIL_SUBJECT are supported only for contacts in the email channel.

    " + "documentation":"

    The categories of PII to redact from the contact. Specify one or more of the following values:

    • CUSTOMER_ENDPOINT – The customer's contact endpoint.

    • ADDITIONAL_EMAIL_RECIPIENTS – Additional recipients on an email contact (email channel only).

    • EMAIL_SUBJECT – The subject line of an email contact (email channel only).

    " } } }, @@ -14700,6 +15362,31 @@ } } }, + "DeleteExtractionDefinitionRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "ExtractionDefinitionId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition to delete.

    ", + "location":"uri", + "locationName":"ExtractionDefinitionId" + } + } + }, + "DeleteExtractionDefinitionResponse":{ + "type":"structure", + "members":{} + }, "DeleteHoursOfOperationOverrideRequest":{ "type":"structure", "required":[ @@ -14789,6 +15476,31 @@ } } }, + "DeleteMetricRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "MetricId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric to delete.

    ", + "location":"uri", + "locationName":"MetricId" + } + } + }, + "DeleteMetricResponse":{ + "type":"structure", + "members":{} + }, "DeleteNotificationRequest":{ "type":"structure", "required":[ @@ -15770,6 +16482,37 @@ } } }, + "DescribeExtractionDefinitionRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "ExtractionDefinitionId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition to describe.

    ", + "location":"uri", + "locationName":"ExtractionDefinitionId" + } + } + }, + "DescribeExtractionDefinitionResponse":{ + "type":"structure", + "required":["ExtractionDefinition"], + "members":{ + "ExtractionDefinition":{ + "shape":"ExtractionDefinition", + "documentation":"

    The extraction definition.

    " + } + } + }, "DescribeHoursOfOperationOverrideRequest":{ "type":"structure", "required":[ @@ -15929,6 +16672,37 @@ } } }, + "DescribeMetricRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "MetricId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric to describe. Adding the $SAVED qualifier will describe the saved version of the metric. Adding $LATEST or omitting a qualifier will describe the published version.

    ", + "location":"uri", + "locationName":"MetricId" + } + } + }, + "DescribeMetricResponse":{ + "type":"structure", + "required":["Metric"], + "members":{ + "Metric":{ + "shape":"MetricDefinition", + "documentation":"

    The metric definition.

    " + } + } + }, "DescribeNotificationRequest":{ "type":"structure", "required":[ @@ -17398,7 +18172,7 @@ "EmailAttachments":{ "type":"list", "member":{"shape":"EmailAttachment"}, - "max":10, + "max":50, "min":1, "sensitive":true }, @@ -17992,10 +18766,72 @@ "LastValidationTime":{ "shape":"Timestamp", "documentation":"

    The timestamp when the most recent validation was started for this evaluation form.

    " + }, + "AIVersion":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The AI version to use for the evaluation form. This specifies which AI model version is used for automated evaluations.

    " } }, "documentation":"

    Information about the evaluation form.

    " }, + "EvaluationFormAIVersion":{ + "type":"string", + "max":256, + "min":1 + }, + "EvaluationFormAIVersionLifecycle":{ + "type":"structure", + "required":[ + "Status", + "StartOfLifeTime" + ], + "members":{ + "Status":{ + "shape":"EvaluationFormAIVersionStatus", + "documentation":"

    The status of the AI version. Valid values:

    • Latest - The most recent AI version.

    • Preview - An AI version available for preview.

    • Active - An AI version that is currently available.

    • Deprecated - An AI version that is no longer recommended for use.

    • Removed - An AI version that is no longer available.

    " + }, + "StartOfLifeTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when this AI version became available.

    " + }, + "EndOfLifeTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when this AI version reaches or reached end of life.

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

    Contains the status and availability dates for an AI version, indicating when the version became active and when it reaches end of life.

    " + }, + "EvaluationFormAIVersionStatus":{ + "type":"string", + "enum":[ + "LATEST", + "PREVIEW", + "ACTIVE", + "DEPRECATED" + ] + }, + "EvaluationFormAIVersionSummary":{ + "type":"structure", + "required":[ + "AIVersionName", + "AIVersionLifecycle" + ], + "members":{ + "AIVersionName":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The name of the AI version.

    " + }, + "AIVersionLifecycle":{ + "shape":"EvaluationFormAIVersionLifecycle", + "documentation":"

    The lifecycle information for this AI version, including its status and availability dates.

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

    Contains the name and lifecycle information for an AI version that you can use when creating or updating an evaluation form.

    " + }, + "EvaluationFormAIVersionSummaryList":{ + "type":"list", + "member":{"shape":"EvaluationFormAIVersionSummary"} + }, "EvaluationFormAutoEvaluationConfiguration":{ "type":"structure", "required":["Enabled"], @@ -18060,6 +18896,10 @@ "ReviewConfiguration":{ "shape":"EvaluationReviewConfiguration", "documentation":"

    Configuration for evaluation review settings of this evaluation form content.

    " + }, + "AIVersion":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The AI version to use for the evaluation form. This specifies which AI model version is used for automated evaluations.

    " } }, "documentation":"

    Information about an evaluation form used in a contact evaluation.

    " @@ -18245,7 +19085,8 @@ "pt-BR", "ja-JP", "ko-KR", - "zh-CN" + "zh-CN", + "ms-MY" ] }, "EvaluationFormLanguageConfiguration":{ @@ -18258,6 +19099,34 @@ }, "documentation":"

    Language configuration for an evaluation form.

    " }, + "EvaluationFormMetricConfiguration":{ + "type":"structure", + "required":[ + "MetricType", + "MetricName" + ], + "members":{ + "MetricType":{ + "shape":"EvaluationFormMetricType", + "documentation":"

    The type of metric. Currently, only BUSINESS_OUTCOME is supported.

    " + }, + "MetricName":{ + "shape":"EvaluationFormMetricName", + "documentation":"

    The name of the metric. Valid values are:

    • SALE_SUCCESS – Sale success.

    • CSAT – Customer satisfaction.

    • CHURN_PROPENSITY – Churn propensity.

    • SELF_SERVICE_SUCCESS – Self-service success.

    • PARTIAL_SELF_SERVICE_SUCCESS – Partial self-service success.

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

    Information about the metric configuration for an evaluation form question. Use this to associate a business outcome metric with a question.

    " + }, + "EvaluationFormMetricName":{ + "type":"string", + "max":256, + "min":1, + "pattern":"^[^\\p{C}]*$" + }, + "EvaluationFormMetricType":{ + "type":"string", + "enum":["BUSINESS_OUTCOME"] + }, "EvaluationFormMultiSelectQuestionAutomation":{ "type":"structure", "members":{ @@ -18476,6 +19345,10 @@ "ScoringConfiguration":{ "shape":"EvaluationFormQuestionScoringConfiguration", "documentation":"

    The scoring configuration of the question.

    " + }, + "MetricConfiguration":{ + "shape":"EvaluationFormMetricConfiguration", + "documentation":"

    The metric configuration for the question. Use this to associate a business outcome metric with the question.

    " } }, "documentation":"

    Information about a question from an evaluation form.

    " @@ -18730,6 +19603,10 @@ "Tags":{ "shape":"TagMap", "documentation":"

    The tags used to organize, track, or control access for this resource. For example, { \"Tags\": {\"key1\":\"value1\", \"key2\":\"value2\"} }.

    " + }, + "AIVersion":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The AI version to use for the evaluation form. This specifies which AI model version is used for automated evaluations.

    " } }, "documentation":"

    Information about the returned evaluation forms.

    " @@ -19800,6 +20677,8 @@ "OnRealTimeCallAnalysisAvailable", "OnRealTimeChatAnalysisAvailable", "OnPostChatAnalysisAvailable", + "OnAfterCallWorkAvailable", + "OnAfterChatWorkAvailable", "OnEmailAnalysisAvailable", "OnZendeskTicketCreate", "OnZendeskTicketStatusUpdate", @@ -19911,6 +20790,169 @@ }, "documentation":"

    The external invocation configuration for the flow module

    " }, + "ExtractInformationActionDefinition":{ + "type":"structure", + "required":["RulesExtractionDefinitions"], + "members":{ + "RulesExtractionDefinitions":{ + "shape":"RulesExtractionDefinitionIdentifierList", + "documentation":"

    The list of extraction definition identifiers that specify what data to extract.

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

    Information about the extract information action, which references extraction definitions to use when extracting structured data from customer interactions.

    " + }, + "ExtractionConfiguration":{ + "type":"structure", + "required":["PromptHint"], + "members":{ + "PromptHint":{ + "shape":"ExtractionDefinitionPromptHint", + "documentation":"

    The prompt hint that guides the extraction. This text tells the generative AI model what data to look for in the customer interaction.

    " + }, + "NotFoundBehavior":{ + "shape":"ExtractionDefinitionNotFoundBehavior", + "documentation":"

    The behavior when the extraction cannot find the specified data in the interaction.

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

    The extraction configuration that defines how data is extracted from customer interactions.

    " + }, + "ExtractionDefinition":{ + "type":"structure", + "required":[ + "Name", + "ExtractionDefinitionId", + "ExtractionDefinitionArn", + "ExtractionConfiguration", + "CreatedTime", + "LastUpdatedTime", + "LastUpdatedBy" + ], + "members":{ + "Name":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    The name of the extraction definition.

    " + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition.

    " + }, + "ExtractionDefinitionArn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the extraction definition.

    " + }, + "ExtractionConfiguration":{ + "shape":"ExtractionConfiguration", + "documentation":"

    The configuration that defines how data is extracted.

    " + }, + "Display":{ + "shape":"ExtractionDefinitionDisplay", + "documentation":"

    The display settings for the extraction definition.

    " + }, + "CreatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the extraction definition was created.

    " + }, + "LastUpdatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the extraction definition was last updated.

    " + }, + "LastUpdatedBy":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the user who last updated the extraction definition.

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

    The tags used to organize, track, or control access for this resource.

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

    Information about an extraction definition.

    " + }, + "ExtractionDefinitionDisplay":{ + "type":"structure", + "members":{ + "Label":{ + "shape":"ExtractionDefinitionDisplayLabel", + "documentation":"

    The label displayed in the agent workspace for this extraction definition.

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

    The display configuration for an extraction definition.

    " + }, + "ExtractionDefinitionDisplayLabel":{ + "type":"string", + "max":25 + }, + "ExtractionDefinitionId":{ + "type":"string", + "max":256, + "min":1 + }, + "ExtractionDefinitionName":{ + "type":"string", + "max":200, + "min":1 + }, + "ExtractionDefinitionNotFoundBehavior":{ + "type":"structure", + "required":["Behavior"], + "members":{ + "Behavior":{ + "shape":"NotFoundBehaviorType", + "documentation":"

    The behavior type. USE_DEFAULT_VALUE returns the specified default value. OMIT excludes the field from the output.

    " + }, + "DefaultValue":{ + "shape":"NotFoundDefaultValue", + "documentation":"

    The default value to use when the behavior is USE_DEFAULT_VALUE.

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

    The behavior configuration when an extraction definition cannot find the target value.

    " + }, + "ExtractionDefinitionPromptHint":{ + "type":"string", + "max":1024, + "min":1 + }, + "ExtractionDefinitionSummary":{ + "type":"structure", + "required":[ + "Name", + "ExtractionDefinitionId", + "ExtractionDefinitionArn", + "CreatedTime", + "LastUpdatedTime", + "LastUpdatedBy" + ], + "members":{ + "Name":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    The name of the extraction definition.

    " + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition.

    " + }, + "ExtractionDefinitionArn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the extraction definition.

    " + }, + "CreatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the extraction definition was created.

    " + }, + "LastUpdatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the extraction definition was last updated.

    " + }, + "LastUpdatedBy":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the user who last updated the extraction definition.

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

    Summary information about an extraction definition.

    " + }, + "ExtractionDefinitionSummaryList":{ + "type":"list", + "member":{"shape":"ExtractionDefinitionSummary"} + }, "FailedBatchAssociationSummary":{ "type":"structure", "members":{ @@ -20080,6 +21122,11 @@ "VOICE_RECORDING" ] }, + "FilterId":{ + "type":"string", + "max":100, + "min":1 + }, "FilterV2":{ "type":"structure", "members":{ @@ -20290,7 +21337,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases and Email.

    This value must be a valid ARN.

    ", + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    ", "location":"querystring", "locationName":"associatedResourceArn" } @@ -20328,7 +21375,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. Cases are the only current supported resource.

    " + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    " }, "FileUseCaseType":{ "shape":"FileUseCaseType", @@ -20418,6 +21465,27 @@ } } }, + "GetCrossRegionRoutingRequest":{ + "type":"structure", + "required":["InstanceId"], + "members":{ + "InstanceId":{ + "shape":"ACGRInstanceIdOrArn", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + } + } + }, + "GetCrossRegionRoutingResponse":{ + "type":"structure", + "members":{ + "IsolatedRegions":{ + "shape":"IsolatedRegionsList", + "documentation":"

    The list of Regions for which cross-region routing is currently disabled (isolated). When a Region appears in this list, contacts originating in that Region will not be routed to agents in other Regions, and agents in that Region will not receive contacts from other Regions.

    " + } + } + }, "GetCurrentMetricDataRequest":{ "type":"structure", "required":[ @@ -20569,7 +21637,7 @@ }, "EffectiveOverrideHoursList":{ "shape":"EffectiveOverrideHoursList", - "documentation":"

    Information about override configurations applied to the base hours of operation to calculate the effective hours.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " + "documentation":"

    Information about override configurations applied to the base hours of operation to calculate the effective hours.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " }, "TimeZone":{ "shape":"TimeZone", @@ -20806,15 +21874,15 @@ }, "Filters":{ "shape":"FiltersV2List", - "documentation":"

    Filtering is an operation that selects records that match a set of specified criteria. By narrowing the dataset before aggregation, filters ensure that only relevant records are included in the computation.

    Filter keys

    The following are valid filter keys for a GetMetricDataV2 request:

    AGENT | AI_AGENT | AI_AGENT_ID | AI_AGENT_NAME | AI_AGENT_TYPE | AI_PROMPT | AI_PROMPT_ID | AI_PROMPT_NAME | AI_PROMPT_TYPE | AI_TOOL_ID | AI_TOOL_NAME | AI_TOOL_TYPE | AI_USE_CASE | AGENT_HIERARCHY_LEVEL_ONE | AGENT_HIERARCHY_LEVEL_TWO | AGENT_HIERARCHY_LEVEL_THREE | AGENT_HIERARCHY_LEVEL_FOUR | AGENT_HIERARCHY_LEVEL_FIVE | ANSWERING_MACHINE_DETECTION_STATUS | BOT_ALIAS | BOT_ID | BOT_INTENT_NAME | BOT_LOCALE | BOT_VERSION | CAMPAIGN | CAMPAIGN_DELIVERY_EVENT_TYPE | CAMPAIGN_EXCLUDED_EVENT_TYPE | CASE_STATUS | CASE_TEMPLATE_ARN | CHANNEL | contact/segmentAttributes/connect:Subtype | contact/segmentAttributes/connect:ValidationTestType | DISCONNECT_REASON | EVALUATION_FORM | EVALUATION_QUESTION | EVALUATION_SECTION | EVALUATION_SOURCE | EVALUATOR_ID | FEATURE | FLOW_ACTION_ID | FLOW_TYPE | FLOWS_MODULE_RESOURCE_ID | FLOWS_NEXT_RESOURCE_ID | FLOWS_NEXT_RESOURCE_QUEUE_ID | FLOWS_OUTCOME_TYPE | FLOWS_RESOURCE_ID | FORM_VERSION | INITIATING_FLOW | INITIATION_METHOD | INVOKING_RESOURCE_PUBLISHED_TIMESTAMP | INVOKING_RESOURCE_TYPE | KNOWLEDGE_BASE_NAME | PARENT_FLOWS_RESOURCE_ID | Q_CONNECT_ENABLED | QUEUE | RESOURCE_PUBLISHED_TIMESTAMP | ROUTING_PROFILE | ROUTING_STEP_EXPRESSION | SESSION_ID | TEST_CASE | TEST_CASE_EXECUTION_FAILURE_REASON | TEST_CASE_EXECUTION_RESULT | TEST_CASE_EXECUTION_STATE

    The following filter keys correspond to Connect Customer resources and are used for authorizing requests. A GetMetricDataV2 request requires at least one of these filters:

    QUEUE, ROUTING_PROFILE, AGENT, AGENT_HIERARCHY_LEVEL_ONE, AGENT_HIERARCHY_LEVEL_TWO, AGENT_HIERARCHY_LEVEL_THREE, AGENT_HIERARCHY_LEVEL_FOUR, AGENT_HIERARCHY_LEVEL_FIVE, CAMPAIGN, EVALUATION_FORM, EVALUATOR_ID

    You can use up to 5 filter keys in a single request, and up to 100 filter values across all filter keys.

    Filter values

    • VOICE, CHAT, TASK, and EMAIL are valid filter values for the CHANNEL filter key. They do not count towards the limit of 100 filter values. For example, a GetMetricDataV2 request can filter by 50 queues, 35 agents, and 15 routing profiles for a total of 100 filter values, along with 4 channel filters.

    • contact_lens_conversational_analytics is a valid filter value for the FEATURE filter key. It is available only for contacts analyzed by Contact Lens conversational analytics.

    • connect:Chat, connect:SMS, connect:Telephony, and connect:WebRTC are valid filter value examples (not exhaustive) for the contact/segmentAttributes/connect:Subtype filter key.

    • ROUTING_STEP_EXPRESSION accepts a filter value up to 3,000 characters in length. Filter values are case-sensitive. JSON object key order and whitespace may be arbitrary; array order and tree structure must be preserved.

    • TRUE and FALSE are the only valid filter values for the Q_CONNECT_ENABLED filter key.

      • TRUE includes all contacts that had Connect AI Agents enabled as part of the flow.

      • FALSE includes all contacts that did not have Connect AI Agents enabled as part of the flow.

    • EXPERIENCE_VALIDATION and FLOW_VALIDATION are the only valid filter values for the contact/segmentAttributes/connect:ValidationTestType filter key. This filter is available only for contact record-driven metrics.

    • Campaign ARNs are valid filter values for the CAMPAIGN filter key.

    • To filter by phone number, see Create a historical metrics report in the Connect Customer Administrator Guide.

    " + "documentation":"

    Filtering is an operation that selects records that match a set of specified criteria. By narrowing the dataset before aggregation, filters ensure that only relevant records are included in the computation.

    Filter keys

    The following are valid filter keys for a GetMetricDataV2 request:

    AGENT | AI_AGENT | AI_AGENT_ID | AI_AGENT_NAME | AI_AGENT_TYPE | AI_PROMPT | AI_PROMPT_ID | AI_PROMPT_NAME | AI_PROMPT_TYPE | AI_TOOL_ID | AI_TOOL_NAME | AI_TOOL_TYPE | AI_USE_CASE | AGENT_HIERARCHY_LEVEL_ONE | AGENT_HIERARCHY_LEVEL_TWO | AGENT_HIERARCHY_LEVEL_THREE | AGENT_HIERARCHY_LEVEL_FOUR | AGENT_HIERARCHY_LEVEL_FIVE | ANSWERING_MACHINE_DETECTION_STATUS | BOT_ALIAS | BOT_ID | BOT_INTENT_NAME | BOT_LOCALE | BOT_VERSION | BROWSER_NAME | CAMPAIGN | CAMPAIGN_DELIVERY_EVENT_TYPE | CAMPAIGN_EXCLUDED_EVENT_TYPE | CASE_STATUS | CASE_TEMPLATE_ARN | CHANNEL | contact/segmentAttributes/connect:Subtype | contact/segmentAttributes/connect:ValidationTestType | DEVICE_MODEL | DEVICE_TYPE | DISCONNECT_REASON | EVALUATION_FORM | EVALUATION_QUESTION | EVALUATION_SECTION | EVALUATION_SOURCE | EVALUATOR_ID | FEATURE | FLOW_ACTION_ID | FLOW_TYPE | FLOWS_MODULE_RESOURCE_ID | FLOWS_NEXT_RESOURCE_ID | FLOWS_NEXT_RESOURCE_QUEUE_ID | FLOWS_OUTCOME_TYPE | FLOWS_RESOURCE_ID | FORM_VERSION | INITIATING_FLOW | INITIATION_METHOD | INVOKING_RESOURCE_PUBLISHED_TIMESTAMP | INVOKING_RESOURCE_TYPE | KNOWLEDGE_BASE_NAME | PARENT_FLOWS_RESOURCE_ID | Q_CONNECT_ENABLED | QUEUE | RESOURCE_PUBLISHED_TIMESTAMP | ROUTING_PROFILE | ROUTING_STEP_EXPRESSION | SESSION_ID | TEST_CASE | TEST_CASE_EXECUTION_FAILURE_REASON | TEST_CASE_EXECUTION_RESULT | TEST_CASE_EXECUTION_STATE | WEB_NOTIFICATION_TYPE

    The following filter keys correspond to Connect Customer resources and are used for authorizing requests. A GetMetricDataV2 request requires at least one of these filters:

    QUEUE, ROUTING_PROFILE, AGENT, AGENT_HIERARCHY_LEVEL_ONE, AGENT_HIERARCHY_LEVEL_TWO, AGENT_HIERARCHY_LEVEL_THREE, AGENT_HIERARCHY_LEVEL_FOUR, AGENT_HIERARCHY_LEVEL_FIVE, CAMPAIGN, EVALUATION_FORM, EVALUATOR_ID

    You can use up to 5 filter keys in a single request, and up to 100 filter values across all filter keys.

    Filter values

    • VOICE, CHAT, TASK, and EMAIL are valid filter values for the CHANNEL filter key. They do not count towards the limit of 100 filter values. For example, a GetMetricDataV2 request can filter by 50 queues, 35 agents, and 15 routing profiles for a total of 100 filter values, along with 4 channel filters.

    • contact_lens_conversational_analytics is a valid filter value for the FEATURE filter key. It is available only for contacts analyzed by Contact Lens conversational analytics.

    • connect:Chat, connect:SMS, connect:Telephony, and connect:WebRTC are valid filter value examples (not exhaustive) for the contact/segmentAttributes/connect:Subtype filter key.

    • ROUTING_STEP_EXPRESSION accepts a filter value up to 3,000 characters in length. Filter values are case-sensitive. JSON object key order and whitespace may be arbitrary; array order and tree structure must be preserved.

    • TRUE and FALSE are the only valid filter values for the Q_CONNECT_ENABLED filter key.

      • TRUE includes all contacts that had Connect AI Agents enabled as part of the flow.

      • FALSE includes all contacts that did not have Connect AI Agents enabled as part of the flow.

    • EXPERIENCE_VALIDATION and FLOW_VALIDATION are the only valid filter values for the contact/segmentAttributes/connect:ValidationTestType filter key. This filter is available only for contact record-driven metrics.

    • Campaign ARNs are valid filter values for the CAMPAIGN filter key.

    • To filter by phone number, see Create a historical metrics report in the Connect Customer Administrator Guide.

    " }, "Groupings":{ "shape":"GroupingsV2", - "documentation":"

    The grouping applied to the metrics that are returned. For example, when results are grouped by queue, the metrics returned are grouped by queue. The values that are returned apply to the metrics for each queue. They are not aggregated for all queues.

    If no grouping is specified, a summary of all metrics is returned.

    Valid grouping keys: AGENT | AI_AGENT | AI_AGENT_ID | AI_AGENT_NAME | AI_AGENT_NAME_VERSION | AI_AGENT_TYPE | AI_PROMPT | AI_PROMPT_ID | AI_PROMPT_NAME | AI_PROMPT_NAME_VERSION | AI_PROMPT_TYPE | AI_TOOL_ID | AI_TOOL_NAME | AI_TOOL_TYPE | AI_USE_CASE | AGENT_HIERARCHY_LEVEL_ONE | AGENT_HIERARCHY_LEVEL_TWO | AGENT_HIERARCHY_LEVEL_THREE | AGENT_HIERARCHY_LEVEL_FOUR | AGENT_HIERARCHY_LEVEL_FIVE | ANSWERING_MACHINE_DETECTION_STATUS | BOT_ID | BOT_ALIAS | BOT_VERSION | BOT_LOCALE | BOT_INTENT_NAME | CAMPAIGN | CAMPAIGN_DELIVERY_EVENT_TYPE | CAMPAIGN_EXCLUDED_EVENT_TYPE | CAMPAIGN_EXECUTION_TIMESTAMP | CASE_TEMPLATE_ARN | CASE_STATUS | CHANNEL | contact/segmentAttributes/connect:Subtype | DISCONNECT_REASON | EVALUATION_FORM | EVALUATION_SECTION | EVALUATION_QUESTION | EVALUATION_SOURCE | EVALUATOR_ID | FLOWS_RESOURCE_ID | FLOWS_MODULE_RESOURCE_ID | FLOW_ACTION_ID | FLOW_TYPE | FLOWS_OUTCOME_TYPE | FORM_VERSION | INITIATION_METHOD | INVOKING_RESOURCE_PUBLISHED_TIMESTAMP | INVOKING_RESOURCE_TYPE | KNOWLEDGE_ARTICLE_NAME | KNOWLEDGE_BASE_NAME | PARENT_FLOWS_RESOURCE_ID | Q_CONNECT_ENABLED | QUEUE | RESOURCE_PUBLISHED_TIMESTAMP | ROUTING_PROFILE | ROUTING_STEP_EXPRESSION | SESSION_ID | TEST_CASE | TEST_CASE_EXECUTION_FAILURE_REASON | TEST_CASE_INVOCATION_METHOD

    AI_AGENT_NAME_VERSION, AI_PROMPT_NAME_VERSION, and KNOWLEDGE_ARTICLE_NAME are valid groupings but not valid filters.

    API, SCHEDULE, and EVENT are the only valid filterValues for TEST_CASE_INVOCATION_METHOD.

    OBSERVE_EVENT, SEND_INSTRUCTION, ASSERT_DATA, and OVERRIDE_SYSTEM_BEHAVIOR are the only valid filterValues for TEST_CASE_EXECUTION_FAILURE_REASON

    Type: Array of strings

    Array Members: Maximum number of 4 items

    Required: No

    " + "documentation":"

    The grouping applied to the metrics that are returned. For example, when results are grouped by queue, the metrics returned are grouped by queue. The values that are returned apply to the metrics for each queue. They are not aggregated for all queues.

    If no grouping is specified, a summary of all metrics is returned.

    Valid grouping keys: AGENT | AI_AGENT | AI_AGENT_ID | AI_AGENT_NAME | AI_AGENT_NAME_VERSION | AI_AGENT_TYPE | AI_PROMPT | AI_PROMPT_ID | AI_PROMPT_NAME | AI_PROMPT_NAME_VERSION | AI_PROMPT_TYPE | AI_TOOL_ID | AI_TOOL_NAME | AI_TOOL_TYPE | AI_USE_CASE | AGENT_HIERARCHY_LEVEL_ONE | AGENT_HIERARCHY_LEVEL_TWO | AGENT_HIERARCHY_LEVEL_THREE | AGENT_HIERARCHY_LEVEL_FOUR | AGENT_HIERARCHY_LEVEL_FIVE | ANSWERING_MACHINE_DETECTION_STATUS | BOT_ID | BOT_ALIAS | BOT_VERSION | BOT_LOCALE | BOT_INTENT_NAME | BROWSER_NAME | CAMPAIGN | CAMPAIGN_DELIVERY_EVENT_TYPE | CAMPAIGN_EXCLUDED_EVENT_TYPE | CAMPAIGN_EXECUTION_TIMESTAMP | CASE_TEMPLATE_ARN | CASE_STATUS | CHANNEL | contact/segmentAttributes/connect:Subtype | DEVICE_MODEL | DEVICE_TYPE | DISCONNECT_REASON | EVALUATION_FORM | EVALUATION_SECTION | EVALUATION_QUESTION | EVALUATION_SOURCE | EVALUATOR_ID | FLOWS_RESOURCE_ID | FLOWS_MODULE_RESOURCE_ID | FLOW_ACTION_ID | FLOW_TYPE | FLOWS_OUTCOME_TYPE | FORM_VERSION | INITIATION_METHOD | INVOKING_RESOURCE_PUBLISHED_TIMESTAMP | INVOKING_RESOURCE_TYPE | KNOWLEDGE_ARTICLE_NAME | KNOWLEDGE_BASE_NAME | PARENT_FLOWS_RESOURCE_ID | Q_CONNECT_ENABLED | QUEUE | RESOURCE_PUBLISHED_TIMESTAMP | ROUTING_PROFILE | ROUTING_STEP_EXPRESSION | SESSION_ID | TEST_CASE | TEST_CASE_EXECUTION_FAILURE_REASON | TEST_CASE_INVOCATION_METHOD | WEB_NOTIFICATION_TYPE

    AI_AGENT_NAME_VERSION, AI_PROMPT_NAME_VERSION, and KNOWLEDGE_ARTICLE_NAME are valid groupings but not valid filters.

    API, SCHEDULE, and EVENT are the only valid filterValues for TEST_CASE_INVOCATION_METHOD.

    OBSERVE_EVENT, SEND_INSTRUCTION, ASSERT_DATA, and OVERRIDE_SYSTEM_BEHAVIOR are the only valid filterValues for TEST_CASE_EXECUTION_FAILURE_REASON

    Type: Array of strings

    Array Members: Maximum number of 4 items

    Required: No

    " }, "Metrics":{ "shape":"MetricsV2", - "documentation":"

    The metrics to retrieve. Specify the name or metricId, groupings, and filters for each metric. The following historical metrics are available. For a description of each metric, see Metrics definition in the Connect Customer Administrator Guide.

    MetricId should be used to reference custom metrics or out of the box metrics as Arn. If using MetricId, the limit is 20 MetricId per request.

    ABANDONMENT_RATE

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Abandonment rate

    AGENT_ADHERENT_TIME

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Adherent time

    AGENT_ANSWER_RATE

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent answer rate

    AGENT_NON_ADHERENT_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Non-adherent time

    AGENT_NON_RESPONSE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent non-response

    AGENT_NON_RESPONSE_WITHOUT_CUSTOMER_ABANDONS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    Data for this metric is available starting from October 1, 2023 0:00:00 GMT.

    UI name: Agent non-response without customer abandons

    AGENT_OCCUPANCY

    Unit: Percentage

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Occupancy

    AGENT_SCHEDULE_ADHERENCE

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Adherence

    AGENT_SCHEDULED_TIME

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Scheduled time

    AVG_ABANDON_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    Valid metric filter key: INITIATION_METHOD

    UI name: Average queue abandon time

    AVG_ACTIVE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average active time

    AVG_AFTER_CONTACT_WORK_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average after contact work time

    Feature is a valid filter but not a valid grouping.

    AVG_AGENT_CONCURRENCY

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average agent concurrency

    AVG_AGENT_CONNECTING_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD. For now, this metric only supports the following as INITIATION_METHOD: INBOUND | OUTBOUND | CALLBACK | API

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Average agent API connecting time

    The Negate key in metric-level filters is not applicable for this metric.

    AVG_AGENT_PAUSE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average agent pause time

    AVG_BOT_CONVERSATION_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Average bot conversation time

    AVG_BOT_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Average bot conversation turns

    AVG_CASE_RELATED_CONTACTS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Average contacts per case

    AVG_CASE_RESOLUTION_TIME

    Unit: Seconds

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Average case resolution time

    AVG_CONTACT_DURATION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average contact duration

    Feature is a valid filter but not a valid grouping.

    AVG_CONTACT_FIRST_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Agent average contact first response wait time

    AVG_CONVERSATION_CLOSE_TIME

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average conversation close time

    AVG_CONVERSATION_DURATION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average conversation duration

    AVG_DIALS_PER_MINUTE

    This metric is available only for outbound campaigns that use the agent assisted voice and automated voice delivery modes.

    Unit: Count

    Valid groupings and filters: Agent, Campaign, Queue, Routing Profile

    UI name: Average dials per minute

    AVG_EVALUATION_SCORE

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Section ID, Evaluation Question ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Average evaluation score

    AVG_FIRST_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent first response time

    AVG_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Average flow time

    AVG_GREETING_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent greeting time

    AVG_HANDLE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, AI Use Case, Feature, contact/segmentAttributes/connect:Subtype, RoutingStepExpression

    UI name: Average handle time

    Feature is a valid filter but not a valid grouping.

    ACTIVE_AI_AGENTS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Active AI Agents

    AI_HANDOFF_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Handoff Rate

    AI_HANDOFFS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Handoff Count

    AI_AGENT_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Agent Name Version, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Count

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_RESPONSE_HELPFUL

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Response Helpful

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_RESPONSE_NOT_HELPFUL

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Response Not Helpful

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_RESPONSE_COMPLETION_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Response Completion Rate

    AI_INVOLVED_CONTACTS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Involved Contacts

    AI_PROMPT_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_PROMPT_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_PROMPT_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocations

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocations

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_AGENT_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Agent Conversation Turns

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Conversation Turns

    AVG_AI_PROMPT_INVOCATION_LATENCY

    Unit: Milliseconds

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Prompt Invocation Latency

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_TOOL_INVOCATION_LATENCY

    Unit: Milliseconds

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Tool Invocation Latency

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_PARAMETER_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Parameter Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_SELECTION_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Selection Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_UTILIZATION_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: AI Tool Utilization Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    COMPLETENESS_SCORE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Completeness Score

    FAITHFULNESS_SCORE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Faithfulness Score

    GOAL_SUCCESS_RATE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Goal Success Rate

    KNOWLEDGE_CONTENT_REFERENCES

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Use Case, Channel, Knowledge Base Name, Queue, Routing Profile

    UI name: Knowledge Content References

    PROACTIVE_INTENT_ENGAGEMENT_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intent Engagement Rate

    PROACTIVE_INTENT_RESPONSE_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intent Response Rate

    PROACTIVE_INTENTS_ANSWERED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Answered

    PROACTIVE_INTENTS_DETECTED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Detected

    PROACTIVE_INTENTS_ENGAGED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Engaged

    AVG_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer hold time

    Feature is a valid filter but not a valid grouping.

    AVG_HOLD_TIME_ALL_CONTACTS

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer hold time all contacts

    AVG_HOLDS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average holds

    Feature is a valid filter but not a valid grouping.

    AVG_INTERACTION_AND_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interaction and customer hold time

    AVG_INTERACTION_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interaction time

    Feature is a valid filter but not a valid grouping.

    AVG_INTERRUPTIONS_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interruptions

    AVG_INTERRUPTION_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interruption time

    AVG_MESSAGE_LENGTH_AGENT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent message length

    AVG_MESSAGE_LENGTH_CUSTOMER

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer message length

    AVG_MESSAGES

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average messages

    AVG_MESSAGES_AGENT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent messages

    AVG_MESSAGES_BOT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average bot messages

    AVG_MESSAGES_CUSTOMER

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer messages

    AVG_NON_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average non-talk time

    AVG_QUEUE_ANSWER_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average queue answer time

    Valid metric level filters: INITIATION_METHOD, FEATURE, DISCONNECT_REASON

    Feature is a valid filter but not a valid grouping.

    AVG_QUEUE_ANSWER_TIME_CUSTOMER_FIRST_CALLBACK

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect, Agent Hierarchy

    UI name: Avg. queue answer time - customer first callback

    AVG_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent response time

    AVG_RESPONSE_TIME_CUSTOMER

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer response time

    AVG_RESOLUTION_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average resolution time

    AVG_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average talk time

    AVG_TALK_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent talk time

    AVG_TALK_TIME_CUSTOMER

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer talk time

    AVG_WAIT_TIME_AFTER_CUSTOMER_CONNECTION

    This metric is available only for outbound campaigns that use the agent assisted voice and automated voice delivery modes.

    Unit: Seconds

    Valid groupings and filters: Campaign

    UI name: Average wait time after customer connection

    AVG_WAIT_TIME_AFTER_CUSTOMER_FIRST_CALLBACK_CONNECTION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect, Agent Hierarchy

    UI name: Avg. wait time after customer connection - customer first callback

    AVG_WEIGHTED_EVALUATION_SCORE

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form Id, Evaluation Section ID, Evaluation Question ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Average weighted evaluation score

    BOT_CONVERSATIONS_COMPLETED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Bot conversations completed

    BOT_INTENTS_COMPLETED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Bot intent name, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Bot intents completed

    CAMPAIGN_CONTACTS_ABANDONED_AFTER_X

    This metric is available only for outbound campaigns using the agent assisted voice and automated voice delivery modes.

    Unit: Count

    Valid groupings and filters: Agent, Campaign

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you must enter GT (for Greater than).

    UI name: Campaign contacts abandoned after X

    CAMPAIGN_CONTACTS_ABANDONED_AFTER_X_RATE

    This metric is available only for outbound campaigns using the agent assisted voice and automated voice delivery modes.

    Unit: Percent

    Valid groupings and filters: Agent, Campaign

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you must enter GT (for Greater than).

    UI name: Campaign contacts abandoned after X rate

    CAMPAIGN_INTERACTIONS

    This metric is available only for outbound campaigns using the email delivery mode.

    Unit: Count

    Valid metric filter key: CAMPAIGN_INTERACTION_EVENT_TYPE

    Valid groupings and filters: Campaign

    UI name: Campaign interactions

    CAMPAIGN_PROGRESS_RATE

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Percent

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Campaign progress rate

    CAMPAIGN_SEND_ATTEMPTS

    This metric is available only for outbound campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Channel, contact/segmentAttributes/connect:Subtype

    UI name: Campaign send attempts

    CAMPAIGN_SEND_EXCLUSIONS

    This metric is available only for outbound campaigns.

    Valid metric filter key: CAMPAIGN_EXCLUDED_EVENT_TYPE

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Excluded Event Type, Campaign Execution Timestamp

    UI name: Campaign send exclusions

    CASES_CREATED

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases created

    CONTACTS_CREATED

    Unit: Count

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts created

    Feature is a valid filter but not a valid grouping.

    CONTACTS_HANDLED

    Unit: Count

    Valid metric filter key: INITIATION_METHOD, DISCONNECT_REASON

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, RoutingStepExpression, Q in Connect

    UI name: Contacts handled

    Feature is a valid filter but not a valid grouping.

    CONTACTS_HANDLED_BY_CONNECTED_TO_AGENT

    Unit: Count

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts handled (connected to agent timestamp)

    CONTACTS_HOLD_ABANDONS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts hold disconnect

    CONTACTS_ON_HOLD_AGENT_DISCONNECT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts hold agent disconnect

    CONTACTS_ON_HOLD_CUSTOMER_DISCONNECT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts hold customer disconnect

    CONTACTS_PUT_ON_HOLD

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts put on hold

    CONTACTS_TRANSFERRED_OUT_EXTERNAL

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts transferred out external

    CONTACTS_TRANSFERRED_OUT_INTERNAL

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts transferred out internal

    CONTACTS_QUEUED

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts queued

    CONTACTS_QUEUED_BY_ENQUEUE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype

    UI name: Contacts queued (enqueue timestamp)

    CONTACTS_REMOVED_FROM_QUEUE_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts removed from queue in X seconds

    CONTACTS_RESOLVED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts resolved in X

    CONTACTS_TRANSFERRED_OUT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out

    Feature is a valid filter but not a valid grouping.

    CONTACTS_TRANSFERRED_OUT_BY_AGENT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out by agent

    CONTACTS_TRANSFERRED_OUT_FROM_QUEUE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out queue

    CURRENT_CASES

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Current cases

    CONVERSATIONS_ABANDONED

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Conversations abandoned

    DELIVERY_ATTEMPTS

    This metric is available only for outbound campaigns.

    Unit: Count

    Valid metric filter key: ANSWERING_MACHINE_DETECTION_STATUS, CAMPAIGN_DELIVERY_EVENT_TYPE, DISCONNECT_REASON

    Valid groupings and filters: Agent, Answering Machine Detection Status, Campaign, Campaign Delivery EventType, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Queue, Routing Profile

    UI name: Delivery attempts

    Campaign Delivery EventType filter and grouping are only available for SMS and Email campaign delivery modes. Agent, Queue, Routing Profile, Answering Machine Detection Status and Disconnect Reason are only available for agent assisted voice and automated voice delivery modes.

    DELIVERY_ATTEMPT_DISPOSITION_RATE

    This metric is available only for outbound campaigns. Dispositions for the agent assisted voice and automated voice delivery modes are only available with answering machine detection enabled.

    Unit: Percent

    Valid metric filter key: ANSWERING_MACHINE_DETECTION_STATUS, CAMPAIGN_DELIVERY_EVENT_TYPE, DISCONNECT_REASON

    Valid groupings and filters: Agent, Answering Machine Detection Status, Campaign, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Queue, Routing Profile

    UI name: Delivery attempt disposition rate

    Campaign Delivery Event Type filter and grouping are only available for SMS and Email campaign delivery modes. Agent, Queue, Routing Profile, Answering Machine Detection Status and Disconnect Reason are only available for agent assisted voice and automated voice delivery modes.

    EVALUATIONS_PERFORMED

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Evaluations performed

    FLOWS_OUTCOME

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows outcome

    FLOWS_STARTED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows started

    HUMAN_ANSWERED_CALLS

    This metric is available only for outbound campaigns. Dispositions for the agent assisted voice and automated voice delivery modes are only available with answering machine detection enabled.

    Unit: Count

    Valid groupings and filters: Agent, Campaign

    UI name: Human answered

    MAX_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Maximum flow time

    MAX_QUEUED_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Maximum queued time

    MIN_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Minimum flow time

    PERCENT_AUTOMATIC_FAILS

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Automatic fails percent

    PERCENT_BOT_CONVERSATIONS_OUTCOME

    Unit: Percent

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Percent bot conversations outcome

    PERCENT_BOT_INTENTS_OUTCOME

    Unit: Percent

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Bot intent name, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Percent bot intents outcome

    PERCENT_CASES_FIRST_CONTACT_RESOLVED

    Unit: Percent

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases resolved on first contact

    PERCENT_CONTACTS_STEP_EXPIRED

    Unit: Percent

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    PERCENT_CONTACTS_STEP_JOINED

    Unit: Percent

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    PERCENT_FLOWS_OUTCOME

    Unit: Percent

    Valid metric filter key: FLOWS_OUTCOME_TYPE

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows outcome percentage.

    The FLOWS_OUTCOME_TYPE is not a valid grouping.

    PERCENT_NON_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Non-talk time percent

    PERCENT_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Talk time percent

    PERCENT_TALK_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Agent talk time percent

    PERCENT_TALK_TIME_CUSTOMER

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Customer talk time percent

    RECIPIENTS_ATTEMPTED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Recipients attempted

    RECIPIENTS_INTERACTED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Valid metric filter key: CAMPAIGN_INTERACTION_EVENT_TYPE

    Unit: Count

    Valid groupings and filters: Campaign, Channel, contact/segmentAttributes/connect:Subtype, Campaign Execution Timestamp

    UI name: Recipients interacted

    RECIPIENTS_TARGETED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Recipients targeted

    REOPENED_CASE_ACTIONS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases reopened

    RESOLVED_CASE_ACTIONS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases resolved

    SERVICE_LEVEL

    You can include up to 20 SERVICE_LEVEL metrics in a request.

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Service level X

    STEP_CONTACTS_QUEUED

    Unit: Count

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    SUM_AFTER_CONTACT_WORK_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: After contact work time

    SUM_CONNECTING_TIME_AGENT

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD. This metric only supports the following filter keys as INITIATION_METHOD: INBOUND | OUTBOUND | CALLBACK | API | CALLBACK_CUSTOMER_FIRST_DIALED

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent API connecting time

    The Negate key in metric-level filters is not applicable for this metric.

    CONTACTS_ABANDONED

    Unit: Count

    Metric filter:

    • Valid values: API| INCOMING | OUTBOUND | TRANSFER | CALLBACK | QUEUE_TRANSFER| Disconnect | CALLBACK_CUSTOMER_FIRST_DIALED

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, RoutingStepExpression, Q in Connect

    UI name: Contact abandoned

    SUM_CONTACTS_ABANDONED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts abandoned in X seconds

    SUM_CONTACTS_ANSWERED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts answered in X seconds

    SUM_CONTACT_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contact flow time

    SUM_CONTACT_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent on contact time

    SUM_CONTACTS_DISCONNECTED

    Valid metric filter key: DISCONNECT_REASON

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contact disconnected

    SUM_ERROR_STATUS_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Error status time

    SUM_HANDLE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contact handle time

    SUM_HOLD_TIME

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Customer hold time

    SUM_IDLE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent idle time

    SUM_INTERACTION_AND_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Agent interaction and hold time

    SUM_INTERACTION_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent interaction time

    SUM_NON_PRODUCTIVE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent non-productive time

    SUM_ONLINE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Online time

    SUM_RETRY_CALLBACK_ATTEMPTS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Callback attempts

    " + "documentation":"

    The metrics to retrieve. Specify the name or metricId, groupings, and filters for each metric. The following historical metrics are available. For a description of each metric, see Metrics definition in the Connect Customer Administrator Guide.

    MetricId should be used to reference custom metrics or out of the box metrics as Arn. If using MetricId, the limit is 20 MetricId per request.

    ABANDONMENT_RATE

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Abandonment rate

    AGENT_ADHERENT_TIME

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Adherent time

    AGENT_ANSWER_RATE

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent answer rate

    AGENT_NON_ADHERENT_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Non-adherent time

    AGENT_NON_RESPONSE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent non-response

    AGENT_NON_RESPONSE_WITHOUT_CUSTOMER_ABANDONS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    Data for this metric is available starting from October 1, 2023 0:00:00 GMT.

    UI name: Agent non-response without customer abandons

    AGENT_OCCUPANCY

    Unit: Percentage

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Occupancy

    AGENT_SCHEDULE_ADHERENCE

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Adherence

    AGENT_SCHEDULED_TIME

    This metric is available only in Amazon Web Services Regions where Forecasting, capacity planning, and scheduling is available.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Scheduled time

    AVG_ABANDON_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    Valid metric filter key: INITIATION_METHOD

    UI name: Average queue abandon time

    AVG_ACTIVE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average active time

    AVG_AFTER_CONTACT_WORK_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average after contact work time

    Feature is a valid filter but not a valid grouping.

    AVG_AGENT_CONCURRENCY

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average agent concurrency

    AVG_AGENT_CONNECTING_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD. For now, this metric only supports the following as INITIATION_METHOD: INBOUND | OUTBOUND | CALLBACK | API

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Average agent API connecting time

    The Negate key in metric-level filters is not applicable for this metric.

    AVG_AGENT_PAUSE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Average agent pause time

    AVG_BOT_CONVERSATION_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Average bot conversation time

    AVG_BOT_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Average bot conversation turns

    AVG_CASE_RELATED_CONTACTS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Average contacts per case

    AVG_CASE_RESOLUTION_TIME

    Unit: Seconds

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Average case resolution time

    AVG_CONTACT_DURATION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average contact duration

    Feature is a valid filter but not a valid grouping.

    AVG_CONTACT_FIRST_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Agent average contact first response wait time

    AVG_CONVERSATION_CLOSE_TIME

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average conversation close time

    AVG_CONVERSATION_DURATION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average conversation duration

    AVG_DIALS_PER_MINUTE

    This metric is available only for outbound campaigns that use the agent assisted voice and automated voice delivery modes.

    Unit: Count

    Valid groupings and filters: Agent, Campaign, Queue, Routing Profile

    UI name: Average dials per minute

    AVG_EVALUATION_SCORE

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Section ID, Evaluation Question ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Average evaluation score

    AVG_FIRST_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent first response time

    AVG_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Average flow time

    AVG_GREETING_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent greeting time

    AVG_HANDLE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, AI Use Case, Feature, contact/segmentAttributes/connect:Subtype, RoutingStepExpression

    UI name: Average handle time

    Feature is a valid filter but not a valid grouping.

    ACTIVE_AI_AGENTS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Active AI Agents

    AI_HANDOFF_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Handoff Rate

    AI_HANDOFFS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Handoff Count

    AI_AGENT_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Agent Name Version, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Invocation Count

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_RESPONSE_HELPFUL

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Response Helpful

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_AGENT_RESPONSE_NOT_HELPFUL

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Agent Response Not Helpful

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_RESPONSE_COMPLETION_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Response Completion Rate

    AI_INVOLVED_CONTACTS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Involved Contacts

    AI_PROMPT_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_PROMPT_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_PROMPT_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Prompt Invocations

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATION_SUCCESS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocation Success

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATION_SUCCESS_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocation Success Rate

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_INVOCATIONS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Invocations

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_AGENT_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Agent Conversation Turns

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_CONVERSATION_TURNS

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Conversation Turns

    AVG_AI_PROMPT_INVOCATION_LATENCY

    Unit: Milliseconds

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Prompt, AI Prompt ID, AI Prompt Name, AI Prompt Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Prompt Invocation Latency

    AI Agent Name Version is not a valid filter but a valid grouping.

    AVG_AI_TOOL_INVOCATION_LATENCY

    Unit: Milliseconds

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Average AI Tool Invocation Latency

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_PARAMETER_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Parameter Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_SELECTION_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: AI Tool Selection Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    AI_TOOL_UTILIZATION_ACCURACY

    Unit: Double

    Valid groupings and filters: AI Agent, AI Agent ID, AI Agent Name, AI Agent Name Version, AI Agent Type, AI Tool ID, AI Tool Name, AI Tool Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: AI Tool Utilization Accuracy

    AI Agent Name Version is not a valid filter but a valid grouping.

    COMPLETENESS_SCORE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Completeness Score

    FAITHFULNESS_SCORE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Faithfulness Score

    GOAL_SUCCESS_RATE

    Unit: Double

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile, Session ID

    UI name: Goal Success Rate

    KNOWLEDGE_CONTENT_REFERENCES

    Unit: Count

    Valid groupings and filters: AI Agent, AI Agent Name, AI Agent Type, AI Use Case, Channel, Knowledge Base Name, Queue, Routing Profile

    UI name: Knowledge Content References

    PROACTIVE_INTENT_ENGAGEMENT_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intent Engagement Rate

    PROACTIVE_INTENT_RESPONSE_RATE

    Unit: Percent

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intent Response Rate

    PROACTIVE_INTENTS_ANSWERED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Answered

    PROACTIVE_INTENTS_DETECTED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Detected

    PROACTIVE_INTENTS_ENGAGED

    Unit: Count

    Valid groupings and filters: AI Agent ID, AI Agent Name, AI Agent Type, AI Use Case, Channel, Queue, Routing Profile

    UI name: Proactive Intents Engaged

    AVG_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer hold time

    Feature is a valid filter but not a valid grouping.

    AVG_HOLD_TIME_ALL_CONTACTS

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer hold time all contacts

    AVG_HOLDS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average holds

    Feature is a valid filter but not a valid grouping.

    AVG_INTERACTION_AND_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interaction and customer hold time

    AVG_INTERACTION_TIME

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interaction time

    Feature is a valid filter but not a valid grouping.

    AVG_INTERRUPTIONS_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interruptions

    AVG_INTERRUPTION_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent interruption time

    AVG_MESSAGE_LENGTH_AGENT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent message length

    AVG_MESSAGE_LENGTH_CUSTOMER

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer message length

    AVG_MESSAGES

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average messages

    AVG_MESSAGES_AGENT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent messages

    AVG_MESSAGES_BOT

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average bot messages

    AVG_MESSAGES_CUSTOMER

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer messages

    AVG_NON_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average non-talk time

    AVG_QUEUE_ANSWER_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average queue answer time

    Valid metric level filters: INITIATION_METHOD, FEATURE, DISCONNECT_REASON

    Feature is a valid filter but not a valid grouping.

    AVG_QUEUE_ANSWER_TIME_CUSTOMER_FIRST_CALLBACK

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect, Agent Hierarchy

    UI name: Avg. queue answer time - customer first callback

    AVG_RESPONSE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average agent response time

    AVG_RESPONSE_TIME_CUSTOMER

    Unit: Seconds

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Average customer response time

    AVG_RESOLUTION_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average resolution time

    AVG_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average talk time

    AVG_TALK_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average agent talk time

    AVG_TALK_TIME_CUSTOMER

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Average customer talk time

    AVG_WAIT_TIME_AFTER_CUSTOMER_CONNECTION

    This metric is available only for outbound campaigns that use the agent assisted voice and automated voice delivery modes.

    Unit: Seconds

    Valid groupings and filters: Campaign

    UI name: Average wait time after customer connection

    AVG_WAIT_TIME_AFTER_CUSTOMER_FIRST_CALLBACK_CONNECTION

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect, Agent Hierarchy

    UI name: Avg. wait time after customer connection - customer first callback

    AVG_WEIGHTED_EVALUATION_SCORE

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form Id, Evaluation Section ID, Evaluation Question ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Average weighted evaluation score

    BOT_CONVERSATIONS_COMPLETED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Bot conversations completed

    BOT_INTENTS_COMPLETED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Bot intent name, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Bot intents completed

    CAMPAIGN_CONTACTS_ABANDONED_AFTER_X

    This metric is available only for outbound campaigns using the agent assisted voice and automated voice delivery modes.

    Unit: Count

    Valid groupings and filters: Agent, Campaign

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you must enter GT (for Greater than).

    UI name: Campaign contacts abandoned after X

    CAMPAIGN_CONTACTS_ABANDONED_AFTER_X_RATE

    This metric is available only for outbound campaigns using the agent assisted voice and automated voice delivery modes.

    Unit: Percent

    Valid groupings and filters: Agent, Campaign

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you must enter GT (for Greater than).

    UI name: Campaign contacts abandoned after X rate

    CAMPAIGN_INTERACTIONS

    This metric is available only for outbound campaigns using the email, WhatsApp, and web notification delivery modes.

    Unit: Count

    Valid metric filter key: CAMPAIGN_INTERACTION_EVENT_TYPE

    Valid groupings and filters: Browser Name, Campaign, Channel, contact/segmentAttributes/connect:Subtype, Device Model, Device Type, Web Notification Type

    UI name: Campaign interactions

    CAMPAIGN_PROGRESS_RATE

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Percent

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Campaign progress rate

    CAMPAIGN_SEND_ATTEMPTS

    This metric is available only for outbound campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Channel, contact/segmentAttributes/connect:Subtype

    UI name: Campaign send attempts

    CAMPAIGN_SEND_EXCLUSIONS

    This metric is available only for outbound campaigns.

    Valid metric filter key: CAMPAIGN_EXCLUDED_EVENT_TYPE

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Excluded Event Type, Campaign Execution Timestamp

    UI name: Campaign send exclusions

    CASES_CREATED

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases created

    CONTACTS_CREATED

    Unit: Count

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Routing Profile, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts created

    Feature is a valid filter but not a valid grouping.

    CONTACTS_HANDLED

    Unit: Count

    Valid metric filter key: INITIATION_METHOD, DISCONNECT_REASON

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, RoutingStepExpression, Q in Connect

    UI name: Contacts handled

    Feature is a valid filter but not a valid grouping.

    CONTACTS_HANDLED_BY_CONNECTED_TO_AGENT

    Unit: Count

    Valid metric filter key: INITIATION_METHOD

    Valid groupings and filters: Queue, Channel, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts handled (connected to agent timestamp)

    CONTACTS_HOLD_ABANDONS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts hold disconnect

    CONTACTS_ON_HOLD_AGENT_DISCONNECT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts hold agent disconnect

    CONTACTS_ON_HOLD_CUSTOMER_DISCONNECT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts hold customer disconnect

    CONTACTS_PUT_ON_HOLD

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts put on hold

    CONTACTS_TRANSFERRED_OUT_EXTERNAL

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts transferred out external

    CONTACTS_TRANSFERRED_OUT_INTERNAL

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contacts transferred out internal

    CONTACTS_QUEUED

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts queued

    CONTACTS_QUEUED_BY_ENQUEUE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype

    UI name: Contacts queued (enqueue timestamp)

    CONTACTS_REMOVED_FROM_QUEUE_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts removed from queue in X seconds

    CONTACTS_RESOLVED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts resolved in X

    CONTACTS_TRANSFERRED_OUT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Feature, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out

    Feature is a valid filter but not a valid grouping.

    CONTACTS_TRANSFERRED_OUT_BY_AGENT

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out by agent

    CONTACTS_TRANSFERRED_OUT_FROM_QUEUE

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contacts transferred out queue

    CURRENT_CASES

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Current cases

    CONVERSATIONS_ABANDONED

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, contact/segmentAttributes/connect:Subtype, Disconnect Reason, Feature, RoutingStepExpression, Initiation method, Routing Profile, Queue, Q in Connect

    UI name: Conversations abandoned

    DELIVERY_ATTEMPTS

    This metric is available only for outbound campaigns.

    Unit: Count

    Valid metric filter key: ANSWERING_MACHINE_DETECTION_STATUS, CAMPAIGN_DELIVERY_EVENT_TYPE, DISCONNECT_REASON

    Valid groupings and filters: Agent, Answering Machine Detection Status, Browser Name, Campaign, Campaign Delivery EventType, Channel, contact/segmentAttributes/connect:Subtype, Device Model, Device Type, Disconnect Reason, Queue, Routing Profile, Web Notification Type

    UI name: Delivery attempts

    Campaign Delivery EventType filter and grouping are only available for SMS, Email, WhatsApp, and web notification campaign delivery modes. Agent, Queue, Routing Profile, Answering Machine Detection Status and Disconnect Reason are only available for agent assisted voice and automated voice delivery modes.

    DELIVERY_ATTEMPT_DISPOSITION_RATE

    This metric is available only for outbound campaigns. Dispositions for the agent assisted voice and automated voice delivery modes are only available with answering machine detection enabled.

    Unit: Percent

    Valid metric filter key: ANSWERING_MACHINE_DETECTION_STATUS, CAMPAIGN_DELIVERY_EVENT_TYPE, DISCONNECT_REASON

    Valid groupings and filters: Agent, Answering Machine Detection Status, Browser Name, Campaign, Channel, contact/segmentAttributes/connect:Subtype, Device Model, Device Type, Disconnect Reason, Queue, Routing Profile, Web Notification Type

    UI name: Delivery attempt disposition rate

    Campaign Delivery Event Type filter and grouping are only available for SMS, Email, WhatsApp, and web notification campaign delivery modes. Agent, Queue, Routing Profile, Answering Machine Detection Status and Disconnect Reason are only available for agent assisted voice and automated voice delivery modes.

    EVALUATIONS_PERFORMED

    Unit: Count

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Evaluations performed

    FLOWS_OUTCOME

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows outcome

    FLOWS_STARTED

    Unit: Count

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows started

    HUMAN_ANSWERED_CALLS

    This metric is available only for outbound campaigns. Dispositions for the agent assisted voice and automated voice delivery modes are only available with answering machine detection enabled.

    Unit: Count

    Valid groupings and filters: Agent, Campaign

    UI name: Human answered

    MAX_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Maximum flow time

    MAX_QUEUED_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Maximum queued time

    MIN_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Minimum flow time

    PERCENT_AUTOMATIC_FAILS

    Unit: Percent

    Valid groupings and filters: Agent, Agent Hierarchy, Channel, Evaluation Form ID, Evaluation Source, Form Version, Queue, Routing Profile

    UI name: Automatic fails percent

    PERCENT_BOT_CONVERSATIONS_OUTCOME

    Unit: Percent

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Percent bot conversations outcome

    PERCENT_BOT_INTENTS_OUTCOME

    Unit: Percent

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Bot ID, Bot alias, Bot version, Bot locale, Bot intent name, Flows resource ID, Flows module resource ID, Flow type, Flow action ID, Invoking resource published timestamp, Initiation method, Invoking resource type, Parent flows resource ID

    UI name: Percent bot intents outcome

    PERCENT_CASES_FIRST_CONTACT_RESOLVED

    Unit: Percent

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases resolved on first contact

    PERCENT_CONTACTS_STEP_EXPIRED

    Unit: Percent

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    PERCENT_CONTACTS_STEP_JOINED

    Unit: Percent

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    PERCENT_FLOWS_OUTCOME

    Unit: Percent

    Valid metric filter key: FLOWS_OUTCOME_TYPE

    Valid groupings and filters: Channel, contact/segmentAttributes/connect:Subtype, Flow type, Flows module resource ID, Flows next resource ID, Flows next resource queue ID, Flows outcome type, Flows resource ID, Initiation method, Resource published timestamp

    UI name: Flows outcome percentage.

    The FLOWS_OUTCOME_TYPE is not a valid grouping.

    PERCENT_NON_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Non-talk time percent

    PERCENT_TALK_TIME

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Talk time percent

    PERCENT_TALK_TIME_AGENT

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Agent talk time percent

    PERCENT_TALK_TIME_CUSTOMER

    This metric is available only for contacts analyzed by Contact Lens conversational analytics.

    Unit: Percentage

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Customer talk time percent

    RECIPIENTS_ATTEMPTED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Recipients attempted

    RECIPIENTS_INTERACTED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Valid metric filter key: CAMPAIGN_INTERACTION_EVENT_TYPE

    Unit: Count

    Valid groupings and filters: Campaign, Channel, contact/segmentAttributes/connect:Subtype, Campaign Execution Timestamp

    UI name: Recipients interacted

    RECIPIENTS_TARGETED

    This metric is only available for outbound campaigns initiated using a customer segment. It is not available for event triggered campaigns.

    Unit: Count

    Valid groupings and filters: Campaign, Campaign Execution Timestamp

    UI name: Recipients targeted

    REOPENED_CASE_ACTIONS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases reopened

    RESOLVED_CASE_ACTIONS

    Unit: Count

    Required filter key: CASE_TEMPLATE_ARN

    Valid groupings and filters: CASE_TEMPLATE_ARN, CASE_STATUS

    UI name: Cases resolved

    SERVICE_LEVEL

    You can include up to 20 SERVICE_LEVEL metrics in a request.

    Unit: Percent

    Valid groupings and filters: Queue, Channel, Routing Profile, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Service level X

    STEP_CONTACTS_QUEUED

    Unit: Count

    Valid groupings and filters: Queue, RoutingStepExpression

    UI name: This metric is available in Real-time Metrics UI but not on the Historical Metrics UI.

    SUM_AFTER_CONTACT_WORK_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: After contact work time

    SUM_CONNECTING_TIME_AGENT

    Unit: Seconds

    Valid metric filter key: INITIATION_METHOD. This metric only supports the following filter keys as INITIATION_METHOD: INBOUND | OUTBOUND | CALLBACK | API | CALLBACK_CUSTOMER_FIRST_DIALED

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent API connecting time

    The Negate key in metric-level filters is not applicable for this metric.

    CONTACTS_ABANDONED

    Unit: Count

    Metric filter:

    • Valid values: API| INCOMING | OUTBOUND | TRANSFER | CALLBACK | QUEUE_TRANSFER| Disconnect | CALLBACK_CUSTOMER_FIRST_DIALED

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, RoutingStepExpression, Q in Connect

    UI name: Contact abandoned

    SUM_CONTACTS_ABANDONED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts abandoned in X seconds

    SUM_CONTACTS_ANSWERED_IN_X

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    Threshold: For ThresholdValue, enter any whole number from 1 to 604800 (inclusive), in seconds. For Comparison, you can use LT (for \"Less than\") or LTE (for \"Less than equal\").

    UI name: Contacts answered in X seconds

    SUM_CONTACT_FLOW_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contact flow time

    SUM_CONTACT_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent on contact time

    SUM_CONTACTS_DISCONNECTED

    Valid metric filter key: DISCONNECT_REASON

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Contact disconnected

    SUM_ERROR_STATUS_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Error status time

    SUM_HANDLE_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Contact handle time

    SUM_HOLD_TIME

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Customer hold time

    SUM_IDLE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent idle time

    SUM_INTERACTION_AND_HOLD_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy, Q in Connect

    UI name: Agent interaction and hold time

    SUM_INTERACTION_TIME

    Unit: Seconds

    Valid groupings and filters: Queue, Channel, Routing Profile, Agent, Agent Hierarchy

    UI name: Agent interaction time

    SUM_NON_PRODUCTIVE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Agent non-productive time

    SUM_ONLINE_TIME_AGENT

    Unit: Seconds

    Valid groupings and filters: Routing Profile, Agent, Agent Hierarchy

    UI name: Online time

    SUM_RETRY_CALLBACK_ATTEMPTS

    Unit: Count

    Valid groupings and filters: Queue, Channel, Routing Profile, contact/segmentAttributes/connect:Subtype, Q in Connect

    UI name: Callback attempts

    " }, "NextToken":{ "shape":"NextToken2500", @@ -20943,7 +22011,7 @@ }, "Constraints":{ "shape":"TaskTemplateConstraints", - "documentation":"

    Constraints that are applicable to the fields listed.

    " + "documentation":"

    Constraints that are applicable to the fields listed. Although this parameter is marked as optional in the API model, the service requires it when calling CreateTaskTemplate or UpdateTaskTemplate. The RequiredFields array must contain at least one element, and the field of type NAME must be included in RequiredFields.

    " }, "Defaults":{ "shape":"TaskTemplateDefaults", @@ -21040,11 +22108,11 @@ "documentation":"

    The distribution of traffic between the instance and its replicas.

    " }, "Id":{ - "shape":"TrafficDistributionGroupId", + "shape":"ACGRTrafficDistributionGroupId", "documentation":"

    The identifier of the traffic distribution group. This can be the ID or the ARN if the API is being called in the Region where the traffic distribution group was created. The ARN must be provided if the call is from the replicated Region.

    " }, "Arn":{ - "shape":"TrafficDistributionGroupArn", + "shape":"ACGRTrafficDistributionGroupArn", "documentation":"

    The Amazon Resource Name (ARN) of the traffic distribution group.

    " }, "SignInConfig":{ @@ -22073,10 +23141,6 @@ }, "documentation":"

    The Connect Customer instance.

    " }, - "InstanceArn":{ - "type":"string", - "pattern":"arn:(aws|aws-us-gov):connect:[a-z]{2}-[a-z]+-[0-9-]{1}:[0-9]{1,20}:instance/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}" - }, "InstanceAttributeType":{ "type":"string", "enum":[ @@ -22461,6 +23525,10 @@ "member":{"shape":"IpCidr"} }, "IsReadOnly":{"type":"boolean"}, + "IsolatedRegionsList":{ + "type":"list", + "member":{"shape":"AwsRegion"} + }, "IvrRecordingTrack":{ "type":"string", "enum":["ALL"] @@ -23616,6 +24684,54 @@ } } }, + "ListEvaluationFormAIVersionsRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "ContactInteractionType" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "ContactInteractionType":{ + "shape":"ContactInteractionType", + "documentation":"

    The contact interaction type for the evaluation form.

    ", + "location":"querystring", + "locationName":"contactInteractionType" + }, + "MaxResults":{ + "shape":"MaxResult100", + "documentation":"

    The maximum number of results to return per page.

    ", + "box":true, + "location":"querystring", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListEvaluationFormAIVersionsResponse":{ + "type":"structure", + "required":["AIVersionSummaries"], + "members":{ + "AIVersionSummaries":{ + "shape":"EvaluationFormAIVersionSummaryList", + "documentation":"

    The list of AI version summaries.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + } + } + }, "ListEvaluationFormVersionsRequest":{ "type":"structure", "required":[ @@ -23703,6 +24819,45 @@ } } }, + "ListExtractionDefinitionsRequest":{ + "type":"structure", + "required":["InstanceId"], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "MaxResults":{ + "shape":"MaxResult100", + "documentation":"

    The maximum number of results to return per page. The default MaxResult size is 100.

    ", + "box":true, + "location":"querystring", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListExtractionDefinitionsResponse":{ + "type":"structure", + "required":["ExtractionDefinitionSummaryList"], + "members":{ + "ExtractionDefinitionSummaryList":{ + "shape":"ExtractionDefinitionSummaryList", + "documentation":"

    Information about the extraction definitions.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + } + } + }, "ListFlowAssociationResourceType":{ "type":"string", "enum":[ @@ -24091,6 +25246,50 @@ } } }, + "ListMetricsRequest":{ + "type":"structure", + "required":["InstanceId"], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "Type":{ + "shape":"MetricType", + "documentation":"

    The type of metrics to list. Valid values: AWS_MANAGED | CUSTOMER_MANAGED.

    ", + "location":"querystring", + "locationName":"type" + }, + "MaxResults":{ + "shape":"MaxResult100", + "documentation":"

    The maximum number of results to return per page.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListMetricsResponse":{ + "type":"structure", + "required":["MetricSummaryList"], + "members":{ + "MetricSummaryList":{ + "shape":"MetricSummaryList", + "documentation":"

    The list of metric summaries.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + } + } + }, "ListNotificationsRequest":{ "type":"structure", "required":["InstanceId"], @@ -24847,6 +26046,61 @@ } } }, + "ListSecurityProfileAIAgentsRequest":{ + "type":"structure", + "required":[ + "SecurityProfileId", + "InstanceId" + ], + "members":{ + "SecurityProfileId":{ + "shape":"SecurityProfileId", + "documentation":"

    The identifier for the security profle.

    ", + "location":"uri", + "locationName":"SecurityProfileId" + }, + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "MaxResults":{ + "shape":"MaxResult1000", + "documentation":"

    The maximum number of results to return per page.

    ", + "box":true, + "location":"querystring", + "locationName":"maxResults" + } + } + }, + "ListSecurityProfileAIAgentsResponse":{ + "type":"structure", + "members":{ + "AllowedAIAgents":{ + "shape":"AllowedAIAgents", + "documentation":"

    A list of the allowed AI agents and their types.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + }, + "LastModifiedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when this resource was last modified.

    " + }, + "LastModifiedRegion":{ + "shape":"RegionName", + "documentation":"

    The Amazon Web Services Region where this resource was last modified.

    " + } + } + }, "ListSecurityProfileApplicationsRequest":{ "type":"structure", "required":[ @@ -25296,7 +26550,7 @@ "locationName":"TrafficDistributionGroupId" }, "MaxResults":{ - "shape":"MaxResult10", + "shape":"MaxResult1000", "documentation":"

    The maximum number of results to return per page.

    ", "box":true, "location":"querystring", @@ -25339,7 +26593,7 @@ "locationName":"nextToken" }, "InstanceId":{ - "shape":"InstanceIdOrArn", + "shape":"ACGRInstanceIdOrArn", "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", "location":"querystring", "locationName":"instanceId" @@ -25907,10 +27161,7 @@ }, "MediaConcurrency":{ "type":"structure", - "required":[ - "Channel", - "Concurrency" - ], + "required":["Channel"], "members":{ "Channel":{ "shape":"Channel", @@ -25923,6 +27174,10 @@ "CrossChannelBehavior":{ "shape":"CrossChannelBehavior", "documentation":"

    Defines the cross-channel routing behavior for each channel that is enabled for this Routing Profile. For example, this allows you to offer an agent a different contact from another channel when they are currently working with a contact from a Voice channel.

    " + }, + "WorkloadTypeConcurrencies":{ + "shape":"WorkloadTypeConcurrencies", + "documentation":"

    Defines the list of workload type concurrency configurations for a channel. When provided, enables granular concurrency control based on workload type values.

    " } }, "documentation":"

    Contains information about which channels are supported, and how many contacts an agent can have on a channel simultaneously.

    " @@ -26050,6 +27305,37 @@ "max":2000, "min":1 }, + "MetricCalculation":{ + "type":"structure", + "required":[ + "CalculationComponents", + "Calculation" + ], + "members":{ + "CalculationComponents":{ + "shape":"CalculationComponentList", + "documentation":"

    The list of component metrics referenced in the calculation formula. Each component has an alias used in the formula expression.

    " + }, + "Calculation":{ + "shape":"CalculationExpression", + "documentation":"

    The formula expression that defines how the metric is calculated. Uses component aliases (for example, 100 * SUM(M1) / SUM(M2)).

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

    Contains the formula and component metrics that define a custom metric calculation.

    " + }, + "MetricCategory":{ + "type":"string", + "max":100, + "min":1 + }, + "MetricCreationMethod":{ + "type":"string", + "documentation":"

    The method used to create a custom metric. Valid values: SERVICE_LEVEL_BUILDER | METRIC_BUILDER.

    ", + "enum":[ + "SERVICE_LEVEL_BUILDER", + "METRIC_BUILDER" + ] + }, "MetricDataCollectionsV2":{ "type":"list", "member":{"shape":"MetricDataV2"} @@ -26069,6 +27355,248 @@ }, "documentation":"

    Contains the name, thresholds, and metric filters.

    " }, + "MetricDefinition":{ + "type":"structure", + "required":[ + "Arn", + "Id", + "Name", + "Type", + "Unit", + "Groupings", + "Filters", + "Category", + "SupportsPreaggregateCalculation", + "SupportsCustomCalculation" + ], + "members":{ + "Arn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the metric. May be qualified with $SAVED or $LATEST.

    " + }, + "Id":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric.

    " + }, + "Name":{ + "shape":"MetricName", + "documentation":"

    The name of the metric.

    " + }, + "Description":{ + "shape":"MetricDescription", + "documentation":"

    The description of the metric.

    " + }, + "MetricCalculation":{ + "shape":"MetricCalculation", + "documentation":"

    The calculation definition for the metric.

    " + }, + "CreationMethod":{ + "shape":"MetricCreationMethod", + "documentation":"

    The method used to create the metric. Valid values: SERVICE_LEVEL_BUILDER (created with the guided service-level experience) | METRIC_BUILDER (created with the free-form metric builder).

    " + }, + "Status":{ + "shape":"MetricStatus", + "documentation":"

    The publish status of the metric. Valid values: PUBLISHED | SAVED.

    " + }, + "Type":{ + "shape":"MetricType", + "documentation":"

    The type of the metric. Valid values: AWS_MANAGED | CUSTOMER_MANAGED.

    " + }, + "Unit":{ + "shape":"MetricUnit", + "documentation":"

    The display unit for the metric's data.

    " + }, + "PositiveTrendIndicator":{ + "shape":"TrendIndicator", + "documentation":"

    How an increase in the metric value should be interpreted. Valid values: POSITIVE, NEUTRAL, NEGATIVE.

    " + }, + "Groupings":{ + "shape":"MetricGroupingList", + "documentation":"

    The groupings available for this metric.

    " + }, + "Filters":{ + "shape":"AvailableFilterList", + "documentation":"

    The filters applied to the metric.

    " + }, + "EffectiveTime":{ + "shape":"Timestamp", + "documentation":"

    The earliest time that can be queried for this metric.

    " + }, + "RefreshRate":{ + "shape":"RefreshRate", + "documentation":"

    The minimum interval, in seconds, between data refreshes for this metric.

    " + }, + "Category":{ + "shape":"MetricCategory", + "documentation":"

    The category of the metric.

    " + }, + "SupportedStats":{ + "shape":"SupportedStatsList", + "documentation":"

    The stat aggregations available for this metric.

    " + }, + "DefaultStat":{ + "shape":"DefaultStat", + "documentation":"

    The default stat aggregation for the metric.

    " + }, + "SupportsPreaggregateCalculation":{ + "shape":"SupportsPreaggregateCalculation", + "documentation":"

    Specifies whether the metric can be used inside aggregating statistical functions (SUM, AVG, etc.) in custom metric calculations.

    " + }, + "SupportsCustomCalculation":{ + "shape":"SupportsCustomCalculation", + "documentation":"

    Specifies whether the metric can be used as a component of custom metrics.

    " + }, + "PrimaryEventSource":{ + "shape":"PrimaryEventSource", + "documentation":"

    The primary event source for the metric data.

    " + }, + "PrimaryEventSourceEffectiveTimestampType":{ + "shape":"PrimaryEventSourceEffectiveTimestampType", + "documentation":"

    The timestamp type that determines where the metric appears on a time series.

    " + }, + "CreatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of when the metric was created.

    " + }, + "CreatedUser":{ + "shape":"CreatedByInfo", + "documentation":"

    The user that created the metric. The creator for metrics created through the CreateMetric API will be Amazon Connect API.

    " + }, + "LastModifiedRegion":{ + "shape":"RegionName", + "documentation":"

    The region where the metric was last modified.

    " + }, + "LastModifiedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of when the metric was last modified.

    " + }, + "LastModifiedUser":{ + "shape":"CreatedByInfo", + "documentation":"

    The user that last modified the metric. For modifications made through the API, this will be Amazon Connect API.

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

    The tags used to organize, track, or control access for this resource. For example, { \"Tags\": {\"key1\":\"value1\", \"key2\":\"value2\"} }.

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

    Contains the full definition of a metric, including its calculation, unit, status, and trend indicator.

    " + }, + "MetricDescription":{ + "type":"string", + "max":500, + "min":0 + }, + "MetricFilter":{ + "type":"structure", + "required":["MetricFilterKey"], + "members":{ + "MetricFilterKey":{ + "shape":"MetricFilterKey", + "documentation":"

    The key identifying the field to filter on.

    " + }, + "Negate":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the filter condition is negated. When set to true, the filter excludes matching data instead of including it.

    " + }, + "NumberCondition":{ + "shape":"MetricFilterNumberCondition", + "documentation":"

    A numeric comparison condition.

    " + }, + "StringCondition":{ + "shape":"MetricFilterStringCondition", + "documentation":"

    A string comparison condition.

    " + }, + "BooleanCondition":{ + "shape":"MetricFilterBooleanCondition", + "documentation":"

    A boolean comparison condition.

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

    A filter condition applied to a metric component in a calculation. Filters restrict the data included in the metric computation.

    " + }, + "MetricFilterBooleanCondition":{ + "type":"structure", + "required":["Comparison"], + "members":{ + "Comparison":{ + "shape":"MetricFilterBooleanConditionComparison", + "documentation":"

    The comparison operator. Valid values: IS_TRUE (matches when the field is true) | IS_FALSE (matches when the field is false).

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

    A boolean comparison condition for metric filters.

    " + }, + "MetricFilterBooleanConditionComparison":{ + "type":"string", + "documentation":"

    The boolean comparison operator for metric filters. Valid values: IS_TRUE | IS_FALSE.

    ", + "enum":[ + "IS_TRUE", + "IS_FALSE" + ] + }, + "MetricFilterKey":{ + "type":"string", + "max":100, + "min":1 + }, + "MetricFilterList":{ + "type":"list", + "member":{"shape":"MetricFilter"}, + "max":5, + "min":0 + }, + "MetricFilterNumberCondition":{ + "type":"structure", + "required":[ + "Comparison", + "Values" + ], + "members":{ + "Comparison":{ + "shape":"MetricFilterNumberConditionComparison", + "documentation":"

    The comparison operator. Valid values: LESSER (less than) | LESSER_OR_EQUAL (less than or equal to) | GREATER (greater than) | GREATER_OR_EQUAL (greater than or equal to).

    " + }, + "Values":{ + "shape":"NumberValueList", + "documentation":"

    The numeric values to compare against.

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

    A numeric comparison condition for metric filters.

    " + }, + "MetricFilterNumberConditionComparison":{ + "type":"string", + "documentation":"

    The numeric comparison operator for metric filters. Valid values: LESSER | LESSER_OR_EQUAL | GREATER | GREATER_OR_EQUAL.

    ", + "enum":[ + "LESSER", + "LESSER_OR_EQUAL", + "GREATER", + "GREATER_OR_EQUAL" + ] + }, + "MetricFilterStringCondition":{ + "type":"structure", + "required":[ + "Comparison", + "Values" + ], + "members":{ + "Comparison":{ + "shape":"MetricFilterStringConditionComparison", + "documentation":"

    The comparison operator. Valid values: MATCHES_ANY (matches any of the specified values) | MATCHES_NONE (matches none of the specified values).

    " + }, + "Values":{ + "shape":"StringValueList", + "documentation":"

    The string values to compare against.

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

    A string comparison condition for metric filters.

    " + }, + "MetricFilterStringConditionComparison":{ + "type":"string", + "documentation":"

    The string comparison operator for metric filters. Valid values: MATCHES_ANY | MATCHES_NONE.

    ", + "enum":[ + "MATCHES_ANY", + "MATCHES_NONE" + ] + }, "MetricFilterV2":{ "type":"structure", "members":{ @@ -26098,6 +27626,10 @@ "member":{"shape":"MetricFilterV2"}, "max":2 }, + "MetricGroupingList":{ + "type":"list", + "member":{"shape":"String"} + }, "MetricId":{ "type":"string", "max":150, @@ -26121,6 +27653,11 @@ }, "documentation":"

    The interval period with the start and end time for the metrics.

    " }, + "MetricName":{ + "type":"string", + "max":128, + "min":1 + }, "MetricNameV2":{"type":"string"}, "MetricResultV2":{ "type":"structure", @@ -26144,6 +27681,111 @@ "type":"list", "member":{"shape":"MetricResultV2"} }, + "MetricSearchConditionList":{ + "type":"list", + "member":{"shape":"MetricSearchCriteria"} + }, + "MetricSearchCriteria":{ + "type":"structure", + "members":{ + "OrConditions":{ + "shape":"MetricSearchConditionList", + "documentation":"

    A list of conditions to be met, where at least one condition must be satisfied.

    " + }, + "AndConditions":{ + "shape":"MetricSearchConditionList", + "documentation":"

    A list of conditions that must all be satisfied.

    " + }, + "StringCondition":{"shape":"StringCondition"}, + "BooleanCondition":{"shape":"BooleanCondition"} + }, + "documentation":"

    Defines the search criteria for filtering metrics.

    " + }, + "MetricSearchFilter":{ + "type":"structure", + "members":{ + "TagFilter":{ + "shape":"ControlPlaneTagFilter", + "documentation":"

    An object that can be used to specify tag conditions inside the SearchFilter. This accepts an OR of AND (List of List) input where:

    • The top level list specifies conditions that need to be applied with OR operator.

    • The inner list specifies conditions that need to be applied with AND operator.

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

    Filters to apply when searching for metrics.

    " + }, + "MetricSearchSummaryList":{ + "type":"list", + "member":{"shape":"MetricDefinition"} + }, + "MetricStatus":{ + "type":"string", + "documentation":"

    The publish status of a metric. Valid values: PUBLISHED | SAVED.

    ", + "enum":[ + "PUBLISHED", + "SAVED" + ] + }, + "MetricSummary":{ + "type":"structure", + "required":[ + "Arn", + "Id", + "Name", + "Status", + "Type" + ], + "members":{ + "Arn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the metric.

    " + }, + "Id":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric.

    " + }, + "Name":{ + "shape":"MetricName", + "documentation":"

    The name of the metric.

    " + }, + "Status":{ + "shape":"MetricStatus", + "documentation":"

    The publish status of the metric.

    " + }, + "Type":{ + "shape":"MetricType", + "documentation":"

    The type of the metric.

    " + }, + "LastModifiedRegion":{ + "shape":"RegionName", + "documentation":"

    The region where the metric was last modified.

    " + }, + "LastModifiedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of when the metric was last modified.

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

    Contains summary information about a metric.

    " + }, + "MetricSummaryList":{ + "type":"list", + "member":{"shape":"MetricSummary"} + }, + "MetricType":{ + "type":"string", + "documentation":"

    The type of the metric. Valid values: AWS_MANAGED | CUSTOMER_MANAGED.

    ", + "enum":[ + "AWS_MANAGED", + "CUSTOMER_MANAGED" + ] + }, + "MetricUnit":{ + "type":"string", + "documentation":"

    The display unit for metric data. Valid values: INTEGER | DOUBLE | PERCENT | SECONDS.

    ", + "enum":[ + "INTEGER", + "DOUBLE", + "PERCENT", + "SECONDS" + ] + }, "MetricV2":{ "type":"structure", "members":{ @@ -26373,6 +28015,17 @@ "max":2500, "min":1 }, + "NotFoundBehaviorType":{ + "type":"string", + "enum":[ + "USE_DEFAULT_VALUE", + "OMIT" + ] + }, + "NotFoundDefaultValue":{ + "type":"string", + "max":1024 + }, "Notification":{ "type":"structure", "required":[ @@ -26637,6 +28290,12 @@ }, "documentation":"

    Information about a reference when the referenceType is NUMBER. Otherwise, null.

    " }, + "NumberValueList":{ + "type":"list", + "member":{"shape":"Double"}, + "max":10, + "min":1 + }, "NumericQuestionPropertyAutomationLabel":{ "type":"string", "enum":[ @@ -27103,7 +28762,7 @@ "documentation":"

    Display name of the participant.

    " } }, - "documentation":"

    The customer's details.

    " + "documentation":"

    The details of the participant, including their display name.

    " }, "ParticipantDetailsToAdd":{ "type":"structure", @@ -27812,6 +29471,65 @@ "max":128, "min":0 }, + "PreEvaluationFilter":{ + "type":"structure", + "required":[ + "ResourceType", + "FilterType", + "FilterKey", + "FilterValue", + "Operator" + ], + "members":{ + "ResourceType":{ + "shape":"PreEvaluationFilterResourceType", + "documentation":"

    The type of resource to filter on. Valid values: CONTACT.

    " + }, + "FilterType":{ + "shape":"PreEvaluationFilterType", + "documentation":"

    The type of filter to apply. Valid values: TAG.

    " + }, + "FilterKey":{ + "shape":"String", + "documentation":"

    The key of the attribute to filter on. For tag filters, this is the tag key.

    " + }, + "FilterValue":{ + "shape":"String", + "documentation":"

    The value to match against. For tag filters, this is the tag value.

    " + }, + "Operator":{ + "shape":"PreEvaluationFilterOperator", + "documentation":"

    The comparison operator for the filter condition. Valid values: EQUALS.

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

    A single pre-evaluation filter condition. Specifies a resource type, filter type, key, value, and operator to match against a resource attribute.

    " + }, + "PreEvaluationFilterList":{ + "type":"list", + "member":{"shape":"PreEvaluationFilter"} + }, + "PreEvaluationFilterOperator":{ + "type":"string", + "enum":["EQUALS"] + }, + "PreEvaluationFilterResourceType":{ + "type":"string", + "enum":["CONTACT"] + }, + "PreEvaluationFilterType":{ + "type":"string", + "enum":["TAG"] + }, + "PreEvaluationFilters":{ + "type":"structure", + "members":{ + "AndConditions":{ + "shape":"PreEvaluationFilterList", + "documentation":"

    A list of conditions that the rule evaluates together using AND logic. All conditions must be met for the event to be evaluated by the rule.

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

    The pre-evaluation filters for a rule, that restrict a rule to be applied to only certain resources based on the resource's attributes, such as tags assigned to a contact. The pre-evaluation filters are applied even before rule conditions are evaluated and are used to enforce tag-based-access-control while applying rules.

    " + }, "PreSignedAttachmentUrl":{ "type":"string", "max":2000, @@ -28028,6 +29746,16 @@ "member":{"shape":"PrimaryAttributeValue"}, "max":5 }, + "PrimaryEventSource":{ + "type":"string", + "max":100, + "min":1 + }, + "PrimaryEventSourceEffectiveTimestampType":{ + "type":"string", + "max":100, + "min":1 + }, "PrimaryValue":{ "type":"structure", "required":[ @@ -28281,7 +30009,8 @@ "REFERENCED_RESOURCE_NOT_FOUND", "RESOURCE_NAME_ALREADY_EXISTS", "REQUIRED_PROPERTY_MISSING", - "NOT_SUPPORTED" + "NOT_SUPPORTED", + "TYPE_MISMATCH" ] }, "PutUserStatusRequest":{ @@ -28899,6 +30628,43 @@ "max":128, "min":1 }, + "RealTimeContactAnalysisExtractedInformationContent":{ + "type":"string", + "max":1024, + "min":1 + }, + "RealTimeContactAnalysisExtractedInformationFailureCode":{ + "type":"string", + "enum":[ + "QUOTA_EXCEEDED", + "INSUFFICIENT_CONVERSATION_CONTENT", + "FAILED_SAFETY_GUIDELINES", + "INTERNAL_ERROR", + "MAX_PACKAGE_FEATURE_ONLY" + ] + }, + "RealTimeContactAnalysisExtractedInformationValue":{ + "type":"structure", + "required":[ + "Content", + "PointsOfInterest" + ], + "members":{ + "Content":{ + "shape":"RealTimeContactAnalysisExtractedInformationContent", + "documentation":"

    The text content of the extracted value.

    " + }, + "PointsOfInterest":{ + "shape":"RealTimeContactAnalysisTranscriptItemsWithCharacterOffsets", + "documentation":"

    The sections in the conversation that indicate where the extracted value was found.

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

    An individual value extracted from the conversation, including its content and the locations where it was found.

    " + }, + "RealTimeContactAnalysisExtractedInformationValues":{ + "type":"list", + "member":{"shape":"RealTimeContactAnalysisExtractedInformationValue"} + }, "RealTimeContactAnalysisId256":{ "type":"string", "max":256, @@ -29058,6 +30824,36 @@ }, "documentation":"

    Segment type describing a contact event.

    " }, + "RealTimeContactAnalysisSegmentExtractedInformation":{ + "type":"structure", + "required":[ + "ExtractionDefinitionId", + "ExtractionDefinitionName" + ], + "members":{ + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition that produced this result.

    " + }, + "ExtractionDefinitionName":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    The name of the extraction definition that produced this result.

    " + }, + "ExtractionDefinitionDisplayLabel":{ + "shape":"ExtractionDefinitionDisplayLabel", + "documentation":"

    The display label of the extraction definition that produced this result.

    " + }, + "ExtractedValues":{ + "shape":"RealTimeContactAnalysisExtractedInformationValues", + "documentation":"

    The list of values extracted from the conversation for this extraction definition. This field is empty when a FailureCode is present.

    " + }, + "FailureCode":{ + "shape":"RealTimeContactAnalysisExtractedInformationFailureCode", + "documentation":"

    If the information failed to be extracted, one of the following failure codes occurs:

    • QUOTA_EXCEEDED: The number of concurrent analytics jobs reached your service quota.

    • INSUFFICIENT_CONVERSATION_CONTENT: Information extraction requires a conversation with at least one turn from each participant.

    • FAILED_SAFETY_GUIDELINES: The extracted information cannot be provided because it failed to meet system safety guidelines.

    • INTERNAL_ERROR: Internal system error.

    • MAX_PACKAGE_FEATURE_ONLY: Information extraction is only available in Amazon Connect Customer instances.

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

    Segment containing information extracted from the conversation. Each segment represents the results for a single extraction definition.

    " + }, "RealTimeContactAnalysisSegmentIssues":{ "type":"structure", "required":["IssuesDetected"], @@ -29145,13 +30941,14 @@ "Issues", "Event", "Attachments", - "PostContactSummary" + "PostContactSummary", + "ExtractedInformation" ] }, "RealTimeContactAnalysisSegmentTypes":{ "type":"list", "member":{"shape":"RealTimeContactAnalysisSegmentType"}, - "max":6 + "max":7 }, "RealTimeContactAnalysisSentimentLabel":{ "type":"string", @@ -29261,6 +31058,10 @@ "PostContactSummary":{ "shape":"RealTimeContactAnalysisSegmentPostContactSummary", "documentation":"

    Information about the post-contact summary.

    " + }, + "ExtractedInformation":{ + "shape":"RealTimeContactAnalysisSegmentExtractedInformation", + "documentation":"

    The extracted information from the conversation.

    " } }, "documentation":"

    An analyzed segment for a real-time analysis session.

    ", @@ -29581,7 +31382,8 @@ "Email":{ "shape":"EmailReference", "documentation":"

    Information about a reference when the referenceType is EMAIL. Otherwise, null.

    " - } + }, + "ContactAnalysis":{"shape":"ContactAnalysisReference"} }, "documentation":"

    Contains summary information about a reference. ReferenceSummary contains only one non null field between the URL and attachment based on the reference type.

    ", "union":true @@ -29616,6 +31418,7 @@ "max":4096, "min":0 }, + "RefreshRate":{"type":"long"}, "RefreshTokenDuration":{ "type":"integer", "box":true, @@ -29661,12 +31464,11 @@ "type":"structure", "required":[ "InstanceId", - "ReplicaRegion", - "ReplicaAlias" + "ReplicaRegion" ], "members":{ "InstanceId":{ - "shape":"InstanceIdOrArn", + "shape":"ACGRInstanceIdOrArn", "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance. You can provide the InstanceId, or the entire ARN.

    ", "location":"uri", "locationName":"InstanceId" @@ -30334,6 +32136,10 @@ "shape":"RuleTriggerEventSource", "documentation":"

    The event source to trigger the rule.

    " }, + "RuleCapabilityTiers":{ + "shape":"RuleCapabilityTiers", + "documentation":"

    The list of capability tiers associated with the rule. Used for categorizing rules by capability (for example, GenerativeAI).

    " + }, "Function":{ "shape":"RuleFunction", "documentation":"

    The conditions of the rule.

    " @@ -30346,6 +32152,10 @@ "shape":"RulePublishStatus", "documentation":"

    The publish status of the rule.

    " }, + "PreEvaluationFilters":{ + "shape":"PreEvaluationFilters", + "documentation":"

    The pre-evaluation filters for the rule, that restrict the rule to be applied to only certain resources based on the resource's attributes, such as tags assigned to a contact. The pre-evaluation filters are applied even before rule conditions are evaluated and are used to enforce tag-based-access-control while applying rules.

    " + }, "CreatedTime":{ "shape":"Timestamp", "documentation":"

    The timestamp for when the rule was created.

    " @@ -30408,6 +32218,10 @@ "SubmitAutoEvaluationAction":{ "shape":"SubmitAutoEvaluationActionDefinition", "documentation":"

    Information about the submit automated evaluation action.

    " + }, + "ExtractInformationAction":{ + "shape":"ExtractInformationActionDefinition", + "documentation":"

    Information about the extract information action.

    " } }, "documentation":"

    Information about the action to be performed when a rule is triggered.

    " @@ -30416,6 +32230,43 @@ "type":"list", "member":{"shape":"RuleAction"} }, + "RuleAttributeAndCondition":{ + "type":"structure", + "members":{ + "TagConditions":{ + "shape":"TagAndConditionList", + "documentation":"

    A list of tag conditions that need to be applied with AND condition.

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

    A list of conditions which would be applied together with an AND condition.

    " + }, + "RuleAttributeFilter":{ + "type":"structure", + "members":{ + "OrConditions":{ + "shape":"RuleAttributeOrConditionList", + "documentation":"

    A list of conditions which would be applied together with an OR condition.

    " + }, + "AndCondition":{ + "shape":"RuleAttributeAndCondition", + "documentation":"

    A list of conditions which would be applied together with an AND condition.

    " + }, + "TagCondition":{"shape":"TagCondition"} + }, + "documentation":"

    An object that can be used to specify tag conditions inside the SearchFilter. This accepts an OR of AND (List of List) input where:

    • The top level list specifies conditions that need to be applied with OR operator.

    • The inner list specifies conditions that need to be applied with AND operator.

    " + }, + "RuleAttributeOrConditionList":{ + "type":"list", + "member":{"shape":"RuleAttributeAndCondition"} + }, + "RuleCapabilityTier":{ + "type":"string", + "enum":["GenerativeAI"] + }, + "RuleCapabilityTiers":{ + "type":"list", + "member":{"shape":"RuleCapabilityTier"} + }, "RuleFunction":{"type":"string"}, "RuleId":{ "type":"string", @@ -30435,6 +32286,75 @@ "PUBLISHED" ] }, + "RuleSearchSummary":{ + "type":"structure", + "required":[ + "Name", + "RuleId", + "RuleArn", + "TriggerEventSource", + "ActionSummaries", + "PublishStatus", + "CreatedTime", + "LastUpdatedTime", + "LastUpdatedBy" + ], + "members":{ + "Name":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "RuleId":{ + "shape":"RuleId", + "documentation":"

    A unique identifier for the rule.

    " + }, + "RuleArn":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "TriggerEventSource":{ + "shape":"RuleTriggerEventSource", + "documentation":"

    The event source to trigger the rule.

    " + }, + "ActionSummaries":{ + "shape":"ActionSummaries", + "documentation":"

    A list of ActionTypes associated with a rule.

    " + }, + "RuleCapabilityTiers":{ + "shape":"RuleCapabilityTiers", + "documentation":"

    The list of capability tiers associated with the rule. Used for categorizing rules by capability (for example, GenerativeAI).

    " + }, + "PublishStatus":{ + "shape":"RulePublishStatus", + "documentation":"

    The publish status of the rule.

    " + }, + "PreEvaluationFilters":{ + "shape":"PreEvaluationFilters", + "documentation":"

    The pre-evaluation filters for the rule, that restrict the rule to be applied to only certain resources based on the resource's attributes, such as tags assigned to a contact. The pre-evaluation filters are applied even before rule conditions are evaluated and are used to enforce tag-based-access-control while applying rules.

    " + }, + "CreatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the rule was created.

    " + }, + "LastUpdatedTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp for when the rule was last updated.

    " + }, + "LastUpdatedBy":{ + "shape":"ARN", + "documentation":"

    The Amazon Resource Name (ARN) of the user who last updated the rule.

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

    The tags used to organize, track, or control access for this resource. For example, { \"Tags\": {\"key1\":\"value1\", \"key2\":\"value2\"} }.

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

    A summary of information about a rule, returned as part of the response to a SearchRules operation.

    " + }, + "RuleSearchSummaryList":{ + "type":"list", + "member":{"shape":"RuleSearchSummary"} + }, "RuleSummary":{ "type":"structure", "required":[ @@ -30468,6 +32388,10 @@ "shape":"RulePublishStatus", "documentation":"

    The publish status of the rule.

    " }, + "RuleCapabilityTiers":{ + "shape":"RuleCapabilityTiers", + "documentation":"

    The list of capability tiers associated with the rule. Used for categorizing rules by capability (for example, GenerativeAI).

    " + }, "ActionSummaries":{ "shape":"ActionSummaries", "documentation":"

    A list of ActionTypes associated with a rule.

    " @@ -30512,6 +32436,58 @@ }, "documentation":"

    The rules configuration for conversational analytics. Controls whether Contact Lens rules are evaluated against the analytics output.

    " }, + "RulesExtractionDefinitionId":{ + "type":"string", + "max":256, + "min":1 + }, + "RulesExtractionDefinitionIdentifier":{ + "type":"structure", + "required":["Identifier"], + "members":{ + "Identifier":{ + "shape":"RulesExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition.

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

    An identifier that references an extraction definition resource.

    " + }, + "RulesExtractionDefinitionIdentifierList":{ + "type":"list", + "member":{"shape":"RulesExtractionDefinitionIdentifier"} + }, + "RulesSearchConditionList":{ + "type":"list", + "member":{"shape":"RulesSearchCriteria"} + }, + "RulesSearchCriteria":{ + "type":"structure", + "members":{ + "OrConditions":{ + "shape":"RulesSearchConditionList", + "documentation":"

    A list of conditions which would be applied together with an OR condition.

    " + }, + "AndConditions":{ + "shape":"RulesSearchConditionList", + "documentation":"

    A list of conditions which would be applied together with an AND condition.

    " + }, + "StringCondition":{ + "shape":"StringCondition", + "documentation":"

    A leaf node condition which can be used to specify a string condition.

    The currently supported values for FieldName are Name, PublishStatus, EventSourceName, RuleId, IntegrationAssociationId, ActionSummaries, and RuleCapabilityTiers.

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

    The search criteria to be used to return rules.

    " + }, + "RulesSearchFilter":{ + "type":"structure", + "members":{ + "AttributeFilter":{ + "shape":"RuleAttributeFilter", + "documentation":"

    An object that can be used to specify tag conditions inside the SearchFilter.

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

    Filters to be applied to search results.

    " + }, "S3Config":{ "type":"structure", "required":[ @@ -31195,6 +33171,50 @@ } } }, + "SearchMetricsRequest":{ + "type":"structure", + "required":["InstanceId"], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    " + }, + "MaxResults":{ + "shape":"MaxResult100", + "documentation":"

    The maximum number of results to return per page.

    ", + "box":true + }, + "SearchFilter":{ + "shape":"MetricSearchFilter", + "documentation":"

    Filters to be applied to search results.

    " + }, + "SearchCriteria":{ + "shape":"MetricSearchCriteria", + "documentation":"

    The search criteria to filter the metrics.

    " + } + } + }, + "SearchMetricsResponse":{ + "type":"structure", + "members":{ + "Metrics":{ + "shape":"MetricSearchSummaryList", + "documentation":"

    The metrics that matched the search criteria.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + }, + "ApproximateTotalCount":{ + "shape":"ApproximateTotalCount", + "documentation":"

    The approximate total number of metrics that matched your search criteria.

    " + } + } + }, "SearchNotificationsRequest":{ "type":"structure", "required":["InstanceId"], @@ -31421,7 +33441,7 @@ }, "ResourceTypes":{ "shape":"ResourceTypeList", - "documentation":"

    The list of resource types to be used to search tags from. If not provided or if any empty list is provided, this API will search from all supported resource types. Note that lowercase and - are required.

    Supported resource types

    • agent

    • agent-state

    • routing-profile

    • standard-queue

    • security-profile

    • operating-hours

    • prompt

    • contact-flow

    • flow- module

    • transfer-destination (also known as quick connect)

    " + "documentation":"

    The list of resource types to be used to search tags from. If not provided or if any empty list is provided, this API will search from all supported resource types. Note that lowercase and - are required.

    Supported resource types

    • agent

    • agent-state

    • routing-profile

    • standard-queue

    • security-profile

    • operating-hours

    • prompt

    • contact-flow

    • flow- module

    • transfer-destination (also known as quick connect)

    • metric

    " }, "NextToken":{ "shape":"NextToken2500", @@ -31495,6 +33515,51 @@ } } }, + "SearchRulesRequest":{ + "type":"structure", + "required":["InstanceId"], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    " + }, + "MaxResults":{ + "shape":"MaxResult200", + "documentation":"

    The maximum number of results to return per page.

    ", + "box":true + }, + "NextToken":{ + "shape":"NextToken2500", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    " + }, + "SearchCriteria":{ + "shape":"RulesSearchCriteria", + "documentation":"

    The search criteria to be used to return rules.

    " + }, + "SearchFilter":{ + "shape":"RulesSearchFilter", + "documentation":"

    Filters to be applied to search results, such as tag-based filters.

    " + } + } + }, + "SearchRulesResponse":{ + "type":"structure", + "required":["Rules"], + "members":{ + "Rules":{ + "shape":"RuleSearchSummaryList", + "documentation":"

    Information about the rules.

    " + }, + "ApproximateTotalCount":{ + "shape":"ApproximateTotalCount", + "documentation":"

    The total number of rules which matched your search query.

    " + }, + "NextToken":{ + "shape":"NextToken2500", + "documentation":"

    If there are additional results, this is the token for the next set of results.

    " + } + } + }, "SearchSecurityProfilesRequest":{ "type":"structure", "required":["InstanceId"], @@ -32678,6 +34743,70 @@ "CASES" ] }, + "StartAssistantContactRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "AiAgent", + "ParticipantDetails" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    " + }, + "AiAgent":{ + "shape":"AiAgentInput", + "documentation":"

    The AI agent configuration for this contact.

    " + }, + "ParticipantDetails":{ + "shape":"ParticipantDetails", + "documentation":"

    The display name and other details that identify the chat participant.

    " + }, + "InitialMessage":{ + "shape":"ChatMessage", + "documentation":"

    The initial message to send to the newly created chat.

    " + }, + "Attributes":{ + "shape":"Attributes", + "documentation":"

    A map of key-value pairs to associate with the contact. We make these attributes available to flows as standard contact attributes.

    You can provide up to 32,768 UTF-8 bytes across all key-value pairs for each contact.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If not provided, the Amazon Web Services SDK populates this field. For more information about idempotency, see Making retries safe with idempotent APIs.

    ", + "idempotencyToken":true + }, + "PersistentChat":{ + "shape":"PersistentChat", + "documentation":"

    The configuration that enables persistent chat. For more information about persistent chat and its use cases, see Enable persistent chat.

    " + }, + "RelatedContactId":{ + "shape":"ContactId", + "documentation":"

    The identifier of an Connect Customer contact related to the new assistant contact.

    You cannot provide both RelatedContactId and PersistentChat.

    " + } + } + }, + "StartAssistantContactResponse":{ + "type":"structure", + "members":{ + "ContactId":{ + "shape":"ContactId", + "documentation":"

    The identifier of the contact within the Connect Customer instance.

    " + }, + "ParticipantId":{ + "shape":"ParticipantId", + "documentation":"

    The identifier of the chat participant. The participant identifier remains the same throughout the chat lifecycle.

    " + }, + "ParticipantToken":{ + "shape":"ParticipantToken", + "documentation":"

    The token that the chat participant uses with the CreateParticipantConnection operation. The token remains valid for the lifetime of the chat participant.

    " + }, + "ContinuedFromContactId":{ + "shape":"ContactId", + "documentation":"

    The identifier of the contact from which the chat continues, returned only for persistent chats.

    " + } + } + }, "StartAttachedFileUploadRequest":{ "type":"structure", "required":[ @@ -32718,7 +34847,7 @@ }, "AssociatedResourceArn":{ "shape":"ARN", - "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases and Email.

    This value must be a valid ARN.

    ", + "documentation":"

    The resource to which the attached file is (being) uploaded to. The supported resources are Cases, Email, and Task.

    This value must be a valid ARN.

    ", "location":"querystring", "locationName":"associatedResourceArn" }, @@ -33545,6 +35674,10 @@ "Description":{ "shape":"Description", "documentation":"

    A description of the task that is shown to an agent in the Contact Control Panel (CCP).

    " + }, + "SegmentAttributes":{ + "shape":"SegmentAttributes", + "documentation":"

    A map of system-defined attributes for the WebRTC contact segment. Use the connect:Subtype attribute to specify the channel subtype, such as connect:WebRTC.

    " } } }, @@ -33819,6 +35952,12 @@ }, "documentation":"

    Information about a reference when the referenceType is STRING. Otherwise, null.

    " }, + "StringValueList":{ + "type":"list", + "member":{"shape":"String"}, + "max":10, + "min":1 + }, "Subject":{ "type":"string", "max":200, @@ -33961,6 +36100,12 @@ "type":"list", "member":{"shape":"SupportedMessagingContentType"} }, + "SupportedStatsList":{ + "type":"list", + "member":{"shape":"String"} + }, + "SupportsCustomCalculation":{"type":"boolean"}, + "SupportsPreaggregateCalculation":{"type":"boolean"}, "SuspendContactRecordingRequest":{ "type":"structure", "required":[ @@ -34784,11 +36929,11 @@ "type":"structure", "members":{ "Id":{ - "shape":"TrafficDistributionGroupId", + "shape":"ACGRTrafficDistributionGroupId", "documentation":"

    The identifier of the traffic distribution group. This can be the ID or the ARN if the API is being called in the Region where the traffic distribution group was created. The ARN must be provided if the call is from the replicated Region.

    " }, "Arn":{ - "shape":"TrafficDistributionGroupArn", + "shape":"ACGRTrafficDistributionGroupArn", "documentation":"

    The Amazon Resource Name (ARN) of the traffic distribution group.

    " }, "Name":{ @@ -34800,7 +36945,7 @@ "documentation":"

    The description of the traffic distribution group.

    " }, "InstanceArn":{ - "shape":"InstanceArn", + "shape":"ACGRInstanceArn", "documentation":"

    The Amazon Resource Name (ARN).

    " }, "Status":{ @@ -34818,10 +36963,6 @@ }, "documentation":"

    Information about a traffic distribution group.

    " }, - "TrafficDistributionGroupArn":{ - "type":"string", - "pattern":"^arn:(aws|aws-us-gov):connect:[a-z]{2}-[a-z]+-[0-9]{1}:[0-9]{1,20}:traffic-distribution-group/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$" - }, "TrafficDistributionGroupId":{ "type":"string", "pattern":"^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$" @@ -34845,11 +36986,11 @@ "type":"structure", "members":{ "Id":{ - "shape":"TrafficDistributionGroupId", + "shape":"ACGRTrafficDistributionGroupId", "documentation":"

    The identifier of the traffic distribution group. This can be the ID or the ARN if the API is being called in the Region where the traffic distribution group was created. The ARN must be provided if the call is from the replicated Region.

    " }, "Arn":{ - "shape":"TrafficDistributionGroupArn", + "shape":"ACGRTrafficDistributionGroupArn", "documentation":"

    The Amazon Resource Name (ARN) of the traffic distribution group.

    " }, "Name":{ @@ -34857,8 +36998,8 @@ "documentation":"

    The name of the traffic distribution group.

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

    The Amazon Resource Name (ARN) of the traffic distribution group.

    " + "shape":"ACGRInstanceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the instance.

    " }, "Status":{ "shape":"TrafficDistributionGroupStatus", @@ -34992,6 +37133,15 @@ } } }, + "TrendIndicator":{ + "type":"string", + "documentation":"

    Specifies how to interpret a positive trend in metric data. Valid values: POSITIVE | NEGATIVE | NEUTRAL.

    ", + "enum":[ + "POSITIVE", + "NEGATIVE", + "NEUTRAL" + ] + }, "URI":{ "type":"string", "max":2000, @@ -35649,6 +37799,55 @@ "type":"structure", "members":{} }, + "UpdateContactTaskTemplateRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "TaskTemplateId", + "ContactId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    " + }, + "TaskTemplateId":{ + "shape":"TaskTemplateId", + "documentation":"

    A unique identifier for the task template. For more information about task templates, see Task templates in the Connect Customer Administrator Guide.

    " + }, + "ContactId":{ + "shape":"ContactId", + "documentation":"

    The identifier of the contact in this instance of Connect Customer.

    " + } + } + }, + "UpdateContactTaskTemplateResponse":{ + "type":"structure", + "members":{} + }, + "UpdateCrossRegionRoutingRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "IsolatedAll" + ], + "members":{ + "InstanceId":{ + "shape":"ACGRInstanceIdOrArn", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "IsolatedAll":{ + "shape":"Boolean", + "documentation":"

    Set to true to disable cross-region routing for all Regions associated with this instance. Set to false to re-enable cross-region routing.

    " + } + } + }, + "UpdateCrossRegionRoutingResponse":{ + "type":"structure", + "members":{} + }, "UpdateDataTableAttributeRequest":{ "type":"structure", "required":[ @@ -35929,6 +38128,10 @@ "LanguageConfiguration":{ "shape":"EvaluationFormLanguageConfiguration", "documentation":"

    Configuration for language settings of the evaluation form.

    " + }, + "AIVersion":{ + "shape":"EvaluationFormAIVersion", + "documentation":"

    The AI version to use for the evaluation form. This specifies which AI model version is used for automated evaluations.

    " } } }, @@ -35954,6 +38157,50 @@ } } }, + "UpdateExtractionDefinitionRequest":{ + "type":"structure", + "required":[ + "ExtractionDefinitionId", + "InstanceId", + "Name", + "ExtractionConfiguration" + ], + "members":{ + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If not provided, the Amazon Web Services SDK populates this field.

    ", + "idempotencyToken":true + }, + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition to update.

    ", + "location":"uri", + "locationName":"ExtractionDefinitionId" + }, + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "Name":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    The name of the extraction definition.

    " + }, + "ExtractionConfiguration":{ + "shape":"ExtractionConfiguration", + "documentation":"

    The configuration that defines how data is extracted, including the prompt hint and not-found behavior.

    " + }, + "Display":{ + "shape":"ExtractionDefinitionDisplay", + "documentation":"

    The display settings for the extraction definition.

    " + } + } + }, + "UpdateExtractionDefinitionResponse":{ + "type":"structure", + "members":{} + }, "UpdateHoursOfOperationDescription":{ "type":"string", "max":250, @@ -36011,7 +38258,7 @@ }, "OverrideType":{ "shape":"OverrideType", - "documentation":"

    Whether the override will be defined as a standard or as a recurring event.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " + "documentation":"

    Whether the override will be defined as a standard or as a recurring event.

    For more information about how override types are applied, see Build your list of overrides in the Administrator Guide.

    " } } }, @@ -36118,6 +38365,76 @@ } } }, + "UpdateMetricContentRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "MetricId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric to update. Adding the $SAVED qualifier will update the saved version of the metric. Adding $LATEST or omitting a qualifier will update the published version.

    ", + "location":"uri", + "locationName":"MetricId" + }, + "MetricCalculation":{ + "shape":"MetricCalculation", + "documentation":"

    The updated calculation definition for the metric.

    " + }, + "Unit":{ + "shape":"MetricUnit", + "documentation":"

    The updated display unit for the metric.

    " + }, + "PositiveTrendIndicator":{ + "shape":"TrendIndicator", + "documentation":"

    How an increase in the metric value should be interpreted. Valid values: POSITIVE, NEUTRAL, NEGATIVE.

    " + } + } + }, + "UpdateMetricContentResponse":{ + "type":"structure", + "members":{} + }, + "UpdateMetricMetadataRequest":{ + "type":"structure", + "required":[ + "InstanceId", + "MetricId" + ], + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The identifier of the Connect Customer instance. You can find the instance ID in the Amazon Resource Name (ARN) of the instance.

    ", + "location":"uri", + "locationName":"InstanceId" + }, + "MetricId":{ + "shape":"MetricId", + "documentation":"

    The identifier of the metric to update. Adding the $SAVED qualifier will update the saved version of the metric. Adding $LATEST or omitting a qualifier will update the published version.

    ", + "location":"uri", + "locationName":"MetricId" + }, + "Name":{ + "shape":"MetricName", + "documentation":"

    The updated name of the metric.

    " + }, + "Description":{ + "shape":"MetricDescription", + "documentation":"

    The updated description of the metric.

    " + } + } + }, + "UpdateMetricMetadataResponse":{ + "type":"structure", + "members":{} + }, "UpdateNotificationContentRequest":{ "type":"structure", "required":[ @@ -36751,6 +39068,10 @@ "PublishStatus":{ "shape":"RulePublishStatus", "documentation":"

    The publish status of the rule.

    " + }, + "PreEvaluationFilters":{ + "shape":"PreEvaluationFilters", + "documentation":"

    The pre-evaluation filters for the rule, that restrict the rule to be applied to only certain resources based on the resource's attributes, such as tags assigned to a contact. The pre-evaluation filters are applied even before rule conditions are evaluated and are used to enforce tag-based-access-control while applying rules.

    " } } }, @@ -36805,6 +39126,10 @@ "shape":"AllowedFlowModules", "documentation":"

    A list of Flow Modules an AI Agent can invoke as a tool

    " }, + "AllowedAIAgents":{ + "shape":"AllowedAIAgents", + "documentation":"

    A list of AI agents that the security profile will give access to.

    " + }, "GranularAccessControlConfiguration":{ "shape":"GranularAccessControlConfiguration", "documentation":"

    The granular access control configuration for the security profile, including data table permissions.

    " @@ -36840,7 +39165,7 @@ }, "ContactFlowId":{ "shape":"ContactFlowId", - "documentation":"

    The identifier of the flow that runs by default when a task is created by referencing this template.

    " + "documentation":"

    The identifier of the flow that runs by default when a task is created by referencing this template.

    Although this parameter is marked as optional, the request must contain either a ContactFlowId or a field of type QUICK_CONNECT.

    " }, "SelfAssignFlowId":{ "shape":"ContactFlowId", @@ -36848,7 +39173,7 @@ }, "Constraints":{ "shape":"TaskTemplateConstraints", - "documentation":"

    Constraints that are applicable to the fields listed.

    " + "documentation":"

    Constraints that are applicable to the fields listed. Although this parameter is marked as optional in the API model, the service requires it when calling CreateTaskTemplate or UpdateTaskTemplate. The RequiredFields array must contain at least one element, and the field of type NAME must be included in RequiredFields.

    " }, "Defaults":{ "shape":"TaskTemplateDefaults", @@ -36856,11 +39181,11 @@ }, "Status":{ "shape":"TaskTemplateStatus", - "documentation":"

    Marks a template as ACTIVE or INACTIVE for a task to refer to it. Tasks can only be created from ACTIVE templates. If a template is marked as INACTIVE, then a task that refers to this template cannot be created.

    " + "documentation":"

    Marks a template as ACTIVE or INACTIVE for a task to refer to it. Tasks can only be created from ACTIVE templates. If a template is marked as INACTIVE, then a task that refers to this template cannot be created.

    Although this parameter is marked as optional, the service requires it when calling UpdateTaskTemplate.

    " }, "Fields":{ "shape":"TaskTemplateFields", - "documentation":"

    Fields that are part of the template.

    " + "documentation":"

    Fields that are part of the template.

    The request must contain exactly one field of type NAME. This field must also be listed in the RequiredFields array within the Constraints parameter.

    " } } }, @@ -36897,7 +39222,7 @@ }, "Constraints":{ "shape":"TaskTemplateConstraints", - "documentation":"

    Constraints that are applicable to the fields listed.

    " + "documentation":"

    Constraints that are applicable to the fields listed. Although this parameter is marked as optional in the API model, the service requires it when calling CreateTaskTemplate or UpdateTaskTemplate. The RequiredFields array must contain at least one element, and the field of type NAME must be included in RequiredFields.

    " }, "Defaults":{ "shape":"TaskTemplateDefaults", @@ -38852,6 +41177,40 @@ }, "documentation":"

    Information about Connect Customer Wisdom.

    " }, + "WorkloadType":{"type":"string"}, + "WorkloadTypeConcurrencies":{ + "type":"list", + "member":{"shape":"WorkloadTypeConcurrency"}, + "max":5, + "min":1 + }, + "WorkloadTypeConcurrency":{ + "type":"structure", + "required":[ + "WorkloadType", + "Concurrency" + ], + "members":{ + "WorkloadType":{ + "shape":"WorkloadType", + "documentation":"

    The value of the workload type.

    " + }, + "Concurrency":{ + "shape":"WorkloadTypeConcurrencyType", + "documentation":"

    The maximum number of contacts an agent can handle simultaneously for a specific channel and workload type combination.

    Valid Range for VOICE: Minimum value of 1. Maximum value of 1.

    Valid Range for CHAT: Minimum value of 1. Maximum value of 10.

    Valid Range for TASK: Minimum value of 1. Maximum value of 10.

    " + }, + "CrossChannelWorkloadBehavior":{ + "shape":"CrossChannelWorkloadBehavior", + "documentation":"

    Defines the cross-channel and workload type routing behavior for each channel and workload type combination that is enabled for this Routing Profile.

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

    Defines the maximum number of contacts an agent can handle simultaneously for a specific channel and workload type combination.

    " + }, + "WorkloadTypeConcurrencyType":{ + "type":"integer", + "max":10, + "min":1 + }, "Workspace":{ "type":"structure", "required":[ diff --git a/services/connectcampaigns/pom.xml b/services/connectcampaigns/pom.xml index 6f3ae666b959..a15dbc5ce805 100644 --- a/services/connectcampaigns/pom.xml +++ b/services/connectcampaigns/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connectcampaigns AWS Java SDK :: Services :: Connect Campaigns diff --git a/services/connectcampaigns/src/main/resources/codegen-resources/customization.config b/services/connectcampaigns/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/connectcampaigns/src/main/resources/codegen-resources/customization.config +++ b/services/connectcampaigns/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..edc67455fa4a --- /dev/null +++ b/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 524ec2a3273e..000000000000 --- a/services/connectcampaigns/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/connectcampaignsv2/pom.xml b/services/connectcampaignsv2/pom.xml index 080ccae78859..d44d310e06f6 100644 --- a/services/connectcampaignsv2/pom.xml +++ b/services/connectcampaignsv2/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connectcampaignsv2 AWS Java SDK :: Services :: Connect Campaigns V2 diff --git a/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..edc67455fa4a --- /dev/null +++ b/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-campaigns.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3fd73aba7f4e..000000000000 --- a/services/connectcampaignsv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://connect-campaigns.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/connectcampaignsv2/src/main/resources/codegen-resources/service-2.json b/services/connectcampaignsv2/src/main/resources/codegen-resources/service-2.json index 963913f8baa2..729d6709553b 100644 --- a/services/connectcampaignsv2/src/main/resources/codegen-resources/service-2.json +++ b/services/connectcampaignsv2/src/main/resources/codegen-resources/service-2.json @@ -705,6 +705,36 @@ } }, "shapes":{ + "AbandonmentRatePacingConfig":{ + "type":"structure", + "required":[ + "targetRate", + "connectionStartPoint", + "connectionThresholdSeconds", + "evaluationWindow" + ], + "members":{ + "targetRate":{"shape":"TargetRate"}, + "connectionStartPoint":{ + "shape":"ConnectionStartPoint", + "documentation":"

    Event from which connectionThresholdSeconds is measured.

    " + }, + "connectionThresholdSeconds":{ + "shape":"AbandonmentRatePacingConfigConnectionThresholdSecondsInteger", + "documentation":"

    Seconds after connectionStartPoint before a contact counts as abandoned.

    " + }, + "evaluationWindow":{ + "shape":"EvaluationWindow", + "documentation":"

    Rolling window over which abandonmentRate is computed.

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

    Configuration for abandonment-rate-based dialer throttling.

    " + }, + "AbandonmentRatePacingConfigConnectionThresholdSecondsInteger":{ + "type":"integer", + "box":true, + "min":1 + }, "AccessDeniedException":{ "type":"structure", "required":["message"], @@ -785,7 +815,7 @@ "type":"double", "documentation":"

    The bandwidth allocation of a queue resource.

    ", "box":true, - "max":1, + "max":2, "min":0 }, "Boolean":{ @@ -1057,6 +1087,15 @@ }, "exception":true }, + "ConnectionStartPoint":{ + "type":"string", + "documentation":"

    Reference point against which the connection threshold is measured.

    ", + "enum":[ + "CONNECTED_TO_SYSTEM", + "GREETING_START", + "GREETING_END" + ] + }, "ContactFlowId":{ "type":"string", "documentation":"

    The identifier of the contact flow for the outbound call.

    ", @@ -1418,6 +1457,13 @@ "box":true, "min":0 }, + "EvaluationWindow":{ + "type":"string", + "documentation":"

    Rolling window over which abandonmentRate is computed. Range PT1H to PT24H.

    ", + "max":5, + "min":0, + "pattern":"PT([1-9]|1[0-9]|2[0-4])H" + }, "EventTrigger":{ "type":"structure", "members":{ @@ -1994,6 +2040,21 @@ "max":25, "min":1 }, + "PacingStrategy":{ + "type":"structure", + "members":{ + "abandonmentRate":{"shape":"AbandonmentRatePacingConfig"} + }, + "documentation":"

    Pacing constraint the dialer may enforce.

    ", + "union":true + }, + "PacingStrategyList":{ + "type":"list", + "member":{"shape":"PacingStrategy"}, + "documentation":"

    List of pacing strategies the dialer enforces simultaneously.

    ", + "max":1, + "min":1 + }, "PauseCampaignRequest":{ "type":"structure", "required":["id"], @@ -2010,7 +2071,11 @@ "type":"structure", "required":["bandwidthAllocation"], "members":{ - "bandwidthAllocation":{"shape":"BandwidthAllocation"} + "bandwidthAllocation":{"shape":"BandwidthAllocation"}, + "pacingStrategies":{ + "shape":"PacingStrategyList", + "documentation":"

    Pacing strategies the dialer enforces simultaneously.

    " + } }, "documentation":"

    Predictive config

    " }, @@ -2503,6 +2568,13 @@ "max":256, "min":0 }, + "TargetRate":{ + "type":"double", + "documentation":"

    Target abandonment rate.

    ", + "box":true, + "max":1.0, + "min":0.0 + }, "TelephonyChannelSubtypeConfig":{ "type":"structure", "required":[ diff --git a/services/connectcases/pom.xml b/services/connectcases/pom.xml index 6053af80d455..1135c2d9b7b3 100644 --- a/services/connectcases/pom.xml +++ b/services/connectcases/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connectcases AWS Java SDK :: Services :: Connect Cases diff --git a/services/connectcases/src/main/resources/codegen-resources/customization.config b/services/connectcases/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/connectcases/src/main/resources/codegen-resources/customization.config +++ b/services/connectcases/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/connectcases/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connectcases/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c074226dfb59 --- /dev/null +++ b/services/connectcases/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cases-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cases-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cases.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cases.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connectcases/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connectcases/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8f44ec8d1bc6..000000000000 --- a/services/connectcases/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cases-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cases-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cases.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cases.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/connectcontactlens/pom.xml b/services/connectcontactlens/pom.xml index 3f049a4748ff..be9b736cc6d2 100644 --- a/services/connectcontactlens/pom.xml +++ b/services/connectcontactlens/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connectcontactlens AWS Java SDK :: Services :: Connect Contact Lens diff --git a/services/connectcontactlens/src/main/resources/codegen-resources/customization.config b/services/connectcontactlens/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/connectcontactlens/src/main/resources/codegen-resources/customization.config +++ b/services/connectcontactlens/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3958c24d6b6c --- /dev/null +++ b/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://contact-lens-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://contact-lens-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://contact-lens.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://contact-lens.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 564aae4b7600..000000000000 --- a/services/connectcontactlens/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://contact-lens-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://contact-lens-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://contact-lens.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://contact-lens.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/connectcontactlens/src/main/resources/codegen-resources/service-2.json b/services/connectcontactlens/src/main/resources/codegen-resources/service-2.json index f0306eca94fc..6225723c8454 100644 --- a/services/connectcontactlens/src/main/resources/codegen-resources/service-2.json +++ b/services/connectcontactlens/src/main/resources/codegen-resources/service-2.json @@ -30,7 +30,7 @@ {"shape":"InternalServiceException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Provides a list of analysis segments for a real-time analysis session.

    " + "documentation":"

    Provides a list of analysis segments for a real-time analysis session for voice.

    Voice data is retained for 24 hours. You must invoke this API during that time.

    " } }, "shapes":{ @@ -107,6 +107,90 @@ "min":1, "pattern":".*\\S.*" }, + "ExtractedInformation":{ + "type":"structure", + "required":[ + "ExtractionDefinitionId", + "ExtractionDefinitionName" + ], + "members":{ + "ExtractionDefinitionId":{ + "shape":"ExtractionDefinitionId", + "documentation":"

    The identifier of the extraction definition that produced this result.

    " + }, + "ExtractionDefinitionName":{ + "shape":"ExtractionDefinitionName", + "documentation":"

    The name of the extraction definition that produced this result.

    " + }, + "ExtractionDefinitionDisplayLabel":{ + "shape":"ExtractionDefinitionDisplayLabel", + "documentation":"

    The display label of the extraction definition that produced this result.

    " + }, + "ExtractedValues":{ + "shape":"ExtractedInformationValues", + "documentation":"

    The list of values extracted from the conversation for this extraction definition. This field is empty when a FailureCode is present.

    " + }, + "FailureCode":{ + "shape":"ExtractedInformationFailureCode", + "documentation":"

    If the information failed to be extracted, one of the following failure codes occurs:

    • QUOTA_EXCEEDED: The number of concurrent analytics jobs reached your service quota.

    • INSUFFICIENT_CONVERSATION_CONTENT: Information extraction requires a conversation with at least one turn from each participant.

    • FAILED_SAFETY_GUIDELINES: The extracted information cannot be provided because it failed to meet system safety guidelines.

    • INTERNAL_ERROR: Internal system error.

    • MAX_PACKAGE_FEATURE_ONLY: Information extraction is only available in Amazon Connect Customer instances.

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

    Segment containing information extracted from the conversation. Each segment represents the results for a single extraction definition.

    " + }, + "ExtractedInformationContent":{ + "type":"string", + "max":1024, + "min":1 + }, + "ExtractedInformationFailureCode":{ + "type":"string", + "enum":[ + "QUOTA_EXCEEDED", + "INSUFFICIENT_CONVERSATION_CONTENT", + "FAILED_SAFETY_GUIDELINES", + "INTERNAL_ERROR", + "MAX_PACKAGE_FEATURE_ONLY" + ] + }, + "ExtractedInformationValue":{ + "type":"structure", + "required":[ + "Content", + "PointsOfInterest" + ], + "members":{ + "Content":{ + "shape":"ExtractedInformationContent", + "documentation":"

    The text content of the extracted value.

    " + }, + "PointsOfInterest":{ + "shape":"PointsOfInterest", + "documentation":"

    The sections in the conversation that indicate where the extracted value was found.

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

    An individual value extracted from the conversation, including its content and the locations where it was found.

    " + }, + "ExtractedInformationValues":{ + "type":"list", + "member":{"shape":"ExtractedInformationValue"} + }, + "ExtractionDefinitionDisplayLabel":{ + "type":"string", + "max":25, + "min":0 + }, + "ExtractionDefinitionId":{ + "type":"string", + "max":256, + "min":1, + "pattern":".*\\S.*" + }, + "ExtractionDefinitionName":{ + "type":"string", + "max":200, + "min":1, + "pattern":".*\\S.*" + }, "InstanceId":{ "type":"string", "max":256, @@ -238,14 +322,14 @@ "members":{ "BeginOffsetMillis":{ "shape":"OffsetMillis", - "documentation":"

    The beginning offset in milliseconds where the category rule was detected.

    " + "documentation":"

    The beginning offset (in milliseconds) where the match was detected.

    " }, "EndOffsetMillis":{ "shape":"OffsetMillis", - "documentation":"

    The ending offset in milliseconds where the category rule was detected.

    " + "documentation":"

    The ending offset (in milliseconds) where the match was detected.

    " } }, - "documentation":"

    The section of the contact audio where that category rule was detected.

    " + "documentation":"

    The section of the contact audio where a match was detected.

    " }, "PointsOfInterest":{ "type":"list", @@ -308,6 +392,10 @@ "PostContactSummary":{ "shape":"PostContactSummary", "documentation":"

    Information about the post-contact summary.

    " + }, + "ExtractedInformation":{ + "shape":"ExtractedInformation", + "documentation":"

    The extracted information from the conversation.

    " } }, "documentation":"

    An analyzed segment for a real-time analysis session.

    " diff --git a/services/connecthealth/pom.xml b/services/connecthealth/pom.xml index c73f064df9fd..57e4d0081bd3 100644 --- a/services/connecthealth/pom.xml +++ b/services/connecthealth/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connecthealth AWS Java SDK :: Services :: Connect Health diff --git a/services/connecthealth/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connecthealth/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e3e26ca40683 --- /dev/null +++ b/services/connecthealth/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://health-agent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://health-agent.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/connecthealth/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connecthealth/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 428478916bfd..000000000000 --- a/services/connecthealth/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://health-agent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://health-agent.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/connecthealth/src/main/resources/codegen-resources/service-2.json b/services/connecthealth/src/main/resources/codegen-resources/service-2.json index de38c6971917..bad046c331f5 100644 --- a/services/connecthealth/src/main/resources/codegen-resources/service-2.json +++ b/services/connecthealth/src/main/resources/codegen-resources/service-2.json @@ -1314,7 +1314,10 @@ }, "MedicalScribeLanguageCode":{ "type":"string", - "enum":["en-US"] + "enum":[ + "en-US", + "multi" + ] }, "MedicalScribeListeningSessionDetails":{ "type":"structure", @@ -1671,11 +1674,6 @@ "min":0, "pattern":"s3://[a-z0-9][\\.\\-a-z0-9]{1,61}[a-z0-9](/.*)?" }, - "SensitiveAlphanumericString":{ - "type":"string", - "pattern":"[a-zA-Z0-9]+", - "sensitive":true - }, "SensitiveIsoDateString":{ "type":"string", "pattern":"\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])", @@ -1691,6 +1689,11 @@ "pattern":".*[\\s\\S]*\\S[\\s\\S]*.*", "sensitive":true }, + "SensitiveSectionHeaderString":{ + "type":"string", + "pattern":"[a-zA-Z0-9_]+", + "sensitive":true + }, "ServiceQuotaExceededException":{ "type":"structure", "members":{ @@ -2016,7 +2019,7 @@ ], "members":{ "sectionHeader":{ - "shape":"SensitiveAlphanumericString", + "shape":"SensitiveSectionHeaderString", "documentation":"

    The header for this section of the template

    " }, "sectionInstruction":{ diff --git a/services/connectparticipant/pom.xml b/services/connectparticipant/pom.xml index 19955c50c234..192fd16e1559 100644 --- a/services/connectparticipant/pom.xml +++ b/services/connectparticipant/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT connectparticipant AWS Java SDK :: Services :: ConnectParticipant diff --git a/services/connectparticipant/src/main/resources/codegen-resources/customization.config b/services/connectparticipant/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/connectparticipant/src/main/resources/codegen-resources/customization.config +++ b/services/connectparticipant/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/connectparticipant/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/connectparticipant/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5be98b336a76 --- /dev/null +++ b/services/connectparticipant/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://participant.connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://participant.connect.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://participant.connect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://participant.connect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://participant.connect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/connectparticipant/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/connectparticipant/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1f27c99c4fbb..000000000000 --- a/services/connectparticipant/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://participant.connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://participant.connect.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://participant.connect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://participant.connect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://participant.connect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/controlcatalog/pom.xml b/services/controlcatalog/pom.xml index 417a5937f366..c6627b96f03e 100644 --- a/services/controlcatalog/pom.xml +++ b/services/controlcatalog/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT controlcatalog AWS Java SDK :: Services :: Control Catalog diff --git a/services/controlcatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/controlcatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..393b7cf7fc71 --- /dev/null +++ b/services/controlcatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlcatalog-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlcatalog-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlcatalog.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlcatalog.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/controlcatalog/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/controlcatalog/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0e34d40ea21a..000000000000 --- a/services/controlcatalog/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlcatalog-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlcatalog-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlcatalog.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlcatalog.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/controltower/pom.xml b/services/controltower/pom.xml index 1fcd1a71b4ab..34cda046a744 100644 --- a/services/controltower/pom.xml +++ b/services/controltower/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT controltower AWS Java SDK :: Services :: Control Tower diff --git a/services/controltower/src/main/resources/codegen-resources/customization.config b/services/controltower/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/controltower/src/main/resources/codegen-resources/customization.config +++ b/services/controltower/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/controltower/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/controltower/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bd945958faf3 --- /dev/null +++ b/services/controltower/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controltower-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controltower-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controltower.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controltower.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/controltower/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/controltower/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fc13dc49af12..000000000000 --- a/services/controltower/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controltower-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controltower-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controltower.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://controltower.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/controltower/src/main/resources/codegen-resources/service-2.json b/services/controltower/src/main/resources/codegen-resources/service-2.json index 905077f3306a..a67f872e9406 100644 --- a/services/controltower/src/main/resources/codegen-resources/service-2.json +++ b/services/controltower/src/main/resources/codegen-resources/service-2.json @@ -1945,7 +1945,7 @@ "members":{ "targetIdentifier":{ "shape":"TargetIdentifier", - "documentation":"

    The ARN of the organizational unit. For information on how to find the targetIdentifier, see the overview page.

    " + "documentation":"

    The ARN of the target. The value depends on the target type:

    • Organizational unit (OU) – Specify the ARN of the OU.

    • Account – Specify the ARN of the account.

    For information on how to find the targetIdentifier, see the overview page.

    " }, "nextToken":{ "shape":"String", @@ -1961,7 +1961,7 @@ }, "includeChildren":{ "shape":"Boolean", - "documentation":"

    A boolean value that determines whether to include enabled controls from child organizational units in the response.

    " + "documentation":"

    Specifies whether to include enabled controls from child organizational units and child accounts in the response.

    " } } }, diff --git a/services/costandusagereport/pom.xml b/services/costandusagereport/pom.xml index dd7999032187..8e6d133cc01b 100644 --- a/services/costandusagereport/pom.xml +++ b/services/costandusagereport/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT costandusagereport AWS Java SDK :: Services :: AWS Cost and Usage Report diff --git a/services/costandusagereport/src/main/resources/codegen-resources/customization.config b/services/costandusagereport/src/main/resources/codegen-resources/customization.config index c45786626403..d40537c05f2d 100644 --- a/services/costandusagereport/src/main/resources/codegen-resources/customization.config +++ b/services/costandusagereport/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "deleteReportDefinition" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/costandusagereport/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/costandusagereport/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..320586214654 --- /dev/null +++ b/services/costandusagereport/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cur-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cur-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cur.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cur.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/costandusagereport/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/costandusagereport/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c3d74ec10086..000000000000 --- a/services/costandusagereport/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cur-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cur-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cur.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cur.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/costexplorer/pom.xml b/services/costexplorer/pom.xml index f0addbb0770f..50a6490dc72f 100644 --- a/services/costexplorer/pom.xml +++ b/services/costexplorer/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 costexplorer diff --git a/services/costexplorer/src/main/resources/codegen-resources/customization.config b/services/costexplorer/src/main/resources/codegen-resources/customization.config index 604d181bf4fe..761ec4700390 100644 --- a/services/costexplorer/src/main/resources/codegen-resources/customization.config +++ b/services/costexplorer/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "getCostAndUsage" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/costexplorer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/costexplorer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e6fda8b20a3c --- /dev/null +++ b/services/costexplorer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,433 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.cn-northwest-1.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.eu-isoe-west-1.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.us-isof-south-1.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.eusc-de-east-1.api.amazonwebservices.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ce.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 21, + "nodes": "/////wAAAAH/////AAAAAAAAABQAAAADAAAAAQAAAAQF9eESAAAAAgAAAAUF9eESAAAAAwAAABAAAAAGAAAABQAAAAwAAAAHAAAABgX14QYAAAAIAAAABwX14QcAAAAJAAAACAX14QgAAAAKAAAACwX14QkAAAALAAAADAX14QoF9eERAAAACQX14QQAAAANAAAACgX14QUAAAAOAAAADAX14QoAAAAPAAAADQX14Q8F9eEQAAAABAAAABIAAAARAAAABQX14QwF9eEOAAAABQAAABMF9eENAAAADQX14QsF9eEMAAAAAwX14QEAAAAVAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/costexplorer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/costexplorer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 00d507fc078a..000000000000 --- a/services/costexplorer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,772 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ce.us-east-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ce.cn-northwest-1.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://ce.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://ce.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://ce.eu-isoe-west-1.cloud.adc-e.uk", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eu-isoe-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://ce.us-isof-south-1.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ce.eusc-de-east-1.api.amazonwebservices.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://ce.eusc-de-east-1.api.amazonwebservices.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ce-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ce-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ce.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ce.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/costoptimizationhub/pom.xml b/services/costoptimizationhub/pom.xml index d21e05ccc968..6d713b81cdd4 100644 --- a/services/costoptimizationhub/pom.xml +++ b/services/costoptimizationhub/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT costoptimizationhub AWS Java SDK :: Services :: Cost Optimization Hub diff --git a/services/costoptimizationhub/src/main/resources/codegen-resources/customization.config b/services/costoptimizationhub/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/costoptimizationhub/src/main/resources/codegen-resources/customization.config +++ b/services/costoptimizationhub/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c4055f8da997 --- /dev/null +++ b/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cost-optimization-hub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cost-optimization-hub-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cost-optimization-hub.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cost-optimization-hub.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c23254ac4d62..000000000000 --- a/services/costoptimizationhub/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cost-optimization-hub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cost-optimization-hub-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cost-optimization-hub.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cost-optimization-hub.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/customerprofiles/pom.xml b/services/customerprofiles/pom.xml index ec309057ff2b..a30469759355 100644 --- a/services/customerprofiles/pom.xml +++ b/services/customerprofiles/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT customerprofiles AWS Java SDK :: Services :: Customer Profiles diff --git a/services/customerprofiles/src/main/resources/codegen-resources/customization.config b/services/customerprofiles/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/customerprofiles/src/main/resources/codegen-resources/customization.config +++ b/services/customerprofiles/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/customerprofiles/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/customerprofiles/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f5e38625b71b --- /dev/null +++ b/services/customerprofiles/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://profile-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://profile-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://profile.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://profile.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/customerprofiles/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/customerprofiles/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 637d62ce2439..000000000000 --- a/services/customerprofiles/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://profile-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://profile-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://profile.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://profile.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/customerprofiles/src/main/resources/codegen-resources/paginators-1.json b/services/customerprofiles/src/main/resources/codegen-resources/paginators-1.json index ae1c665254dd..9c7b6beb4a2c 100644 --- a/services/customerprofiles/src/main/resources/codegen-resources/paginators-1.json +++ b/services/customerprofiles/src/main/resources/codegen-resources/paginators-1.json @@ -72,6 +72,12 @@ "limit_key": "MaxResults", "result_key": "Items" }, + "ListSegmentSubscriptionEvents": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Events" + }, "ListUploadJobs": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/customerprofiles/src/main/resources/codegen-resources/service-2.json b/services/customerprofiles/src/main/resources/codegen-resources/service-2.json index 304802c9429c..0928c24f692d 100644 --- a/services/customerprofiles/src/main/resources/codegen-resources/service-2.json +++ b/services/customerprofiles/src/main/resources/codegen-resources/service-2.json @@ -32,6 +32,24 @@ ], "documentation":"

    Associates a new key value with a specific profile, such as a Contact Record ContactId.

    A profile object can have a single unique key and any number of additional keys that can be used to identify the profile that it belongs to.

    " }, + "AssociateStreamForSegments":{ + "name":"AssociateStreamForSegments", + "http":{ + "method":"POST", + "requestUri":"/domains/{DomainName}/segment-streams", + "responseCode":200 + }, + "input":{"shape":"AssociateStreamForSegmentsRequest"}, + "output":{"shape":"AssociateStreamForSegmentsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Associates an Amazon Kinesis data stream to receive segment membership events for a given domain. This is a domain-level configuration that applies to all segment subscriptions within the domain. A domain can have only one associated stream at a time.

    " + }, "BatchGetCalculatedAttributeForProfile":{ "name":"BatchGetCalculatedAttributeForProfile", "http":{ @@ -588,6 +606,25 @@ "documentation":"

    Deletes a segment definition from the domain.

    ", "idempotent":true }, + "DeleteSegmentSubscription":{ + "name":"DeleteSegmentSubscription", + "http":{ + "method":"DELETE", + "requestUri":"/domains/{DomainName}/segment-definitions/{SegmentDefinitionName}/subscriptions", + "responseCode":200 + }, + "input":{"shape":"DeleteSegmentSubscriptionRequest"}, + "output":{"shape":"DeleteSegmentSubscriptionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes a segment subscription for membership events. All active event notifications for this segment are stopped.

    ", + "idempotent":true + }, "DeleteWorkflow":{ "name":"DeleteWorkflow", "http":{ @@ -622,6 +659,25 @@ ], "documentation":"

    The process of detecting profile object type mapping by using given objects.

    " }, + "DisassociateStreamForSegments":{ + "name":"DisassociateStreamForSegments", + "http":{ + "method":"DELETE", + "requestUri":"/domains/{DomainName}/segment-streams", + "responseCode":200 + }, + "input":{"shape":"DisassociateStreamForSegmentsRequest"}, + "output":{"shape":"DisassociateStreamForSegmentsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Disassociates the Amazon Kinesis data stream configured for segment membership events. All active segment subscriptions delivering events to this stream are eventually stopped.

    ", + "idempotent":true + }, "GetAutoMergingPreview":{ "name":"GetAutoMergingPreview", "http":{ @@ -1023,6 +1079,25 @@ ], "documentation":"

    Retrieve the latest status of a segment snapshot.

    " }, + "GetSegmentSubscription":{ + "name":"GetSegmentSubscription", + "http":{ + "method":"GET", + "requestUri":"/domains/{DomainName}/segment-definitions/{SegmentDefinitionName}/subscriptions", + "responseCode":200 + }, + "input":{"shape":"GetSegmentSubscriptionRequest"}, + "output":{"shape":"GetSegmentSubscriptionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns the current subscription configuration, execution schedule, and status for segment membership events.

    ", + "readonly":true + }, "GetSimilarProfiles":{ "name":"GetSimilarProfiles", "http":{ @@ -1040,6 +1115,25 @@ ], "documentation":"

    Returns a set of profiles that belong to the same matching group using the matchId or profileId. You can also specify the type of matching that you want for finding similar profiles using either RULE_BASED_MATCHING or ML_BASED_MATCHING.

    " }, + "GetStreamForSegments":{ + "name":"GetStreamForSegments", + "http":{ + "method":"GET", + "requestUri":"/domains/{DomainName}/segment-streams", + "responseCode":200 + }, + "input":{"shape":"GetStreamForSegmentsRequest"}, + "output":{"shape":"GetStreamForSegmentsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns information about the segment membership event stream configured for a specific domain, including the stream state and associated segments.

    ", + "readonly":true + }, "GetUploadJob":{ "name":"GetUploadJob", "http":{ @@ -1512,6 +1606,25 @@ "documentation":"

    Lists all segment definitions under a domain.

    ", "readonly":true }, + "ListSegmentSubscriptionEvents":{ + "name":"ListSegmentSubscriptionEvents", + "http":{ + "method":"GET", + "requestUri":"/domains/{DomainName}/segment-definitions/{SegmentDefinitionName}/subscription-events", + "responseCode":200 + }, + "input":{"shape":"ListSegmentSubscriptionEventsRequest"}, + "output":{"shape":"ListSegmentSubscriptionEventsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns the most recent membership events for a segment. Each event represents a profile that entered or exited the segment.

    This operation is paginated.

    ", + "readonly":true + }, "ListTagsForResource":{ "name":"ListTagsForResource", "http":{ @@ -1647,6 +1760,25 @@ ], "documentation":"

    Defines a ProfileObjectType.

    To add or remove tags on an existing ObjectType, see TagResource/UntagResource.

    " }, + "PutSegmentSubscription":{ + "name":"PutSegmentSubscription", + "http":{ + "method":"PUT", + "requestUri":"/domains/{DomainName}/segment-definitions/{SegmentDefinitionName}/subscriptions", + "responseCode":200 + }, + "input":{"shape":"PutSegmentSubscriptionRequest"}, + "output":{"shape":"PutSegmentSubscriptionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"BadRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Creates or updates a segment subscription for membership events. When a subscription is created, an initial snapshot is taken and the system begins monitoring for membership changes.

    You can optionally set a schedule configuration interval to control how often membership snapshots are run. The interval can be from 1 to 24 hours. If not set, the interval defaults to 24 hours. Scheduled snapshots run on a best-effort basis. If a scheduled snapshot takes longer than the configured interval, the next scheduled run does not start until the in-progress snapshot completes, so a run might be delayed or skipped and is not guaranteed to occur at exactly the requested time.

    For Classic segments, membership events are generated from these scheduled snapshots and also in near real-time as profile attribute changes occur. For SQL segments, membership events are generated only from the scheduled snapshots.

    ", + "idempotent":true + }, "SearchProfiles":{ "name":"SearchProfiles", "http":{ @@ -1664,6 +1796,23 @@ ], "documentation":"

    Searches for profiles within a specific domain using one or more predefined search keys (e.g., _fullName, _phone, _email, _account, etc.) and/or custom-defined search keys. A search key is a data type pair that consists of a KeyName and Values list.

    This operation supports searching for profiles with a minimum of 1 key-value(s) pair and up to 5 key-value(s) pairs using either AND or OR logic.

    " }, + "SearchRecommendations":{ + "name":"SearchRecommendations", + "http":{ + "method":"POST", + "requestUri":"/domains/{DomainName}/recommendations" + }, + "input":{"shape":"SearchRecommendationsRequest"}, + "output":{"shape":"SearchRecommendationsResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves recommendations for a profile in a specific domain. The profile is identified using a search key, which consists of a KeyName and a KeyValues list. The KeyName can be a predefined key (for example, _profileId, _phone, _email) or a custom-defined key.

    The search key must match exactly one profile. If no profile matches the search key, the operation returns a ResourceNotFoundException. If more than one profile matches the search key, the operation returns a BadRequestException. You can use the SearchProfiles API to review the matching profiles.

    " + }, "StartRecommender":{ "name":"StartRecommender", "http":{ @@ -2163,6 +2312,59 @@ "type":"string", "pattern":"arn:([a-z\\d-]+):profile:.*:.*:.+" }, + "AssociateStreamForSegmentsRequest":{ + "type":"structure", + "required":[ + "DomainName", + "DestinationArn", + "DestinationRoleArn" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "DestinationArn":{ + "shape":"DestinationArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Kinesis data stream to deliver segment membership events to. For example, arn:aws:kinesis:region:account-id:stream/stream-name.

    " + }, + "DestinationRoleArn":{ + "shape":"DestinationRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that allows Customer Profiles service principal to assume the role for conducting AWS Key Management Service (KMS) and Amazon Kinesis operations. The role must grant the following Amazon Kinesis permissions to deliver segment membership events to the stream:

    • kinesis:PutRecord

    • kinesis:PutRecords

    • kinesis:DescribeStream

    " + } + } + }, + "AssociateStreamForSegmentsResponse":{ + "type":"structure", + "members":{} + }, + "AssociatedSegment":{ + "type":"structure", + "members":{ + "SegmentName":{ + "shape":"name", + "documentation":"

    The unique name of the segment definition.

    ", + "locationName":"SegmentName" + }, + "Status":{ + "shape":"EventSubscriptionSegmentStatus", + "documentation":"

    The subscription status of the segment. The following are valid values:

    • STARTING: The segment is being prepared to publish membership events.

    • RUNNING: The segment is actively publishing membership events to the stream.

    • STOPPED: The segment has stopped publishing membership events.

    • FAILED: The segment failed to publish membership events.

    ", + "locationName":"Status" + }, + "Message":{ + "shape":"string1To1000", + "documentation":"

    An optional message providing context, such as a failure reason.

    ", + "locationName":"Message" + } + }, + "documentation":"

    Represents a segment associated with a membership event stream.

    " + }, + "AssociatedSegmentsList":{ + "type":"list", + "member":{"shape":"AssociatedSegment"} + }, "AttributeDetails":{ "type":"structure", "required":[ @@ -2196,7 +2398,7 @@ }, "Values":{ "shape":"Values", - "documentation":"

    The values to apply the DimensionType on.

    ", + "documentation":"

    The values to apply the DimensionType on. To reference a calculated attribute or profile attribute as a dynamic value, use handlebar notation: {{_profile.ProfileAttributeName}} or {{_calculated_attribute.CalculatedAttributeName}}.

    ", "locationName":"Values" } }, @@ -2219,7 +2421,9 @@ "LESS_THAN", "GREATER_THAN_OR_EQUAL", "LESS_THAN_OR_EQUAL", - "EQUAL" + "EQUAL", + "LIST_CONTAINS", + "LIST_CONTAINS_ALL" ] }, "AttributeItem":{ @@ -2637,7 +2841,7 @@ }, "Values":{ "shape":"Values", - "documentation":"

    The values to apply the DimensionType with.

    ", + "documentation":"

    The values to apply the DimensionType with. To reference a calculated attribute or profile attribute as a dynamic value, use handlebar notation: {{_profile.ProfileAttributeName}} or {{_calculated_attribute.CalculatedAttributeName}}.

    ", "locationName":"Values" }, "ConditionOverrides":{ @@ -3981,7 +4185,7 @@ }, "Values":{ "shape":"DateValues", - "documentation":"

    The values to apply the DimensionType on.

    ", + "documentation":"

    The values to apply the DimensionType on. To reference a calculated attribute or profile attribute as a dynamic value, use handlebar notation: {{_profile.ProfileAttributeName}} or {{_calculated_attribute.CalculatedAttributeName}}.

    ", "locationName":"Values" } }, @@ -4443,6 +4647,37 @@ } } }, + "DeleteSegmentSubscriptionRequest":{ + "type":"structure", + "required":[ + "DomainName", + "SegmentDefinitionName" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "SegmentDefinitionName":{ + "shape":"name", + "documentation":"

    The unique name of the segment definition.

    ", + "location":"uri", + "locationName":"SegmentDefinitionName" + } + } + }, + "DeleteSegmentSubscriptionResponse":{ + "type":"structure", + "members":{ + "Message":{ + "shape":"string1To1000", + "documentation":"

    A confirmation message indicating the subscription was deleted successfully.

    ", + "locationName":"Message" + } + } + }, "DeleteWorkflowRequest":{ "type":"structure", "required":[ @@ -4468,11 +4703,22 @@ "type":"structure", "members":{} }, + "DestinationArnString":{ + "type":"string", + "max":2048, + "min":1 + }, "DestinationField":{ "type":"string", "max":256, "pattern":".*" }, + "DestinationRoleArn":{ + "type":"string", + "max":512, + "min":1, + "pattern":".*arn:aws:iam:.*:[0-9]+:.*" + }, "DestinationSummary":{ "type":"structure", "required":[ @@ -4566,6 +4812,28 @@ "type":"list", "member":{"shape":"Dimension"} }, + "DisassociateStreamForSegmentsRequest":{ + "type":"structure", + "required":["DomainName"], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + } + } + }, + "DisassociateStreamForSegmentsResponse":{ + "type":"structure", + "members":{ + "Message":{ + "shape":"string1To1000", + "documentation":"

    A confirmation message indicating the stream was disassociated successfully.

    ", + "locationName":"Message" + } + } + }, "DiversityCapType":{ "type":"string", "enum":[ @@ -4890,6 +5158,23 @@ "type":"list", "member":{"shape":"EventStreamSummary"} }, + "EventSubscriptionSegmentStatus":{ + "type":"string", + "enum":[ + "STARTING", + "RUNNING", + "STOPPED", + "FAILED" + ] + }, + "EventSubscriptionState":{ + "type":"string", + "enum":[ + "RUNNING", + "UNHEALTHY", + "STOPPED" + ] + }, "EventTriggerCondition":{ "type":"structure", "required":[ @@ -5046,7 +5331,7 @@ }, "Values":{ "shape":"ExtraLengthValues", - "documentation":"

    The values to apply the DimensionType on.

    ", + "documentation":"

    The values to apply the DimensionType on. To reference a calculated attribute or profile attribute as a dynamic value, use handlebar notation: {{_profile.ProfileAttributeName}} or {{_calculated_attribute.CalculatedAttributeName}}.

    ", "locationName":"Values" } }, @@ -6882,6 +7167,62 @@ } } }, + "GetSegmentSubscriptionRequest":{ + "type":"structure", + "required":[ + "DomainName", + "SegmentDefinitionName" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "SegmentDefinitionName":{ + "shape":"name", + "documentation":"

    The unique name of the segment definition.

    ", + "location":"uri", + "locationName":"SegmentDefinitionName" + } + } + }, + "GetSegmentSubscriptionResponse":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"SegmentSubscriptionStatus", + "documentation":"

    The current lifecycle status of the subscription. The following are valid values:

    • STARTING: Initial snapshot is in progress.

    • RUNNING: Notifications are active and running.

    • STOPPED: Notifications have been stopped.

    • FAILED: Notifications failed (for example, the Amazon Kinesis data stream became inaccessible).

    ", + "locationName":"Status" + }, + "Message":{ + "shape":"string1To1000", + "documentation":"

    A status message providing additional context, such as a failure reason.

    ", + "locationName":"Message" + }, + "ScheduleConfiguration":{ + "shape":"ScheduleConfiguration", + "documentation":"

    The schedule configuration for periodic membership event notifications.

    ", + "locationName":"ScheduleConfiguration" + }, + "ScheduledExecutions":{ + "shape":"ScheduledExecutions", + "documentation":"

    Information about scheduled execution timestamps.

    ", + "locationName":"ScheduledExecutions" + }, + "StartedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of when the subscription was first started.

    ", + "locationName":"StartedAt" + }, + "LastUpdatedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of the most recent configuration change.

    ", + "locationName":"LastUpdatedAt" + } + } + }, "GetSimilarProfilesRequest":{ "type":"structure", "required":[ @@ -6952,6 +7293,63 @@ } } }, + "GetStreamForSegmentsRequest":{ + "type":"structure", + "required":["DomainName"], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + } + } + }, + "GetStreamForSegmentsResponse":{ + "type":"structure", + "members":{ + "AssociatedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of when the stream was associated.

    ", + "locationName":"AssociatedAt" + }, + "AssociatedSegments":{ + "shape":"AssociatedSegmentsList", + "documentation":"

    A list of segments currently associated with the stream and their subscription status.

    ", + "locationName":"AssociatedSegments" + }, + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "locationName":"DomainName" + }, + "DestinationArn":{ + "shape":"DestinationArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Kinesis data stream receiving segment membership events.

    ", + "locationName":"DestinationArn" + }, + "DestinationRoleArn":{ + "shape":"DestinationRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role used for Amazon Kinesis and AWS Key Management Service (KMS) operations.

    ", + "locationName":"DestinationRoleArn" + }, + "State":{ + "shape":"EventSubscriptionState", + "documentation":"

    The operational state of the destination stream. The following are valid values:

    • RUNNING: The stream is associated and healthy. Segment membership events are being published.

    • UNHEALTHY: The stream is associated but events cannot currently be published. See FailureReason for details.

    • STOPPED: The stream is no longer publishing segment membership events.

    ", + "locationName":"State" + }, + "DisassociatedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of when the stream was disassociated.

    ", + "locationName":"DisassociatedAt" + }, + "FailureReason":{ + "shape":"string1To255", + "documentation":"

    The reason why the stream is in an unhealthy state, if applicable.

    ", + "locationName":"FailureReason" + } + } + }, "GetUploadJobPathRequest":{ "type":"structure", "required":[ @@ -7341,6 +7739,12 @@ "exception":true, "fault":true }, + "IntervalValue":{ + "type":"integer", + "box":true, + "max":24, + "min":1 + }, "JobSchedule":{ "type":"structure", "required":[ @@ -7401,6 +7805,13 @@ "value":{"shape":"ObjectTypeKeyList"}, "sensitive":true }, + "KeyValuesList":{ + "type":"list", + "member":{"shape":"string1To255"}, + "max":10, + "min":1, + "sensitive":true + }, "KmsArn":{ "type":"string", "max":2048, @@ -8620,6 +9031,54 @@ } } }, + "ListSegmentSubscriptionEventsRequest":{ + "type":"structure", + "required":[ + "DomainName", + "SegmentDefinitionName" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "SegmentDefinitionName":{ + "shape":"name", + "documentation":"

    The unique name of the segment definition.

    ", + "location":"uri", + "locationName":"SegmentDefinitionName" + }, + "MaxResults":{ + "shape":"maxSize100", + "documentation":"

    The maximum number of events to return per page.

    ", + "location":"querystring", + "locationName":"max-results" + }, + "NextToken":{ + "shape":"token", + "documentation":"

    The pagination token from the previous call to retrieve the next page of results.

    ", + "location":"querystring", + "locationName":"next-token" + } + } + }, + "ListSegmentSubscriptionEventsResponse":{ + "type":"structure", + "members":{ + "Events":{ + "shape":"SubscriptionEventsList", + "documentation":"

    A list of segment membership events.

    ", + "locationName":"Events" + }, + "NextToken":{ + "shape":"token", + "documentation":"

    The pagination token to use to retrieve the next page of results.

    ", + "locationName":"NextToken" + } + } + }, "ListTagsForResourceRequest":{ "type":"structure", "required":["resourceArn"], @@ -9485,7 +9944,7 @@ }, "Values":{ "shape":"Values", - "documentation":"

    The values to apply the DimensionType on.

    ", + "documentation":"

    The values to apply the DimensionType on. To reference a calculated attribute or profile attribute as a dynamic value, use handlebar notation: {{_profile.ProfileAttributeName}} or {{_calculated_attribute.CalculatedAttributeName}}.

    ", "locationName":"Values" } }, @@ -10010,6 +10469,51 @@ } } }, + "PutSegmentSubscriptionRequest":{ + "type":"structure", + "required":[ + "DomainName", + "SegmentDefinitionName" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "SegmentDefinitionName":{ + "shape":"name", + "documentation":"

    The unique name of the segment definition.

    ", + "location":"uri", + "locationName":"SegmentDefinitionName" + }, + "ScheduleConfiguration":{ + "shape":"ScheduleConfiguration", + "documentation":"

    The optional schedule configuration that controls how often membership snapshots are run. If not provided, the subscription defaults to a 24-hour interval.

    " + } + } + }, + "PutSegmentSubscriptionResponse":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"SegmentSubscriptionStatus", + "documentation":"

    The current lifecycle status of the subscription. The following are valid values:

    • STARTING: Initial snapshot is in progress.

    • RUNNING: Notifications are active and running.

    • STOPPED: Notifications have been stopped.

    • FAILED: Notifications failed (for example, the Amazon Kinesis data stream became inaccessible).

    ", + "locationName":"Status" + }, + "ScheduleConfiguration":{ + "shape":"ScheduleConfiguration", + "documentation":"

    The schedule configuration for the subscription, if configured.

    ", + "locationName":"ScheduleConfiguration" + }, + "StartedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of when the subscription was started.

    ", + "locationName":"StartedAt" + } + } + }, "QueryResult":{ "type":"string", "enum":[ @@ -10121,11 +10625,40 @@ }, "documentation":"

    Runtime diversity configuration for a GetProfileRecommendations request.

    " }, + "RecommendationMetadata":{ + "type":"structure", + "members":{ + "Columns":{ + "shape":"MetadataColumnsList", + "documentation":"

    A list of metadata column names from your Items dataset to include in the recommendation response.

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

    Configuration for metadata to include in recommendation responses.

    " + }, "Recommendations":{ "type":"list", "member":{"shape":"Recommendation"}, "sensitive":true }, + "Recommender":{ + "type":"structure", + "required":["Name"], + "members":{ + "Name":{ + "shape":"name", + "documentation":"

    The unique name of the recommender.

    " + }, + "Filters":{ + "shape":"RecommenderFilters", + "documentation":"

    A list of filters to apply to the returned recommendations. Filters define criteria for including or excluding items from the recommendation results.

    " + }, + "PromotionalFilters":{ + "shape":"RecommenderPromotionalFilters", + "documentation":"

    A list of promotional filters to apply to the recommendations. Promotional filters allow you to promote specific items within a configurable subset of recommendation results.

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

    The recommender used to generate the recommendations.

    " + }, "RecommenderConfig":{ "type":"structure", "members":{ @@ -10720,6 +11253,27 @@ }, "documentation":"

    The properties that are applied when Salesforce is being used as a source.

    " }, + "ScheduleConfiguration":{ + "type":"structure", + "required":["Interval"], + "members":{ + "Interval":{ + "shape":"IntervalValue", + "documentation":"

    The interval between scheduled executions.

    ", + "locationName":"Interval" + }, + "Unit":{ + "shape":"ScheduleConfigurationUnit", + "documentation":"

    The unit for the interval. The following are valid values:

    • HOURLY: The interval is measured in hours.

    ", + "locationName":"Unit" + } + }, + "documentation":"

    Configuration for scheduled segment membership event notifications.

    " + }, + "ScheduleConfigurationUnit":{ + "type":"string", + "enum":["HOURLY"] + }, "ScheduleExpression":{ "type":"string", "max":256, @@ -10730,6 +11284,22 @@ "max":36000, "min":0 }, + "ScheduledExecutions":{ + "type":"structure", + "members":{ + "NextExecutedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of the next scheduled execution.

    ", + "locationName":"NextExecutedAt" + }, + "LastExecutedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of the last successful scheduled execution.

    ", + "locationName":"LastExecutedAt" + } + }, + "documentation":"

    Information about scheduled execution timestamps.

    " + }, "ScheduledTriggerProperties":{ "type":"structure", "required":["ScheduleExpression"], @@ -10830,6 +11400,68 @@ } } }, + "SearchRecommendationsRequest":{ + "type":"structure", + "required":[ + "DomainName", + "KeyName", + "KeyValues", + "Recommender" + ], + "members":{ + "DomainName":{ + "shape":"name", + "documentation":"

    The unique name of the domain.

    ", + "location":"uri", + "locationName":"DomainName" + }, + "KeyName":{ + "shape":"name", + "documentation":"

    A searchable identifier of a customer profile. You can use a predefined key, such as _profileId, _phone, or _email, or a custom-defined key.

    " + }, + "KeyValues":{ + "shape":"KeyValuesList", + "documentation":"

    A list of key values. Provide one value for each field of the search key.

    " + }, + "Recommender":{ + "shape":"Recommender", + "documentation":"

    The recommender used to generate the recommendations.

    " + }, + "CandidateIds":{ + "shape":"CandidateIdList", + "documentation":"

    A list of item IDs to rank for the user. Use this when you want to re-rank a specific set of items rather than getting recommendations from the full item catalog. Required for personalized-ranking use cases.

    " + }, + "Context":{ + "shape":"RecommenderContext", + "documentation":"

    The contextual metadata used to provide dynamic runtime information to tailor recommendations.

    " + }, + "Diversity":{ + "shape":"RecommendationDiversityConfig", + "documentation":"

    Runtime diversity configuration for this request. Enables diversity-aware recommendations and optionally supplies values for placeholder-based diversity caps configured on the recommender.

    " + }, + "Metadata":{ + "shape":"RecommendationMetadata", + "documentation":"

    Configuration for metadata to include in recommendation responses.

    " + }, + "MaxRecommendations":{ + "shape":"maxSize500", + "documentation":"

    The maximum number of recommendations to return. The default value is 5.

    " + } + } + }, + "SearchRecommendationsResponse":{ + "type":"structure", + "members":{ + "ProfileId":{ + "shape":"uuid", + "documentation":"

    The unique identifier of the profile for which to retrieve recommendations.

    " + }, + "Recommendations":{ + "shape":"Recommendations", + "documentation":"

    List of recommendations generated by the recommender.

    " + } + } + }, "SegmentDefinitionArn":{ "type":"string", "max":255, @@ -10951,6 +11583,15 @@ "DESC" ] }, + "SegmentSubscriptionStatus":{ + "type":"string", + "enum":[ + "STARTING", + "RUNNING", + "STOPPED", + "FAILED" + ] + }, "SegmentType":{ "type":"string", "enum":[ @@ -11209,7 +11850,8 @@ "MINIMUM", "MAXIMUM", "AVERAGE", - "MAX_OCCURRENCE" + "MAX_OCCURRENCE", + "RECENT_OCCURRENCES" ], "sensitive":true }, @@ -11294,6 +11936,50 @@ "ENDS_WITH" ] }, + "SubscriptionEvent":{ + "type":"string", + "enum":[ + "JOINED", + "LEFT" + ] + }, + "SubscriptionEventItem":{ + "type":"structure", + "members":{ + "ProfileId":{ + "shape":"uuid", + "documentation":"

    The unique identifier of a customer profile.

    ", + "locationName":"ProfileId" + }, + "UpdatedAt":{ + "shape":"timestamp", + "documentation":"

    The timestamp of when the membership change was detected.

    ", + "locationName":"UpdatedAt" + }, + "EventType":{ + "shape":"SubscriptionEventType", + "documentation":"

    The type of event that triggered the membership change. The following are valid values:

    • LIVE: Real-time event triggered by a profile or calculated attribute change (Classic segments only).

    • SCHEDULE: Event generated during a scheduled execution.

    ", + "locationName":"EventType" + }, + "Event":{ + "shape":"SubscriptionEvent", + "documentation":"

    Whether the profile joined or left the segment. The following are valid values:

    • JOINED: The profile joined the segment.

    • LEFT: The profile left the segment.

    ", + "locationName":"Event" + } + }, + "documentation":"

    Represents a single segment membership event.

    " + }, + "SubscriptionEventType":{ + "type":"string", + "enum":[ + "LIVE", + "SCHEDULE" + ] + }, + "SubscriptionEventsList":{ + "type":"list", + "member":{"shape":"SubscriptionEventItem"} + }, "TagArn":{ "type":"string", "max":256, diff --git a/services/databasemigration/pom.xml b/services/databasemigration/pom.xml index 8e59f5d08b28..b2af45c99541 100644 --- a/services/databasemigration/pom.xml +++ b/services/databasemigration/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT databasemigration AWS Java SDK :: Services :: AWS Database Migration Service diff --git a/services/databasemigration/src/main/resources/codegen-resources/customization.config b/services/databasemigration/src/main/resources/codegen-resources/customization.config index a2efe702958d..e2a5e3eb68a2 100644 --- a/services/databasemigration/src/main/resources/codegen-resources/customization.config +++ b/services/databasemigration/src/main/resources/codegen-resources/customization.config @@ -15,6 +15,5 @@ ], "excludedSimpleMethods": [ "describeReplicationTaskAssessmentResults" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/databasemigration/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/databasemigration/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d1635cdb1c82 --- /dev/null +++ b/services/databasemigration/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,260 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms.{Region}.c2s.ic.gov", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms.{Region}.sc2s.sgov.gov", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dms.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 16, + "nodes": "/////wAAAAH/////AAAAAAAAAA8AAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAgAAAAGAAAABAAAAAcF9eENAAAABQX14QsF9eEMAAAABAAAAA0AAAAJAAAABgAAAAoF9eEKAAAABwX14QYAAAALAAAACAX14QcAAAAMAAAACQX14QgF9eEJAAAABQAAAA4F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAQAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/databasemigration/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/databasemigration/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1d54ec785e25..000000000000 --- a/services/databasemigration/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://dms.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ], - "endpoint": { - "url": "https://dms.{Region}.c2s.ic.gov", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ], - "endpoint": { - "url": "https://dms.{Region}.sc2s.sgov.gov", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dms-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dms.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dms.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/databasemigration/src/main/resources/codegen-resources/service-2.json b/services/databasemigration/src/main/resources/codegen-resources/service-2.json index e3114b7abfd7..5e1eb2c701b4 100644 --- a/services/databasemigration/src/main/resources/codegen-resources/service-2.json +++ b/services/databasemigration/src/main/resources/codegen-resources/service-2.json @@ -69,7 +69,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Cancels a single metadata model conversion operation that was started with StartMetadataModelConversion.

    " + "documentation":"

    Cancels a single metadata model conversion operation that was started with StartMetadataModelConversion.

    Required permissions: dms:CancelMetadataModelConversion. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "CancelMetadataModelCreation":{ "name":"CancelMetadataModelCreation", @@ -84,7 +84,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Cancels a single metadata model creation operation that was started with StartMetadataModelCreation.

    " + "documentation":"

    Cancels a single metadata model creation operation that was started with StartMetadataModelCreation.

    Required permissions: dms:CancelMetadataModelCreation. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "CancelReplicationTaskAssessmentRun":{ "name":"CancelReplicationTaskAssessmentRun", @@ -132,7 +132,7 @@ {"shape":"ResourceAlreadyExistsFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Creates a data provider using the provided settings. A data provider stores a data store type and location information about your database.

    " + "documentation":"

    Creates a data provider using the provided settings. A data provider stores a data store type and location information about your database.

    Required permissions: dms:CreateDataProvider. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "CreateEndpoint":{ "name":"CreateEndpoint", @@ -211,7 +211,7 @@ {"shape":"S3AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Creates the instance profile using the specified parameters.

    " + "documentation":"

    Creates the instance profile using the specified parameters.

    Required permissions: dms:CreateInstanceProfile. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "CreateMigrationProject":{ "name":"CreateMigrationProject", @@ -230,7 +230,7 @@ {"shape":"S3AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Creates the migration project using the specified parameters.

    You can run this action only after you create an instance profile and data providers using CreateInstanceProfile and CreateDataProvider.

    " + "documentation":"

    Creates the migration project using the specified parameters.

    You can run this action only after you create an instance profile and data providers using CreateInstanceProfile and CreateDataProvider.

    Required permissions: dms:CreateMigrationProject. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "CreateReplicationConfig":{ "name":"CreateReplicationConfig", @@ -368,7 +368,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Deletes the specified data provider.

    All migration projects associated with the data provider must be deleted or modified before you can delete the data provider.

    " + "documentation":"

    Deletes the specified data provider.

    Required permissions: dms:DeleteDataProvider. For more information, see Actions, resources, and condition keys for Database Migration Service.

    All migration projects associated with the data provider must be deleted or modified before you can delete the data provider.

    " }, "DeleteEndpoint":{ "name":"DeleteEndpoint", @@ -442,7 +442,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Deletes the specified instance profile.

    All migration projects associated with the instance profile must be deleted or modified before you can delete the instance profile.

    " + "documentation":"

    Deletes the specified instance profile.

    Required permissions: dms:DeleteInstanceProfile. For more information, see Actions, resources, and condition keys for Database Migration Service.

    All migration projects associated with the instance profile must be deleted or modified before you can delete the instance profile.

    " }, "DeleteMigrationProject":{ "name":"DeleteMigrationProject", @@ -459,7 +459,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Deletes the specified migration project.

    The migration project must be closed before you can delete it.

    " + "documentation":"

    Deletes the specified migration project.

    Required permissions: dms:DeleteMigrationProject. For more information, see Actions, resources, and condition keys for Database Migration Service.

    The migration project must be closed before you can delete it.

    " }, "DeleteReplicationConfig":{ "name":"DeleteReplicationConfig", @@ -596,7 +596,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns configuration parameters for a schema conversion project.

    " + "documentation":"

    Returns configuration parameters for a schema conversion project.

    Required permissions: dms:DescribeConversionConfiguration. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeDataMigrations":{ "name":"DescribeDataMigrations", @@ -626,7 +626,7 @@ {"shape":"AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Returns a paginated list of data providers for your account in the current region.

    " + "documentation":"

    Returns a paginated list of data providers for your account in the current region.

    Required permissions: dms:ListDataProviders. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeEndpointSettings":{ "name":"DescribeEndpointSettings", @@ -712,7 +712,7 @@ }, "input":{"shape":"DescribeExtensionPackAssociationsMessage"}, "output":{"shape":"DescribeExtensionPackAssociationsResponse"}, - "documentation":"

    Returns a paginated list of extension pack associations for the specified migration project. An extension pack is an add-on module that emulates functions present in a source database that are required when converting objects to the target database.

    " + "documentation":"

    Returns a paginated list of extension pack installation requests for a migration project, initiated by StartExtensionPackAssociation.

    Required permissions: dms:ListExtensionPacks. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeFleetAdvisorCollectors":{ "name":"DescribeFleetAdvisorCollectors", @@ -792,7 +792,7 @@ {"shape":"AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Returns a paginated list of instance profiles for your account in the current region.

    " + "documentation":"

    Returns a paginated list of instance profiles for your account in the current region.

    Required permissions: dms:ListInstanceProfiles. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModel":{ "name":"DescribeMetadataModel", @@ -806,7 +806,7 @@ {"shape":"ResourceNotFoundFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Gets detailed information about the specified metadata model, including its definition and corresponding converted objects in the target database if applicable.

    " + "documentation":"

    Gets detailed information about the specified metadata model, including its definition and corresponding converted objects in the target database if applicable.

    Required permissions: dms:DescribeMetadataModel. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelAssessments":{ "name":"DescribeMetadataModelAssessments", @@ -819,7 +819,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns a paginated list of metadata model assessments for your account in the current region.

    " + "documentation":"

    Returns a paginated list of metadata model assessment requests for a migration project, initiated by StartMetadataModelAssessment.

    Required permissions: dms:ListMetadataModelAssessments. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelChildren":{ "name":"DescribeMetadataModelChildren", @@ -833,7 +833,7 @@ {"shape":"ResourceNotFoundFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Gets a list of child metadata models for the specified metadata model in the database hierarchy.

    " + "documentation":"

    Gets a list of child metadata models for the specified metadata model in the database hierarchy.

    Required permissions: dms:DescribeMetadataModelChildren. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelConversions":{ "name":"DescribeMetadataModelConversions", @@ -846,7 +846,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns a paginated list of metadata model conversions for a migration project.

    " + "documentation":"

    Returns a paginated list of metadata model conversion requests for a migration project, initiated by StartMetadataModelConversion.

    To cancel a queued or in-progress request, call CancelMetadataModelConversion.

    Required permissions: dms:ListMetadataModelConversions. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelCreations":{ "name":"DescribeMetadataModelCreations", @@ -860,7 +860,7 @@ {"shape":"ResourceNotFoundFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Returns a paginated list of metadata model creation requests for a migration project.

    " + "documentation":"

    Returns a paginated list of metadata model creation requests for a migration project, initiated by StartMetadataModelCreation.

    To cancel a queued or in-progress request, call CancelMetadataModelCreation.

    Required permissions: dms:DescribeMetadataModelCreations. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelExportsAsScript":{ "name":"DescribeMetadataModelExportsAsScript", @@ -873,7 +873,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns a paginated list of metadata model exports.

    " + "documentation":"

    Returns a paginated list of metadata model export requests for a migration project, initiated by StartMetadataModelExportAsScript.

    Required permissions: dms:ListMetadataModelExports. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelExportsToTarget":{ "name":"DescribeMetadataModelExportsToTarget", @@ -886,7 +886,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns a paginated list of metadata model exports.

    " + "documentation":"

    Returns a paginated list of metadata model export requests for a migration project, initiated by StartMetadataModelExportToTarget.

    Required permissions: dms:ListMetadataModelExports. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMetadataModelImports":{ "name":"DescribeMetadataModelImports", @@ -899,7 +899,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Returns a paginated list of metadata model imports.

    " + "documentation":"

    Returns a paginated list of metadata model import requests for a migration project, initiated by StartMetadataModelImport.

    Required permissions: dms:DescribeMetadataModelImports. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeMigrationProjects":{ "name":"DescribeMigrationProjects", @@ -914,7 +914,7 @@ {"shape":"AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Returns a paginated list of migration projects for your account in the current region.

    " + "documentation":"

    Returns a paginated list of migration projects for your account in the current region.

    Required permissions: dms:ListMigrationProjects. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "DescribeOrderableReplicationInstances":{ "name":"DescribeOrderableReplicationInstances", @@ -1153,7 +1153,7 @@ "errors":[ {"shape":"ResourceNotFoundFault"} ], - "documentation":"

    Saves a copy of a database migration assessment report to your Amazon S3 bucket. DMS can save your assessment report as a comma-separated value (CSV) or a PDF file.

    " + "documentation":"

    Saves a copy of a database migration assessment report to your Amazon S3 bucket. DMS can save your assessment report as a comma-separated value (CSV) or a PDF file.

    Required permissions: dms:ExportMetadataModelAssessment. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "GetTargetSelectionRules":{ "name":"GetTargetSelectionRules", @@ -1168,7 +1168,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Converts source selection rules into their target counterparts for schema conversion operations.

    " + "documentation":"

    Converts source selection rules into their target counterparts for schema conversion operations.

    Required permissions: dms:GetTargetSelectionRules. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "ImportCertificate":{ "name":"ImportCertificate", @@ -1212,7 +1212,7 @@ {"shape":"ResourceNotFoundFault"}, {"shape":"InvalidResourceStateFault"} ], - "documentation":"

    Modifies the specified schema conversion configuration using the provided parameters.

    " + "documentation":"

    Modifies the specified schema conversion configuration using the provided parameters.

    Required permissions: dms:UpdateConversionConfiguration. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "ModifyDataMigration":{ "name":"ModifyDataMigration", @@ -1243,7 +1243,7 @@ {"shape":"InvalidResourceStateFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Modifies the specified data provider using the provided settings.

    You must remove the data provider from all migration projects before you can modify it.

    " + "documentation":"

    Modifies the specified data provider using the provided settings.

    Required permissions: dms:UpdateDataProvider. For more information, see Actions, resources, and condition keys for Database Migration Service.

    You must remove the data provider from all migration projects before you can modify it.

    " }, "ModifyEndpoint":{ "name":"ModifyEndpoint", @@ -1301,7 +1301,7 @@ {"shape":"S3AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Modifies the specified instance profile using the provided parameters.

    All migration projects associated with the instance profile must be deleted or modified before you can modify the instance profile.

    " + "documentation":"

    Modifies the specified instance profile using the provided parameters.

    Required permissions: dms:UpdateInstanceProfile. For more information, see Actions, resources, and condition keys for Database Migration Service.

    All migration projects associated with the instance profile must be deleted or modified before you can modify the instance profile.

    " }, "ModifyMigrationProject":{ "name":"ModifyMigrationProject", @@ -1319,7 +1319,7 @@ {"shape":"S3AccessDeniedFault"}, {"shape":"FailedDependencyFault"} ], - "documentation":"

    Modifies the specified migration project using the provided parameters.

    The migration project must be closed before you can modify it.

    " + "documentation":"

    Modifies the specified migration project using the provided parameters.

    Required permissions: dms:UpdateMigrationProject. For more information, see Actions, resources, and condition keys for Database Migration Service.

    The migration project must be closed before you can modify it.

    " }, "ModifyReplicationConfig":{ "name":"ModifyReplicationConfig", @@ -1529,7 +1529,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Applies the extension pack to your target database. An extension pack is an add-on module that emulates functions present in a source database that are required when converting objects to the target database.

    " + "documentation":"

    Queues the installation of the extension pack on your target database. If other requests created by Start* operations are already in the migration project's queue, the installation begins after they complete.

    This operation requires a non-virtual target data provider.

    If the extension pack already exists, the operation reinstalls it. To ensure compatibility, reconvert your database objects if the version has changed since your last conversion. For more information, see Using extension packs in DMS Schema Conversion.

    To check the status of the request, call DescribeExtensionPackAssociations using the returned RequestIdentifier as a filter.

    Required permissions: dms:AssociateExtensionPack. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelAssessment":{ "name":"StartMetadataModelAssessment", @@ -1549,7 +1549,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Creates a database migration assessment report by assessing the migration complexity for your source database. A database migration assessment report summarizes all of the schema conversion tasks. It also details the action items for database objects that can't be converted to the database engine of your target database instance.

    " + "documentation":"

    Queues an assessment of the selected source metadata models (database objects such as tables, views, and procedures) to evaluate conversion complexity to the target database format. If other requests created by Start* operations are already in the migration project's queue, the assessment begins after they complete.

    The assessment request loads metadata models that are not yet in the metadata tree, but does not reload metadata models that are already present. If your source database has changed since the metadata was loaded, refresh the affected metadata models with StartMetadataModelImport before calling this operation.

    To check the status of the assessment request, call DescribeMetadataModelAssessments using the returned RequestIdentifier as a filter.

    To export the conversion assessment report after the request completes successfully, call ExportMetadataModelAssessment.

    Required permissions: dms:StartMetadataModelAssessment. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelConversion":{ "name":"StartMetadataModelConversion", @@ -1569,7 +1569,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Converts your source database objects to a format compatible with the target database.

    " + "documentation":"

    Queues a conversion of the selected source metadata models (database objects such as tables, views, and procedures) to the target database format. If other requests created by Start* operations are already in the migration project's queue, the conversion begins after they complete.

    The conversion request loads metadata models that are not yet in the metadata tree, but does not reload metadata models that are already present. If your source database has changed since the metadata was loaded, refresh the affected metadata models with StartMetadataModelImport before calling this operation.

    If converted objects already exist in the target metadata tree, the conversion overwrites them, including any manual edits.

    To check the status of the conversion request, call DescribeMetadataModelConversions using the returned RequestIdentifier as a filter.

    To cancel a queued or in-progress request, call CancelMetadataModelConversion with the returned RequestIdentifier.

    After the conversion completes successfully:

    Required permissions: dms:StartMetadataModelConversion. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelCreation":{ "name":"StartMetadataModelCreation", @@ -1585,7 +1585,7 @@ {"shape":"ResourceQuotaExceededFault"}, {"shape":"AccessDeniedFault"} ], - "documentation":"

    Creates source metadata model of the given type with the specified properties for schema conversion operations.

    This action supports only these directions: from SQL Server to Aurora PostgreSQL, or from SQL Server to RDS for PostgreSQL.

    " + "documentation":"

    Queues the creation of a metadata model in the source metadata tree. If other requests created by Start* operations are already in the migration project's queue, the creation begins after they complete.

    This operation supports only Microsoft SQL Server to Aurora PostgreSQL and Microsoft SQL Server to Amazon RDS for PostgreSQL conversion paths.

    To check the status of the creation request, call DescribeMetadataModelCreations using the returned RequestIdentifier as a filter.

    To cancel a queued or in-progress request, call CancelMetadataModelCreation with the returned RequestIdentifier.

    Calling StartMetadataModelImport with Refresh deletes metadata models created by this operation.

    After the creation completes successfully:

    Required permissions: dms:StartMetadataModelCreation. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelExportAsScript":{ "name":"StartMetadataModelExportAsScript", @@ -1605,7 +1605,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Saves your converted code to a file as a SQL script, and stores this file on your Amazon S3 bucket.

    " + "documentation":"

    Queues an export of metadata models (database objects such as tables, views, and procedures) as a data definition language (DDL) script. The script is stored as a ZIP archive in the Amazon S3 bucket associated with the migration project. If other requests created by Start* operations are already in the migration project's queue, the export begins after they complete.

    When exporting from the target metadata tree, the export applies only to metadata models created by conversion. Metadata models imported from the database are skipped.

    To check the status of the export request, call DescribeMetadataModelExportsAsScript using the returned RequestIdentifier as a filter.

    Required permissions: dms:StartMetadataModelExportAsScripts. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelExportToTarget":{ "name":"StartMetadataModelExportToTarget", @@ -1625,7 +1625,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Applies converted database objects to your target database.

    " + "documentation":"

    Queues an export of the selected converted metadata models (database objects such as tables, views, and procedures) to your target database. If other requests created by Start* operations are already in the migration project's queue, the export begins after they complete.

    This operation requires a non-virtual target data provider.

    The export applies only metadata models created by conversion. Metadata models imported from the database are skipped.

    If objects with the same name already exist on the target database, the export overwrites them.

    The operation installs the extension pack on the target database. For more information, see Using extension packs in DMS Schema Conversion.

    To check the status of the export request, call DescribeMetadataModelExportsToTarget using the returned RequestIdentifier as a filter.

    Required permissions: dms:StartMetadataModelExportToTarget. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartMetadataModelImport":{ "name":"StartMetadataModelImport", @@ -1645,7 +1645,7 @@ {"shape":"S3ResourceNotFoundFault"}, {"shape":"S3AccessDeniedFault"} ], - "documentation":"

    Loads the metadata for all the dependent database objects of the parent object.

    This operation uses your project's Amazon S3 bucket as a metadata cache to improve performance.

    " + "documentation":"

    Queues an import of metadata models (database objects such as tables, views, and procedures) from your data provider into the metadata tree. If other requests created by Start* operations are already in the migration project's queue, the import begins after they complete.

    To check the status of the import request, call DescribeMetadataModelImports using the returned RequestIdentifier as a filter.

    Required permissions: dms:StartMetadataModelImport. For more information, see Actions, resources, and condition keys for Database Migration Service.

    " }, "StartRecommendations":{ "name":"StartRecommendations", @@ -2006,7 +2006,10 @@ "CancelMetadataModelConversionResponse":{ "type":"structure", "members":{ - "Request":{"shape":"SchemaConversionRequest"} + "Request":{ + "shape":"SchemaConversionRequest", + "documentation":"

    The metadata model conversion request.

    DMS never populates the ExportSqlDetails field for this operation.

    " + } } }, "CancelMetadataModelCreationMessage":{ @@ -2029,7 +2032,10 @@ "CancelMetadataModelCreationResponse":{ "type":"structure", "members":{ - "Request":{"shape":"SchemaConversionRequest"} + "Request":{ + "shape":"SchemaConversionRequest", + "documentation":"

    The metadata model creation request.

    DMS never populates the ExportSqlDetails field for this operation.

    " + } } }, "CancelReplicationTaskAssessmentRunMessage":{ @@ -2399,7 +2405,7 @@ }, "Engine":{ "shape":"String", - "documentation":"

    The type of database engine for the data provider. Valid values include \"aurora\", \"aurora-postgresql\", \"mysql\", \"oracle\", \"postgres\", \"sqlserver\", redshift, mariadb, mongodb, db2, db2-zos, docdb, and sybase. A value of \"aurora\" represents Amazon Aurora MySQL-Compatible Edition.

    " + "documentation":"

    The type of database engine for the data provider.

    Valid values: aurora, aurora-postgresql, db2, db2-zos, docdb, mariadb, mongodb, mysql, oracle, postgres, redshift, sqlserver, and sybase. A value of aurora represents Amazon Aurora MySQL-Compatible Edition.

    " }, "Virtual":{ "shape":"BooleanOptional", @@ -2754,7 +2760,7 @@ }, "TransformationRules":{ "shape":"String", - "documentation":"

    The settings in JSON format for migration rules. Migration rules make it possible for you to change the object names according to the rules that you specify. For example, you can change an object name to lowercase or uppercase, add or remove a prefix or suffix, or rename objects.

    " + "documentation":"

    A JSON string that specifies the transformation rules for the migration project. Transformation rules let you customize how DMS Schema Conversion converts your source database objects, including renaming, adding prefixes or suffixes, and changing data types. For the transformation rule format and examples, see Transformation rules in DMS Schema Conversion.

    Homogeneous data migrations do not support transformation rules.

    " }, "Description":{ "shape":"String", @@ -3214,7 +3220,7 @@ }, "Engine":{ "shape":"String", - "documentation":"

    The type of database engine for the data provider. Valid values include \"aurora\", \"aurora-postgresql\", \"mysql\", \"oracle\", \"postgres\", \"sqlserver\", redshift, mariadb, mongodb, db2, db2-zos, docdb, and sybase. A value of \"aurora\" represents Amazon Aurora MySQL-Compatible Edition.

    " + "documentation":"

    The type of database engine for the data provider.

    Valid values: aurora, aurora-postgresql, db2, db2-zos, docdb, mariadb, mongodb, mysql, oracle, postgres, redshift, sqlserver, and sybase. A value of aurora represents Amazon Aurora MySQL-Compatible Edition.

    " }, "Virtual":{ "shape":"BooleanOptional", @@ -3886,7 +3892,7 @@ }, "ConversionConfiguration":{ "shape":"String", - "documentation":"

    The configuration parameters for the schema conversion project.

    " + "documentation":"

    A JSON string that contains the schema conversion settings for the migration project. For the format and available settings, see Specifying schema conversion settings for migration projects.

    " } } }, @@ -3933,7 +3939,7 @@ "members":{ "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the data providers described in the form of key-value pairs.

    Valid filter names and values: data-provider-identifier, data provider arn or name

    " + "documentation":"

    The filters to apply to the data providers.

    The following filter names are supported:

    • data-provider-identifier – The data provider name or ARN.

    " }, "MaxRecords":{ "shape":"IntegerOptional", @@ -4201,11 +4207,11 @@ "members":{ "MigrationProjectIdentifier":{ "shape":"MigrationProjectIdentifier", - "documentation":"

    The name or Amazon Resource Name (ARN) for the migration project.

    " + "documentation":"

    The migration project name or Amazon Resource Name (ARN).

    " }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the extension pack associations described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the extension pack installation requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED.

    " }, "Marker":{ "shape":"String", @@ -4226,7 +4232,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of extension pack associations for the specified migration project.

    " + "documentation":"

    A paginated list of extension pack installation requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4381,7 +4387,7 @@ "members":{ "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the instance profiles described in the form of key-value pairs.

    Valid filter names and values: instance-profile-identifier, instance profile arn or name

    " + "documentation":"

    The filters to apply to the instance profiles.

    The following filter names are supported:

    • instance-profile-identifier – The instance profile name or ARN.

    " }, "MaxRecords":{ "shape":"IntegerOptional", @@ -4412,11 +4418,11 @@ "members":{ "MigrationProjectIdentifier":{ "shape":"MigrationProjectIdentifier", - "documentation":"

    The name or Amazon Resource Name (ARN) of the migration project.

    " + "documentation":"

    The migration project name or Amazon Resource Name (ARN).

    " }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model assessments described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the metadata model assessment requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED.

    " }, "Marker":{ "shape":"String", @@ -4437,7 +4443,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of metadata model assessments for the specified migration project.

    " + "documentation":"

    A paginated list of metadata model assessment requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4451,7 +4457,7 @@ "members":{ "SelectionRules":{ "shape":"String", - "documentation":"

    The JSON string that specifies which metadata model's children to retrieve. Only one selection rule with \"rule-action\": \"explicit\" can be provided. For more information, see Selection Rules in the DMS User Guide.

    " + "documentation":"

    A JSON string that identifies the metadata model whose children to retrieve. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts source or target selection rules depending on the Origin parameter. The server-name in the object locator must match the corresponding data provider.

    • Supports only explicit rule actions.

    • Exactly one rule is allowed.

    " }, "MigrationProjectIdentifier":{ "shape":"MigrationProjectIdentifier", @@ -4494,7 +4500,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model conversions described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the metadata model conversion requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED, CANCELING, CANCELED.

    " }, "Marker":{ "shape":"String", @@ -4515,7 +4521,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of metadata model conversions.

    " + "documentation":"

    A paginated list of metadata model conversion requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4525,15 +4531,15 @@ "members":{ "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model creation requests described in the form of key-value pairs. The supported filters are request-id and status.

    " + "documentation":"

    The filters to apply to the metadata model creation requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED, CANCELING, CANCELED.

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

    Specifies the unique pagination token that makes it possible to display the next page of metadata model creation requests. If Marker is returned by a previous response, there are more metadata model creation requests available.

    " + "documentation":"

    Specifies the unique pagination token that makes it possible to display the next page of results. If this parameter is specified, the response includes only records beyond the marker, up to the value specified by MaxRecords.

    If Marker is returned by a previous response, there are more results available. The value of Marker is a unique pagination token for each page. To retrieve the next page, make the call again using the returned token and keeping all other arguments unchanged.

    " }, "MaxRecords":{ "shape":"IntegerOptional", - "documentation":"

    The maximum number of metadata model creation requests to include in the response. If more requests exist than the specified MaxRecords value, a pagination token is provided in the response so that you can retrieve the remaining results.

    " + "documentation":"

    The maximum number of records to include in the response. If more records exist than the specified MaxRecords value, DMS includes a pagination token in the response so that you can retrieve the remaining results.

    " }, "MigrationProjectIdentifier":{ "shape":"MigrationProjectIdentifier", @@ -4546,11 +4552,11 @@ "members":{ "Marker":{ "shape":"String", - "documentation":"

    Specifies the unique pagination token that makes it possible to display the next page of metadata model creation requests. If Marker is returned, there are more metadata model creation requests available.

    " + "documentation":"

    Specifies the unique pagination token that makes it possible to display the next page of results. If this parameter is specified, the response includes only records beyond the marker, up to the value specified by MaxRecords.

    If Marker is returned by a previous response, there are more results available. The value of Marker is a unique pagination token for each page. To retrieve the next page, make the call again using the returned token and keeping all other arguments unchanged.

    " }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A list of metadata model creation requests. The ExportSqlDetails field will never be populated for the DescribeMetadataModelCreations operation.

    " + "documentation":"

    A paginated list of metadata model creation requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4564,7 +4570,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model exports described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the metadata model export requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED.

    " }, "Marker":{ "shape":"String", @@ -4585,7 +4591,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of metadata model exports.

    " + "documentation":"

    A paginated list of metadata model export requests.

    " } } }, @@ -4599,7 +4605,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model exports described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the metadata model export requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED.

    " }, "Marker":{ "shape":"String", @@ -4620,7 +4626,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of metadata model exports.

    " + "documentation":"

    A paginated list of metadata model export requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4634,7 +4640,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the metadata model imports described in the form of key-value pairs.

    " + "documentation":"

    The filters to apply to the metadata model import requests.

    The following filter names are supported:

    • request-id – The request identifier.

    • status – The request status. Valid values: RECEIVED, IN_PROGRESS, SUCCESS, FAILED.

    " }, "Marker":{ "shape":"String", @@ -4642,7 +4648,7 @@ }, "MaxRecords":{ "shape":"IntegerOptional", - "documentation":"

    A paginated list of metadata model imports.

    " + "documentation":"

    The maximum number of records to include in the response. If more records exist than the specified MaxRecords value, DMS includes a pagination token in the response so that you can retrieve the remaining results.

    " } } }, @@ -4655,7 +4661,7 @@ }, "Requests":{ "shape":"SchemaConversionRequestList", - "documentation":"

    A paginated list of metadata model imports.

    " + "documentation":"

    A paginated list of metadata model import requests.

    DMS never populates the ExportSqlDetails field for this operation.

    " } } }, @@ -4669,7 +4675,7 @@ "members":{ "SelectionRules":{ "shape":"String", - "documentation":"

    The JSON string that specifies which metadata model to retrieve. Only one selection rule with \"rule-action\": \"explicit\" can be provided. For more information, see Selection Rules in the DMS User Guide.

    " + "documentation":"

    A JSON string that identifies the metadata model to retrieve. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts source or target selection rules depending on the Origin parameter. The server-name in the object locator must match the corresponding data provider.

    • Supports only explicit rule actions.

    • Exactly one rule is allowed.

    " }, "MigrationProjectIdentifier":{ "shape":"MigrationProjectIdentifier", @@ -4707,7 +4713,7 @@ "members":{ "Filters":{ "shape":"FilterList", - "documentation":"

    Filters applied to the migration projects described in the form of key-value pairs.

    Valid filter names and values:

    • instance-profile-identifier, instance profile arn or name

    • data-provider-identifier, data provider arn or name

    • migration-project-identifier, migration project arn or name

    " + "documentation":"

    The filters to apply to the migration projects.

    The following filter names are supported:

    • migration-project-identifier – The migration project name or ARN.

    • instance-profile-identifier – The instance profile name or ARN.

    • data-provider-identifier – The source or target data provider name or ARN.

    • source-data-provider-identifier – The source data provider name or ARN.

    • target-data-provider-identifier – The target data provider name or ARN.

    " }, "MaxRecords":{ "shape":"IntegerOptional", @@ -5369,7 +5375,7 @@ }, "ExtractDocId":{ "shape":"BooleanOptional", - "documentation":"

    Specifies the document ID. Use this setting when NestingLevel is set to \"none\".

    Default value is \"false\".

    " + "documentation":"

    Specifies whether the document ID is added to the target table. Use this setting when NestingLevel is set to \"none\".

    Set ExtractDocId to true when using multi-document transactions with CDC.

    Default value is false.

    " }, "DocsToInvestigate":{ "shape":"IntegerOptional", @@ -5842,7 +5848,7 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to assess.

    " + "documentation":"

    A JSON string that identifies the metadata models to export a conversion assessment report for. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only source selection rules, where server-name in the object locator matches the source data provider.

    • Supports only explicit rule actions.

    " }, "FileName":{ "shape":"String", @@ -5886,14 +5892,14 @@ "members":{ "S3ObjectKey":{ "shape":"String", - "documentation":"

    The Amazon S3 object key for the object containing the exported metadata model assessment.

    " + "documentation":"

    The Amazon S3 URI of the object that contains the ZIP archive with exported DDL scripts.

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

    The URL for the object containing the exported metadata model assessment.

    " + "documentation":"

    The URL of the Amazon S3 object that contains the ZIP archive with exported DDL scripts.

    " } }, - "documentation":"

    Provides information about a metadata model assessment exported to SQL.

    " + "documentation":"

    The Amazon S3 location of the ZIP archive that contains the exported data definition language (DDL) scripts.

    " }, "FailedDependencyFault":{ "type":"structure", @@ -6056,7 +6062,7 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    The JSON string representing the source selection rules for conversion. Selection rules must contain only supported metadata model types. For more information, see Selection Rules in the DMS User Guide.

    " + "documentation":"

    A JSON string that contains the source selection rules to convert into their target counterparts. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only source selection rules, where server-name in the object locator matches the source data provider.

    • Supports only explicit rule actions.

    • Does not support category-name in the object locator.

    • Up to 10 rules are allowed.

    " } } }, @@ -6742,10 +6748,10 @@ "members":{ "StatementProperties":{ "shape":"StatementProperties", - "documentation":"

    The properties of the statement.

    " + "documentation":"

    The properties of the SQL statement.

    " } }, - "documentation":"

    The properties of metadata model in JSON format. This object is a Union. Only one member of this object can be specified or returned.

    ", + "documentation":"

    The properties of the metadata model.

    ", "union":true }, "MetadataModelReference":{ @@ -6757,7 +6763,7 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    The JSON string representing metadata model location.

    " + "documentation":"

    A JSON string that identifies this metadata model in the metadata tree. For the selection rule format, see Selection rules in DMS Schema Conversion.

    Usage:

    • You can pass this value as the SelectionRules parameter to any operation that accepts selection rules, such as DescribeMetadataModel, StartMetadataModelConversion, and others.

    " } }, "documentation":"

    A reference to a metadata model, including its name and selection rules for location identification.

    " @@ -6911,7 +6917,7 @@ }, "TransformationRules":{ "shape":"String", - "documentation":"

    The settings in JSON format for migration rules. Migration rules make it possible for you to change the object names according to the rules that you specify. For example, you can change an object name to lowercase or uppercase, add or remove a prefix or suffix, or rename objects.

    " + "documentation":"

    The transformation rules for the migration project in JSON format. Transformation rules let you customize how DMS Schema Conversion converts your source database objects, including renaming, adding prefixes or suffixes, and changing data types. For the transformation rule format and examples, see Transformation rules in DMS Schema Conversion.

    Homogeneous data migrations do not support transformation rules.

    " }, "Description":{ "shape":"String", @@ -6953,7 +6959,7 @@ }, "ConversionConfiguration":{ "shape":"String", - "documentation":"

    The new conversion configuration.

    " + "documentation":"

    A JSON string that contains the schema conversion settings to update. For the format and available settings, see Specifying schema conversion settings for migration projects.

    Usage:

    • Include only the sections and keys to change. The operation merges supplied values with the existing configuration.

    " } } }, @@ -7035,7 +7041,7 @@ }, "Engine":{ "shape":"String", - "documentation":"

    The type of database engine for the data provider. Valid values include \"aurora\", \"aurora-postgresql\", \"mysql\", \"oracle\", \"postgres\", \"sqlserver\", redshift, mariadb, mongodb, db2, db2-zos, docdb, and sybase. A value of \"aurora\" represents Amazon Aurora MySQL-Compatible Edition.

    " + "documentation":"

    The type of database engine for the data provider.

    Valid values: aurora, aurora-postgresql, db2, db2-zos, docdb, mariadb, mongodb, mysql, oracle, postgres, redshift, sqlserver, and sybase. A value of aurora represents Amazon Aurora MySQL-Compatible Edition.

    " }, "Virtual":{ "shape":"BooleanOptional", @@ -7324,7 +7330,7 @@ }, "TransformationRules":{ "shape":"String", - "documentation":"

    The settings in JSON format for migration rules. Migration rules make it possible for you to change the object names according to the rules that you specify. For example, you can change an object name to lowercase or uppercase, add or remove a prefix or suffix, or rename objects.

    " + "documentation":"

    A JSON string that specifies the transformation rules for the migration project. Transformation rules let you customize how DMS Schema Conversion converts your source database objects, including renaming, adding prefixes or suffixes, and changing data types. For the transformation rule format and examples, see Transformation rules in DMS Schema Conversion.

    Homogeneous data migrations do not support transformation rules.

    " }, "Description":{ "shape":"String", @@ -7626,7 +7632,7 @@ }, "ExtractDocId":{ "shape":"String", - "documentation":"

    Specifies the document ID. Use this setting when NestingLevel is set to \"none\".

    Default value is \"false\".

    " + "documentation":"

    Specifies whether the document ID is added to the target table. Use this setting when NestingLevel is set to \"none\".

    Set ExtractDocId to \"true\" when using multi-document transactions with CDC.

    Default value is \"false\".

    " }, "DocsToInvestigate":{ "shape":"String", @@ -8017,7 +8023,7 @@ }, "SecurityDbEncryption":{ "shape":"SecretString", - "documentation":"

    For an Oracle source endpoint, the transparent data encryption (TDE) password required by AWM DMS to access Oracle redo logs encrypted by TDE using Binary Reader. It is also the TDE_Password part of the comma-separated value you set to the Password request parameter when you create the endpoint. The SecurityDbEncryptian setting is related to this SecurityDbEncryptionName setting. For more information, see Supported encryption methods for using Oracle as a source for DMS in the Database Migration Service User Guide.

    " + "documentation":"

    For an Oracle source endpoint, the transparent data encryption (TDE) password required by DMS to access Oracle redo logs encrypted by TDE using Binary Reader. It is also the TDE_Password part of the comma-separated value you set to the Password request parameter when you create the endpoint. The SecurityDbEncryption setting is related to this SecurityDbEncryptionName setting. For more information, see Supported encryption methods for using Oracle as a source for DMS in the Database Migration Service User Guide.

    " }, "SecurityDbEncryptionName":{ "shape":"String", @@ -10072,7 +10078,7 @@ "members":{ "Status":{ "shape":"String", - "documentation":"

    The schema conversion action status.

    " + "documentation":"

    The schema conversion operation status. Possible values:

    • RECEIVED – The operation is received but not yet queued for processing.

    • IN_PROGRESS – The operation is queued or actively running.

    • SUCCESS – The operation completed successfully.

    • FAILED – The operation did not complete.

    • CANCELING – The operation is being canceled. The operation might still succeed or fail before cancellation takes effect.

    • CANCELED – The operation was canceled before completion.

    " }, "RequestIdentifier":{ "shape":"String", @@ -10083,7 +10089,10 @@ "documentation":"

    The migration project ARN.

    " }, "Error":{"shape":"ErrorDetails"}, - "ExportSqlDetails":{"shape":"ExportSqlDetails"}, + "ExportSqlDetails":{ + "shape":"ExportSqlDetails", + "documentation":"

    The Amazon S3 location of the ZIP archive that contains the exported data definition language (DDL) scripts.

    DMS populates this field only for the DescribeMetadataModelExportsAsScript operation.

    " + }, "Progress":{"shape":"Progress"} }, "documentation":"

    Provides information about a schema conversion action.

    " @@ -10272,7 +10281,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the request operation.

    " + "documentation":"

    The identifier for the installation request.

    " } } }, @@ -10289,7 +10298,7 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to assess.

    " + "documentation":"

    A JSON string that identifies the metadata models to assess. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only source selection rules, where server-name in the object locator matches the source data provider.

    • Supports explicit, include, and exclude rule actions.

    " } } }, @@ -10298,7 +10307,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the assessment operation.

    " + "documentation":"

    The identifier for the assessment request.

    " } } }, @@ -10315,7 +10324,7 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to convert.

    " + "documentation":"

    A JSON string that identifies the metadata models to convert. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only source selection rules, where server-name in the object locator matches the source data provider.

    • Supports explicit, include, and exclude rule actions.

    " } } }, @@ -10324,7 +10333,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the conversion operation.

    " + "documentation":"

    The identifier for the conversion request.

    " } } }, @@ -10343,15 +10352,15 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    The JSON string that specifies the location where the metadata model will be created. Selection rules must specify a single schema. For more information, see Selection Rules in the DMS User Guide.

    " + "documentation":"

    A JSON string that identifies the source schema for the metadata model. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only source selection rules, where server-name in the object locator matches the source data provider.

    • Supports only explicit rule actions.

    • Exactly one rule is allowed.

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

    The name of the metadata model.

    " + "documentation":"

    The name for the metadata model to use in subsequent operations.

    " }, "Properties":{ "shape":"MetadataModelProperties", - "documentation":"

    The properties of metadata model in JSON format. This object is a Union. Only one member of this object can be specified or returned.

    " + "documentation":"

    The properties of the metadata model.

    " } } }, @@ -10360,7 +10369,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the metadata model creation operation.

    " + "documentation":"

    The identifier for the creation request.

    " } } }, @@ -10378,15 +10387,15 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to export.

    " + "documentation":"

    A JSON string that identifies the metadata models to export as a SQL script. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts source or target selection rules depending on the Origin parameter. The server-name in the object locator must match the corresponding data provider.

    • Supports explicit, include, and exclude rule actions.

    " }, "Origin":{ "shape":"OriginTypeValue", - "documentation":"

    Whether to export the metadata model from the source or the target.

    " + "documentation":"

    Specifies the metadata tree to export from.

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

    The name of the model file to create in the Amazon S3 bucket.

    " + "documentation":"

    The name for the exported file. When you omit this parameter, the service generates a name from the data provider engine name and an export timestamp.

    " } } }, @@ -10395,7 +10404,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the export operation.

    " + "documentation":"

    The identifier for the export request.

    " } } }, @@ -10412,11 +10421,11 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to export.

    " + "documentation":"

    A JSON string that identifies the metadata models to export to the target database. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts only target selection rules, where server-name in the object locator matches the target data provider.

    • Supports explicit, include, and exclude rule actions.

    " }, "OverwriteExtensionPack":{ "shape":"BooleanOptional", - "documentation":"

    Whether to overwrite the migration project extension pack. An extension pack is an add-on module that emulates functions present in a source database that are required when converting objects to the target database.

    " + "documentation":"

    Specifies whether to overwrite the extension pack if one already exists on the target database. The default value is true.

    " } } }, @@ -10425,7 +10434,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the export operation.

    " + "documentation":"

    The identifier for the export request.

    " } } }, @@ -10443,15 +10452,15 @@ }, "SelectionRules":{ "shape":"String", - "documentation":"

    A value that specifies the database objects to import.

    " + "documentation":"

    A JSON string that identifies the metadata models to import from the data provider. For the selection rule format and examples, see Selection rules in DMS Schema Conversion.

    Usage:

    • Accepts source or target selection rules depending on the Origin parameter. The server-name in the object locator must match the corresponding data provider.

    • Supports explicit, include, and exclude rule actions.

    " }, "Origin":{ "shape":"OriginTypeValue", - "documentation":"

    Whether to load metadata to the source or target database.

    " + "documentation":"

    Specifies the metadata tree to import into.

    You cannot import from a virtual target data provider.

    " }, "Refresh":{ "shape":"Boolean", - "documentation":"

    If true, DMS loads metadata for the specified objects from the source database.

    " + "documentation":"

    Specifies whether to refresh the selected metadata models from the data provider.

    When true, the import reloads the selected metadata models with current definitions and removes their existing subtree.

    When false (default), the import loads the full subtree that has not yet been loaded into the metadata tree.

    " } } }, @@ -10460,7 +10469,7 @@ "members":{ "RequestIdentifier":{ "shape":"String", - "documentation":"

    The identifier for the import operation.

    " + "documentation":"

    The identifier for the import request.

    " } } }, @@ -10695,7 +10704,7 @@ "documentation":"

    The SQL text of the statement.

    " } }, - "documentation":"

    The properties of the statement for metadata model creation.

    " + "documentation":"

    The properties of the SQL statement.

    " }, "StopDataMigrationMessage":{ "type":"structure", diff --git a/services/databrew/pom.xml b/services/databrew/pom.xml index 87a5422ae945..eb1e8c290ce7 100644 --- a/services/databrew/pom.xml +++ b/services/databrew/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT databrew AWS Java SDK :: Services :: Data Brew diff --git a/services/databrew/src/main/resources/codegen-resources/customization.config b/services/databrew/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/databrew/src/main/resources/codegen-resources/customization.config +++ b/services/databrew/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/databrew/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/databrew/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4a220e62936a --- /dev/null +++ b/services/databrew/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,206 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://databrew-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://databrew.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://databrew-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://databrew.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://databrew.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/databrew/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/databrew/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c5af85da6ac0..000000000000 --- a/services/databrew/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,333 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://databrew-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://databrew.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://databrew-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://databrew.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://databrew.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/dataexchange/pom.xml b/services/dataexchange/pom.xml index d4a15a5a9089..eac7b00253c5 100644 --- a/services/dataexchange/pom.xml +++ b/services/dataexchange/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dataexchange AWS Java SDK :: Services :: DataExchange diff --git a/services/dataexchange/src/main/resources/codegen-resources/customization.config b/services/dataexchange/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/dataexchange/src/main/resources/codegen-resources/customization.config +++ b/services/dataexchange/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/dataexchange/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/dataexchange/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1e82061c5f7e --- /dev/null +++ b/services/dataexchange/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataexchange-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataexchange-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataexchange.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataexchange.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/dataexchange/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/dataexchange/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4eda94a7d5de..000000000000 --- a/services/dataexchange/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataexchange-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataexchange-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataexchange.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dataexchange.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/datapipeline/pom.xml b/services/datapipeline/pom.xml index b93a1fc8f2e0..c900e8be6aed 100644 --- a/services/datapipeline/pom.xml +++ b/services/datapipeline/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT datapipeline AWS Java SDK :: Services :: AWS Data Pipeline diff --git a/services/datapipeline/src/main/resources/codegen-resources/customization.config b/services/datapipeline/src/main/resources/codegen-resources/customization.config index 291756f11dd3..6e046d2a7d0d 100644 --- a/services/datapipeline/src/main/resources/codegen-resources/customization.config +++ b/services/datapipeline/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listPipelines" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/datapipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/datapipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..07e3e53d8f96 --- /dev/null +++ b/services/datapipeline/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datapipeline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datapipeline-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datapipeline.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datapipeline.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/datapipeline/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/datapipeline/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 98155121dabb..000000000000 --- a/services/datapipeline/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datapipeline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datapipeline-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datapipeline.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://datapipeline.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/datasync/pom.xml b/services/datasync/pom.xml index 6ed14540abca..9a6368ee0a42 100644 --- a/services/datasync/pom.xml +++ b/services/datasync/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT datasync AWS Java SDK :: Services :: DataSync diff --git a/services/datasync/src/main/resources/codegen-resources/customization.config b/services/datasync/src/main/resources/codegen-resources/customization.config index fadc149e092b..65bee9195b12 100644 --- a/services/datasync/src/main/resources/codegen-resources/customization.config +++ b/services/datasync/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "listTaskExecutions", "listTasks" ], - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/datasync/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/datasync/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6014fa94211a --- /dev/null +++ b/services/datasync/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datasync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datasync-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datasync.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datasync.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/datasync/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/datasync/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fbf3d8f10ddf..000000000000 --- a/services/datasync/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datasync-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datasync-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datasync.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://datasync.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/datasync/src/main/resources/codegen-resources/service-2.json b/services/datasync/src/main/resources/codegen-resources/service-2.json index ce527e6775ba..07300920ce21 100644 --- a/services/datasync/src/main/resources/codegen-resources/service-2.json +++ b/services/datasync/src/main/resources/codegen-resources/service-2.json @@ -1227,7 +1227,7 @@ }, "NameNodes":{ "shape":"HdfsNameNodeList", - "documentation":"

    The NameNode that manages the HDFS namespace. The NameNode performs operations such as opening, closing, and renaming files and directories. The NameNode contains the information to map blocks of data to the DataNodes. You can use only one NameNode.

    " + "documentation":"

    The NameNode that manages the HDFS namespace. The NameNode performs operations such as opening, closing, and renaming files and directories. The NameNode contains the information to map blocks of data to the DataNodes.

    The number of NameNodes you can specify depends on the task mode:

    • Enhanced mode – You can specify multiple NameNodes for HDFS High Availability (HA) configurations.

    • Basic mode – You can specify only one NameNode.

    " }, "BlockSize":{ "shape":"HdfsBlockSize", @@ -3283,11 +3283,11 @@ }, "Atime":{ "shape":"Atime", - "documentation":"

    Specifies whether to preserve metadata indicating the last time a file was read or written to.

    The behavior of Atime isn't fully standard across platforms, so DataSync can only do this on a best-effort basis.

    • BEST_EFFORT (default) - DataSync attempts to preserve the original Atime attribute on all source files (that is, the version before the PREPARING steps of the task execution). This option is recommended.

    • NONE - Ignores Atime.

    If Atime is set to BEST_EFFORT, Mtime must be set to PRESERVE.

    If Atime is set to NONE, Mtime must also be NONE.

    " + "documentation":"

    Specifies whether to preserve metadata indicating the last time a file was read or written to.

    The behavior of Atime isn't fully standard across platforms, so DataSync can only do this on a best-effort basis.

    • BEST_EFFORT (default) - DataSync attempts to preserve the original Atime attribute on all source files (that is, the version before the PREPARING steps of the task execution). This option is recommended.

    • NONE - Ignores Atime.

    The following applies only to Basic mode tasks:

    If Atime is set to BEST_EFFORT, Mtime must be set to PRESERVE.

    If Atime is set to NONE, Mtime must also be NONE.

    Enhanced mode tasks support configuring Atime independently of Mtime.

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

    Specifies whether to preserve metadata indicating the last time that a file was written to before the PREPARING step of your task execution. This option is required when you need to run the a task more than once.

    • PRESERVE (default) - Preserves original Mtime, which is recommended.

    • NONE - Ignores Mtime.

    If Mtime is set to PRESERVE, Atime must be set to BEST_EFFORT.

    If Mtime is set to NONE, Atime must also be set to NONE.

    " + "documentation":"

    Specifies whether to preserve metadata indicating the last time that a file was written to before the PREPARING step of your task execution. This option is required when you need to run the a task more than once.

    • PRESERVE (default) - Preserves original Mtime, which is recommended.

    • NONE - Ignores Mtime.

    The following applies only to Basic mode tasks:

    If Mtime is set to PRESERVE, Atime must be set to BEST_EFFORT.

    If Mtime is set to NONE, Atime must also be set to NONE.

    Enhanced mode tasks don't support Mtime set to NONE.

    " }, "Uid":{ "shape":"Uid", @@ -4368,7 +4368,7 @@ }, "NameNodes":{ "shape":"HdfsNameNodeList", - "documentation":"

    The NameNode that manages the HDFS namespace. The NameNode performs operations such as opening, closing, and renaming files and directories. The NameNode contains the information to map blocks of data to the DataNodes. You can use only one NameNode.

    " + "documentation":"

    The NameNode that manages the HDFS namespace. The NameNode performs operations such as opening, closing, and renaming files and directories. The NameNode contains the information to map blocks of data to the DataNodes.

    The number of NameNodes you can specify depends on the task mode:

    • Enhanced mode – You can specify multiple NameNodes for HDFS High Availability (HA) configurations.

    • Basic mode – You can specify only one NameNode.

    " }, "BlockSize":{ "shape":"HdfsBlockSize", @@ -4684,5 +4684,5 @@ "long":{"type":"long"}, "string":{"type":"string"} }, - "documentation":"DataSync

    DataSync is an online data movement service that simplifies data migration and helps you quickly, easily, and securely transfer your file or object data to, from, and between Amazon Web Services storage services.

    This API interface reference includes documentation for using DataSync programmatically. For complete information, see the DataSync User Guide .

    " + "documentation":"DataSync

    In addition to the Amazon Web Services Management Console and Amazon Web Services Command Line Interface, you can use the DataSync API to configure and manage DataSync with the Amazon Web Services SDKs.

    DataSync is an online data movement service that simplifies data migration and helps you quickly, easily, and securely transfer your file or object data to, from, and between Amazon Web Services storage services.

    This API interface reference includes documentation for using DataSync programmatically. For complete information, see the DataSync User Guide .

    " } diff --git a/services/datazone/pom.xml b/services/datazone/pom.xml index e203b1faa460..5344ae21a96d 100644 --- a/services/datazone/pom.xml +++ b/services/datazone/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT datazone AWS Java SDK :: Services :: Data Zone diff --git a/services/datazone/src/main/resources/codegen-resources/customization.config b/services/datazone/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/datazone/src/main/resources/codegen-resources/customization.config +++ b/services/datazone/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/datazone/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/datazone/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1c12f0574c18 --- /dev/null +++ b/services/datazone/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,157 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datazone-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datazone.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datazone-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://datazone.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAAAAAkAAAADAAAAAQAAAAQF9eEIAAAAAgAAAAUF9eEIAAAAAwAAAAcAAAAGAAAABQX14QUF9eEHAAAABAAAAAgF9eEEAAAABQX14QMF9eEGAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/datazone/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/datazone/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6b0886153a88..000000000000 --- a/services/datazone/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datazone-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://datazone.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://datazone-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://datazone.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/datazone/src/main/resources/codegen-resources/service-2.json b/services/datazone/src/main/resources/codegen-resources/service-2.json index c05ee037d800..f7edaafa184e 100644 --- a/services/datazone/src/main/resources/codegen-resources/service-2.json +++ b/services/datazone/src/main/resources/codegen-resources/service-2.json @@ -3344,6 +3344,28 @@ "documentation":"

    Starts a notebook run in Amazon SageMaker Unified Studio. A notebook run represents the execution of an Amazon SageMaker notebook within a project. You can configure compute, network, timeout, and environment settings for the run.

    ", "idempotent":true }, + "StartNotebookSync":{ + "name":"StartNotebookSync", + "http":{ + "method":"POST", + "requestUri":"/v2/domains/{domainIdentifier}/notebook-syncs", + "responseCode":201 + }, + "input":{"shape":"StartNotebookSyncInput"}, + "output":{"shape":"StartNotebookSyncOutput"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"UnauthorizedException"} + ], + "documentation":"

    Starts a notebook sync in Amazon SageMaker Unified Studio. This operation syncs a notebook from a Git repository into a project.

    ", + "idempotent":true + }, "StopNotebookRun":{ "name":"StopNotebookRun", "http":{ @@ -4968,6 +4990,10 @@ "shape":"String", "documentation":"

    The status of the asset scope.

    " }, + "scopeName":{ + "shape":"String", + "documentation":"

    The name of the materialized asset scope.

    " + }, "errorMessage":{ "shape":"String", "documentation":"

    The error message of the asset scope.

    " @@ -5810,6 +5836,18 @@ "type":"list", "member":{"shape":"String"} }, + "CommitHash":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9]+" + }, + "CommitMessage":{ + "type":"string", + "max":2048, + "min":0, + "sensitive":true + }, "CompletedAt":{"type":"timestamp"}, "ComputeConfig":{ "type":"structure", @@ -6035,6 +6073,10 @@ "vpcProperties":{ "shape":"VpcPropertiesInput", "documentation":"

    The VPC properties of a connection.

    " + }, + "gitProperties":{ + "shape":"GitPropertiesInput", + "documentation":"

    The Git properties of a connection.

    " } }, "documentation":"

    The properties of a connection.

    ", @@ -6102,6 +6144,10 @@ "vpcProperties":{ "shape":"VpcPropertiesOutput", "documentation":"

    The VPC properties of a connection.

    " + }, + "gitProperties":{ + "shape":"GitPropertiesOutput", + "documentation":"

    The Git properties of a connection.

    " } }, "documentation":"

    The properties of a connection.

    ", @@ -6153,6 +6199,10 @@ "vpcProperties":{ "shape":"VpcPropertiesPatch", "documentation":"

    The VPC properties of a connection properties patch.

    " + }, + "gitProperties":{ + "shape":"GitPropertiesPatch", + "documentation":"

    The Git properties of a connection properties patch.

    " } }, "documentation":"

    The connection properties patch.

    ", @@ -6270,7 +6320,8 @@ "WORKFLOWS_MWAA", "AMAZON_Q", "MLFLOW", - "VPC" + "VPC", + "GIT" ] }, "ConnectivityProperties":{ @@ -8513,6 +8564,10 @@ "shape":"Description", "documentation":"

    The description of the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type of the notebook.

    " + }, "metadata":{ "shape":"Metadata", "documentation":"

    The metadata for the notebook, specified as key-value pairs. You can specify up to 50 entries, with keys up to 128 characters and values up to 1024 characters.

    " @@ -8563,6 +8618,10 @@ "shape":"NotebookStatus", "documentation":"

    The status of the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type of the notebook.

    " + }, "description":{ "shape":"Description", "documentation":"

    The description of the notebook.

    " @@ -8614,6 +8673,10 @@ "error":{ "shape":"NotebookError", "documentation":"

    The error details if the notebook creation failed.

    " + }, + "gitMetadata":{ + "shape":"GitMetadata", + "documentation":"

    The Git metadata associated with the notebook.

    " } } }, @@ -10492,9 +10555,15 @@ }, "skipDeletionCheck":{ "shape":"Boolean", - "documentation":"

    Specifies the optional flag to delete all child entities within the domain.

    ", + "documentation":"

    Specifies whether to skip the check that prevents deletion of a domain that still contains resources. When you use this parameter, Amazon DataZone deletes the domain but might not remove its associated resources, which can leave orphaned resources behind. To delete a domain and fully clean up its associated resources, use cascadeDelete instead. You can't use this parameter together with cascadeDelete.

    ", "location":"querystring", "locationName":"skipDeletionCheck" + }, + "cascadeDelete":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to delete the domain along with all of its associated resources. When you use this parameter, Amazon DataZone deletes the domain and cleanly removes its associated resources without leaving orphaned resources behind. Amazon DataZone reports deletion progress in the deleteProgress field. Amazon DataZone reports any resources that it can't delete in the failureReasons field of the GetDomain response. You can't use this parameter together with skipDeletionCheck. If you don't specify a value, the default is false.

    ", + "location":"querystring", + "locationName":"cascadeDelete" } } }, @@ -10812,6 +10881,16 @@ "type":"structure", "members":{} }, + "DeleteProgress":{ + "type":"structure", + "members":{ + "successfullyDeletedProjectCount":{ + "shape":"Integer", + "documentation":"

    The number of projects that Amazon DataZone successfully deleted during the domain deletion.

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

    The progress of a domain deletion, including the number of projects that Amazon DataZone successfully deleted. Amazon DataZone returns this structure in the response to a GetDomain request while a cascade deletion is in progress.

    " + }, "DeleteProjectInput":{ "type":"structure", "required":[ @@ -12237,10 +12316,29 @@ }, "documentation":"

    Specifies the error message that is returned if the operation cannot be successfully completed.

    " }, + "FailureReason":{ + "type":"structure", + "members":{ + "id":{ + "shape":"String", + "documentation":"

    The identifier of the resource that failed to delete.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    The error message associated with the resource that failed to delete.

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

    The details of a resource deletion failure during a cascade deletion of the domain.

    " + }, "FailureReasons":{ "type":"list", "member":{"shape":"ProjectDeletionError"} }, + "FailureReasonsList":{ + "type":"list", + "member":{"shape":"FailureReason"}, + "documentation":"

    A list of FailureReason objects that describe the resources that Amazon DataZone could not delete during a cascade deletion. Amazon DataZone returns this list in the failureReasons field of the GetDomain response.

    " + }, "FileFormat":{ "type":"string", "documentation":"

    The file format for a notebook export in Amazon SageMaker Unified Studio.

    ", @@ -12249,6 +12347,11 @@ "IPYNB" ] }, + "FileName":{ + "type":"string", + "max":255, + "min":1 + }, "Filter":{ "type":"structure", "required":["attribute"], @@ -13489,6 +13592,14 @@ "serviceRole":{ "shape":"RoleArn", "documentation":"

    The service role of the domain.

    " + }, + "failureReasons":{ + "shape":"FailureReasonsList", + "documentation":"

    The list of failure reasons for resources that Amazon DataZone could not delete during a cascade deletion of the domain.

    " + }, + "deleteProgress":{ + "shape":"DeleteProgress", + "documentation":"

    The progress of the current domain deletion, including the number of projects that Amazon DataZone successfully deleted.

    " } } }, @@ -14884,6 +14995,10 @@ "shape":"NotebookStatus", "documentation":"

    The status of the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type of the notebook.

    " + }, "description":{ "shape":"Description", "documentation":"

    The description of the notebook.

    " @@ -14935,6 +15050,10 @@ "error":{ "shape":"NotebookError", "documentation":"

    The error details if the notebook is in a failed state.

    " + }, + "gitMetadata":{ + "shape":"GitMetadata", + "documentation":"

    The Git metadata associated with the notebook.

    " } } }, @@ -15853,6 +15972,180 @@ } } }, + "GitBranch":{ + "type":"string", + "max":256, + "min":1, + "sensitive":true + }, + "GitConnectionId":{ + "type":"string", + "max":40, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "GitMetadata":{ + "type":"structure", + "required":[ + "connectionId", + "repository", + "branch", + "commitHash" + ], + "members":{ + "connectionId":{ + "shape":"GitConnectionId", + "documentation":"

    The identifier of the Git connection.

    " + }, + "repository":{ + "shape":"GitRepository", + "documentation":"

    The name of the Git repository.

    " + }, + "branch":{ + "shape":"GitBranch", + "documentation":"

    The name of the Git branch.

    " + }, + "commitHash":{ + "shape":"CommitHash", + "documentation":"

    The commit hash in the Git repository.

    " + }, + "fileName":{ + "shape":"FileName", + "documentation":"

    The name of the file in the Git repository.

    " + }, + "committedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of when the commit was made.

    " + }, + "commitMessage":{ + "shape":"CommitMessage", + "documentation":"

    The commit message associated with the Git commit.

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

    The Git metadata for a notebook sync operation in Amazon SageMaker Unified Studio. Contains information about the Git repository, branch, and commit associated with the notebook.

    " + }, + "GitPropertiesInput":{ + "type":"structure", + "required":[ + "codeConnectionArn", + "repositoryId", + "defaultBranch" + ], + "members":{ + "codeConnectionArn":{ + "shape":"GitPropertiesInputCodeConnectionArnString", + "documentation":"

    The ARN of the CodeConnections connection used to connect to the Git repository.

    " + }, + "repositoryId":{ + "shape":"GitPropertiesInputRepositoryIdString", + "documentation":"

    The ID of the Git repository. This is the owner and repository name, for example, owner/repo-name.

    " + }, + "defaultBranch":{ + "shape":"GitPropertiesInputDefaultBranchString", + "documentation":"

    The default branch of the Git repository.

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

    Contains the Git connection properties that you specify when creating a Git connection.

    " + }, + "GitPropertiesInputCodeConnectionArnString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"arn:aws[^:]*:(codeconnections|codestar-connections):[a-z0-9\\-]+:\\d{12}:connection/[a-f0-9\\-]+" + }, + "GitPropertiesInputDefaultBranchString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9._\\-/]+" + }, + "GitPropertiesInputRepositoryIdString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9._\\-]+(/[a-zA-Z0-9._\\-]+)+" + }, + "GitPropertiesOutput":{ + "type":"structure", + "required":[ + "codeConnectionArn", + "repositoryId", + "defaultBranch" + ], + "members":{ + "codeConnectionArn":{ + "shape":"GitPropertiesOutputCodeConnectionArnString", + "documentation":"

    The ARN of the CodeConnections connection used to connect to the Git repository.

    " + }, + "repositoryId":{ + "shape":"GitPropertiesOutputRepositoryIdString", + "documentation":"

    The ID of the Git repository. This is the owner and repository name, for example, owner/repo-name.

    " + }, + "defaultBranch":{ + "shape":"GitPropertiesOutputDefaultBranchString", + "documentation":"

    The default branch of the Git repository.

    " + }, + "status":{ + "shape":"ConnectionStatus", + "documentation":"

    The status of the Git connection.

    " + }, + "errorMessage":{ + "shape":"String", + "documentation":"

    The error message that describes why the Git connection failed. This member is populated when the connection status is CREATE_FAILED or UPDATE_FAILED.

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

    The properties of a Git connection returned by get and list operations, including connection status and any error details.

    " + }, + "GitPropertiesOutputCodeConnectionArnString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"arn:aws[^:]*:(codeconnections|codestar-connections):[a-z0-9\\-]+:\\d{12}:connection/[a-f0-9\\-]+" + }, + "GitPropertiesOutputDefaultBranchString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9._\\-/]+" + }, + "GitPropertiesOutputRepositoryIdString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9._\\-]+(/[a-zA-Z0-9._\\-]+)+" + }, + "GitPropertiesPatch":{ + "type":"structure", + "members":{ + "codeConnectionArn":{ + "shape":"GitPropertiesPatchCodeConnectionArnString", + "documentation":"

    The ARN of the CodeConnections connection used to connect to the Git repository.

    " + }, + "defaultBranch":{ + "shape":"GitPropertiesPatchDefaultBranchString", + "documentation":"

    The default branch of the Git repository.

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

    The properties used to update an existing Git connection, such as the CodeConnections ARN or the default branch.

    " + }, + "GitPropertiesPatchCodeConnectionArnString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"arn:aws[^:]*:(codeconnections|codestar-connections):[a-z0-9\\-]+:\\d{12}:connection/[a-f0-9\\-]+" + }, + "GitPropertiesPatchDefaultBranchString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9._\\-/]+" + }, + "GitRepository":{ + "type":"string", + "max":512, + "min":1, + "sensitive":true + }, "GlobalParameterMap":{ "type":"map", "key":{"shape":"String"}, @@ -18768,6 +19061,12 @@ "location":"querystring", "locationName":"status" }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type to filter notebooks by.

    ", + "location":"querystring", + "locationName":"type" + }, "nextToken":{ "shape":"PaginationToken", "documentation":"

    When the number of notebooks is greater than the default value for the MaxResults parameter, or if you explicitly specify a value for MaxResults that is less than the number of notebooks, the response includes a pagination token named NextToken. You can specify this NextToken value in a subsequent call to ListNotebooks to list the next set of notebooks.

    ", @@ -20445,7 +20744,9 @@ "documentation":"

    The status of a notebook in Amazon SageMaker Unified Studio.

    ", "enum":[ "ACTIVE", - "ARCHIVED" + "ARCHIVED", + "SYNC_IN_PROGRESS", + "SYNC_FAILED" ] }, "NotebookSummary":{ @@ -20478,6 +20779,10 @@ "shape":"NotebookStatus", "documentation":"

    The status of the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type of the notebook.

    " + }, "description":{ "shape":"Description", "documentation":"

    The description of the notebook.

    " @@ -20505,6 +20810,14 @@ "type":"list", "member":{"shape":"NotebookSummary"} }, + "NotebookType":{ + "type":"string", + "documentation":"

    The type of a notebook in Amazon SageMaker Unified Studio.

    ", + "enum":[ + "DATA", + "SQL" + ] + }, "NotificationOutput":{ "type":"structure", "required":[ @@ -24773,6 +25086,96 @@ } } }, + "StartNotebookSyncInput":{ + "type":"structure", + "required":[ + "domainIdentifier", + "owningProjectIdentifier", + "sourceLocation" + ], + "members":{ + "domainIdentifier":{ + "shape":"DomainId", + "documentation":"

    The identifier of the Amazon SageMaker Unified Studio domain in which to sync the notebook.

    ", + "location":"uri", + "locationName":"domainIdentifier" + }, + "owningProjectIdentifier":{ + "shape":"ProjectId", + "documentation":"

    The identifier of the project that will own the synced notebook.

    " + }, + "sourceLocation":{ + "shape":"SourceLocation", + "documentation":"

    The source location of the notebook to sync. This specifies the Amazon Simple Storage Service URI of the notebook file.

    " + }, + "gitMetadata":{ + "shape":"GitMetadata", + "documentation":"

    The Git metadata for the notebook sync, including repository, branch, and commit information.

    " + }, + "notebookId":{ + "shape":"NotebookId", + "documentation":"

    The identifier of an existing notebook to sync. If not specified, a new notebook is created.

    " + }, + "name":{ + "shape":"NotebookName", + "documentation":"

    The name of the notebook. The name must be between 1 and 256 characters.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the notebook.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure idempotency of the request. This field is automatically populated if not provided.

    ", + "idempotencyToken":true + } + } + }, + "StartNotebookSyncOutput":{ + "type":"structure", + "members":{ + "notebookId":{ + "shape":"NotebookId", + "documentation":"

    The identifier of the synced notebook.

    " + }, + "status":{ + "shape":"NotebookStatus", + "documentation":"

    The status of the notebook sync.

    " + }, + "domainId":{ + "shape":"DomainId", + "documentation":"

    The identifier of the Amazon SageMaker Unified Studio domain.

    " + }, + "owningProjectId":{ + "shape":"ProjectId", + "documentation":"

    The identifier of the project that owns the synced notebook.

    " + }, + "sourceLocation":{ + "shape":"SourceLocation", + "documentation":"

    The source location from which the notebook was synced.

    " + }, + "gitMetadata":{ + "shape":"GitMetadata", + "documentation":"

    The Git metadata associated with the synced notebook.

    " + }, + "name":{ + "shape":"NotebookName", + "documentation":"

    The name of the synced notebook.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the synced notebook.

    " + }, + "createdAt":{ + "shape":"CreatedAt", + "documentation":"

    The timestamp of when the notebook sync was started.

    " + }, + "createdBy":{ + "shape":"CreatedBy", + "documentation":"

    The identifier of the user who started the notebook sync.

    " + } + } + }, "Status":{ "type":"string", "enum":[ @@ -27376,6 +27779,10 @@ "shape":"CellOrder", "documentation":"

    The updated ordered list of cells in the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The updated type of the notebook.

    " + }, "metadata":{ "shape":"Metadata", "documentation":"

    The updated metadata for the notebook, specified as key-value pairs.

    " @@ -27430,6 +27837,10 @@ "shape":"NotebookStatus", "documentation":"

    The status of the notebook.

    " }, + "type":{ + "shape":"NotebookType", + "documentation":"

    The type of the notebook.

    " + }, "description":{ "shape":"Description", "documentation":"

    The description of the notebook.

    " @@ -27481,6 +27892,10 @@ "error":{ "shape":"NotebookError", "documentation":"

    The error details if the notebook is in a failed state.

    " + }, + "gitMetadata":{ + "shape":"GitMetadata", + "documentation":"

    The Git metadata associated with the notebook.

    " } } }, diff --git a/services/dax/pom.xml b/services/dax/pom.xml index cd3fb6e40a17..1d0b517f76e5 100644 --- a/services/dax/pom.xml +++ b/services/dax/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dax AWS Java SDK :: Services :: Amazon DynamoDB Accelerator (DAX) diff --git a/services/dax/src/main/resources/codegen-resources/customization.config b/services/dax/src/main/resources/codegen-resources/customization.config index 4f0fb398e0e7..e63b58e10ec2 100644 --- a/services/dax/src/main/resources/codegen-resources/customization.config +++ b/services/dax/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "describeEvents", "describeParameterGroups", "describeSubnetGroups" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/dax/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/dax/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..870ae4483778 --- /dev/null +++ b/services/dax/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dax-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dax-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dax.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dax.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/dax/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/dax/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 859c8c7c1dea..000000000000 --- a/services/dax/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dax-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dax-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dax.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dax.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/deadline/pom.xml b/services/deadline/pom.xml index 63d77deb2e66..02a41b0b1f47 100644 --- a/services/deadline/pom.xml +++ b/services/deadline/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT deadline AWS Java SDK :: Services :: Deadline diff --git a/services/deadline/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/deadline/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5c3082d392c8 --- /dev/null +++ b/services/deadline/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deadline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deadline-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deadline.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deadline.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/deadline/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/deadline/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 86dafc7ae8f8..000000000000 --- a/services/deadline/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deadline-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deadline-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deadline.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deadline.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/deadline/src/main/resources/codegen-resources/service-2.json b/services/deadline/src/main/resources/codegen-resources/service-2.json index 7ffa3e85187a..ba7d3f370438 100644 --- a/services/deadline/src/main/resources/codegen-resources/service-2.json +++ b/services/deadline/src/main/resources/codegen-resources/service-2.json @@ -9166,7 +9166,7 @@ "documentation":"

    The job ID.

    " }, "jobAttachmentSettings":{ - "shape":"JobAttachmentSettings", + "shape":"JobDetailsJobAttachmentSettings", "documentation":"

    The job attachment settings.

    " }, "jobRunAsUser":{ @@ -9230,6 +9230,24 @@ }, "documentation":"

    The identifiers for a job.

    " }, + "JobDetailsJobAttachmentSettings":{ + "type":"structure", + "required":[ + "s3BucketName", + "rootPrefix" + ], + "members":{ + "s3BucketName":{ + "shape":"S3BucketName", + "documentation":"

    The Amazon S3 bucket name.

    " + }, + "rootPrefix":{ + "shape":"S3Prefix", + "documentation":"

    The root prefix.

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

    The job attachment settings returned to workers for a job. These are the Amazon S3 bucket name and the Amazon S3 prefix.

    " + }, "JobEntity":{ "type":"structure", "members":{ @@ -15278,7 +15296,8 @@ "type":"string", "enum":[ "COMPUTE", - "LICENSE" + "LICENSE", + "PERSISTENT_VOLUME" ] }, "UserId":{"type":"string"}, diff --git a/services/detective/pom.xml b/services/detective/pom.xml index 33542c811ea2..ff901b8bc02c 100644 --- a/services/detective/pom.xml +++ b/services/detective/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT detective AWS Java SDK :: Services :: Detective diff --git a/services/detective/src/main/resources/codegen-resources/customization.config b/services/detective/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/detective/src/main/resources/codegen-resources/customization.config +++ b/services/detective/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/detective/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/detective/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..72326a41608d --- /dev/null +++ b/services/detective/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://detective.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://detective-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.detective-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.detective-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.detective.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.detective.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAoAAAAGAAAABAAAAAcF9eEMAAAABQX14QQAAAAIAAAABgX14QQAAAAJAAAACAX14QoF9eELAAAABAAAAAwAAAALAAAABwX14QgF9eEJAAAABQX14QUAAAANAAAABgX14QUAAAAOAAAABwAAAA8F9eEHAAAACAX14QYF9eEHAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/detective/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/detective/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cbcea13b364d..000000000000 --- a/services/detective/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,516 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://detective.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://detective-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://detective.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://detective-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.detective-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.detective-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.detective.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.detective.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/devicefarm/pom.xml b/services/devicefarm/pom.xml index 06f88703d130..3e1a44188b79 100644 --- a/services/devicefarm/pom.xml +++ b/services/devicefarm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT devicefarm AWS Java SDK :: Services :: AWS Device Farm diff --git a/services/devicefarm/src/main/resources/codegen-resources/customization.config b/services/devicefarm/src/main/resources/codegen-resources/customization.config index 34218832ad4b..689d56e2c251 100644 --- a/services/devicefarm/src/main/resources/codegen-resources/customization.config +++ b/services/devicefarm/src/main/resources/codegen-resources/customization.config @@ -14,6 +14,5 @@ "purchaseOffering", "renewOffering", "listVPCEConfigurations" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/devicefarm/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/devicefarm/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ed89ff6d676e --- /dev/null +++ b/services/devicefarm/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devicefarm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devicefarm-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devicefarm.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devicefarm.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/devicefarm/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/devicefarm/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 107b1f4ff648..000000000000 --- a/services/devicefarm/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devicefarm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devicefarm-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devicefarm.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://devicefarm.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/devicefarm/src/main/resources/codegen-resources/service-2.json b/services/devicefarm/src/main/resources/codegen-resources/service-2.json index 62942f6cf13b..ac9eaf097fa1 100644 --- a/services/devicefarm/src/main/resources/codegen-resources/service-2.json +++ b/services/devicefarm/src/main/resources/codegen-resources/service-2.json @@ -553,7 +553,7 @@ {"shape":"ArgumentException"}, {"shape":"InternalServiceException"} ], - "documentation":"

    A session is an instance of a browser created through a RemoteWebDriver with the URL from CreateTestGridUrlResult$url. You can use the following to look up sessions:

    " + "documentation":"

    A session is an instance of a browser created through a RemoteWebDriver with the URL from CreateTestGridUrlResult. You can use the following to look up sessions:

    • The session ARN.

    • The project ARN and a session ID.

    " }, "GetUpload":{ "name":"GetUpload", @@ -827,7 +827,7 @@ {"shape":"LimitExceededException"}, {"shape":"ServiceAccountException"} ], - "documentation":"

    Gets information about samples, given an AWS Device Farm job ARN.

    " + "documentation":"

    Gets information about samples, given an AWS Device Farm job ARN.

    Device Farm does not support performance data samples during test executions.

    " }, "ListSuites":{ "name":"ListSuites", @@ -1665,6 +1665,10 @@ "deviceProxy":{ "shape":"DeviceProxy", "documentation":"

    The device proxy to be configured on the device for the remote access session.

    " + }, + "parameters":{ + "shape":"RemoteAccessParameters", + "documentation":"

    The name-value string pairs that specify additional settings for the remote access session.

    • appium:version: The major version of the Appium server to use for the session (for example, 2 or 3). The service may reject the selected version if it is not available for the selected device.

    " } }, "documentation":"

    Configuration settings for a remote access session, including billing method.

    " @@ -1773,11 +1777,11 @@ "members":{ "url":{ "shape":"SensitiveString", - "documentation":"

    A signed URL, expiring in CreateTestGridUrlRequest$expiresInSeconds seconds, to be passed to a RemoteWebDriver.

    " + "documentation":"

    A signed URL, expiring in the time specified by the CreateTestGridUrlRequest, to be passed to a RemoteWebDriver.

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

    The number of seconds the URL from CreateTestGridUrlResult$url stays active.

    " + "documentation":"

    The number of seconds the URL stays active from creation.

    " } } }, @@ -2917,6 +2921,17 @@ "type":"list", "member":{"shape":"IncompatibilityMessage"} }, + "InsightsType":{ + "type":"string", + "documentation":"

    The type of insights to generate.

    ", + "enum":["TEST_REPORT"] + }, + "InsightsTypes":{ + "type":"list", + "member":{"shape":"InsightsType"}, + "max":5, + "min":1 + }, "InstallToRemoteAccessSessionRequest":{ "type":"structure", "required":[ @@ -3086,10 +3101,92 @@ "videoCapture":{ "shape":"VideoCapture", "documentation":"

    This value is set to true if video capture is enabled. Otherwise, it is set to false.

    " + }, + "insights":{ + "shape":"JobInsights", + "documentation":"

    The insights for the job, including the report status and test-level metrics. This field contains data only if you specified insightsTypes when you scheduled the run.

    " } }, "documentation":"

    Represents a device.

    " }, + "JobInsights":{ + "type":"structure", + "members":{ + "status":{ + "shape":"ReportStatus", + "documentation":"

    The status of the insights report for the job.

    " + }, + "testReport":{ + "shape":"TestReport", + "documentation":"

    The test-level aggregated report for the job.

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

    Contains insights for a job, including report status, and test-level aggregated metrics such as per test execution time and median test execution time.

    " + }, + "JobReport":{ + "type":"structure", + "members":{ + "message":{ + "shape":"ReportMessage", + "documentation":"

    A message associated with the job report.

    " + }, + "metrics":{ + "shape":"JobReportMetrics", + "documentation":"

    The aggregated job-level metrics for the run.

    " + }, + "jobDetailsUrl":{ + "shape":"SensitiveURL", + "documentation":"

    A URL to the detailed job results.

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

    Contains aggregated job-level metrics for a run.

    " + }, + "JobReportMetrics":{ + "type":"structure", + "members":{ + "jobsTotal":{ + "shape":"Integer", + "documentation":"

    The total number of jobs in the run.

    " + }, + "jobsPassed":{ + "shape":"Integer", + "documentation":"

    The number of jobs that passed.

    " + }, + "jobsFailed":{ + "shape":"Integer", + "documentation":"

    The number of jobs that failed.

    " + }, + "jobsSkipped":{ + "shape":"Integer", + "documentation":"

    The number of jobs that were skipped.

    " + }, + "jobsErrored":{ + "shape":"Integer", + "documentation":"

    The number of jobs that errored.

    " + }, + "jobsStopped":{ + "shape":"Integer", + "documentation":"

    The number of jobs that were stopped.

    " + }, + "jobsPassedPercentage":{ + "shape":"Double", + "documentation":"

    The percentage of jobs that passed.

    " + }, + "totalJobExecutionDurationSeconds":{ + "shape":"Double", + "documentation":"

    The total execution duration of all jobs in the run, in seconds.

    " + }, + "averageJobExecutionDurationSeconds":{ + "shape":"Double", + "documentation":"

    The average execution duration of jobs in the run, in seconds.

    " + }, + "medianJobExecutionDurationSeconds":{ + "shape":"Double", + "documentation":"

    The median execution duration of jobs in the run, in seconds.

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

    Contains aggregated metrics across all jobs in a run.

    " + }, "JobTimeoutMinutes":{"type":"integer"}, "Jobs":{ "type":"list", @@ -4287,6 +4384,25 @@ }, "documentation":"

    Represents the remote endpoints for viewing and controlling a device during a remote access session.

    " }, + "RemoteAccessParameterKey":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9:_]+" + }, + "RemoteAccessParameterValue":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_.]+" + }, + "RemoteAccessParameters":{ + "type":"map", + "key":{"shape":"RemoteAccessParameterKey"}, + "value":{"shape":"RemoteAccessParameterValue"}, + "max":3, + "min":1 + }, "RemoteAccessSession":{ "type":"structure", "members":{ @@ -4408,6 +4524,22 @@ }, "documentation":"

    The result of a renewal offering.

    " }, + "ReportMessage":{ + "type":"string", + "max":4096, + "min":0 + }, + "ReportStatus":{ + "type":"string", + "documentation":"

    The status of an insights report. Possible values are:

    • PENDING: The service has queued the report and generation has not started.

    • RUNNING: The service is generating the report.

    • COMPLETED: The service successfully generated the report.

    • SKIPPED: The service did not generate the report because the necessary conditions were not met. For more information about why the service could not generate the report, view the message field in TestReport or JobReport.

    • ERRORED: An error occurred while generating the report. For more information about why the service could not generate the report, view the message field in TestReport or JobReport.

    ", + "enum":[ + "PENDING", + "RUNNING", + "COMPLETED", + "SKIPPED", + "ERRORED" + ] + }, "Resolution":{ "type":"structure", "members":{ @@ -4617,10 +4749,32 @@ "environmentVariables":{ "shape":"EnvironmentVariables", "documentation":"

    Environment variables associated with the run.

    " + }, + "insightsTypes":{ + "shape":"InsightsTypes", + "documentation":"

    The types of insights requested for the run.

    " + }, + "insights":{ + "shape":"RunInsights", + "documentation":"

    The insights for the run, including the report status and job-level metrics. This field contains data only if you specified insightsTypes when you scheduled the run.

    " } }, "documentation":"

    Represents a test run on a set of devices with a given app package, test parameters, and so on.

    " }, + "RunInsights":{ + "type":"structure", + "members":{ + "status":{ + "shape":"ReportStatus", + "documentation":"

    The status of the insights report for the run.

    " + }, + "jobReport":{ + "shape":"JobReport", + "documentation":"

    The job-level aggregated report for the run.

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

    Contains insights for a run, including report status, and job-level aggregated metrics such as per job execution time and median job execution time.

    " + }, "Runs":{ "type":"list", "member":{"shape":"Run"} @@ -4641,7 +4795,7 @@ "documentation":"

    The presigned Amazon S3 URL that can be used with a GET request to download the sample's file.

    " } }, - "documentation":"

    Represents a sample of performance data.

    " + "documentation":"

    Represents a sample of performance data.

    Device Farm does not support performance data samples during test executions.

    " }, "SampleType":{ "type":"string", @@ -4719,6 +4873,10 @@ "executionRoleArn":{ "shape":"AmazonRoleResourceName", "documentation":"

    An IAM role to be assumed by the test host for the run.

    " + }, + "insightsTypes":{ + "shape":"InsightsTypes", + "documentation":"

    The types of insights to generate for a run. Specify one or more values to opt in to insights generation when scheduling a run.

    Insights are currently supported for custom mode runs with Instrumentation, Appium Java TestNG, and XCTest UI test types.

    " } }, "documentation":"

    Represents the settings for a run. Includes things like location, radio states, auxiliary apps, and network profiles.

    " @@ -4797,7 +4955,7 @@ }, "parameters":{ "shape":"TestParameters", - "documentation":"

    The test's parameters, such as test framework parameters and fixture settings. Parameters are represented by name-value pairs of strings.

    For all tests:

    • app_performance_monitoring: Performance monitoring is enabled by default. Set this parameter to false to disable it.

    For Appium tests (all types):

    • appium_version: The Appium version. Currently supported values are 1.6.5 (and later), latest, and default.

      • latest runs the latest Appium version supported by Device Farm (1.9.1).

      • For default, Device Farm selects a compatible version of Appium for the device. The current behavior is to run 1.7.2 on Android devices and iOS 9 and earlier and 1.7.2 for iOS 10 and later.

      • This behavior is subject to change.

    For fuzz tests (Android only):

    • event_count: The number of events, between 1 and 10000, that the UI fuzz test should perform.

    • throttle: The time, in ms, between 0 and 1000, that the UI fuzz test should wait between events.

    • seed: A seed to use for randomizing the UI fuzz test. Using the same seed value between tests ensures identical event sequences.

    For Instrumentation:

    • filter: A test filter string. Examples:

      • Running a single test case: com.android.abc.Test1

      • Running a single test: com.android.abc.Test1#smoke

      • Running multiple tests: com.android.abc.Test1,com.android.abc.Test2

    For XCTest and XCTestUI:

    • filter: A test filter string. Examples:

      • Running a single test class: LoginTests

      • Running a multiple test classes: LoginTests,SmokeTests

      • Running a single test: LoginTests/testValid

      • Running multiple tests: LoginTests/testValid,LoginTests/testInvalid

    " + "documentation":"

    The test's parameters, such as test framework parameters and fixture settings. Parameters are represented by name-value pairs of strings.

    For fuzz tests (Android only):

    • event_count: The number of events, between 1 and 10000, that the UI fuzz test should perform.

    • throttle: The time, in ms, between 0 and 1000, that the UI fuzz test should wait between events.

    • seed: A seed to use for randomizing the UI fuzz test. Using the same seed value between tests ensures identical event sequences.

    For Instrumentation:

    • filter: A test filter string. Examples:

      • Running a single test case: com.android.abc.Test1

      • Running a single test: com.android.abc.Test1#smoke

      • Running multiple tests: com.android.abc.Test1,com.android.abc.Test2

    For XCTest and XCTestUI:

    • filter: A test filter string. Examples:

      • Running a single test class: LoginTests

      • Running a multiple test classes: LoginTests,SmokeTests

      • Running a single test: LoginTests/testValid

      • Running multiple tests: LoginTests/testValid,LoginTests/testInvalid

    " } }, "documentation":"

    Represents test settings. This data structure is passed in as the test parameter to ScheduleRun. For an example of the JSON request syntax, see ScheduleRun.

    " @@ -5268,6 +5426,66 @@ "key":{"shape":"String"}, "value":{"shape":"String"} }, + "TestReport":{ + "type":"structure", + "members":{ + "message":{ + "shape":"ReportMessage", + "documentation":"

    A message associated with the test report.

    " + }, + "metrics":{ + "shape":"TestReportMetrics", + "documentation":"

    The aggregated test-level metrics for the job.

    " + }, + "testDetailsUrl":{ + "shape":"SensitiveURL", + "documentation":"

    A URL to the detailed test results.

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

    Contains aggregated test-level metrics for a job.

    " + }, + "TestReportMetrics":{ + "type":"structure", + "members":{ + "testsTotal":{ + "shape":"Integer", + "documentation":"

    The total number of tests in the job.

    " + }, + "testsPassed":{ + "shape":"Integer", + "documentation":"

    The number of tests that passed.

    " + }, + "testsFailed":{ + "shape":"Integer", + "documentation":"

    The number of tests that failed.

    " + }, + "testsSkipped":{ + "shape":"Integer", + "documentation":"

    The number of tests that were skipped.

    " + }, + "testsErrored":{ + "shape":"Integer", + "documentation":"

    The number of tests that errored.

    " + }, + "testsOther":{ + "shape":"Integer", + "documentation":"

    The number of tests with other result types.

    " + }, + "testsPassedPercentage":{ + "shape":"Double", + "documentation":"

    The percentage of tests that passed.

    " + }, + "totalTestExecutionDurationSeconds":{ + "shape":"Double", + "documentation":"

    The total execution duration of all tests in the job, in seconds.

    " + }, + "medianTestExecutionDurationSeconds":{ + "shape":"Double", + "documentation":"

    The median execution duration of tests in the job, in seconds.

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

    Contains aggregated metrics across all tests in a job.

    " + }, "TestType":{ "type":"string", "enum":[ diff --git a/services/devopsagent/pom.xml b/services/devopsagent/pom.xml index 4ed4c2c76a19..0ec9d5eceb2f 100644 --- a/services/devopsagent/pom.xml +++ b/services/devopsagent/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT devopsagent AWS Java SDK :: Services :: Dev Ops Agent diff --git a/services/devopsagent/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/devopsagent/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b293b962285f --- /dev/null +++ b/services/devopsagent/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aidevops-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aidevops.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/devopsagent/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/devopsagent/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 09d5fa8448a0..000000000000 --- a/services/devopsagent/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://aidevops-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://aidevops.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/devopsagent/src/main/resources/codegen-resources/service-2.json b/services/devopsagent/src/main/resources/codegen-resources/service-2.json index 50ac694bf588..bfe6c552973a 100644 --- a/services/devopsagent/src/main/resources/codegen-resources/service-2.json +++ b/services/devopsagent/src/main/resources/codegen-resources/service-2.json @@ -169,8 +169,8 @@ {"shape":"ConflictException"}, {"shape":"InternalServerException"}, {"shape":"AccessDeniedException"}, - {"shape":"ThrottlingException"}, {"shape":"InvalidParameterException"}, + {"shape":"ThrottlingException"}, {"shape":"ResourceNotFoundException"} ], "documentation":"

    Creates a Private Connection to a target resource.

    ", @@ -1245,6 +1245,29 @@ "documentation":"

    Updates the information of an existing AgentSpace.

    ", "endpoint":{"hostPrefix":"cp."} }, + "UpdateApprovalAction":{ + "name":"UpdateApprovalAction", + "http":{ + "method":"POST", + "requestUri":"/agents/agent-space/{agentSpaceId}/approvals/{approvalId}/update-action", + "responseCode":200 + }, + "input":{"shape":"UpdateApprovalActionRequest"}, + "output":{"shape":"UpdateApprovalActionResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ContentSizeExceededException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"} + ], + "documentation":"

    Updates an approval request with the terminal decision (APPROVED or REJECTED). A single operation handles both verbs via the action enum.

    ", + "endpoint":{"hostPrefix":"dp."} + }, "UpdateAsset":{ "name":"UpdateAsset", "http":{ @@ -1499,6 +1522,14 @@ "accountType":{ "shape":"MonitorAccountType", "documentation":"

    Account Type 'monitor' for AIDevOps monitoring.

    " + }, + "agentElevatedRoleArn":{ + "shape":"RoleArn", + "documentation":"

    Optional IAM role ARN to be assumed by AIDevOps for elevated directed actions on behalf of the customer. Used for mutating operations gated by elevatedActionsEnabled on the AgentSpace. When not provided, only non-elevated directed actions are available for this AWS account.

    " + }, + "agentElevatedRoleArnStatus":{ + "shape":"ValidationStatus", + "documentation":"

    Validation status of the agentElevatedRoleArn. Updated asynchronously after the customer registers an elevated role. Possible values: PENDING_CONFIRMATION (validation in progress), VALID (role validated), INVALID (validation failed).

    " } }, "documentation":"

    Configuration for AWS monitor account integration, allowing AIDevOps to monitor AWS resources.

    " @@ -1637,6 +1668,10 @@ "agentSpaceId":{ "shape":"AgentSpaceId", "documentation":"

    The unique identifier of the AgentSpace

    " + }, + "preferences":{ + "shape":"AgentSpacePreferences", + "documentation":"

    The preferences configured on the agent space. Preferences that are not set take their default values.

    " } }, "documentation":"

    Represents a complete AgentSpace with all its properties, timestamps, encryption settings, and unique identifier.

    " @@ -1646,6 +1681,11 @@ "documentation":"

    Unique identifier for an agent space (allows alphanumeric characters and hyphens; 1-64 characters)

    ", "pattern":"[a-zA-Z0-9-]{1,64}" }, + "AgentSpaceIdentifier":{ + "type":"string", + "max":2048, + "min":1 + }, "AgentSpaceList":{ "type":"list", "member":{"shape":"AgentSpace"}, @@ -1658,12 +1698,119 @@ "min":1, "pattern":"[\\p{L}\\p{N}\\p{P}\\p{S}\\p{Z}]+" }, + "AgentSpacePreferenceKey":{ + "type":"string", + "documentation":"

    The key of a preference that can be configured on an agent space. The `elevatedActionsEnabled` key controls whether elevated directed actions are permitted in the agent space. Elevated directed actions are mutating operations that also require per-action operator approval, and default to `false` when not set.

    ", + "enum":["elevatedActionsEnabled"] + }, + "AgentSpacePreferences":{ + "type":"map", + "key":{"shape":"AgentSpacePreferenceKey"}, + "value":{"shape":"Boolean"}, + "documentation":"

    The preferences configured on an agent space, keyed by preference key. Each key must be a recognized preference key; unrecognized keys are rejected.

    ", + "max":25, + "min":0 + }, "ApiKeyValue":{ "type":"string", "documentation":"

    API Key Value for service.

    ", "min":1, "sensitive":true }, + "ApprovalAction":{ + "type":"structure", + "members":{ + "toolUseId":{ + "shape":"ToolUseId", + "documentation":"

    Identifier of the specific paused tool invocation that requested approval. Correlates the approval decision back to the paused invocation.

    " + }, + "interruptId":{ + "shape":"InterruptId", + "documentation":"

    An opaque resume identifier issued by the service when an agent execution pauses for approval. Provide it when resuming so the service can resume the correct paused execution.

    " + }, + "approvalId":{ + "shape":"ApprovalId", + "documentation":"

    Identifier of the approval request being resolved.

    " + }, + "buttonText":{ + "shape":"ButtonText", + "documentation":"

    Optional display text of the UI control the user chose (for example, \"Approve Exact\", \"Approve Broader\", or \"Reject\"), provided as auxiliary decision context.

    " + }, + "action":{ + "shape":"ApprovalActionType", + "documentation":"

    The action taken on the approval request — APPROVED or REJECTED.

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

    An approval decision supplied when resuming a paused agent execution. When an agent execution pauses to request approval for an elevated action, SendMessage streams an approval request carrying interrupt identifiers. This structure carries the decision back to the service — which paused tool invocation is being resumed, the opaque interrupt identifier that resumes it, the identifier of the approval request being resolved, optional display text of the control the user chose, and the action taken (APPROVED or REJECTED) — so the service can resume the paused execution. All members are optional on the wire; service-side validation is applied against the populated subset.

    " + }, + "ApprovalActionType":{ + "type":"string", + "documentation":"

    The action to take on an approval request — APPROVED or REJECTED.

    ", + "enum":[ + "APPROVED", + "REJECTED" + ] + }, + "ApprovalArgumentPins":{ + "type":"map", + "key":{"shape":"ApprovalPinKey"}, + "value":{"shape":"ApprovalPinValue"}, + "documentation":"

    Map of argument pin keys to pinned values used to narrow an ApprovalPattern.

    ", + "max":20, + "min":0 + }, + "ApprovalId":{ + "type":"string", + "documentation":"

    The service-generated unique identifier of the approval request, formatted as a version 7 UUID (RFC 9562) in the canonical 8-4-4-4-12 hexadecimal representation.

    ", + "pattern":"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-7[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}" + }, + "ApprovalPattern":{ + "type":"structure", + "required":[ + "tool", + "argumentPins" + ], + "members":{ + "tool":{ + "shape":"ToolIdentifier", + "documentation":"

    Identifier of the tool the pattern applies to (e.g. `use_aws` for AWS actions, or a third-party tool name).

    " + }, + "argumentPins":{ + "shape":"ApprovalArgumentPins", + "documentation":"

    Argument constraints that narrow which tool invocations the pattern matches. For AWS tools, the map must include `operation` (the IAM action, e.g. `ec2:AuthorizeSecurityGroupIngress`) and `resource_arn` (the resource ARN or ARN glob); additional narrowing arguments go in further pin keys. The same `{tool, argumentPins}` shape is used uniformly for AWS and third-party tools, with tool-specific keys for third-party tools. Requests whose argument pins are collectively too large are rejected with a ValidationException.

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

    Tool-invocation pattern primitive used to express both an agent-requested approval and a finalized approval. The primitive is uniform across AWS and third-party tools: a tool identifier plus a map of argument pins that narrow which invocations the pattern matches.

    " + }, + "ApprovalPinKey":{ + "type":"string", + "documentation":"

    Argument pin key in an ApprovalPattern (e.g. `operation`, `resource_arn`).

    ", + "max":128, + "min":1 + }, + "ApprovalPinValue":{ + "type":"string", + "documentation":"

    Argument pin value in an ApprovalPattern.

    ", + "max":131072, + "min":1 + }, + "ApprovalReason":{ + "type":"string", + "documentation":"

    Free-text rationale for an approval rejection.

    ", + "max":1024, + "min":0 + }, + "ApprovalStatus":{ + "type":"string", + "documentation":"

    Lifecycle status of an approval request, distinct from the action verb. State machine: PENDING (awaiting a decision) -> APPROVED (the action was APPROVED; redeemable until revoked or fully redeemed) or REJECTED (the action was REJECTED; terminal). APPROVED -> REDEEMED (consumed by a credential mint at least once; non-single-use approvals stay re-redeemable until expiry) or REVOKED (administratively invalidated; terminal).

    ", + "enum":[ + "PENDING", + "APPROVED", + "REJECTED", + "REVOKED", + "REDEEMED" + ] + }, "Asset":{ "type":"structure", "required":[ @@ -1848,7 +1995,7 @@ "AssetFileText":{ "type":"string", "documentation":"

    Text file content

    ", - "max":1572864, + "max":6291456, "min":0 }, "AssetIdList":{ @@ -1868,7 +2015,7 @@ "members":{ "url":{ "shape":"AssetContentUrl", - "documentation":"

    The source URL to import asset content from

    " + "documentation":"

    The source URL to import asset content from.

    " } }, "documentation":"

    Content for an asset sourced from an external URL.

    " @@ -2138,12 +2285,22 @@ "type":"boolean", "box":true }, + "ButtonText":{ + "type":"string", + "documentation":"

    Optional display text of the UI control the user chose (for example, \"Approve Exact\", \"Approve Broader\", or \"Reject\"), provided as auxiliary decision context.

    ", + "max":256, + "min":1 + }, "CapabilityConfiguration":{ "type":"structure", "members":{ "enabled":{ "shape":"Boolean", "documentation":"

    Whether the capability is enabled.

    " + }, + "triggerFilterGroups":{ + "shape":"TriggerFilterGroups", + "documentation":"

    Optional trigger filter groups. Evaluated only when enabled=true; retained while the capability is disabled, so re-enabling restores the prior trigger behavior.

    " } }, "documentation":"

    Capability configuration for the AWS DevOps Agent.

    " @@ -2191,7 +2348,9 @@ "ChatExecutionId":{ "type":"string", "documentation":"

    Chat execution identifier — must be a valid UUID

    ", - "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + "max":50, + "min":32, + "pattern":"[A-Za-z0-9_-]+" }, "ChatExecutionList":{ "type":"list", @@ -2270,6 +2429,10 @@ "tags":{ "shape":"Tags", "documentation":"

    Tags to add to the AgentSpace at creation time.

    " + }, + "preferences":{ + "shape":"AgentSpacePreferences", + "documentation":"

    The preferences to configure on the agent space. Preferences not provided take their default values.

    " } }, "documentation":"

    Input for creating a new AgentSpace.

    " @@ -2302,7 +2465,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2360,7 +2523,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space where the asset will be created

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2411,7 +2574,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space where the task will be created

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2437,13 +2600,19 @@ "documentation":"

    The priority level of the task

    " }, "clientToken":{ - "shape":"String", + "shape":"CreateBacklogTaskRequestClientTokenString", "documentation":"

    Client-provided token for idempotent operations

    ", "idempotencyToken":true } }, "documentation":"

    Request structure for creating a new backlog task

    " }, + "CreateBacklogTaskRequestClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, "CreateBacklogTaskResponse":{ "type":"structure", "required":["task"], @@ -2460,7 +2629,8 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", + "documentation":"

    The unique identifier for the agent space where the chat will be created.

    ", "location":"uri", "locationName":"agentSpaceId" }, @@ -2587,7 +2757,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space where the Trigger will be created

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2618,8 +2788,9 @@ }, "CreateTriggerRequestClientTokenString":{ "type":"string", - "max":128, - "min":1 + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" }, "CreateTriggerResponse":{ "type":"structure", @@ -2732,7 +2903,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2765,7 +2936,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -2823,7 +2994,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the Trigger

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3244,7 +3415,8 @@ "RUNNING", "STOPPED", "CANCELED", - "TIMED_OUT" + "TIMED_OUT", + "WAITING" ] }, "FailureMessage":{ @@ -3349,7 +3521,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3401,7 +3573,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3451,7 +3623,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3525,7 +3697,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the task

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3584,7 +3756,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the recommendation

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3648,7 +3820,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the Trigger

    ", "location":"uri", "locationName":"agentSpaceId" @@ -3701,7 +3873,10 @@ }, "runtimeRoleArn":{ "shape":"RoleArn", - "documentation":"

    Optional role ARN that AIDevOps assumes at runtime for automatic verification testing and VPC connectivity on this association.

    " + "documentation":"

    Optional role ARN that AIDevOps assumes at runtime for automatic verification testing and VPC connectivity on this association.

    ", + "deprecated":true, + "deprecatedMessage":"Superseded by the ReleaseManagement association. Configure the runtime role on the ReleaseManagement association and reference it via releaseManagementAssociationId.", + "deprecatedSince":"2026-08-04" } }, "documentation":"

    Configuration for GitHub repository integration.

    " @@ -3727,7 +3902,10 @@ }, "runtimeRoleArn":{ "shape":"RoleArn", - "documentation":"

    Optional role ARN that AIDevOps assumes at runtime for automatic verification testing and VPC connectivity on this association.

    " + "documentation":"

    Optional role ARN that AIDevOps assumes at runtime for automatic verification testing and VPC connectivity on this association.

    ", + "deprecated":true, + "deprecatedMessage":"Superseded by the ReleaseManagement association. Configure the runtime role on the ReleaseManagement association and reference it via releaseManagementAssociationId.", + "deprecatedSince":"2026-08-04" } }, "documentation":"

    Configuration for GitLab project integration.

    " @@ -3749,7 +3927,7 @@ "documentation":"

    Type of GitLab access token

    " }, "tokenValue":{ - "shape":"GitLabDetailsTokenValueString", + "shape":"GitLabTokenValue", "documentation":"

    GitLab access token value

    " }, "groupId":{ @@ -3763,12 +3941,6 @@ "type":"string", "pattern":"https://[a-zA-Z0-9]([a-zA-Z0-9.-]*[a-zA-Z0-9])?(?::[0-9]{1,5})?/?" }, - "GitLabDetailsTokenValueString":{ - "type":"string", - "documentation":"

    Token value for authentication.

    ", - "pattern":"[a-zA-Z0-9._-]+", - "sensitive":true - }, "GitLabTokenType":{ "type":"string", "documentation":"

    Type of GitLab access token.

    ", @@ -3777,6 +3949,11 @@ "group" ] }, + "GitLabTokenValue":{ + "type":"string", + "pattern":"[a-zA-Z0-9._-]+", + "sensitive":true + }, "GithubRepoOwnerType":{ "type":"string", "documentation":"

    Type of GitHub repository owner.

    ", @@ -4101,6 +4278,12 @@ "fault":true, "retryable":{"throttling":false} }, + "InterruptId":{ + "type":"string", + "documentation":"

    An opaque resume identifier issued by the service when an agent execution pauses for approval. The service emits this identifier in the streamed approval request; provide the same value on the resuming SendMessage so the service can resume the paused execution. The format is opaque — bounded for safe transit but intentionally not pattern-validated.

    ", + "max":256, + "min":1 + }, "InvalidParameterException":{ "type":"structure", "required":["message"], @@ -4237,7 +4420,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4342,7 +4525,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4394,7 +4577,7 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space to list assets from

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4514,7 +4697,7 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the tasks

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4568,7 +4751,8 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", + "documentation":"

    The unique identifier for the agent space to list chats from.

    ", "location":"uri", "locationName":"agentSpaceId" }, @@ -4625,7 +4809,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4665,7 +4849,7 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4718,7 +4902,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the execution

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4844,7 +5028,7 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the recommendations

    ", "location":"uri", "locationName":"agentSpaceId" @@ -4953,7 +5137,7 @@ }, "ListTagsForResourceRequestResourceArnString":{ "type":"string", - "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service)/[a-zA-Z0-9-]+" + "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service|private-connection)/[a-zA-Z0-9_-]+" }, "ListTagsForResourceResponse":{ "type":"structure", @@ -4970,7 +5154,7 @@ "required":["agentSpaceId"], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space whose Triggers should be listed

    ", "location":"uri", "locationName":"agentSpaceId" @@ -5194,13 +5378,22 @@ "tools":{ "shape":"MCPToolsList", "documentation":"

    List of MCP tools can be used with the association.

    " + }, + "toolDetails":{ + "shape":"MCPToolDetailsList", + "documentation":"

    List of MCP tools with their access categorization. When provided, the tool names must match those in the tools member.

    " } }, "documentation":"

    Configuration for Model Context Protocol (MCP) server integration.

    " }, "MCPServerDatadogConfiguration":{ "type":"structure", - "members":{}, + "members":{ + "enabledElevatedTools":{ + "shape":"MCPToolDetailsList", + "documentation":"

    The subset of elevated-access tools enabled for this integration.

    " + } + }, "documentation":"

    Mixin for webhook update support.

    " }, "MCPServerDetails":{ @@ -5260,6 +5453,10 @@ "tools":{ "shape":"MCPToolsList", "documentation":"

    List of MCP tools that can be used.

    " + }, + "enabledElevatedTools":{ + "shape":"MCPToolDetailsList", + "documentation":"

    The subset of elevated-access tools enabled for this integration.

    " } }, "documentation":"

    Configuration for Grafana MCP server integration, used with an AWS-hosted MCP server.

    " @@ -5476,6 +5673,10 @@ "tools":{ "shape":"MCPToolsList", "documentation":"

    List of MCP tools available for the association.

    " + }, + "toolDetails":{ + "shape":"MCPToolDetailsList", + "documentation":"

    List of MCP tools with their access categorization. When provided, the tool names must match those in the tools member.

    " } }, "documentation":"

    Configuration for SigV4-authenticated MCP server integration.

    " @@ -5520,6 +5721,33 @@ "members":{}, "documentation":"

    Mixin for webhook update support.

    " }, + "MCPToolDetail":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{ + "shape":"MCPToolDetailNameString", + "documentation":"

    The name of the MCP tool.

    " + }, + "toolClassification":{ + "shape":"ToolClassification", + "documentation":"

    The access categorization of the MCP tool.

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

    An MCP tool together with its access categorization.

    " + }, + "MCPToolDetailNameString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "MCPToolDetailsList":{ + "type":"list", + "member":{"shape":"MCPToolDetail"}, + "max":500, + "min":0 + }, "MCPToolsList":{ "type":"list", "member":{"shape":"MCPToolsListMemberString"}, @@ -5571,6 +5799,11 @@ "type":"string", "pattern":"[0-9]+" }, + "NewRelicApiKey":{ + "type":"string", + "pattern":"NRAK-[A-Z0-9]+", + "sensitive":true + }, "NewRelicApiKeyConfig":{ "type":"structure", "required":[ @@ -5580,7 +5813,7 @@ ], "members":{ "apiKey":{ - "shape":"NewRelicApiKeyConfigApiKeyString", + "shape":"NewRelicApiKey", "documentation":"

    New Relic User API Key

    " }, "accountId":{ @@ -5612,13 +5845,6 @@ "min":3, "pattern":"[0-9]+" }, - "NewRelicApiKeyConfigApiKeyString":{ - "type":"string", - "documentation":"

    API Key Value for service.

    ", - "min":1, - "pattern":"NRAK-[A-Z0-9]+", - "sensitive":true - }, "NewRelicApplicationIds":{ "type":"list", "member":{"shape":"NewRelicApplicationIdsMemberString"}, @@ -5642,7 +5868,8 @@ "documentation":"

    The NewRelic region (determines API endpoint).

    ", "enum":[ "US", - "EU" + "EU", + "JP" ] }, "NewRelicServiceAuthorizationConfig":{ @@ -5799,6 +6026,17 @@ "member":{"shape":"String"}, "documentation":"

    List of pager duty services available for the association.

    " }, + "PatternFilter":{ + "type":"structure", + "required":["patterns"], + "members":{ + "patterns":{ + "shape":"TriggerRegexPatternList", + "documentation":"

    Anchored full-match regex patterns. The condition passes when the value matches at least one pattern.

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

    A regex-based match condition. Passes when the value matches any pattern.

    " + }, "PendingMessage":{ "type":"structure", "required":[ @@ -6528,7 +6766,9 @@ "type":"structure", "required":[ "serviceId", - "serviceType" + "serviceType", + "createdAt", + "updatedAt" ], "members":{ "serviceId":{ @@ -6558,6 +6798,14 @@ "privateConnectionName":{ "shape":"PrivateConnectionName", "documentation":"

    The name of the private connection used for VPC connectivity.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the service was registered.

    " + }, + "updatedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the service was last updated.

    " } }, "documentation":"

    Represents a registered service with its configuration and accessible resources.

    " @@ -7046,7 +7294,11 @@ }, "userActionResponse":{ "shape":"String", - "documentation":"

    Response to a UI prompt (not a text conversation message). Operator App SDK clients set this to the control-string sentinel `\"APPROVAL_ACTION\"` when the request is resuming a paused tool call after an operator approval decision; in that case the structured decision context lives on the sibling `approvalAction` member and the chat agent reads from there. Preserved as a String for back-compat: pre-typed-approval clients still encode arbitrary UI-prompt responses as JSON in this field, and the chat agent parses them out during the transition.

    " + "documentation":"

    Response to a UI prompt (not a text conversation message). Set this to the sentinel value `\"APPROVAL_ACTION\"` when the request is resuming a paused execution after an approval decision; in that case the structured decision is provided on the sibling `approvalAction` member. Preserved as a String for backward compatibility: clients that predate the typed approval field may still encode UI-prompt responses as JSON in this field.

    " + }, + "approvalAction":{ + "shape":"ApprovalAction", + "documentation":"

    An approval decision supplied when resuming a paused agent execution. When an agent execution pauses to request approval for an elevated action, SendMessage streams an approval request carrying interrupt identifiers. To resume the paused execution, call SendMessage again with `userActionResponse` set to `\"APPROVAL_ACTION\"` and this member populated with those identifiers and the decision (APPROVED or REJECTED). Optional; omit it for messages that are not resuming an approval.

    " } }, "documentation":"

    Context object for additional message metadata

    " @@ -7119,7 +7371,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The agent space identifier

    ", "location":"uri", "locationName":"agentSpaceId" @@ -7146,6 +7398,10 @@ "assetIds":{ "shape":"AssetIdList", "documentation":"

    Optional list of asset identifiers to attach to the message

    " + }, + "modelTier":{ + "shape":"String", + "documentation":"

    Optional model tier selection. Valid values: smart, balanced, fast. Absent or unrecognized values default to balanced.

    " } }, "documentation":"

    Request structure for sending a chat message

    " @@ -7615,6 +7871,21 @@ "min":1, "pattern":"(\\*|[a-z]{2,4}(-[a-z]+)+-\\d+)" }, + "SlackBidirectionalConfiguration":{ + "type":"structure", + "required":["roleArn"], + "members":{ + "roleArn":{ + "shape":"RoleArn", + "documentation":"

    IAM role ARN that AWS DevOps Agent assumes to exchange messages with your Slack workspace on behalf of this association.

    " + }, + "enabled":{ + "shape":"Boolean", + "documentation":"

    Whether bidirectional communication is enabled for this association. When you set this value to true, you can mention the agent in a configured Slack channel and it responds in that channel. When you omit this value or set it to false, the agent ignores mentions and only sends notifications.

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

    Configuration for bidirectional Slack communication.

    " + }, "SlackChannel":{ "type":"structure", "required":["channelId"], @@ -7655,6 +7926,10 @@ "transmissionTarget":{ "shape":"SlackTransmissionTarget", "documentation":"

    Transmission targets for agent notifications

    " + }, + "bidirectional":{ + "shape":"SlackBidirectionalConfiguration", + "documentation":"

    Optional bidirectional communication configuration. Supply this configuration and set enabled to true so you can interact with the agent directly from Slack.

    " } }, "documentation":"

    Configuration for Slack workspace integration.

    " @@ -7701,14 +7976,22 @@ }, "assumableRoleArn":{ "shape":"RoleArn", - "documentation":"

    Role ARN to be assumed by AIDevOps to operate on behalf of customer.

    " + "documentation":"

    Role ARN to be assumed by AIDevOps to operate on behalf of customer. To set this role ARN on AssociateService or UpdateAssociation, the caller must have at least the iam:PassRole permission on arn:aws:iam::<account-id>:role/* in the caller's own account, with the condition iam:PassedToService set to aidevops.amazonaws.com. A broader iam:PassRole grant also satisfies this requirement.

    " }, "externalId":{ "shape":"String", "documentation":"

    External ID for additional security when assuming the role. Used to prevent the confused deputy problem.

    " + }, + "agentElevatedRoleArn":{ + "shape":"RoleArn", + "documentation":"

    Optional IAM role ARN to be assumed by AIDevOps for elevated directed actions on behalf of the customer. Used for mutating operations gated by elevatedActionsEnabled on the AgentSpace. When not provided, only non-elevated directed actions are available for this AWS account. Setting this role is subject to the same minimum iam:PassRole requirement described on assumableRoleArn.

    " + }, + "agentElevatedRoleArnStatus":{ + "shape":"ValidationStatus", + "documentation":"

    Validation status of the agentElevatedRoleArn. Updated asynchronously after the customer registers an elevated role. Possible values: PENDING_CONFIRMATION (validation in progress), VALID (role validated), INVALID (validation failed).

    " } }, - "documentation":"

    Configuration for AWS source account integration. Note: passRole check on 'assumableRoleArn' is not supported.

    " + "documentation":"

    Configuration for AWS source account integration. Setting the role ARNs on this configuration requires the caller to have at least the iam:PassRole permission (see assumableRoleArn).

    " }, "SourceAwsConfigurationAccountIdString":{ "type":"string", @@ -7759,7 +8042,7 @@ }, "TagResourceRequestResourceArnString":{ "type":"string", - "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service)/[a-zA-Z0-9-]+" + "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service|private-connection)/[a-zA-Z0-9_-]+" }, "TagResourceResponse":{ "type":"structure", @@ -7948,7 +8231,8 @@ "FAILED", "TIMED_OUT", "CANCELED", - "SKIPPED" + "SKIPPED", + "WAITING" ] }, "TaskType":{ @@ -7979,6 +8263,26 @@ "retryable":{"throttling":false} }, "Timestamp":{"type":"timestamp"}, + "ToolClassification":{ + "type":"string", + "enum":[ + "READ_ONLY", + "MUTATIVE", + "DESTRUCTIVE" + ] + }, + "ToolIdentifier":{ + "type":"string", + "documentation":"

    Identifier of an approval-target tool — for example `use_aws` for AWS actions, or a third-party tool name.

    ", + "max":256, + "min":1 + }, + "ToolUseId":{ + "type":"string", + "documentation":"

    Identifier of the specific paused tool invocation that requested approval. Correlates the approval decision back to the paused invocation.

    ", + "max":256, + "min":1 + }, "Trigger":{ "type":"structure", "required":[ @@ -8044,11 +8348,61 @@ "documentation":"

    Defines the firing condition for a Trigger

    ", "union":true }, + "TriggerEvent":{ + "type":"string", + "documentation":"

    Webhook events that can auto-trigger a capability. PULL_REQUEST_* events apply to RELEASE_READINESS_REVIEW; WORKFLOW_* events apply to RELEASE_SHEPHERDING.

    ", + "enum":[ + "PULL_REQUEST_READY_FOR_REVIEW", + "PULL_REQUEST_DRAFT" + ] + }, + "TriggerEventList":{ + "type":"list", + "member":{"shape":"TriggerEvent"}, + "documentation":"

    Webhook events that activate a trigger filter group.

    ", + "max":10, + "min":1 + }, + "TriggerFilterGroup":{ + "type":"structure", + "members":{ + "events":{ + "shape":"TriggerEventList", + "documentation":"

    Passes when the webhook event is one of the listed events.

    " + }, + "targetBranches":{ + "shape":"PatternFilter", + "documentation":"

    Passes when the change request target branch matches. Applicable to RELEASE_READINESS_REVIEW only.

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

    A group of trigger conditions. The group matches when ALL present conditions pass. A group cannot be empty: at least one condition must be present.

    " + }, + "TriggerFilterGroups":{ + "type":"list", + "member":{"shape":"TriggerFilterGroup"}, + "documentation":"

    Filter groups controlling when a capability auto-triggers. The capability triggers when ANY group matches. Absent = default trigger behavior (all applicable events trigger).

    ", + "max":5, + "min":1 + }, "TriggerList":{ "type":"list", "member":{"shape":"Trigger"}, "documentation":"

    List of Triggers

    " }, + "TriggerRegexPattern":{ + "type":"string", + "documentation":"

    A regex pattern matched against the entire value. Example: 'main' or 'release/.*'.

    ", + "max":256, + "min":1, + "pattern":"[^\\x00-\\x1F\\x7F-\\x9F]+" + }, + "TriggerRegexPatternList":{ + "type":"list", + "member":{"shape":"TriggerRegexPattern"}, + "documentation":"

    A list of anchored full-match regex patterns.

    ", + "max":20, + "min":1 + }, "TriggerStatus":{ "type":"string", "documentation":"

    The status of a Trigger

    ", @@ -8084,7 +8438,7 @@ }, "UntagResourceRequestResourceArnString":{ "type":"string", - "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service)/[a-zA-Z0-9-]+" + "pattern":"arn:aws:aidevops:[a-z0-9-]+:\\d{12}:(agentspace|service|private-connection)/[a-zA-Z0-9_-]+" }, "UntagResourceResponse":{ "type":"structure", @@ -8111,6 +8465,10 @@ "locale":{ "shape":"Locale", "documentation":"

    The updated locale for the AgentSpace, which determines the language used in agent responses.

    " + }, + "preferences":{ + "shape":"AgentSpacePreferences", + "documentation":"

    The preferences to configure on the agent space. When provided, this replaces the full set of configured preferences; preferences not included revert to their default values. When omitted, the current preferences are left unchanged.

    " } }, "documentation":"

    Input for updating an existing AgentSpace's properties. All fields except agentSpaceId are optional for partial updates.

    " @@ -8123,6 +8481,77 @@ }, "documentation":"

    Output containing the updated AgentSpace.

    " }, + "UpdateApprovalActionRequest":{ + "type":"structure", + "required":[ + "agentSpaceId", + "approvalId", + "action" + ], + "members":{ + "agentSpaceId":{ + "shape":"AgentSpaceIdentifier", + "documentation":"

    The agent space identifier — multi-tenant workspace scope. Bound from the request URI.

    ", + "location":"uri", + "locationName":"agentSpaceId" + }, + "approvalId":{ + "shape":"ApprovalId", + "documentation":"

    Identifier of the approval request being resolved. A UUID. Bound from the request URI.

    ", + "location":"uri", + "locationName":"approvalId" + }, + "action":{ + "shape":"ApprovalActionType", + "documentation":"

    The action to take on the approval request — APPROVED or REJECTED.

    " + }, + "finalPattern":{ + "shape":"ApprovalPattern", + "documentation":"

    The finalized pattern (tool + argumentPins) that scopes the approval. Required when `action` is APPROVED; must be absent when `action` is REJECTED. The pattern narrows, and must not widen, the invocation originally requested by the agent. This cross-field invariant is enforced by service-side validation.

    " + }, + "reason":{ + "shape":"ApprovalReason", + "documentation":"

    Optional free-text rationale for the decision. Permitted when `action` is REJECTED; ignored when `action` is APPROVED.

    " + }, + "ttlSeconds":{ + "shape":"UpdateApprovalActionRequestTtlSecondsInteger", + "documentation":"

    Approval lifetime in seconds, starting from when the decision is submitted. Required when `action` is APPROVED AND `singleUse` is false; must be absent when `action` is REJECTED or when `singleUse` is true (a single-use approval backs one executed action and the redemption window collapses). Cross-field invariants are enforced by service-side validation; the @range bound here is the operation-boundary check that always applies (a maximum of 4 hours).

    " + }, + "singleUse":{ + "shape":"Boolean", + "documentation":"

    Whether the approved action backs a single executed tool call (true) or is reusable within ttlSeconds (false). Required when `action` is APPROVED; must be absent when `action` is REJECTED. When true, ttlSeconds must be absent (the redemption window collapses to the single use). When false, ttlSeconds is required and bounds the reuse window. Cross-field invariants are enforced by service-side validation.

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

    Request structure for UpdateApprovalAction. Submits the terminal decision (APPROVED or REJECTED) against an approval request, optionally carrying the finalized pattern and time-to-live when the action is APPROVED, or a free-text rationale when the action is REJECTED. Cross-field invariants between `action` and the approve-only / reject-only members are enforced by service-side validation.

    " + }, + "UpdateApprovalActionRequestTtlSecondsInteger":{ + "type":"integer", + "box":true, + "max":14400, + "min":1 + }, + "UpdateApprovalActionResponse":{ + "type":"structure", + "required":[ + "approvalId", + "status" + ], + "members":{ + "approvalId":{ + "shape":"ApprovalId", + "documentation":"

    Identifier of the approval request that was resolved. Echoed back so the client can correlate the response with the request.

    " + }, + "status":{ + "shape":"ApprovalStatus", + "documentation":"

    Lifecycle status of the approval request immediately after submission. Expected post-submission states are APPROVED (when the action is APPROVED) or REJECTED (when the action is REJECTED); PENDING is not returned from this operation, and REVOKED and REDEEMED are reachable only via subsequent reads.

    " + }, + "expiresAt":{ + "shape":"Timestamp", + "documentation":"

    Absolute timestamp at which the approval expires. Set when status is APPROVED (computed as the submission time plus ttlSeconds); absent when status is REJECTED.

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

    Response structure for UpdateApprovalAction. Reports the post-submission lifecycle status of the approval request and, when applicable, the absolute expiry timestamp. The status is a lifecycle state distinct from the action verb — an APPROVED submission transitions the request to APPROVED status (live, redeemable); a REJECTED submission transitions it to REJECTED status (terminal).

    " + }, "UpdateAssetFileRequest":{ "type":"structure", "required":[ @@ -8132,7 +8561,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8189,7 +8618,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the asset

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8283,7 +8712,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the task

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8299,13 +8728,19 @@ "documentation":"

    Updated task status

    " }, "clientToken":{ - "shape":"String", + "shape":"UpdateBacklogTaskRequestClientTokenString", "documentation":"

    Client-provided token for idempotent operations

    ", "idempotencyToken":true } }, "documentation":"

    Request structure for updating a task

    " }, + "UpdateBacklogTaskRequestClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, "UpdateBacklogTaskResponse":{ "type":"structure", "required":["task"], @@ -8325,7 +8760,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the goal

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8341,13 +8776,19 @@ "documentation":"

    Update goal schedule state

    " }, "clientToken":{ - "shape":"String", + "shape":"UpdateGoalRequestClientTokenString", "documentation":"

    Client-provided token for idempotent operations

    ", "idempotencyToken":true } }, "documentation":"

    Request structure for updating a goal

    " }, + "UpdateGoalRequestClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, "UpdateGoalResponse":{ "type":"structure", "required":["goal"], @@ -8470,7 +8911,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the recommendation

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8490,13 +8931,19 @@ "documentation":"

    Additional context for recommendation

    " }, "clientToken":{ - "shape":"String", + "shape":"UpdateRecommendationRequestClientTokenString", "documentation":"

    A unique token that ensures idempotency of the request

    ", "idempotencyToken":true } }, "documentation":"

    Request structure for updating an existing recommendation

    " }, + "UpdateRecommendationRequestClientTokenString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, "UpdateRecommendationResponse":{ "type":"structure", "required":["recommendation"], @@ -8516,7 +8963,7 @@ ], "members":{ "agentSpaceId":{ - "shape":"AgentSpaceId", + "shape":"AgentSpaceIdentifier", "documentation":"

    The unique identifier for the agent space containing the Trigger

    ", "location":"uri", "locationName":"agentSpaceId" @@ -8541,8 +8988,9 @@ }, "UpdateTriggerRequestClientTokenString":{ "type":"string", - "max":128, - "min":1 + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" }, "UpdateTriggerResponse":{ "type":"structure", diff --git a/services/devopsguru/pom.xml b/services/devopsguru/pom.xml index 245d1f50e5bd..aca1f8b3f865 100644 --- a/services/devopsguru/pom.xml +++ b/services/devopsguru/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT devopsguru AWS Java SDK :: Services :: Dev Ops Guru diff --git a/services/devopsguru/src/main/resources/codegen-resources/customization.config b/services/devopsguru/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/devopsguru/src/main/resources/codegen-resources/customization.config +++ b/services/devopsguru/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/devopsguru/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/devopsguru/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..dc2394ce4b34 --- /dev/null +++ b/services/devopsguru/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devops-guru-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devops-guru-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devops-guru.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://devops-guru.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/devopsguru/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/devopsguru/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 14be786ab84f..000000000000 --- a/services/devopsguru/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devops-guru-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devops-guru-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://devops-guru.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://devops-guru.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/directconnect/pom.xml b/services/directconnect/pom.xml index e8c642174aa2..ba8b8aad2342 100644 --- a/services/directconnect/pom.xml +++ b/services/directconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT directconnect AWS Java SDK :: Services :: AWS Direct Connect diff --git a/services/directconnect/src/main/resources/codegen-resources/customization.config b/services/directconnect/src/main/resources/codegen-resources/customization.config index 747a898ef2d7..8b6d304ea12a 100644 --- a/services/directconnect/src/main/resources/codegen-resources/customization.config +++ b/services/directconnect/src/main/resources/codegen-resources/customization.config @@ -19,6 +19,5 @@ "DescribeConnectionLoa", "DescribeConnectionsOnInterconnect", "DescribeInterconnectLoa" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/directconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/directconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d164755ea136 --- /dev/null +++ b/services/directconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://directconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://directconnect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://directconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://directconnect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/directconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/directconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9af119ef4c8f..000000000000 --- a/services/directconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://directconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://directconnect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://directconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://directconnect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/directconnect/src/main/resources/codegen-resources/service-2.json b/services/directconnect/src/main/resources/codegen-resources/service-2.json index 08c6a8e2d0d7..1ab58756f724 100644 --- a/services/directconnect/src/main/resources/codegen-resources/service-2.json +++ b/services/directconnect/src/main/resources/codegen-resources/service-2.json @@ -119,12 +119,27 @@ "input":{"shape":"AssociateConnectionWithLagRequest"}, "output":{"shape":"Connection"}, "errors":[ + {"shape":"LimitExceededException"}, {"shape":"DirectConnectServerException"}, - {"shape":"DirectConnectClientException"}, - {"shape":"LimitExceededException"} + {"shape":"DirectConnectClientException"} ], "documentation":"

    Associates an existing connection with a link aggregation group (LAG). The connection is interrupted and re-established as a member of the LAG (connectivity to Amazon Web Services is interrupted). The connection must be hosted on the same Direct Connect endpoint as the LAG, and its bandwidth must match the bandwidth for the LAG. You can re-associate a connection that's currently associated with a different LAG; however, if removing the connection would cause the original LAG to fall below its setting for minimum number of operational connections, the request fails.

    Any virtual interfaces that are directly associated with the connection are automatically re-associated with the LAG. If the connection was originally associated with a different LAG, the virtual interfaces remain associated with the original LAG.

    For interconnects, any hosted connections are automatically re-associated with the LAG. If the interconnect was originally associated with a different LAG, the hosted connections remain associated with the original LAG.

    " }, + "AssociateConnectionsToResiliencyGroup":{ + "name":"AssociateConnectionsToResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AssociateConnectionsToResiliencyGroupRequest"}, + "output":{"shape":"AssociateConnectionsToResiliencyGroupResult"}, + "errors":[ + {"shape":"LimitExceededException"}, + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Associates one or more connections with the specified resiliency group. This operation is atomic: either all of the specified connections are associated, or the operation fails and no changes are made.

    " + }, "AssociateHostedConnection":{ "name":"AssociateHostedConnection", "http":{ @@ -375,6 +390,23 @@ ], "documentation":"

    Creates a public virtual interface. A virtual interface is the VLAN that transports Direct Connect traffic. A public virtual interface supports sending traffic to public services of Amazon Web Services such as Amazon S3.

    When creating an IPv6 public virtual interface (addressFamily is ipv6), leave the customer and amazon address fields blank to use auto-assigned IPv6 space. Custom IPv6 addresses are not supported.

    " }, + "CreateResiliencyGroup":{ + "name":"CreateResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateResiliencyGroupRequest"}, + "output":{"shape":"CreateResiliencyGroupResult"}, + "errors":[ + {"shape":"DuplicateTagKeysException"}, + {"shape":"TooManyTagsException"}, + {"shape":"LimitExceededException"}, + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Creates a resiliency group. A resiliency group lets you group Direct Connect connections together and manage them as a single unit to meet a target resiliency model.

    " + }, "CreateTransitVirtualInterface":{ "name":"CreateTransitVirtualInterface", "http":{ @@ -490,6 +522,20 @@ ], "documentation":"

    Deletes the specified link aggregation group (LAG). You cannot delete a LAG if it has active virtual interfaces or hosted connections.

    " }, + "DeleteResiliencyGroup":{ + "name":"DeleteResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteResiliencyGroupRequest"}, + "output":{"shape":"DeleteResiliencyGroupResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Deletes the specified resiliency group. Deletion is asynchronous: the resiliency group transitions through the deleting state before it reaches the deleted state. The response returns the resiliency group so you can observe its current state without a subsequent GetResiliencyGroup call.

    " + }, "DeleteVirtualInterface":{ "name":"DeleteVirtualInterface", "http":{ @@ -770,6 +816,20 @@ ], "documentation":"

    Disassociates a connection from a link aggregation group (LAG). The connection is interrupted and re-established as a standalone connection (the connection is not deleted; to delete the connection, use the DeleteConnection request). If the LAG has associated virtual interfaces or hosted connections, they remain associated with the LAG. A disassociated connection owned by an Direct Connect Partner is automatically converted to an interconnect.

    If disassociating the connection would cause the LAG to fall below its setting for minimum number of operational connections, the request fails, except when it's the last member of the LAG. If all connections are disassociated, the LAG continues to exist as an empty LAG with no physical connections.

    " }, + "DisassociateConnectionsFromResiliencyGroup":{ + "name":"DisassociateConnectionsFromResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DisassociateConnectionsFromResiliencyGroupRequest"}, + "output":{"shape":"DisassociateConnectionsFromResiliencyGroupResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Disassociates one or more connections from the specified resiliency group. This operation is atomic: either all of the specified connections are disassociated, or the operation fails and no changes are made.

    " + }, "DisassociateMacSecKey":{ "name":"DisassociateMacSecKey", "http":{ @@ -784,6 +844,62 @@ ], "documentation":"

    Removes the association between a MAC Security (MACsec) security key and a Direct Connect connection.

    " }, + "GetResiliencyGroup":{ + "name":"GetResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetResiliencyGroupRequest"}, + "output":{"shape":"GetResiliencyGroupResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Gets information about the specified resiliency group.

    " + }, + "ListResiliencyGroupAssociations":{ + "name":"ListResiliencyGroupAssociations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListResiliencyGroupAssociationsRequest"}, + "output":{"shape":"ListResiliencyGroupAssociationsResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Lists the connection associations for the specified resiliency group.

    " + }, + "ListResiliencyGroups":{ + "name":"ListResiliencyGroups", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListResiliencyGroupsRequest"}, + "output":{"shape":"ListResiliencyGroupsResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Lists the resiliency groups owned by your Amazon Web Services account in the current Amazon Web Services Region.

    " + }, + "ListVirtualInterfaceRoutes":{ + "name":"ListVirtualInterfaceRoutes", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListVirtualInterfaceRoutesRequest"}, + "output":{"shape":"ListVirtualInterfaceRoutesResponse"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Lists the routes for the specified virtual interface.

    Use the routeDirection filter to control which routes are returned:

    • accepted: routes received from the customer network over the virtual interface.

    • advertised: routes advertised to the customer network over the virtual interface.

    " + }, "ListVirtualInterfaceTestHistory":{ "name":"ListVirtualInterfaceTestHistory", "http":{ @@ -870,6 +986,20 @@ ], "documentation":"

    Updates the Direct Connect connection configuration.

    You can update the following parameters for a connection:

    • The connection name

    • The connection's MAC Security (MACsec) encryption mode.

    " }, + "UpdateConnectionsBillingMode":{ + "name":"UpdateConnectionsBillingMode", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateConnectionsBillingModeRequest"}, + "output":{"shape":"UpdateConnectionsBillingModeResponse"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Updates the billing mode for the specified Direct Connect connections. You can update the billing mode for up to 200 connections in a single request.

    " + }, "UpdateDirectConnectGateway":{ "name":"UpdateDirectConnectGateway", "http":{ @@ -912,6 +1042,20 @@ ], "documentation":"

    Updates the attributes of the specified link aggregation group (LAG).

    You can update the following LAG attributes:

    • The name of the LAG.

    • The value for the minimum number of connections that must be operational for the LAG itself to be operational.

    • The LAG's MACsec encryption mode.

      Amazon Web Services assigns this value to each connection which is part of the LAG.

    • The tags

    If you adjust the threshold value for the minimum number of operational connections, ensure that the new value does not cause the LAG to fall below the threshold and become non-operational.

    " }, + "UpdateResiliencyGroup":{ + "name":"UpdateResiliencyGroup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateResiliencyGroupRequest"}, + "output":{"shape":"UpdateResiliencyGroupResult"}, + "errors":[ + {"shape":"DirectConnectServerException"}, + {"shape":"DirectConnectClientException"} + ], + "documentation":"

    Updates the name of the specified resiliency group.

    " + }, "UpdateVirtualInterfaceAttributes":{ "name":"UpdateVirtualInterfaceAttributes", "http":{ @@ -1123,6 +1267,35 @@ } }, "AmazonAddress":{"type":"string"}, + "AsPathList":{ + "type":"list", + "member":{"shape":"LongAsn"} + }, + "AsPathSegment":{ + "type":"structure", + "members":{ + "pathType":{ + "shape":"AsPathType", + "documentation":"

    The type of the AS path segment.

    The valid values are seq (an ordered AS_SEQUENCE) and set (an unordered AS_SET).

    " + }, + "path":{ + "shape":"AsPathList", + "documentation":"

    The autonomous system (AS) numbers in the segment.

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

    A segment of an autonomous system (AS) path.

    " + }, + "AsPathSegmentList":{ + "type":"list", + "member":{"shape":"AsPathSegment"} + }, + "AsPathType":{ + "type":"string", + "enum":[ + "seq", + "set" + ] + }, "AssociateConnectionWithLagRequest":{ "type":"structure", "required":[ @@ -1140,6 +1313,36 @@ } } }, + "AssociateConnectionsToResiliencyGroupRequest":{ + "type":"structure", + "required":[ + "connectionIdentifiers", + "resiliencyGroupId" + ], + "members":{ + "connectionIdentifiers":{ + "shape":"ConnectionIdentifierList", + "documentation":"

    The IDs or ARNs of the connections to associate with the resiliency group.

    " + }, + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    " + } + } + }, + "AssociateConnectionsToResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroupAssociations":{ + "shape":"ResiliencyGroupAssociationList", + "documentation":"

    The connection associations for the resiliency group.

    " + } + } + }, "AssociateHostedConnectionRequest":{ "type":"structure", "required":[ @@ -1250,6 +1453,28 @@ "documentation":"

    Information about the associated gateway.

    " }, "AssociatedGatewayId":{"type":"string"}, + "AvailableBillingMode":{ + "type":"structure", + "members":{ + "billingMode":{ + "shape":"BillingMode", + "documentation":"

    The billing mode.

    " + }, + "availablePortSpeeds":{ + "shape":"AvailablePortSpeeds", + "documentation":"

    The port speeds available for the billing mode.

    " + }, + "includedRegions":{ + "shape":"IncludedRegionList", + "documentation":"

    The Amazon Web Services Regions included with the billing mode.

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

    Information about a billing mode available at an Direct Connect location.

    " + }, + "AvailableBillingModeList":{ + "type":"list", + "member":{"shape":"AvailableBillingMode"} + }, "AvailableMacSecPortSpeeds":{ "type":"list", "member":{"shape":"PortSpeed"} @@ -1343,10 +1568,31 @@ ] }, "Bandwidth":{"type":"string"}, + "BillingMode":{ + "type":"string", + "enum":[ + "PayAsYouGo", + "FlatRateTier1", + "FlatRateTier2", + "FlatRateTier3", + "FlatRateTier4", + "FlatRateTier5", + "PortPairFlatRateTier1", + "PortPairFlatRateTier2", + "PortPairFlatRateTier3", + "PortPairFlatRateTier4", + "PortPairFlatRateTier5" + ] + }, "BooleanFlag":{"type":"boolean"}, "CIDR":{"type":"string"}, "Cak":{"type":"string"}, "Ckn":{"type":"string"}, + "CommunityEntry":{"type":"string"}, + "CommunityList":{ + "type":"list", + "member":{"shape":"CommunityEntry"} + }, "ConfirmConnectionRequest":{ "type":"structure", "required":["connectionId"], @@ -1554,11 +1800,53 @@ "partnerInterconnectMacSecCapable":{ "shape":"PartnerInterconnectMacSecCapable", "documentation":"

    Indicates whether the interconnect hosting this connection supports MAC Security (MACsec).

    " + }, + "prefixPoolSizeIpv4":{ + "shape":"PrefixPoolSize", + "documentation":"

    The total number of inbound IPv4 route prefixes you can allocate across the virtual interfaces on the connection. Not applicable to hosted connections or interconnects.

    " + }, + "prefixPoolSizeIpv6":{ + "shape":"PrefixPoolSize", + "documentation":"

    The total number of inbound IPv6 route prefixes you can allocate across the virtual interfaces on the connection. Not applicable to hosted connections or interconnects.

    " + }, + "prefixPoolUnallocatedCountIpv4":{ + "shape":"PrefixPoolUnallocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes in the connection prefix pool not yet allocated to a virtual interface. Not applicable to hosted connections or interconnects.

    " + }, + "prefixPoolUnallocatedCountIpv6":{ + "shape":"PrefixPoolUnallocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes in the connection prefix pool not yet allocated to a virtual interface. Not applicable to hosted connections or interconnects.

    " + }, + "billingMode":{ + "shape":"BillingMode", + "documentation":"

    The billing mode of the connection.

    " } }, "documentation":"

    Information about an Direct Connect connection.

    " }, + "ConnectionArn":{ + "type":"string", + "max":1024, + "min":1 + }, "ConnectionId":{"type":"string"}, + "ConnectionIdList":{ + "type":"list", + "member":{"shape":"ConnectionId"}, + "max":200, + "min":1 + }, + "ConnectionIdentifier":{ + "type":"string", + "max":1024, + "min":1 + }, + "ConnectionIdentifierList":{ + "type":"list", + "member":{"shape":"ConnectionIdentifier"}, + "max":50, + "min":1 + }, "ConnectionList":{ "type":"list", "member":{"shape":"Connection"} @@ -1661,6 +1949,10 @@ "requestMACSec":{ "shape":"RequestMACSec", "documentation":"

    Indicates whether you want the connection to support MAC Security (MACsec).

    MAC Security (MACsec) is unavailable on hosted connections. For information about MAC Security (MACsec) prerequisites, see MAC Security in Direct Connect in the Direct Connect User Guide.

    " + }, + "billingMode":{ + "shape":"RequestBillingMode", + "documentation":"

    The billing mode for the connection.

    " } } }, @@ -1843,6 +2135,10 @@ "requestMACSec":{ "shape":"RequestMACSec", "documentation":"

    Indicates whether the connection will support MAC Security (MACsec).

    All connections in the LAG must be capable of supporting MAC Security (MACsec). For information about MAC Security (MACsec) prerequisties, see MACsec prerequisties in the Direct Connect User Guide.

    " + }, + "billingMode":{ + "shape":"RequestBillingMode", + "documentation":"

    The billing mode for the LAG.

    " } } }, @@ -1880,6 +2176,40 @@ } } }, + "CreateResiliencyGroupRequest":{ + "type":"structure", + "required":[ + "resiliencyGroupName", + "intendedResiliencyModel" + ], + "members":{ + "resiliencyGroupName":{ + "shape":"ResiliencyGroupName", + "documentation":"

    The name of the resiliency group.

    " + }, + "intendedResiliencyModel":{ + "shape":"ResiliencyModel", + "documentation":"

    The resiliency model that the resiliency group is intended to meet. The valid values are maximum-resiliency, high-resiliency, and basic-resiliency.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

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

    The tags to associate with the resiliency group.

    " + } + } + }, + "CreateResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroup":{ + "shape":"ResiliencyGroup", + "documentation":"

    Information about the resiliency group.

    " + } + } + }, "CreateTransitVirtualInterfaceRequest":{ "type":"structure", "required":[ @@ -2058,6 +2388,25 @@ } } }, + "DeleteResiliencyGroupRequest":{ + "type":"structure", + "required":["resiliencyGroupId"], + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + } + } + }, + "DeleteResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroup":{ + "shape":"ResiliencyGroup", + "documentation":"

    Information about the resiliency group.

    " + } + } + }, "DeleteVirtualInterfaceRequest":{ "type":"structure", "required":["virtualInterfaceId"], @@ -2496,6 +2845,10 @@ "shape":"StateChangeError", "documentation":"

    The error message if the state of an object failed to advance.

    " }, + "totalPrefixPoolAllocations":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The total number of inbound route prefixes allocated to the attachments on the Direct Connect gateway. The count combines the IPv4 and IPv6 address families.

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

    Information about a tag.

    " @@ -2709,6 +3062,36 @@ } } }, + "DisassociateConnectionsFromResiliencyGroupRequest":{ + "type":"structure", + "required":[ + "connectionIdentifiers", + "resiliencyGroupId" + ], + "members":{ + "connectionIdentifiers":{ + "shape":"ConnectionIdentifierList", + "documentation":"

    The IDs or ARNs of the connections to disassociate from the resiliency group.

    " + }, + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    " + } + } + }, + "DisassociateConnectionsFromResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroupAssociations":{ + "shape":"ResiliencyGroupAssociationList", + "documentation":"

    The connection associations for the resiliency group.

    " + } + } + }, "DisassociateMacSecKeyRequest":{ "type":"structure", "required":[ @@ -2759,6 +3142,25 @@ "transitGateway" ] }, + "GetResiliencyGroupRequest":{ + "type":"structure", + "required":["resiliencyGroupId"], + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + } + } + }, + "GetResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroup":{ + "shape":"ResiliencyGroup", + "documentation":"

    Information about the resiliency group.

    " + } + } + }, "HasLogicalRedundancy":{ "type":"string", "enum":[ @@ -2767,6 +3169,15 @@ "no" ] }, + "IdempotencyToken":{ + "type":"string", + "max":128, + "min":1 + }, + "IncludedRegionList":{ + "type":"list", + "member":{"shape":"Region"} + }, "Interconnect":{ "type":"structure", "members":{ @@ -2968,9 +3379,29 @@ "shape":"MacSecKeyList", "documentation":"

    The MAC Security (MACsec) security keys associated with the LAG.

    " }, + "prefixPoolSizeIpv4":{ + "shape":"PrefixPoolSize", + "documentation":"

    The total number of inbound IPv4 route prefixes you can allocate across the virtual interfaces on the LAG. Not applicable to LAGs that are interconnects and support hosted connections.

    " + }, + "prefixPoolSizeIpv6":{ + "shape":"PrefixPoolSize", + "documentation":"

    The total number of inbound IPv6 route prefixes you can allocate across the virtual interfaces on the LAG. Not applicable to LAGs that are interconnects and support hosted connections.

    " + }, + "prefixPoolUnallocatedCountIpv4":{ + "shape":"PrefixPoolUnallocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes in the LAG prefix pool not yet allocated to a virtual interface. Not applicable to LAGs that are interconnects and support hosted connections.

    " + }, + "prefixPoolUnallocatedCountIpv6":{ + "shape":"PrefixPoolUnallocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes in the LAG prefix pool not yet allocated to a virtual interface. Not applicable to LAGs that are interconnects and support hosted connections.

    " + }, "rateLimiterStatus":{ "shape":"RateLimiterStatus", "documentation":"

    The rate limiter status for the LAG, including how many rate limiters are in use and the maximum allowed.

    " + }, + "billingMode":{ + "shape":"BillingMode", + "documentation":"

    The billing mode of the LAG.

    " } }, "documentation":"

    Information about a link aggregation group (LAG).

    " @@ -3012,6 +3443,101 @@ "documentation":"

    The rate limiter limit has been exceeded for the connection. You cannot add more rate limiters to virtual interfaces on this connection.

    ", "exception":true }, + "ListResiliencyGroupAssociationsRequest":{ + "type":"structure", + "required":["resiliencyGroupId"], + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "maxResults":{ + "shape":"MaxResultSetSize", + "documentation":"

    The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.

    If MaxResults is given a value larger than 100, only 100 results are returned.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListResiliencyGroupAssociationsResult":{ + "type":"structure", + "members":{ + "items":{ + "shape":"ResiliencyGroupAssociationList", + "documentation":"

    The connection associations for the resiliency group.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to use to retrieve the next page of results. This value is null when there are no more results to return.

    " + } + } + }, + "ListResiliencyGroupsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResultSetSize", + "documentation":"

    The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.

    If MaxResults is given a value larger than 100, only 100 results are returned.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListResiliencyGroupsResult":{ + "type":"structure", + "members":{ + "items":{ + "shape":"ResiliencyGroupSummaryList", + "documentation":"

    Summary information about the resiliency groups.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to use to retrieve the next page of results. This value is null when there are no more results to return.

    " + } + } + }, + "ListVirtualInterfaceRoutesRequest":{ + "type":"structure", + "members":{ + "virtualInterfaceId":{ + "shape":"VirtualInterfaceId", + "documentation":"

    The ID of the virtual interface.

    " + }, + "filters":{ + "shape":"RouteFilters", + "documentation":"

    The filters to apply to the routes returned.

    " + }, + "maxResults":{ + "shape":"MaxResultSetSize", + "documentation":"

    The maximum number of results to return with a single call. To retrieve the remaining results, make another call with the returned nextToken value.

    If MaxResults is given a value larger than 100, only 100 results are returned.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListVirtualInterfaceRoutesResponse":{ + "type":"structure", + "members":{ + "virtualInterfaceId":{ + "shape":"VirtualInterfaceId", + "documentation":"

    The ID of the virtual interface.

    " + }, + "routes":{ + "shape":"RouteList", + "documentation":"

    The routes for the virtual interface.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to use to retrieve the next page of results. This value is null when there are no more results to return.

    " + } + } + }, "ListVirtualInterfaceTestHistoryRequest":{ "type":"structure", "members":{ @@ -3100,6 +3626,10 @@ "availableMacSecPortSpeeds":{ "shape":"AvailableMacSecPortSpeeds", "documentation":"

    The available MAC Security (MACsec) port speeds for the location.

    " + }, + "availableBillingModes":{ + "shape":"AvailableBillingModeList", + "documentation":"

    The billing modes available at the location, including the port speeds and Amazon Web Services Regions supported by each mode.

    " } }, "documentation":"

    Information about an Direct Connect location.

    " @@ -3241,6 +3771,14 @@ "shape":"EnableSiteLink", "documentation":"

    Indicates whether to enable or disable SiteLink.

    " }, + "prefixPoolAllocatedCountIpv4":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes to allocate to the virtual interface.

    " + }, + "prefixPoolAllocatedCountIpv6":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes to allocate to the virtual interface.

    " + }, "rateLimit":{ "shape":"RateLimit", "documentation":"

    The rate limit (bandwidth allocation) to apply to the virtual interface. The rate limit restricts the maximum bandwidth that the virtual interface can use on the parent connection.

    " @@ -3461,6 +3999,14 @@ "shape":"EnableSiteLink", "documentation":"

    Indicates whether to enable or disable SiteLink.

    " }, + "prefixPoolAllocatedCountIpv4":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes to allocate to the virtual interface.

    " + }, + "prefixPoolAllocatedCountIpv6":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes to allocate to the virtual interface.

    " + }, "rateLimit":{ "shape":"RateLimit", "documentation":"

    The rate limit (bandwidth allocation) to apply to the virtual interface. The rate limit restricts the maximum bandwidth that the virtual interface can use on the parent connection.

    " @@ -3533,6 +4079,18 @@ "Platform":{"type":"string"}, "PortEncryptionStatus":{"type":"string"}, "PortSpeed":{"type":"string"}, + "PrefixPoolAllocatedCount":{ + "type":"integer", + "min":0 + }, + "PrefixPoolSize":{ + "type":"integer", + "min":0 + }, + "PrefixPoolUnallocatedCount":{ + "type":"integer", + "min":0 + }, "ProviderList":{ "type":"list", "member":{"shape":"ProviderName"} @@ -3562,7 +4120,156 @@ "documentation":"

    Contains information about the rate limiter status for a connection, including the maximum number of rate limiters allowed, the number currently in use, and the remaining capacity.

    " }, "Region":{"type":"string"}, + "RequestBillingMode":{ + "type":"string", + "enum":[ + "PayAsYouGo", + "FlatRateTier1", + "FlatRateTier2", + "FlatRateTier3", + "FlatRateTier4", + "FlatRateTier5" + ] + }, "RequestMACSec":{"type":"boolean"}, + "ResiliencyGroup":{ + "type":"structure", + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "resiliencyGroupArn":{ + "shape":"ResiliencyGroupArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resiliency group.

    " + }, + "resiliencyGroupName":{ + "shape":"ResiliencyGroupName", + "documentation":"

    The name of the resiliency group.

    " + }, + "resiliencyGroupType":{ + "shape":"ResiliencyGroupType", + "documentation":"

    The type of the resiliency group. The valid value is Managed.

    " + }, + "ownerAccount":{ + "shape":"OwnerAccount", + "documentation":"

    The ID of the Amazon Web Services account that owns the resiliency group.

    " + }, + "state":{ + "shape":"ResiliencyGroupState", + "documentation":"

    The state of the resiliency group. The valid values are pending, available, deleting, and deleted.

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

    The tags associated with the resiliency group.

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

    Information about a resiliency group.

    " + }, + "ResiliencyGroupArn":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"^arn:(aws|aws-cn|aws-us-gov):directconnect::[0-9]{12}:dx-resiliency-group/dxrg-[0-9a-z]{17}$" + }, + "ResiliencyGroupAssociation":{ + "type":"structure", + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "connectionArn":{ + "shape":"ConnectionArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated connection.

    " + }, + "state":{ + "shape":"ResiliencyGroupAssociationState", + "documentation":"

    The state of the association. The valid values are associating, associated, disassociating, and disassociated.

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

    Information about an association between a connection and a resiliency group.

    " + }, + "ResiliencyGroupAssociationList":{ + "type":"list", + "member":{"shape":"ResiliencyGroupAssociation"} + }, + "ResiliencyGroupAssociationState":{ + "type":"string", + "enum":[ + "associating", + "associated", + "disassociating", + "disassociated" + ] + }, + "ResiliencyGroupId":{ + "type":"string", + "max":22, + "min":22, + "pattern":"^(dxrg|DXRG)-[0-9a-zA-Z]{17}$" + }, + "ResiliencyGroupName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"^[a-zA-Z0-9_\\-]+$" + }, + "ResiliencyGroupState":{ + "type":"string", + "enum":[ + "pending", + "available", + "deleting", + "deleted" + ] + }, + "ResiliencyGroupSummary":{ + "type":"structure", + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "resiliencyGroupArn":{ + "shape":"ResiliencyGroupArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resiliency group.

    " + }, + "resiliencyGroupName":{ + "shape":"ResiliencyGroupName", + "documentation":"

    The name of the resiliency group.

    " + }, + "resiliencyGroupType":{ + "shape":"ResiliencyGroupType", + "documentation":"

    The type of the resiliency group. The valid value is Managed.

    " + }, + "ownerAccount":{ + "shape":"OwnerAccount", + "documentation":"

    The ID of the Amazon Web Services account that owns the resiliency group.

    " + }, + "state":{ + "shape":"ResiliencyGroupState", + "documentation":"

    The state of the resiliency group.

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

    Summary information about a resiliency group.

    " + }, + "ResiliencyGroupSummaryList":{ + "type":"list", + "member":{"shape":"ResiliencyGroupSummary"} + }, + "ResiliencyGroupType":{ + "type":"string", + "enum":["Managed"] + }, + "ResiliencyModel":{ + "type":"string", + "enum":[ + "maximum-resiliency", + "high-resiliency", + "basic-resiliency" + ] + }, "ResourceArn":{"type":"string"}, "ResourceArnList":{ "type":"list", @@ -3586,6 +4293,55 @@ "type":"list", "member":{"shape":"ResourceTag"} }, + "Route":{ + "type":"structure", + "members":{ + "cidr":{ + "shape":"RouteCidr", + "documentation":"

    The CIDR (prefix) of the route.

    " + }, + "routeDirection":{ + "shape":"RouteDirection", + "documentation":"

    The direction of the route.

    The valid values are accepted (received from the customer network) and advertised (advertised to the customer network).

    " + }, + "addressFamily":{ + "shape":"AddressFamily", + "documentation":"

    The address family of the route.

    The valid values are ipv4 and ipv6.

    " + }, + "asPath":{ + "shape":"AsPathSegmentList", + "documentation":"

    The autonomous system (AS) path of the route.

    " + }, + "communities":{ + "shape":"CommunityList", + "documentation":"

    The BGP communities associated with the route.

    " + }, + "awsLogicalDeviceId":{ + "shape":"AwsLogicalDeviceId", + "documentation":"

    The Direct Connect endpoint that terminates the logical connection. This device might be different than the device that terminates the physical connection.

    " + }, + "routeInstalledAt":{ + "shape":"RouteInstalledAt", + "documentation":"

    The time when the route was installed. The value is displayed in UTC format.

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

    Information about a route for a virtual interface.

    " + }, + "RouteCidr":{"type":"string"}, + "RouteDirection":{ + "type":"string", + "enum":[ + "accepted", + "advertised" + ] + }, + "RouteFilterCidrString":{"type":"string"}, + "RouteFilterCidrStringList":{ + "type":"list", + "member":{"shape":"RouteFilterCidrString"}, + "max":10, + "min":1 + }, "RouteFilterPrefix":{ "type":"structure", "members":{ @@ -3600,6 +4356,37 @@ "type":"list", "member":{"shape":"RouteFilterPrefix"} }, + "RouteFilters":{ + "type":"structure", + "members":{ + "routeDirection":{ + "shape":"RouteDirection", + "documentation":"

    The direction of the routes to return.

    The valid values are accepted (routes received from the customer network) and advertised (routes advertised to the customer network).

    " + }, + "addressFamily":{ + "shape":"AddressFamily", + "documentation":"

    The address family of the routes to return.

    The valid values are ipv4 and ipv6.

    " + }, + "cidrs":{ + "shape":"RouteFilterCidrStringList", + "documentation":"

    The CIDRs (prefixes) used to filter the routes. You can specify up to 10 CIDRs.

    " + }, + "asPath":{ + "shape":"AsPathList", + "documentation":"

    The autonomous system (AS) numbers used to filter the routes by their AS path.

    " + }, + "communities":{ + "shape":"CommunityList", + "documentation":"

    The BGP communities used to filter the routes.

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

    The filters used to limit the routes returned by ListVirtualInterfaceRoutes.

    " + }, + "RouteInstalledAt":{"type":"timestamp"}, + "RouteList":{ + "type":"list", + "member":{"shape":"Route"} + }, "RouterConfig":{"type":"string"}, "RouterType":{ "type":"structure", @@ -3796,6 +4583,36 @@ } } }, + "UpdateConnectionsBillingModeRequest":{ + "type":"structure", + "required":[ + "connectionIds", + "billingMode" + ], + "members":{ + "connectionIds":{ + "shape":"ConnectionIdList", + "documentation":"

    The IDs of the connections to update. You can specify from 1 to 200 connections.

    " + }, + "billingMode":{ + "shape":"RequestBillingMode", + "documentation":"

    The billing mode to apply to the specified connections. The valid values are PayAsYouGo, FlatRateTier1, FlatRateTier2, FlatRateTier3, FlatRateTier4, and FlatRateTier5.

    " + } + } + }, + "UpdateConnectionsBillingModeResponse":{ + "type":"structure", + "members":{ + "billingMode":{ + "shape":"BillingMode", + "documentation":"

    The billing mode applied to the connections.

    " + }, + "connections":{ + "shape":"ConnectionList", + "documentation":"

    The connections with the updated billing mode.

    " + } + } + }, "UpdateDirectConnectGatewayAssociationRequest":{ "type":"structure", "members":{ @@ -3870,6 +4687,36 @@ } } }, + "UpdateResiliencyGroupRequest":{ + "type":"structure", + "required":[ + "resiliencyGroupId", + "resiliencyGroupName" + ], + "members":{ + "resiliencyGroupId":{ + "shape":"ResiliencyGroupId", + "documentation":"

    The ID of the resiliency group.

    " + }, + "resiliencyGroupName":{ + "shape":"ResiliencyGroupName", + "documentation":"

    The new name of the resiliency group.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    " + } + } + }, + "UpdateResiliencyGroupResult":{ + "type":"structure", + "members":{ + "resiliencyGroup":{ + "shape":"ResiliencyGroup", + "documentation":"

    Information about the resiliency group.

    " + } + } + }, "UpdateVirtualInterfaceAttributesRequest":{ "type":"structure", "required":["virtualInterfaceId"], @@ -3890,6 +4737,14 @@ "shape":"VirtualInterfaceName", "documentation":"

    The name of the virtual private interface.

    " }, + "prefixPoolAllocatedCountIpv4":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes to allocate to the virtual interface. Not applicable to public virtual interfaces.

    " + }, + "prefixPoolAllocatedCountIpv6":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes to allocate to the virtual interface. Not applicable to public virtual interfaces.

    " + }, "rateLimit":{ "shape":"RateLimit", "documentation":"

    The rate limit (bandwidth allocation) to apply to the virtual interface. Use this to update the bandwidth allocation on an existing virtual interface.

    " @@ -4042,6 +4897,14 @@ "shape":"SiteLinkEnabled", "documentation":"

    Indicates whether SiteLink is enabled.

    " }, + "prefixPoolAllocatedCountIpv4":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv4 route prefixes allocated to the virtual interface. Not applicable to public virtual interfaces.

    " + }, + "prefixPoolAllocatedCountIpv6":{ + "shape":"PrefixPoolAllocatedCount", + "documentation":"

    The number of inbound IPv6 route prefixes allocated to the virtual interface. Not applicable to public virtual interfaces.

    " + }, "rateLimit":{ "shape":"RateLimit", "documentation":"

    The rate limit (bandwidth allocation) applied to the virtual interface. The value must be one of the supported bandwidth values and cannot exceed the bandwidth of the parent connection or LAG. Supported values: 50Mbps, 100Mbps, 200Mbps, 300Mbps, 400Mbps, 500Mbps, 600Mbps, 700Mbps, 800Mbps, 900Mbps, 1Gbps, 1.2Gbps, 1.5Gbps, 1.8Gbps, 2Gbps, 2.1Gbps, 2.4Gbps, 2.7Gbps, 3Gbps, 3.2Gbps, 3.6Gbps, 4Gbps, 5Gbps, 6Gbps, 7Gbps, 8Gbps, 9Gbps, 10Gbps, 12Gbps, 15Gbps, 18Gbps, 20Gbps, 21Gbps, 24Gbps, 27Gbps, 30Gbps, 32Gbps, 36Gbps, 40Gbps, 50Gbps, 60Gbps, 70Gbps, 80Gbps, 100Gbps, 120Gbps, 150Gbps, 180Gbps, 200Gbps, 210Gbps, 240Gbps, 270Gbps, 300Gbps, 320Gbps, 360Gbps, 400Gbps, 450Gbps, 480Gbps, 500Gbps, 540Gbps, 600Gbps, 700Gbps, 800Gbps, 900Gbps, 1Tbps, 1.1Tbps, 1.2Tbps, 1.3Tbps, 1.4Tbps, 1.5Tbps, 1.6Tbps.

    " diff --git a/services/directory/pom.xml b/services/directory/pom.xml index a6385ad006d3..0233dc13e3a2 100644 --- a/services/directory/pom.xml +++ b/services/directory/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT directory AWS Java SDK :: Services :: AWS Directory Service diff --git a/services/directory/src/main/resources/codegen-resources/customization.config b/services/directory/src/main/resources/codegen-resources/customization.config index 4136b1085a58..c37d98d79126 100644 --- a/services/directory/src/main/resources/codegen-resources/customization.config +++ b/services/directory/src/main/resources/codegen-resources/customization.config @@ -215,6 +215,5 @@ } ] } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/directory/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/directory/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..78061a502c22 --- /dev/null +++ b/services/directory/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/directory/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/directory/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d248e0cb6f34..000000000000 --- a/services/directory/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ds.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/directoryservicedata/pom.xml b/services/directoryservicedata/pom.xml index 3e5424715c0a..1eeca3436cc1 100644 --- a/services/directoryservicedata/pom.xml +++ b/services/directoryservicedata/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT directoryservicedata AWS Java SDK :: Services :: Directory Service Data diff --git a/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..193d17f45b34 --- /dev/null +++ b/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-data-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-data.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ds-data.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4c5051758d29..000000000000 --- a/services/directoryservicedata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-data-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-data.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ds-data.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/dlm/pom.xml b/services/dlm/pom.xml index 9d5940265a13..2f50ac6e9144 100644 --- a/services/dlm/pom.xml +++ b/services/dlm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dlm AWS Java SDK :: Services :: DLM diff --git a/services/dlm/src/main/resources/codegen-resources/customization.config b/services/dlm/src/main/resources/codegen-resources/customization.config index 108e3431d2ec..a6f7fab65273 100644 --- a/services/dlm/src/main/resources/codegen-resources/customization.config +++ b/services/dlm/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "getLifecyclePolicies" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/dlm/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/dlm/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..88c3cbb0d5ad --- /dev/null +++ b/services/dlm/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dlm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dlm.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dlm-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dlm.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dlm.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/dlm/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/dlm/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7ad908c256f8..000000000000 --- a/services/dlm/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dlm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://dlm.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dlm-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dlm.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dlm.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/docdb/pom.xml b/services/docdb/pom.xml index fff5372ce0fa..e341a5f90e22 100644 --- a/services/docdb/pom.xml +++ b/services/docdb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT docdb AWS Java SDK :: Services :: DocDB diff --git a/services/docdb/src/main/java/software/amazon/awssdk/services/docdb/internal/RdsPresignInterceptor.java b/services/docdb/src/main/java/software/amazon/awssdk/services/docdb/internal/RdsPresignInterceptor.java index cd2c0d8c4de1..650619610feb 100644 --- a/services/docdb/src/main/java/software/amazon/awssdk/services/docdb/internal/RdsPresignInterceptor.java +++ b/services/docdb/src/main/java/software/amazon/awssdk/services/docdb/internal/RdsPresignInterceptor.java @@ -24,9 +24,7 @@ import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsExecutionAttribute; -import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.core.ClientEndpointProvider; -import software.amazon.awssdk.core.Protocol; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -35,7 +33,6 @@ 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.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; @@ -48,6 +45,7 @@ import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.docdb.endpoints.DocDbEndpointProvider; import software.amazon.awssdk.services.docdb.model.DocDbRequest; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -72,7 +70,6 @@ public abstract class RdsPresignInterceptor implements E .build()) .build(); - private static final String SERVICE_NAME = "rds"; private static final String PARAM_SOURCE_REGION = "SourceRegion"; private static final String PARAM_DESTINATION_REGION = "DestinationRegion"; private static final String PARAM_PRESIGNED_URL = "PreSignedUrl"; @@ -109,7 +106,7 @@ public final SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, SelectedAuthScheme selectedAuthScheme = resolveAuthScheme(context.request(), executionAttributes); String sourceRegion = presignableRequest.getSourceRegion(); String destinationRegion = selectedAuthScheme.authSchemeOption().signerProperty(AwsV4HttpSigner.REGION_NAME); - URI endpoint = createEndpoint(sourceRegion, SERVICE_NAME, executionAttributes); + URI endpoint = createEndpoint(sourceRegion, executionAttributes); SdkHttpFullRequest.Builder marshalledRequest = presignableRequest.marshall().toBuilder().uri(endpoint); SdkHttpFullRequest requestToPresign = @@ -223,17 +220,14 @@ private SdkHttpFullRequest toSdkHttpFullRequest(SignedRequest signedRequest) { .build(); } - private URI createEndpoint(String regionName, String serviceName, ExecutionAttributes attributes) { - return AwsClientEndpointProvider.builder() - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol(Protocol.HTTPS.toString()) - .region(Region.of(regionName)) - .profileFile(attributes.getAttribute(SdkExecutionAttribute.PROFILE_FILE_SUPPLIER)) - .profileName(attributes.getAttribute(SdkExecutionAttribute.PROFILE_NAME)) - .dualstackEnabled( - attributes.getAttribute(AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) - .fipsEnabled(attributes.getAttribute(AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED)) - .build() - .clientEndpoint(); + private URI createEndpoint(String regionName, ExecutionAttributes attributes) { + return CompletableFutureUtils.joinLikeSync( + DocDbEndpointProvider.defaultProvider() + .resolveEndpoint(p -> p.region(Region.of(regionName)) + .useDualStack(attributes.getAttribute( + AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(attributes.getAttribute( + AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED))) + ).url(); } } diff --git a/services/docdb/src/main/resources/codegen-resources/customization.config b/services/docdb/src/main/resources/codegen-resources/customization.config index b087eccac9d3..fcaf860a4b62 100644 --- a/services/docdb/src/main/resources/codegen-resources/customization.config +++ b/services/docdb/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { - "enableGenerateCompiledEndpointRules": true, "verifiedSimpleMethods" : [ "describeDBClusterParameterGroups", "describeDBClusterSnapshots", diff --git a/services/docdb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/docdb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fd1d9901492d --- /dev/null +++ b/services/docdb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/docdb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/docdb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index eaad8e6d0e8d..000000000000 --- a/services/docdb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://rds.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/docdb/src/main/resources/codegen-resources/service-2.json b/services/docdb/src/main/resources/codegen-resources/service-2.json index a5c87179ce8d..21008c372ef5 100644 --- a/services/docdb/src/main/resources/codegen-resources/service-2.json +++ b/services/docdb/src/main/resources/codegen-resources/service-2.json @@ -151,7 +151,7 @@ {"shape":"DBParameterGroupQuotaExceededFault"}, {"shape":"DBParameterGroupAlreadyExistsFault"} ], - "documentation":"

    Creates a new cluster parameter group.

    Parameters in a cluster parameter group apply to all of the instances in a cluster.

    A cluster parameter group is initially created with the default parameters for the database engine used by instances in the cluster. In Amazon DocumentDB, you cannot make modifications directly to the default.docdb3.6 cluster parameter group. If your Amazon DocumentDB cluster is using the default cluster parameter group and you want to modify a value in it, you must first create a new parameter group or copy an existing parameter group, modify it, and then apply the modified parameter group to your cluster. For the new cluster parameter group and associated settings to take effect, you must then reboot the instances in the cluster without failover. For more information, see Modifying Amazon DocumentDB Cluster Parameter Groups.

    " + "documentation":"

    Creates a new cluster parameter group.

    Parameters in a cluster parameter group apply to all of the instances in a cluster.

    A cluster parameter group is initially created with the default parameters for the database engine used by instances in the cluster. In Amazon DocumentDB, you cannot make modifications directly to the default.docdb3.6 cluster parameter group. If your Amazon DocumentDB cluster is using the default cluster parameter group and you want to modify a value in it, you must first create a new parameter group or copy an existing parameter group, modify it, and then apply the modified parameter group to your cluster. For the new cluster parameter group and associated settings to take effect, you must then reboot the instances in the cluster without failover. For more information, see Modifying Amazon DocumentDB Cluster Parameter Groups.

    " }, "CreateDBClusterSnapshot":{ "name":"CreateDBClusterSnapshot", @@ -988,7 +988,7 @@ {"shape":"InvalidDBClusterStateFault"}, {"shape":"InvalidDBInstanceStateFault"} ], - "documentation":"

    Restarts the stopped cluster that is specified by DBClusterIdentifier. For more information, see Stopping and Starting an Amazon DocumentDB Cluster.

    " + "documentation":"

    Restarts the stopped cluster that is specified by DBClusterIdentifier. For more information, see Stopping and Starting an Amazon DocumentDB Cluster.

    " }, "StopDBCluster":{ "name":"StopDBCluster", @@ -1006,7 +1006,7 @@ {"shape":"InvalidDBClusterStateFault"}, {"shape":"InvalidDBInstanceStateFault"} ], - "documentation":"

    Stops the running cluster that is specified by DBClusterIdentifier. The cluster must be in the available state. For more information, see Stopping and Starting an Amazon DocumentDB Cluster.

    " + "documentation":"

    Stops the running cluster that is specified by DBClusterIdentifier. The cluster must be in the available state. For more information, see Stopping and Starting an Amazon DocumentDB Cluster.

    " }, "SwitchoverGlobalCluster":{ "name":"SwitchoverGlobalCluster", @@ -1199,7 +1199,7 @@ "documentation":"

    The expiration date of the DB instance’s server certificate.

    " } }, - "documentation":"

    Returns the details of the DB instance’s server certificate.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " + "documentation":"

    Returns the details of the DB instance’s server certificate.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " }, "CertificateList":{ "type":"list", @@ -1414,7 +1414,7 @@ }, "EnableCloudwatchLogsExports":{ "shape":"LogTypeList", - "documentation":"

    A list of log types that need to be enabled for exporting to Amazon CloudWatch Logs. You can enable audit logs or profiler logs. For more information, see Auditing Amazon DocumentDB Events and Profiling Amazon DocumentDB Operations.

    " + "documentation":"

    A list of log types that need to be enabled for exporting to Amazon CloudWatch Logs. You can enable audit logs or profiler logs. For more information, see Auditing Amazon DocumentDB Events and Profiling Amazon DocumentDB Operations.

    " }, "DeletionProtection":{ "shape":"BooleanOptional", @@ -1442,7 +1442,11 @@ }, "NetworkType":{ "shape":"String", - "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + }, + "CopyTagsToSnapshot":{ + "shape":"BooleanOptional", + "documentation":"

    Specifies whether to copy all tags from the DB cluster to snapshots of the DB cluster. The default is not to copy them.

    " } }, "documentation":"

    Represents the input to CreateDBCluster.

    " @@ -1565,7 +1569,7 @@ }, "EnablePerformanceInsights":{ "shape":"BooleanOptional", - "documentation":"

    A value that indicates whether to enable Performance Insights for the DB Instance. For more information, see Using Amazon Performance Insights.

    " + "documentation":"

    A value that indicates whether to enable Performance Insights for the DB Instance. For more information, see Using Amazon Performance Insights.

    " }, "PerformanceInsightsKMSKeyId":{ "shape":"String", @@ -1573,7 +1577,7 @@ }, "CACertificateIdentifier":{ "shape":"String", - "documentation":"

    The CA certificate identifier to use for the DB instance's server certificate.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " + "documentation":"

    The CA certificate identifier to use for the DB instance's server certificate.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " } }, "documentation":"

    Represents the input to CreateDBInstance.

    " @@ -1851,7 +1855,11 @@ }, "NetworkType":{ "shape":"String", - "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + }, + "CopyTagsToSnapshot":{ + "shape":"BooleanOptional", + "documentation":"

    Specifies whether to copy all tags from the DB cluster to snapshots of the DB cluster. The default is not to copy them.

    " } }, "documentation":"

    Detailed information about a cluster.

    ", @@ -2242,7 +2250,7 @@ }, "SupportedCACertificateIdentifiers":{ "shape":"CACertificateIdentifiersList", - "documentation":"

    A list of the supported CA certificate identifiers.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " + "documentation":"

    A list of the supported CA certificate identifiers.

    For more information, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " }, "SupportsCertificateRotationWithoutRestart":{ "shape":"BooleanOptional", @@ -3977,7 +3985,11 @@ }, "NetworkType":{ "shape":"String", - "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + }, + "CopyTagsToSnapshot":{ + "shape":"BooleanOptional", + "documentation":"

    Specifies whether to copy all tags from the DB cluster to snapshots of the DB cluster. The default is not to copy them.

    " } }, "documentation":"

    Represents the input to ModifyDBCluster.

    " @@ -4080,7 +4092,7 @@ }, "EnablePerformanceInsights":{ "shape":"BooleanOptional", - "documentation":"

    A value that indicates whether to enable Performance Insights for the DB Instance. For more information, see Using Amazon Performance Insights.

    " + "documentation":"

    A value that indicates whether to enable Performance Insights for the DB Instance. For more information, see Using Amazon Performance Insights.

    " }, "PerformanceInsightsKMSKeyId":{ "shape":"String", @@ -4088,7 +4100,7 @@ }, "CertificateRotationRestart":{ "shape":"BooleanOptional", - "documentation":"

    Specifies whether the DB instance is restarted when you rotate your SSL/TLS certificate.

    By default, the DB instance is restarted when you rotate your SSL/TLS certificate. The certificate is not updated until the DB instance is restarted.

    Set this parameter only if you are not using SSL/TLS to connect to the DB instance.

    If you are using SSL/TLS to connect to the DB instance, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " + "documentation":"

    Specifies whether the DB instance is restarted when you rotate your SSL/TLS certificate.

    By default, the DB instance is restarted when you rotate your SSL/TLS certificate. The certificate is not updated until the DB instance is restarted.

    Set this parameter only if you are not using SSL/TLS to connect to the DB instance.

    If you are using SSL/TLS to connect to the DB instance, see Updating Your Amazon DocumentDB TLS Certificates and Encrypting Data in Transit in the Amazon DocumentDB Developer Guide.

    " } }, "documentation":"

    Represents the input to ModifyDBInstance.

    " @@ -4656,7 +4668,11 @@ }, "NetworkType":{ "shape":"String", - "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + }, + "CopyTagsToSnapshot":{ + "shape":"BooleanOptional", + "documentation":"

    Specifies whether to copy all tags from the restored DB cluster to snapshots of the restored DB cluster. The default is not to copy them.

    " } }, "documentation":"

    Represents the input to RestoreDBClusterFromSnapshot.

    " @@ -4732,7 +4748,11 @@ }, "NetworkType":{ "shape":"String", - "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + "documentation":"

    The network type of the cluster.

    The network type is determined by the DBSubnetGroup specified for the cluster. A DBSubnetGroup can support only the IPv4 protocol or the IPv4 and the IPv6 protocols (DUAL).

    For more information, see DocumentDB clusters in a VPC in the Amazon DocumentDB Developer Guide.

    Valid Values: IPV4 | DUAL

    " + }, + "CopyTagsToSnapshot":{ + "shape":"BooleanOptional", + "documentation":"

    Specifies whether to copy all tags from the restored DB cluster to snapshots of the restored DB cluster. The default is not to copy them.

    " } }, "documentation":"

    Represents the input to RestoreDBClusterToPointInTime.

    " diff --git a/services/docdbelastic/pom.xml b/services/docdbelastic/pom.xml index 92ba1f27ea49..6cfca22c73c9 100644 --- a/services/docdbelastic/pom.xml +++ b/services/docdbelastic/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT docdbelastic AWS Java SDK :: Services :: Doc DB Elastic diff --git a/services/docdbelastic/src/main/resources/codegen-resources/customization.config b/services/docdbelastic/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/docdbelastic/src/main/resources/codegen-resources/customization.config +++ b/services/docdbelastic/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/docdbelastic/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/docdbelastic/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..275be094b672 --- /dev/null +++ b/services/docdbelastic/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://docdb-elastic-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://docdb-elastic-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://docdb-elastic.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://docdb-elastic.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/docdbelastic/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/docdbelastic/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 00afd80c1e05..000000000000 --- a/services/docdbelastic/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://docdb-elastic-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://docdb-elastic-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://docdb-elastic.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://docdb-elastic.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/drs/pom.xml b/services/drs/pom.xml index 0476028cdac1..287de8f31132 100644 --- a/services/drs/pom.xml +++ b/services/drs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT drs AWS Java SDK :: Services :: Drs diff --git a/services/drs/src/main/resources/codegen-resources/customization.config b/services/drs/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/drs/src/main/resources/codegen-resources/customization.config +++ b/services/drs/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/drs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/drs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..097fb3c91c0b --- /dev/null +++ b/services/drs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://drs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://drs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://drs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://drs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/drs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/drs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d5e7245357fa..000000000000 --- a/services/drs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://drs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://drs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://drs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://drs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/drs/src/main/resources/codegen-resources/paginators-1.json b/services/drs/src/main/resources/codegen-resources/paginators-1.json index 5a7deb487d88..9beeb72dffe5 100644 --- a/services/drs/src/main/resources/codegen-resources/paginators-1.json +++ b/services/drs/src/main/resources/codegen-resources/paginators-1.json @@ -60,6 +60,30 @@ "limit_key": "maxResults", "result_key": "items" }, + "ListRecoveryPlanExecutionSteps": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "recoveryPlanExecutionSteps" + }, + "ListRecoveryPlanExecutions": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "recoveryPlanExecutions" + }, + "ListRecoveryPlanSteps": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "recoveryPlanSteps" + }, + "ListRecoveryPlans": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "recoveryPlans" + }, "ListStagingAccounts": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/drs/src/main/resources/codegen-resources/service-2.json b/services/drs/src/main/resources/codegen-resources/service-2.json index bb29e7191745..71c93bb7b769 100644 --- a/services/drs/src/main/resources/codegen-resources/service-2.json +++ b/services/drs/src/main/resources/codegen-resources/service-2.json @@ -34,6 +34,26 @@ ], "documentation":"

    Associate a Source Network to an existing CloudFormation Stack and modify launch templates to use this network. Can be used for reverting to previously deployed CloudFormation stacks.

    " }, + "CancelRecoveryPlanExecution":{ + "name":"CancelRecoveryPlanExecution", + "http":{ + "method":"POST", + "requestUri":"/CancelRecoveryPlanExecution", + "responseCode":200 + }, + "input":{"shape":"CancelRecoveryPlanExecutionRequest"}, + "output":{"shape":"CancelRecoveryPlanExecutionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Cancels an in-progress Recovery Plan execution. Remaining steps are skipped.

    " + }, "CreateExtendedSourceServer":{ "name":"CreateExtendedSourceServer", "http":{ @@ -73,6 +93,47 @@ ], "documentation":"

    Creates a new Launch Configuration Template.

    " }, + "CreateRecoveryPlan":{ + "name":"CreateRecoveryPlan", + "http":{ + "method":"POST", + "requestUri":"/CreateRecoveryPlan", + "responseCode":201 + }, + "input":{"shape":"CreateRecoveryPlanRequest"}, + "output":{"shape":"CreateRecoveryPlanResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Creates a Recovery Plan to orchestrate multi-server disaster recovery.

    " + }, + "CreateRecoveryPlanStep":{ + "name":"CreateRecoveryPlanStep", + "http":{ + "method":"POST", + "requestUri":"/CreateRecoveryPlanStep", + "responseCode":201 + }, + "input":{"shape":"CreateRecoveryPlanStepRequest"}, + "output":{"shape":"CreateRecoveryPlanStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Creates a step in a Recovery Plan. A step is either SERVER type (servers to recover in parallel) or WAIT type (timed pause between steps).

    " + }, "CreateReplicationConfigurationTemplate":{ "name":"CreateReplicationConfigurationTemplate", "http":{ @@ -185,6 +246,66 @@ ], "documentation":"

    Deletes a single Recovery Instance by ID. This deletes the Recovery Instance resource from Elastic Disaster Recovery. The Recovery Instance must be disconnected first in order to delete it.

    " }, + "DeleteRecoveryPlan":{ + "name":"DeleteRecoveryPlan", + "http":{ + "method":"POST", + "requestUri":"/DeleteRecoveryPlan", + "responseCode":200 + }, + "input":{"shape":"DeleteRecoveryPlanRequest"}, + "output":{"shape":"DeleteRecoveryPlanResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Deletes a Recovery Plan. Cannot delete a plan that has an execution in a non-terminal status (CREATED, IN_PROGRESS).

    " + }, + "DeleteRecoveryPlanExecution":{ + "name":"DeleteRecoveryPlanExecution", + "http":{ + "method":"POST", + "requestUri":"/DeleteRecoveryPlanExecution", + "responseCode":200 + }, + "input":{"shape":"DeleteRecoveryPlanExecutionRequest"}, + "output":{"shape":"DeleteRecoveryPlanExecutionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Deletes a Recovery Plan execution record. Must be in a terminal status.

    " + }, + "DeleteRecoveryPlanStep":{ + "name":"DeleteRecoveryPlanStep", + "http":{ + "method":"POST", + "requestUri":"/DeleteRecoveryPlanStep", + "responseCode":200 + }, + "input":{"shape":"DeleteRecoveryPlanStepRequest"}, + "output":{"shape":"DeleteRecoveryPlanStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Deletes a step from a Recovery Plan.

    " + }, "DeleteReplicationConfigurationTemplate":{ "name":"DeleteReplicationConfigurationTemplate", "http":{ @@ -480,6 +601,86 @@ "documentation":"

    Gets a LaunchConfiguration, filtered by Source Server IDs.

    ", "readonly":true }, + "GetRecoveryPlan":{ + "name":"GetRecoveryPlan", + "http":{ + "method":"POST", + "requestUri":"/GetRecoveryPlan", + "responseCode":200 + }, + "input":{"shape":"GetRecoveryPlanRequest"}, + "output":{"shape":"GetRecoveryPlanResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Gets a Recovery Plan by ARN.

    ", + "readonly":true + }, + "GetRecoveryPlanExecution":{ + "name":"GetRecoveryPlanExecution", + "http":{ + "method":"POST", + "requestUri":"/GetRecoveryPlanExecution", + "responseCode":200 + }, + "input":{"shape":"GetRecoveryPlanExecutionRequest"}, + "output":{"shape":"GetRecoveryPlanExecutionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Gets the details of a Recovery Plan execution.

    ", + "readonly":true + }, + "GetRecoveryPlanExecutionStep":{ + "name":"GetRecoveryPlanExecutionStep", + "http":{ + "method":"POST", + "requestUri":"/GetRecoveryPlanExecutionStep", + "responseCode":200 + }, + "input":{"shape":"GetRecoveryPlanExecutionStepRequest"}, + "output":{"shape":"GetRecoveryPlanExecutionStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Gets the details of a step within a Recovery Plan execution.

    ", + "readonly":true + }, + "GetRecoveryPlanStep":{ + "name":"GetRecoveryPlanStep", + "http":{ + "method":"POST", + "requestUri":"/GetRecoveryPlanStep", + "responseCode":200 + }, + "input":{"shape":"GetRecoveryPlanStepRequest"}, + "output":{"shape":"GetRecoveryPlanStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Gets a Recovery Plan step by ARN.

    ", + "readonly":true + }, "GetReplicationConfiguration":{ "name":"GetReplicationConfiguration", "http":{ @@ -554,6 +755,84 @@ "documentation":"

    Lists resource launch actions.

    ", "readonly":true }, + "ListRecoveryPlanExecutionSteps":{ + "name":"ListRecoveryPlanExecutionSteps", + "http":{ + "method":"POST", + "requestUri":"/ListRecoveryPlanExecutionSteps", + "responseCode":200 + }, + "input":{"shape":"ListRecoveryPlanExecutionStepsRequest"}, + "output":{"shape":"ListRecoveryPlanExecutionStepsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Lists all steps within a Recovery Plan execution.

    ", + "readonly":true + }, + "ListRecoveryPlanExecutions":{ + "name":"ListRecoveryPlanExecutions", + "http":{ + "method":"POST", + "requestUri":"/ListRecoveryPlanExecutions", + "responseCode":200 + }, + "input":{"shape":"ListRecoveryPlanExecutionsRequest"}, + "output":{"shape":"ListRecoveryPlanExecutionsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Lists executions of Recovery Plans, optionally filtered by plan or status.

    ", + "readonly":true + }, + "ListRecoveryPlanSteps":{ + "name":"ListRecoveryPlanSteps", + "http":{ + "method":"POST", + "requestUri":"/ListRecoveryPlanSteps", + "responseCode":200 + }, + "input":{"shape":"ListRecoveryPlanStepsRequest"}, + "output":{"shape":"ListRecoveryPlanStepsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Lists all steps in a Recovery Plan.

    ", + "readonly":true + }, + "ListRecoveryPlans":{ + "name":"ListRecoveryPlans", + "http":{ + "method":"POST", + "requestUri":"/ListRecoveryPlans", + "responseCode":200 + }, + "input":{"shape":"ListRecoveryPlansRequest"}, + "output":{"shape":"ListRecoveryPlansResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Lists all Recovery Plans in the account.

    ", + "readonly":true + }, "ListStagingAccounts":{ "name":"ListStagingAccounts", "http":{ @@ -611,6 +890,26 @@ ], "documentation":"

    Puts a resource launch action.

    " }, + "ReorderRecoveryPlanSteps":{ + "name":"ReorderRecoveryPlanSteps", + "http":{ + "method":"POST", + "requestUri":"/ReorderRecoveryPlanSteps", + "responseCode":200 + }, + "input":{"shape":"ReorderRecoveryPlanStepsRequest"}, + "output":{"shape":"ReorderRecoveryPlanStepsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Reorders steps in a Recovery Plan. Accepts a complete ordered list of step ARNs.

    " + }, "RetryDataReplication":{ "name":"RetryDataReplication", "http":{ @@ -631,6 +930,26 @@ "deprecated":true, "deprecatedMessage":"WARNING: RetryDataReplication is deprecated" }, + "RetryRecoveryPlanExecutionStep":{ + "name":"RetryRecoveryPlanExecutionStep", + "http":{ + "method":"POST", + "requestUri":"/RetryRecoveryPlanExecutionStep", + "responseCode":200 + }, + "input":{"shape":"RetryRecoveryPlanExecutionStepRequest"}, + "output":{"shape":"RetryRecoveryPlanExecutionStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Retries a failed SERVER type execution step.

    " + }, "ReverseReplication":{ "name":"ReverseReplication", "http":{ @@ -688,6 +1007,27 @@ ], "documentation":"

    Launches Recovery Instances for the specified Source Servers. For each Source Server you may choose a point in time snapshot to launch from, or use an on demand snapshot.

    " }, + "StartRecoveryPlanExecution":{ + "name":"StartRecoveryPlanExecution", + "http":{ + "method":"POST", + "requestUri":"/StartRecoveryPlanExecution", + "responseCode":201 + }, + "input":{"shape":"StartRecoveryPlanExecutionRequest"}, + "output":{"shape":"StartRecoveryPlanExecutionResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Starts executing a Recovery Plan in DRILL or RECOVERY mode. A plan cannot have more than one execution in a non-terminal status at a time.

    " + }, "StartReplication":{ "name":"StartReplication", "http":{ @@ -906,15 +1246,15 @@ ], "documentation":"

    Updates an existing Launch Configuration Template by ID.

    " }, - "UpdateReplicationConfiguration":{ - "name":"UpdateReplicationConfiguration", + "UpdateRecoveryPlan":{ + "name":"UpdateRecoveryPlan", "http":{ "method":"POST", - "requestUri":"/UpdateReplicationConfiguration", + "requestUri":"/UpdateRecoveryPlan", "responseCode":200 }, - "input":{"shape":"UpdateReplicationConfigurationRequest"}, - "output":{"shape":"ReplicationConfiguration"}, + "input":{"shape":"UpdateRecoveryPlanRequest"}, + "output":{"shape":"UpdateRecoveryPlanResponse"}, "errors":[ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, @@ -924,31 +1264,91 @@ {"shape":"ValidationException"}, {"shape":"UninitializedAccountException"} ], - "documentation":"

    Allows you to update a ReplicationConfiguration by Source Server ID.

    ", - "idempotent":true + "documentation":"

    Updates a Recovery Plan's name or description.

    " }, - "UpdateReplicationConfigurationTemplate":{ - "name":"UpdateReplicationConfigurationTemplate", + "UpdateRecoveryPlanExecutionStep":{ + "name":"UpdateRecoveryPlanExecutionStep", "http":{ "method":"POST", - "requestUri":"/UpdateReplicationConfigurationTemplate", + "requestUri":"/UpdateRecoveryPlanExecutionStep", "responseCode":200 }, - "input":{"shape":"UpdateReplicationConfigurationTemplateRequest"}, - "output":{"shape":"ReplicationConfigurationTemplate"}, + "input":{"shape":"UpdateRecoveryPlanExecutionStepRequest"}, + "output":{"shape":"UpdateRecoveryPlanExecutionStepResponse"}, "errors":[ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"UninitializedAccountException"} ], - "documentation":"

    Updates a ReplicationConfigurationTemplate by ID.

    " - } - }, - "shapes":{ - "ARN":{ + "documentation":"

    Updates an execution step. Supports two actions: (1) skip a step that is in NOT_STARTED or FAILED status; (2) update the wait duration of a WAIT type step that is in NOT_STARTED status.

    " + }, + "UpdateRecoveryPlanStep":{ + "name":"UpdateRecoveryPlanStep", + "http":{ + "method":"POST", + "requestUri":"/UpdateRecoveryPlanStep", + "responseCode":200 + }, + "input":{"shape":"UpdateRecoveryPlanStepRequest"}, + "output":{"shape":"UpdateRecoveryPlanStepResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Updates a Recovery Plan step's name or configuration. Step type is immutable.

    " + }, + "UpdateReplicationConfiguration":{ + "name":"UpdateReplicationConfiguration", + "http":{ + "method":"POST", + "requestUri":"/UpdateReplicationConfiguration", + "responseCode":200 + }, + "input":{"shape":"UpdateReplicationConfigurationRequest"}, + "output":{"shape":"ReplicationConfiguration"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Allows you to update a ReplicationConfiguration by Source Server ID.

    ", + "idempotent":true + }, + "UpdateReplicationConfigurationTemplate":{ + "name":"UpdateReplicationConfigurationTemplate", + "http":{ + "method":"POST", + "requestUri":"/UpdateReplicationConfigurationTemplate", + "responseCode":200 + }, + "input":{"shape":"UpdateReplicationConfigurationTemplateRequest"}, + "output":{"shape":"ReplicationConfigurationTemplate"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"UninitializedAccountException"} + ], + "documentation":"

    Updates a ReplicationConfigurationTemplate by ID.

    " + } + }, + "shapes":{ + "ARN":{ "type":"string", "max":2048, "min":20, @@ -1029,13 +1429,13 @@ "type":"string", "max":255, "min":0, - "pattern":"(us(-gov)?|ap|ca|cn|eu|eusc|sa|af|me|il)-([a-z]{2}-)?(central|north|(north(?:east|west))|south|south(?:east|west)|east|west)-[0-9][a-z]" + "pattern":"(us(-gov)?|ap|ca|cn|eu|eusc|sa|af|me|mx|il)-([a-z]{2}-)?(central|north|(north(?:east|west))|south|south(?:east|west)|east|west)-[0-9][a-z]" }, "AwsRegion":{ "type":"string", "max":255, "min":0, - "pattern":"(us(-gov)?|ap|ca|cn|eu|eusc|sa|af|me|il)-([a-z]{2}-)?(central|north|(north(?:east|west))|south|south(?:east|west)|east|west)-[0-9]" + "pattern":"(us(-gov)?|ap|ca|cn|eu|eusc|sa|af|me|mx|il)-([a-z]{2}-)?(central|north|(north(?:east|west))|south|south(?:east|west)|east|west)-[0-9]" }, "Boolean":{ "type":"boolean", @@ -1060,6 +1460,26 @@ }, "documentation":"

    Information about a server's CPU.

    " }, + "CancelRecoveryPlanExecutionRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionArn"], + "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution to cancel.

    " + } + } + }, + "CancelRecoveryPlanExecutionResponse":{ + "type":"structure", + "required":["recoveryPlanExecution"], + "members":{ + "recoveryPlanExecution":{ + "shape":"RecoveryPlanExecution", + "documentation":"

    The cancelled Recovery Plan execution.

    " + } + } + }, "CfnStackName":{ "type":"string", "max":128, @@ -1067,6 +1487,11 @@ "pattern":"[a-zA-Z][-a-zA-Z0-9]*", "sensitive":true }, + "ClientIdempotencyToken":{ + "type":"string", + "max":64, + "min":0 + }, "ConflictException":{ "type":"structure", "members":{ @@ -1190,6 +1615,10 @@ "launchIntoSourceInstance":{ "shape":"Boolean", "documentation":"

    DRS will set the 'launch into instance ID' of any source server when performing a drill, recovery or failback to the previous region or availability zone, using the instance ID of the source instance.

    " + }, + "recoveryMode":{ + "shape":"RecoveryMode", + "documentation":"

    Recovery mode.

    " } } }, @@ -1202,6 +1631,59 @@ } } }, + "CreateRecoveryPlanRequest":{ + "type":"structure", + "required":["name"], + "members":{ + "name":{"shape":"RecoveryPlanName"}, + "description":{"shape":"RecoveryPlanDescription"}, + "clientToken":{ + "shape":"ClientIdempotencyToken", + "documentation":"

    A unique string provided to ensure request idempotency.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags to apply to the Recovery Plan.

    " + } + } + }, + "CreateRecoveryPlanResponse":{ + "type":"structure", + "required":["recoveryPlan"], + "members":{ + "recoveryPlan":{"shape":"RecoveryPlan"} + } + }, + "CreateRecoveryPlanStepRequest":{ + "type":"structure", + "required":[ + "recoveryPlanArn", + "stepName", + "configuration" + ], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan to add the step to.

    " + }, + "stepName":{"shape":"RecoveryPlanStepName"}, + "stepOrder":{"shape":"RecoveryPlanStepOrder"}, + "configuration":{"shape":"RecoveryPlanStepConfiguration"}, + "clientToken":{ + "shape":"ClientIdempotencyToken", + "documentation":"

    A unique string provided to ensure request idempotency.

    ", + "idempotencyToken":true + } + } + }, + "CreateRecoveryPlanStepResponse":{ + "type":"structure", + "required":["recoveryPlanStep"], + "members":{ + "recoveryPlanStep":{"shape":"RecoveryPlanStep"} + } + }, "CreateReplicationConfigurationTemplateRequest":{ "type":"structure", "required":[ @@ -1551,6 +2033,66 @@ } } }, + "DeleteRecoveryPlanExecutionRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionArn"], + "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution to delete.

    " + } + } + }, + "DeleteRecoveryPlanExecutionResponse":{ + "type":"structure", + "required":["recoveryPlanExecutionArn"], + "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the deleted Recovery Plan execution.

    " + } + } + }, + "DeleteRecoveryPlanRequest":{ + "type":"structure", + "required":["recoveryPlanArn"], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan to delete.

    " + } + } + }, + "DeleteRecoveryPlanResponse":{ + "type":"structure", + "required":["recoveryPlanArn"], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the deleted Recovery Plan.

    " + } + } + }, + "DeleteRecoveryPlanStepRequest":{ + "type":"structure", + "required":["recoveryPlanStepArn"], + "members":{ + "recoveryPlanStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan step to delete.

    " + } + } + }, + "DeleteRecoveryPlanStepResponse":{ + "type":"structure", + "required":["recoveryPlanStepArn"], + "members":{ + "recoveryPlanStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the deleted Recovery Plan step.

    " + } + } + }, "DeleteReplicationConfigurationTemplateRequest":{ "type":"structure", "required":["replicationConfigurationTemplateID"], @@ -2024,6 +2566,24 @@ "min":10, "pattern":"vol-([0-9a-fA-F]{8}|[0-9a-fA-F]{17})" }, + "ErrorDetail":{ + "type":"structure", + "required":[ + "message", + "code" + ], + "members":{ + "message":{ + "shape":"String", + "documentation":"

    The error message.

    " + }, + "code":{ + "shape":"String", + "documentation":"

    The error code.

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

    Error details for a failed operation.

    " + }, "EventResourceData":{ "type":"structure", "members":{ @@ -2035,6 +2595,17 @@ "documentation":"

    Properties of resource related to a job event.

    ", "union":true }, + "ExecutionServerStepConfiguration":{ + "type":"structure", + "required":["servers"], + "members":{ + "servers":{ + "shape":"RecoveryPlanExecutionServers", + "documentation":"

    The list of servers in this execution step.

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

    Configuration for a SERVER type execution step.

    " + }, "ExportSourceNetworkCfnTemplateRequest":{ "type":"structure", "required":["sourceNetworkID"], @@ -2159,6 +2730,77 @@ } } }, + "GetRecoveryPlanExecutionRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionArn"], + "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution.

    " + } + } + }, + "GetRecoveryPlanExecutionResponse":{ + "type":"structure", + "required":["recoveryPlanExecution"], + "members":{ + "recoveryPlanExecution":{ + "shape":"RecoveryPlanExecution", + "documentation":"

    The Recovery Plan execution details.

    " + } + } + }, + "GetRecoveryPlanExecutionStepRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionStepArn"], + "members":{ + "recoveryPlanExecutionStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the execution step.

    " + } + } + }, + "GetRecoveryPlanExecutionStepResponse":{ + "type":"structure", + "required":["recoveryPlanExecutionStep"], + "members":{ + "recoveryPlanExecutionStep":{"shape":"RecoveryPlanExecutionStep"} + } + }, + "GetRecoveryPlanRequest":{ + "type":"structure", + "required":["recoveryPlanArn"], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan to retrieve.

    " + } + } + }, + "GetRecoveryPlanResponse":{ + "type":"structure", + "required":["recoveryPlan"], + "members":{ + "recoveryPlan":{"shape":"RecoveryPlan"} + } + }, + "GetRecoveryPlanStepRequest":{ + "type":"structure", + "required":["recoveryPlanStepArn"], + "members":{ + "recoveryPlanStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan step to retrieve.

    " + } + } + }, + "GetRecoveryPlanStepResponse":{ + "type":"structure", + "required":["recoveryPlanStep"], + "members":{ + "recoveryPlanStep":{"shape":"RecoveryPlanStep"} + } + }, "GetReplicationConfigurationRequest":{ "type":"structure", "required":["sourceServerID"], @@ -2689,6 +3331,10 @@ "launchIntoInstanceProperties":{ "shape":"LaunchIntoInstanceProperties", "documentation":"

    Launch into existing instance properties.

    " + }, + "recoveryMode":{ + "shape":"RecoveryMode", + "documentation":"

    Recovery mode.

    " } } }, @@ -2738,6 +3384,10 @@ "launchIntoSourceInstance":{ "shape":"Boolean", "documentation":"

    DRS will set the 'launch into instance ID' of any source server when performing a drill, recovery or failback to the previous region or availability zone, using the instance ID of the source instance.

    " + }, + "recoveryMode":{ + "shape":"RecoveryMode", + "documentation":"

    Recovery mode.

    " } }, "documentation":"

    Account level Launch Configuration Template.

    " @@ -2918,89 +3568,229 @@ } } }, - "ListStagingAccountsRequest":{ + "ListRecoveryPlanExecutionStepsFilter":{ + "type":"structure", + "members":{ + "status":{ + "shape":"RecoveryPlanExecutionStepStatus", + "documentation":"

    Filter by execution step status.

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

    Filters for listing Recovery Plan execution steps.

    " + }, + "ListRecoveryPlanExecutionStepsRequest":{ "type":"structure", + "required":["recoveryPlanExecutionArn"], "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution.

    " + }, + "filter":{ + "shape":"ListRecoveryPlanExecutionStepsFilter", + "documentation":"

    Filters for listing execution steps.

    " + }, "maxResults":{ - "shape":"ListStagingAccountsRequestMaxResultsInteger", - "documentation":"

    The maximum number of staging Accounts to retrieve.

    ", - "location":"querystring", - "locationName":"maxResults" + "shape":"MaxResultsType", + "documentation":"

    Maximum number of results to return.

    " }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    The token of the next staging Account to retrieve.

    ", - "location":"querystring", - "locationName":"nextToken" + "documentation":"

    The token for the next page of results.

    " } } }, - "ListStagingAccountsRequestMaxResultsInteger":{ - "type":"integer", - "box":true, - "max":50, - "min":1 - }, - "ListStagingAccountsResponse":{ + "ListRecoveryPlanExecutionStepsResponse":{ "type":"structure", + "required":["recoveryPlanExecutionSteps"], "members":{ - "accounts":{ - "shape":"Accounts", - "documentation":"

    An array of staging AWS Accounts.

    " + "recoveryPlanExecutionSteps":{ + "shape":"RecoveryPlanExecutionStepSummaryList", + "documentation":"

    The list of execution steps.

    " }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    The token of the next staging Account to retrieve.

    " + "documentation":"

    The token for the next page of results.

    " } } }, - "ListTagsForResourceRequest":{ + "ListRecoveryPlanExecutionsRequest":{ "type":"structure", - "required":["resourceArn"], "members":{ - "resourceArn":{ - "shape":"ARN", - "documentation":"

    The ARN of the resource whose tags should be returned.

    ", - "location":"uri", - "locationName":"resourceArn" + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    Filter executions by Recovery Plan ARN.

    " + }, + "status":{ + "shape":"RecoveryPlanExecutionStatus", + "documentation":"

    Filter executions by status.

    " + }, + "maxResults":{ + "shape":"MaxResultsType", + "documentation":"

    Maximum number of results to return.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " } } }, - "ListTagsForResourceResponse":{ + "ListRecoveryPlanExecutionsResponse":{ "type":"structure", + "required":["recoveryPlanExecutions"], "members":{ - "tags":{ - "shape":"TagsMap", - "documentation":"

    The tags of the requested resource.

    " + "recoveryPlanExecutions":{ + "shape":"RecoveryPlanExecutionSummaryList", + "documentation":"

    The list of Recovery Plan executions.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " } } }, - "MaxResultsReplicatingSourceServers":{ - "type":"integer", - "box":true, - "max":300, - "min":1 - }, - "MaxResultsType":{ - "type":"integer", - "box":true, - "max":1000, - "min":1 - }, - "NetworkInterface":{ + "ListRecoveryPlanStepsRequest":{ "type":"structure", + "required":["recoveryPlanArn"], "members":{ - "macAddress":{ - "shape":"BoundedString", - "documentation":"

    The MAC address of the network interface.

    " + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan.

    " }, - "ips":{ - "shape":"IPsList", - "documentation":"

    Network interface IPs.

    " + "maxResults":{ + "shape":"MaxResultsType", + "documentation":"

    Maximum number of results to return.

    " }, - "isPrimary":{ - "shape":"Boolean", - "documentation":"

    Whether this is the primary network interface.

    " + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListRecoveryPlanStepsResponse":{ + "type":"structure", + "required":["recoveryPlanSteps"], + "members":{ + "recoveryPlanSteps":{ + "shape":"RecoveryPlanStepList", + "documentation":"

    The list of Recovery Plan steps.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListRecoveryPlansRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResultsType", + "documentation":"

    Maximum number of results to return.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListRecoveryPlansResponse":{ + "type":"structure", + "required":["recoveryPlans"], + "members":{ + "recoveryPlans":{ + "shape":"RecoveryPlanSummaryList", + "documentation":"

    The list of Recovery Plans.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "ListStagingAccountsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListStagingAccountsRequestMaxResultsInteger", + "documentation":"

    The maximum number of staging Accounts to retrieve.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token of the next staging Account to retrieve.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListStagingAccountsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":50, + "min":1 + }, + "ListStagingAccountsResponse":{ + "type":"structure", + "members":{ + "accounts":{ + "shape":"Accounts", + "documentation":"

    An array of staging AWS Accounts.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token of the next staging Account to retrieve.

    " + } + } + }, + "ListTagsForResourceRequest":{ + "type":"structure", + "required":["resourceArn"], + "members":{ + "resourceArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the resource whose tags should be returned.

    ", + "location":"uri", + "locationName":"resourceArn" + } + } + }, + "ListTagsForResourceResponse":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags of the requested resource.

    " + } + } + }, + "MaxResultsReplicatingSourceServers":{ + "type":"integer", + "box":true, + "max":300, + "min":1 + }, + "MaxResultsType":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "NetworkInterface":{ + "type":"structure", + "members":{ + "macAddress":{ + "shape":"BoundedString", + "documentation":"

    The MAC address of the network interface.

    " + }, + "ips":{ + "shape":"IPsList", + "documentation":"

    Network interface IPs.

    " + }, + "isPrimary":{ + "shape":"Boolean", + "documentation":"

    Whether this is the primary network interface.

    " } }, "documentation":"

    Network interface.

    " @@ -3037,8 +3827,8 @@ "PITPolicy":{ "type":"list", "member":{"shape":"PITPolicyRule"}, - "max":10, - "min":1 + "max":3, + "min":3 }, "PITPolicyRule":{ "type":"structure", @@ -3476,145 +4266,598 @@ "NOT_STARTED" ] }, - "RecoveryInstanceDisk":{ + "RecoveryInstanceDisk":{ + "type":"structure", + "members":{ + "internalDeviceName":{ + "shape":"BoundedString", + "documentation":"

    The internal device name of this disk. This is the name that is visible on the machine itself and not from the EC2 console.

    " + }, + "bytes":{ + "shape":"PositiveInteger", + "documentation":"

    The amount of storage on the disk in bytes.

    " + }, + "ebsVolumeID":{ + "shape":"EbsVolumeID", + "documentation":"

    The EBS Volume ID of this disk.

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

    An object representing a block storage device on the Recovery Instance.

    " + }, + "RecoveryInstanceDisks":{ + "type":"list", + "member":{"shape":"RecoveryInstanceDisk"}, + "max":1000, + "min":0 + }, + "RecoveryInstanceFailback":{ + "type":"structure", + "members":{ + "failbackClientID":{ + "shape":"BoundedString", + "documentation":"

    The ID of the failback client that this Recovery Instance is associated with.

    " + }, + "failbackJobID":{ + "shape":"JobID", + "documentation":"

    The Job ID of the last failback log for this Recovery Instance.

    " + }, + "failbackInitiationTime":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The date and time that the failback initiation started.

    " + }, + "state":{ + "shape":"FailbackState", + "documentation":"

    The state of the failback process that this Recovery Instance is in.

    " + }, + "agentLastSeenByServiceDateTime":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The date and time the agent on the Recovery Instance was last seen by the service.

    " + }, + "failbackClientLastSeenByServiceDateTime":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The date and time that the failback client was last seen by the service.

    " + }, + "failbackToOriginalServer":{ + "shape":"Boolean", + "documentation":"

    Whether we are failing back to the original Source Server for this Recovery Instance.

    " + }, + "firstByteDateTime":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The date and time of the first byte that was replicated from the Recovery Instance.

    " + }, + "elapsedReplicationDuration":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The amount of time that the Recovery Instance has been replicating for.

    " + }, + "failbackLaunchType":{ + "shape":"FailbackLaunchType", + "documentation":"

    The launch type (Recovery / Drill) of the last launch for the failback replication of this recovery instance.

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

    An object representing failback related information of the Recovery Instance.

    " + }, + "RecoveryInstanceID":{ + "type":"string", + "max":19, + "min":10, + "pattern":"i-[0-9a-fA-F]{8,}" + }, + "RecoveryInstanceIDs":{ + "type":"list", + "member":{"shape":"RecoveryInstanceID"}, + "max":200, + "min":0 + }, + "RecoveryInstanceProperties":{ + "type":"structure", + "members":{ + "lastUpdatedDateTime":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The date and time the Recovery Instance properties were last updated on.

    " + }, + "identificationHints":{ + "shape":"IdentificationHints", + "documentation":"

    Hints used to uniquely identify a machine.

    " + }, + "networkInterfaces":{ + "shape":"NetworkInterfaces", + "documentation":"

    An array of network interfaces.

    " + }, + "disks":{ + "shape":"RecoveryInstanceDisks", + "documentation":"

    An array of disks.

    " + }, + "cpus":{ + "shape":"Cpus", + "documentation":"

    An array of CPUs.

    " + }, + "ramBytes":{ + "shape":"PositiveInteger", + "documentation":"

    The amount of RAM in bytes.

    " + }, + "os":{ + "shape":"OS", + "documentation":"

    Operating system.

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

    Properties of the Recovery Instance machine.

    " + }, + "RecoveryInstancesForTerminationRequest":{ + "type":"list", + "member":{"shape":"RecoveryInstanceID"}, + "max":200, + "min":1 + }, + "RecoveryLifeCycle":{ + "type":"structure", + "members":{ + "apiCallDateTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time the last Source Network recovery was initiated.

    " + }, + "jobID":{ + "shape":"JobID", + "documentation":"

    The ID of the Job that was used to last recover the Source Network.

    " + }, + "lastRecoveryResult":{ + "shape":"RecoveryResult", + "documentation":"

    The status of the last recovery status of this Source Network.

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

    An object representing the Source Network recovery Lifecycle.

    " + }, + "RecoveryMode":{ + "type":"string", + "documentation":"

    Recovery mode to use during launch. FAST skips conversion to reduce recovery time. OPTIMAL runs full conversion for maximum compatibility.

    ", + "enum":[ + "FAST", + "OPTIMAL" + ] + }, + "RecoveryPlan":{ + "type":"structure", + "required":[ + "recoveryPlanArn", + "name", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan.

    " + }, + "name":{"shape":"RecoveryPlanName"}, + "description":{"shape":"RecoveryPlanDescription"}, + "status":{ + "shape":"RecoveryPlanStatus", + "documentation":"

    The status of the Recovery Plan.

    " + }, + "createdAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the Recovery Plan was created.

    " + }, + "updatedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the Recovery Plan was last updated.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags associated with the Recovery Plan.

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

    A Recovery Plan resource.

    " + }, + "RecoveryPlanDescription":{ + "type":"string", + "documentation":"

    The description of a Recovery Plan.

    ", + "max":1024, + "min":0 + }, + "RecoveryPlanExecution":{ + "type":"structure", + "required":[ + "recoveryPlanExecutionArn", + "recoveryPlanArn", + "mode", + "status", + "startedAt" + ], + "members":{ + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution.

    " + }, + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan being executed.

    " + }, + "mode":{ + "shape":"RecoveryPlanExecutionMode", + "documentation":"

    The execution mode.

    " + }, + "status":{ + "shape":"RecoveryPlanExecutionStatus", + "documentation":"

    The execution status.

    " + }, + "startedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the execution started.

    " + }, + "completedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the execution completed.

    " + }, + "errorDetail":{ + "shape":"ErrorDetail", + "documentation":"

    Error details if the execution failed.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags associated with the Recovery Plan execution.

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

    A Recovery Plan execution.

    " + }, + "RecoveryPlanExecutionMode":{ + "type":"string", + "documentation":"

    Execution mode. DRILL for testing, RECOVERY for actual disaster recovery.

    ", + "enum":[ + "DRILL", + "RECOVERY" + ] + }, + "RecoveryPlanExecutionServer":{ + "type":"structure", + "required":["serverArn"], + "members":{ + "serverArn":{ + "shape":"SourceServerARN", + "documentation":"

    The ARN of the source server.

    " + }, + "impactLevel":{ + "shape":"RecoveryPlanServerImpactLevel", + "documentation":"

    Defaults to CRITICAL if not specified.

    " + }, + "jobID":{ + "shape":"JobID", + "documentation":"

    The DRS recovery job ID. Populated when recovery is initiated for this server.

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

    A server within a recovery plan execution step, enriched with execution state.

    " + }, + "RecoveryPlanExecutionServers":{ + "type":"list", + "member":{"shape":"RecoveryPlanExecutionServer"}, + "max":100, + "min":1 + }, + "RecoveryPlanExecutionSourceServer":{ + "type":"structure", + "required":[ + "sourceServerID", + "recoverySnapshotID" + ], + "members":{ + "sourceServerID":{ + "shape":"SourceServerID", + "documentation":"

    The ID of the source server.

    " + }, + "recoverySnapshotID":{ + "shape":"RecoverySnapshotID", + "documentation":"

    The ID of the recovery snapshot to use.

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

    A source server with a specific recovery snapshot for plan execution.

    " + }, + "RecoveryPlanExecutionSourceServerList":{ + "type":"list", + "member":{"shape":"RecoveryPlanExecutionSourceServer"}, + "max":200, + "min":0 + }, + "RecoveryPlanExecutionStatus":{ + "type":"string", + "documentation":"

    The status of a Recovery Plan execution.

    ", + "enum":[ + "CREATED", + "IN_PROGRESS", + "COMPLETED", + "FAILED", + "CANCELLING", + "CANCELLED" + ] + }, + "RecoveryPlanExecutionStep":{ + "type":"structure", + "required":[ + "recoveryPlanExecutionStepArn", + "stepIndex", + "status", + "stepName", + "configuration", + "attempt", + "createdAt", + "updatedAt" + ], + "members":{ + "recoveryPlanExecutionStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the execution step.

    " + }, + "stepIndex":{"shape":"RecoveryPlanStepOrder"}, + "status":{ + "shape":"RecoveryPlanExecutionStepStatus", + "documentation":"

    The status of the execution step.

    " + }, + "stepName":{"shape":"RecoveryPlanStepName"}, + "configuration":{"shape":"RecoveryPlanExecutionStepConfiguration"}, + "errorDetail":{ + "shape":"ErrorDetail", + "documentation":"

    Error details if the step failed.

    " + }, + "attempt":{ + "shape":"StrictlyPositiveInteger", + "documentation":"

    The number of times this step has been attempted.

    " + }, + "createdAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the execution step was created.

    " + }, + "updatedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the execution step was last updated.

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

    A Recovery Plan Execution Step resource.

    " + }, + "RecoveryPlanExecutionStepConfiguration":{ + "type":"structure", + "members":{ + "executionServerStepConfiguration":{ + "shape":"ExecutionServerStepConfiguration", + "documentation":"

    Configuration for a SERVER type step (with execution state like jobID).

    " + }, + "waitStepConfiguration":{ + "shape":"WaitStepConfiguration", + "documentation":"

    Configuration for a WAIT type step.

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

    Type-specific configuration for an execution step response. Mirrors RecoveryPlanStepConfiguration but uses execution-enriched server shapes.

    ", + "union":true + }, + "RecoveryPlanExecutionStepStatus":{ + "type":"string", + "documentation":"

    The status of a step within a Recovery Plan execution.

    ", + "enum":[ + "NOT_STARTED", + "EXECUTING", + "WAITING", + "COMPLETED", + "FAILED", + "TIMED_OUT", + "SKIPPED" + ] + }, + "RecoveryPlanExecutionStepSummary":{ "type":"structure", + "required":[ + "recoveryPlanExecutionStepArn", + "stepName", + "stepIndex", + "status", + "configuration" + ], "members":{ - "internalDeviceName":{ - "shape":"BoundedString", - "documentation":"

    The internal device name of this disk. This is the name that is visible on the machine itself and not from the EC2 console.

    " + "recoveryPlanExecutionStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the execution step.

    " }, - "bytes":{ - "shape":"PositiveInteger", - "documentation":"

    The amount of storage on the disk in bytes.

    " + "stepName":{"shape":"RecoveryPlanStepName"}, + "stepIndex":{"shape":"RecoveryPlanStepOrder"}, + "status":{ + "shape":"RecoveryPlanExecutionStepStatus", + "documentation":"

    The status of the execution step.

    " }, - "ebsVolumeID":{ - "shape":"EbsVolumeID", - "documentation":"

    The EBS Volume ID of this disk.

    " + "configuration":{"shape":"RecoveryPlanExecutionStepConfiguration"}, + "errorDetail":{ + "shape":"ErrorDetail", + "documentation":"

    Error details if the step failed.

    " } }, - "documentation":"

    An object representing a block storage device on the Recovery Instance.

    " + "documentation":"

    Summary information about a Recovery Plan execution step.

    " }, - "RecoveryInstanceDisks":{ + "RecoveryPlanExecutionStepSummaryList":{ "type":"list", - "member":{"shape":"RecoveryInstanceDisk"}, - "max":1000, - "min":0 + "member":{"shape":"RecoveryPlanExecutionStepSummary"} }, - "RecoveryInstanceFailback":{ + "RecoveryPlanExecutionSummary":{ "type":"structure", + "required":[ + "recoveryPlanExecutionArn", + "recoveryPlanArn", + "mode", + "status", + "startedAt" + ], "members":{ - "failbackClientID":{ - "shape":"BoundedString", - "documentation":"

    The ID of the failback client that this Recovery Instance is associated with.

    " - }, - "failbackJobID":{ - "shape":"JobID", - "documentation":"

    The Job ID of the last failback log for this Recovery Instance.

    " - }, - "failbackInitiationTime":{ - "shape":"ISO8601DatetimeString", - "documentation":"

    The date and time that the failback initiation started.

    " - }, - "state":{ - "shape":"FailbackState", - "documentation":"

    The state of the failback process that this Recovery Instance is in.

    " + "recoveryPlanExecutionArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan execution.

    " }, - "agentLastSeenByServiceDateTime":{ - "shape":"ISO8601DatetimeString", - "documentation":"

    The date and time the agent on the Recovery Instance was last seen by the service.

    " + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan.

    " }, - "failbackClientLastSeenByServiceDateTime":{ - "shape":"ISO8601DatetimeString", - "documentation":"

    The date and time that the failback client was last seen by the service.

    " + "mode":{ + "shape":"RecoveryPlanExecutionMode", + "documentation":"

    The execution mode.

    " }, - "failbackToOriginalServer":{ - "shape":"Boolean", - "documentation":"

    Whether we are failing back to the original Source Server for this Recovery Instance.

    " + "status":{ + "shape":"RecoveryPlanExecutionStatus", + "documentation":"

    The execution status.

    " }, - "firstByteDateTime":{ + "startedAt":{ "shape":"ISO8601DatetimeString", - "documentation":"

    The date and time of the first byte that was replicated from the Recovery Instance.

    " + "documentation":"

    The timestamp when the execution started.

    " }, - "elapsedReplicationDuration":{ - "shape":"ISO8601DatetimeString", - "documentation":"

    The amount of time that the Recovery Instance has been replicating for.

    " + "errorDetail":{ + "shape":"ErrorDetail", + "documentation":"

    Error details if the execution failed.

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

    Summary information about a Recovery Plan execution.

    " + }, + "RecoveryPlanExecutionSummaryList":{ + "type":"list", + "member":{"shape":"RecoveryPlanExecutionSummary"} + }, + "RecoveryPlanName":{ + "type":"string", + "documentation":"

    The name of a Recovery Plan.

    ", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _-]*" + }, + "RecoveryPlanServer":{ + "type":"structure", + "required":["serverArn"], + "members":{ + "serverArn":{ + "shape":"SourceServerARN", + "documentation":"

    The ARN of the source server.

    " }, - "failbackLaunchType":{ - "shape":"FailbackLaunchType", - "documentation":"

    The launch type (Recovery / Drill) of the last launch for the failback replication of this recovery instance.

    " + "impactLevel":{ + "shape":"RecoveryPlanServerImpactLevel", + "documentation":"

    Defaults to CRITICAL if not specified.

    " } }, - "documentation":"

    An object representing failback related information of the Recovery Instance.

    " + "documentation":"

    A server associated with a Recovery Plan Step.

    " }, - "RecoveryInstanceID":{ + "RecoveryPlanServerImpactLevel":{ "type":"string", - "max":19, - "min":10, - "pattern":"i-[0-9a-fA-F]{8,}" + "documentation":"

    The impact level of a server within a Recovery Plan step. CRITICAL means the step fails if this server fails. OPTIONAL means the step continues even if this server fails.

    ", + "enum":[ + "CRITICAL", + "OPTIONAL" + ] }, - "RecoveryInstanceIDs":{ + "RecoveryPlanServers":{ "type":"list", - "member":{"shape":"RecoveryInstanceID"}, - "max":200, - "min":0 + "member":{"shape":"RecoveryPlanServer"}, + "max":100, + "min":1 }, - "RecoveryInstanceProperties":{ + "RecoveryPlanStatus":{ + "type":"string", + "documentation":"

    Recovery Plan status. ACTIVE means executable. INVALID means the plan has no SERVER type steps and cannot be executed.

    ", + "enum":[ + "ACTIVE", + "INVALID" + ] + }, + "RecoveryPlanStep":{ "type":"structure", + "required":[ + "recoveryPlanStepArn", + "stepOrder", + "stepName", + "configuration", + "createdAt", + "updatedAt" + ], "members":{ - "lastUpdatedDateTime":{ - "shape":"ISO8601DatetimeString", - "documentation":"

    The date and time the Recovery Instance properties were last updated on.

    " - }, - "identificationHints":{ - "shape":"IdentificationHints", - "documentation":"

    Hints used to uniquely identify a machine.

    " - }, - "networkInterfaces":{ - "shape":"NetworkInterfaces", - "documentation":"

    An array of network interfaces.

    " - }, - "disks":{ - "shape":"RecoveryInstanceDisks", - "documentation":"

    An array of disks.

    " + "recoveryPlanStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan step.

    " }, - "cpus":{ - "shape":"Cpus", - "documentation":"

    An array of CPUs.

    " + "stepOrder":{"shape":"RecoveryPlanStepOrder"}, + "stepName":{"shape":"RecoveryPlanStepName"}, + "configuration":{"shape":"RecoveryPlanStepConfiguration"}, + "createdAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the step was created.

    " }, - "ramBytes":{ - "shape":"PositiveInteger", - "documentation":"

    The amount of RAM in bytes.

    " + "updatedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the step was last updated.

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

    A Recovery Plan Step resource.

    " + }, + "RecoveryPlanStepArnList":{ + "type":"list", + "member":{"shape":"StrictDRSARN"}, + "max":20, + "min":1 + }, + "RecoveryPlanStepConfiguration":{ + "type":"structure", + "members":{ + "serverStepConfiguration":{ + "shape":"ServerStepConfiguration", + "documentation":"

    Configuration for a SERVER type step.

    " }, - "os":{ - "shape":"OS", - "documentation":"

    Operating system.

    " + "waitStepConfiguration":{ + "shape":"WaitStepConfiguration", + "documentation":"

    Configuration for a WAIT type step.

    " } }, - "documentation":"

    Properties of the Recovery Instance machine.

    " + "documentation":"

    Type-specific configuration for a recovery plan step. Exactly one member must be set.

    ", + "union":true }, - "RecoveryInstancesForTerminationRequest":{ + "RecoveryPlanStepList":{ "type":"list", - "member":{"shape":"RecoveryInstanceID"}, - "max":200, + "member":{"shape":"RecoveryPlanStep"} + }, + "RecoveryPlanStepName":{ + "type":"string", + "documentation":"

    The name of a Recovery Plan Step.

    ", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _-]*" + }, + "RecoveryPlanStepOrder":{ + "type":"integer", + "documentation":"

    The order of a step within a Recovery Plan (1-based).

    ", + "box":true, + "max":20, "min":1 }, - "RecoveryLifeCycle":{ + "RecoveryPlanSummary":{ "type":"structure", + "required":[ + "recoveryPlanArn", + "name", + "status", + "createdAt", + "updatedAt" + ], "members":{ - "apiCallDateTime":{ - "shape":"SyntheticTimestamp_date_time", - "documentation":"

    The date and time the last Source Network recovery was initiated.

    " + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan.

    " }, - "jobID":{ - "shape":"JobID", - "documentation":"

    The ID of the Job that was used to last recover the Source Network.

    " + "name":{"shape":"RecoveryPlanName"}, + "status":{ + "shape":"RecoveryPlanStatus", + "documentation":"

    The status of the Recovery Plan.

    " }, - "lastRecoveryResult":{ - "shape":"RecoveryResult", - "documentation":"

    The status of the last recovery status of this Source Network.

    " + "createdAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the Recovery Plan was created.

    " + }, + "updatedAt":{ + "shape":"ISO8601DatetimeString", + "documentation":"

    The timestamp when the Recovery Plan was last updated.

    " } }, - "documentation":"

    An object representing the Source Network recovery Lifecycle.

    " + "documentation":"

    Summary information about a Recovery Plan.

    " + }, + "RecoveryPlanSummaryList":{ + "type":"list", + "member":{"shape":"RecoveryPlanSummary"} }, "RecoveryResult":{ "type":"string", @@ -3676,6 +4919,33 @@ "DESC" ] }, + "ReorderRecoveryPlanStepsRequest":{ + "type":"structure", + "required":[ + "recoveryPlanArn", + "orderedStepArns" + ], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan.

    " + }, + "orderedStepArns":{ + "shape":"RecoveryPlanStepArnList", + "documentation":"

    Ordered list of all step ARNs representing the desired sequence.

    " + } + } + }, + "ReorderRecoveryPlanStepsResponse":{ + "type":"structure", + "required":["recoveryPlanSteps"], + "members":{ + "recoveryPlanSteps":{ + "shape":"RecoveryPlanStepList", + "documentation":"

    The steps with updated order.

    " + } + } + }, "ReplicationConfiguration":{ "type":"structure", "members":{ @@ -3975,6 +5245,23 @@ "deprecated":true, "deprecatedMessage":"WARNING: RetryDataReplication is deprecated" }, + "RetryRecoveryPlanExecutionStepRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionStepArn"], + "members":{ + "recoveryPlanExecutionStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the execution step to retry.

    " + } + } + }, + "RetryRecoveryPlanExecutionStepResponse":{ + "type":"structure", + "required":["recoveryPlanExecutionStep"], + "members":{ + "recoveryPlanExecutionStep":{"shape":"RecoveryPlanExecutionStep"} + } + }, "ReverseReplicationRequest":{ "type":"structure", "required":["recoveryInstanceID"], @@ -4006,6 +5293,17 @@ "min":0, "sensitive":true }, + "ServerStepConfiguration":{ + "type":"structure", + "required":["servers"], + "members":{ + "servers":{ + "shape":"RecoveryPlanServers", + "documentation":"

    The list of servers to recover in this step.

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

    Configuration for a SERVER type step.

    " + }, "ServiceQuotaExceededException":{ "type":"structure", "members":{ @@ -4182,6 +5480,10 @@ "supportsNitroInstances":{ "shape":"Boolean", "documentation":"

    Are EC2 nitro instance types supported when recovering the Source Server.

    " + }, + "architecture":{ + "shape":"SourceServerArchitecture", + "documentation":"

    The architecture of the Source Server.

    " } }, "documentation":"

    Properties of the Source Server machine.

    " @@ -4253,6 +5555,13 @@ "min":20, "pattern":"arn:(?:[0-9a-zA-Z_-]+:){3}([0-9]{12,}):source-server/(s-[0-9a-zA-Z]{17})" }, + "SourceServerArchitecture":{ + "type":"string", + "enum":[ + "x86_64", + "arm64" + ] + }, "SourceServerID":{ "type":"string", "max":19, @@ -4346,6 +5655,46 @@ "max":200, "min":1 }, + "StartRecoveryPlanExecutionRequest":{ + "type":"structure", + "required":[ + "recoveryPlanArn", + "mode" + ], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan to execute.

    " + }, + "mode":{ + "shape":"RecoveryPlanExecutionMode", + "documentation":"

    The execution mode (DRILL or RECOVERY).

    " + }, + "clientToken":{ + "shape":"ClientIdempotencyToken", + "documentation":"

    A unique string provided to ensure request idempotency.

    ", + "idempotencyToken":true + }, + "sourceServers":{ + "shape":"RecoveryPlanExecutionSourceServerList", + "documentation":"

    Optional list of source servers with specific recovery snapshots. If not provided, the latest snapshot is used for each server.

    " + }, + "tags":{ + "shape":"TagsMap", + "documentation":"

    The tags to apply to the Recovery Plan execution.

    " + } + } + }, + "StartRecoveryPlanExecutionResponse":{ + "type":"structure", + "required":["recoveryPlanExecution"], + "members":{ + "recoveryPlanExecution":{ + "shape":"RecoveryPlanExecution", + "documentation":"

    The started Recovery Plan execution.

    " + } + } + }, "StartRecoveryRequest":{ "type":"structure", "required":["sourceServers"], @@ -4528,11 +5877,19 @@ } } }, + "StrictDRSARN":{ + "type":"string", + "documentation":"

    Strict ARN type for Recovery Plan resources. Only allows safe characters in the resource portion — rejects HTML/script injection characters (<, >, ", ', etc.) per AWS API input validation standards. Resource portion allows: [A-Za-z0-9_/.-] which covers all DRS recovery plan resource identifiers (plan-xxx, st-xxx, exec-xxx, step-xxx).

    ", + "max":2048, + "min":20, + "pattern":"arn:aws(-[a-z0-9]+)*:drs:[a-z0-9-]+:[0-9]{12}:[a-zA-Z0-9_/.-]+" + }, "StrictlyPositiveInteger":{ "type":"integer", "box":true, "min":1 }, + "String":{"type":"string"}, "SubnetID":{ "type":"string", "max":255, @@ -4736,6 +6093,10 @@ "launchIntoInstanceProperties":{ "shape":"LaunchIntoInstanceProperties", "documentation":"

    Launch into existing instance properties.

    " + }, + "recoveryMode":{ + "shape":"RecoveryMode", + "documentation":"

    Recovery mode.

    " } } }, @@ -4778,6 +6139,10 @@ "launchIntoSourceInstance":{ "shape":"Boolean", "documentation":"

    DRS will set the 'launch into instance ID' of any source server when performing a drill, recovery or failback to the previous region or availability zone, using the instance ID of the source instance.

    " + }, + "recoveryMode":{ + "shape":"RecoveryMode", + "documentation":"

    Recovery mode.

    " } } }, @@ -4790,6 +6155,73 @@ } } }, + "UpdateRecoveryPlanExecutionStepRequest":{ + "type":"structure", + "required":["recoveryPlanExecutionStepArn"], + "members":{ + "recoveryPlanExecutionStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the execution step to update.

    " + }, + "status":{ + "shape":"RecoveryPlanExecutionStepStatus", + "documentation":"

    Only SKIPPED is accepted. Step must be in NOT_STARTED or FAILED status.

    " + }, + "servers":{ + "shape":"RecoveryPlanServers", + "documentation":"

    Full replacement of the server list. Only allowed when the step is in NOT_STARTED status (Server type steps only).

    " + }, + "waitDurationMinutes":{ + "shape":"WaitDurationMinutes", + "documentation":"

    Updated wait duration. Only allowed when the step is in NOT_STARTED status (Wait type steps only).

    " + } + } + }, + "UpdateRecoveryPlanExecutionStepResponse":{ + "type":"structure", + "required":["recoveryPlanExecutionStep"], + "members":{ + "recoveryPlanExecutionStep":{"shape":"RecoveryPlanExecutionStep"} + } + }, + "UpdateRecoveryPlanRequest":{ + "type":"structure", + "required":["recoveryPlanArn"], + "members":{ + "recoveryPlanArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan to update.

    " + }, + "name":{"shape":"RecoveryPlanName"}, + "description":{"shape":"RecoveryPlanDescription"} + } + }, + "UpdateRecoveryPlanResponse":{ + "type":"structure", + "required":["recoveryPlan"], + "members":{ + "recoveryPlan":{"shape":"RecoveryPlan"} + } + }, + "UpdateRecoveryPlanStepRequest":{ + "type":"structure", + "required":["recoveryPlanStepArn"], + "members":{ + "recoveryPlanStepArn":{ + "shape":"StrictDRSARN", + "documentation":"

    The ARN of the Recovery Plan step to update.

    " + }, + "stepName":{"shape":"RecoveryPlanStepName"}, + "configuration":{"shape":"RecoveryPlanStepConfiguration"} + } + }, + "UpdateRecoveryPlanStepResponse":{ + "type":"structure", + "required":["recoveryPlanStep"], + "members":{ + "recoveryPlanStep":{"shape":"RecoveryPlanStep"} + } + }, "UpdateReplicationConfigurationRequest":{ "type":"structure", "required":["sourceServerID"], @@ -5020,6 +6452,21 @@ "max":21, "min":12, "pattern":"vpc-[0-9a-fA-F]{8,}" + }, + "WaitDurationMinutes":{ + "type":"integer", + "documentation":"

    The wait duration in minutes for a Wait type step.

    ", + "box":true, + "max":120, + "min":1 + }, + "WaitStepConfiguration":{ + "type":"structure", + "required":["waitDurationMinutes"], + "members":{ + "waitDurationMinutes":{"shape":"WaitDurationMinutes"} + }, + "documentation":"

    Configuration for a WAIT type step.

    " } }, "documentation":"

    AWS Elastic Disaster Recovery Service.

    " diff --git a/services/dsql/pom.xml b/services/dsql/pom.xml index 4be451fcdba5..cf05d17130c0 100644 --- a/services/dsql/pom.xml +++ b/services/dsql/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dsql AWS Java SDK :: Services :: DSQL diff --git a/services/dsql/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/dsql/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..dc1dba984f66 --- /dev/null +++ b/services/dsql/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dsql-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dsql.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/dsql/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/dsql/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ce4eee3f6589..000000000000 --- a/services/dsql/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://dsql-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://dsql.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/dsql/src/main/resources/codegen-resources/service-2.json b/services/dsql/src/main/resources/codegen-resources/service-2.json index 27de88f586c5..93877be4468c 100644 --- a/services/dsql/src/main/resources/codegen-resources/service-2.json +++ b/services/dsql/src/main/resources/codegen-resources/service-2.json @@ -319,7 +319,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"} ], - "documentation":"

    The UpdateCluster API allows you to modify both single-Region and multi-Region cluster configurations. With the multiRegionProperties parameter, you can add or modify witness Region support and manage peer relationships with clusters in other Regions.

    Note that updating multi-Region clusters requires additional IAM permissions beyond those needed for standard cluster updates, as detailed in the Permissions section.

    Required permissions

    dsql:UpdateCluster

    Permission to update a DSQL cluster.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:PutMultiRegionProperties

    Permission to configure multi-Region properties for a cluster.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:GetCluster

    Permission to retrieve cluster information.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:AddPeerCluster

    Permission to add peer clusters.

    Resources:

    • Local cluster: arn:aws:dsql:region:account-id:cluster/cluster-id

    • Each peer cluster: exact ARN of each specified peer cluster

    dsql:RemovePeerCluster

    Permission to remove peer clusters. The dsql:RemovePeerCluster permission uses a wildcard ARN pattern to simplify permission management during updates.

    Resources: arn:aws:dsql:*:account-id:cluster/*

    dsql:PutWitnessRegion

    Permission to set a witness Region.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    Condition Keys: dsql:WitnessRegion (matching the specified witness Region)

    This permission is checked both in the cluster Region and in the witness Region.

    • The witness region specified in multiRegionProperties.witnessRegion cannot be the same as the cluster's Region.

    • When updating clusters with peer relationships, permissions are checked for both adding and removing peers.

    • The dsql:RemovePeerCluster permission uses a wildcard ARN pattern to simplify permission management during updates.

    " + "documentation":"

    The UpdateCluster API allows you to modify both single-Region and multi-Region cluster configurations. With the multiRegionProperties parameter, you can add or modify witness Region support and manage peer relationships with clusters in other Regions.

    Note that updating multi-Region clusters requires additional IAM permissions beyond those needed for standard cluster updates, as detailed in the Permissions section.

    Required permissions

    dsql:UpdateCluster

    Permission to update a DSQL cluster.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:PutMultiRegionProperties

    Permission to configure multi-Region properties for a cluster.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:GetCluster

    Permission to retrieve cluster information.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    dsql:AddPeerCluster

    Permission to add peer clusters.

    Resources:

    • Local cluster: arn:aws:dsql:region:account-id:cluster/cluster-id

    • Each peer cluster: exact ARN of each specified peer cluster

    dsql:RemovePeerCluster

    Permission to remove peer clusters. When you list peer clusters in multiRegionProperties.clusters, you need this permission for each current peer cluster that your list omits.

    Resources:

    • Each removed peer cluster: exact ARN of each removed peer cluster, in its own Region

    dsql:PutWitnessRegion

    Permission to set a witness Region.

    Resources: arn:aws:dsql:region:account-id:cluster/cluster-id

    Condition Keys: dsql:WitnessRegion (matching the specified witness Region)

    This permission is checked both in the cluster Region and in the witness Region.

    • The witness Region specified in multiRegionProperties.witnessRegion cannot be the same as the cluster's Region.

    • When you list peer clusters in multiRegionProperties.clusters, you need dsql:AddPeerCluster for every peer cluster in your request. You need dsql:RemovePeerCluster only for the peer clusters that the update removes.

    " } }, "shapes":{ @@ -1001,7 +1001,7 @@ "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Kinesis Data Stream.

    ", "max":2048, "min":1, - "pattern":"arn:aws.*:kinesis:.*:\\d{12}:stream/\\S+" + "pattern":"arn:aws[a-zA-Z-]*:kinesis:[a-z0-9-]*:[0-9]{12}:stream/[a-zA-Z0-9+=,.@_/\\-]+" }, "KinesisTargetDefinition":{ "type":"structure", @@ -1233,7 +1233,7 @@ "documentation":"

    The name of the VPC endpoint service that provides access to your cluster. Use this endpoint to establish a private connection between your VPC and the cluster.

    ", "max":128, "min":1, - "pattern":"com\\.amazonaws\\.[a-z0-9-]+\\.dsql-[a-f0-9]{6}" + "pattern":"com\\.amazonaws\\.[a-z0-9-]+\\.dsql[a-z0-9-]*" }, "ServiceQuotaExceededException":{ "type":"structure", @@ -1508,7 +1508,7 @@ }, "kmsEncryptionKey":{ "shape":"KmsEncryptionKey", - "documentation":"

    The KMS key that encrypts and protects the data on your cluster. You can specify the ARN, ID, or alias of an existing key or have Amazon Web Services create a default key for you.

    " + "documentation":"

    The KMS key that encrypts and protects the data on your cluster. You can specify the ARN, ID, or alias of an existing key or have Amazon Web Services create a default key for you.

    To switch to the key owned by Amazon Web Services, specify the reserved value AWS_OWNED_KMS_KEY.

    " }, "clientToken":{ "shape":"ClientToken", diff --git a/services/dynamodb/pom.xml b/services/dynamodb/pom.xml index a0c5a8573864..5dfb1584acec 100644 --- a/services/dynamodb/pom.xml +++ b/services/dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT dynamodb AWS Java SDK :: Services :: Amazon DynamoDB diff --git a/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/DynamoDbJavaClientRetryOnTimeoutIntegrationTest.java b/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/DynamoDbJavaClientRetryOnTimeoutIntegrationTest.java index 163607d23e60..e04bbbb4fa9d 100644 --- a/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/DynamoDbJavaClientRetryOnTimeoutIntegrationTest.java +++ b/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/DynamoDbJavaClientRetryOnTimeoutIntegrationTest.java @@ -65,9 +65,8 @@ public static RetryPolicy createRetryPolicyWithCounter(AtomicInteger counter, In public void testRetryAttemptsOnTimeOut() throws Exception { AtomicInteger atomicInteger = new AtomicInteger(0); Boolean apiTimeOutExceptionOccurred = Boolean.FALSE; - setupWithRetryPolicy(createRetryPolicyWithCounter(atomicInteger, RETRY_ATTEMPTS), 2); + setupWithRetryPolicy(createRetryPolicyWithCounter(atomicInteger, RETRY_ATTEMPTS), 5); try { - ddb.listTables(); } catch (ApiCallAttemptTimeoutException e) { apiTimeOutExceptionOccurred = true; diff --git a/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/ParallelScanIntegrationTest.java b/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/ParallelScanIntegrationTest.java index 799cc9487d54..a4ee1ad016c6 100644 --- a/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/ParallelScanIntegrationTest.java +++ b/services/dynamodb/src/it/java/software/amazon/awssdk/services/dynamodb/ParallelScanIntegrationTest.java @@ -88,43 +88,40 @@ private static void putTestData() { public void testParallelScan() { putTestData(); + Condition filterCondition = Condition.builder() + .attributeValueList(AttributeValue.builder().n("" + itemNumber / 2).build()) + .comparisonOperator(ComparisonOperator.LT.toString()) + .build(); + Map scanFilter = Collections.singletonMap(ATTRIBUTE_RANDOM, filterCondition); + /** - * Only one segment. + * Only one segment — use scanPaginator to handle pagination automatically. */ - ScanRequest scanRequest = ScanRequest.builder() + int totalScannedCount = 0; + int filteredItems = 0; + for (ScanResponse page : dynamo.scanPaginator(ScanRequest.builder() .tableName(tableName) - .scanFilter(Collections.singletonMap( - ATTRIBUTE_RANDOM, - Condition.builder() - .attributeValueList( - AttributeValue.builder().n("" + itemNumber / 2).build()) - .comparisonOperator( - ComparisonOperator.LT.toString()).build())) - .totalSegments(1).segment(0).build(); - ScanResponse scanResult = dynamo.scan(scanRequest); - assertEquals((Object) itemNumber, (Object) scanResult.scannedCount()); - int filteredItems = scanResult.count(); + .scanFilter(scanFilter) + .totalSegments(1).segment(0) + .build())) { + totalScannedCount += page.scannedCount(); + filteredItems += page.count(); + } + assertEquals((Object) itemNumber, (Object) totalScannedCount); /** - * Multiple segments. + * Multiple segments — use scanPaginator for each segment. */ int totalSegments = 10; int filteredItemsInsegments = 0; for (int segment = 0; segment < totalSegments; segment++) { - scanRequest = ScanRequest.builder() + for (ScanResponse page : dynamo.scanPaginator(ScanRequest.builder() .tableName(tableName) - .scanFilter( - Collections.singletonMap( - ATTRIBUTE_RANDOM, - Condition.builder().attributeValueList( - AttributeValue.builder().n("" - + itemNumber / 2).build()) - .comparisonOperator( - ComparisonOperator.LT - .toString()).build())) - .totalSegments(totalSegments).segment(segment).build(); - scanResult = dynamo.scan(scanRequest); - filteredItemsInsegments += scanResult.count(); + .scanFilter(scanFilter) + .totalSegments(totalSegments).segment(segment) + .build())) { + filteredItemsInsegments += page.count(); + } } assertEquals(filteredItems, filteredItemsInsegments); } diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/customization.config b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/customization.config index 22bdb5244ee6..01363ce0186e 100644 --- a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/customization.config +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/customization.config @@ -37,6 +37,5 @@ ], "customRetryStrategy" : "software.amazon.awssdk.services.dynamodb.DynamoDbRetryPolicy", "enableEndpointDiscoveryMethodRequired": true, - "enableGenerateCompiledEndpointRules": true, "enableEndpointProviderUriCaching": true } diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-bdd-1.json b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-bdd-1.json new file mode 100644 index 000000000000..3613e61fbc38 --- /dev/null +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-bdd-1.json @@ -0,0 +1,761 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "AccountId": { + "builtIn": "AWS::Auth::AccountId", + "required": false, + "documentation": "The AWS AccountId used for the request.", + "type": "string" + }, + "AccountIdEndpointMode": { + "builtIn": "AWS::Auth::AccountIdEndpointMode", + "required": false, + "documentation": "The AccountId Endpoint Mode.", + "type": "string" + }, + "ResourceArn": { + "required": false, + "documentation": "ResourceArn containing arn of resource", + "type": "string" + }, + "ResourceArnList": { + "required": false, + "documentation": "ResourceArnList containing list of resource arns", + "type": "stringArray" + }, + "IsSearchOperation": { + "required": false, + "documentation": "Set to true for SearchVectors to route to the Search FQDN", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "local" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "parsedEndpoint" + }, + { + "fn": "stringEquals", + "argv": [ + "dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}", + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedEndpoint" + }, + "authority" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + "search-dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}", + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedEndpoint" + }, + "authority" + ] + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountIdEndpointMode" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountIdEndpointMode" + }, + "disabled" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ResourceArn" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "ResourceArn" + } + ], + "assign": "ParsedArn_ssa_2" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_2" + }, + "region" + ] + }, + { + "ref": "Region" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_2" + }, + "service" + ] + }, + "dynamodb" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_2" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_2" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ResourceArnList" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "ResourceArnList" + }, + "[0]" + ], + "assign": "FirstArn" + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "FirstArn" + } + ], + "assign": "ParsedArn_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_1" + }, + "region" + ] + }, + { + "ref": "Region" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_1" + }, + "service" + ] + }, + "dynamodb" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_1" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "ParsedArn_ssa_1" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountId" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountIdEndpointMode" + }, + "required" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "AccountId" + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "IsSearchOperation" + }, + false + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and local endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and local endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "http://localhost:8000", + "properties": { + "authSchemes": [ + { + "signingRegion": "us-east-1", + "name": "sigv4", + "signingName": "dynamodb" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://search-dynamodb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dynamodb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://search-dynamodb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dynamodb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://search-dynamodb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dynamodb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_2#accountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_2#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_1#accountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_1#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Credentials-sourced account ID parameter is invalid", + "type": "error" + }, + { + "conditions": [], + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://search-dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_2#accountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_2#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_1#accountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn_ssa_1#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 82, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEjAAAAAgX14QEAAAAFAAAAAwX14QIF9eEEAAAAAQAAAE0AAAAHAAAAAgAAAD0AAAAIAAAAAwAAACIAAAAJAAAABAAAAAoF9eEjAAAABQX14QcAAAALAAAACwAAAAwAAABFAAAADAAAAA4AAAANAAAAHAX14RkAAABFAAAADQAAACEAAAAPAAAADgAAABAAAAAVAAAADwAAABEAAAAVAAAAEAAAABIAAAAVAAAAEQAAABMAAAAVAAAAEgAAABQAAAAVAAAAEwAAACAAAAAVAAAAFAAAABYAAAAcAAAAFQAAABcAAAAcAAAAFgAAABgAAAAcAAAAFwAAABkAAAAcAAAAGAAAABoAAAAcAAAAGQAAABsAAAAcAAAAGgAAAB8AAAAcAAAAGwAAAB0AAAAhAAAAHQAAAB4F9eEXAAAAHwX14SEF9eEiAAAAHwX14R8F9eEgAAAAHwX14R0F9eEeAAAAHAX14RgAAABFAAAABAAAACMF9eEjAAAABQX14QYAAAAkAAAACQAAACUF9eEcAAAACwAAACYAAAA8AAAADAAAACgAAAAnAAAAHAX14RkAAAA8AAAADQAAADsAAAApAAAADgAAACoAAAAvAAAADwAAACsAAAAvAAAAEAAAACwAAAAvAAAAEQAAAC0AAAAvAAAAEgAAAC4AAAAvAAAAEwAAADoAAAAvAAAAFAAAADAAAAA2AAAAFQAAADEAAAA2AAAAFgAAADIAAAA2AAAAFwAAADMAAAA2AAAAGAAAADQAAAA2AAAAGQAAADUAAAA2AAAAGgAAADkAAAA2AAAAGwAAADcAAAA7AAAAHQAAADgF9eEXAAAAHwX14RUF9eEWAAAAHwX14RMF9eEUAAAAHwX14REF9eESAAAAHAX14RgAAAA8AAAAHwX14RoF9eEbAAAAAwAAAEYAAAA+AAAABAAAAD8F9eEjAAAABQX14QUAAABAAAAABgAAAEEF9eEQAAAACwAAAEIAAABDAAAAHAX14QgAAABDAAAAHgAAAEUAAABEAAAAHwX14Q4F9eEPAAAAHwX14QwF9eENAAAABAAAAEcF9eEjAAAABQX14QUAAABIAAAABgAAAEkF9eELAAAACQAAAEoF9eELAAAACwAAAEsAAABMAAAAHAX14QgAAABMAAAAHwX14QkF9eEKAAAAAgX14QEAAABOAAAAAwX14QIAAABPAAAABAAAAFAF9eEEAAAABwAAAFEF9eEEAAAACAX14QMAAABSAAAACgX14QMF9eEE" +} \ No newline at end of file diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-rule-set.json b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-rule-set.json index 7a3b1e9d81c4..373ecfc8df78 100644 --- a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-rule-set.json +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-rule-set.json @@ -48,6 +48,11 @@ "required": false, "documentation": "ResourceArnList containing list of resource arns", "type": "stringArray" + }, + "IsSearchOperation": { + "required": false, + "documentation": "Set to true for SearchVectors to route to the Search FQDN", + "type": "boolean" } }, "rules": [ @@ -77,6 +82,15 @@ } ], "assign": "PartitionResult" + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "parsedEndpoint" } ], "rules": [ @@ -116,9 +130,36 @@ "fn": "stringEquals", "argv": [ { - "ref": "Endpoint" + "fn": "getAttr", + "argv": [ + { + "ref": "parsedEndpoint" + }, + "authority" + ] + }, + "dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}" + ] + } + ], + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html", + "type": "error" + }, + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "parsedEndpoint" + }, + "authority" + ] }, - "https://dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}" + "search-dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}" ] } ], @@ -266,9 +307,9 @@ "properties": { "authSchemes": [ { + "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb", - "signingRegion": "us-east-1" + "signingName": "dynamodb" } ] }, @@ -364,6 +405,33 @@ ], "type": "tree" }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://search-dynamodb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -464,6 +532,33 @@ ], "type": "tree" }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://search-dynamodb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -505,6 +600,33 @@ ], "type": "tree" }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://search-dynamodb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -688,16 +810,53 @@ ] } ], - "endpoint": { - "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "metricValues": [ - "O" - ] + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{ParsedArn#accountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" }, - "headers": {} - }, - "type": "endpoint" + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" }, { "conditions": [ @@ -840,16 +999,53 @@ ] } ], - "endpoint": { - "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "metricValues": [ - "O" - ] + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{ParsedArn#accountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" }, - "headers": {} - }, - "type": "endpoint" + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" }, { "conditions": [ @@ -927,6 +1123,37 @@ } ], "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{AccountId}.search-ddb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -1033,6 +1260,33 @@ ], "type": "tree" }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://search-dynamodb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -1184,16 +1438,53 @@ ] } ], - "endpoint": { - "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", - "properties": { - "metricValues": [ - "O" - ] + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{ParsedArn#accountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" }, - "headers": {} - }, - "type": "endpoint" + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" }, { "conditions": [ @@ -1336,16 +1627,53 @@ ] } ], - "endpoint": { - "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", - "properties": { - "metricValues": [ - "O" - ] + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{ParsedArn#accountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" }, - "headers": {} - }, - "type": "endpoint" + { + "conditions": [], + "endpoint": { + "url": "https://{ParsedArn#accountId}.ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" }, { "conditions": [ @@ -1423,6 +1751,37 @@ } ], "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://{AccountId}.search-ddb.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -1529,6 +1888,33 @@ ], "type": "tree" }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "IsSearchOperation" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "IsSearchOperation" + }, + true + ] + } + ], + "endpoint": { + "url": "https://search-dynamodb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-tests.json b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-tests.json index 890c3efb1a36..873383b95592 100644 --- a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-tests.json +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/endpoint-tests.json @@ -2750,9 +2750,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2786,9 +2786,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2838,9 +2838,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2866,9 +2866,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2894,9 +2894,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2922,9 +2922,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2950,9 +2950,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -2978,9 +2978,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3053,9 +3053,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3091,9 +3091,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3129,9 +3129,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3167,9 +3167,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3236,9 +3236,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3286,9 +3286,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3313,9 +3313,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3375,9 +3375,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3411,9 +3411,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3463,9 +3463,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3491,9 +3491,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3519,9 +3519,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3547,9 +3547,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3575,9 +3575,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3603,9 +3603,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3678,9 +3678,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3716,9 +3716,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3754,9 +3754,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3792,9 +3792,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3861,9 +3861,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3911,9 +3911,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -3938,9 +3938,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4000,9 +4000,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4036,9 +4036,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4088,9 +4088,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4116,9 +4116,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4144,9 +4144,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4172,9 +4172,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4200,9 +4200,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4228,9 +4228,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4303,9 +4303,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4341,9 +4341,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4379,9 +4379,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4417,9 +4417,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4486,9 +4486,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4536,9 +4536,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -4563,9 +4563,9 @@ "properties": { "authSchemes": [ { - "signingRegion": "us-east-1", "name": "sigv4", - "signingName": "dynamodb" + "signingName": "dynamodb", + "signingRegion": "us-east-1" } ] }, @@ -8716,6 +8716,6307 @@ "Endpoint": "https://dynamodb.us-west-2.api.aws", "Region": "us-west-2" } + }, + { + "documentation": "{Endpoint=https://dynamodb.us-east-1.api.aws/, Region=us-east-1}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "params": { + "Endpoint": "https://dynamodb.us-east-1.api.aws/", + "Region": "us-east-1" + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=disabled, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=required, Region=us-east-1, Endpoint=https://example.com, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://example.com", + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "Endpoint": "https://example.com", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=disabled, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "disabled", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: FIPS and local endpoint are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: Dualstack and local endpoint are not supported" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=required, Region=local, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "dynamodb", + "signingRegion": "us-east-1" + } + ] + }, + "url": "http://localhost:8000" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "local", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "required", + "Region": "local", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://111111111111.search-ddb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://111111111111.search-ddb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Credentials-sourced account ID parameter is invalid" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://222222222222.search-ddb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://222222222222.search-ddb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://111111111111.search-ddb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://111111111111.search-ddb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Credentials-sourced account ID parameter is invalid" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://222222222222.search-ddb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://222222222222.search-ddb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=required, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "required", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required and FIPS is enabled, but FIPS account endpoints are not supported" + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=required, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "required", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": true, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=disabled, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "disabled", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.cn-north-1.amazonaws.com.cn" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "cn-north-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-iso-east-1.api.aws.ic.gov" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.api.aws.ic.gov" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-iso-east-1.api.aws.ic.gov" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.api.aws.ic.gov" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=us-iso-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-iso-east-1.c2s.ic.gov" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-iso-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "us-iso-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-gov-east-1.api.aws" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.api.aws" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=111111111111, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "111111111111", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "111111111111", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountId=, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountId": "", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountId": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb-fips.us-gov-east-1.api.aws" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=true, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "UseFIPS": true, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=true, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.api.aws" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": true, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-east-1:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-east-1:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:dynamodb:us-west-2:222222222222:table/table_name, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:dynamodb:us-west-2:222222222222:table/table_name", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=arn:aws:s3:us-west-2:222222222222:stream/testStream, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "arn:aws:s3:us-west-2:222222222222:stream/testStream", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, ResourceArn=, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "ResourceArn": "", + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{UseFIPS=false, UseDualStack=false, AccountIdEndpointMode=preferred, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://search-dynamodb.us-gov-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-gov-east-1", + "AWS::UseFIPS": false, + "AWS::UseDualStack": false, + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "UseFIPS": false, + "UseDualStack": false, + "AccountIdEndpointMode": "preferred", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.cn-north-1.api.amazonwebservices.com.cn, Region=cn-north-1, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.cn-north-1.api.amazonwebservices.com.cn", + "AWS::Region": "cn-north-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.cn-north-1.api.amazonwebservices.com.cn", + "Region": "cn-north-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.us-gov-east-1.api.aws, Region=us-gov-east-1, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.us-gov-east-1.api.aws", + "AWS::Region": "us-gov-east-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.us-gov-east-1.api.aws", + "Region": "us-gov-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.us-east-1.api.aws, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.us-east-1.api.aws", + "AWS::Region": "us-east-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.us-east-1.api.aws", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://111111111111.ddb.us-east-1.api.aws, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://111111111111.ddb.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://111111111111.ddb.us-east-1.api.aws", + "AWS::Region": "us-east-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://111111111111.ddb.us-east-1.api.aws", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://vpce-1a2b3c4d-5e6f.dynamodb.us-east-1.vpce.api.aws, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "endpoint": { + "url": "https://vpce-1a2b3c4d-5e6f.dynamodb.us-east-1.vpce.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://vpce-1a2b3c4d-5e6f.dynamodb.us-east-1.vpce.api.aws", + "AWS::Region": "us-east-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://vpce-1a2b3c4d-5e6f.dynamodb.us-east-1.vpce.api.aws", + "Region": "us-east-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.eu-west-1.api.aws, Region=eu-west-1, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.eu-west-1.api.aws", + "AWS::Region": "eu-west-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.eu-west-1.api.aws", + "Region": "eu-west-1", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.us-west-2.api.aws, Region=us-west-2, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.us-west-2.api.aws", + "AWS::Region": "us-west-2" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.us-west-2.api.aws", + "Region": "us-west-2", + "IsSearchOperation": true + } + }, + { + "documentation": "{Endpoint=https://dynamodb.us-east-1.api.aws/, Region=us-east-1, IsSearchOperation=true}", + "expect": { + "error": "Endpoint override is not supported for dual-stack endpoints. Please enable dual-stack functionality by enabling the configuration. For more details, see: https://docs.aws.amazon.com/sdkref/latest/guide/feature-endpoints.html" + }, + "operationInputs": [ + { + "builtInParams": { + "SDK::Endpoint": "https://dynamodb.us-east-1.api.aws/", + "AWS::Region": "us-east-1" + }, + "operationName": "SearchVectors", + "operationParams": { + "TableName": "test-table", + "IndexName": "test-index", + "SearchVector": [ + { + "N": "1.0" + }, + { + "N": "2.0" + }, + { + "N": "3.0" + } + ], + "TopK": 10 + } + } + ], + "params": { + "Endpoint": "https://dynamodb.us-east-1.api.aws/", + "Region": "us-east-1", + "IsSearchOperation": true + } } ], "version": "1.0" diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/service-2.json b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/service-2.json index 7f0081427ae0..39b044147ef7 100644 --- a/services/dynamodb/src/main/resources/codegen-resources/dynamodb/service-2.json +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodb/service-2.json @@ -68,7 +68,7 @@ {"shape":"ReplicatedWriteConflictException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    The BatchWriteItem operation puts or deletes multiple items in one or more tables. A single call to BatchWriteItem can transmit up to 16MB of data over the network, consisting of up to 25 item put or delete operations. While individual items can be up to 400 KB once stored, it's important to note that an item's representation might be greater than 400KB while being sent in DynamoDB's JSON format for the API call. For more details on this distinction, see Naming Rules and Data Types.

    BatchWriteItem cannot update items. If you perform a BatchWriteItem operation on an existing item, that item's values will be overwritten by the operation and it will appear like it was updated. To update items, we recommend you use the UpdateItem action.

    The individual PutItem and DeleteItem operations specified in BatchWriteItem are atomic; however BatchWriteItem as a whole is not. If any requested operations fail because the table's provisioned throughput is exceeded or an internal processing failure occurs, the failed operations are returned in the UnprocessedItems response parameter. You can investigate and optionally resend the requests. Typically, you would call BatchWriteItem in a loop. Each iteration would check for unprocessed items and submit a new BatchWriteItem request with those unprocessed items until all items have been processed.

    For tables and indexes with provisioned capacity, if none of the items can be processed due to insufficient provisioned throughput on all of the tables in the request, then BatchWriteItem returns a ProvisionedThroughputExceededException. For all tables and indexes, if none of the items can be processed due to other throttling scenarios (such as exceeding partition level limits), then BatchWriteItem returns a ThrottlingException.

    If DynamoDB returns any unprocessed items, you should retry the batch operation on those items. However, we strongly recommend that you use an exponential backoff algorithm. If you retry the batch operation immediately, the underlying read or write requests can still fail due to throttling on the individual tables. If you delay the batch operation using exponential backoff, the individual requests in the batch are much more likely to succeed.

    For more information, see Batch Operations and Error Handling in the Amazon DynamoDB Developer Guide.

    With BatchWriteItem, you can efficiently write or delete large amounts of data, such as from Amazon EMR, or copy data from another database into DynamoDB. In order to improve performance with these large-scale operations, BatchWriteItem does not behave in the same way as individual PutItem and DeleteItem calls would. For example, you cannot specify conditions on individual put and delete requests, and BatchWriteItem does not return deleted items in the response.

    If you use a programming language that supports concurrency, you can use threads to write items in parallel. Your application must include the necessary logic to manage the threads. With languages that don't support threading, you must update or delete the specified items one at a time. In both situations, BatchWriteItem performs the specified put and delete operations in parallel, giving you the power of the thread pool approach without having to introduce complexity into your application.

    Parallel processing reduces latency, but each specified put and delete request consumes the same number of write capacity units whether it is processed in parallel or not. Delete operations on nonexistent items consume one write capacity unit.

    If one or more of the following is true, DynamoDB rejects the entire batch write operation:

    • One or more tables specified in the BatchWriteItem request does not exist.

    • Primary key attributes specified on an item in the request do not match those in the corresponding table's primary key schema.

    • You try to perform multiple operations on the same item in the same BatchWriteItem request. For example, you cannot put and delete the same item in the same BatchWriteItem request.

    • Your request contains at least two items with identical hash and range keys (which essentially is two put operations).

    • There are more than 25 requests in the batch.

    • Any individual item in a batch exceeds 400 KB.

    • The total request size exceeds 16 MB.

    • Any individual items with keys exceeding the key length limits. For a partition key, the limit is 2048 bytes and for a sort key, the limit is 1024 bytes.

    ", + "documentation":"

    The BatchWriteItem operation puts or deletes multiple items in one or more tables. A single call to BatchWriteItem can transmit up to 16MB of data over the network, consisting of up to 25 item put or delete operations. While individual items can be up to 400 KB once stored, it's important to note that an item's representation might be greater than 400KB while being sent in DynamoDB's JSON format for the API call. For more details on this distinction, see Naming Rules and Data Types.

    BatchWriteItem cannot update items. If you perform a BatchWriteItem operation on an existing item, that item's values will be overwritten by the operation and it will appear like it was updated. To update items, we recommend you use the UpdateItem action.

    The individual PutItem and DeleteItem operations specified in BatchWriteItem are atomic; however BatchWriteItem as a whole is not. If any requested operations fail because the table's provisioned throughput is exceeded or an internal processing failure occurs, the failed operations are returned in the UnprocessedItems response parameter. You can investigate and optionally resend the requests. Typically, you would call BatchWriteItem in a loop. Each iteration would check for unprocessed items and submit a new BatchWriteItem request with those unprocessed items until all items have been processed.

    If BatchWriteItem cannot process any items due to throttling (for example, insufficient provisioned throughput on the tables in the request, or partition-level or account-level limits), it returns a ProvisionedThroughputExceededException or a ThrottlingException. Both indicate that the request was throttled; check the ThrottlingReason field in the returned exception for details.

    If DynamoDB returns any unprocessed items, you should retry the batch operation on those items. However, we strongly recommend that you use an exponential backoff algorithm. If you retry the batch operation immediately, the underlying read or write requests can still fail due to throttling on the individual tables. If you delay the batch operation using exponential backoff, the individual requests in the batch are much more likely to succeed.

    For more information, see Batch Operations and Error Handling in the Amazon DynamoDB Developer Guide.

    With BatchWriteItem, you can efficiently write or delete large amounts of data, such as from Amazon EMR, or copy data from another database into DynamoDB. In order to improve performance with these large-scale operations, BatchWriteItem does not behave in the same way as individual PutItem and DeleteItem calls would. For example, you cannot specify conditions on individual put and delete requests, and BatchWriteItem does not return deleted items in the response.

    If you use a programming language that supports concurrency, you can use threads to write items in parallel. Your application must include the necessary logic to manage the threads. With languages that don't support threading, you must update or delete the specified items one at a time. In both situations, BatchWriteItem performs the specified put and delete operations in parallel, giving you the power of the thread pool approach without having to introduce complexity into your application.

    Parallel processing reduces latency, but each specified put and delete request consumes the same number of write capacity units whether it is processed in parallel or not. Delete operations on nonexistent items consume one write capacity unit.

    If one or more of the following is true, DynamoDB rejects the entire batch write operation:

    • One or more tables specified in the BatchWriteItem request does not exist.

    • Primary key attributes specified on an item in the request do not match those in the corresponding table's primary key schema.

    • You try to perform multiple operations on the same item in the same BatchWriteItem request. For example, you cannot put and delete the same item in the same BatchWriteItem request.

    • Your request contains at least two items with identical hash and range keys (which essentially is two put operations).

    • There are more than 25 requests in the batch.

    • Any individual item in a batch exceeds 400 KB.

    • The total request size exceeds 16 MB.

    • Any individual items with keys exceeding the key length limits. For a partition key, the limit is 2048 bytes and for a sort key, the limit is 1024 bytes.

    ", "endpointdiscovery":{}, "operationContextParams":{ "ResourceArnList":{"path":"keys(RequestItems)"} @@ -744,6 +744,25 @@ "documentation":"

    The Scan operation returns one or more items and item attributes by accessing every item in a table or a secondary index. To have DynamoDB return fewer items, you can provide a FilterExpression operation.

    If the total size of scanned items exceeds the maximum dataset size limit of 1 MB, the scan completes and results are returned to the user. The LastEvaluatedKey value is also returned and the requestor can use the LastEvaluatedKey to continue the scan in a subsequent operation. Each scan response also includes number of items that were scanned (ScannedCount) as part of the request. If using a FilterExpression, a scan result can result in no items meeting the criteria and the Count will result in zero. If you did not use a FilterExpression in the scan request, then Count is the same as ScannedCount.

    Count and ScannedCount only return the count of items specific to a single scan request and, unless the table is less than 1MB, do not represent the total number of items in the table.

    A single Scan operation first reads up to the maximum number of items set (if using the Limit parameter) or a maximum of 1 MB of data and then applies any filtering to the results if a FilterExpression is provided. If LastEvaluatedKey is present in the response, pagination is required to complete the full table scan. For more information, see Paginating the Results in the Amazon DynamoDB Developer Guide.

    Scan operations proceed sequentially; however, for faster performance on a large table or secondary index, applications can request a parallel Scan operation by providing the Segment and TotalSegments parameters. For more information, see Parallel Scan in the Amazon DynamoDB Developer Guide.

    By default, a Scan uses eventually consistent reads when accessing the items in a table. Therefore, the results from an eventually consistent Scan may not include the latest item changes at the time the scan iterates through each item in the table. If you require a strongly consistent read of each item as the scan iterates through the items in the table, you can set the ConsistentRead parameter to true. Strong consistency only relates to the consistency of the read at the item level.

    DynamoDB does not provide snapshot isolation for a scan operation when the ConsistentRead parameter is set to true. Thus, a DynamoDB scan operation does not guarantee that all reads in a scan see a consistent snapshot of the table when the scan operation was requested.

    ", "endpointdiscovery":{} }, + "SearchVectors":{ + "name":"SearchVectors", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"SearchVectorsInput"}, + "output":{"shape":"SearchVectorsOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"RequestLimitExceeded"}, + {"shape":"InternalServerError"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Performs a vector similarity search on a vector index associated with an Amazon DynamoDB table, and returns the most similar items sorted by similarity score based on the distance function configured for the index.

    Score interpretation depends on the distance function:

    • COSINE - Returns the items with the k smallest scores. Scores range from 0 (identical) to 2 (opposite). Lower scores indicate higher similarity.

    • EUCLIDEAN - Returns the items with the k smallest scores. Scores represent the Euclidean distance between vectors. Lower scores indicate higher similarity.

    • DOT_PRODUCT - Returns the items with the k highest scores. Higher scores indicate higher similarity.

    ", + "staticContextParams":{ + "IsSearchOperation":{"value":true} + } + }, "TagResource":{ "name":"TagResource", "http":{ @@ -1605,7 +1624,7 @@ }, "ConsumedCapacity":{ "shape":"ConsumedCapacityMultiple", - "documentation":"

    The capacity units consumed by the entire BatchWriteItem operation.

    Each element consists of:

    • TableName - The table that consumed the provisioned throughput.

    • CapacityUnits - The total number of capacity units consumed.

    " + "documentation":"

    The capacity units consumed by the entire BatchWriteItem operation.

    Each element consists of:

    • TableName - The table that consumed the provisioned throughput.

    • CapacityUnits - The total number of capacity units consumed.

    If the table has vector indexes, each element also includes a VectorIndexes field with VectorWriteRequestBytes consumed for each affected vector index.

    " } }, "documentation":"

    Represents the output of a BatchWriteItem operation.

    " @@ -1829,6 +1848,10 @@ "GlobalSecondaryIndexes":{ "shape":"SecondaryIndexesCapacityMap", "documentation":"

    The amount of throughput consumed on each global index affected by the operation.

    " + }, + "VectorIndexes":{ + "shape":"VectorIndexesCapacityMap", + "documentation":"

    The amount of throughput consumed on each vector index affected by the operation. Each entry contains VectorWriteRequestBytes (for write operations) or VectorSearchRequestBytes (for search operations).

    " } }, "documentation":"

    The capacity units consumed by an operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the request asked for it. For more information, see Provisioned capacity mode in the Amazon DynamoDB Developer Guide.

    " @@ -2140,6 +2163,10 @@ "GlobalTableSettingsReplicationMode":{ "shape":"GlobalTableSettingsReplicationMode", "documentation":"

    Controls the settings synchronization mode for the global table. For multi-account global tables, this parameter is required and the only supported value is ENABLED. For same-account global tables, this parameter is set to ENABLED_WITH_OVERRIDES.

    " + }, + "VectorIndexes":{ + "shape":"VectorIndexList", + "documentation":"

    One or more vector indexes to be created on the table. Each vector index enables similarity search on a vector attribute. Each element in the list consists of:

    • IndexName - The name of the vector index. Must be unique within the table.

    • VectorAttribute - The attribute that contains vector embeddings. If multiple vector indexes reference the same attribute, they must all use the same number of dimensions.

    • Dimensions - The number of dimensions in each vector.

    • DistanceFunction - The distance function used to calculate similarity. Valid values: COSINE, EUCLIDEAN, DOT_PRODUCT.

    • Projection - Specifies attributes that are copied (projected) from the table into the vector index. The total number of projected non-key attributes is shared across the vector attribute (counts as 1) and INLINE_FILTER search schema elements (each counts as 1). HASH search schema elements do not count toward this limit.

    • SearchSchema - (Optional) Defines the partition key (HASH) and inline filter (INLINE_FILTER) attributes for the vector index.

    " } }, "documentation":"

    Represents the input of a CreateTable operation.

    " @@ -2154,6 +2181,43 @@ }, "documentation":"

    Represents the output of a CreateTable operation.

    " }, + "CreateVectorIndexAction":{ + "type":"structure", + "required":[ + "IndexName", + "VectorAttribute", + "Projection", + "Dimensions", + "DistanceFunction" + ], + "members":{ + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index. Must be unique within the table.

    " + }, + "VectorAttribute":{ + "shape":"VectorAttributeDefinition", + "documentation":"

    The attribute that contains vector embeddings. If multiple vector indexes reference the same attribute, they must all use the same number of dimensions.

    " + }, + "SearchSchema":{ + "shape":"SearchSchema", + "documentation":"

    The partition key and inline filter attribute definitions for the vector index.

    " + }, + "Projection":{ + "shape":"Projection", + "documentation":"

    Specifies attributes that are copied (projected) from the table into the vector index.

    " + }, + "Dimensions":{ + "shape":"PositiveLongObject", + "documentation":"

    The number of dimensions in each vector.

    " + }, + "DistanceFunction":{ + "shape":"VectorDistanceFunction", + "documentation":"

    The distance function used to calculate similarity. Valid values: COSINE, EUCLIDEAN, DOT_PRODUCT.

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

    A new vector index to be added to a table.

    " + }, "CsvDelimiter":{ "type":"string", "max":1, @@ -2324,7 +2388,7 @@ }, "ConsumedCapacity":{ "shape":"ConsumedCapacity", - "documentation":"

    The capacity units consumed by the DeleteItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Provisioned capacity mode in the Amazon DynamoDB Developer Guide.

    " + "documentation":"

    The capacity units consumed by the DeleteItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Provisioned capacity mode in the Amazon DynamoDB Developer Guide.

    If the table has vector indexes, the response includes a VectorIndexes field with VectorWriteRequestBytes consumed for each affected vector index.

    " }, "ItemCollectionMetrics":{ "shape":"ItemCollectionMetrics", @@ -2412,6 +2476,17 @@ }, "documentation":"

    Represents the output of a DeleteTable operation.

    " }, + "DeleteVectorIndexAction":{ + "type":"structure", + "required":["IndexName"], + "members":{ + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index to delete.

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

    A vector index to be removed from a table.

    " + }, "DeletionProtectionEnabled":{"type":"boolean"}, "DescribeBackupInput":{ "type":"structure", @@ -3643,7 +3718,7 @@ }, "EndTime":{ "shape":"ImportEndTime", - "documentation":"

    The time at which this import task ended. (Does this include the successful complete creation of the table it was imported to?)

    " + "documentation":"

    The time at which this import task ended.

    " } }, "documentation":"

    Summary information about the source file for the import.

    " @@ -3796,7 +3871,7 @@ }, "ExportViewType":{ "shape":"ExportViewType", - "documentation":"

    The view type that was chosen for the export. Valid values are NEW_AND_OLD_IMAGES and NEW_IMAGES. The default value is NEW_AND_OLD_IMAGES.

    " + "documentation":"

    The view type that was chosen for the export. Valid values are NEW_AND_OLD_IMAGES and NEW_IMAGES. The default value is NEW_AND_OLD_IMAGES.

    NEW_AND_OLD_IMAGES exports both the new and old images of each changed item, while NEW_IMAGES exports only the new (latest) image. The view type you choose determines the structure of each item in the output for insert, update, and delete operations. For details and examples of how each view type shapes the export output, see DynamoDB table export output format in the Amazon DynamoDB Developer Guide.

    " } }, "documentation":"

    Optional object containing the parameters specific to an incremental export.

    " @@ -4683,11 +4758,11 @@ }, "ReadCapacityUnits":{ "shape":"NonNegativeLongObject", - "documentation":"

    The maximum number of strongly consistent reads consumed per second before DynamoDB returns a ThrottlingException. Eventually consistent reads require less effort than strongly consistent reads, so a setting of 50 ReadCapacityUnits per second provides 100 eventually consistent ReadCapacityUnits per second.

    " + "documentation":"

    The maximum number of strongly consistent reads consumed per second before DynamoDB returns a ThrottlingException. Eventually consistent reads require less effort than strongly consistent reads, so a setting of 50 ReadCapacityUnits per second provides 100 eventually consistent ReadCapacityUnits per second.

    For a table or global secondary index that uses on-demand capacity mode (PAY_PER_REQUEST), this value is 0, because on-demand mode does not use provisioned throughput.

    " }, "WriteCapacityUnits":{ "shape":"NonNegativeLongObject", - "documentation":"

    The maximum number of writes consumed per second before DynamoDB returns a ThrottlingException.

    " + "documentation":"

    The maximum number of writes consumed per second before DynamoDB returns a ThrottlingException.

    For a table or global secondary index that uses on-demand capacity mode (PAY_PER_REQUEST), this value is 0, because on-demand mode does not use provisioned throughput.

    " } }, "documentation":"

    Represents the provisioned throughput settings for the table, consisting of read and write capacity units, along with data about increases and decreases.

    " @@ -4765,7 +4840,7 @@ }, "Item":{ "shape":"PutItemInputAttributeMap", - "documentation":"

    A map of attribute name/value pairs, one for each attribute. Only the primary key attributes are required; you can optionally provide other attribute name-value pairs for the item.

    You must provide all of the attributes for the primary key. For example, with a simple primary key, you only need to provide a value for the partition key. For a composite primary key, you must provide both values for both the partition key and the sort key.

    If you specify any attributes that are part of an index key, then the data types for those attributes must match those of the schema in the table's attribute definition.

    Empty String and Binary attribute values are allowed. Attribute values of type String and Binary must have a length greater than zero if the attribute is used as a key attribute for a table or index.

    For more information about primary keys, see Primary Key in the Amazon DynamoDB Developer Guide.

    Each element in the Item map is an AttributeValue object.

    " + "documentation":"

    A map of attribute name/value pairs, one for each attribute. Only the primary key attributes are required; you can optionally provide other attribute name-value pairs for the item.

    You must provide all of the attributes for the primary key. For example, with a simple primary key, you only need to provide a value for the partition key. For a composite primary key, you must provide both values for both the partition key and the sort key.

    If you specify any attributes that are part of an index key, then the data types for those attributes must match those of the schema in the table's attribute definition.

    If the table has vector indexes, the following validations apply to write operations. A violation of any of these constraints results in a ValidationException:

    • The vector attribute must be a list of numbers with dimensions matching the index configuration.

    • Vector values must fit in 32-bit IEEE-754 floating point format (f32).

    • Partition key and inline filter attributes defined in the search schema must have data types matching the index schema definition.

    Empty String and Binary attribute values are allowed. Attribute values of type String and Binary must have a length greater than zero if the attribute is used as a key attribute for a table or index.

    For more information about primary keys, see Primary Key in the Amazon DynamoDB Developer Guide.

    Each element in the Item map is an AttributeValue object.

    " }, "Expected":{ "shape":"ExpectedAttributeMap", @@ -4817,7 +4892,7 @@ }, "ConsumedCapacity":{ "shape":"ConsumedCapacity", - "documentation":"

    The capacity units consumed by the PutItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Capacity unity consumption for write operations in the Amazon DynamoDB Developer Guide.

    " + "documentation":"

    The capacity units consumed by the PutItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Capacity unity consumption for write operations in the Amazon DynamoDB Developer Guide.

    If the table has vector indexes, the response includes a VectorIndexes field with VectorWriteRequestBytes consumed for each affected vector index.

    " }, "ItemCollectionMetrics":{ "shape":"ItemCollectionMetrics", @@ -5505,6 +5580,10 @@ "SSESpecificationOverride":{ "shape":"SSESpecification", "documentation":"

    The new server-side encryption settings for the restored table.

    " + }, + "VectorIndexOverride":{ + "shape":"VectorIndexList", + "documentation":"

    The vector indexes for the restored table. If not specified, all vector indexes from the backup are restored. The indexes provided must match existing vector indexes from the backup. You can choose to exclude some or all of the vector indexes at the time of restore.

    " } } }, @@ -5548,7 +5627,7 @@ }, "GlobalSecondaryIndexOverride":{ "shape":"GlobalSecondaryIndexList", - "documentation":"

    List of global secondary indexes for the restored table. The indexes provided should match existing secondary indexes. You can choose to exclude some or all of the indexes at the time of restore.

    " + "documentation":"

    List of global secondary indexes for the restored table. The indexes provided should match existing secondary indexes. You can choose to exclude some or all of the indexes at the time of restore.

    The WarmThroughput setting is not supported on global secondary indexes when you use RestoreTableToPointInTime. Although WarmThroughput appears in the shared index definition, including it in a GlobalSecondaryIndexOverride entry causes the request to fail with a validation error.

    " }, "LocalSecondaryIndexOverride":{ "shape":"LocalSecondaryIndexList", @@ -5562,6 +5641,10 @@ "SSESpecificationOverride":{ "shape":"SSESpecification", "documentation":"

    The new server-side encryption settings for the restored table.

    " + }, + "VectorIndexOverride":{ + "shape":"VectorIndexList", + "documentation":"

    The vector indexes for the restored table. If not specified, all vector indexes from the source table are restored. The indexes provided must match existing vector indexes from the source table. You can choose to exclude some or all of the vector indexes at the time of restore.

    " } } }, @@ -5822,6 +5905,119 @@ "max":1000000, "min":1 }, + "ScoreNumber":{"type":"double"}, + "SearchResultItem":{ + "type":"structure", + "members":{ + "Item":{ + "shape":"AttributeMap", + "documentation":"

    A map of attribute names to AttributeValue objects, representing the projected attributes of the item returned by the vector search.

    " + }, + "Score":{ + "shape":"ScoreNumber", + "documentation":"

    The similarity score for this item relative to the search vector. The interpretation depends on the distance function configured for the vector index.

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

    A single result from a SearchVectors operation.

    " + }, + "SearchResultList":{ + "type":"list", + "member":{"shape":"SearchResultItem"} + }, + "SearchSchema":{ + "type":"list", + "member":{"shape":"SearchSchemaElement"}, + "min":1 + }, + "SearchSchemaElement":{ + "type":"structure", + "required":[ + "AttributeName", + "SearchSchemaElementType" + ], + "members":{ + "AttributeName":{ + "shape":"AttributeName", + "documentation":"

    The name of the attribute.

    " + }, + "SearchSchemaElementType":{ + "shape":"SearchSchemaElementType", + "documentation":"

    The role of the attribute in the search schema. Valid values:

    • HASH - A partition key that partitions the vector index for independent scaling. When specified, you must provide this attribute's value in the SearchConditionExpression.

    • INLINE_FILTER - An attribute projected into the vector index for filtering at the storage layer during search. Inline filters are optional in the SearchConditionExpression.

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

    An element in the search schema of a vector index.

    " + }, + "SearchSchemaElementType":{ + "type":"string", + "enum":[ + "HASH", + "INLINE_FILTER" + ] + }, + "SearchVectorList":{ + "type":"list", + "member":{"shape":"AttributeValue"}, + "max":4096, + "min":1 + }, + "SearchVectorsInput":{ + "type":"structure", + "required":[ + "TableName", + "IndexName", + "SearchVector", + "TopK" + ], + "members":{ + "TableName":{ + "shape":"TableArn", + "documentation":"

    The name or Amazon Resource Name (ARN) of the table containing the vector index.

    ", + "contextParam":{"name":"ResourceArn"} + }, + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index to search. The index must be in the ACTIVE state.

    " + }, + "ReturnConsumedCapacity":{"shape":"ReturnConsumedCapacity"}, + "ExpressionAttributeNames":{ + "shape":"ExpressionAttributeNameMap", + "documentation":"

    One or more substitution tokens for attribute names in an expression. Use the # character in an expression to dereference an attribute name.

    " + }, + "ExpressionAttributeValues":{ + "shape":"ExpressionAttributeValueMap", + "documentation":"

    One or more values that can be substituted in an expression. Use the : character in an expression to dereference an attribute value.

    " + }, + "ProjectionExpression":{ + "shape":"ProjectionExpression", + "documentation":"

    A string that identifies one or more attributes to retrieve from the index. Separate attribute names with commas. If not specified, the operation returns all attributes projected into the vector index.

    Only attributes projected into the vector index can be retrieved.

    " + }, + "SearchVector":{ + "shape":"SearchVectorList", + "documentation":"

    The search vector to compare against the indexed vectors. Each element is a 32-bit IEEE-754 floating point number, provided in DynamoDB list format.

    The number of dimensions must match the number of dimensions configured for the vector index.

    " + }, + "SearchConditionExpression":{ + "shape":"String", + "documentation":"

    A condition expression used to filter the vector search results. The expression can reference attributes defined in the vector index search schema, including HASH and INLINE_FILTER key elements.

    Only the equality operator (=) is supported for HASH attributes. Comparison and range operators are supported for INLINE_FILTER attributes. Only top-level attributes from the search schema can be referenced.

    " + }, + "TopK":{ + "shape":"TopKInteger", + "documentation":"

    The number of most similar results to return.

    " + } + } + }, + "SearchVectorsOutput":{ + "type":"structure", + "members":{ + "ConsumedCapacity":{ + "shape":"VectorCapacity", + "documentation":"

    The capacity units consumed by the SearchVectors operation. Contains VectorSearchRequestBytes, which represents the vector search capacity consumed.

    " + }, + "SearchResults":{ + "shape":"SearchResultList", + "documentation":"

    A list of items returned by the vector similarity search, sorted by similarity with the most similar item first. Each item contains the projected attributes and a similarity score.

    " + } + } + }, "SecondaryIndexesCapacityMap":{ "type":"map", "key":{"shape":"IndexName"}, @@ -5908,6 +6104,10 @@ "SSEDescription":{ "shape":"SSEDescription", "documentation":"

    The description of the server-side encryption status on the table when the backup was created.

    " + }, + "VectorIndexes":{ + "shape":"VectorIndexes", + "documentation":"

    The vector index properties for the table at the time the backup was created, including the index name, vector attribute, dimensions, distance function, search schema, and projection.

    " } }, "documentation":"

    Contains the details of the features enabled on the table when the backup was created. For example, LSIs, GSIs, streams, TTL.

    " @@ -6031,6 +6231,10 @@ "GlobalSecondaryIndexes":{ "shape":"GlobalSecondaryIndexList", "documentation":"

    The Global Secondary Indexes (GSI) of the table to be created as part of the import operation.

    " + }, + "VectorIndexes":{ + "shape":"VectorIndexList", + "documentation":"

    The vector indexes of the table to be created as part of the import operation.

    " } }, "documentation":"

    The parameters for the table created as part of the import operation.

    " @@ -6076,7 +6280,7 @@ }, "TableId":{ "shape":"TableId", - "documentation":"

    Unique identifier for the table for which the backup was created.

    " + "documentation":"

    A unique identifier for the table, in UUID format, generated by DynamoDB when the table is created.

    " }, "BillingModeSummary":{ "shape":"BillingModeSummary", @@ -6149,6 +6353,10 @@ "MultiRegionConsistency":{ "shape":"MultiRegionConsistency", "documentation":"

    Indicates one of the following consistency modes for a global table:

    • EVENTUAL: Indicates that the global table is configured for multi-Region eventual consistency (MREC).

    • STRONG: Indicates that the global table is configured for multi-Region strong consistency (MRSC).

    If you don't specify this field, the global table consistency mode defaults to EVENTUAL. For more information about global tables consistency modes, see Consistency modes in DynamoDB developer guide.

    " + }, + "VectorIndexes":{ + "shape":"VectorIndexDescriptionList", + "documentation":"

    The vector indexes, if any, on the table. Each element is composed of:

    • IndexName - The name of the vector index.

    • IndexStatus - The current status of the vector index: CREATING, ACTIVE, or DELETING.

    • Backfilling - Specifies whether the index is currently backfilling. During backfill, SearchVectors operations might return incomplete results.

    • VectorAttribute - The attribute that contains vector embeddings.

    • Dimensions - The number of dimensions in each vector.

    • DistanceFunction - The distance function used to calculate similarity (COSINE, EUCLIDEAN, or DOT_PRODUCT).

    • SearchSchema - The partition key and inline filter attributes for the vector index.

    • Projection - Specifies attributes that are copied (projected) from the table into the vector index.

    • IndexArn - The Amazon Resource Name (ARN) that uniquely identifies the index.

    • IndexSizeBytes - The total size of the vector index, in bytes. Amazon DynamoDB updates this value approximately every six hours. Recent changes might not be reflected in this value.

    • ItemCount - The number of items indexed in the vector index. Amazon DynamoDB updates this value approximately every six hours. Recent changes might not be reflected in this value.

    " } }, "documentation":"

    Represents the properties of a table.

    " @@ -6348,6 +6556,11 @@ "DISABLED" ] }, + "TopKInteger":{ + "type":"integer", + "box":true, + "min":1 + }, "TransactGetItem":{ "type":"structure", "required":["Get"], @@ -6445,7 +6658,7 @@ "members":{ "ConsumedCapacity":{ "shape":"ConsumedCapacityMultiple", - "documentation":"

    The capacity units consumed by the entire TransactWriteItems operation. The values of the list are ordered according to the ordering of the TransactItems request parameter.

    " + "documentation":"

    The capacity units consumed by the entire TransactWriteItems operation. The values of the list are ordered according to the ordering of the TransactItems request parameter.

    If the table has vector indexes, each element also includes a VectorIndexes field with VectorWriteRequestBytes consumed for each affected vector index.

    " }, "ItemCollectionMetrics":{ "shape":"ItemCollectionMetricsPerTable", @@ -6462,7 +6675,7 @@ "documentation":"

    A list of cancellation reasons.

    " } }, - "documentation":"

    The entire transaction request was canceled.

    DynamoDB cancels a TransactWriteItems request under the following circumstances:

    • A condition in one of the condition expressions is not met.

    • A table in the TransactWriteItems request is in a different account or region.

    • More than one action in the TransactWriteItems operation targets the same item.

    • There is insufficient provisioned capacity for the transaction to be completed.

    • An item size becomes too large (larger than 400 KB), or a local secondary index (LSI) becomes too large, or a similar validation error occurs because of changes made by the transaction.

    • There is a user error, such as an invalid data format.

    • There is an ongoing TransactWriteItems operation that conflicts with a concurrent TransactWriteItems request. In this case the TransactWriteItems operation fails with a TransactionCanceledException.

    DynamoDB cancels a TransactGetItems request under the following circumstances:

    • There is an ongoing TransactGetItems operation that conflicts with a concurrent PutItem, UpdateItem, DeleteItem or TransactWriteItems request. In this case the TransactGetItems operation fails with a TransactionCanceledException.

    • A table in the TransactGetItems request is in a different account or region.

    • There is insufficient provisioned capacity for the transaction to be completed.

    • There is a user error, such as an invalid data format.

    DynamoDB lists the cancellation reasons on the CancellationReasons property. Transaction cancellation reasons are ordered in the order of requested items, if an item has no error it will have None code and Null message.

    Cancellation reason codes and possible error messages:

    • No Errors:

      • Code: None

      • Message: null

    • Conditional Check Failed:

      • Code: ConditionalCheckFailed

      • Message: The conditional request failed.

    • Item Collection Size Limit Exceeded:

      • Code: ItemCollectionSizeLimitExceeded

      • Message: Collection size exceeded.

    • Transaction Conflict:

      • Code: TransactionConflict

      • Message: Transaction is ongoing for the item.

    • Provisioned Throughput Exceeded:

      • Code: ProvisionedThroughputExceeded

      • Messages:

        • The level of configured provisioned throughput for the table was exceeded. Consider increasing your provisioning level with the UpdateTable API.

          This Message is received when provisioned throughput is exceeded is on a provisioned DynamoDB table.

        • The level of configured provisioned throughput for one or more global secondary indexes of the table was exceeded. Consider increasing your provisioning level for the under-provisioned global secondary indexes with the UpdateTable API.

          This message is returned when provisioned throughput is exceeded is on a provisioned GSI.

    • Throttling Error:

      • Code: ThrottlingError

      • Messages:

        • Throughput exceeds the current capacity of your table or index. DynamoDB is automatically scaling your table or index so please try again shortly. If exceptions persist, check if you have a hot key: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html.

          This message is returned when writes get throttled on an On-Demand table as DynamoDB is automatically scaling the table.

        • Throughput exceeds the current capacity for one or more global secondary indexes. DynamoDB is automatically scaling your index so please try again shortly.

          This message is returned when writes get throttled on an On-Demand GSI as DynamoDB is automatically scaling the GSI.

    • Validation Error:

      • Code: ValidationError

      • Messages:

        • One or more parameter values were invalid.

        • The update expression attempted to update the secondary index key beyond allowed size limits.

        • The update expression attempted to update the secondary index key to unsupported type.

        • An operand in the update expression has an incorrect data type.

        • Item size to update has exceeded the maximum allowed size.

        • Number overflow. Attempting to store a number with magnitude larger than supported range.

        • Type mismatch for attribute to update.

        • Nesting Levels have exceeded supported limits.

        • The document path provided in the update expression is invalid for update.

        • The provided expression refers to an attribute that does not exist in the item.

    ", + "documentation":"

    The entire transaction request was canceled.

    DynamoDB cancels a TransactWriteItems request under the following circumstances:

    • A condition in one of the condition expressions is not met.

    • A table in the TransactWriteItems request is in a different account or region.

    • More than one action in the TransactWriteItems operation targets the same item.

    • There is insufficient provisioned capacity for the transaction to be completed.

    • An item size becomes too large (larger than 400 KB), or a local secondary index (LSI) becomes too large, or a similar validation error occurs because of changes made by the transaction.

    • There is a user error, such as an invalid data format.

    • There is an ongoing TransactWriteItems operation that conflicts with a concurrent TransactWriteItems request. In this case the TransactWriteItems operation fails with a TransactionCanceledException.

    DynamoDB cancels a TransactGetItems request under the following circumstances:

    • There is an ongoing TransactGetItems operation that conflicts with a concurrent PutItem, UpdateItem, DeleteItem or TransactWriteItems request. In this case the TransactGetItems operation fails with a TransactionCanceledException.

    • A table in the TransactGetItems request is in a different account or region.

    • There is insufficient provisioned capacity for the transaction to be completed.

    • There is a user error, such as an invalid data format.

    DynamoDB lists the cancellation reasons on the CancellationReasons property. Transaction cancellation reasons are ordered in the order of requested items, if an item has no error it will have None code and Null message. The None code is returned as the literal string \"None\", not a null or absent value; the message field is omitted entirely for an item that has no error. This is important to note when using an SDK that surfaces the code as an optional or nullable type.

    Cancellation reason codes and possible error messages:

    • No Errors:

      • Code: None

      • Message: null

    • Conditional Check Failed:

      • Code: ConditionalCheckFailed

      • Message: The conditional request failed.

    • Item Collection Size Limit Exceeded:

      • Code: ItemCollectionSizeLimitExceeded

      • Message: Collection size exceeded.

    • Transaction Conflict:

      • Code: TransactionConflict

      • Message: Transaction is ongoing for the item.

    • Provisioned Throughput Exceeded:

      • Code: ProvisionedThroughputExceeded

      • Messages:

        • The level of configured provisioned throughput for the table was exceeded. Consider increasing your provisioning level with the UpdateTable API.

          This Message is received when provisioned throughput is exceeded is on a provisioned DynamoDB table.

        • The level of configured provisioned throughput for one or more global secondary indexes of the table was exceeded. Consider increasing your provisioning level for the under-provisioned global secondary indexes with the UpdateTable API.

          This message is returned when provisioned throughput is exceeded is on a provisioned GSI.

    • Throttling Error:

      • Code: ThrottlingError

      • Messages:

        • Throughput exceeds the current capacity of your table or index. DynamoDB is automatically scaling your table or index so please try again shortly. If exceptions persist, check if you have a hot key: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-partition-key-design.html.

          This message is returned when writes get throttled on an On-Demand table as DynamoDB is automatically scaling the table.

        • Throughput exceeds the current capacity for one or more global secondary indexes. DynamoDB is automatically scaling your index so please try again shortly.

          This message is returned when writes get throttled on an On-Demand GSI as DynamoDB is automatically scaling the GSI.

    • Validation Error:

      • Code: ValidationError

      • Messages:

        • One or more parameter values were invalid.

        • The update expression attempted to update the secondary index key beyond allowed size limits.

        • The update expression attempted to update the secondary index key to unsupported type.

        • An operand in the update expression has an incorrect data type.

        • Item size to update has exceeded the maximum allowed size.

        • Number overflow. Attempting to store a number with magnitude larger than supported range.

        • Type mismatch for attribute to update.

        • Nesting Levels have exceeded supported limits.

        • The document path provided in the update expression is invalid for update.

        • The provided expression refers to an attribute that does not exist in the item.

    ", "exception":true }, "TransactionConflictException":{ @@ -6776,7 +6989,7 @@ }, "ConsumedCapacity":{ "shape":"ConsumedCapacity", - "documentation":"

    The capacity units consumed by the UpdateItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Capacity unity consumption for write operations in the Amazon DynamoDB Developer Guide.

    " + "documentation":"

    The capacity units consumed by the UpdateItem operation. The data returned includes the total provisioned throughput consumed, along with statistics for the table and any indexes involved in the operation. ConsumedCapacity is only returned if the ReturnConsumedCapacity parameter was specified. For more information, see Capacity unity consumption for write operations in the Amazon DynamoDB Developer Guide.

    If the table has vector indexes, the response includes a VectorIndexes field with VectorWriteRequestBytes consumed for each affected vector index.

    " }, "ItemCollectionMetrics":{ "shape":"ItemCollectionMetrics", @@ -6933,6 +7146,10 @@ "GlobalTableSettingsReplicationMode":{ "shape":"GlobalTableSettingsReplicationMode", "documentation":"

    Controls the settings replication mode for a global table replica. This attribute can be defined using UpdateTable operation only on a regional table with values:

    • ENABLED: Defines settings replication on a regional table to be used as a source table for creating Multi-Account Global Table.

    • DISABLED: Remove settings replication on a regional table. Settings replication needs to be defined to ENABLED again in order to create a Multi-Account Global Table using this table.

    " + }, + "VectorIndexUpdates":{ + "shape":"VectorIndexUpdateList", + "documentation":"

    A list of vector indexes to be added to or removed from the table. You can add or remove one vector index for each UpdateTable operation.

    To add a vector index, specify IndexName, VectorAttribute, Dimensions, DistanceFunction, and Projection. To remove a vector index, specify only the IndexName.

    " } }, "documentation":"

    Represents the input of an UpdateTable operation.

    " @@ -7004,6 +7221,196 @@ } } }, + "VectorAttributeDefinition":{ + "type":"structure", + "required":["AttributeName"], + "members":{ + "AttributeName":{ + "shape":"VectorAttributeName", + "documentation":"

    The name of the vector attribute.

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

    The definition of a vector attribute for a vector index.

    " + }, + "VectorAttributeName":{ + "type":"string", + "max":255, + "min":1 + }, + "VectorCapacity":{ + "type":"structure", + "members":{ + "VectorSearchRequestBytes":{ + "shape":"ConsumedCapacityUnits", + "documentation":"

    The number of vector search request bytes consumed by a SearchVectors operation.

    " + }, + "VectorWriteRequestBytes":{ + "shape":"ConsumedCapacityUnits", + "documentation":"

    The number of vector write request bytes consumed when writing to a vector index. Reported for write operations that modify attributes indexed by a vector index.

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

    The consumed capacity for vector index operations, including vector search request bytes and vector write request bytes.

    " + }, + "VectorDistanceFunction":{ + "type":"string", + "enum":[ + "COSINE", + "DOT_PRODUCT", + "EUCLIDEAN" + ] + }, + "VectorIndex":{ + "type":"structure", + "required":[ + "IndexName", + "VectorAttribute", + "Projection", + "Dimensions", + "DistanceFunction" + ], + "members":{ + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index.

    " + }, + "VectorAttribute":{ + "shape":"VectorAttributeDefinition", + "documentation":"

    The vector attribute configuration for the index.

    " + }, + "SearchSchema":{ + "shape":"SearchSchema", + "documentation":"

    The search schema that defines partition key and inline filter attributes for the vector index.

    " + }, + "Projection":{ + "shape":"Projection", + "documentation":"

    Specifies attributes that are copied (projected) from the table into the vector index.

    " + }, + "Dimensions":{ + "shape":"PositiveLongObject", + "documentation":"

    The number of dimensions in each vector.

    " + }, + "DistanceFunction":{ + "shape":"VectorDistanceFunction", + "documentation":"

    The distance function used to calculate similarity between vectors. Valid values: COSINE, EUCLIDEAN, DOT_PRODUCT.

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

    Contains the configuration settings for a vector index, including the index name, vector attribute, dimensions, distance function, search schema, and projection.

    " + }, + "VectorIndexDescription":{ + "type":"structure", + "members":{ + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index.

    " + }, + "SearchSchema":{ + "shape":"SearchSchema", + "documentation":"

    The search schema that defines partition key and inline filter attributes for the vector index.

    " + }, + "Projection":{ + "shape":"Projection", + "documentation":"

    Specifies attributes that are copied (projected) from the table into the vector index.

    " + }, + "VectorAttribute":{ + "shape":"VectorAttributeDefinition", + "documentation":"

    The vector attribute configuration for the index.

    " + }, + "Dimensions":{ + "shape":"PositiveLongObject", + "documentation":"

    The number of dimensions in each vector.

    " + }, + "DistanceFunction":{ + "shape":"VectorDistanceFunction", + "documentation":"

    The distance function used to calculate similarity between vectors.

    " + }, + "IndexStatus":{ + "shape":"IndexStatus", + "documentation":"

    The current state of the vector index:

    • CREATING - The index is being created.

    • ACTIVE - The index is ready for use.

    • DELETING - The index is being deleted.

    " + }, + "Backfilling":{ + "shape":"Backfilling", + "documentation":"

    Specifies whether the index is currently backfilling. During backfill, SearchVectors operations might return incomplete results.

    " + }, + "IndexSizeBytes":{ + "shape":"LongObject", + "documentation":"

    The total size of the vector index, in bytes. Amazon DynamoDB updates this value approximately every six hours. Recent changes might not be reflected in this value.

    " + }, + "ItemCount":{ + "shape":"LongObject", + "documentation":"

    The number of items indexed in the vector index. Amazon DynamoDB updates this value approximately every six hours. Recent changes might not be reflected in this value.

    " + }, + "IndexArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the vector index.

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

    Contains the current state and configuration of a vector index, including its status, size, item count, and the settings specified when the index was created.

    " + }, + "VectorIndexDescriptionList":{ + "type":"list", + "member":{"shape":"VectorIndexDescription"} + }, + "VectorIndexInfo":{ + "type":"structure", + "members":{ + "IndexName":{ + "shape":"IndexName", + "documentation":"

    The name of the vector index.

    " + }, + "VectorAttribute":{ + "shape":"VectorAttributeDefinition", + "documentation":"

    The vector attribute configuration for the index.

    " + }, + "SearchSchema":{ + "shape":"SearchSchema", + "documentation":"

    The search schema that defines partition key and inline filter attributes for the vector index.

    " + }, + "Projection":{ + "shape":"Projection", + "documentation":"

    Specifies attributes that are copied (projected) from the table into the vector index.

    " + }, + "Dimensions":{ + "shape":"PositiveLongObject", + "documentation":"

    The number of dimensions in each vector.

    " + }, + "DistanceFunction":{ + "shape":"VectorDistanceFunction", + "documentation":"

    The distance function used to calculate similarity between vectors.

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

    Contains the configuration of a vector index as it existed at the time a backup was created.

    " + }, + "VectorIndexList":{ + "type":"list", + "member":{"shape":"VectorIndex"} + }, + "VectorIndexUpdate":{ + "type":"structure", + "members":{ + "Create":{ + "shape":"CreateVectorIndexAction", + "documentation":"

    The configuration for creating a new vector index on the table.

    " + }, + "Delete":{ + "shape":"DeleteVectorIndexAction", + "documentation":"

    The configuration for deleting an existing vector index from the table.

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

    A vector index to be added to or removed from a table.

    " + }, + "VectorIndexUpdateList":{ + "type":"list", + "member":{"shape":"VectorIndexUpdate"} + }, + "VectorIndexes":{ + "type":"list", + "member":{"shape":"VectorIndexInfo"} + }, + "VectorIndexesCapacityMap":{ + "type":"map", + "key":{"shape":"IndexName"}, + "value":{"shape":"VectorCapacity"} + }, "WarmThroughput":{ "type":"structure", "members":{ diff --git a/services/dynamodb/src/main/resources/codegen-resources/dynamodbstreams/customization.config b/services/dynamodb/src/main/resources/codegen-resources/dynamodbstreams/customization.config index bb7121a9fd10..41101d3f9ff3 100644 --- a/services/dynamodb/src/main/resources/codegen-resources/dynamodbstreams/customization.config +++ b/services/dynamodb/src/main/resources/codegen-resources/dynamodbstreams/customization.config @@ -21,6 +21,5 @@ }, "verifiedSimpleMethods" : [ "listStreams" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java new file mode 100644 index 000000000000..489d8309c377 --- /dev/null +++ b/services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java @@ -0,0 +1,278 @@ +/* + * 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.dynamodb.endpoints.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.dynamodb.endpoints.DynamoDbEndpointParams; +import software.amazon.awssdk.services.dynamodb.jmespath.internal.JmesPathRuntime.Value; +import software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest; +import software.amazon.awssdk.services.dynamodb.model.ConditionCheck; +import software.amazon.awssdk.services.dynamodb.model.Delete; +import software.amazon.awssdk.services.dynamodb.model.Get; +import software.amazon.awssdk.services.dynamodb.model.ImportTableRequest; +import software.amazon.awssdk.services.dynamodb.model.KeysAndAttributes; +import software.amazon.awssdk.services.dynamodb.model.Put; +import software.amazon.awssdk.services.dynamodb.model.TableCreationParameters; +import software.amazon.awssdk.services.dynamodb.model.TransactGetItem; +import software.amazon.awssdk.services.dynamodb.model.TransactGetItemsRequest; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItem; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest; +import software.amazon.awssdk.services.dynamodb.model.Update; +import software.amazon.awssdk.services.dynamodb.model.WriteRequest; + +/** + * Verifies that the codegen-lowered {@code operationContextParams} bindings for DynamoDB produce the same + * values as the reflective {@code JmesPathRuntime} evaluation, which remains the fallback for unsupported + * expressions and is used here as the equivalence oracle. Covers {@code keys()}, a scalar field chain, a + * projection, and a multiselect-list + flatten (TransactWriteItems). + * + *

    Each lowered binding is invoked directly via its generated, private + * {@code setOperationContextParams(builder, request)} overload, so the check is isolated to the binding itself. + */ +public class OperationContextParamsBindingEquivalenceTest { + + private static List loweredList(Object request) { + return invokeBinding(request).resourceArnList(); + } + + private static String loweredScalar(Object request) { + return invokeBinding(request).resourceArn(); + } + + private static DynamoDbEndpointParams invokeBinding(Object request) { + try { + Method binding = DynamoDbEndpointResolverUtils.class.getDeclaredMethod( + "setOperationContextParams", DynamoDbEndpointParams.Builder.class, request.getClass()); + binding.setAccessible(true); + DynamoDbEndpointParams.Builder builder = DynamoDbEndpointParams.builder(); + binding.invoke(null, builder, request); + return builder.build(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private static void assertKeysEquivalent(List reflectiveResult, List loweredResult, + List expectedContent) { + assertEquals(reflectiveResult.size(), loweredResult.size(), + "lowered result must contain the same number of keys as reflective evaluation"); + assertEquals(new HashSet<>(reflectiveResult), new HashSet<>(loweredResult), + "lowered key content must equal reflective evaluation"); + assertEquals(new HashSet<>(expectedContent), new HashSet<>(loweredResult), "content must match"); + } + + @Test + public void batchGetItemKeys() { + BatchGetItemRequest empty = BatchGetItemRequest.builder().build(); + assertKeysEquivalent(new Value(empty).field("RequestItems").keys().stringValues(), + loweredList(empty), Collections.emptyList()); + + String[] keys = {"zebra", "mango", "apple", "delta", "foxtrot", "bravo", "yankee", "tango", "kilo", "echo"}; + Map items = new LinkedHashMap<>(); + for (String key : keys) { + items.put(key, KeysAndAttributes.builder().build()); + } + BatchGetItemRequest req = BatchGetItemRequest.builder().requestItems(items).build(); + assertKeysEquivalent(new Value(req).field("RequestItems").keys().stringValues(), + loweredList(req), Arrays.asList(keys)); + } + + @Test + public void batchGetItemNullKeyDropped() { + Map items = new LinkedHashMap<>(); + items.put(null, KeysAndAttributes.builder().build()); + items.put("table", KeysAndAttributes.builder().build()); + BatchGetItemRequest req = BatchGetItemRequest.builder().requestItems(items).build(); + assertKeysEquivalent(new Value(req).field("RequestItems").keys().stringValues(), + loweredList(req), Collections.singletonList("table")); + } + + @Test + public void batchWriteItemKeys() { + Map> items = new LinkedHashMap<>(); + items.put("t1", Collections.emptyList()); + items.put("t2", Collections.singletonList(WriteRequest.builder().build())); + BatchWriteItemRequest req = BatchWriteItemRequest.builder().requestItems(items).build(); + assertKeysEquivalent(new Value(req).field("RequestItems").keys().stringValues(), + loweredList(req), Arrays.asList("t1", "t2")); + } + + private static void assertImportTableEquivalent(ImportTableRequest req, String expected) { + String ref = new Value(req).field("TableCreationParameters").field("TableName").stringValue(); + String low = loweredScalar(req); + assertEquals(ref, low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + @Test + public void importTableContainerNull() { + assertImportTableEquivalent(ImportTableRequest.builder().build(), null); + } + + @Test + public void importTableScalarPresent() { + assertImportTableEquivalent( + ImportTableRequest.builder() + .tableCreationParameters(TableCreationParameters.builder().tableName("my-table").build()) + .build(), + "my-table"); + } + + @Test + public void importTableScalarLeafNull() { + assertImportTableEquivalent( + ImportTableRequest.builder() + .tableCreationParameters(TableCreationParameters.builder().build()) + .build(), + null); + } + + private static void assertGetEquivalent(TransactGetItemsRequest req, List expected) { + List ref = new Value(req).field("TransactItems").wildcard().field("Get").field("TableName").stringValues(); + List low = loweredList(req); + assertEquals(ref, low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + @Test + public void transactGetEmpty() { + assertGetEquivalent(TransactGetItemsRequest.builder().build(), Collections.emptyList()); + } + + @Test + public void transactGetMultiple() { + TransactGetItem g1 = TransactGetItem.builder().get(Get.builder().tableName("ga").build()).build(); + TransactGetItem g2 = TransactGetItem.builder().get(Get.builder().tableName("gb").build()).build(); + assertGetEquivalent(TransactGetItemsRequest.builder().transactItems(g1, g2).build(), + Arrays.asList("ga", "gb")); + } + + @Test + public void transactGetNullInnerAndLeaf() { + TransactGetItem hasName = TransactGetItem.builder().get(Get.builder().tableName("ga").build()).build(); + TransactGetItem getNull = TransactGetItem.builder().build(); + TransactGetItem leafNull = TransactGetItem.builder().get(Get.builder().build()).build(); + assertGetEquivalent(TransactGetItemsRequest.builder().transactItems(hasName, getNull, leafNull).build(), + Collections.singletonList("ga")); + } + + private static List reflectiveWrite(TransactWriteItemsRequest req) { + Function cc = v -> v.field("ConditionCheck").field("TableName"); + Function put = v -> v.field("Put").field("TableName"); + Function del = v -> v.field("Delete").field("TableName"); + Function upd = v -> v.field("Update").field("TableName"); + return new Value(req).field("TransactItems").wildcard() + .multiSelectList(cc, put, del, upd).flatten().stringValues(); + } + + private static void assertWriteEquivalent(TransactWriteItemsRequest req, List expected) { + List low = loweredList(req); + assertEquals(reflectiveWrite(req), low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + @Test + public void transactWriteEmpty() { + assertWriteEquivalent(TransactWriteItemsRequest.builder().build(), Collections.emptyList()); + } + + @Test + public void transactWriteSingleBranch() { + TransactWriteItem putOnly = TransactWriteItem.builder().put(Put.builder().tableName("p1").build()).build(); + assertWriteEquivalent(TransactWriteItemsRequest.builder().transactItems(putOnly).build(), + Collections.singletonList("p1")); + } + + @Test + public void transactWriteAllBranchesOrdered() { + // Within one item the multiselect order is [ConditionCheck, Put, Delete, Update]. + TransactWriteItem all = TransactWriteItem.builder() + .conditionCheck(ConditionCheck.builder().tableName("cc").build()) + .put(Put.builder().tableName("p").build()) + .delete(Delete.builder().tableName("d").build()) + .update(Update.builder().tableName("u").build()) + .build(); + assertWriteEquivalent(TransactWriteItemsRequest.builder().transactItems(all).build(), + Arrays.asList("cc", "p", "d", "u")); + } + + @Test + public void transactWriteMixedItemsAndNullLeaf() { + TransactWriteItem item1 = TransactWriteItem.builder().put(Put.builder().tableName("p1").build()).build(); + TransactWriteItem item2 = TransactWriteItem.builder() + .conditionCheck(ConditionCheck.builder().tableName("cc2").build()) + .delete(Delete.builder().tableName("d2").build()) + .build(); + // Put present but its TableName null -> dropped. + TransactWriteItem item3 = TransactWriteItem.builder().put(Put.builder().build()).build(); + assertWriteEquivalent( + TransactWriteItemsRequest.builder().transactItems(item1, item2, item3).build(), + Arrays.asList("p1", "cc2", "d2")); + } + + @Test + public void transactWriteNullItemGuarded() { + List items = new ArrayList<>(); + items.add(TransactWriteItem.builder().put(Put.builder().tableName("p1").build()).build()); + items.add(null); + assertWriteEquivalent(TransactWriteItemsRequest.builder().transactItems(items).build(), + Collections.singletonList("p1")); + } + + /** + * The equivalence assertions above are only meaningful if the generated methods are actually lowered: a codegen + * regression that sends these operations back to the reflective path would make every comparison + * oracle-against-itself. The resolver's class file must not reference the reflective runtime. + */ + @Test + public void operationContextParamBindingsDoNotUseReflectiveFallback() throws IOException { + byte[] classBytes = readClassBytes(DynamoDbEndpointResolverUtils.class); + assertFalse(new String(classBytes, StandardCharsets.ISO_8859_1).contains("JmesPathRuntime"), + "The generated resolver references JmesPathRuntime, so at least one operation's bindings use the " + + "reflective fallback. If a codegen change caused this, fix the regression. If a model change " + + "added an expression outside the lowering subset, the fallback is working as designed but is a " + + "performance regression for that operation: extend the lowerer or consciously update this test."); + } + + private static byte[] readClassBytes(Class clazz) throws IOException { + try (InputStream in = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) > 0) { + out.write(buffer, 0, read); + } + return out.toByteArray(); + } + } +} diff --git a/services/ebs/pom.xml b/services/ebs/pom.xml index ec18bdafac6a..9c12319705f6 100644 --- a/services/ebs/pom.xml +++ b/services/ebs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ebs AWS Java SDK :: Services :: EBS diff --git a/services/ebs/src/main/resources/codegen-resources/customization.config b/services/ebs/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ebs/src/main/resources/codegen-resources/customization.config +++ b/services/ebs/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ebs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ebs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9bdbdd1d488b --- /dev/null +++ b/services/ebs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ebs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ebs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ebs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ebs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ebs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ebs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e6ec388a5b2a..000000000000 --- a/services/ebs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ebs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ebs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ebs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ebs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ec2/pom.xml b/services/ec2/pom.xml index 6e54a203b77b..1f48d594a190 100644 --- a/services/ec2/pom.xml +++ b/services/ec2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ec2 AWS Java SDK :: Services :: Amazon EC2 diff --git a/services/ec2/src/main/resources/codegen-resources/customization.config b/services/ec2/src/main/resources/codegen-resources/customization.config index 0fa0ad4afc2d..d3fd63aea99d 100644 --- a/services/ec2/src/main/resources/codegen-resources/customization.config +++ b/services/ec2/src/main/resources/codegen-resources/customization.config @@ -348,8 +348,6 @@ "interceptors": [ "software.amazon.awssdk.services.ec2.transform.internal.GeneratePreSignUrlInterceptor", "software.amazon.awssdk.services.ec2.transform.internal.TimestampFormatInterceptor" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ec2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ec2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7bd2756775fd --- /dev/null +++ b/services/ec2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ec2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ec2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ed2816b5b16c..000000000000 --- a/services/ec2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ec2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://ec2.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ec2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ec2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ec2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ec2/src/main/resources/codegen-resources/paginators-1.json b/services/ec2/src/main/resources/codegen-resources/paginators-1.json index b293a481cd7c..928b173eb9e6 100644 --- a/services/ec2/src/main/resources/codegen-resources/paginators-1.json +++ b/services/ec2/src/main/resources/codegen-resources/paginators-1.json @@ -78,6 +78,12 @@ "output_token": "NextToken", "result_key": "CapacityReservationBillingRequests" }, + "DescribeCapacityReservationDateChangeQuotes": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "output_token": "NextToken", + "result_key": "CapacityReservationModificationQuotes" + }, "DescribeCapacityReservationFleets": { "input_token": "NextToken", "limit_key": "MaxResults", @@ -1001,6 +1007,12 @@ "output_token": "NextToken", "result_key": "Associations" }, + "GetTransitGatewayPolicyTableEntries": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "output_token": "NextToken", + "result_key": "TransitGatewayPolicyTableEntries" + }, "GetTransitGatewayPrefixListReferences": { "input_token": "NextToken", "limit_key": "MaxResults", diff --git a/services/ec2/src/main/resources/codegen-resources/service-2.json b/services/ec2/src/main/resources/codegen-resources/service-2.json index ee58b10b8380..d9d07919e40c 100644 --- a/services/ec2/src/main/resources/codegen-resources/service-2.json +++ b/services/ec2/src/main/resources/codegen-resources/service-2.json @@ -194,6 +194,16 @@ "output":{"shape":"AssociateAddressResult"}, "documentation":"

    Associates an Elastic IP address, or carrier IP address (for instances that are in subnets in Wavelength Zones) with an instance or a network interface. Before you can use an Elastic IP address, you must allocate it to your account.

    If the Elastic IP address is already associated with a different instance, it is disassociated from that instance and associated with the specified instance. If you associate an Elastic IP address with an instance that has an existing Elastic IP address, the existing address is disassociated from the instance, but remains allocated to your account.

    [Subnets in Wavelength Zones] You can associate an IP address from the telecommunication carrier to the instance or network interface.

    You cannot associate an Elastic IP address with an interface in a different network border group.

    This is an idempotent operation. If you perform the operation more than once, Amazon EC2 doesn't return an error, and you may be charged for each time the Elastic IP address is remapped to the same instance. For more information, see the Elastic IP Addresses section of Amazon EC2 Pricing.

    " }, + "AssociateApplicationStatusCheck":{ + "name":"AssociateApplicationStatusCheck", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AssociateApplicationStatusCheckRequest"}, + "output":{"shape":"AssociateApplicationStatusCheckResult"}, + "documentation":"

    Associates an application status check with instances or tags. Once you create an association, health monitoring automatically begins for the specified instances or for instances that match the specified tags. The following rules apply:

    • You must specify either TargetTagAssociations or InstanceIds, but not both. Specifying both results in an InvalidParameterCombination error.

    • You must own the application status check. The check must already exist in your account.

    • You must not leave tag keys blank.

    • You can create a maximum of 50 tag associations for each application status check.

    • You can use DisassociateApplicationStatusCheck to remove associations.

    • You can associate tags so that the application status check automatically monitors all current and future instances that have the specified tags.

    " + }, "AssociateCapacityReservationBillingOwner":{ "name":"AssociateCapacityReservationBillingOwner", "http":{ @@ -472,6 +482,16 @@ "output":{"shape":"AuthorizeSecurityGroupIngressResult"}, "documentation":"

    Adds the specified inbound (ingress) rules to a security group.

    An inbound rule permits instances to receive traffic from the specified IPv4 or IPv6 address range, the IP address ranges that are specified by a prefix list, or the instances that are associated with a destination security group. For more information, see Security group rules.

    You must specify exactly one of the following sources: an IPv4 or IPv6 address range, a prefix list, or a security group. You must specify a protocol for each rule (for example, TCP). If the protocol is TCP or UDP, you must also specify a port or port range. If the protocol is ICMP or ICMPv6, you must also specify the ICMP/ICMPv6 type and code.

    Rule changes are propagated to instances associated with the security group as quickly as possible. However, a small delay might occur.

    For examples of rules that you can add to security groups for specific access scenarios, see Security group rules for different use cases in the Amazon EC2 User Guide.

    For more information about security group quotas, see Amazon VPC quotas in the Amazon VPC User Guide.

    " }, + "BatchModifyIpamRoutingPolicyRegistrations":{ + "name":"BatchModifyIpamRoutingPolicyRegistrations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"BatchModifyIpamRoutingPolicyRegistrationsRequest"}, + "output":{"shape":"BatchModifyIpamRoutingPolicyRegistrationsResult"}, + "documentation":"

    Modifies multiple routing policy registrations in a single operation. You can create, update, or delete Route Origin Authorizations (ROAs) in batch.

    " + }, "BundleInstance":{ "name":"BundleInstance", "http":{ @@ -480,7 +500,7 @@ }, "input":{"shape":"BundleInstanceRequest"}, "output":{"shape":"BundleInstanceResult"}, - "documentation":"

    Bundles an Amazon instance store-backed Windows instance.

    During bundling, only the root device volume (C:\\) is bundled. Data on other instance store volumes is not preserved.

    This action is no longer supported. To create an AMI, use CreateImage. For more information, see Create an Amazon EBS-backed AMI in the Amazon EC2 User Guide.

    " + "documentation":"

    Bundles an Amazon instance store-backed Windows instance.

    During bundling, only the root device volume (C:\\) is bundled. Data on other instance store volumes is not preserved.

    BundleInstance is no longer supported. To create an AMI, use CreateImage instead. For more information about creating an Amazon EBS-backed AMI, see Create an Amazon EBS-backed AMI in the Amazon EC2 User Guide.

    " }, "CancelBundleTask":{ "name":"CancelBundleTask", @@ -490,7 +510,7 @@ }, "input":{"shape":"CancelBundleTaskRequest"}, "output":{"shape":"CancelBundleTaskResult"}, - "documentation":"

    Cancels a bundling operation for an instance store-backed Windows instance.

    " + "documentation":"

    Cancels a bundling operation for an instance store-backed Windows instance.

    CancelBundleTask is no longer supported because BundleInstance, the operation it cancels, is no longer supported.

    " }, "CancelCapacityReservation":{ "name":"CancelCapacityReservation", @@ -640,6 +660,16 @@ "output":{"shape":"CopyVolumesResult"}, "documentation":"

    Creates a crash-consistent, point-in-time copy of an existing Amazon EBS volume within the same Availability Zone. The volume copy can be attached to an Amazon EC2 instance once it reaches the available state. For more information, see Copy an Amazon EBS volume.

    " }, + "CreateApplicationStatusCheck":{ + "name":"CreateApplicationStatusCheck", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateApplicationStatusCheckRequest"}, + "output":{"shape":"CreateApplicationStatusCheckResult"}, + "documentation":"

    Creates an application status check for monitoring the health of applications running on your instances. You can configure the protocol, port, path, and thresholds for the health check. The following rules apply:

    • You can create a maximum of 50 application status checks for each account.

    • You must associate the check with instances or tags using AssociateApplicationStatusCheck before health checks start.

    • You must set the Timeout value to less than the Interval value.

    • You must start the Path with a forward slash (/). Default: /.

    • You can specify Aggregation as included or excluded. If you do not specify a value, it defaults to included, which means the check contributes to the instance-level application status.

    • You can use the following default values: Interval is 60 seconds, Timeout is 6 seconds, FailureThreshold is 2, SuccessThreshold is 2, StatusCodeMatcher is 200, InitializationGracePeriodSeconds is 300 seconds.

    • You can tag the application status check during creation. For more information, see Tag your Amazon EC2 resources.

    " + }, "CreateCapacityManagerDataExport":{ "name":"CreateCapacityManagerDataExport", "http":{ @@ -680,6 +710,16 @@ "output":{"shape":"CreateCapacityReservationCancellationQuoteResult"}, "documentation":"

    Generates a cancellation quote for a future-dated Capacity Reservation that is within its commitment duration. The quote includes the cancellation terms and a quote ID that you can pass to the CancelCapacityReservation action. Cancellation quotes are valid for 24 hours.

    " }, + "CreateCapacityReservationDateChangeQuote":{ + "name":"CreateCapacityReservationDateChangeQuote", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateCapacityReservationDateChangeQuoteRequest"}, + "output":{"shape":"CreateCapacityReservationDateChangeQuoteResult"}, + "documentation":"

    Generates a quote for changing the start date of a future-dated Capacity Reservation that has not yet been delivered. The quote includes the new start date, the resulting commitment end date, and a quote ID. Pass the quote ID to ModifyCapacityReservation to apply the change.

    The cumulative pushout across all changes is limited to 30 days from the Capacity Reservation's original start date. Quotes are valid for 24 hours, and always expire at least one hour before the start date.

    " + }, "CreateCapacityReservationFleet":{ "name":"CreateCapacityReservationFleet", "http":{ @@ -838,7 +878,7 @@ }, "input":{"shape":"CreateImageRequest"}, "output":{"shape":"CreateImageResult"}, - "documentation":"

    Creates an Amazon EBS-backed AMI from an Amazon EBS-backed instance that is either running or stopped.

    If you customized your instance with instance store volumes or Amazon EBS volumes in addition to the root device volume, the new AMI contains block device mapping information for those volumes. When you launch an instance from this new AMI, the instance automatically launches with those additional volumes.

    The location of the source instance determines where you can create the snapshots of the AMI:

    • If the source instance is in a Region, you must create the snapshots in the same Region as the instance.

    • If the source instance is in a Local Zone, you can create the snapshots in the same Local Zone or in its parent Region.

    For more information, see Create an Amazon EBS-backed AMI in the Amazon Elastic Compute Cloud User Guide.

    " + "documentation":"

    Creates an Amazon EBS-backed AMI from an Amazon EBS-backed instance that is either running or stopped.

    If you customized your instance with instance store volumes or Amazon EBS volumes in addition to the root device volume, the new AMI contains block device mapping information for those volumes. When you launch an instance from this new AMI, the instance automatically launches with those additional volumes.

    The location of the source instance determines where you can create the snapshots of the AMI:

    • If the source instance is in a Region, you must create the snapshots in the same Region as the instance.

    • If the source instance is in a Local Zone, you can create the snapshots in the same Local Zone or in its parent Region.

    • If the source instance is on an Outpost that supports local snapshots, you can create the snapshots on the same Outpost or in the parent Region of that Outpost. In this case, you must use the SnapshotLocation parameter to specify where to create the snapshots.

    For more information, see Create an Amazon EBS-backed AMI in the Amazon Elastic Compute Cloud User Guide.

    " }, "CreateImageUsageReport":{ "name":"CreateImageUsageReport", @@ -920,6 +960,16 @@ "output":{"shape":"CreateIpamExternalResourceVerificationTokenResult"}, "documentation":"

    Create a verification token.

    A verification token is an Amazon Web Services-generated random value that you can use to prove ownership of an external resource. For example, you can use a verification token to validate that you control a public IP address range when you bring an IP address range to Amazon Web Services (BYOIP).

    " }, + "CreateIpamInternetRegistryAssociation":{ + "name":"CreateIpamInternetRegistryAssociation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateIpamInternetRegistryAssociationRequest"}, + "output":{"shape":"CreateIpamInternetRegistryAssociationResult"}, + "documentation":"

    Creates an association between an IPAM and a Regional Internet Registry (RIR) for Resource Public Key Infrastructure (RPKI) management. You can use this association to create Route Origin Authorizations (ROAs) for IP address prefixes registered with the internet registry. Your IPAM must be in the Advanced tier to use this feature.

    " + }, "CreateIpamPolicy":{ "name":"CreateIpamPolicy", "http":{ @@ -970,6 +1020,16 @@ "output":{"shape":"CreateIpamResourceDiscoveryResult"}, "documentation":"

    Creates an IPAM resource discovery. A resource discovery is an IPAM component that enables IPAM to manage and monitor resources that belong to the owning account.

    " }, + "CreateIpamRoutingPolicyRegistration":{ + "name":"CreateIpamRoutingPolicyRegistration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateIpamRoutingPolicyRegistrationRequest"}, + "output":{"shape":"CreateIpamRoutingPolicyRegistrationResult"}, + "documentation":"

    Creates a routing policy registration and publishes Route Origin Authorizations (ROAs) to the RPKI for the specified CIDR prefix and ASNs.

    " + }, "CreateIpamScope":{ "name":"CreateIpamScope", "http":{ @@ -1478,6 +1538,16 @@ "output":{"shape":"CreateTransitGatewayPolicyTableResult"}, "documentation":"

    Creates a transit gateway policy table.

    " }, + "CreateTransitGatewayPolicyTableEntry":{ + "name":"CreateTransitGatewayPolicyTableEntry", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateTransitGatewayPolicyTableEntryRequest"}, + "output":{"shape":"CreateTransitGatewayPolicyTableEntryResult"}, + "documentation":"

    Creates an entry in a transit gateway policy table to route matching traffic to a specified route table.

    " + }, "CreateTransitGatewayPrefixListReference":{ "name":"CreateTransitGatewayPrefixListReference", "http":{ @@ -1687,6 +1757,16 @@ "output":{"shape":"CreateVpnGatewayResult"}, "documentation":"

    Creates a virtual private gateway. A virtual private gateway is the endpoint on the VPC side of your VPN connection. You can create a virtual private gateway before creating the VPC itself.

    For more information, see Amazon Web Services Site-to-Site VPN in the Amazon Web Services Site-to-Site VPN User Guide.

    " }, + "DeleteApplicationStatusCheck":{ + "name":"DeleteApplicationStatusCheck", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteApplicationStatusCheckRequest"}, + "output":{"shape":"DeleteApplicationStatusCheckResult"}, + "documentation":"

    Deletes an application status check. The following rules apply:

    • Deleting a check automatically removes all of its associations.

    • Use DescribeApplicationStatusChecks to view existing checks before deleting.

    " + }, "DeleteCapacityManagerDataExport":{ "name":"DeleteCapacityManagerDataExport", "http":{ @@ -1864,6 +1944,16 @@ "output":{"shape":"DeleteIpamExternalResourceVerificationTokenResult"}, "documentation":"

    Delete a verification token.

    A verification token is an Amazon Web Services-generated random value that you can use to prove ownership of an external resource. For example, you can use a verification token to validate that you control a public IP address range when you bring an IP address range to Amazon Web Services (BYOIP).

    " }, + "DeleteIpamInternetRegistryAssociation":{ + "name":"DeleteIpamInternetRegistryAssociation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteIpamInternetRegistryAssociationRequest"}, + "output":{"shape":"DeleteIpamInternetRegistryAssociationResult"}, + "documentation":"

    Deletes an IPAM internet registry association. Before deleting, you must remove all routing policy registrations associated with the internet registry.

    " + }, "DeleteIpamPolicy":{ "name":"DeleteIpamPolicy", "http":{ @@ -1914,6 +2004,16 @@ "output":{"shape":"DeleteIpamResourceDiscoveryResult"}, "documentation":"

    Deletes an IPAM resource discovery. A resource discovery is an IPAM component that enables IPAM to manage and monitor resources that belong to the owning account.

    " }, + "DeleteIpamRoutingPolicyRegistration":{ + "name":"DeleteIpamRoutingPolicyRegistration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteIpamRoutingPolicyRegistrationRequest"}, + "output":{"shape":"DeleteIpamRoutingPolicyRegistrationResult"}, + "documentation":"

    Deletes a routing policy registration for a specified CIDR prefix.

    " + }, "DeleteIpamScope":{ "name":"DeleteIpamScope", "http":{ @@ -2394,6 +2494,16 @@ "output":{"shape":"DeleteTransitGatewayPolicyTableResult"}, "documentation":"

    Deletes the specified transit gateway policy table.

    " }, + "DeleteTransitGatewayPolicyTableEntry":{ + "name":"DeleteTransitGatewayPolicyTableEntry", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteTransitGatewayPolicyTableEntryRequest"}, + "output":{"shape":"DeleteTransitGatewayPolicyTableEntryResult"}, + "documentation":"

    Deletes the specified transit gateway policy table entry.

    " + }, "DeleteTransitGatewayPrefixListReference":{ "name":"DeleteTransitGatewayPrefixListReference", "http":{ @@ -2739,6 +2849,36 @@ "output":{"shape":"DescribeAggregateIdFormatResult"}, "documentation":"

    Describes the longer ID format settings for all resource types in a specific Region. This request is useful for performing a quick audit to determine whether a specific Region is fully opted in for longer IDs (17-character IDs).

    This request only returns information about resource types that support longer IDs.

    The following resource types support longer IDs: bundle | conversion-task | customer-gateway | dhcp-options | elastic-ip-allocation | elastic-ip-association | export-task | flow-log | image | import-task | instance | internet-gateway | network-acl | network-acl-association | network-interface | network-interface-attachment | prefix-list | reservation | route-table | route-table-association | security-group | snapshot | subnet | subnet-cidr-block-association | volume | vpc | vpc-cidr-block-association | vpc-endpoint | vpc-peering-connection | vpn-connection | vpn-gateway.

    " }, + "DescribeApplicationStatus":{ + "name":"DescribeApplicationStatus", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeApplicationStatusRequest"}, + "output":{"shape":"DescribeApplicationStatusResult"}, + "documentation":"

    Describes the aggregated application health status for the specified instances. The following rules apply:

    • The instance-level status is derived from all application status checks with the aggregation setting set to included.

    • Use DescribeApplicationStatusChecks to view the configuration of individual checks.

    • Use EnableApplicationStatusCheckSuppression to temporarily suppress health check results from affecting the instance-level status.

    " + }, + "DescribeApplicationStatusCheckAssociations":{ + "name":"DescribeApplicationStatusCheckAssociations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeApplicationStatusCheckAssociationsRequest"}, + "output":{"shape":"DescribeApplicationStatusCheckAssociationsResult"}, + "documentation":"

    Describes the associations for one or more application status checks. For more information, see Application status checks. To avoid timeouts and retrieve complete results, use the pagination parameters.

    The order of the elements in the response, including those within nested structures, might vary.

    " + }, + "DescribeApplicationStatusChecks":{ + "name":"DescribeApplicationStatusChecks", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeApplicationStatusChecksRequest"}, + "output":{"shape":"DescribeApplicationStatusChecksResult"}, + "documentation":"

    Describes application status checks, including configuration details such as protocol, port, path, thresholds, and associations. Results are paginated. Use the NextToken parameter to retrieve additional results. The following rules apply:

    • If you do not specify any application status check IDs, all checks in your account are returned.

    • Use DescribeApplicationStatus to see the actual health status of instances.

    " + }, "DescribeAvailabilityZones":{ "name":"DescribeAvailabilityZones", "http":{ @@ -2859,6 +2999,16 @@ "output":{"shape":"DescribeCapacityReservationCancellationQuotesResult"}, "documentation":"

    Describes one or more Capacity Reservation cancellation quotes. The results describe only the quotes that you have previously generated by using the CreateCapacityReservationCancellationQuote action.

    " }, + "DescribeCapacityReservationDateChangeQuotes":{ + "name":"DescribeCapacityReservationDateChangeQuotes", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeCapacityReservationDateChangeQuotesRequest"}, + "output":{"shape":"DescribeCapacityReservationDateChangeQuotesResult"}, + "documentation":"

    Describes one or more Capacity Reservation date change quotes that you generated by using the CreateCapacityReservationDateChangeQuote operation.

    " + }, "DescribeCapacityReservationFleets":{ "name":"DescribeCapacityReservationFleets", "http":{ @@ -3287,7 +3437,7 @@ }, "input":{"shape":"DescribeInstanceCreditSpecificationsRequest"}, "output":{"shape":"DescribeInstanceCreditSpecificationsResult"}, - "documentation":"

    Describes the credit option for CPU usage of the specified burstable performance instances. The credit options are standard and unlimited.

    If you do not specify an instance ID, Amazon EC2 returns burstable performance instances with the unlimited credit option, as well as instances that were previously configured as T2, T3, and T3a with the unlimited credit option. For example, if you resize a T2 instance, while it is configured as unlimited, to an M4 instance, Amazon EC2 returns the M4 instance.

    If you specify one or more instance IDs, Amazon EC2 returns the credit option (standard or unlimited) of those instances. If you specify an instance ID that is not valid, such as an instance that is not a burstable performance instance, an error is returned.

    Recently terminated instances might appear in the returned results. This interval is usually less than one hour.

    If an Availability Zone is experiencing a service disruption and you specify instance IDs in the affected zone, or do not specify any instance IDs at all, the call fails. If you specify only instance IDs in an unaffected zone, the call works normally.

    For more information, see Burstable performance instances in the Amazon EC2 User Guide.

    " + "documentation":"

    Describes the credit option for CPU usage of the specified burstable performance instances. The credit options are standard and unlimited.

    If you do not specify an instance ID, Amazon EC2 returns burstable performance instances with the unlimited credit option, as well as instances that were previously configured as T2, T3, and T3a with the unlimited credit option. For example, if you resize a T2 instance, while it is configured as unlimited, to an M4 instance, Amazon EC2 returns the M4 instance.

    If you specify one or more instance IDs, Amazon EC2 returns the credit option (standard or unlimited) of those instances. If you specify an instance ID that is not a burstable performance instance, Amazon EC2 returns the standard credit option.

    Recently terminated instances might appear in the returned results. This interval is usually less than one hour.

    If an Availability Zone is experiencing a service disruption and you specify instance IDs in the affected zone, or do not specify any instance IDs at all, the call fails. If you specify only instance IDs in an unaffected zone, the call works normally.

    For more information, see Burstable performance instances in the Amazon EC2 User Guide.

    " }, "DescribeInstanceEventNotificationAttributes":{ "name":"DescribeInstanceEventNotificationAttributes", @@ -3347,7 +3497,7 @@ }, "input":{"shape":"DescribeInstanceStatusRequest"}, "output":{"shape":"DescribeInstanceStatusResult"}, - "documentation":"

    Describes the status of the specified instances or all of your instances. By default, only running instances are described, unless you specifically indicate to return the status of all instances.

    Instance status includes the following components:

    • Status checks - Amazon EC2 performs status checks on running EC2 instances to identify hardware and software issues. For more information, see Status checks for your instances and Troubleshoot instances with failed status checks in the Amazon EC2 User Guide.

    • Scheduled events - Amazon EC2 can schedule events (such as reboot, stop, or terminate) for your instances related to hardware issues, software updates, or system maintenance. For more information, see Scheduled events for your instances in the Amazon EC2 User Guide.

    • Instance state - You can manage your instances from the moment you launch them through their termination. For more information, see Instance lifecycle in the Amazon EC2 User Guide.

    The Amazon EC2 API follows an eventual consistency model. This means that the result of an API command you run that creates or modifies resources might not be immediately available to all subsequent commands you run. For guidance on how to manage eventual consistency, see Eventual consistency in the Amazon EC2 API in the Amazon EC2 Developer Guide.

    The order of the elements in the response, including those within nested structures, might vary. Applications should not assume the elements appear in a particular order.

    " + "documentation":"

    Describes the status of the specified instances or all of your instances. By default, only running instances are described, unless you specifically indicate to return the status of all instances.

    Instance status includes the following components:

    • Status checks - Amazon EC2 performs status checks on running EC2 instances to identify hardware and software issues. For more information, see Status checks for your instances and Troubleshoot instances with failed status checks in the Amazon EC2 User Guide.

    • Application status checks - Amazon EC2 reports application-level health status for instances, indicating whether applications running on the instance are functioning properly.

    • Scheduled events - Amazon EC2 can schedule events (such as reboot, stop, or terminate) for your instances related to hardware issues, software updates, or system maintenance. For more information, see Scheduled events for your instances in the Amazon EC2 User Guide.

    • Instance state - You can manage your instances from the moment you launch them through their termination. For more information, see Instance lifecycle in the Amazon EC2 User Guide.

    The Amazon EC2 API follows an eventual consistency model. This means that the result of an API command you run that creates or modifies resources might not be immediately available to all subsequent commands you run. For guidance on how to manage eventual consistency, see Eventual consistency in the Amazon EC2 API in the Amazon EC2 Developer Guide.

    The order of the elements in the response, including those within nested structures, might vary. Applications should not assume the elements appear in a particular order.

    " }, "DescribeInstanceTopology":{ "name":"DescribeInstanceTopology", @@ -3419,6 +3569,16 @@ "output":{"shape":"DescribeIpamExternalResourceVerificationTokensResult"}, "documentation":"

    Describe verification tokens.

    A verification token is an Amazon Web Services-generated random value that you can use to prove ownership of an external resource. For example, you can use a verification token to validate that you control a public IP address range when you bring an IP address range to Amazon Web Services (BYOIP).

    " }, + "DescribeIpamInternetRegistryAssociations":{ + "name":"DescribeIpamInternetRegistryAssociations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeIpamInternetRegistryAssociationsRequest"}, + "output":{"shape":"DescribeIpamInternetRegistryAssociationsResult"}, + "documentation":"

    Describes one or more IPAM internet registry associations. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, "DescribeIpamPolicies":{ "name":"DescribeIpamPolicies", "http":{ @@ -4646,6 +4806,16 @@ "output":{"shape":"DisableAllowedImagesSettingsResult"}, "documentation":"

    Disables Allowed AMIs for your account in the specified Amazon Web Services Region. When set to disabled, the image criteria in your Allowed AMIs settings do not apply, and no restrictions are placed on AMI discoverability or usage. Users in your account can launch instances using any public AMI or AMI shared with your account.

    The Allowed AMIs feature does not restrict the AMIs owned by your account. Regardless of the criteria you set, the AMIs created by your account will always be discoverable and usable by users in your account.

    For more information, see Control the discovery and use of AMIs in Amazon EC2 with Allowed AMIs in Amazon EC2 User Guide.

    " }, + "DisableApplicationStatusCheckSuppression":{ + "name":"DisableApplicationStatusCheckSuppression", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DisableApplicationStatusCheckSuppressionRequest"}, + "output":{"shape":"DisableApplicationStatusCheckSuppressionResult"}, + "documentation":"

    Disables suppression of application status checks for the specified instances. After suppression is disabled, health check results resume affecting the instance-level application status. You can specify a maximum of 100 instance IDs for each request.

    " + }, "DisableAwsNetworkPerformanceMetricSubscription":{ "name":"DisableAwsNetworkPerformanceMetricSubscription", "http":{ @@ -4844,6 +5014,16 @@ "input":{"shape":"DisassociateAddressRequest"}, "documentation":"

    Disassociates an Elastic IP address from the instance or network interface it's associated with.

    This is an idempotent operation. If you perform the operation more than once, Amazon EC2 doesn't return an error.

    An address cannot be disassociated if the all of the following conditions are met:

    • Network interface has a publicDualStackDnsName publicDnsName

    • Public IPv4 address is the primary public IPv4 address

    • Network interface only has one remaining public IPv4 address

    " }, + "DisassociateApplicationStatusCheck":{ + "name":"DisassociateApplicationStatusCheck", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DisassociateApplicationStatusCheckRequest"}, + "output":{"shape":"DisassociateApplicationStatusCheckResult"}, + "documentation":"

    Disassociates an application status check from instances or tags. After disassociation, health monitoring stops for the affected instances. The following rules apply:

    • You must specify either TargetTagAssociations or InstanceIds, but not both. Specifying both results in an InvalidParameterCombination error.

    • The application status check must already exist and belong to your account.

    • Tag keys must not be blank.

    " + }, "DisassociateCapacityReservationBillingOwner":{ "name":"DisassociateCapacityReservationBillingOwner", "http":{ @@ -5033,6 +5213,16 @@ "output":{"shape":"EnableAllowedImagesSettingsResult"}, "documentation":"

    Enables Allowed AMIs for your account in the specified Amazon Web Services Region. Two values are accepted:

    • enabled: The image criteria in your Allowed AMIs settings are applied. As a result, only AMIs matching these criteria are discoverable and can be used by your account to launch instances.

    • audit-mode: The image criteria in your Allowed AMIs settings are not applied. No restrictions are placed on AMI discoverability or usage. Users in your account can launch instances using any public AMI or AMI shared with your account.

      The purpose of audit-mode is to indicate which AMIs will be affected when Allowed AMIs is enabled. In audit-mode, each AMI displays either \"ImageAllowed\": true or \"ImageAllowed\": false to indicate whether the AMI will be discoverable and available to users in the account when Allowed AMIs is enabled.

    The Allowed AMIs feature does not restrict the AMIs owned by your account. Regardless of the criteria you set, the AMIs created by your account will always be discoverable and usable by users in your account.

    For more information, see Control the discovery and use of AMIs in Amazon EC2 with Allowed AMIs in Amazon EC2 User Guide.

    " }, + "EnableApplicationStatusCheckSuppression":{ + "name":"EnableApplicationStatusCheckSuppression", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"EnableApplicationStatusCheckSuppressionRequest"}, + "output":{"shape":"EnableApplicationStatusCheckSuppressionResult"}, + "documentation":"

    Suppresses application status checks for the specified instances. While suppressed, health checks continue to run but do not affect the instance-level application status. The following rules apply:

    • You can specify a maximum of 100 instance IDs for each request.

    • Use DisableApplicationStatusCheckSuppression to resume normal health check reporting.

    • If you do not specify DurationSeconds, suppression continues indefinitely until you call DisableApplicationStatusCheckSuppression.

    " + }, "EnableAwsNetworkPerformanceMetricSubscription":{ "name":"EnableAwsNetworkPerformanceMetricSubscription", "http":{ @@ -5133,6 +5323,16 @@ "output":{"shape":"EnableInstanceSqlHaStandbyDetectionsResult"}, "documentation":"

    Enable Amazon EC2 instances running in an SQL Server High Availability cluster for SQL Server High Availability instance standby detection monitoring. Once enabled, Amazon Web Services monitors the metadata for the instances to determine whether they are active or standby nodes in the SQL Server High Availability cluster. If the instances are determined to be standby failover nodes, Amazon Web Services automatically applies SQL Server licensing fee waiver for those instances.

    To register an instance, it must be running a Windows SQL Server license-included AMI and have the Amazon Web Services Systems Manager agent installed and running. Only Windows Server 2019 and later and SQL Server (Standard and Enterprise editions) 2017 and later are supported. For more information, see Prerequisites for using SQL Server High Availability instance standby detection.

    " }, + "EnableIpamInternetRegistryAssociation":{ + "name":"EnableIpamInternetRegistryAssociation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"EnableIpamInternetRegistryAssociationRequest"}, + "output":{"shape":"EnableIpamInternetRegistryAssociationResult"}, + "documentation":"

    Enables Resource Public Key Infrastructure (RPKI) on an existing IPAM internet registry association by providing BGP Public Key Infrastructure (BPKI) certificate details. After enabling, you can create Route Origin Authorizations (ROAs) for prefixes registered with the internet registry.

    " + }, "EnableIpamOrganizationAdminAccount":{ "name":"EnableIpamOrganizationAdminAccount", "http":{ @@ -5601,6 +5801,36 @@ "output":{"shape":"GetIpamDiscoveredResourceCidrsResult"}, "documentation":"

    Returns the resource CIDRs that are monitored as part of a resource discovery. A discovered resource is a resource CIDR monitored under a resource discovery. The following resources can be discovered: VPCs, Public IPv4 pools, VPC subnets, and Elastic IP addresses.

    " }, + "GetIpamDiscoveredRoutes":{ + "name":"GetIpamDiscoveredRoutes", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamDiscoveredRoutesRequest"}, + "output":{"shape":"GetIpamDiscoveredRoutesResult"}, + "documentation":"

    Retrieves Border Gateway Protocol (BGP) routes discovered by IPAM resource discovery for a specified Region. Use this operation to view the Bring Your Own IP (BYOIP) address ranges that are currently advertised through BGP. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, + "GetIpamInternetRegistryAssociationAsns":{ + "name":"GetIpamInternetRegistryAssociationAsns", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamInternetRegistryAssociationAsnsRequest"}, + "output":{"shape":"GetIpamInternetRegistryAssociationAsnsResult"}, + "documentation":"

    Retrieves Autonomous System Numbers (ASNs) registered with an internet registry for an IPAM internet registry association. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, + "GetIpamInternetRegistryAssociationCidrs":{ + "name":"GetIpamInternetRegistryAssociationCidrs", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamInternetRegistryAssociationCidrsRequest"}, + "output":{"shape":"GetIpamInternetRegistryAssociationCidrsResult"}, + "documentation":"

    Retrieves IP address CIDRs registered with an internet registry for an IPAM internet registry association. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, "GetIpamPolicyAllocationRules":{ "name":"GetIpamPolicyAllocationRules", "http":{ @@ -5681,6 +5911,46 @@ "output":{"shape":"GetIpamResourceCidrsResult"}, "documentation":"

    Returns resource CIDRs managed by IPAM in a given scope. If an IPAM is associated with more than one resource discovery, the resource CIDRs across all of the resource discoveries is returned. A resource discovery is an IPAM component that enables IPAM to manage and monitor resources that belong to the owning account.

    " }, + "GetIpamRouteOriginAuthorizations":{ + "name":"GetIpamRouteOriginAuthorizations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamRouteOriginAuthorizationsRequest"}, + "output":{"shape":"GetIpamRouteOriginAuthorizationsResult"}, + "documentation":"

    Retrieves the current Route Origin Authorizations (ROAs) published to the RPKI for an IPAM internet registry association. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, + "GetIpamRouteProtectionFindings":{ + "name":"GetIpamRouteProtectionFindings", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamRouteProtectionFindingsRequest"}, + "output":{"shape":"GetIpamRouteProtectionFindingsResult"}, + "documentation":"

    Retrieves route protection findings for an IPAM. Route protection findings show the Resource Public Key Infrastructure (RPKI) validation status of your Bring Your Own IP (BYOIP) routes. Findings identify routes that have valid, invalid, or unknown validation states. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, + "GetIpamRoutingPolicyRegistrationDeltas":{ + "name":"GetIpamRoutingPolicyRegistrationDeltas", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamRoutingPolicyRegistrationDeltasRequest"}, + "output":{"shape":"GetIpamRoutingPolicyRegistrationDeltasResult"}, + "documentation":"

    Retrieves the history of routing policy registration changes for an IPAM internet registry association. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, + "GetIpamRoutingPolicyRegistrations":{ + "name":"GetIpamRoutingPolicyRegistrations", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetIpamRoutingPolicyRegistrationsRequest"}, + "output":{"shape":"GetIpamRoutingPolicyRegistrationsResult"}, + "documentation":"

    Retrieves routing policy registrations for an IPAM internet registry association. Each registration represents a Route Origin Authorization (ROA) that has been created or is pending publication to the RPKI. We recommend using pagination to ensure that the operation returns quickly and successfully.

    " + }, "GetLaunchTemplateData":{ "name":"GetLaunchTemplateData", "http":{ @@ -6111,6 +6381,16 @@ "output":{"shape":"ModifyAddressAttributeResult"}, "documentation":"

    Modifies an attribute of the specified Elastic IP address. For requirements, see Using reverse DNS for email applications.

    " }, + "ModifyApplicationStatusCheck":{ + "name":"ModifyApplicationStatusCheck", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ModifyApplicationStatusCheckRequest"}, + "output":{"shape":"ModifyApplicationStatusCheckResult"}, + "documentation":"

    Modifies an existing application status check. You can update the protocol, port, path, thresholds, and other configuration settings. The following rules apply:

    • The application status check must exist and belong to your account.

    • Changes take effect on the next health check interval.

    " + }, "ModifyAvailabilityZoneGroup":{ "name":"ModifyAvailabilityZoneGroup", "http":{ @@ -6129,7 +6409,7 @@ }, "input":{"shape":"ModifyCapacityReservationRequest"}, "output":{"shape":"ModifyCapacityReservationResult"}, - "documentation":"

    Modifies a Capacity Reservation's capacity, instance eligibility, and the conditions under which it is to be released. You can't modify a Capacity Reservation's instance type, EBS optimization, platform, instance store settings, Availability Zone, or tenancy. If you need to modify any of these attributes, we recommend that you cancel the Capacity Reservation, and then create a new one with the required attributes. For more information, see Modify an active Capacity Reservation.

    The allowed modifications depend on the state of the Capacity Reservation:

    • assessing or scheduled state - You can modify the tags only.

    • pending state - You can't modify the Capacity Reservation in any way.

    • active state but still within the commitment duration - You can't decrease the instance count or set an end date that is within the commitment duration. All other modifications are allowed.

    • active state with no commitment duration or elapsed commitment duration - All modifications are allowed.

    • expired, cancelled, unsupported, or failed state - You can't modify the Capacity Reservation in any way.

    " + "documentation":"

    Modifies a Capacity Reservation's capacity, instance eligibility, and the conditions under which it is to be released. You can't modify a Capacity Reservation's instance type, EBS optimization, platform, instance store settings, Availability Zone, or tenancy. If you need to modify any of these attributes, we recommend that you cancel the Capacity Reservation, and then create a new one with the required attributes. For more information, see Modify an active Capacity Reservation.

    The allowed modifications depend on the state of the Capacity Reservation:

    • assessing or scheduled state - You can modify the tags only.

    • pending state - You can't modify the Capacity Reservation in any way.

    • active state but still within the commitment duration - You can't decrease the instance count or set an end date that is within the commitment duration. All other modifications are allowed.

    • active state with no commitment duration or elapsed commitment duration - All modifications are allowed.

    • expired, cancelled, unsupported, or failed state - You can't modify the Capacity Reservation in any way.

    For a future-dated Capacity Reservation that has not yet been delivered, pushing out the start date requires a quote generated by CreateCapacityReservationDateChangeQuote. For more information, see Modify an active Capacity Reservation in the Amazon EC2 User Guide.

    " }, "ModifyCapacityReservationFleet":{ "name":"ModifyCapacityReservationFleet", @@ -6427,6 +6707,16 @@ "output":{"shape":"ModifyIpamResourceDiscoveryResult"}, "documentation":"

    Modifies a resource discovery. A resource discovery is an IPAM component that enables IPAM to manage and monitor resources that belong to the owning account.

    " }, + "ModifyIpamRoutingPolicyRegistration":{ + "name":"ModifyIpamRoutingPolicyRegistration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ModifyIpamRoutingPolicyRegistrationRequest"}, + "output":{"shape":"ModifyIpamRoutingPolicyRegistrationResult"}, + "documentation":"

    Modifies an existing routing policy registration. You can update the authorized ASNs, maximum prefix length, and other properties of a Route Origin Authorization (ROA).

    " + }, "ModifyIpamScope":{ "name":"ModifyIpamScope", "http":{ @@ -6624,6 +6914,16 @@ "output":{"shape":"ModifyTransitGatewayMeteringPolicyResult"}, "documentation":"

    Modifies a transit gateway metering policy.

    " }, + "ModifyTransitGatewayPolicyTableEntry":{ + "name":"ModifyTransitGatewayPolicyTableEntry", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ModifyTransitGatewayPolicyTableEntryRequest"}, + "output":{"shape":"ModifyTransitGatewayPolicyTableEntryResult"}, + "documentation":"

    Modifies the specified transit gateway policy table entry.

    " + }, "ModifyTransitGatewayPrefixListReference":{ "name":"ModifyTransitGatewayPrefixListReference", "http":{ @@ -6940,7 +7240,7 @@ }, "input":{"shape":"ProvisionByoipCidrRequest"}, "output":{"shape":"ProvisionByoipCidrResult"}, - "documentation":"

    Provisions an IPv4 or IPv6 address range for use with your Amazon Web Services resources through bring your own IP addresses (BYOIP) and creates a corresponding address pool. After the address range is provisioned, it is ready to be advertised.

    Amazon Web Services verifies that you own the address range and are authorized to advertise it. You must ensure that the address range is registered to you and that you created an RPKI ROA to authorize Amazon ASNs 16509 and 14618 to advertise the address range. For more information, see Bring your own IP addresses (BYOIP) in the Amazon EC2 User Guide.

    Provisioning an address range is an asynchronous operation, so the call returns immediately, but the address range is not ready to use until its status changes from pending-provision to provisioned. For more information, see Onboard your address range.

    " + "documentation":"

    Provisions an IPv4 or IPv6 address range for use with your Amazon Web Services resources through bring your own IP addresses (BYOIP) and creates a corresponding address pool. After the address range is provisioned, it is ready to be advertised.

    Amazon Web Services verifies that you own the address range and are authorized to advertise it. You must ensure that the address range is registered to you and that you created an RPKI ROA to authorize Amazon ASNs 16509 and 14618 to advertise the address range. For the Amazon Web Services GovCloud (US) Regions, authorize only ASN 8987. For the Amazon Web Services European Sovereign Cloud, authorize ASNs 16509 and 214101. For more information, see Bring your own IP addresses (BYOIP) in the Amazon EC2 User Guide.

    Provisioning an address range is an asynchronous operation, so the call returns immediately, but the address range is not ready to use until its status changes from pending-provision to provisioned. For more information, see Onboard your address range.

    " }, "ProvisionIpamByoasn":{ "name":"ProvisionIpamByoasn", @@ -7190,6 +7490,16 @@ "output":{"shape":"ReplaceImageCriteriaInAllowedImagesSettingsResult"}, "documentation":"

    Sets or replaces the criteria for Allowed AMIs.

    The ImageCriteria can include up to:

    • 10 ImageCriterion

    The Allowed AMIs feature does not restrict the AMIs owned by your account. Regardless of the criteria you set, the AMIs created by your account will always be discoverable and usable by users in your account.

    For more information, see Control the discovery and use of AMIs in Amazon EC2 with Allowed AMIs in Amazon EC2 User Guide.

    " }, + "ReplaceImageInstanceTypeSpecification":{ + "name":"ReplaceImageInstanceTypeSpecification", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ReplaceImageInstanceTypeSpecificationRequest"}, + "output":{"shape":"ReplaceImageInstanceTypeSpecificationResult"}, + "documentation":"

    Replaces or removes the instance type specification for an AMI. The instance type specification defines which instance types are compatible with the AMI.

    When you launch an instance using RunInstances, Amazon EC2 validates the requested instance type against the AMI's instance type specification. If the instance type is not compatible, the request fails with an InvalidParameterCombination error.

    You can specify supported instance types, unsupported instance types, or both. The evaluation logic is as follows:

    • No specification set – all instance types are allowed.

    • Only UnsupportedInstanceTypes set – All instance types are allowed except those that match the unsupported list.

    • SupportedInstanceTypes set – The instance type must match the supported list and must not match the unsupported list.

    Instance type entries support wildcard patterns using * (for example, t3.* matches all t3 sizes).

    To remove an existing instance type specification, omit the InstanceTypeSpecification parameter or set it to null.

    To set the instance type specification, you must be the AMI owner. You cannot set an instance type specification on an AMI that is listed in Amazon Web Services Marketplace, and you cannot list an AMI in Amazon Web Services Marketplace if it has an instance type specification set.

    " + }, "ReplaceNetworkAclAssociation":{ "name":"ReplaceNetworkAclAssociation", "http":{ @@ -7671,6 +7981,16 @@ "output":{"shape":"UpdateSecurityGroupRuleDescriptionsIngressResult"}, "documentation":"

    Updates the description of an ingress (inbound) security group rule. You can replace an existing description, or add a description to a rule that did not have one previously. You can remove a description for a security group rule by omitting the description parameter in the request.

    " }, + "ValidateSecurityGroupQuotasForInterface":{ + "name":"ValidateSecurityGroupQuotasForInterface", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ValidateSecurityGroupQuotasForInterfaceRequest"}, + "output":{"shape":"ValidateSecurityGroupQuotasForInterfaceResult"}, + "documentation":"

    Validates whether the specified security groups can be associated with a single network interface. The operation checks Amazon Virtual Private Cloud (Amazon VPC) quotas. It checks inbound or outbound rules per security group and security groups per network interface. Only authorized Amazon Web Services services can call this operation.

    For more information about security group quotas, see Amazon VPC quotas in the Amazon VPC User Guide.

    " + }, "WithdrawByoipCidr":{ "name":"WithdrawByoipCidr", "http":{ @@ -8761,6 +9081,13 @@ "host" ] }, + "AggregationStatusEnum":{ + "type":"string", + "enum":[ + "included", + "excluded" + ] + }, "AllocateAddressRequest":{ "type":"structure", "members":{ @@ -9402,6 +9729,313 @@ "disable" ] }, + "ApplicationStatus":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"ApplicationStatusEnum", + "documentation":"

    The current instance-level application status. This status is derived from application status checks with Aggregation set to included. Possible values:

    • ok – All included checks passed.

    • impaired – At least one included check failed.

    • initializing – At least one included check is initializing, and no included check is impaired.

    • insufficient-data – At least one included check has insufficient data, and no included check is impaired or initializing.

    • not-applicable – No checks with Aggregation set to included apply to the instance.

    • suppressed – Application status reporting is suppressed for the instance.

    Checks with Aggregation set to excluded do not affect this value.

    ", + "locationName":"status" + }, + "StatusTimeStamp":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time of the last status update.

    ", + "locationName":"statusTimeStamp" + }, + "StatusSince":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the current status started.

    ", + "locationName":"statusSince" + }, + "ResumeAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when application status reporting resumes after suppression.

    ", + "locationName":"resumeAt" + }, + "Details":{ + "shape":"ApplicationStatusDetailSet", + "documentation":"

    Details about the application status checks for the instance.

    ", + "locationName":"detailSet" + } + }, + "documentation":"

    Describes the application-level health status for an instance.

    " + }, + "ApplicationStatusCheckAssociationObject":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check.

    ", + "locationName":"applicationStatusCheckId" + }, + "AssociationType":{ + "shape":"AssociationTypeEnum", + "documentation":"

    The type of target that the application status check is associated with. Possible values:

    • tag – The check applies to current and future instances with a matching tag key-value pair.

    • instance-id – The check applies to a specific instance.

    ", + "locationName":"associationType" + }, + "Key":{ + "shape":"String", + "documentation":"

    The key for the association. This value is present only for tag-based associations, where it contains the tag key. For instance-based associations, this value is absent.

    ", + "locationName":"key" + }, + "Value":{ + "shape":"String", + "documentation":"

    The value for the association target. For tag-based associations, this is the tag value. For instance-based associations, this is the instance ID (for example, i-0123456789abcdef0).

    ", + "locationName":"value" + } + }, + "documentation":"

    Information about an application status check association. Each item in the associationSet of a DescribeApplicationStatusCheckAssociations response is of this type.

    " + }, + "ApplicationStatusCheckAssociationSet":{ + "type":"list", + "member":{ + "shape":"ApplicationStatusCheckAssociationObject", + "locationName":"item" + } + }, + "ApplicationStatusCheckEnum":{ + "type":"string", + "enum":[ + "passed", + "failed", + "initializing", + "insufficient-data", + "not-applicable" + ] + }, + "ApplicationStatusCheckId":{"type":"string"}, + "ApplicationStatusCheckIdList":{ + "type":"list", + "member":{ + "shape":"ApplicationStatusCheckId", + "locationName":"item" + } + }, + "ApplicationStatusCheckResponseObject":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check.

    ", + "locationName":"applicationStatusCheckId" + }, + "Aggregation":{ + "shape":"AggregationStatusEnum", + "documentation":"

    The aggregation setting for the application status check. When set to included, the result of this check contributes to the instance-level application status. When set to excluded, the check runs independently and does not affect the instance-level status.

    ", + "locationName":"aggregation" + }, + "HealthCheckPaths":{ + "shape":"HealthCheckPathResponseList", + "documentation":"

    The health check paths for the application status check.

    ", + "locationName":"healthCheckPathSet" + }, + "Protocol":{ + "shape":"NetworkProtocolEnum", + "documentation":"

    The protocol used for the health check.

    ", + "locationName":"protocol" + }, + "Port":{ + "shape":"Integer", + "documentation":"

    The port used for the health check.

    ", + "locationName":"port" + }, + "Path":{ + "shape":"String", + "documentation":"

    The URL path used for the health check HTTP request.

    ", + "locationName":"path" + }, + "DeviceIndex":{ + "shape":"Integer", + "documentation":"

    The index of the network device used for the health check. The value is greater than or equal to 0.

    ", + "locationName":"deviceIndex" + }, + "IpVersion":{ + "shape":"IpVersionEnum", + "documentation":"

    The IP version used for the health check.

    ", + "locationName":"ipVersion" + }, + "IpScope":{ + "shape":"IpScopeEnum", + "documentation":"

    The IP scope used for the health check.

    ", + "locationName":"ipScope" + }, + "Interval":{ + "shape":"Integer", + "documentation":"

    The interval, in seconds, between health checks. Valid value: 60.

    ", + "locationName":"interval" + }, + "Timeout":{ + "shape":"Integer", + "documentation":"

    The amount of time, in seconds, to wait for a health check response. Valid values: 1 to 30.

    ", + "locationName":"timeout" + }, + "FailureThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive failed health checks before the application status is considered impaired. The value must be greater than 0.

    ", + "locationName":"failureThreshold" + }, + "SuccessThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive successful health checks before the application status is considered healthy. The value must be greater than 0.

    ", + "locationName":"successThreshold" + }, + "StatusCodeMatcher":{ + "shape":"String", + "documentation":"

    The comma-separated list of individual HTTP status codes or ranges that indicate a successful health check response.

    ", + "locationName":"statusCodeMatcher" + }, + "InitializationGracePeriodSeconds":{ + "shape":"InitializationGracePeriodSeconds", + "documentation":"

    The number of seconds to wait before starting health checks after an instance is launched. Valid values: 1 to 600.

    ", + "locationName":"initializationGracePeriodSeconds" + }, + "LastUpdatedAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the application status check was last updated.

    ", + "locationName":"lastUpdatedAt" + }, + "TargetTagAssociations":{ + "shape":"CustomKeyValuePairResponseSet", + "documentation":"

    The tags associated with the application status check. Instances with these tags are automatically monitored by this check.

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

    The tags assigned to the application status check.

    ", + "locationName":"tagSet" + }, + "CreationTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the application status check was created.

    ", + "locationName":"creationTime" + }, + "ModifyTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the application status check was last modified.

    ", + "locationName":"modifyTime" + }, + "DeletionTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the application status check was deleted.

    ", + "locationName":"deletionTime" + } + }, + "documentation":"

    Describes an application status check.

    " + }, + "ApplicationStatusCheckResponseSet":{ + "type":"list", + "member":{ + "shape":"ApplicationStatusCheckResponseObject", + "locationName":"item" + } + }, + "ApplicationStatusDetail":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check.

    ", + "locationName":"applicationStatusCheckId" + }, + "CheckUpdateTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the check was last updated.

    ", + "locationName":"checkUpdateTime" + }, + "Aggregation":{ + "shape":"AggregationStatusEnum", + "documentation":"

    The aggregation setting for the application status check. When set to included, the result of this check contributes to the instance-level application status. When set to excluded, the check runs independently and does not affect the instance-level status.

    ", + "locationName":"aggregation" + }, + "Status":{ + "shape":"ApplicationStatusCheckEnum", + "documentation":"

    The status of the individual application status check. Possible values:

    • passed – The check reached its success threshold.

    • failed – The check reached its failure threshold.

    • initializing – The check is initializing or has not reached a success or failure threshold.

    • insufficient-data – The check does not have enough data to determine a result.

    • not-applicable – The check does not apply to the instance.

    This value reflects the check result and is not affected by aggregation or suppression.

    ", + "locationName":"status" + }, + "StatusTimeStamp":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time of the last status update for this check.

    ", + "locationName":"statusTimeStamp" + }, + "StatusSince":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the current status started for this check.

    ", + "locationName":"statusSince" + }, + "Reason":{ + "shape":"ApplicationStatusReason", + "documentation":"

    The reason for the current status.

    ", + "locationName":"reason" + } + }, + "documentation":"

    Describes the details of an application status check for an instance.

    " + }, + "ApplicationStatusDetailSet":{ + "type":"list", + "member":{ + "shape":"ApplicationStatusDetail", + "locationName":"item" + } + }, + "ApplicationStatusEnum":{ + "type":"string", + "enum":[ + "ok", + "impaired", + "initializing", + "insufficient-data", + "not-applicable", + "suppressed" + ] + }, + "ApplicationStatusReason":{ + "type":"structure", + "members":{ + "Code":{ + "shape":"String", + "documentation":"

    The reason code for the application status check result. Possible values:

    • ResponseCodeMatched – The HTTP status code returned by the health check matched the configured StatusCodeMatcher.

    • ResponseCodeMismatch – The HTTP status code returned by the health check did not match the configured StatusCodeMatcher.

    • ConnectionTimeout – The connection to the target timed out.

    • ResponseTimeout – The health check timed out while waiting for a response from the target.

    • ConnectionRefused – The target refused the health check connection.

    • ConnectionReset – The target reset the health check connection before returning a response.

    Current health check results use the values in the preceding list. Legacy results that do not contain structured reason metadata can instead contain a producer error type, such as Http Status Code or HttpConnectTimeoutException.

    For ResponseCodeMatched and ResponseCodeMismatch, the statusCode field contains the returned HTTP status code. The protocol field contains the protocol used for the health check.

    ", + "locationName":"code" + }, + "StatusCode":{ + "shape":"Integer", + "documentation":"

    The HTTP status code returned by the health check.

    ", + "locationName":"statusCode" + }, + "Protocol":{ + "shape":"String", + "documentation":"

    The protocol used for the health check. Possible values: HTTP and HTTPS.

    ", + "locationName":"protocol" + } + }, + "documentation":"

    Describes the reason for an application status check result.

    " + }, + "ApplicationStatusSummary":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"SummaryStatus", + "documentation":"

    The current status.

    ", + "locationName":"status" + }, + "ImpairedSince":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when the application status became impaired.

    ", + "locationName":"impairedSince" + } + }, + "documentation":"

    Provides a summary of the application-level health status for an instance.

    " + }, + "ApplicationStatusesResponseType":{ + "type":"structure", + "members":{ + "Instances":{ + "shape":"InstanceApplicationStatusSet", + "documentation":"

    The application status information for the instances.

    ", + "locationName":"instanceSet" + } + }, + "documentation":"

    Describes the application statuses for instances.

    " + }, "ApplyCancellationCharges":{ "type":"string", "enum":["commitment-wind-down"] @@ -9555,6 +10189,13 @@ }, "documentation":"

    Provides authorization for Amazon to bring an Autonomous System Number (ASN) to a specific Amazon Web Services account using bring your own ASN (BYOASN). For details on the format of the message and signature, see Tutorial: Bring your ASN to IPAM in the Amazon VPC IPAM guide.

    " }, + "AsnList":{ + "type":"list", + "member":{ + "shape":"String", + "locationName":"item" + } + }, "AsnState":{ "type":"string", "enum":[ @@ -9780,6 +10421,50 @@ } } }, + "AssociateApplicationStatusCheckRequest":{ + "type":"structure", + "required":["ApplicationStatusCheckId"], + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check to associate.

    " + }, + "TargetTagAssociations":{ + "shape":"CustomKeyValuePairRequestSet", + "documentation":"

    The tags to associate the application status check with. Each tag is a key-value pair. When you associate tags, the application status check automatically monitors all instances that have the specified tags.

    ", + "locationName":"TargetTagAssociation" + }, + "InstanceIds":{ + "shape":"InstanceIdList", + "documentation":"

    The IDs of the instances to associate with the application status check.

    ", + "locationName":"InstanceId" + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "AssociateApplicationStatusCheckResult":{ + "type":"structure", + "members":{ + "SuccessfulResults":{ + "shape":"SuccessfulAssociationResponseSet", + "documentation":"

    The associations that were successfully created.

    ", + "locationName":"successfulResultSet" + }, + "UnsuccessfulResults":{ + "shape":"UnsuccessfulAssociationResponseSet", + "documentation":"

    The associations that failed to be created.

    ", + "locationName":"unsuccessfulResultSet" + } + } + }, "AssociateCapacityReservationBillingOwnerRequest":{ "type":"structure", "required":[ @@ -10560,6 +11245,13 @@ "disassociated" ] }, + "AssociationTypeEnum":{ + "type":"string", + "enum":[ + "tag", + "instance-id" + ] + }, "AthenaIntegration":{ "type":"structure", "required":[ @@ -11528,6 +12220,46 @@ "documentation":"

    The baseline performance to consider, using an instance family as a baseline reference. The instance family establishes the lowest acceptable level of performance. Amazon EC2 uses this baseline to guide instance type selection, but there is no guarantee that the selected instance types will always exceed the baseline for every application.

    Currently, this parameter only supports CPU performance as a baseline performance factor. For example, specifying c6i would use the CPU performance of the c6i family as the baseline reference.

    " }, "BaselineThroughputInMBps":{"type":"double"}, + "BatchModifyIpamRoutingPolicyRegistrationsRequest":{ + "type":"structure", + "required":[ + "IpamInternetRegistryAssociationId", + "DeltaJson" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "DeltaJson":{ + "shape":"String", + "documentation":"

    The batch modifications to apply, in JSON format.

    " + }, + "Force":{ + "shape":"BoxedBoolean", + "documentation":"

    Forces the batch modification even if individual changes conflict with announced routes. Default: false.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "BatchModifyIpamRoutingPolicyRegistrationsResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrationDelta":{ + "shape":"IpamRoutingPolicyRegistrationDelta", + "documentation":"

    Information about the routing policy registration delta created by this batch operation.

    ", + "locationName":"ipamRoutingPolicyRegistrationDelta" + } + } + }, "BatchState":{ "type":"string", "enum":[ @@ -11657,6 +12389,10 @@ "documentation":"

    The state of VPC Block Public Access (BPA).

    " }, "Boolean":{"type":"boolean"}, + "BootModeOverrideValues":{ + "type":"string", + "enum":["uefi"] + }, "BootModeType":{ "type":"string", "enum":[ @@ -11885,6 +12621,16 @@ "shape":"String", "documentation":"

    Specifies the advertisement method for the BYOIP CIDR. Valid values are:

    • unicast: IP is advertised from a single location (regional services like EC2)

    • anycast: IP is advertised from multiple global locations simultaneously (global services like CloudFront)

    For more information, see Bring your own IP to CloudFront using IPAM in the Amazon VPC IPAM User Guide.

    ", "locationName":"advertisementType" + }, + "PoolId":{ + "shape":"String", + "documentation":"

    The ID of the address pool associated with the CIDR.

    ", + "locationName":"poolId" + }, + "IpamPoolId":{ + "shape":"IpamPoolId", + "documentation":"

    The ID of the IPAM pool associated with the CIDR.

    ", + "locationName":"ipamPoolId" } }, "documentation":"

    Information about an address range that is provisioned for use with your Amazon Web Services resources through bring your own IP addresses (BYOIP).

    " @@ -13258,10 +14004,69 @@ "shape":"InterruptionInfo", "documentation":"

    Information about the interruption configuration and association with the source reservation for interruptible Capacity Reservations.

    ", "locationName":"interruptionInfo" + }, + "AdjustmentStatus":{ + "shape":"CapacityReservationAdjustmentStatus", + "documentation":"

    The status of the most recent modification to the Capacity Reservation. A Capacity Reservation can have one of the following adjustment statuses:

    • requested - The modification was requested and is being processed.

    • applied - The modification was applied to the Capacity Reservation.

    • rejected - The modification was not applied and the Capacity Reservation keeps its existing configuration.

    This field is not returned if the Capacity Reservation has never been modified.

    ", + "locationName":"adjustmentStatus" + }, + "AdjustmentDetails":{ + "shape":"CapacityReservationAdjustmentDetails", + "documentation":"

    The configuration that the Capacity Reservation will have after the requested adjustment is applied.

    ", + "locationName":"adjustmentDetails" + }, + "OriginalStartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start date that you originally requested for the Capacity Reservation, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ). This value doesn't change when you push out the start date.

    ", + "locationName":"originalStartDate" + }, + "ZeroSizePreference":{ + "shape":"ZeroSizePreference", + "documentation":"

    The zero-size preference configured for the interruptible Capacity Reservation. A value of retain keeps the interruptible Capacity Reservation active at zero capacity when you reduce its allocation to zero. A value of default cancels the interruptible Capacity Reservation when you reduce its allocation to zero.

    ", + "locationName":"zeroSizePreference" } }, "documentation":"

    Describes a Capacity Reservation.

    " }, + "CapacityReservationAdjustmentDetails":{ + "type":"structure", + "members":{ + "StartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start date that the Capacity Reservation will have after the adjustment.

    ", + "locationName":"startDate" + }, + "EndDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The end date that the Capacity Reservation will have after the adjustment.

    ", + "locationName":"endDate" + }, + "CommitmentEndDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time at which the commitment duration will expire after the adjustment.

    ", + "locationName":"commitmentEndDate" + }, + "EndDateType":{ + "shape":"String", + "documentation":"

    Indicates the way in which the Capacity Reservation will end after the adjustment. Possible values are:

    • unlimited - The Capacity Reservation remains active until you explicitly cancel it.

    • limited - The Capacity Reservation expires automatically at the date and time given by endDate.

    ", + "locationName":"endDateType" + }, + "CommitmentDuration":{ + "shape":"BoxedLong", + "documentation":"

    The commitment duration, in seconds, that the Capacity Reservation will have after the adjustment.

    ", + "locationName":"commitmentDuration" + } + }, + "documentation":"

    Describes the configuration that a Capacity Reservation will have after a pending adjustment is applied.

    " + }, + "CapacityReservationAdjustmentStatus":{ + "type":"string", + "enum":[ + "requested", + "applied", + "rejected" + ] + }, "CapacityReservationBillingRequest":{ "type":"structure", "members":{ @@ -13407,6 +14212,11 @@ "shape":"MillisecondDateTime", "documentation":"

    The date and time at which the commitment duration expires, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ). You can't decrease the instance count or cancel the Capacity Reservation before this date and time.

    ", "locationName":"commitmentEndDate" + }, + "CommitmentDuration":{ + "shape":"BoxedLong", + "documentation":"

    The commitment duration, in seconds, for the future-dated Capacity Reservation. This is the minimum duration for which you commit to having the Capacity Reservation in the active state in your account after it has been delivered.

    ", + "locationName":"commitmentDuration" } }, "documentation":"

    Information about your commitment for a future-dated Capacity Reservation.

    " @@ -13637,6 +14447,76 @@ "Ubuntu Pro" ] }, + "CapacityReservationModificationQuote":{ + "type":"structure", + "members":{ + "CapacityReservationModificationQuoteId":{ + "shape":"CapacityReservationModificationQuoteId", + "documentation":"

    The ID of the modification quote.

    ", + "locationName":"capacityReservationModificationQuoteId" + }, + "CapacityReservationId":{ + "shape":"CapacityReservationId", + "documentation":"

    The ID of the Capacity Reservation associated with the modification quote.

    ", + "locationName":"capacityReservationId" + }, + "CreateTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time at which the modification quote was created.

    ", + "locationName":"createTime" + }, + "ExpirationTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time at which the modification quote expires.

    ", + "locationName":"expirationTime" + }, + "QuoteState":{ + "shape":"CapacityReservationModificationQuoteState", + "documentation":"

    The state of the modification quote itself. Possible values are:

    • active - The quote can still be used.

    • expired - The quote can no longer be used. A quote becomes expired at its expirationTime.

    ", + "locationName":"quoteState" + }, + "CurrentConfiguration":{ + "shape":"ModificationQuoteCurrentConfiguration", + "documentation":"

    The configuration that the Capacity Reservation has at the time the quote was generated.

    ", + "locationName":"currentConfiguration" + }, + "ModificationTerms":{ + "shape":"ModificationTerms", + "documentation":"

    The terms of the modification, including the configuration that the Capacity Reservation will have if you accept them by using ModifyCapacityReservation.

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

    The tags assigned to the modification quote.

    ", + "locationName":"tagSet" + } + }, + "documentation":"

    Describes a Capacity Reservation modification quote, which provides the terms for changing the start date or the commitment of a future-dated Capacity Reservation.

    " + }, + "CapacityReservationModificationQuoteId":{"type":"string"}, + "CapacityReservationModificationQuoteIdSet":{ + "type":"list", + "member":{ + "shape":"CapacityReservationModificationQuoteId", + "locationName":"item" + }, + "max":1000, + "min":0 + }, + "CapacityReservationModificationQuoteResponseSet":{ + "type":"list", + "member":{ + "shape":"CapacityReservationModificationQuote", + "locationName":"item" + } + }, + "CapacityReservationModificationQuoteState":{ + "type":"string", + "enum":[ + "active", + "expired" + ] + }, "CapacityReservationOptions":{ "type":"structure", "members":{ @@ -13666,6 +14546,13 @@ "none" ] }, + "CapacityReservationResourceGroupArnSet":{ + "type":"list", + "member":{ + "shape":"ResourceGroupName", + "locationName":"item" + } + }, "CapacityReservationSet":{ "type":"list", "member":{ @@ -13938,6 +14825,14 @@ "documentation":"

    Information about the client certificate to be used for authentication.

    " }, "CertificateId":{"type":"string"}, + "ChronologicalOrder":{ + "type":"string", + "documentation":"

    The chronological order for returning results.

    ", + "enum":[ + "forward", + "reverse" + ] + }, "CidrAuthorizationContext":{ "type":"structure", "required":[ @@ -15465,6 +16360,14 @@ "shape":"String", "documentation":"

    Unique, case-sensitive identifier that you provide to ensure the idempotency of the request. For more information, see Ensure Idempotency.

    ", "idempotencyToken":true + }, + "Encrypted":{ + "shape":"Boolean", + "documentation":"

    Indicates whether to encrypt the volume copy. If the source volume is encrypted, the service always encrypts the copy regardless of this value. Set to true to encrypt a copy of an unencrypted source volume during the copy operation. If you set Encrypted to true but do not specify KmsKeyId, the service uses the default KMS key for EBS encryption in your account.

    " + }, + "KmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The identifier of the KMS key to use for encryption of the volume copy. Specify a symmetric encryption KMS key. You can specify a KMS key using the key ID, key ARN, alias name, or alias ARN. If you set Encrypted to true but do not specify this parameter, the service uses the default KMS key for EBS encryption in your account. For cross-account volume copies, this must be a KMS key in the calling account.

    " } } }, @@ -15574,6 +16477,96 @@ }, "documentation":"

    The CPU performance to consider, using an instance family as the baseline reference.

    " }, + "CreateApplicationStatusCheckRequest":{ + "type":"structure", + "required":[ + "Protocol", + "Port" + ], + "members":{ + "HealthCheckPaths":{ + "shape":"HealthCheckPathRequestList", + "documentation":"

    The health check paths to use for the application status check. Health check paths define the network path from a source subnet to one or more destination subnets for cross-Availability Zone or Availability Zone to Local Zone health checking. If omitted, health checks are performed in the same subnet as the instance.

    ", + "locationName":"HealthCheckPath" + }, + "Aggregation":{ + "shape":"AggregationStatusEnum", + "documentation":"

    The aggregation setting for the application status check. When set to included, the result of this check contributes to the instance-level application status reported by DescribeApplicationStatus. When set to excluded, the check runs independently and does not affect the instance-level status. Valid values: included | excluded.

    " + }, + "Protocol":{ + "shape":"NetworkProtocolEnum", + "documentation":"

    The protocol to use for the health check. Valid values: http | https.

    " + }, + "Port":{ + "shape":"PortNumber", + "documentation":"

    The port to use for the health check. Valid values: 1 to 65535.

    " + }, + "Path":{ + "shape":"String", + "documentation":"

    The URL path to use for the health check HTTP request (for example, /health or /status).

    " + }, + "DeviceIndex":{ + "shape":"Integer", + "documentation":"

    The index of the network device to use for the health check. The value must be greater than or equal to 0.

    " + }, + "IpVersion":{ + "shape":"IpVersionEnum", + "documentation":"

    The IP version to use for the health check. Valid values: ipv4 and ipv6.

    " + }, + "IpScope":{ + "shape":"IpScopeEnum", + "documentation":"

    The IP scope to use for the health check. Valid value: private.

    " + }, + "Interval":{ + "shape":"Integer", + "documentation":"

    The interval, in seconds, between health checks. Valid value: 60.

    " + }, + "Timeout":{ + "shape":"Integer", + "documentation":"

    The amount of time, in seconds, to wait for a health check response before considering it failed. Valid values: 1 to 30. The value must be less than Interval.

    " + }, + "FailureThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive failed health checks before the application status is considered impaired. The value must be greater than 0.

    " + }, + "SuccessThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive successful health checks before the application status is considered healthy. The value must be greater than 0.

    " + }, + "StatusCodeMatcher":{ + "shape":"String", + "documentation":"

    The HTTP status codes that indicate a successful health check response. Specify a comma-separated list of individual status codes or ranges, for example, 200,202,300-399. For a range, the first value must be less than the second value. Maximum length: 64 characters. Default: 200.

    " + }, + "InitializationGracePeriodSeconds":{ + "shape":"InitializationGracePeriodSeconds", + "documentation":"

    The number of seconds to wait before starting health checks after an instance is launched. Valid values: 1 to 600.

    " + }, + "TagSpecifications":{ + "shape":"TagSpecificationList", + "documentation":"

    The tags to apply to the application status check.

    ", + "locationName":"TagSpecification" + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "CreateApplicationStatusCheckResult":{ + "type":"structure", + "members":{ + "ApplicationStatusCheck":{ + "shape":"ApplicationStatusCheckResponseObject", + "documentation":"

    Information about the application status check.

    ", + "locationName":"applicationStatusCheck" + } + } + }, "CreateCapacityManagerDataExportRequest":{ "type":"structure", "required":[ @@ -15709,6 +16702,47 @@ } } }, + "CreateCapacityReservationDateChangeQuoteRequest":{ + "type":"structure", + "required":[ + "CapacityReservationId", + "NewStartDate" + ], + "members":{ + "CapacityReservationId":{ + "shape":"CapacityReservationId", + "documentation":"

    The ID of the Capacity Reservation.

    " + }, + "NewStartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The requested new start date for the Capacity Reservation, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ). The new start date must be later than the current start date and within the cumulative 30-day pushout limit.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    Unique, case-sensitive identifier that you provide to ensure the idempotency of the request. For more information, see Ensure Idempotency.

    ", + "idempotencyToken":true + }, + "TagSpecifications":{ + "shape":"TagSpecificationList", + "documentation":"

    The tags to apply to the date change quote.

    ", + "locationName":"TagSpecification" + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "CreateCapacityReservationDateChangeQuoteResult":{ + "type":"structure", + "members":{ + "CapacityReservationModificationQuote":{ + "shape":"CapacityReservationModificationQuote", + "documentation":"

    Information about the Capacity Reservation date change quote.

    ", + "locationName":"capacityReservationModificationQuote" + } + } + }, "CreateCapacityReservationFleetRequest":{ "type":"structure", "required":["TotalTargetCapacity"], @@ -16400,7 +17434,7 @@ }, "Lifecycle":{ "shape":"InstanceLifecycle", - "documentation":"

    Indicates if the instance that could not be launched was a Spot, On-Demand, Capacity Block, or Interruptible Capacity Reservation instance.

    ", + "documentation":"

    Indicates if the instance that could not be launched was a Spot, On-Demand, Capacity Block for ML, or interruptible Capacity Reservation instance. If you are using ReservedCapacityOptions with on-demand-capacity-reservation in the ReservationTypes list, the value can also be on-demand-capacity-reservation.

    ", "locationName":"lifecycle" }, "ErrorCode":{ @@ -16433,7 +17467,7 @@ }, "Lifecycle":{ "shape":"InstanceLifecycle", - "documentation":"

    Indicates if the instance that was launched is a Spot, On-Demand, Capacity Block, or Interruptible Capacity Reservation instance.

    ", + "documentation":"

    Indicates if the instance that was launched is a Spot, On-Demand, Capacity Block for ML, or interruptible Capacity Reservation instance.

    ", "locationName":"lifecycle" }, "InstanceIds":{ @@ -16596,7 +17630,7 @@ }, "ResourceIds":{ "shape":"FlowLogResourceIds", - "documentation":"

    The IDs of the resources to monitor. For example, if the resource type is VPC, specify the IDs of the VPCs.

    Constraints: Maximum of 25 for transit gateway resource types. Maximum of 1000 for the other resource types.

    ", + "documentation":"

    The IDs of the resources to monitor. For example, if the resource type is VPC, specify the IDs of the VPCs.

    Constraints: Maximum of 25 for transit gateway resource types. Maximum of 300 for the other resource types.

    ", "locationName":"ResourceId" }, "ResourceType":{ @@ -16723,7 +17757,11 @@ }, "SnapshotLocation":{ "shape":"SnapshotLocationEnum", - "documentation":"

    Only supported for instances in Local Zones. If the source instance is not in a Local Zone, omit this parameter.

    The Amazon S3 location where the snapshots will be stored.

    • To create local snapshots in the same Local Zone as the source instance, specify local.

    • To create regional snapshots in the parent Region of the Local Zone, specify regional or omit this parameter.

    Default: regional

    " + "documentation":"

    Only supported for instances in Local Zones and for instances on Outposts that support local snapshots. If the source instance is not in one of these locations, omit this parameter.

    The Amazon S3 location where the snapshots will be stored.

    • To create local snapshots in the same Local Zone or on the same Outpost as the source instance, specify local.

    • To create regional snapshots in the parent Region of the Local Zone or Outpost, specify regional.

    If the source instance is in a Local Zone and you omit this parameter, regional snapshots are created in the parent Region of the Local Zone.

    If the source instance is on an Outpost that supports local snapshots, this parameter is required. If you omit it, the request fails with an InvalidParameterValue error.

    Default: regional (for instances in Local Zones only)

    " + }, + "BootModeOverride":{ + "shape":"BootModeOverrideValues", + "documentation":"

    The boot mode of the new image, which overrides the default boot mode. By default, if you do not specify this parameter, the new image inherits the boot-mode from the source instance.

    A value of uefi indicates that the image only supports UEFI boot mode. You can specify this parameter only if the current-instance-boot-mode of the source instance is uefi. To find the boot-mode or current-instance-boot-mode of an instance, see DescribeInstances.

    The operating system contained in the AMI must be configured to support the specified boot mode.

    For more information, see Instance launch behavior with Amazon EC2 boot modes in the Amazon EC2 User Guide.

    " }, "DryRun":{ "shape":"Boolean", @@ -17006,6 +18044,10 @@ "shape":"TagSpecificationList", "documentation":"

    The tags to apply to the interruptible Capacity Reservation during creation.

    ", "locationName":"TagSpecification" + }, + "ZeroSizePreference":{ + "shape":"ZeroSizePreference", + "documentation":"

    Specifies the behavior for the interruptible Capacity Reservation when you reduce its allocation to zero instances. Specify retain to keep the interruptible Capacity Reservation active at zero capacity so that you can allocate instances to it again later. Specify default to cancel the interruptible Capacity Reservation and return the capacity to your source Capacity Reservation. The default value is default.

    " } } }, @@ -17068,6 +18110,56 @@ } } }, + "CreateIpamInternetRegistryAssociationRequest":{ + "type":"structure", + "required":[ + "IpamId", + "Rir", + "OrganizationHandle" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamId":{ + "shape":"IpamId", + "documentation":"

    The ID of the IPAM to associate with the internet registry.

    " + }, + "Rir":{ + "shape":"Rir", + "documentation":"

    The Regional Internet Registry to associate with. Possible values:

    • ripe - RIPE NCC (Europe, the Middle East, and Central Asia).

    • apnic - APNIC (Asia Pacific).

    • arin - ARIN (North America).

    • lacnic - LACNIC (Latin America and the Caribbean).

    " + }, + "OrganizationHandle":{ + "shape":"String", + "documentation":"

    The organization handle at the internet registry (for example, a RIPE NCC organization ID or ARIN Org ID).

    " + }, + "Description":{ + "shape":"String", + "documentation":"

    A description for the internet registry association.

    " + }, + "TagSpecifications":{ + "shape":"TagSpecificationList", + "documentation":"

    The tags to assign to the internet registry association.

    ", + "locationName":"TagSpecification" + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "CreateIpamInternetRegistryAssociationResult":{ + "type":"structure", + "members":{ + "IpamInternetRegistryAssociation":{ + "shape":"IpamInternetRegistryAssociation", + "documentation":"

    Information about the internet registry association.

    ", + "locationName":"ipamInternetRegistryAssociation" + } + } + }, "CreateIpamPolicyRequest":{ "type":"structure", "required":["IpamId"], @@ -17385,6 +18477,64 @@ } } }, + "CreateIpamRoutingPolicyRegistrationRequest":{ + "type":"structure", + "required":[ + "IpamInternetRegistryAssociationId", + "Cidr", + "Asns" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation to authorize in the ROA.

    " + }, + "Asns":{ + "shape":"AsnList", + "documentation":"

    The Autonomous System Numbers (ASNs) authorized to originate the prefix.

    ", + "locationName":"Asn" + }, + "PermitMoreSpecificAnnouncements":{ + "shape":"BoxedBoolean", + "documentation":"

    Specifies whether to permit more specific route announcements than the CIDR prefix. When enabled, ASNs can announce sub-prefixes of the authorized CIDR up to the specified maximum length. Default: false.

    " + }, + "MaxLength":{ + "shape":"IpamRoutingPolicyRegistrationMaxLength", + "documentation":"

    The maximum prefix length that the ASNs are authorized to announce. Must be greater than or equal to the prefix length of the CIDR. If not specified, defaults to the prefix length of the CIDR (exact match only).

    " + }, + "Description":{ + "shape":"String", + "documentation":"

    A description for the routing policy registration.

    " + }, + "Force":{ + "shape":"BoxedBoolean", + "documentation":"

    Forces the creation of the routing policy registration even if it conflicts with an announced route. Default: false.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "CreateIpamRoutingPolicyRegistrationResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrationDelta":{ + "shape":"IpamRoutingPolicyRegistrationDelta", + "documentation":"

    Information about the routing policy registration delta created by this operation.

    ", + "locationName":"ipamRoutingPolicyRegistrationDelta" + } + } + }, "CreateIpamScopeRequest":{ "type":"structure", "required":["IpamId"], @@ -19816,6 +20966,46 @@ } } }, + "CreateTransitGatewayPolicyTableEntryRequest":{ + "type":"structure", + "required":[ + "TransitGatewayPolicyTableId", + "PolicyRuleNumber", + "TargetRouteTableId" + ], + "members":{ + "TransitGatewayPolicyTableId":{ + "shape":"TransitGatewayPolicyTableId", + "documentation":"

    The ID of the transit gateway policy table.

    " + }, + "PolicyRuleNumber":{ + "shape":"String", + "documentation":"

    The rule number for the policy table entry. Lower rule numbers are evaluated first and take precedence.

    " + }, + "PolicyRule":{ + "shape":"TransitGatewayRequestPolicyRule", + "documentation":"

    The matching criteria for the policy table entry.

    " + }, + "TargetRouteTableId":{ + "shape":"TransitGatewayRouteTableId", + "documentation":"

    The ID of the transit gateway route table to use for traffic matching this rule.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "CreateTransitGatewayPolicyTableEntryResult":{ + "type":"structure", + "members":{ + "TransitGatewayPolicyTableEntry":{ + "shape":"TransitGatewayPolicyTableEntry", + "documentation":"

    Describes a transit gateway policy table entry

    ", + "locationName":"transitGatewayPolicyTableEntry" + } + } + }, "CreateTransitGatewayPolicyTableRequest":{ "type":"structure", "required":["TransitGatewayId"], @@ -20065,7 +21255,7 @@ }, "Ipv6Support":{ "shape":"Ipv6SupportValue", - "documentation":"

    Enable or disable IPv6 support. The default is disable.

    " + "documentation":"

    Specifies whether IPv6 support is enabled for the attachment. When enabled, the transit gateway network interface receives an IPv6 address. When you enable route propagation, IPv6 VPC CIDRs propagate to the transit gateway route tables. When disabled, the network interface does not receive an IPv6 address, and IPv6 routes do not propagate. The setting does not filter IPv6 traffic. The default is disable.

    " }, "ApplianceModeSupport":{ "shape":"ApplianceModeSupportValue", @@ -21249,6 +22439,50 @@ "enum":["USD"] }, "CurrentGenerationFlag":{"type":"boolean"}, + "CustomKeyValuePairRequestSet":{ + "type":"list", + "member":{ + "shape":"CustomTagKeyValueRequestPair", + "locationName":"item" + } + }, + "CustomKeyValuePairResponseSet":{ + "type":"list", + "member":{ + "shape":"CustomTagKeyValueResponsePair", + "locationName":"item" + } + }, + "CustomTagKeyValueRequestPair":{ + "type":"structure", + "members":{ + "Key":{ + "shape":"String", + "documentation":"

    The key of the tag.

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

    The value of the tag.

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

    Describes a tag key-value pair for an application status check association request.

    " + }, + "CustomTagKeyValueResponsePair":{ + "type":"structure", + "members":{ + "Key":{ + "shape":"String", + "documentation":"

    The key of the tag.

    ", + "locationName":"key" + }, + "Value":{ + "shape":"String", + "documentation":"

    The value of the tag.

    ", + "locationName":"value" + } + }, + "documentation":"

    Describes a tag key-value pair for an application status check association.

    " + }, "CustomerGateway":{ "type":"structure", "members":{ @@ -21557,6 +22791,35 @@ "DefaultUdpStreamTimeout":{"type":"integer"}, "DefaultUdpTimeout":{"type":"integer"}, "DefaultingDhcpOptionsId":{"type":"string"}, + "DeleteApplicationStatusCheckRequest":{ + "type":"structure", + "required":["ApplicationStatusCheckId"], + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check to delete.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DeleteApplicationStatusCheckResult":{ + "type":"structure", + "members":{ + "ApplicationStatusCheck":{ + "shape":"ApplicationStatusCheckResponseObject", + "documentation":"

    Information about the deleted application status check.

    ", + "locationName":"applicationStatusCheck" + } + } + }, "DeleteCapacityManagerDataExportRequest":{ "type":"structure", "required":["CapacityManagerDataExportId"], @@ -22052,6 +23315,30 @@ } } }, + "DeleteIpamInternetRegistryAssociationRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association to delete.

    " + } + } + }, + "DeleteIpamInternetRegistryAssociationResult":{ + "type":"structure", + "members":{ + "IpamInternetRegistryAssociation":{ + "shape":"IpamInternetRegistryAssociation", + "documentation":"

    Information about the deleted internet registry association.

    ", + "locationName":"ipamInternetRegistryAssociation" + } + } + }, "DeleteIpamPolicyRequest":{ "type":"structure", "required":["IpamPolicyId"], @@ -22204,6 +23491,46 @@ } } }, + "DeleteIpamRoutingPolicyRegistrationRequest":{ + "type":"structure", + "required":[ + "IpamInternetRegistryAssociationId", + "Cidr" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation identifying the routing policy registration to delete.

    " + }, + "Force":{ + "shape":"BoxedBoolean", + "documentation":"

    Forces the deletion even if it conflicts with an announced route. Default: false.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "DeleteIpamRoutingPolicyRegistrationResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrationDelta":{ + "shape":"IpamRoutingPolicyRegistrationDelta", + "documentation":"

    Information about the routing policy registration delta created by this deletion.

    ", + "locationName":"ipamRoutingPolicyRegistrationDelta" + } + } + }, "DeleteIpamScopeRequest":{ "type":"structure", "required":["IpamScopeId"], @@ -23482,6 +24809,37 @@ } } }, + "DeleteTransitGatewayPolicyTableEntryRequest":{ + "type":"structure", + "required":[ + "TransitGatewayPolicyTableId", + "PolicyRuleNumber" + ], + "members":{ + "TransitGatewayPolicyTableId":{ + "shape":"TransitGatewayPolicyTableId", + "documentation":"

    The ID of the transit gateway policy table.

    " + }, + "PolicyRuleNumber":{ + "shape":"String", + "documentation":"

    The rule number of the policy table entry to delete.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DeleteTransitGatewayPolicyTableEntryResult":{ + "type":"structure", + "members":{ + "TransitGatewayPolicyTableEntry":{ + "shape":"TransitGatewayPolicyTableEntry", + "documentation":"

    Describes a transit gateway policy table entry

    ", + "locationName":"transitGatewayPolicyTableEntry" + } + } + }, "DeleteTransitGatewayPolicyTableRequest":{ "type":"structure", "required":["TransitGatewayPolicyTableId"], @@ -24502,6 +25860,156 @@ } } }, + "DescribeApplicationStatusCheckAssociationsMaxResults":{ + "type":"integer", + "max":1000, + "min":5 + }, + "DescribeApplicationStatusCheckAssociationsRequest":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckIds":{ + "shape":"ApplicationStatusCheckIdList", + "documentation":"

    The IDs of the application status checks for which to describe associations.

    ", + "locationName":"ApplicationStatusCheckId" + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    The filters to use to limit the results.

    • association-type – The type of association. Valid values: tag and instance-id.

    ", + "locationName":"Filter" + }, + "MaxResults":{ + "shape":"DescribeApplicationStatusCheckAssociationsMaxResults", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output. For more information, see Pagination.

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

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DescribeApplicationStatusCheckAssociationsResult":{ + "type":"structure", + "members":{ + "Associations":{ + "shape":"ApplicationStatusCheckAssociationSet", + "documentation":"

    The associations for the specified application status checks.

    ", + "locationName":"associationSet" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is <code>null</code> when there are no more items to return.

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

    The tags associated with the application status checks.

    ", + "locationName":"tagSet" + } + } + }, + "DescribeApplicationStatusChecksMaxResults":{ + "type":"integer", + "max":100, + "min":5 + }, + "DescribeApplicationStatusChecksRequest":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckIds":{ + "shape":"ApplicationStatusCheckIdList", + "documentation":"

    The IDs of the application status checks to describe.

    ", + "locationName":"ApplicationStatusCheckId" + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    The filters.

    • aggregation – The aggregation setting. Valid values: included and excluded.

    ", + "locationName":"Filter" + }, + "MaxResults":{ + "shape":"DescribeApplicationStatusChecksMaxResults", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output. For more information, see Pagination.

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

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "IncludeAll":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to include recently deleted application status checks that remain available during the deletion grace period. If you omit this parameter or set it to false, the response includes only active checks.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DescribeApplicationStatusChecksResult":{ + "type":"structure", + "members":{ + "ApplicationStatusChecks":{ + "shape":"ApplicationStatusCheckResponseSet", + "documentation":"

    Information about the application status checks.

    ", + "locationName":"applicationStatusCheckSet" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is <code>null</code> when there are no more items to return.

    ", + "locationName":"nextToken" + } + } + }, + "DescribeApplicationStatusMaxResults":{ + "type":"integer", + "max":100, + "min":1 + }, + "DescribeApplicationStatusRequest":{ + "type":"structure", + "members":{ + "InstanceIds":{ + "shape":"InstanceIdList", + "documentation":"

    The IDs of the instances for which to describe application status.

    ", + "locationName":"InstanceId" + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    The filters.

    • availability-zone-id – The ID of the Availability Zone.

    • status – The instance-level application status. For valid values and their meanings, see ApplicationStatus.

    ", + "locationName":"Filter" + }, + "MaxResults":{ + "shape":"DescribeApplicationStatusMaxResults", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output. For more information, see Pagination.

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

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DescribeApplicationStatusResult":{ + "type":"structure", + "members":{ + "ApplicationStatuses":{ + "shape":"ApplicationStatusesResponseType", + "documentation":"

    The application statuses for the specified instances.

    ", + "locationName":"applicationStatusesResponseType" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is <code>null</code> when there are no more items to return.

    ", + "locationName":"nextToken" + } + } + }, "DescribeAvailabilityZonesRequest":{ "type":"structure", "members":{ @@ -25047,6 +26555,53 @@ } } }, + "DescribeCapacityReservationDateChangeQuotesRequest":{ + "type":"structure", + "members":{ + "CapacityReservationModificationQuoteIds":{ + "shape":"CapacityReservationModificationQuoteIdSet", + "documentation":"

    The IDs of the date change quotes to describe.

    ", + "locationName":"CapacityReservationModificationQuoteId" + }, + "MaxResults":{ + "shape":"DescribeCapacityReservationDateChangeQuotesRequestMaxResults", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output. For more information, see Pagination.

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

    The token to use to retrieve the next page of results.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters. Filter names and values are case-sensitive.

    ", + "locationName":"Filter" + } + } + }, + "DescribeCapacityReservationDateChangeQuotesRequestMaxResults":{ + "type":"integer", + "max":1000, + "min":1 + }, + "DescribeCapacityReservationDateChangeQuotesResult":{ + "type":"structure", + "members":{ + "CapacityReservationModificationQuotes":{ + "shape":"CapacityReservationModificationQuoteResponseSet", + "documentation":"

    Information about the Capacity Reservation date change quotes.

    ", + "locationName":"capacityReservationModificationQuoteSet" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token to use to retrieve the next page of results. This value is null when there are no more results to return.

    ", + "locationName":"nextToken" + } + } + }, "DescribeCapacityReservationFleetsMaxResults":{ "type":"integer", "max":100, @@ -25116,7 +26671,7 @@ }, "CapacityReservationIds":{ "shape":"CapacityReservationIdSet", - "documentation":"

    The Capacity Reservation IDs.

    Default: Describes all your Capacity Reservations.

    Constraints: Maximum 100 explicitly specified Capacity Reservation IDs.

    ", + "documentation":"

    The Capacity Reservation IDs.

    Default: Describes all your Capacity Reservations.

    Constraints: Maximum 10 explicitly specified Capacity Reservation IDs.

    ", "locationName":"CapacityReservationId" }, "Filters":{ @@ -26111,17 +27666,17 @@ }, "Lifecycle":{ "shape":"InstanceLifecycle", - "documentation":"

    Indicates if the instance that could not be launched was a Spot, On-Demand, Capacity Block, or Interruptible Capacity Reservation instance.

    ", + "documentation":"

    Indicates if the instance that could not be launched was a Spot, On-Demand, Capacity Block for ML, or interruptible Capacity Reservation instance. If you are using ReservedCapacityOptions with on-demand-capacity-reservation in the ReservationTypes list, the value can also be on-demand-capacity-reservation.

    ", "locationName":"lifecycle" }, "ErrorCode":{ "shape":"String", - "documentation":"

    The error code that indicates why the instance could not be launched. For more information about error codes, see Error codes.

    ", + "documentation":"

    The error code that indicates why the instance could not be launched. For more information about error codes, see Error codes.

    ", "locationName":"errorCode" }, "ErrorMessage":{ "shape":"String", - "documentation":"

    The error message that describes why the instance could not be launched. For more information about error messages, see Error codes.

    ", + "documentation":"

    The error message that describes why the instance could not be launched. For more information about error messages, see Error codes.

    ", "locationName":"errorMessage" } }, @@ -26254,7 +27809,7 @@ }, "Lifecycle":{ "shape":"InstanceLifecycle", - "documentation":"

    Indicates if the instance that was launched is a Spot, On-Demand, Capacity Block, or Interruptible Capacity Reservation instance.

    ", + "documentation":"

    Indicates if the instance that was launched is a Spot, On-Demand, Capacity Block for ML, or interruptible Capacity Reservation instance.

    ", "locationName":"lifecycle" }, "InstanceIds":{ @@ -26895,7 +28450,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    The filters.

    • architecture - The image architecture (i386 | x86_64 | arm64 | x86_64_mac | arm64_mac).

    • block-device-mapping.delete-on-termination - A Boolean value that indicates whether the Amazon EBS volume is deleted on instance termination.

    • block-device-mapping.device-name - The device name specified in the block device mapping (for example, /dev/sdh or xvdh).

    • block-device-mapping.snapshot-id - The ID of the snapshot used for the Amazon EBS volume.

    • block-device-mapping.volume-size - The volume size of the Amazon EBS volume, in GiB.

    • block-device-mapping.volume-type - The volume type of the Amazon EBS volume (io1 | io2 | gp2 | gp3 | sc1 | st1 | standard).

    • block-device-mapping.encrypted - A Boolean that indicates whether the Amazon EBS volume is encrypted.

    • creation-date - The time when the image was created, in the ISO 8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ), for example, 2021-09-29T11:04:43.305Z. You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • description - The description of the image (provided during image creation).

    • ena-support - A Boolean that indicates whether enhanced networking with ENA is enabled.

    • free-tier-eligible - A Boolean that indicates whether this image can be used under the Amazon Web Services Free Tier (true | false).

    • hypervisor - The hypervisor type (ovm | xen).

    • image-allowed - A Boolean that indicates whether the image meets the criteria specified for Allowed AMIs.

    • image-id - The ID of the image.

    • image-watermark.source-image-creation-time - The creation date of the source AMI, in the ISO 8601 format in the UTC time zone ( YYYY-MM-DDTHH:MM:SS.ssssss+HH:MM ). You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • image-watermark.source-image-id - The ID of the AMI to which the watermark was originally attached.

    • image-watermark.source-image-region - The Region where the watermark was originally attached.

    • image-watermark.watermark-creation-time - The date and time the watermark was attached to the AMI, in the ISO 8601 format in the UTC time zone ( YYYY-MM-DDTHH:MM:SS.ssssss+HH:MM ). You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • image-watermark.watermark-key - The watermark identifier, in accountId:watermarkName format (for example, 123456789012:approvedAmi).

    • image-type - The image type (machine | kernel | ramdisk).

    • is-public - A Boolean that indicates whether the image is public.

    • kernel-id - The kernel ID.

    • manifest-location - The location of the image manifest.

    • name - The name of the AMI (provided during image creation).

    • owner-alias - The owner alias (amazon | aws-backup-vault | aws-marketplace). The valid aliases are defined in an Amazon-maintained list. This is not the Amazon Web Services account alias that can be set using the IAM console. We recommend that you use the Owner request parameter instead of this filter.

    • owner-id - The Amazon Web Services account ID of the owner. We recommend that you use the Owner request parameter instead of this filter.

    • platform - The platform. The only supported value is windows.

    • product-code - The product code.

    • product-code.type - The type of the product code (marketplace).

    • public-ssm-parameter-name - The name of a public Systems Manager parameter associated with the AMI. The parameter must be in a trusted Amazon Web Services namespace under aws/service/. Returns all AMIs that have ever been associated with the parameter, including previous versions.

    • ramdisk-id - The RAM disk ID.

    • root-device-name - The device name of the root device volume (for example, /dev/sda1).

    • root-device-type - The type of the root device volume (ebs | instance-store).

    • source-image-id - The ID of the source AMI from which the AMI was created.

    • source-image-region - The Region of the source AMI.

    • source-instance-id - The ID of the instance that the AMI was created from if the AMI was created using CreateImage. This filter is applicable only if the AMI was created using CreateImage.

    • state - The state of the image (available | pending | failed).

    • state-reason-code - The reason code for the state change.

    • state-reason-message - The message for the state change.

    • sriov-net-support - A value of simple indicates that enhanced networking with the Intel 82599 VF interface is enabled.

    • tag:<key> - The key/value combination of a tag assigned to the resource. Use the tag key in the filter name and the tag value as the filter value. For example, to find all resources that have a tag with the key Owner and the value TeamA, specify tag:Owner for the filter name and TeamA for the filter value.

    • tag-key - The key of a tag assigned to the resource. Use this filter to find all resources assigned a tag with a specific key, regardless of the tag value.

    • virtualization-type - The virtualization type (paravirtual | hvm).

    ", + "documentation":"

    The filters.

    • architecture - The image architecture (i386 | x86_64 | arm64 | x86_64_mac | arm64_mac).

    • block-device-mapping.delete-on-termination - A Boolean value that indicates whether the Amazon EBS volume is deleted on instance termination.

    • block-device-mapping.device-name - The device name specified in the block device mapping (for example, /dev/sdh or xvdh).

    • block-device-mapping.snapshot-id - The ID of the snapshot used for the Amazon EBS volume.

    • block-device-mapping.volume-size - The volume size of the Amazon EBS volume, in GiB.

    • block-device-mapping.volume-type - The volume type of the Amazon EBS volume (io1 | io2 | gp2 | gp3 | sc1 | st1 | standard).

    • block-device-mapping.encrypted - A Boolean that indicates whether the Amazon EBS volume is encrypted.

    • boot-mode – The boot mode of the image (legacy-bios | uefi | uefi-preferred).

    • creation-date - The time when the image was created, in the ISO 8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ), for example, 2021-09-29T11:04:43.305Z. You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • description - The description of the image (provided during image creation).

    • ena-support - A Boolean that indicates whether enhanced networking with ENA is enabled.

    • free-tier-eligible - A Boolean that indicates whether this image can be used under the Amazon Web Services Free Tier (true | false).

    • hypervisor - The hypervisor type (ovm | xen).

    • image-allowed - A Boolean that indicates whether the image meets the criteria specified for Allowed AMIs.

    • image-id - The ID of the image.

    • image-watermark.source-image-creation-time - The creation date of the source AMI, in the ISO 8601 format in the UTC time zone ( YYYY-MM-DDTHH:MM:SS.ssssss+HH:MM ). You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • image-watermark.source-image-id - The ID of the AMI to which the watermark was originally attached.

    • image-watermark.source-image-region - The Region where the watermark was originally attached.

    • image-watermark.watermark-creation-time - The date and time the watermark was attached to the AMI, in the ISO 8601 format in the UTC time zone ( YYYY-MM-DDTHH:MM:SS.ssssss+HH:MM ). You can use a wildcard (*), for example, 2021-09-29T*, which matches an entire day.

    • image-watermark.watermark-key - The watermark identifier, in accountId:watermarkName format (for example, 123456789012:approvedAmi).

    • image-type - The image type (machine | kernel | ramdisk).

    • instance-type-specification.supported-instance-type – The instance types that are compatible with the AMI, as specified by the AMI owner. Values can be individual instance types (for example, t3.micro) or wildcard patterns that match multiple instance types (for example, t3.*).

    • instance-type-specification.unsupported-instance-type – The instance types that are not compatible with the AMI, as specified by the AMI owner. Values can be individual instance types (for example, t3.micro) or wildcard patterns that match multiple instance types (for example, t3.*).

    • is-public - A Boolean that indicates whether the image is public.

    • kernel-id - The kernel ID.

    • manifest-location - The location of the image manifest.

    • name - The name of the AMI (provided during image creation).

    • owner-alias - The owner alias (amazon | aws-backup-vault | aws-marketplace). The valid aliases are defined in an Amazon-maintained list. This is not the Amazon Web Services account alias that can be set using the IAM console. We recommend that you use the Owner request parameter instead of this filter.

    • owner-id - The Amazon Web Services account ID of the owner. We recommend that you use the Owner request parameter instead of this filter.

    • platform - The platform. The only supported value is windows.

    • product-code - The product code.

    • product-code.type - The type of the product code (marketplace).

    • public-ssm-parameter-name - The name of a public Systems Manager parameter associated with the AMI. The parameter must be in a trusted Amazon Web Services namespace under aws/service/. Returns all AMIs that have ever been associated with the parameter, including previous versions.

    • ramdisk-id - The RAM disk ID.

    • root-device-name - The device name of the root device volume (for example, /dev/sda1).

    • root-device-type - The type of the root device volume (ebs | instance-store).

    • source-image-id - The ID of the source AMI from which the AMI was created.

    • source-image-region - The Region of the source AMI.

    • source-instance-id - The ID of the instance that the AMI was created from if the AMI was created using CreateImage. This filter is applicable only if the AMI was created using CreateImage.

    • state - The state of the image (available | pending | failed).

    • state-reason-code - The reason code for the state change.

    • state-reason-message - The message for the state change.

    • sriov-net-support - A value of simple indicates that enhanced networking with the Intel 82599 VF interface is enabled.

    • tag:<key> - The key/value combination of a tag assigned to the resource. Use the tag key in the filter name and the tag value as the filter value. For example, to find all resources that have a tag with the key Owner and the value TeamA, specify tag:Owner for the filter name and TeamA for the filter value.

    • tag-key - The key of a tag assigned to the resource. Use this filter to find all resources assigned a tag with a specific key, regardless of the tag value.

    • virtualization-type - The virtualization type (paravirtual | hvm).

    ", "locationName":"Filter" } } @@ -27343,7 +28898,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    The filters.

    • availability-zone - The Availability Zone of the instance.

    • availability-zone-id - The ID of the Availability Zone of the instance.

    • event.code - The code for the scheduled event (instance-reboot | system-reboot | system-maintenance | instance-retirement | instance-stop).

    • event.description - A description of the event.

    • event.instance-event-id - The ID of the event whose date and time you are modifying.

    • event.not-after - The latest end time for the scheduled event (for example, 2014-09-15T17:15:20.000Z).

    • event.not-before - The earliest start time for the scheduled event (for example, 2014-09-15T17:15:20.000Z).

    • event.not-before-deadline - The deadline for starting the event (for example, 2014-09-15T17:15:20.000Z).

    • instance-state-code - The code for the instance state, as a 16-bit unsigned integer. The high byte is used for internal purposes and should be ignored. The low byte is set based on the state represented. The valid values are 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), and 80 (stopped).

    • instance-state-name - The state of the instance (pending | running | shutting-down | terminated | stopping | stopped).

    • instance-status.reachability - Filters on instance status where the name is reachability (passed | failed | initializing | insufficient-data).

    • instance-status.status - The status of the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    • operator.managed - A Boolean that indicates whether this is a managed instance.

    • operator.principal - The principal that manages the instance. Only valid for managed instances, where managed is true.

    • system-status.reachability - Filters on system status where the name is reachability (passed | failed | initializing | insufficient-data).

    • system-status.status - The system status of the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    • attached-ebs-status.status - The status of the attached EBS volume for the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    ", + "documentation":"

    The filters.

    • availability-zone - The Availability Zone of the instance.

    • availability-zone-id - The ID of the Availability Zone of the instance.

    • event.code - The code for the scheduled event (instance-reboot | system-reboot | system-maintenance | instance-retirement | instance-stop).

    • event.description - A description of the event.

    • event.instance-event-id - The ID of the event whose date and time you are modifying.

    • event.not-after - The latest end time for the scheduled event (for example, 2014-09-15T17:15:20.000Z).

    • event.not-before - The earliest start time for the scheduled event (for example, 2014-09-15T17:15:20.000Z).

    • event.not-before-deadline - The deadline for starting the event (for example, 2014-09-15T17:15:20.000Z).

    • instance-state-code - The code for the instance state, as a 16-bit unsigned integer. The high byte is used for internal purposes and should be ignored. The low byte is set based on the state represented. The valid values are 0 (pending), 16 (running), 32 (shutting-down), 48 (terminated), 64 (stopping), and 80 (stopped).

    • instance-state-name - The state of the instance (pending | running | shutting-down | terminated | stopping | stopped).

    • instance-status.reachability - Filters on instance status where the name is reachability (passed | failed | initializing | insufficient-data).

    • instance-status.status - The status of the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    • operator.managed - A Boolean that indicates whether this is a managed instance.

    • operator.principal - The principal that manages the instance. Only valid for managed instances, where managed is true.

    • system-status.reachability - Filters on system status where the name is reachability (passed | failed | initializing | insufficient-data).

    • system-status.status - The system status of the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    • attached-ebs-status.status - The status of the attached EBS volume for the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    • application-status.status - The application status of the instance (ok | impaired | initializing | insufficient-data | not-applicable).

    ", "locationName":"Filter" }, "IncludeAllInstances":{ @@ -27691,6 +29246,48 @@ } } }, + "DescribeIpamInternetRegistryAssociationsRequest":{ + "type":"structure", + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationIds":{ + "shape":"ValueStringList", + "documentation":"

    The IDs of the internet registry associations to describe.

    ", + "locationName":"IpamInternetRegistryAssociationId" + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters to apply to the results.

    ", + "locationName":"Filter" + } + } + }, + "DescribeIpamInternetRegistryAssociationsResult":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + }, + "IpamInternetRegistryAssociations":{ + "shape":"IpamInternetRegistryAssociationSet", + "documentation":"

    The internet registry associations.

    ", + "locationName":"ipamInternetRegistryAssociationSet" + } + } + }, "DescribeIpamPoliciesRequest":{ "type":"structure", "members":{ @@ -33227,6 +34824,40 @@ } } }, + "DisableApplicationStatusCheckSuppressionRequest":{ + "type":"structure", + "members":{ + "InstanceIds":{ + "shape":"InstanceIdList", + "documentation":"

    The IDs of the instances for which to disable application status check suppression.

    ", + "locationName":"InstanceId" + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DisableApplicationStatusCheckSuppressionResult":{ + "type":"structure", + "members":{ + "SuccessfulResults":{ + "shape":"SuccessfulSuppressionResponseSet", + "documentation":"

    The instances for which suppression was successfully disabled.

    ", + "locationName":"successfulResultSet" + }, + "UnsuccessfulResults":{ + "shape":"UnsuccessfulSuppressionResponseSet", + "documentation":"

    The instances for which suppression failed to be disabled.

    ", + "locationName":"unsuccessfulResultSet" + } + } + }, "DisableAwsNetworkPerformanceMetricSubscriptionRequest":{ "type":"structure", "members":{ @@ -33912,6 +35543,50 @@ } } }, + "DisassociateApplicationStatusCheckRequest":{ + "type":"structure", + "required":["ApplicationStatusCheckId"], + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check to disassociate.

    " + }, + "TargetTagAssociations":{ + "shape":"CustomKeyValuePairRequestSet", + "documentation":"

    The tags to disassociate from the application status check. Specify the same key-value pairs that were used during association.

    ", + "locationName":"TargetTagAssociation" + }, + "InstanceIds":{ + "shape":"InstanceIdList", + "documentation":"

    The IDs of the instances to disassociate from the application status check.

    ", + "locationName":"InstanceId" + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "DisassociateApplicationStatusCheckResult":{ + "type":"structure", + "members":{ + "SuccessfulResults":{ + "shape":"SuccessfulAssociationResponseSet", + "documentation":"

    The associations that were successfully removed.

    ", + "locationName":"successfulResultSet" + }, + "UnsuccessfulResults":{ + "shape":"UnsuccessfulAssociationResponseSet", + "documentation":"

    The associations that failed to be removed.

    ", + "locationName":"unsuccessfulResultSet" + } + } + }, "DisassociateCapacityReservationBillingOwnerRequest":{ "type":"structure", "required":[ @@ -35579,6 +37254,44 @@ } } }, + "EnableApplicationStatusCheckSuppressionRequest":{ + "type":"structure", + "members":{ + "InstanceIds":{ + "shape":"InstanceIdList", + "documentation":"

    The IDs of the instances for which to suppress application status checks.

    ", + "locationName":"InstanceId" + }, + "DurationSeconds":{ + "shape":"BoxedInteger", + "documentation":"

    The duration, in seconds, for which to suppress application status checks. If omitted, the application status check is suppressed indefinitely until you call DisableApplicationStatusCheckSuppression.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "EnableApplicationStatusCheckSuppressionResult":{ + "type":"structure", + "members":{ + "SuccessfulResults":{ + "shape":"SuccessfulSuppressionResponseSet", + "documentation":"

    The instances for which suppression was successfully enabled.

    ", + "locationName":"successfulResultSet" + }, + "UnsuccessfulResults":{ + "shape":"UnsuccessfulSuppressionResponseSet", + "documentation":"

    The instances for which suppression failed to be enabled.

    ", + "locationName":"unsuccessfulResultSet" + } + } + }, "EnableAwsNetworkPerformanceMetricSubscriptionRequest":{ "type":"structure", "members":{ @@ -36062,6 +37775,62 @@ } } }, + "EnableIpamInternetRegistryAssociationRequest":{ + "type":"structure", + "required":[ + "IpamInternetRegistryAssociationId", + "RpkiVersion", + "ServiceUri", + "ChildHandle", + "ParentHandle", + "ParentBpkiTa" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association to enable.

    " + }, + "RpkiVersion":{ + "shape":"String", + "documentation":"

    The RPKI version to use from the Parent Response XML.

    " + }, + "ServiceUri":{ + "shape":"String", + "documentation":"

    The RPKI service URI for the publication point from the Parent Response XML.

    " + }, + "ChildHandle":{ + "shape":"String", + "documentation":"

    The child handle for the BPKI certificate hierarchy from the Parent Response XML.

    " + }, + "ParentHandle":{ + "shape":"String", + "documentation":"

    The parent handle for the BPKI certificate hierarchy from the Parent Response XML.

    " + }, + "ParentBpkiTa":{ + "shape":"String", + "documentation":"

    The parent BPKI Trust Anchor certificate in PEM format from the Parent Response XML.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "EnableIpamInternetRegistryAssociationResult":{ + "type":"structure", + "members":{ + "IpamInternetRegistryAssociation":{ + "shape":"IpamInternetRegistryAssociation", + "documentation":"

    Information about the enabled internet registry association.

    ", + "locationName":"ipamInternetRegistryAssociation" + } + } + }, "EnableIpamOrganizationAdminAccountRequest":{ "type":"structure", "required":["DelegatedAdminAccountId"], @@ -37672,6 +39441,22 @@ "locationName":"item" } }, + "FleetCapacityReservationTargetRequest":{ + "type":"structure", + "members":{ + "CapacityReservationIds":{ + "shape":"CapacityReservationIdSet", + "documentation":"

    The IDs of the Capacity Reservations in which to launch the instances.

    ", + "locationName":"CapacityReservationId" + }, + "CapacityReservationResourceGroupArns":{ + "shape":"CapacityReservationResourceGroupArnSet", + "documentation":"

    The ARNs of the Capacity Reservation Resource Groups in which to launch the instances.

    ", + "locationName":"CapacityReservationResourceGroupArn" + } + }, + "documentation":"

    Describes the target Capacity Reservations or Capacity Reservation Resource Groups for an EC2 Fleet that launches into reserved capacity. You can specify Capacity Reservation IDs or a Capacity Reservation Resource Group ARN, but not both.

    " + }, "FleetCapacityReservationTenancy":{ "type":"string", "enum":["default"] @@ -38147,7 +39932,11 @@ }, "FleetReservationType":{ "type":"string", - "enum":["interruptible-capacity-reservation"] + "enum":[ + "on-demand-capacity-reservation", + "capacity-block", + "interruptible-capacity-reservation" + ] }, "FleetSet":{ "type":"list", @@ -39665,7 +41454,7 @@ "locationName":"instanceId" }, "UefiData":{ - "shape":"String", + "shape":"SensitiveString", "documentation":"

    Base64 representation of the non-volatile UEFI variable store.

    ", "locationName":"uefiData" } @@ -39879,6 +41668,139 @@ } } }, + "GetIpamDiscoveredRoutesRequest":{ + "type":"structure", + "required":[ + "IpamResourceDiscoveryId", + "ResourceRegion" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamResourceDiscoveryId":{ + "shape":"IpamResourceDiscoveryId", + "documentation":"

    The ID of the IPAM resource discovery.

    " + }, + "ResourceRegion":{ + "shape":"String", + "documentation":"

    The Amazon Web Services Region to retrieve discovered routes for.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters to apply to the results.

    ", + "locationName":"Filter" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + } + } + }, + "GetIpamDiscoveredRoutesResult":{ + "type":"structure", + "members":{ + "IpamDiscoveredRoutes":{ + "shape":"IpamDiscoveredRouteSet", + "documentation":"

    The discovered BGP routes.

    ", + "locationName":"ipamDiscoveredRouteSet" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + } + } + }, + "GetIpamInternetRegistryAssociationAsnsRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters to apply to the results.

    ", + "locationName":"Filter" + } + } + }, + "GetIpamInternetRegistryAssociationAsnsResult":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + }, + "IpamInternetRegistryAssociationAsns":{ + "shape":"IpamInternetRegistryAssociationAsnSet", + "documentation":"

    The ASNs registered with the internet registry.

    ", + "locationName":"ipamInternetRegistryAssociationAsnSet" + } + } + }, + "GetIpamInternetRegistryAssociationCidrsRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters to apply to the results.

    ", + "locationName":"Filter" + } + } + }, + "GetIpamInternetRegistryAssociationCidrsResult":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + }, + "IpamInternetRegistryAssociationCidrs":{ + "shape":"IpamInternetRegistryAssociationCidrSet", + "documentation":"

    The CIDRs registered with the internet registry.

    ", + "locationName":"ipamInternetRegistryAssociationCidrSet" + } + } + }, "GetIpamPolicyAllocationRulesRequest":{ "type":"structure", "required":["IpamPolicyId"], @@ -40259,6 +42181,188 @@ } } }, + "GetIpamRouteOriginAuthorizationsRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "Cidr":{ + "shape":"String", + "documentation":"

    Filter results to a specific CIDR prefix.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "GetIpamRouteOriginAuthorizationsResult":{ + "type":"structure", + "members":{ + "IpamRouteOriginAuthorizations":{ + "shape":"IpamRouteOriginAuthorizationInfoSet", + "documentation":"

    The Route Origin Authorizations published to the RPKI.

    ", + "locationName":"ipamRouteOriginAuthorizationSet" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + } + } + }, + "GetIpamRouteProtectionFindingsRequest":{ + "type":"structure", + "required":["IpamId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamId":{ + "shape":"IpamId", + "documentation":"

    The ID of the IPAM to retrieve route protection findings for.

    " + }, + "Filters":{ + "shape":"FilterList", + "documentation":"

    One or more filters to apply to the results.

    ", + "locationName":"Filter" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + } + } + }, + "GetIpamRouteProtectionFindingsResult":{ + "type":"structure", + "members":{ + "IpamId":{ + "shape":"IpamId", + "documentation":"

    The ID of the IPAM.

    ", + "locationName":"ipamId" + }, + "RouteProtectionFindings":{ + "shape":"IpamRouteProtectionFindingSet", + "documentation":"

    The route protection findings.

    ", + "locationName":"routeProtectionFindingSet" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + } + } + }, + "GetIpamRoutingPolicyRegistrationDeltasRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "DeltaId":{ + "shape":"String", + "documentation":"

    Filter results to a specific delta ID.

    " + }, + "StartTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start of the time range to filter deltas by.

    " + }, + "EndTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The end of the time range to filter deltas by.

    " + }, + "ChronologicalOrder":{ + "shape":"ChronologicalOrder", + "documentation":"

    The chronological order to return results in. Valid values: forward | reverse.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "GetIpamRoutingPolicyRegistrationDeltasResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrationDeltas":{ + "shape":"IpamRoutingPolicyRegistrationDeltaSet", + "documentation":"

    The routing policy registration deltas.

    ", + "locationName":"ipamRoutingPolicyRegistrationDeltaSet" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + } + } + }, + "GetIpamRoutingPolicyRegistrationsRequest":{ + "type":"structure", + "required":["IpamInternetRegistryAssociationId"], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "Cidr":{ + "shape":"String", + "documentation":"

    Filter results to a specific CIDR prefix.

    " + }, + "MaxResults":{ + "shape":"IpamMaxResults", + "documentation":"

    The maximum number of results to return in a single call. If not specified, all available results are returned. To retrieve the remaining results, make another call with the returned nextToken value.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results.

    " + } + } + }, + "GetIpamRoutingPolicyRegistrationsResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrations":{ + "shape":"IpamRoutingPolicyRegistrationSet", + "documentation":"

    The routing policy registrations.

    ", + "locationName":"ipamRoutingPolicyRegistrationSet" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to use to retrieve the next page of results.

    ", + "locationName":"nextToken" + } + } + }, "GetLaunchTemplateDataRequest":{ "type":"structure", "required":["InstanceId"], @@ -40803,6 +42907,10 @@ "NextToken":{ "shape":"String", "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "IncludeLocalZones":{ + "shape":"Boolean", + "documentation":"

    Specify true so that the response returns scores that include Local Zones. Otherwise, the response ignores Local Zones.

    When you request regional scores, Local Zone capacity counts toward its parent Region.

    " } } }, @@ -41051,7 +43159,7 @@ }, "Filters":{ "shape":"FilterList", - "documentation":"

    The filters associated with the transit gateway policy table.

    ", + "documentation":"

    One or more filters. The possible values are:

    • policy-rule-number - The rule number for the transit gateway policy table entry.

    • target-route-table-id - The ID of the target route table.

    • policy-rule.source-ip - The source CIDR block for the policy rule.

    • policy-rule.destination-ip - The destination CIDR block for the policy rule.

    • policy-rule.source-port - The source port or port range for the policy rule.

    • policy-rule.destination-port - The destination port or port range for the policy rule.

    • policy-rule.protocol - The protocol for the policy rule.

    • policy-rule.meta-data.key - The metadata key for the policy rule.

    • policy-rule.meta-data.value - The metadata value for the policy rule.

    ", "locationName":"Filter" }, "MaxResults":{ @@ -41075,6 +43183,11 @@ "shape":"TransitGatewayPolicyTableEntryList", "documentation":"

    The entries for the transit gateway policy table.

    ", "locationName":"transitGatewayPolicyTableEntries" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token to use to retrieve the next page of results. This value is null when there are no more results to return.

    ", + "locationName":"nextToken" } } }, @@ -41647,6 +43760,125 @@ "invalid" ] }, + "HealthCheckPathDestinationRequestObject":{ + "type":"structure", + "members":{ + "SubnetId":{ + "shape":"SubnetId", + "documentation":"

    The ID of the subnet for the destination.

    " + }, + "SecurityGroupId":{ + "shape":"SecurityGroupId", + "documentation":"

    The ID of the security group for the destination.

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

    Describes a destination for a health check path in a request. Destinations can be in a different Availability Zone than the source (cross-AZ) or in a Local Zone (AZ to Local Zone), enabling remote health validation of your application.

    " + }, + "HealthCheckPathDestinationRequestSet":{ + "type":"list", + "member":{ + "shape":"HealthCheckPathDestinationRequestObject", + "locationName":"item" + } + }, + "HealthCheckPathDestinationResponseList":{ + "type":"list", + "member":{ + "shape":"HealthCheckPathDestinationResponseObject", + "locationName":"item" + } + }, + "HealthCheckPathDestinationResponseObject":{ + "type":"structure", + "members":{ + "SubnetId":{ + "shape":"String", + "documentation":"

    The ID of the subnet for the destination.

    ", + "locationName":"subnetId" + }, + "SecurityGroupId":{ + "shape":"String", + "documentation":"

    The ID of the security group for the destination.

    ", + "locationName":"securityGroupId" + } + }, + "documentation":"

    Describes a destination for a health check path.

    " + }, + "HealthCheckPathRequestList":{ + "type":"list", + "member":{ + "shape":"HealthCheckPathRequestObject", + "locationName":"item" + } + }, + "HealthCheckPathRequestObject":{ + "type":"structure", + "members":{ + "Source":{ + "shape":"HealthCheckPathSourceRequestObject", + "documentation":"

    The source for the health check path.

    " + }, + "Destinations":{ + "shape":"HealthCheckPathDestinationRequestSet", + "documentation":"

    The destinations for the health check path.

    ", + "locationName":"Destination" + } + }, + "documentation":"

    Describes a health check path for an application status check request.

    " + }, + "HealthCheckPathResponseList":{ + "type":"list", + "member":{ + "shape":"HealthCheckPathResponseObject", + "locationName":"item" + } + }, + "HealthCheckPathResponseObject":{ + "type":"structure", + "members":{ + "Source":{ + "shape":"HealthCheckPathSourceResponseObject", + "documentation":"

    The source for the health check path.

    ", + "locationName":"source" + }, + "Destinations":{ + "shape":"HealthCheckPathDestinationResponseList", + "documentation":"

    The destinations for the health check path.

    ", + "locationName":"destinationSet" + } + }, + "documentation":"

    Describes a health check path for an application status check.

    " + }, + "HealthCheckPathSourceRequestObject":{ + "type":"structure", + "members":{ + "SubnetId":{ + "shape":"SubnetId", + "documentation":"

    The ID of the subnet for the source.

    " + }, + "SecurityGroupId":{ + "shape":"SecurityGroupId", + "documentation":"

    The ID of the security group for the source.

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

    Describes the source for a health check path in a request. The source defines the subnet and security group where a health check elastic network interface (ENI) is created to originate health check traffic.

    " + }, + "HealthCheckPathSourceResponseObject":{ + "type":"structure", + "members":{ + "SubnetId":{ + "shape":"String", + "documentation":"

    The ID of the subnet for the source.

    ", + "locationName":"subnetId" + }, + "SecurityGroupId":{ + "shape":"String", + "documentation":"

    The ID of the security group for the source.

    ", + "locationName":"securityGroupId" + } + }, + "documentation":"

    Describes the source for a health check path.

    " + }, "HibernationFlag":{"type":"boolean"}, "HibernationOptions":{ "type":"structure", @@ -42421,6 +44653,11 @@ "documentation":"

    The watermarks attached to the AMI.

    ", "locationName":"imageWatermarkSet" }, + "InstanceTypeSpecification":{ + "shape":"InstanceTypeSpecification", + "documentation":"

    The instance type specification for the AMI, which defines which instance types are compatible with this image.

    ", + "locationName":"instanceTypeSpecification" + }, "ImageId":{ "shape":"String", "documentation":"

    The ID of the AMI.

    ", @@ -42976,7 +45213,8 @@ "ImageUefiDataRequest":{ "type":"string", "max":64000, - "min":0 + "min":0, + "sensitive":true }, "ImageUsageReport":{ "type":"structure", @@ -44130,6 +46368,11 @@ "ingestion-failed" ] }, + "InitializationGracePeriodSeconds":{ + "type":"integer", + "max":600, + "min":-1 + }, "InitializationStatusDetails":{ "type":"structure", "members":{ @@ -44477,6 +46720,44 @@ }, "documentation":"

    Describes an instance.

    " }, + "InstanceApplicationStatus":{ + "type":"structure", + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The ID of the instance.

    ", + "locationName":"instanceId" + }, + "AvailabilityZone":{ + "shape":"String", + "documentation":"

    The Availability Zone of the instance.

    ", + "locationName":"availabilityZone" + }, + "AvailabilityZoneId":{ + "shape":"String", + "documentation":"

    The ID of the Availability Zone of the instance.

    ", + "locationName":"availabilityZoneId" + }, + "ApplicationStatus":{ + "shape":"ApplicationStatus", + "documentation":"

    The application status for the instance.

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

    The tags assigned to the instance.

    ", + "locationName":"tagSet" + } + }, + "documentation":"

    Describes the application status for an instance.

    " + }, + "InstanceApplicationStatusSet":{ + "type":"list", + "member":{ + "shape":"InstanceApplicationStatus", + "locationName":"item" + } + }, "InstanceAttachmentEnaSrdSpecification":{ "type":"structure", "members":{ @@ -45278,7 +47559,8 @@ "enum":[ "spot", "on-demand", - "interruptible-capacity-reservation" + "interruptible-capacity-reservation", + "capacity-block" ] }, "InstanceLifecycleType":{ @@ -46459,9 +48741,14 @@ "shape":"EbsStatusSummary", "documentation":"

    Reports impaired functionality that stems from an attached Amazon EBS volume that is unreachable and unable to complete I/O operations.

    ", "locationName":"attachedEbsStatus" + }, + "ApplicationStatus":{ + "shape":"ApplicationStatusSummary", + "documentation":"

    Reports the application-level health status for the instance.

    ", + "locationName":"applicationStatus" } }, - "documentation":"

    Describes the status of an instance.

    " + "documentation":"

    Describes the status of an instance, including system status, instance status, attached EBS status, and application status.

    " }, "InstanceStatusDetails":{ "type":"structure", @@ -47869,7 +50156,223 @@ "m8id.96xlarge", "m8id.metal-48xl", "m8id.metal-96xl", - "hpc8a.96xlarge" + "hpc8a.96xlarge", + "c8in.large", + "c8in.xlarge", + "c8in.2xlarge", + "c8in.4xlarge", + "c8in.8xlarge", + "c8in.12xlarge", + "c8in.16xlarge", + "c8in.24xlarge", + "c8in.32xlarge", + "c8in.48xlarge", + "c8in.96xlarge", + "c8in.metal-48xl", + "c8in.metal-96xl", + "c8ib.large", + "c8ib.xlarge", + "c8ib.2xlarge", + "c8ib.4xlarge", + "c8ib.8xlarge", + "c8ib.12xlarge", + "c8ib.16xlarge", + "c8ib.24xlarge", + "c8ib.32xlarge", + "c8ib.48xlarge", + "c8ib.96xlarge", + "c8ib.metal-48xl", + "c8ib.metal-96xl", + "r8in.large", + "r8in.xlarge", + "r8in.2xlarge", + "r8in.4xlarge", + "r8in.8xlarge", + "r8in.12xlarge", + "r8in.16xlarge", + "r8in.24xlarge", + "r8in.32xlarge", + "r8in.48xlarge", + "r8in.96xlarge", + "r8ib.large", + "r8ib.xlarge", + "r8ib.2xlarge", + "r8ib.4xlarge", + "r8ib.8xlarge", + "r8ib.12xlarge", + "r8ib.16xlarge", + "r8ib.24xlarge", + "r8ib.32xlarge", + "r8ib.48xlarge", + "r8ib.96xlarge", + "m8in.large", + "m8in.xlarge", + "m8in.2xlarge", + "m8in.4xlarge", + "m8in.8xlarge", + "m8in.12xlarge", + "m8in.16xlarge", + "m8in.24xlarge", + "m8in.32xlarge", + "m8in.48xlarge", + "m8in.96xlarge", + "m8ib.large", + "m8ib.xlarge", + "m8ib.2xlarge", + "m8ib.4xlarge", + "m8ib.8xlarge", + "m8ib.12xlarge", + "m8ib.16xlarge", + "m8ib.24xlarge", + "m8ib.32xlarge", + "m8ib.48xlarge", + "m8ib.96xlarge", + "m8ine.large", + "m8ine.xlarge", + "m8ine.2xlarge", + "m8ine.4xlarge", + "m8ine.8xlarge", + "m8ine.12xlarge", + "c8ine.large", + "c8ine.xlarge", + "c8ine.2xlarge", + "c8ine.4xlarge", + "c8ine.8xlarge", + "c8ine.12xlarge", + "m8idn.large", + "m8idn.xlarge", + "m8idn.2xlarge", + "m8idn.4xlarge", + "m8idn.8xlarge", + "m8idn.12xlarge", + "m8idn.16xlarge", + "m8idn.24xlarge", + "m8idn.32xlarge", + "m8idn.48xlarge", + "m8idn.96xlarge", + "r8idn.large", + "r8idn.xlarge", + "r8idn.2xlarge", + "r8idn.4xlarge", + "r8idn.8xlarge", + "r8idn.12xlarge", + "r8idn.16xlarge", + "r8idn.24xlarge", + "r8idn.32xlarge", + "r8idn.48xlarge", + "r8idn.96xlarge", + "m8idb.large", + "m8idb.xlarge", + "m8idb.2xlarge", + "m8idb.4xlarge", + "m8idb.8xlarge", + "m8idb.12xlarge", + "m8idb.16xlarge", + "m8idb.24xlarge", + "m8idb.32xlarge", + "m8idb.48xlarge", + "m8idb.96xlarge", + "r8idb.large", + "r8idb.xlarge", + "r8idb.2xlarge", + "r8idb.4xlarge", + "r8idb.8xlarge", + "r8idb.12xlarge", + "r8idb.16xlarge", + "r8idb.24xlarge", + "r8idb.32xlarge", + "r8idb.48xlarge", + "r8idb.96xlarge", + "mac-m3ultra.metal", + "m9g.large", + "m9g.xlarge", + "m9g.2xlarge", + "m9g.4xlarge", + "m9g.8xlarge", + "m9g.12xlarge", + "m9g.16xlarge", + "m9g.24xlarge", + "m9g.48xlarge", + "m9g.metal-24xl", + "m9g.metal-48xl", + "m9gd.large", + "m9gd.xlarge", + "m9gd.2xlarge", + "m9gd.4xlarge", + "m9gd.8xlarge", + "m9gd.12xlarge", + "m9gd.16xlarge", + "m9gd.24xlarge", + "m9gd.48xlarge", + "m9gd.metal-24xl", + "m9gd.metal-48xl", + "r8in.metal-48xl", + "r8in.metal-96xl", + "r8ib.metal-48xl", + "r8ib.metal-96xl", + "r8idn.metal-48xl", + "r8idn.metal-96xl", + "r8idb.metal-48xl", + "r8idb.metal-96xl", + "m8in.metal-48xl", + "m8in.metal-96xl", + "m8ib.metal-48xl", + "m8ib.metal-96xl", + "m8idn.metal-48xl", + "m8idn.metal-96xl", + "m8idb.metal-48xl", + "m8idb.metal-96xl", + "g7.2xlarge", + "g7.4xlarge", + "g7.8xlarge", + "g7.12xlarge", + "g7.24xlarge", + "g7.48xlarge", + "c9g.medium", + "c9g.large", + "c9g.xlarge", + "c9g.2xlarge", + "c9g.4xlarge", + "c9g.8xlarge", + "c9g.12xlarge", + "c9g.16xlarge", + "c9g.24xlarge", + "c9g.48xlarge", + "c9g.metal-48xl", + "c9gd.medium", + "c9gd.large", + "c9gd.xlarge", + "c9gd.2xlarge", + "c9gd.4xlarge", + "c9gd.8xlarge", + "c9gd.12xlarge", + "c9gd.16xlarge", + "c9gd.24xlarge", + "c9gd.48xlarge", + "c9gd.metal-48xl", + "r9g.medium", + "r9g.large", + "r9g.xlarge", + "r9g.2xlarge", + "r9g.4xlarge", + "r9g.8xlarge", + "r9g.12xlarge", + "r9g.16xlarge", + "r9g.24xlarge", + "r9g.48xlarge", + "r9g.metal-48xl", + "r9gd.medium", + "r9gd.large", + "r9gd.xlarge", + "r9gd.2xlarge", + "r9gd.4xlarge", + "r9gd.8xlarge", + "r9gd.12xlarge", + "r9gd.16xlarge", + "r9gd.24xlarge", + "r9gd.48xlarge", + "r9gd.metal-48xl", + "m9g.medium" ] }, "InstanceTypeHypervisor":{ @@ -48070,6 +50573,22 @@ "locationName":"item" } }, + "InstanceTypeItem":{ + "type":"structure", + "members":{ + "InstanceType":{ + "shape":"String", + "documentation":"

    The instance type or wildcard pattern (for example, t3.* or m5.large).

    ", + "locationName":"instanceType" + } + }, + "documentation":"

    An instance type name or wildcard pattern in an instance type specification.

    " + }, + "InstanceTypeItemRequest":{ + "type":"string", + "max":24, + "min":0 + }, "InstanceTypeList":{ "type":"list", "member":{"shape":"InstanceType"} @@ -48102,6 +50621,38 @@ "locationName":"item" } }, + "InstanceTypeSpecification":{ + "type":"structure", + "members":{ + "SupportedInstanceTypes":{ + "shape":"SupportedInstanceTypeSet", + "documentation":"

    The instance types that the AMI supports.

    ", + "locationName":"supportedInstanceTypeSet" + }, + "UnsupportedInstanceTypes":{ + "shape":"UnsupportedInstanceTypeSet", + "documentation":"

    The instance types that the AMI does not support.

    ", + "locationName":"unsupportedInstanceTypeSet" + } + }, + "documentation":"

    Describes the instance type compatibility rules for an AMI, including lists of supported and unsupported instance type patterns.

    " + }, + "InstanceTypeSpecificationRequest":{ + "type":"structure", + "members":{ + "SupportedInstanceTypes":{ + "shape":"SupportedInstanceTypeRequestSet", + "documentation":"

    The instance types that the AMI supports. You can specify instance type names or use wildcard patterns (for example, t3.*).

    Constraints: Maximum 100 entries. Each entry must be 1-24 characters and match the pattern ^[A-Za-z0-9_.*-]+$. Consecutive wildcard characters (**) are not allowed. Entries must be unique within each list and across both lists; duplicate entries cause the request to fail.

    ", + "locationName":"SupportedInstanceType" + }, + "UnsupportedInstanceTypes":{ + "shape":"UnsupportedInstanceTypeRequestSet", + "documentation":"

    The instance types that the AMI does not support. You can specify instance type names or use wildcard patterns (for example, t3.*).

    Constraints: Maximum 100 entries. Each entry must be 1-24 characters and match the pattern ^[A-Za-z0-9_.*-]+$. Consecutive wildcard characters (**) are not allowed. Entries must be unique within each list and across both lists; duplicate entries cause the request to fail.

    ", + "locationName":"UnsupportedInstanceType" + } + }, + "documentation":"

    The instance type specification for an AMI, which contains lists of supported and unsupported instance types that define which instance types are compatible with the AMI.

    " + }, "InstanceTypes":{ "type":"list", "member":{"shape":"String"}, @@ -48274,6 +50825,11 @@ "shape":"InterruptionType", "documentation":"

    The type of interruption policy applied to the interruptible reservation.

    ", "locationName":"interruptionType" + }, + "ZeroSizePreference":{ + "shape":"ZeroSizePreference", + "documentation":"

    Specifies how Amazon EC2 handles the interruptible Capacity Reservation when you reduce its allocation to zero instances. A value of retain keeps the interruptible Capacity Reservation active at zero capacity so that you can allocate instances to it again later. A value of default cancels the interruptible Capacity Reservation and returns the capacity to your source Capacity Reservation.

    ", + "locationName":"zeroSizePreference" } }, "documentation":"

    Represents the allocation of capacity from a source reservation to an interruptible reservation, tracking current and target instance counts for allocation management.

    " @@ -48422,6 +50978,10 @@ "locationName":"item" } }, + "IpScopeEnum":{ + "type":"string", + "enum":["private"] + }, "IpSource":{ "type":"string", "enum":[ @@ -48430,6 +50990,13 @@ "none" ] }, + "IpVersionEnum":{ + "type":"string", + "enum":[ + "ipv4", + "ipv6" + ] + }, "Ipam":{ "type":"structure", "members":{ @@ -48616,6 +51183,30 @@ "not-found" ] }, + "IpamByoipAdvertisementType":{ + "type":"string", + "documentation":"

    The advertisement type of a BYOIP route.

    ", + "enum":[ + "regional", + "global" + ] + }, + "IpamByoipCidrState":{ + "type":"string", + "documentation":"

    The state of a BYOIP CIDR.

    ", + "enum":[ + "advertised", + "deprovisioned", + "failed-deprovision", + "failed-provision", + "pending-advertising", + "pending-deprovision", + "pending-provision", + "pending-withdrawal", + "provisioned", + "provisioned-not-publicly-advertisable" + ] + }, "IpamCidrAuthorizationContext":{ "type":"structure", "members":{ @@ -48873,6 +51464,74 @@ "locationName":"item" } }, + "IpamDiscoveredRoute":{ + "type":"structure", + "members":{ + "IpamResourceDiscoveryId":{ + "shape":"IpamResourceDiscoveryId", + "documentation":"

    The ID of the IPAM resource discovery that discovered the route.

    ", + "locationName":"ipamResourceDiscoveryId" + }, + "ResourceRegion":{ + "shape":"String", + "documentation":"

    The Amazon Web Services Region where the route was discovered.

    ", + "locationName":"resourceRegion" + }, + "ResourceOwnerId":{ + "shape":"String", + "documentation":"

    The ID of the resource owner.

    ", + "locationName":"resourceOwnerId" + }, + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix of the discovered route in CIDR notation.

    ", + "locationName":"cidr" + }, + "Asn":{ + "shape":"String", + "documentation":"

    The Autonomous System Number (ASN) that originates the route.

    ", + "locationName":"asn" + }, + "State":{ + "shape":"IpamByoipCidrState", + "documentation":"

    The state of the BYOIP CIDR. Possible values:

    • advertised - The CIDR is being advertised.

    • deprovisioned - The CIDR has been deprovisioned.

    • failed-deprovision - Deprovisioning failed.

    • failed-provision - Provisioning failed.

    • pending-deprovision - Deprovisioning is in progress.

    • pending-provision - Provisioning is in progress.

    • provisioned - The CIDR is provisioned.

    • provisioned-not-publicly-advertisable - The CIDR is provisioned but not publicly advertisable.

    ", + "locationName":"state" + }, + "AdvertisementType":{ + "shape":"IpamByoipAdvertisementType", + "documentation":"

    The advertisement type of the route. Possible values:

    • regional - The IP address is advertised from a single location (regional services such as Amazon EC2).

    • global - The IP address is advertised from multiple global locations simultaneously (global services such as Amazon CloudFront).

    ", + "locationName":"advertisementType" + }, + "NetworkBorderGroup":{ + "shape":"String", + "documentation":"

    The network border group for the route.

    ", + "locationName":"networkBorderGroup" + }, + "PoolId":{ + "shape":"String", + "documentation":"

    The ID of the BYOIP pool associated with the route.

    ", + "locationName":"poolId" + }, + "IpamPoolId":{ + "shape":"String", + "documentation":"

    The ID of the IPAM pool associated with the route.

    ", + "locationName":"ipamPoolId" + }, + "SampleTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the route was last sampled.

    ", + "locationName":"sampleTime" + } + }, + "documentation":"

    Contains information about a BGP route discovered by IPAM resource discovery.

    " + }, + "IpamDiscoveredRouteSet":{ + "type":"list", + "member":{ + "shape":"IpamDiscoveredRoute", + "locationName":"item" + } + }, "IpamDiscoveryFailureCode":{ "type":"string", "enum":[ @@ -48978,6 +51637,141 @@ ] }, "IpamId":{"type":"string"}, + "IpamInternetRegistryAssociation":{ + "type":"structure", + "members":{ + "OwnerId":{ + "shape":"String", + "documentation":"

    The ID of the Amazon Web Services account that owns the internet registry association.

    ", + "locationName":"ownerId" + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the internet registry association.

    ", + "locationName":"ipamInternetRegistryAssociationId" + }, + "IpamInternetRegistryAssociationArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the internet registry association.

    ", + "locationName":"ipamInternetRegistryAssociationArn" + }, + "IpamId":{ + "shape":"IpamId", + "documentation":"

    The ID of the associated IPAM.

    ", + "locationName":"ipamId" + }, + "IpamRegion":{ + "shape":"String", + "documentation":"

    The Amazon Web Services Region of the IPAM.

    ", + "locationName":"ipamRegion" + }, + "Rir":{ + "shape":"Rir", + "documentation":"

    The Regional Internet Registry. Possible values:

    • ripe - RIPE NCC (Europe, the Middle East, and Central Asia).

    • apnic - APNIC (Asia Pacific).

    • arin - ARIN (North America).

    • lacnic - LACNIC (Latin America and the Caribbean).

    ", + "locationName":"rir" + }, + "OrganizationHandle":{ + "shape":"String", + "documentation":"

    The organization handle at the internet registry.

    ", + "locationName":"organizationHandle" + }, + "Description":{ + "shape":"String", + "documentation":"

    The description of the internet registry association.

    ", + "locationName":"description" + }, + "State":{ + "shape":"IpamInternetRegistryAssociationState", + "documentation":"

    The state of the internet registry association. Valid values: pending-activation | pending-enable | create-in-progress | create-failed | enable-in-progress | enable-complete | enable-failed | delete-in-progress | delete-complete | delete-failed.

    ", + "locationName":"state" + }, + "StateMessage":{ + "shape":"String", + "documentation":"

    A message describing the current state of the internet registry association, including additional details such as the reason for a failure.

    ", + "locationName":"stateMessage" + }, + "ChildRequestXml":{ + "shape":"String", + "documentation":"

    The XML content for the child request to be submitted to the internet registry to complete the BPKI setup.

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

    The tags assigned to the internet registry association.

    ", + "locationName":"tagSet" + } + }, + "documentation":"

    Contains information about an association between an IPAM and a Regional Internet Registry (RIR) for delegated RPKI management.

    " + }, + "IpamInternetRegistryAssociationAsn":{ + "type":"structure", + "members":{ + "Asn":{ + "shape":"String", + "documentation":"

    The Autonomous System Number.

    ", + "locationName":"asn" + }, + "LastObservedAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the ASN was last observed at the internet registry.

    ", + "locationName":"lastObservedAt" + } + }, + "documentation":"

    Contains information about an Autonomous System Number (ASN) registered at an internet registry and associated with an IPAM.

    " + }, + "IpamInternetRegistryAssociationAsnSet":{ + "type":"list", + "member":{ + "shape":"IpamInternetRegistryAssociationAsn", + "locationName":"item" + } + }, + "IpamInternetRegistryAssociationCidr":{ + "type":"structure", + "members":{ + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation.

    ", + "locationName":"cidr" + }, + "LastObservedAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the CIDR was last observed at the internet registry.

    ", + "locationName":"lastObservedAt" + } + }, + "documentation":"

    Contains information about an IP address CIDR registered at an internet registry and associated with an IPAM.

    " + }, + "IpamInternetRegistryAssociationCidrSet":{ + "type":"list", + "member":{ + "shape":"IpamInternetRegistryAssociationCidr", + "locationName":"item" + } + }, + "IpamInternetRegistryAssociationId":{"type":"string"}, + "IpamInternetRegistryAssociationSet":{ + "type":"list", + "member":{ + "shape":"IpamInternetRegistryAssociation", + "locationName":"item" + } + }, + "IpamInternetRegistryAssociationState":{ + "type":"string", + "documentation":"

    The state of an IPAM internet registry association.

    ", + "enum":[ + "pending-enable", + "create-in-progress", + "create-failed", + "enable-in-progress", + "enable-complete", + "enable-failed", + "delete-in-progress", + "delete-complete", + "delete-failed" + ] + }, "IpamManagementState":{ "type":"string", "enum":[ @@ -50400,6 +53194,316 @@ "anycast-ip-list" ] }, + "IpamRouteOriginAuthorization":{ + "type":"structure", + "members":{ + "Asn":{ + "shape":"String", + "documentation":"

    The Autonomous System Number (ASN) authorized by the ROA.

    ", + "locationName":"asn" + }, + "Prefix":{ + "shape":"String", + "documentation":"

    The IP address prefix authorized by the ROA in CIDR notation.

    ", + "locationName":"prefix" + }, + "MaxLength":{ + "shape":"Integer", + "documentation":"

    The maximum prefix length that the ASN is authorized to announce.

    ", + "locationName":"maxLength" + }, + "Match":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the ROA matches the route announcement.

    ", + "locationName":"match" + }, + "Expiration":{ + "shape":"MillisecondDateTime", + "documentation":"

    The expiration date of the ROA.

    ", + "locationName":"expiration" + } + }, + "documentation":"

    Contains information about a Route Origin Authorization (ROA) published in the RPKI. A ROA cryptographically attests that a specific ASN is authorized to originate a specific IP address prefix.

    " + }, + "IpamRouteOriginAuthorizationInfo":{ + "type":"structure", + "members":{ + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation authorized by the ROA.

    ", + "locationName":"cidr" + }, + "Asn":{ + "shape":"String", + "documentation":"

    The Autonomous System Number (ASN) authorized to originate the prefix.

    ", + "locationName":"asn" + }, + "MaxLength":{ + "shape":"Integer", + "documentation":"

    The maximum prefix length that the ASN is authorized to announce.

    ", + "locationName":"maxLength" + } + }, + "documentation":"

    Contains information about a Route Origin Authorization (ROA) currently published in the RPKI.

    " + }, + "IpamRouteOriginAuthorizationInfoSet":{ + "type":"list", + "member":{ + "shape":"IpamRouteOriginAuthorizationInfo", + "locationName":"item" + } + }, + "IpamRouteOriginAuthorizationSet":{ + "type":"list", + "member":{ + "shape":"IpamRouteOriginAuthorization", + "locationName":"item" + } + }, + "IpamRouteOverlap":{ + "type":"structure", + "members":{ + "Prefix":{ + "shape":"String", + "documentation":"

    The overlapping IP address prefix in CIDR notation.

    ", + "locationName":"prefix" + }, + "Asn":{ + "shape":"String", + "documentation":"

    The ASN originating the overlapping route.

    ", + "locationName":"asn" + }, + "DetectedAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the overlap was detected.

    ", + "locationName":"detectedAt" + } + }, + "documentation":"

    Contains information about an overlapping route detected for a BYOIP prefix.

    " + }, + "IpamRouteOverlapSet":{ + "type":"list", + "member":{ + "shape":"IpamRouteOverlap", + "locationName":"item" + }, + "max":100, + "min":0 + }, + "IpamRouteProtectionFinding":{ + "type":"structure", + "members":{ + "ResourceOwnerId":{ + "shape":"String", + "documentation":"

    The ID of the resource owner.

    ", + "locationName":"resourceOwnerId" + }, + "ResourceRegion":{ + "shape":"String", + "documentation":"

    The Amazon Web Services Region of the resource.

    ", + "locationName":"resourceRegion" + }, + "IpamPoolId":{ + "shape":"IpamPoolId", + "documentation":"

    The ID of the IPAM pool associated with the finding.

    ", + "locationName":"ipamPoolId" + }, + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation.

    ", + "locationName":"cidr" + }, + "State":{ + "shape":"IpamByoipCidrState", + "documentation":"

    The state of the BYOIP CIDR. Possible values:

    • advertised - The CIDR is being advertised.

    • deprovisioned - The CIDR has been deprovisioned.

    • failed-deprovision - Deprovisioning failed.

    • failed-provision - Provisioning failed.

    • pending-deprovision - Deprovisioning is in progress.

    • pending-provision - Provisioning is in progress.

    • provisioned - The CIDR is provisioned.

    • provisioned-not-publicly-advertisable - The CIDR is provisioned but not publicly advertisable.

    ", + "locationName":"state" + }, + "AdvertisementType":{ + "shape":"IpamByoipAdvertisementType", + "documentation":"

    The advertisement type. Possible values:

    • regional - The IP address is advertised from a single location (regional services such as Amazon EC2).

    • global - The IP address is advertised from multiple global locations simultaneously (global services such as Amazon CloudFront).

    ", + "locationName":"advertisementType" + }, + "NetworkBorderGroup":{ + "shape":"String", + "documentation":"

    The network border group.

    ", + "locationName":"networkBorderGroup" + }, + "PoolId":{ + "shape":"String", + "documentation":"

    The ID of the BYOIP pool.

    ", + "locationName":"poolId" + }, + "Asn":{ + "shape":"String", + "documentation":"

    The Autonomous System Number (ASN) that originates the route.

    ", + "locationName":"asn" + }, + "RpkiStatus":{ + "shape":"IpamRpkiStatus", + "documentation":"

    The RPKI validation status of the route. Possible values:

    • valid - The route has a matching ROA that covers the prefix and origin ASN.

    • invalid - The route has a ROA for the prefix, but the origin ASN or prefix length does not match.

    • unknown - No ROA exists for the prefix, so RPKI validation cannot be performed.

    ", + "locationName":"rpkiStatus" + }, + "RpkiStrength":{ + "shape":"IpamRpkiStrength", + "documentation":"

    The RPKI enforcement strength for the route. Possible values:

    • strict - Invalid routes are rejected.

    • permissive - Invalid routes are accepted but flagged.

    ", + "locationName":"rpkiStrength" + }, + "Roas":{ + "shape":"IpamRouteOriginAuthorizationSet", + "documentation":"

    The Route Origin Authorizations (ROAs) that cover the prefix.

    ", + "locationName":"roaSet" + }, + "RouteOverlaps":{ + "shape":"IpamRouteOverlapSet", + "documentation":"

    The overlapping routes detected for this prefix.

    ", + "locationName":"routeOverlapSet" + }, + "SampleTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the route was last sampled.

    ", + "locationName":"sampleTime" + }, + "RoaSampleTime":{ + "shape":"MillisecondDateTime", + "documentation":"

    The time when the ROA data was last sampled.

    ", + "locationName":"roaSampleTime" + } + }, + "documentation":"

    Contains information about a route protection finding, including the RPKI validation status of a BYOIP route announcement.

    " + }, + "IpamRouteProtectionFindingSet":{ + "type":"list", + "member":{ + "shape":"IpamRouteProtectionFinding", + "locationName":"item" + } + }, + "IpamRoutingPolicyRegistration":{ + "type":"structure", + "members":{ + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation authorized by the ROA.

    ", + "locationName":"cidr" + }, + "Asns":{ + "shape":"AsnList", + "documentation":"

    The Autonomous System Numbers (ASNs) authorized to originate the prefix.

    ", + "locationName":"asnSet" + }, + "PermitMoreSpecificAnnouncements":{ + "shape":"BoxedBoolean", + "documentation":"

    Specifies whether to permit more specific route announcements than the CIDR prefix. When enabled, ASNs can announce sub-prefixes of the authorized CIDR up to the specified maximum length. Default: false.

    ", + "locationName":"permitMoreSpecificAnnouncements" + }, + "MaxLength":{ + "shape":"IpamRoutingPolicyRegistrationMaxLength", + "documentation":"

    The maximum prefix length that the ASNs are authorized to announce.

    ", + "locationName":"maxLength" + }, + "Description":{ + "shape":"String", + "documentation":"

    The description of the routing policy registration.

    ", + "locationName":"description" + }, + "LatestDeltaId":{ + "shape":"String", + "documentation":"

    The ID of the most recent delta that modified this registration.

    ", + "locationName":"latestDeltaId" + }, + "State":{ + "shape":"IpamRoutingPolicyRegistrationState", + "documentation":"

    The state of the routing policy registration. Valid values: pending-activate | activate-failed | create-in-progress | create-complete | update-in-progress | update-complete | delete-in-progress | delete-complete.

    ", + "locationName":"state" + } + }, + "documentation":"

    Contains information about a routing policy registration that represents a Route Origin Authorization (ROA) managed through IPAM.

    " + }, + "IpamRoutingPolicyRegistrationDelta":{ + "type":"structure", + "members":{ + "DeltaId":{ + "shape":"String", + "documentation":"

    The unique identifier of the delta.

    ", + "locationName":"deltaId" + }, + "DeltaJson":{ + "shape":"String", + "documentation":"

    The JSON specification describing the changes applied in this delta.

    ", + "locationName":"deltaJson" + }, + "State":{ + "shape":"IpamRoutingPolicyRegistrationDeltaState", + "documentation":"

    The state of the delta. Valid values: pending | published | failed.

    ", + "locationName":"state" + }, + "StateMessage":{ + "shape":"String", + "documentation":"

    A message describing the current state, including error information if the delta failed.

    ", + "locationName":"stateMessage" + } + }, + "documentation":"

    Contains information about a routing policy registration change, including the changes applied and their publication state.

    " + }, + "IpamRoutingPolicyRegistrationDeltaSet":{ + "type":"list", + "member":{ + "shape":"IpamRoutingPolicyRegistrationDelta", + "locationName":"item" + } + }, + "IpamRoutingPolicyRegistrationDeltaState":{ + "type":"string", + "documentation":"

    The state of a routing policy registration delta.

    ", + "enum":[ + "pending", + "published", + "failed" + ] + }, + "IpamRoutingPolicyRegistrationMaxLength":{ + "type":"integer", + "max":48, + "min":0 + }, + "IpamRoutingPolicyRegistrationSet":{ + "type":"list", + "member":{ + "shape":"IpamRoutingPolicyRegistration", + "locationName":"item" + } + }, + "IpamRoutingPolicyRegistrationState":{ + "type":"string", + "documentation":"

    The state of a routing policy registration.

    ", + "enum":[ + "pending-activate", + "activate-failed", + "create-in-progress", + "create-complete", + "update-in-progress", + "update-complete", + "delete-in-progress", + "delete-complete" + ] + }, + "IpamRpkiStatus":{ + "type":"string", + "documentation":"

    The RPKI validation status of a BGP route.

    ", + "enum":[ + "valid", + "invalid", + "unknown" + ] + }, + "IpamRpkiStrength":{ + "type":"string", + "documentation":"

    The RPKI enforcement strength for route protection.

    ", + "enum":[ + "strict", + "permissive" + ] + }, "IpamScope":{ "type":"structure", "members":{ @@ -53761,7 +56865,8 @@ "enum":[ "spot", "capacity-block", - "interruptible-capacity-reservation" + "interruptible-capacity-reservation", + "on-demand" ] }, "MarketplaceProductCode":{"type":"string"}, @@ -54119,6 +57224,64 @@ } }, "MillisecondDateTime":{"type":"timestamp"}, + "ModificationQuoteCurrentConfiguration":{ + "type":"structure", + "members":{ + "InstanceCount":{ + "shape":"Integer", + "documentation":"

    The number of instances in the Capacity Reservation.

    ", + "locationName":"instanceCount" + }, + "ReservationState":{ + "shape":"String", + "documentation":"

    The current state of the Capacity Reservation.

    ", + "locationName":"reservationState" + }, + "StartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start date that the Capacity Reservation has before the quoted modification is applied.

    ", + "locationName":"startDate" + }, + "OriginalStartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start date that the Capacity Reservation was originally requested with. This value does not change when you push out the start date.

    ", + "locationName":"originalStartDate" + } + }, + "documentation":"

    Describes the configuration that a Capacity Reservation has at the time a modification quote is generated.

    " + }, + "ModificationReservationUpdate":{ + "type":"structure", + "members":{ + "NewCommitmentEndDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time at which the commitment duration will expire after the modification, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ).

    ", + "locationName":"newCommitmentEndDate" + }, + "NewStartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The start date that the Capacity Reservation will have after the modification, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ).

    ", + "locationName":"newStartDate" + }, + "NewCommitmentDuration":{ + "shape":"BoxedInteger", + "documentation":"

    The commitment duration, in seconds, that the Capacity Reservation will have after the modification.

    ", + "locationName":"newCommitmentDuration" + } + }, + "documentation":"

    Describes the changes that a Capacity Reservation modification quote will apply to a Capacity Reservation.

    " + }, + "ModificationTerms":{ + "type":"structure", + "members":{ + "ReservationUpdate":{ + "shape":"ModificationReservationUpdate", + "documentation":"

    The changes that will be applied to the Capacity Reservation if you accept the modification terms.

    ", + "locationName":"reservationUpdate" + } + }, + "documentation":"

    Describes the terms of a Capacity Reservation modification quote.

    " + }, "ModifyAccountVpcEncryptionControlRequest":{ "type":"structure", "members":{ @@ -54202,6 +57365,92 @@ } } }, + "ModifyApplicationStatusCheckRequest":{ + "type":"structure", + "required":["ApplicationStatusCheckId"], + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check to modify.

    " + }, + "Aggregation":{ + "shape":"AggregationStatusEnum", + "documentation":"

    The aggregation setting for the application status check. When set to included, the result of this check contributes to the instance-level application status reported by DescribeApplicationStatus. When set to excluded, the check runs independently and does not affect the instance-level status. Valid values: included | excluded.

    " + }, + "HealthCheckPaths":{ + "shape":"HealthCheckPathRequestList", + "documentation":"

    The health check paths to use for the application status check.

    ", + "locationName":"HealthCheckPath" + }, + "Protocol":{ + "shape":"NetworkProtocolEnum", + "documentation":"

    The protocol to use for the health check. Valid values: http | https.

    " + }, + "Port":{ + "shape":"PortNumber", + "documentation":"

    The port to use for the health check. Valid values: 1 to 65535.

    " + }, + "Path":{ + "shape":"String", + "documentation":"

    The URL path to use for the health check HTTP request (for example, /health or /status).

    " + }, + "DeviceIndex":{ + "shape":"Integer", + "documentation":"

    The index of the network device to use for the health check. The value must be greater than or equal to 0.

    " + }, + "IpVersion":{ + "shape":"IpVersionEnum", + "documentation":"

    The IP version to use for the health check. Valid values: ipv4 and ipv6.

    " + }, + "IpScope":{ + "shape":"IpScopeEnum", + "documentation":"

    The IP scope to use for the health check. Valid value: private.

    " + }, + "Interval":{ + "shape":"Integer", + "documentation":"

    The interval, in seconds, between health checks. Valid value: 60.

    " + }, + "Timeout":{ + "shape":"Integer", + "documentation":"

    The amount of time, in seconds, to wait for a health check response before considering it failed. Valid values: 1 to 30. The value must be less than Interval.

    " + }, + "FailureThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive failed health checks before the application status is considered impaired. The value must be greater than 0.

    " + }, + "SuccessThreshold":{ + "shape":"Integer", + "documentation":"

    The number of consecutive successful health checks before the application status is considered healthy. The value must be greater than 0.

    " + }, + "StatusCodeMatcher":{ + "shape":"String", + "documentation":"

    The HTTP status codes that indicate a successful health check response. Specify a comma-separated list of individual status codes or ranges, for example, 200,202,300-399. For a range, the first value must be less than the second value. Maximum length: 64 characters.

    " + }, + "InitializationGracePeriodSeconds":{ + "shape":"InitializationGracePeriodSeconds", + "documentation":"

    The number of seconds to wait before starting health checks after an instance is launched. Valid values: 1 to 600.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you retry a request with the same token, the service ignores the request but does not return an error. For more information, see Ensuring idempotency.

    ", + "idempotencyToken":true + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "ModifyApplicationStatusCheckResult":{ + "type":"structure", + "members":{ + "ApplicationStatusCheck":{ + "shape":"ApplicationStatusCheckResponseObject", + "documentation":"

    Information about the modified application status check.

    ", + "locationName":"applicationStatusCheck" + } + } + }, "ModifyAvailabilityZoneGroupRequest":{ "type":"structure", "required":[ @@ -54311,6 +57560,18 @@ "InstanceMatchCriteria":{ "shape":"InstanceMatchCriteria", "documentation":"

    The matching criteria (instance eligibility) that you want to use in the modified Capacity Reservation. If you change the instance eligibility of an existing Capacity Reservation from targeted to open, any running instances that match the attributes of the Capacity Reservation, have the CapacityReservationPreference set to open, and are not yet running in the Capacity Reservation, will automatically use the modified Capacity Reservation.

    To modify the instance eligibility, the Capacity Reservation must be completely idle (zero usage).

    " + }, + "AcceptModificationTerms":{ + "shape":"Boolean", + "documentation":"

    Indicates that you accept the modification terms of the quote identified by QuoteId. To apply a quoted modification, set this parameter to true.

    " + }, + "StartDate":{ + "shape":"MillisecondDateTime", + "documentation":"

    The new start date for the Capacity Reservation, in the ISO8601 format in the UTC time zone (YYYY-MM-DDThh:mm:ss.sssZ). Applies to future-dated Capacity Reservations only. Requires a quote from CreateCapacityReservationDateChangeQuote; pass the quote ID in QuoteId with AcceptModificationTerms set to true.

    " + }, + "QuoteId":{ + "shape":"CapacityReservationModificationQuoteId", + "documentation":"

    The ID of the quote that describes the modification you want to apply. Generate a quote by using CreateCapacityReservationDateChangeQuote. The quote must be in the active state, and each quote can be used only once.

    " } } }, @@ -54321,6 +57582,16 @@ "shape":"Boolean", "documentation":"

    Returns true if the request succeeds; otherwise, it returns an error.

    ", "locationName":"return" + }, + "AdjustmentStatus":{ + "shape":"CapacityReservationAdjustmentStatus", + "documentation":"

    The status of the requested modification. For a description of each possible value, see the adjustmentStatus field of the CapacityReservation data type.

    ", + "locationName":"adjustmentStatus" + }, + "AdjustmentDetails":{ + "shape":"CapacityReservationAdjustmentDetails", + "documentation":"

    The configuration that the Capacity Reservation will have after the adjustment is applied.

    ", + "locationName":"adjustmentDetails" } } }, @@ -55614,6 +58885,64 @@ } } }, + "ModifyIpamRoutingPolicyRegistrationRequest":{ + "type":"structure", + "required":[ + "IpamInternetRegistryAssociationId", + "Cidr", + "Asns" + ], + "members":{ + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the operation, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + }, + "IpamInternetRegistryAssociationId":{ + "shape":"IpamInternetRegistryAssociationId", + "documentation":"

    The ID of the IPAM internet registry association.

    " + }, + "Cidr":{ + "shape":"String", + "documentation":"

    The IP address prefix in CIDR notation identifying the routing policy registration to modify.

    " + }, + "Asns":{ + "shape":"AsnList", + "documentation":"

    The updated list of Autonomous System Numbers (ASNs) authorized to originate the prefix.

    ", + "locationName":"Asn" + }, + "PermitMoreSpecificAnnouncements":{ + "shape":"BoxedBoolean", + "documentation":"

    Specifies whether to permit more specific route announcements than the CIDR prefix. Default: false.

    " + }, + "MaxLength":{ + "shape":"IpamRoutingPolicyRegistrationMaxLength", + "documentation":"

    The new maximum prefix length that the ASNs are authorized to announce. Must be greater than or equal to the prefix length of the CIDR.

    " + }, + "Description":{ + "shape":"String", + "documentation":"

    A new description for the routing policy registration.

    " + }, + "Force":{ + "shape":"BoxedBoolean", + "documentation":"

    Forces the modification even if it conflicts with an announced route. Default: false.

    " + }, + "ClientToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the operation ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + } + }, + "ModifyIpamRoutingPolicyRegistrationResult":{ + "type":"structure", + "members":{ + "IpamRoutingPolicyRegistrationDelta":{ + "shape":"IpamRoutingPolicyRegistrationDelta", + "documentation":"

    Information about the routing policy registration delta created by this modification.

    ", + "locationName":"ipamRoutingPolicyRegistrationDelta" + } + } + }, "ModifyIpamScopeRequest":{ "type":"structure", "required":["IpamScopeId"], @@ -56437,6 +59766,45 @@ }, "documentation":"

    The transit gateway options.

    " }, + "ModifyTransitGatewayPolicyTableEntryRequest":{ + "type":"structure", + "required":[ + "TransitGatewayPolicyTableId", + "PolicyRuleNumber" + ], + "members":{ + "TransitGatewayPolicyTableId":{ + "shape":"TransitGatewayPolicyTableId", + "documentation":"

    The ID of the transit gateway policy table.

    " + }, + "PolicyRuleNumber":{ + "shape":"String", + "documentation":"

    The rule number of the policy table entry to modify.

    " + }, + "PolicyRule":{ + "shape":"TransitGatewayRequestPolicyRule", + "documentation":"

    The updated matching criteria for the policy table entry. Unspecified fields retain their current values.

    " + }, + "TargetRouteTableId":{ + "shape":"TransitGatewayRouteTableId", + "documentation":"

    The ID of the transit gateway route table to use for traffic matching this rule.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "ModifyTransitGatewayPolicyTableEntryResult":{ + "type":"structure", + "members":{ + "TransitGatewayPolicyTableEntry":{ + "shape":"TransitGatewayPolicyTableEntry", + "documentation":"

    Describes a transit gateway policy table entry

    ", + "locationName":"transitGatewayPolicyTableEntry" + } + } + }, "ModifyTransitGatewayPrefixListReferenceRequest":{ "type":"structure", "required":[ @@ -56547,7 +59915,7 @@ }, "Ipv6Support":{ "shape":"Ipv6SupportValue", - "documentation":"

    Enable or disable IPv6 support. The default is enable.

    " + "documentation":"

    Specifies whether IPv6 support is enabled for the attachment. When enabled, the transit gateway network interface receives an IPv6 address. When you enable route propagation, IPv6 VPC CIDRs propagate to the transit gateway route tables. When disabled, the network interface does not receive an IPv6 address, and IPv6 routes do not propagate. The setting does not filter IPv6 traffic.

    " }, "ApplianceModeSupport":{ "shape":"ApplianceModeSupportValue", @@ -58608,6 +61976,11 @@ "shape":"MaximumEnaQueueCountPerInterface", "documentation":"

    The maximum number of the ENA queues for each interface.

    ", "locationName":"maximumEnaQueueCountPerInterface" + }, + "InterfaceTypes":{ + "shape":"NetworkCardInterfaceTypeList", + "documentation":"

    The supported interface types for the network card.

    ", + "locationName":"interfaceTypeSet" } }, "documentation":"

    Describes the network card support of the instance type.

    " @@ -58619,6 +61992,22 @@ "locationName":"item" } }, + "NetworkCardInterfaceType":{ + "type":"string", + "enum":[ + "interface", + "efa", + "efa-only", + "secondary" + ] + }, + "NetworkCardInterfaceTypeList":{ + "type":"list", + "member":{ + "shape":"NetworkCardInterfaceType", + "locationName":"item" + } + }, "NetworkInfo":{ "type":"structure", "members":{ @@ -59607,6 +62996,13 @@ } }, "NetworkPerformance":{"type":"string"}, + "NetworkProtocolEnum":{ + "type":"string", + "enum":[ + "http", + "https" + ] + }, "NeuronDeviceCoreCount":{"type":"integer"}, "NeuronDeviceCoreInfo":{ "type":"structure", @@ -60331,7 +63727,10 @@ }, "PayerResponsibilityScope":{ "type":"string", - "enum":["vpc-endpoint-charges"] + "enum":[ + "vpc-endpoint-charges", + "resource-gateway-charges" + ] }, "PayerResponsibilitySet":{ "type":"list", @@ -60344,6 +63743,7 @@ "type":"string", "enum":[ "vpc-endpoint-account", + "resource-gateway-account", "vpc-endpoint-service-account" ] }, @@ -60959,6 +64359,11 @@ "max":65535, "min":0 }, + "PortNumber":{ + "type":"integer", + "max":65535, + "min":1 + }, "PortRange":{ "type":"structure", "members":{ @@ -62990,6 +66395,34 @@ } } }, + "ReplaceImageInstanceTypeSpecificationRequest":{ + "type":"structure", + "required":["ImageId"], + "members":{ + "ImageId":{ + "shape":"ImageId", + "documentation":"

    The ID of the AMI.

    " + }, + "InstanceTypeSpecification":{ + "shape":"InstanceTypeSpecificationRequest", + "documentation":"

    The instance type specification to set on the AMI. Omit this parameter to remove the existing instance type specification.

    " + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "ReplaceImageInstanceTypeSpecificationResult":{ + "type":"structure", + "members":{ + "ReturnValue":{ + "shape":"Boolean", + "documentation":"

    Returns true if the request succeeds; otherwise, it returns an error.

    ", + "locationName":"returnValue" + } + } + }, "ReplaceNetworkAclAssociationRequest":{ "type":"structure", "required":[ @@ -64015,27 +67448,86 @@ }, "documentation":"

    The cost associated with the Reserved Instance.

    " }, + "ReservedCapacityAllocationStrategy":{ + "type":"string", + "enum":["prioritized"] + }, + "ReservedCapacityFallbackMarketType":{ + "type":"string", + "enum":["on-demand"] + }, + "ReservedCapacityFallbackMarketTypeList":{ + "type":"list", + "member":{ + "shape":"ReservedCapacityFallbackMarketType", + "locationName":"item" + } + }, + "ReservedCapacityFallbackOptions":{ + "type":"structure", + "members":{ + "MarketTypes":{ + "shape":"ReservedCapacityFallbackMarketTypeList", + "documentation":"

    The instance purchasing options to fall back to when the reserved capacity is not enough to meet the target capacity. The only supported value is on-demand, which launches On-Demand Instances to fulfill the remaining target capacity.

    ", + "locationName":"marketTypeSet" + } + }, + "documentation":"

    Describes the fallback behavior for an EC2 Fleet that uses reserved capacity when the reserved capacity is not enough to meet the target capacity. If you don't specify fallback options, EC2 Fleet does not fall back to any other market type after the specified reservation types are exhausted.

    " + }, + "ReservedCapacityFallbackOptionsRequest":{ + "type":"structure", + "members":{ + "MarketTypes":{ + "shape":"ReservedCapacityFallbackMarketTypeList", + "documentation":"

    The instance purchasing options to fall back to when the reserved capacity is not enough to meet the target capacity. The only supported value is on-demand, which launches On-Demand Instances to fulfill the remaining target capacity.

    ", + "locationName":"MarketType" + } + }, + "documentation":"

    Describes the fallback behavior for an EC2 Fleet that uses reserved capacity when the reserved capacity is not enough to meet the target capacity. If you don't specify fallback options, EC2 Fleet does not fall back to any other market type after the specified reservation types are exhausted.

    " + }, "ReservedCapacityOptions":{ "type":"structure", "members":{ + "AllocationStrategy":{ + "shape":"ReservedCapacityAllocationStrategy", + "documentation":"

    The strategy that determines the order in which EC2 Fleet launches instances across the reservation types that you specify. The only supported value is prioritized, which launches instances in the priority order that you specify in your launch template overrides. If you don't specify an allocation strategy, instances are launched in a random order.

    ", + "locationName":"allocationStrategy" + }, "ReservationTypes":{ "shape":"ReservationTypeList", "documentation":"

    The types of Capacity Reservations used for fulfilling the EC2 Fleet request.

    ", "locationName":"reservationTypeSet" + }, + "ReservedCapacityFallbackOptions":{ + "shape":"ReservedCapacityFallbackOptions", + "documentation":"

    The fallback behavior for the EC2 Fleet when there is not enough reserved capacity available to meet the target capacity.

    ", + "locationName":"reservedCapacityFallbackOptions" } }, - "documentation":"

    Defines EC2 Fleet preferences for utilizing reserved capacity when DefaultTargetCapacityType is set to reserved-capacity.

    " + "documentation":"

    Defines EC2 Fleet preferences for utilizing reserved capacity when DefaultTargetCapacityType is set to reserved-capacity. EC2 Fleet can fulfill reserved capacity using On-Demand Capacity Reservations, Capacity Blocks for ML, and interruptible Capacity Reservations.

    " }, "ReservedCapacityOptionsRequest":{ "type":"structure", "members":{ + "AllocationStrategy":{ + "shape":"ReservedCapacityAllocationStrategy", + "documentation":"

    The strategy that determines the order in which EC2 Fleet launches instances across the reservation types that you specify. The only supported value is prioritized, which launches instances in the priority order that you specify in your launch template overrides. If you don't specify an allocation strategy, instances are launched in a random order.

    " + }, "ReservationTypes":{ "shape":"ReservationTypeListRequest", - "documentation":"

    The types of Capacity Reservations to use for fulfilling the EC2 Fleet request.

    ", + "documentation":"

    The types of Capacity Reservations to use for fulfilling the EC2 Fleet request. This is an ordered list: EC2 Fleet attempts to launch instances into each Capacity Reservation type in the order that you specify them before moving on to the next type.

    ", "locationName":"ReservationType" + }, + "CapacityReservationTarget":{ + "shape":"FleetCapacityReservationTargetRequest", + "documentation":"

    The Capacity Reservations or Capacity Reservation Resource Groups to use for fulfilling the EC2 Fleet request. You can specify Capacity Reservation IDs or a Capacity Reservation Resource Group ARN, but not both.

    " + }, + "ReservedCapacityFallbackOptions":{ + "shape":"ReservedCapacityFallbackOptionsRequest", + "documentation":"

    The fallback behavior for the EC2 Fleet when there is not enough reserved capacity available to meet the target capacity. This member takes a ReservedCapacityFallbackOptionsRequest structure, in which you set MarketTypes to the instance purchasing options to fall back to.

    " } }, - "documentation":"

    Defines EC2 Fleet preferences for utilizing reserved capacity when DefaultTargetCapacityType is set to reserved-capacity.

    This configuration can only be used if the EC2 Fleet is of type instant.

    When you specify ReservedCapacityOptions, you must also set DefaultTargetCapacityType to reserved-capacity in the TargetCapacitySpecification.

    For more information about Interruptible Capacity Reservations, see Launch instances into an Interruptible Capacity Reservation in the Amazon EC2 User Guide.

    " + "documentation":"

    Defines EC2 Fleet preferences for utilizing reserved capacity when DefaultTargetCapacityType is set to reserved-capacity. EC2 Fleet can fulfill reserved capacity using On-Demand Capacity Reservations, Capacity Blocks for ML, and interruptible Capacity Reservations.

    This configuration can only be used if the EC2 Fleet is of type instant.

    When you specify ReservedCapacityOptions, you must also set DefaultTargetCapacityType to reserved-capacity in the TargetCapacitySpecification.

    For more information about interruptible Capacity Reservations, see Launch instances into an interruptible Capacity Reservation in the Amazon EC2 User Guide.

    " }, "ReservedInstanceIdSet":{ "type":"list", @@ -64704,6 +68196,7 @@ "min":1 }, "ResourceConfigurationArn":{"type":"string"}, + "ResourceGroupName":{"type":"string"}, "ResourceIdList":{ "type":"list", "member":{"shape":"TaggableResourceId"} @@ -64852,13 +68345,16 @@ "ipam-prefix-list-resolver", "ipam-policy", "ipam-prefix-list-resolver-target", + "ipam-internet-registry-association", "secondary-interface", "secondary-network", "secondary-subnet", "capacity-manager-data-export", "vpn-concentrator", "ipam-pool-allocation", - "capacity-reservation-cancellation-quote" + "capacity-reservation-cancellation-quote", + "application-status-check", + "capacity-reservation-modification-quote" ] }, "ResourceTypeOption":{ @@ -65616,6 +69112,16 @@ "locationName":"item" } }, + "Rir":{ + "type":"string", + "documentation":"

    The Regional Internet Registry (RIR).

    ", + "enum":[ + "ripe", + "apnic", + "arin", + "lacnic" + ] + }, "RoleId":{"type":"string"}, "RootDeviceType":{ "type":"string", @@ -67909,9 +71415,11 @@ "members":{ "Value":{ "shape":"SecureBlob", + "documentation":"

    The attribute value.

    ", "locationName":"value" } - } + }, + "documentation":"

    Describes a value for a resource attribute that is a Base64-encoded binary data object.

    " }, "SecurityGroup":{ "type":"structure", @@ -68360,6 +71868,10 @@ "type":"string", "sensitive":true }, + "SensitiveString":{ + "type":"string", + "sensitive":true + }, "SensitiveUrl":{ "type":"string", "sensitive":true @@ -70919,6 +74431,34 @@ "locationName":"item" } }, + "SuccessfulAssociationResponseObject":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check.

    ", + "locationName":"applicationStatusCheckId" + }, + "AssociationType":{ + "shape":"String", + "documentation":"

    The type of association. Valid values: EC2TAG and INSTANCE_ID.

    ", + "locationName":"associationType" + }, + "AssociationValue":{ + "shape":"String", + "documentation":"

    The association value. For EC2TAG, the value is formatted as key=value. For INSTANCE_ID, the value is the instance ID.

    ", + "locationName":"associationValue" + } + }, + "documentation":"

    Describes a successful application status check association.

    " + }, + "SuccessfulAssociationResponseSet":{ + "type":"list", + "member":{ + "shape":"SuccessfulAssociationResponseObject", + "locationName":"item" + } + }, "SuccessfulInstanceCreditSpecificationItem":{ "type":"structure", "members":{ @@ -70955,6 +74495,34 @@ "locationName":"item" } }, + "SuccessfulSuppressionResponseObject":{ + "type":"structure", + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The ID of the instance.

    ", + "locationName":"instanceId" + }, + "SuppressAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when suppression started.

    ", + "locationName":"suppressAt" + }, + "ResumeAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when suppression ends and health checks resume.

    ", + "locationName":"resumeAt" + } + }, + "documentation":"

    Describes a successful application status check suppression.

    " + }, + "SuccessfulSuppressionResponseSet":{ + "type":"list", + "member":{ + "shape":"SuccessfulSuppressionResponseObject", + "locationName":"item" + } + }, "SummaryStatus":{ "type":"string", "enum":[ @@ -70980,6 +74548,22 @@ } }, "SupportedInRegion":{"type":"boolean"}, + "SupportedInstanceTypeRequestSet":{ + "type":"list", + "member":{ + "shape":"InstanceTypeItemRequest", + "locationName":"Item" + }, + "max":100, + "min":0 + }, + "SupportedInstanceTypeSet":{ + "type":"list", + "member":{ + "shape":"InstanceTypeItem", + "locationName":"item" + } + }, "SupportedIpAddressTypes":{ "type":"list", "member":{ @@ -72135,6 +75719,11 @@ "documentation":"

    The ID of the route table for the transit gateway.

    ", "locationName":"transitGatewayRouteTableId" }, + "TransitGatewayPolicyTableId":{ + "shape":"String", + "documentation":"

    The ID of the transit gateway policy table associated with the attachment.

    ", + "locationName":"transitGatewayPolicyTableId" + }, "State":{ "shape":"TransitGatewayAssociationState", "documentation":"

    The state of the association.

    ", @@ -73179,7 +76768,7 @@ }, "SourcePortRange":{ "shape":"String", - "documentation":"

    The port range for the transit gateway policy rule. Currently this is set to * (all).

    ", + "documentation":"

    The source port or port range for the transit gateway policy rule.

    ", "locationName":"sourcePortRange" }, "DestinationCidrBlock":{ @@ -73189,7 +76778,7 @@ }, "DestinationPortRange":{ "shape":"String", - "documentation":"

    The port range for the transit gateway policy rule. Currently this is set to * (all).

    ", + "documentation":"

    The destination port or port range for the transit gateway policy rule.

    ", "locationName":"destinationPortRange" }, "Protocol":{ @@ -73307,6 +76896,11 @@ "shape":"TransitGatewayRouteTableId", "documentation":"

    The ID of the target route table.

    ", "locationName":"targetRouteTableId" + }, + "State":{ + "shape":"TransitGatewayPolicyTableEntryState", + "documentation":"

    The state of the transit gateway policy table entry.

    ", + "locationName":"state" } }, "documentation":"

    Describes a transit gateway policy table entry

    " @@ -73318,6 +76912,13 @@ "locationName":"item" } }, + "TransitGatewayPolicyTableEntryState":{ + "type":"string", + "enum":[ + "active", + "deleted" + ] + }, "TransitGatewayPolicyTableId":{"type":"string"}, "TransitGatewayPolicyTableIdStringList":{ "type":"list", @@ -73502,6 +77103,50 @@ }, "documentation":"

    Describes the options for a transit gateway.

    " }, + "TransitGatewayRequestPolicyRule":{ + "type":"structure", + "members":{ + "SourceCidrBlock":{ + "shape":"String", + "documentation":"

    The source CIDR block for the policy rule.

    " + }, + "SourcePortRange":{ + "shape":"String", + "documentation":"

    The source port or port range for the policy rule. You can specify a port range only when Protocol is 6 (TCP) or 17 (UDP); for all other protocols, this value must be *.

    " + }, + "DestinationCidrBlock":{ + "shape":"String", + "documentation":"

    The destination CIDR block for the policy rule.

    " + }, + "DestinationPortRange":{ + "shape":"String", + "documentation":"

    The destination port or port range for the policy rule. You can specify a port range only when Protocol is 6 (TCP) or 17 (UDP); for all other protocols, this value must be *.

    " + }, + "Protocol":{ + "shape":"String", + "documentation":"

    The protocol for the policy rule. Valid values are 1 (ICMP), 6 (TCP), 17 (UDP), 47 (GRE), or * for all protocols.

    " + }, + "MetaData":{ + "shape":"TransitGatewayRequestPolicyRuleMetaData", + "documentation":"

    The metadata key-value pair for the policy rule.

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

    The matching criteria for a transit gateway policy table entry.

    " + }, + "TransitGatewayRequestPolicyRuleMetaData":{ + "type":"structure", + "members":{ + "MetaDataKey":{ + "shape":"String", + "documentation":"

    The key of the metadata pair for the policy rule.

    " + }, + "MetaDataValue":{ + "shape":"String", + "documentation":"

    The value of the metadata pair for the policy rule.

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

    A metadata key-value pair for a transit gateway policy rule.

    " + }, "TransitGatewayRoute":{ "type":"structure", "members":{ @@ -74267,7 +77912,8 @@ "t2", "t3", "t3a", - "t4g" + "t4g", + "t8i" ] }, "UnlockSnapshotRequest":{ @@ -74320,6 +77966,39 @@ } } }, + "UnsuccessfulAssociationResponseObject":{ + "type":"structure", + "members":{ + "ApplicationStatusCheckId":{ + "shape":"ApplicationStatusCheckId", + "documentation":"

    The ID of the application status check.

    ", + "locationName":"applicationStatusCheckId" + }, + "AssociationType":{ + "shape":"String", + "documentation":"

    The type of association. Valid values: EC2TAG and INSTANCE_ID.

    ", + "locationName":"associationType" + }, + "AssociationValue":{ + "shape":"String", + "documentation":"

    The association value. For EC2TAG, the value is formatted as key=value. For INSTANCE_ID, the value is the instance ID.

    ", + "locationName":"associationValue" + }, + "Reason":{ + "shape":"String", + "documentation":"

    The reason the association failed.

    ", + "locationName":"reason" + } + }, + "documentation":"

    Describes an unsuccessful application status check association.

    " + }, + "UnsuccessfulAssociationResponseSet":{ + "type":"list", + "member":{ + "shape":"UnsuccessfulAssociationResponseObject", + "locationName":"item" + } + }, "UnsuccessfulInstanceCreditSpecificationErrorCode":{ "type":"string", "enum":[ @@ -74414,6 +78093,55 @@ "locationName":"item" } }, + "UnsuccessfulSuppressionResponseObject":{ + "type":"structure", + "members":{ + "InstanceId":{ + "shape":"InstanceId", + "documentation":"

    The ID of the instance.

    ", + "locationName":"instanceId" + }, + "SuppressAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when suppression was attempted.

    ", + "locationName":"suppressAt" + }, + "ResumeAt":{ + "shape":"MillisecondDateTime", + "documentation":"

    The date and time when health checks would have resumed.

    ", + "locationName":"resumeAt" + }, + "Reason":{ + "shape":"String", + "documentation":"

    The reason the suppression failed.

    ", + "locationName":"reason" + } + }, + "documentation":"

    Describes an unsuccessful application status check suppression.

    " + }, + "UnsuccessfulSuppressionResponseSet":{ + "type":"list", + "member":{ + "shape":"UnsuccessfulSuppressionResponseObject", + "locationName":"item" + } + }, + "UnsupportedInstanceTypeRequestSet":{ + "type":"list", + "member":{ + "shape":"InstanceTypeItemRequest", + "locationName":"Item" + }, + "max":100, + "min":0 + }, + "UnsupportedInstanceTypeSet":{ + "type":"list", + "member":{ + "shape":"InstanceTypeItem", + "locationName":"item" + } + }, "UpdateCapacityManagerMonitoredTagKeysRequest":{ "type":"structure", "members":{ @@ -74484,10 +78212,7 @@ }, "UpdateInterruptibleCapacityReservationAllocationRequest":{ "type":"structure", - "required":[ - "CapacityReservationId", - "TargetInstanceCount" - ], + "required":["CapacityReservationId"], "members":{ "CapacityReservationId":{ "shape":"CapacityReservationId", @@ -74500,6 +78225,10 @@ "DryRun":{ "shape":"Boolean", "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response.

    " + }, + "ZeroSizePreference":{ + "shape":"ZeroSizePreference", + "documentation":"

    Specifies the updated behavior for the interruptible Capacity Reservation when you reduce its allocation to zero instances. Specify retain to keep the interruptible Capacity Reservation active at zero capacity so that you can allocate instances to it again later. Specify default to cancel the interruptible Capacity Reservation and return the capacity to your source Capacity Reservation.

    " } } }, @@ -74813,6 +78542,31 @@ }, "documentation":"

    Describes the vCPU configurations for the instance type.

    " }, + "ValidateSecurityGroupQuotasForInterfaceRequest":{ + "type":"structure", + "required":["SecurityGroupIds"], + "members":{ + "SecurityGroupIds":{ + "shape":"SecurityGroupIdList", + "documentation":"

    The IDs of the security groups to validate for association with a single network interface. You must specify at least one ID, and each ID must be unique. The number of IDs cannot exceed the maximum number of security groups allowed per network interface.

    ", + "locationName":"SecurityGroupId" + }, + "DryRun":{ + "shape":"Boolean", + "documentation":"

    Checks whether you have the required permissions for the action, without actually making the request, and provides an error response. If you have the required permissions, the error response is DryRunOperation. Otherwise, it is UnauthorizedOperation.

    " + } + } + }, + "ValidateSecurityGroupQuotasForInterfaceResult":{ + "type":"structure", + "members":{ + "Valid":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the specified security groups can be associated with a single network interface without exceeding the quotas. If associating the security groups would exceed a quota, the operation returns an error.

    ", + "locationName":"valid" + } + } + }, "ValidationError":{ "type":"structure", "members":{ @@ -75983,6 +79737,16 @@ "documentation":"

    The Amazon EBS Provisioned Rate for Volume Initialization (volume initialization rate) specified for the volume during creation, in MiB/s. If no volume initialization rate was specified, the value is null.

    ", "locationName":"volumeInitializationRate" }, + "VolumeArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the volume.

    ", + "locationName":"volumeArn" + }, + "OwnerId":{ + "shape":"String", + "documentation":"

    The ID of the Amazon Web Services account that owns the volume.

    ", + "locationName":"ownerId" + }, "VolumeId":{ "shape":"String", "documentation":"

    The ID of the volume.

    ", @@ -77468,7 +81232,8 @@ "Gateway", "GatewayLoadBalancer", "Resource", - "ServiceNetwork" + "ServiceNetwork", + "Tunnel" ] }, "VpcFlowLogId":{"type":"string"}, @@ -77683,7 +81448,8 @@ "type":"string", "enum":[ "pending", - "available" + "available", + "deleting" ] }, "VpcTenancy":{ @@ -78286,6 +82052,13 @@ "locationName":"item" } }, + "ZeroSizePreference":{ + "type":"string", + "enum":[ + "retain", + "default" + ] + }, "ZoneIdStringList":{ "type":"list", "member":{ diff --git a/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java b/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java index 3ae2c4dc5c6e..4bc8b2350422 100644 --- a/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java +++ b/services/ec2/src/test/java/software/amazon/awssdk/services/ec2/transform/internal/GeneratePreSignUrlInterceptorTest.java @@ -142,7 +142,7 @@ private static void addSraAttributes(ExecutionAttributes attrs, AwsBasicCredenti attrs.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEMES, authSchemes); attrs.putAttribute(SdkInternalExecutionAttribute.IDENTITY_PROVIDERS, identityProviders); attrs.putAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER, - request -> Collections.singletonList( + (request, executionAttributes) -> Collections.singletonList( software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption.builder() .schemeId(authScheme.schemeId()) .putSignerProperty(software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner diff --git a/services/ec2instanceconnect/pom.xml b/services/ec2instanceconnect/pom.xml index 76fdd19129e6..d04261a2e98d 100644 --- a/services/ec2instanceconnect/pom.xml +++ b/services/ec2instanceconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ec2instanceconnect AWS Java SDK :: Services :: EC2 Instance Connect diff --git a/services/ec2instanceconnect/src/main/resources/codegen-resources/customization.config b/services/ec2instanceconnect/src/main/resources/codegen-resources/customization.config index c2457f7c37ab..0db3279e44b0 100644 --- a/services/ec2instanceconnect/src/main/resources/codegen-resources/customization.config +++ b/services/ec2instanceconnect/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true - } diff --git a/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8382aae79671 --- /dev/null +++ b/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-instance-connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-instance-connect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-instance-connect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ec2-instance-connect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bedf00589356..000000000000 --- a/services/ec2instanceconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ec2-instance-connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ec2-instance-connect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ec2-instance-connect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ec2-instance-connect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ecr/pom.xml b/services/ecr/pom.xml index 56cb19648ed1..cf40bc47498f 100644 --- a/services/ecr/pom.xml +++ b/services/ecr/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ecr AWS Java SDK :: Services :: Amazon EC2 Container Registry diff --git a/services/ecr/src/main/resources/codegen-resources/customization.config b/services/ecr/src/main/resources/codegen-resources/customization.config index 7bc9d5f27c4e..36000c58599a 100644 --- a/services/ecr/src/main/resources/codegen-resources/customization.config +++ b/services/ecr/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "describeRepositories", "getAuthorizationToken" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ecr/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ecr/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c2abc7f003a7 --- /dev/null +++ b/services/ecr/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,326 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 24, + "nodes": "/////wAAAAH/////AAAAAAAAABcAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAABQAAAAGAAAABAAAABQAAAAHAAAABQAAABQAAAAIAAAABgAAABQAAAAJAAAABwAAABQAAAAKAAAACAAAABQAAAALAAAACQAAABQAAAAMAAAACgAAABQAAAANAAAACwAAABAAAAAOAAAADQAAAA8F9eEEAAAADgX14QsF9eEMAAAADAAAABIAAAARAAAADQX14QkF9eEKAAAADQAAABMF9eEGAAAADgX14QgF9eEJAAAACwAAABYAAAAVAAAADQX14QUF9eEEAAAADQX14QcF9eEGAAAACwX14QEAAAAYAAAADQX14QIF9eED" +} \ No newline at end of file diff --git a/services/ecr/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ecr/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3594031049dd..000000000000 --- a/services/ecr/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,1720 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/ecr/src/main/resources/codegen-resources/service-2.json b/services/ecr/src/main/resources/codegen-resources/service-2.json index d96a73ae6a0e..c636772c1fa1 100644 --- a/services/ecr/src/main/resources/codegen-resources/service-2.json +++ b/services/ecr/src/main/resources/codegen-resources/service-2.json @@ -4208,7 +4208,7 @@ "ReplicationRuleList":{ "type":"list", "member":{"shape":"ReplicationRule"}, - "max":10, + "max":25, "min":0 }, "ReplicationStatus":{ diff --git a/services/ecrpublic/pom.xml b/services/ecrpublic/pom.xml index d76f9b8c89e4..9f5cb91c1e9c 100644 --- a/services/ecrpublic/pom.xml +++ b/services/ecrpublic/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ecrpublic AWS Java SDK :: Services :: ECR PUBLIC diff --git a/services/ecrpublic/src/main/resources/codegen-resources/customization.config b/services/ecrpublic/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ecrpublic/src/main/resources/codegen-resources/customization.config +++ b/services/ecrpublic/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ecrpublic/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ecrpublic/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a5f3c535ba4d --- /dev/null +++ b/services/ecrpublic/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-public-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-public-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecr-public.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-public.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.ecr-public.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAAAAAcF9eELAAAABQAAAAgF9eEKAAAABwX14QgF9eEJAAAABAAAAAsAAAAKAAAABgX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ecrpublic/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ecrpublic/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bf1472a7a341..000000000000 --- a/services/ecrpublic/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-public-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-public-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://ecr-public.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-public.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.ecr-public.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ecs/pom.xml b/services/ecs/pom.xml index 6a54f889537c..153a2dbb0c37 100644 --- a/services/ecs/pom.xml +++ b/services/ecs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ecs AWS Java SDK :: Services :: Amazon EC2 Container Service diff --git a/services/ecs/src/main/resources/codegen-resources/customization.config b/services/ecs/src/main/resources/codegen-resources/customization.config index bd024bf3aca1..ccbc51ea8f1b 100644 --- a/services/ecs/src/main/resources/codegen-resources/customization.config +++ b/services/ecs/src/main/resources/codegen-resources/customization.config @@ -15,6 +15,5 @@ "registerContainerInstance", "submitContainerStateChange", "submitTaskStateChange" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ecs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ecs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5189b9e41040 --- /dev/null +++ b/services/ecs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ecs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ecs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ecs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 36f414b806a1..000000000000 --- a/services/ecs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ecs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ecs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ecs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ecs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ecs/src/main/resources/codegen-resources/service-2.json b/services/ecs/src/main/resources/codegen-resources/service-2.json index a4926e89f14c..480a6a0cd6d5 100644 --- a/services/ecs/src/main/resources/codegen-resources/service-2.json +++ b/services/ecs/src/main/resources/codegen-resources/service-2.json @@ -2955,6 +2955,10 @@ "clientToken":{ "shape":"String", "documentation":"

    An identifier that you provide to ensure the idempotency of the request. It must be unique and is case sensitive. Up to 36 ASCII characters in the range of 33-126 (inclusive) are allowed.

    " + }, + "critical":{ + "shape":"BoxedBoolean", + "documentation":"

    If the critical parameter of a daemon is true, and the daemon task fails, stops, or becomes unhealthy, Amazon ECS drains the container instance and stops the other tasks running on it. If the critical parameter is false, the daemon task failure doesn't affect the other tasks on the instance. The default value is true.

    A non-critical daemon doesn't block instance registration. The container instance becomes active and continues to run your other tasks, whether the daemon task fails during scale-out or during a deployment.

    Amazon ECS emits an EventBridge event when a daemon task fails to start, for both critical and non-critical daemons.

    Daemon task launch failures during a deployment are still counted by the deployment circuit breaker. The circuit breaker can roll back an unstable target revision.

    " } } }, @@ -3023,6 +3027,10 @@ "shape":"String", "documentation":"

    The amount of memory (in MiB) used by the task. This parameter determines the memory allocation for each task in the Express service. The default value for an express service is 512 MiB.

    " }, + "cpuArchitecture":{ + "shape":"ExpressCpuArchitecture", + "documentation":"

    The CPU architecture that the tasks in the Express service run on. Amazon ECS applies this value to the task definition revision that it registers for the service. If you don't specify a value, the default is X86_64.

    Valid values:

    • X86_64 - The x86 64-bit architecture.

    • ARM64 - The 64-bit ARM architecture.

    Make sure that the container image that you specify supports the architecture that you choose. The operating system family for an Express service is always LINUX.

    You can't specify cpuArchitecture when you also specify taskDefinitionArn, because this value applies only to a task definition that Amazon ECS registers on your behalf.

    " + }, "scalingTarget":{ "shape":"ExpressGatewayScalingTarget", "documentation":"

    The auto-scaling configuration for the Express service. This defines how the service automatically adjusts the number of running tasks based on demand.

    You can specify the minimum and maximum number of tasks, the scaling metric (CPU utilization, memory utilization, or request count per target), and the target value for the metric. If not specified, the default target value for an Express service is 60.

    " @@ -3033,7 +3041,7 @@ }, "taskDefinitionArn":{ "shape":"String", - "documentation":"

    The Amazon Resource Name (ARN) of a task definition to use to create the Express Gateway service. This allows you to manage your own task definition, giving you more control over the service configuration such as adding sidecar containers.

    The task definition must have a container named Main with a single TCP port mapping that includes a container port and port name. The task definition must also have FARGATE compatibility.

    If you provide a task definition ARN, you cannot also specify primaryContainer, executionRoleArn, taskRoleArn, cpu, or memory.

    " + "documentation":"

    The Amazon Resource Name (ARN) of a task definition to use to create the Express Gateway service. This allows you to manage your own task definition, giving you more control over the service configuration such as adding sidecar containers.

    The task definition must have a container named Main with a single TCP port mapping that includes a container port and port name. The task definition must also have FARGATE compatibility.

    If you provide a task definition ARN, you cannot also specify primaryContainer, executionRoleArn, taskRoleArn, cpu, memory, or cpuArchitecture.

    " } } }, @@ -3310,6 +3318,10 @@ "runningCount":{ "shape":"Integer", "documentation":"

    The number of daemon tasks running on this capacity provider.

    " + }, + "withoutDaemonCount":{ + "shape":"Integer", + "documentation":"

    The number of instances on this capacity provider that are running without the daemon task. This applies to daemons that aren't critical, where the instance remains available for your other tasks even if the daemon task can't start or stops. These instances aren't included in runningCount.

    " } }, "documentation":"

    Information about a capacity provider associated with a daemon revision.

    " @@ -3576,6 +3588,10 @@ "shape":"BoxedInteger", "documentation":"

    The number of instances running daemon tasks on this capacity provider.

    " }, + "withoutDaemonInstanceCount":{ + "shape":"BoxedInteger", + "documentation":"

    The number of instances on this capacity provider that are running without the daemon task. This applies to daemons that aren't critical, where the instance remains available for your other tasks even if the daemon task can't start or stops. These instances aren't included in runningInstanceCount.

    " + }, "drainingInstanceCount":{ "shape":"BoxedInteger", "documentation":"

    The number of instances being drained on this capacity provider during the deployment.

    " @@ -3624,6 +3640,10 @@ "shape":"BoxedInteger", "documentation":"

    The total number of instances running daemon tasks for this revision.

    " }, + "totalWithoutDaemonInstanceCount":{ + "shape":"BoxedInteger", + "documentation":"

    The total number of instances running without the daemon task for this revision, across all capacity providers. These instances aren't included in totalRunningInstanceCount.

    " + }, "totalDrainingInstanceCount":{ "shape":"BoxedInteger", "documentation":"

    The total number of instances being drained for this revision during the deployment.

    " @@ -3854,6 +3874,10 @@ "enableExecuteCommand":{ "shape":"BoxedBoolean", "documentation":"

    Specifies whether the execute command functionality is turned on for the daemon tasks.

    " + }, + "critical":{ + "shape":"BoxedBoolean", + "documentation":"

    If the critical parameter of this daemon revision is true, and the daemon task fails, stops, or becomes unhealthy, Amazon ECS drains the container instance and stops the other tasks running on it. If the parameter is false, the daemon task failure doesn't affect the other tasks on the instance, and doesn't block instance registration. The default value is true.

    " } }, "documentation":"

    Information about a daemon revision. A daemon revision is a snapshot of the daemon's configuration at the time a deployment was initiated.

    " @@ -3872,6 +3896,10 @@ "totalRunningCount":{ "shape":"Integer", "documentation":"

    The total number of daemon tasks running for this revision.

    " + }, + "totalWithoutDaemonCount":{ + "shape":"Integer", + "documentation":"

    The total number of instances running without the daemon task for this revision, across all capacity providers. These instances aren't included in totalRunningCount.

    " } }, "documentation":"

    Details about a daemon revision, including the running task counts per capacity provider.

    " @@ -4502,6 +4530,10 @@ "canaryConfiguration":{ "shape":"CanaryConfiguration", "documentation":"

    Configuration for canary deployment strategy. Only valid when the deployment strategy is CANARY. This configuration enables shifting a fixed percentage of traffic for testing, followed by shifting the remaining traffic after a bake period.

    " + }, + "earlySuccessCriteria":{ + "shape":"DeploymentEarlySuccessCriteria", + "documentation":"

    The early success criteria configuration for a rolling deployment. With early success criteria, you can configure an Amazon ECS deployment to complete faster. Amazon ECS declares a deployment successful once a target percentage of tasks are healthy, instead of waiting for the service to fully stabilize.

    " } }, "documentation":"

    Optional deployment parameters that control how many tasks run during a deployment and the ordering of stopping and starting tasks.

    " @@ -4525,6 +4557,25 @@ "EXTERNAL" ] }, + "DeploymentEarlySuccessCriteria":{ + "type":"structure", + "required":["enable"], + "members":{ + "enable":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to use the early success criteria for the service deployment. When set to false, the deployment uses the default behavior, where Amazon ECS considers the deployment successful when the target service revision fully stabilizes and the previous tasks are removed. The default value is false.

    When set to true, Amazon ECS monitors the deployment to meet early success criteria. You must also specify healthyPercent and sourceServiceRevisionCleanup.

    " + }, + "healthyPercent":{ + "shape":"HealthyPercentInteger", + "documentation":"

    The percentage of healthy tasks that the target service revision must reach before Amazon ECS considers the deployment successful. This percentage is relative to the service's desiredCount and must be an integer between 0 and 100. This value must be greater than or equal to the minimumHealthyPercent value.

    After this percentage of tasks is healthy and the bake time elapses, Amazon ECS completes the deployment. Amazon ECS continues to scale the target service revision to 100 percent in the background.

    " + }, + "sourceServiceRevisionCleanup":{ + "shape":"ServiceRevisionCleanup", + "documentation":"

    The time when Amazon ECS removes the source revisions' tasks relative to deployment completion. The valid values are:

    • BLOCKING—Amazon ECS removes the previous tasks before it marks the deployment as successful.

    • DEFERRED—Amazon ECS marks the deployment successful, and then removes the previous tasks in the background.

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

    You can use early success criteria only with rolling deployment strategy.

    The configuration that determines when a rolling update deployment is considered successful. Early success criteria defines the percentage of tasks that must be healthy before a deployment completes. It also controls whether Amazon ECS must remove the previous tasks before a deployment completes.

    " + }, "DeploymentEphemeralStorage":{ "type":"structure", "members":{ @@ -5560,6 +5611,13 @@ } } }, + "ExpressCpuArchitecture":{ + "type":"string", + "enum":[ + "X86_64", + "ARM64" + ] + }, "ExpressGatewayContainer":{ "type":"structure", "required":["image"], @@ -5672,6 +5730,10 @@ "shape":"String", "documentation":"

    The memory allocation for tasks in this service revision.

    " }, + "cpuArchitecture":{ + "shape":"ExpressCpuArchitecture", + "documentation":"

    The CPU architecture that the tasks in this service revision run on. This is the architecture from the task definition that the service revision uses, so it reflects the default or the previously configured architecture when the request that created the revision didn't specify one.

    Valid values:

    • X86_64 - The x86 64-bit architecture.

    • ARM64 - The 64-bit ARM architecture.

    This value isn't returned when the task definition for the service revision doesn't specify a runtime platform. Because the architecture comes from each service revision's own task definition, revisions of the same service can report different architectures.

    " + }, "networkConfiguration":{ "shape":"ExpressGatewayServiceNetworkConfiguration", "documentation":"

    The network configuration for tasks in this service revision.

    " @@ -5911,6 +5973,12 @@ "UNKNOWN" ] }, + "HealthyPercentInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":0 + }, "HookDetails":{ "type":"structure", "members":{}, @@ -6088,7 +6156,8 @@ "enum":[ "CONTAINER_RUNTIME", "ACCELERATED_COMPUTE", - "DAEMON" + "DAEMON", + "AGENT_CONNECTIVITY" ] }, "InstanceLaunchTemplate":{ @@ -8039,7 +8108,7 @@ }, "protocol":{ "shape":"TransportProtocol", - "documentation":"

    The protocol used for the port mapping. Valid values are tcp and udp. The default is tcp. protocol is immutable in a Service Connect service. Updating this field requires a service deletion and redeployment.

    " + "documentation":"

    The protocol that's used for the port mapping. Valid values are tcp and udp (case-sensitive). The default is tcp. Amazon ECS treats any other specified value as tcp. protocol is immutable in a Service Connect service. To update this field, you must delete and redeploy the service.

    " }, "name":{ "shape":"String", @@ -9604,6 +9673,14 @@ }, "documentation":"

    Information about the service revision.

    A service revision contains a record of the workload configuration Amazon ECS is attempting to deploy. Whenever you create or deploy a service, Amazon ECS automatically creates and captures the configuration that you're trying to deploy in the service revision. For information about service revisions, see Amazon ECS service revisions in the Amazon Elastic Container Service Developer Guide .

    " }, + "ServiceRevisionCleanup":{ + "type":"string", + "documentation":"

    The time when Amazon ECS removes the source revisions' tasks relative to deployment completion. When set to BLOCKING, Amazon ECS removes the previous tasks before completing the deployment. When set to DEFERRED, Amazon ECS completes the deployment first and removes the previous tasks in the background.

    ", + "enum":[ + "BLOCKING", + "DEFERRED" + ] + }, "ServiceRevisionLoadBalancer":{ "type":"structure", "members":{ @@ -10735,7 +10812,8 @@ "UserInitiated", "ServiceSchedulerInitiated", "SpotInterruption", - "TerminationNotice" + "TerminationNotice", + "InfrastructureHealth" ] }, "TaskVolumeConfiguration":{ @@ -11118,6 +11196,10 @@ "enableExecuteCommand":{ "shape":"Boolean", "documentation":"

    If true, the execute command functionality is turned on for all tasks in the daemon. If false, the execute command functionality is turned off.

    " + }, + "critical":{ + "shape":"BoxedBoolean", + "documentation":"

    If the critical parameter of a daemon is true, and the daemon task fails, stops, or becomes unhealthy, Amazon ECS drains the container instance and stops the other tasks running on it. If the critical parameter is false, the daemon task failure doesn't affect the other tasks on the instance. The default value is true.

    A non-critical daemon doesn't block instance registration. The container instance becomes active and continues to run your other tasks, whether the daemon task fails during scale-out or during a deployment.

    Amazon ECS emits an EventBridge event when a daemon task fails to start, for both critical and non-critical daemons.

    Daemon task launch failures during a deployment are still counted by the deployment circuit breaker. The circuit breaker can roll back an unstable target revision.

    " } } }, @@ -11182,13 +11264,17 @@ "shape":"String", "documentation":"

    The amount of memory (in MiB) used by the task.

    " }, + "cpuArchitecture":{ + "shape":"ExpressCpuArchitecture", + "documentation":"

    The CPU architecture that the tasks in the Express service run on. Amazon ECS applies this value to the task definition revision that it registers for the service. If you don't specify a value, the service keeps the architecture that it currently runs on.

    Valid values:

    • X86_64 - The x86 64-bit architecture.

    • ARM64 - The 64-bit ARM architecture.

    Changing the architecture starts a new deployment that replaces the running tasks. Make sure that the container image that the service uses supports the architecture that you choose. The operating system family for an Express service is always LINUX.

    You can't specify cpuArchitecture when you also specify taskDefinitionArn, because this value applies only to a task definition that Amazon ECS registers on your behalf.

    " + }, "scalingTarget":{ "shape":"ExpressGatewayScalingTarget", "documentation":"

    The auto-scaling configuration for the Express service.

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

    The Amazon Resource Name (ARN) of a task definition to use to update the Express Gateway service. This allows you to manage your own task definition, giving you more control over the service configuration such as adding sidecar containers.

    The task definition must have a container named Main with a single TCP port mapping that includes a container port and port name. The task definition must also have FARGATE compatibility.

    If you provide a task definition ARN, you cannot also specify primaryContainer, executionRoleArn, taskRoleArn, cpu, or memory.

    " + "documentation":"

    The Amazon Resource Name (ARN) of a task definition to use to update the Express Gateway service. This allows you to manage your own task definition, giving you more control over the service configuration such as adding sidecar containers.

    The task definition must have a container named Main with a single TCP port mapping that includes a container port and port name. The task definition must also have FARGATE compatibility.

    If you provide a task definition ARN, you cannot also specify primaryContainer, executionRoleArn, taskRoleArn, cpu, memory, or cpuArchitecture.

    " } } }, diff --git a/services/efs/pom.xml b/services/efs/pom.xml index b5aed1700caa..6abc340c874c 100644 --- a/services/efs/pom.xml +++ b/services/efs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT efs AWS Java SDK :: Services :: Amazon Elastic File System diff --git a/services/efs/src/main/resources/codegen-resources/customization.config b/services/efs/src/main/resources/codegen-resources/customization.config index ddfc00a7e632..735bd9dbc777 100644 --- a/services/efs/src/main/resources/codegen-resources/customization.config +++ b/services/efs/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "describeMountTargets" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/efs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/efs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3a072df4141e --- /dev/null +++ b/services/efs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,251 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://efs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://efs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticfilesystem-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticfilesystem-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticfilesystem.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticfilesystem.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAACAAAAAcF9eEMAAAACQX14QgF9eEJAAAABAAAAA8AAAAJAAAABQAAAA8AAAAKAAAABgAAAA8AAAALAAAABwAAAA0AAAAMAAAACAX14QcF9eELAAAACAAAAA4F9eEKAAAACQX14QYF9eEHAAAACAX14QUF9eEEAAAAAwAAABIAAAARAAAACAX14QEF9eEDAAAACAX14QEF9eEC" +} \ No newline at end of file diff --git a/services/efs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/efs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 765b2e987a61..000000000000 --- a/services/efs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,602 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://efs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticfilesystem-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticfilesystem-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticfilesystem.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticfilesystem.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/eks/pom.xml b/services/eks/pom.xml index 5aad42d293c2..09d79d4d0b88 100644 --- a/services/eks/pom.xml +++ b/services/eks/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT eks AWS Java SDK :: Services :: EKS diff --git a/services/eks/src/main/resources/codegen-resources/customization.config b/services/eks/src/main/resources/codegen-resources/customization.config index 9ebe291adc93..ee26fa7f9350 100644 --- a/services/eks/src/main/resources/codegen-resources/customization.config +++ b/services/eks/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listClusters" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/eks/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/eks/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e037b7b336ea --- /dev/null +++ b/services/eks/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fips.eks.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/eks/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/eks/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a3c6645c206e..000000000000 --- a/services/eks/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://eks-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://fips.eks.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://eks.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://eks-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://eks.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://eks.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/eks/src/main/resources/codegen-resources/paginators-1.json b/services/eks/src/main/resources/codegen-resources/paginators-1.json index 67dacd30dbec..3c13cbea7b9f 100644 --- a/services/eks/src/main/resources/codegen-resources/paginators-1.json +++ b/services/eks/src/main/resources/codegen-resources/paginators-1.json @@ -46,6 +46,12 @@ "output_token": "nextToken", "result_key": "capabilities" }, + "ListCertificateAuthorities": { + "input_token": "nextToken", + "limit_key": "maxResults", + "output_token": "nextToken", + "result_key": "certificateAuthorities" + }, "ListClusters": { "input_token": "nextToken", "limit_key": "maxResults", diff --git a/services/eks/src/main/resources/codegen-resources/service-2.json b/services/eks/src/main/resources/codegen-resources/service-2.json index 7948fab126bf..192bf3ac0fea 100644 --- a/services/eks/src/main/resources/codegen-resources/service-2.json +++ b/services/eks/src/main/resources/codegen-resources/service-2.json @@ -15,6 +15,22 @@ "auth":["aws.auth#sigv4"] }, "operations":{ + "ActivateCertificateAuthority":{ + "name":"ActivateCertificateAuthority", + "http":{ + "method":"POST", + "requestUri":"/clusters/{name}/certificate-authorities/{certificateAuthorityId}/activate" + }, + "input":{"shape":"ActivateCertificateAuthorityRequest"}, + "output":{"shape":"ActivateCertificateAuthorityResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ServerException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Activates a successor certificate authority (CA) as the signing certificate authority for your cluster, completing a CA rotation.

    When you activate a successor CA, Amazon EKS promotes it to be the cluster's signer (its signingStatus becomes IN_USE) and the outgoing CA is retired (NOT_USED). The outgoing CA remains in the cluster's trust bundle but no longer signs certificates. The successor CA you activate must already be present on the cluster and fully distributed (its distributionStatus must be COMPLETE). This is an asynchronous operation that returns an update object you can track with DescribeUpdate .

    Before you activate the successor CA, make sure the worker nodes you manage and your external clients have been updated to trust it, so they maintain connectivity to the API server after activation. For a limited period after activation, CA rollback is available to revert to the outgoing CA if needed. If you don't activate the successor CA yourself, Amazon EKS activates it automatically as the expiration deadline approaches. For more information, see Rotate the Amazon EKS cluster certificate authority in the Amazon EKS User Guide.

    " + }, "AssociateAccessPolicy":{ "name":"AssociateAccessPolicy", "http":{ @@ -144,6 +160,24 @@ ], "documentation":"

    Creates a managed capability resource for an Amazon EKS cluster.

    Capabilities provide fully managed capabilities to build and scale with Kubernetes. When you create a capability, Amazon EKSprovisions and manages the infrastructure required to run the capability outside of your cluster. This approach reduces operational overhead and preserves cluster resources.

    You can only create one Capability of each type on a given Amazon EKS cluster. Valid types are Argo CD for declarative GitOps deployment, Amazon Web Services Controllers for Kubernetes (ACK) for resource management, and Kube Resource Orchestrator (KRO) for Kubernetes custom resource orchestration.

    For more information, see EKS Capabilities in the Amazon EKS User Guide.

    " }, + "CreateCertificateAuthority":{ + "name":"CreateCertificateAuthority", + "http":{ + "method":"POST", + "requestUri":"/clusters/{name}/certificate-authorities" + }, + "input":{"shape":"CreateCertificateAuthorityRequest"}, + "output":{"shape":"CreateCertificateAuthorityResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceLimitExceededException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceInUseException"}, + {"shape":"ServerException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Appends a successor certificate authority (CA) to your cluster, beginning the CA rotation process.

    A cluster certificate authority is the root of trust for your cluster's control plane. It signs the certificates that secure communication between the Kubernetes API server and its clients, and its public certificate is distributed to your cluster's trust bundle so that worker nodes and clients can verify the API server's identity. Each cluster can have at most two certificate authorities at a time: the outgoing CA that's currently signing (its signingStatus is IN_USE) and one successor CA (signingStatus of NOT_USED) that you can later activate to complete the rotation.

    Appending a successor CA adds its public certificate to the cluster's trust bundle so that the cluster trusts both CAs simultaneously (the dual trust period), but it doesn't begin signing certificates. Amazon EKS then distributes the successor CA to the Amazon Web Services managed components in your cluster; you can track this through the CA's distributionStatus. The successor CA can't be activated until its distributionStatus is COMPLETE. To activate it as the cluster's signer, use ActivateCertificateAuthority . This is an asynchronous operation that returns an update object. If you don't append a successor CA yourself, Amazon EKS appends one automatically before the outgoing CA approaches expiration.

    For more information, see Rotate the Amazon EKS cluster certificate authority in the Amazon EKS User Guide.

    " + }, "CreateCluster":{ "name":"CreateCluster", "http":{ @@ -284,6 +318,23 @@ ], "documentation":"

    Deletes a managed capability from your Amazon EKS cluster. When you delete a capability, Amazon EKS removes the capability infrastructure but retains all resources that were managed by the capability.

    Before deleting a capability, you should delete all Kubernetes resources that were created by the capability. After the capability is deleted, these resources become difficult to manage because the controller that managed them is no longer available. To delete resources before removing the capability, use kubectl delete or remove them through your GitOps workflow.

    " }, + "DeleteCertificateAuthority":{ + "name":"DeleteCertificateAuthority", + "http":{ + "method":"DELETE", + "requestUri":"/clusters/{name}/certificate-authorities/{certificateAuthorityId}" + }, + "input":{"shape":"DeleteCertificateAuthorityRequest"}, + "output":{"shape":"DeleteCertificateAuthorityResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ResourceInUseException"}, + {"shape":"ServerException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Deletes a certificate authority (CA) from your cluster.

    Deleting a certificate authority removes its public certificate from the cluster's trust bundle. You can't delete the certificate authority that's currently signing certificates for the cluster (its signingStatus is IN_USE) — to remove the outgoing CA, first activate the successor CA with ActivateCertificateAuthority . Amazon EKS also protects a successor CA from deletion in certain cases to keep a valid rotation path — for example, a successor that Amazon EKS appended can't be deleted while it's the only successor on the cluster. This is an asynchronous operation that returns an update object.

    " + }, "DeleteCluster":{ "name":"DeleteCluster", "http":{ @@ -464,6 +515,21 @@ ], "documentation":"

    Returns detailed information about a specific managed capability in your Amazon EKS cluster, including its current status, configuration, health information, and any issues that may be affecting its operation.

    " }, + "DescribeCertificateAuthority":{ + "name":"DescribeCertificateAuthority", + "http":{ + "method":"GET", + "requestUri":"/clusters/{name}/certificate-authorities/{certificateAuthorityId}" + }, + "input":{"shape":"DescribeCertificateAuthorityRequest"}, + "output":{"shape":"DescribeCertificateAuthorityResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ServerException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Returns detailed information about a certificate authority (CA) in your cluster, including its validity period, signing and distribution status, provenance, scheduled auto-activation events, and public certificate data.

    " + }, "DescribeCluster":{ "name":"DescribeCluster", "http":{ @@ -734,6 +800,22 @@ ], "documentation":"

    Lists all managed capabilities in your Amazon EKS cluster. You can use this operation to get an overview of all capabilities and their current status.

    " }, + "ListCertificateAuthorities":{ + "name":"ListCertificateAuthorities", + "http":{ + "method":"GET", + "requestUri":"/clusters/{name}/certificate-authorities" + }, + "input":{"shape":"ListCertificateAuthoritiesRequest"}, + "output":{"shape":"ListCertificateAuthoritiesResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParameterException"}, + {"shape":"ServerException"}, + {"shape":"ServiceUnavailableException"} + ], + "documentation":"

    Lists the certificate authorities (CAs) for your cluster. A cluster has at most two certificate authorities: the outgoing CA that's currently signing and, during a rotation, one successor CA.

    " + }, "ListClusters":{ "name":"ListClusters", "http":{ @@ -1238,6 +1320,59 @@ "namespace" ] }, + "ActivateCertificateAuthorityRequest":{ + "type":"structure", + "required":[ + "clusterName", + "certificateAuthorityId" + ], + "members":{ + "clusterName":{ + "shape":"String", + "documentation":"

    The name of your cluster.

    ", + "location":"uri", + "locationName":"name" + }, + "certificateAuthorityId":{ + "shape":"String", + "documentation":"

    The ID of the certificate authority to activate as the cluster's signing certificate authority. This certificate authority must already exist on the cluster and have a distributionStatus of COMPLETE.

    ", + "location":"uri", + "locationName":"certificateAuthorityId" + }, + "clientRequestToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + } + } + }, + "ActivateCertificateAuthorityResponse":{ + "type":"structure", + "members":{ + "update":{ + "shape":"Update", + "documentation":"

    An object representing the asynchronous update that promotes the certificate authority to be the cluster's signer.

    " + }, + "certificateAuthority":{ + "shape":"CertificateAuthoritySummary", + "documentation":"

    Summary information about the certificate authority that is being activated.

    " + } + } + }, + "ActiveCertificateAuthority":{ + "type":"structure", + "members":{ + "id":{ + "shape":"String", + "documentation":"

    The unique identifier of the certificate authority that is currently signing certificates for the cluster.

    " + }, + "activatedBy":{ + "shape":"CertificateAuthorityActivatedBy", + "documentation":"

    The entity that activated the current signing certificate authority, either CUSTOMER or EKS.

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

    Identifies the certificate authority that is currently signing certificates for the cluster.

    " + }, "AdditionalInfoMap":{ "type":"map", "key":{"shape":"String"}, @@ -1523,6 +1658,22 @@ "type":"list", "member":{"shape":"AddonInfo"} }, + "AllowedValuesConstraint":{ + "type":"structure", + "members":{ + "allowedValues":{ + "shape":"AllowedValuesList", + "documentation":"

    The list of allowed values.

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

    A constraint specifying the allowed values for a parameter.

    " + }, + "AllowedValuesList":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    A list of allowed string values for a parameter constraint.

    ", + "max":20 + }, "ArgoCdAwsIdcConfigRequest":{ "type":"structure", "required":["idcInstanceArn"], @@ -2110,10 +2261,167 @@ "data":{ "shape":"String", "documentation":"

    The Base64-encoded certificate data required to communicate with your cluster. Add this to the certificate-authority-data section of the kubeconfig file for your cluster.

    " + }, + "active":{ + "shape":"ActiveCertificateAuthority", + "documentation":"

    An object identifying the certificate authority that is currently signing certificates for the cluster.

    " } }, "documentation":"

    An object representing the certificate-authority-data for your cluster.

    " }, + "CertificateAuthority":{ + "type":"structure", + "members":{ + "id":{ + "shape":"String", + "documentation":"

    The unique identifier of the certificate authority.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for when the certificate authority was created.

    " + }, + "createdBy":{ + "shape":"CertificateAuthorityCreatedBy", + "documentation":"

    The entity that created the certificate authority. Certificate authorities that you create are CUSTOMER; those that Amazon EKS provisions on your behalf, such as a cluster's initial certificate authority, are EKS.

    " + }, + "activatedAt":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for when the certificate authority was last activated as the cluster's signer. This value is absent if the certificate authority has never been activated.

    " + }, + "activatedBy":{ + "shape":"CertificateAuthorityActivatedBy", + "documentation":"

    The entity that most recently activated the certificate authority. A value of EKS indicates that Amazon EKS activated it automatically; CUSTOMER indicates that you activated it.

    " + }, + "signingStatus":{ + "shape":"CertificateAuthoritySigningStatus", + "documentation":"

    The signing status of the certificate authority. IN_USE means the certificate authority is currently signing certificates for the cluster, ACTIVATING means it's being promoted to the signer, and NOT_USED means it's trusted by the cluster (for example, a successor CA during a rotation, or a retired outgoing CA) but isn't the signer.

    " + }, + "distributionStatus":{ + "shape":"CertificateAuthorityDistributionStatus", + "documentation":"

    The distribution status of the certificate authority, which tracks whether Amazon EKS has distributed its trust to the Amazon Web Services managed components in your cluster (the control plane, Amazon EKS Auto Mode instances, and Amazon Web Services Fargate nodes). Valid values are IN_PROGRESS, COMPLETE, FAILED, and DELETING. A successor CA can only be activated after its distribution status is COMPLETE.

    " + }, + "validity":{ + "shape":"CertificateAuthorityValidity", + "documentation":"

    The validity period of the certificate authority's certificate.

    " + }, + "scheduledEvents":{ + "shape":"CertificateAuthorityScheduledEvents", + "documentation":"

    The scheduled auto-activation events for the certificate authority, computed from its validity period.

    " + }, + "rollbackAvailable":{ + "shape":"BoxedBoolean", + "documentation":"

    Indicates whether CA rollback is still available for this certificate authority. After you activate a successor CA, rollback lets you revert to the outgoing CA for a limited period while you finish updating any worker nodes or clients that were missed.

    " + }, + "data":{ + "shape":"String", + "documentation":"

    The Base64-encoded public certificate of the certificate authority.

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

    An object representing a certificate authority (CA) for an Amazon EKS cluster.

    " + }, + "CertificateAuthorityActivatedBy":{ + "type":"string", + "enum":[ + "EKS", + "CUSTOMER" + ] + }, + "CertificateAuthorityCreatedBy":{ + "type":"string", + "enum":[ + "EKS", + "CUSTOMER" + ] + }, + "CertificateAuthorityDistributionStatus":{ + "type":"string", + "enum":[ + "IN_PROGRESS", + "COMPLETE", + "FAILED", + "DELETING" + ] + }, + "CertificateAuthorityMaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "CertificateAuthorityScheduledEvents":{ + "type":"structure", + "members":{ + "firstAutoActivation":{ + "shape":"Timestamp", + "documentation":"

    The earliest Unix epoch timestamp in seconds at which Amazon EKS may automatically activate this certificate authority.

    " + }, + "finalAutoActivation":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds by which Amazon EKS will automatically activate this certificate authority if you haven't already activated it.

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

    The scheduled events during which Amazon EKS may automatically activate a certificate authority, computed from its validity period. These events help ensure that a cluster's signing certificate authority is rotated before its certificate expires.

    " + }, + "CertificateAuthoritySigningStatus":{ + "type":"string", + "enum":[ + "NOT_USED", + "ACTIVATING", + "IN_USE" + ] + }, + "CertificateAuthoritySummary":{ + "type":"structure", + "members":{ + "id":{ + "shape":"String", + "documentation":"

    The unique identifier of the certificate authority.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for when the certificate authority was created.

    " + }, + "createdBy":{ + "shape":"CertificateAuthorityCreatedBy", + "documentation":"

    The entity that created the certificate authority, either CUSTOMER or EKS.

    " + }, + "activatedAt":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for when the certificate authority was last activated. This value is absent if the certificate authority has never been activated.

    " + }, + "activatedBy":{ + "shape":"CertificateAuthorityActivatedBy", + "documentation":"

    The entity that most recently activated the certificate authority, either CUSTOMER or EKS.

    " + }, + "signingStatus":{ + "shape":"CertificateAuthoritySigningStatus", + "documentation":"

    The signing status of the certificate authority: IN_USE, ACTIVATING, or NOT_USED.

    " + }, + "distributionStatus":{ + "shape":"CertificateAuthorityDistributionStatus", + "documentation":"

    The distribution status of the certificate authority: IN_PROGRESS, COMPLETE, FAILED, or DELETING.

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

    Summary information about a certificate authority (CA) for an Amazon EKS cluster, returned by ListCertificateAuthorities and the certificate-authority write operations.

    " + }, + "CertificateAuthoritySummaryList":{ + "type":"list", + "member":{"shape":"CertificateAuthoritySummary"} + }, + "CertificateAuthorityValidity":{ + "type":"structure", + "members":{ + "notBefore":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for the start of the certificate authority's validity period.

    " + }, + "notAfter":{ + "shape":"Timestamp", + "documentation":"

    The Unix epoch timestamp in seconds for the end of the certificate authority's validity period.

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

    The validity period of a certificate authority's certificate.

    " + }, "ClientException":{ "type":"structure", "members":{ @@ -2278,6 +2586,18 @@ "controlPlaneScalingConfig":{ "shape":"ControlPlaneScalingConfig", "documentation":"

    The control plane scaling tier configuration. For more information, see EKS Provisioned Control Plane in the Amazon EKS User Guide.

    " + }, + "kubeApiServerConfig":{ + "shape":"KubeApiServerConfigResponse", + "documentation":"

    The Kubernetes API server configuration for the cluster.

    " + }, + "kubeSchedulerConfig":{ + "shape":"KubeSchedulerConfigResponse", + "documentation":"

    The Kubernetes scheduler configuration for the cluster.

    " + }, + "kubeControllerManagerConfig":{ + "shape":"KubeControllerManagerConfigResponse", + "documentation":"

    The Kubernetes controller manager configuration for the cluster.

    " } }, "documentation":"

    An object representing an Amazon EKS cluster.

    " @@ -2397,6 +2717,14 @@ "kubernetesPatchVersion":{ "shape":"String", "documentation":"

    The patch version of Kubernetes for this cluster version.

    " + }, + "controlPlaneScalingTiers":{ + "shape":"ControlPlaneScalingTierList", + "documentation":"

    The available provisioned control plane scaling tiers and their capabilities for this Kubernetes version.

    " + }, + "controlPlaneComponentConfig":{ + "shape":"ControlPlaneConfigInfo", + "documentation":"

    The default control plane component configuration and constraints for this Kubernetes version.

    " } }, "documentation":"

    Contains details about a specific EKS cluster version.

    " @@ -2529,6 +2857,24 @@ }, "documentation":"

    The full description of your connected cluster.

    " }, + "ControlPlaneConfigInfo":{ + "type":"structure", + "members":{ + "kubeApiServerConfig":{ + "shape":"KubeApiServerVersionConfig", + "documentation":"

    The Kubernetes API server configuration defaults and constraints.

    " + }, + "kubeSchedulerConfig":{ + "shape":"KubeSchedulerVersionConfig", + "documentation":"

    The Kubernetes scheduler configuration defaults and constraints.

    " + }, + "kubeControllerManagerConfig":{ + "shape":"KubeControllerManagerVersionConfig", + "documentation":"

    The Kubernetes controller manager configuration defaults and constraints.

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

    The control plane component configuration defaults and constraints.

    " + }, "ControlPlaneEgressModeType":{ "type":"string", "enum":[ @@ -2575,6 +2921,38 @@ }, "documentation":"

    The control plane scaling tier configuration. For more information, see EKS Provisioned Control Plane in the Amazon EKS User Guide.

    " }, + "ControlPlaneScalingTierInfo":{ + "type":"structure", + "members":{ + "tierName":{ + "shape":"String", + "documentation":"

    The name of the scaling tier.

    " + }, + "apiRequestConcurrency":{ + "shape":"BoxedInteger", + "documentation":"

    The maximum API request concurrency supported by this tier.

    " + }, + "podSchedulingRatePerSecond":{ + "shape":"BoxedInteger", + "documentation":"

    The maximum pod scheduling rate per second supported by this tier.

    " + }, + "clusterDatabaseSizeGb":{ + "shape":"BoxedInteger", + "documentation":"

    The maximum cluster database size in GB supported by this tier.

    " + }, + "controlPlaneComponentConfigOverrides":{ + "shape":"ControlPlaneConfigInfo", + "documentation":"

    The control plane component configuration overrides specific to this scaling tier.

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

    Information about a provisioned control plane scaling tier.

    " + }, + "ControlPlaneScalingTierList":{ + "type":"list", + "member":{"shape":"ControlPlaneScalingTierInfo"}, + "documentation":"

    A list of available provisioned control plane scaling tiers.

    ", + "max":10 + }, "CreateAccessConfigRequest":{ "type":"structure", "members":{ @@ -2746,6 +3124,36 @@ } } }, + "CreateCertificateAuthorityRequest":{ + "type":"structure", + "required":["clusterName"], + "members":{ + "clusterName":{ + "shape":"String", + "documentation":"

    The name of your cluster.

    ", + "location":"uri", + "locationName":"name" + }, + "clientRequestToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + } + } + }, + "CreateCertificateAuthorityResponse":{ + "type":"structure", + "members":{ + "update":{ + "shape":"Update", + "documentation":"

    An object representing the asynchronous update that adds the certificate authority to the cluster's trust bundle.

    " + }, + "certificateAuthority":{ + "shape":"CertificateAuthoritySummary", + "documentation":"

    Summary information about the certificate authority that was created, including its ID and initial signing and distribution status.

    " + } + } + }, "CreateClusterRequest":{ "type":"structure", "required":[ @@ -2830,6 +3238,18 @@ "controlPlaneScalingConfig":{ "shape":"ControlPlaneScalingConfig", "documentation":"

    The control plane scaling tier configuration. For more information, see EKS Provisioned Control Plane in the Amazon EKS User Guide.

    " + }, + "kubeApiServerConfig":{ + "shape":"KubeApiServerConfigRequest", + "documentation":"

    The Kubernetes API server configuration for the new cluster.

    " + }, + "kubeSchedulerConfig":{ + "shape":"KubeSchedulerConfigRequest", + "documentation":"

    The Kubernetes scheduler configuration for the new cluster.

    " + }, + "kubeControllerManagerConfig":{ + "shape":"KubeControllerManagerConfigRequest", + "documentation":"

    The Kubernetes controller manager configuration for the new cluster.

    " } } }, @@ -3189,6 +3609,47 @@ } } }, + "DeleteCertificateAuthorityRequest":{ + "type":"structure", + "required":[ + "clusterName", + "certificateAuthorityId" + ], + "members":{ + "clusterName":{ + "shape":"String", + "documentation":"

    The name of your cluster.

    ", + "location":"uri", + "locationName":"name" + }, + "certificateAuthorityId":{ + "shape":"String", + "documentation":"

    The ID of the certificate authority to delete. You can't delete the certificate authority that's currently signing certificates for the cluster.

    ", + "location":"uri", + "locationName":"certificateAuthorityId" + }, + "clientRequestToken":{ + "shape":"String", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true, + "location":"querystring", + "locationName":"clientRequestToken" + } + } + }, + "DeleteCertificateAuthorityResponse":{ + "type":"structure", + "members":{ + "update":{ + "shape":"Update", + "documentation":"

    An object representing the asynchronous update that removes the certificate authority from the cluster's trust bundle.

    " + }, + "certificateAuthority":{ + "shape":"CertificateAuthoritySummary", + "documentation":"

    Summary information about the certificate authority that is being deleted.

    " + } + } + }, "DeleteClusterRequest":{ "type":"structure", "required":["name"], @@ -3534,33 +3995,63 @@ } } }, - "DescribeCapabilityRequest":{ + "DescribeCapabilityRequest":{ + "type":"structure", + "required":[ + "clusterName", + "capabilityName" + ], + "members":{ + "clusterName":{ + "shape":"String", + "documentation":"

    The name of the Amazon EKS cluster that contains the capability you want to describe.

    ", + "location":"uri", + "locationName":"name" + }, + "capabilityName":{ + "shape":"String", + "documentation":"

    The name of the capability to describe.

    ", + "location":"uri", + "locationName":"capabilityName" + } + } + }, + "DescribeCapabilityResponse":{ + "type":"structure", + "members":{ + "capability":{ + "shape":"Capability", + "documentation":"

    An object containing detailed information about the capability, including its name, ARN, type, status, version, configuration, health status, and timestamps for when it was created and last modified.

    " + } + } + }, + "DescribeCertificateAuthorityRequest":{ "type":"structure", "required":[ "clusterName", - "capabilityName" + "certificateAuthorityId" ], "members":{ "clusterName":{ "shape":"String", - "documentation":"

    The name of the Amazon EKS cluster that contains the capability you want to describe.

    ", + "documentation":"

    The name of your cluster.

    ", "location":"uri", "locationName":"name" }, - "capabilityName":{ + "certificateAuthorityId":{ "shape":"String", - "documentation":"

    The name of the capability to describe.

    ", + "documentation":"

    The ID of the certificate authority to describe.

    ", "location":"uri", - "locationName":"capabilityName" + "locationName":"certificateAuthorityId" } } }, - "DescribeCapabilityResponse":{ + "DescribeCertificateAuthorityResponse":{ "type":"structure", "members":{ - "capability":{ - "shape":"Capability", - "documentation":"

    An object containing detailed information about the capability, including its name, ARN, type, status, version, configuration, health status, and timestamps for when it was created and last modified.

    " + "certificateAuthority":{ + "shape":"CertificateAuthority", + "documentation":"

    An object containing detailed information about the certificate authority.

    " } } }, @@ -3973,6 +4464,34 @@ "update":{"shape":"Update"} } }, + "DurationConstraints":{ + "type":"structure", + "members":{ + "min":{ + "shape":"String", + "documentation":"

    The minimum allowed duration value.

    " + }, + "max":{ + "shape":"String", + "documentation":"

    The maximum allowed duration value.

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

    Constraints for a duration parameter.

    " + }, + "DurationParameterConfig":{ + "type":"structure", + "members":{ + "defaultValue":{ + "shape":"String", + "documentation":"

    The default value for the duration parameter.

    " + }, + "constraints":{ + "shape":"DurationConstraints", + "documentation":"

    The constraints for the duration parameter.

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

    A duration parameter configuration with default value and constraints.

    " + }, "EksAnywhereSubscription":{ "type":"structure", "members":{ @@ -4093,7 +4612,10 @@ "members":{ "resources":{ "shape":"StringList", - "documentation":"

    Specifies the resources to be encrypted. The only supported value is secrets.

    " + "documentation":"

    Amazon EKS encrypts all Kubernetes API data with envelope encryption by default for clusters running Kubernetes version 1.28 or higher, so this field no longer affects which resources are encrypted.

    Specifies the resources to be encrypted. The only supported value is secrets.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. Amazon EKS encrypts all Kubernetes API data by default, so this value no longer determines which resources are encrypted.", + "deprecatedSince":"2025-03-05" }, "provider":{ "shape":"Provider", @@ -4297,6 +4819,36 @@ "max":100, "min":1 }, + "HorizontalPodAutoscalerControllerConfigRequest":{ + "type":"structure", + "members":{ + "horizontalPodAutoscalerSyncPeriod":{ + "shape":"String", + "documentation":"

    The interval between each sync of the horizontal pod autoscaler. Valid values are single-unit durations such as 15s or 1m.

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

    The horizontal pod autoscaler controller configuration for the Kubernetes controller manager.

    " + }, + "HorizontalPodAutoscalerControllerConfigResponse":{ + "type":"structure", + "members":{ + "horizontalPodAutoscalerSyncPeriod":{ + "shape":"String", + "documentation":"

    The interval between each sync of the horizontal pod autoscaler.

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

    The horizontal pod autoscaler controller configuration for the Kubernetes controller manager.

    " + }, + "HorizontalPodAutoscalerControllerVersionConfig":{ + "type":"structure", + "members":{ + "horizontalPodAutoscalerSyncPeriod":{ + "shape":"DurationParameterConfig", + "documentation":"

    The HPA sync period configuration with default value and constraints.

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

    The horizontal pod autoscaler controller version configuration.

    " + }, "Identity":{ "type":"structure", "members":{ @@ -4529,6 +5081,48 @@ ] }, "Integer":{"type":"integer"}, + "IntegerConstraints":{ + "type":"structure", + "members":{ + "min":{ + "shape":"BoxedInteger", + "documentation":"

    The minimum allowed value.

    " + }, + "max":{ + "shape":"BoxedInteger", + "documentation":"

    The maximum allowed value.

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

    Constraints for an integer parameter specifying allowed range.

    " + }, + "IntegerParameterConfig":{ + "type":"structure", + "members":{ + "defaultValue":{ + "shape":"BoxedInteger", + "documentation":"

    The default value for the integer parameter.

    " + }, + "constraints":{ + "shape":"IntegerConstraints", + "documentation":"

    The constraints for the integer parameter.

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

    An integer parameter configuration with default value and constraints.

    " + }, + "IntegerRangeConstraint":{ + "type":"structure", + "members":{ + "min":{ + "shape":"BoxedInteger", + "documentation":"

    The minimum allowed value.

    " + }, + "max":{ + "shape":"BoxedInteger", + "documentation":"

    The maximum allowed value.

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

    An integer range constraint specifying minimum and maximum allowed values.

    " + }, "InvalidParameterException":{ "type":"structure", "members":{ @@ -4631,6 +5225,120 @@ "type":"list", "member":{"shape":"Issue"} }, + "KubeApiServerConfigRequest":{ + "type":"structure", + "members":{ + "eventTtl":{ + "shape":"String", + "documentation":"

    The duration that Kubernetes events are retained. Valid values are single-unit durations such as 30m or 1h.

    " + }, + "serviceNodePortRange":{ + "shape":"ServiceNodePortRange", + "documentation":"

    The port range for NodePort services.

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

    The configuration for the Kubernetes API server on an Amazon EKS cluster.

    " + }, + "KubeApiServerConfigResponse":{ + "type":"structure", + "members":{ + "eventTtl":{ + "shape":"String", + "documentation":"

    The duration that Kubernetes events are retained.

    " + }, + "serviceNodePortRange":{ + "shape":"ServiceNodePortRange", + "documentation":"

    The port range for NodePort services.

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

    The Kubernetes API server configuration for an Amazon EKS cluster.

    " + }, + "KubeApiServerVersionConfig":{ + "type":"structure", + "members":{ + "eventTtl":{ + "shape":"DurationParameterConfig", + "documentation":"

    The event TTL configuration with default value and constraints.

    " + }, + "serviceNodePortRange":{ + "shape":"PortRangeParameterConfig", + "documentation":"

    The service node port range configuration with default value and constraints.

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

    The Kubernetes API server version-specific configuration defaults and constraints.

    " + }, + "KubeControllerManagerConfigRequest":{ + "type":"structure", + "members":{ + "podGcControllerConfig":{ + "shape":"PodGcControllerConfigRequest", + "documentation":"

    The pod garbage collection controller configuration.

    " + }, + "horizontalPodAutoscalerControllerConfig":{ + "shape":"HorizontalPodAutoscalerControllerConfigRequest", + "documentation":"

    The horizontal pod autoscaler controller configuration.

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

    The configuration for the Kubernetes controller manager on an Amazon EKS cluster.

    " + }, + "KubeControllerManagerConfigResponse":{ + "type":"structure", + "members":{ + "podGcControllerConfig":{ + "shape":"PodGcControllerConfigResponse", + "documentation":"

    The pod garbage collection controller configuration.

    " + }, + "horizontalPodAutoscalerControllerConfig":{ + "shape":"HorizontalPodAutoscalerControllerConfigResponse", + "documentation":"

    The horizontal pod autoscaler controller configuration.

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

    The Kubernetes controller manager configuration for an Amazon EKS cluster.

    " + }, + "KubeControllerManagerVersionConfig":{ + "type":"structure", + "members":{ + "podGcControllerConfig":{ + "shape":"PodGcControllerVersionConfig", + "documentation":"

    The pod garbage collection controller configuration with default value and constraints.

    " + }, + "horizontalPodAutoscalerControllerConfig":{ + "shape":"HorizontalPodAutoscalerControllerVersionConfig", + "documentation":"

    The horizontal pod autoscaler controller configuration with default value and constraints.

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

    The Kubernetes controller manager version-specific configuration defaults and constraints.

    " + }, + "KubeSchedulerConfigRequest":{ + "type":"structure", + "members":{ + "nodeResourcesFit":{ + "shape":"NodeResourcesFitConfig", + "documentation":"

    The node resource fit scoring configuration for the scheduler.

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

    The configuration for the Kubernetes scheduler on an Amazon EKS cluster.

    " + }, + "KubeSchedulerConfigResponse":{ + "type":"structure", + "members":{ + "nodeResourcesFit":{ + "shape":"NodeResourcesFitConfig", + "documentation":"

    The node resource fit scoring configuration for the scheduler.

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

    The Kubernetes scheduler configuration for an Amazon EKS cluster.

    " + }, + "KubeSchedulerVersionConfig":{ + "type":"structure", + "members":{ + "nodeResourcesFit":{ + "shape":"NodeResourcesFitVersionConfig", + "documentation":"

    The NodeResourcesFit configuration with default value and constraints.

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

    The Kubernetes scheduler version-specific configuration defaults and constraints.

    " + }, "KubernetesNetworkConfigRequest":{ "type":"structure", "members":{ @@ -4938,6 +5646,43 @@ } } }, + "ListCertificateAuthoritiesRequest":{ + "type":"structure", + "required":["clusterName"], + "members":{ + "clusterName":{ + "shape":"String", + "documentation":"

    The name of your cluster.

    ", + "location":"uri", + "locationName":"name" + }, + "maxResults":{ + "shape":"CertificateAuthorityMaxResults", + "documentation":"

    The maximum number of results to return in a single call. To retrieve the remaining results, make another call with the returned nextToken value. If you don't specify a value, the default is 100 results.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The nextToken value returned from a previous paginated request, where maxResults was used and the results exceeded the value of that parameter. Pagination continues from the end of the previous results that returned the nextToken value. This value is null when there are no more results to return.

    This token should be treated as an opaque identifier that is used only to retrieve the next items in a list and not for other programmatic purposes.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListCertificateAuthoritiesResponse":{ + "type":"structure", + "members":{ + "certificateAuthorities":{ + "shape":"CertificateAuthoritySummaryList", + "documentation":"

    A list of certificate authority summary objects, each containing basic information about a certificate authority, including its ID, signing status, and distribution status.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The nextToken value to include in a future ListCertificateAuthorities request. When the results of a ListCertificateAuthorities request exceed maxResults, you can use this value to retrieve the next page of results. This value is null when there are no more results to return.

    This token should be treated as an opaque identifier that is used only to retrieve the next items in a list and not for other programmatic purposes.

    " + } + } + }, "ListClustersRequest":{ "type":"structure", "members":{ @@ -5437,6 +6182,26 @@ "type":"list", "member":{"shape":"NodeRepairConfigOverrides"} }, + "NodeResourcesFitConfig":{ + "type":"structure", + "members":{ + "scoringStrategy":{ + "shape":"ScoringStrategy", + "documentation":"

    The scoring strategy used to rank nodes during scheduling.

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

    The NodeResourcesFit plugin configuration for the Kubernetes scheduler.

    " + }, + "NodeResourcesFitVersionConfig":{ + "type":"structure", + "members":{ + "scoringStrategy":{ + "shape":"ScoringStrategyConfig", + "documentation":"

    The scoring strategy configuration with default value and constraints.

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

    The NodeResourcesFit version configuration with default value and constraints.

    " + }, "Nodegroup":{ "type":"structure", "members":{ @@ -5853,6 +6618,36 @@ "max":100, "min":1 }, + "PodGcControllerConfigRequest":{ + "type":"structure", + "members":{ + "terminatedPodGcThreshold":{ + "shape":"TerminatedPodGcThresholdValue", + "documentation":"

    The number of terminated pods that can exist before the garbage collector starts deleting them.

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

    The pod garbage collection controller configuration for the Kubernetes controller manager.

    " + }, + "PodGcControllerConfigResponse":{ + "type":"structure", + "members":{ + "terminatedPodGcThreshold":{ + "shape":"TerminatedPodGcThresholdValue", + "documentation":"

    The number of terminated pods that can exist before the garbage collector starts deleting them.

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

    The pod garbage collection controller configuration for the Kubernetes controller manager.

    " + }, + "PodGcControllerVersionConfig":{ + "type":"structure", + "members":{ + "terminatedPodGcThreshold":{ + "shape":"IntegerParameterConfig", + "documentation":"

    The terminated pod garbage collection threshold configuration with default value and constraints.

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

    The pod garbage collection controller version configuration.

    " + }, "PodIdentityAssociation":{ "type":"structure", "members":{ @@ -5949,6 +6744,34 @@ }, "documentation":"

    The summarized description of the association.

    Each summary is simplified by removing these fields compared to the full PodIdentityAssociation :

    • The IAM role: roleArn

    • The timestamp that the association was created at: createdAt

    • The most recent timestamp that the association was modified at:. modifiedAt

    • The tags on the association: tags

    " }, + "PortRangeConstraints":{ + "type":"structure", + "members":{ + "minPort":{ + "shape":"IntegerRangeConstraint", + "documentation":"

    The constraints for the minimum port value.

    " + }, + "maxPort":{ + "shape":"IntegerRangeConstraint", + "documentation":"

    The constraints for the maximum port value.

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

    Constraints for a port range parameter.

    " + }, + "PortRangeParameterConfig":{ + "type":"structure", + "members":{ + "defaultValue":{ + "shape":"ServiceNodePortRange", + "documentation":"

    The default port range value.

    " + }, + "constraints":{ + "shape":"PortRangeConstraints", + "documentation":"

    The constraints for the port range parameter.

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

    A port range parameter configuration with default value and constraints.

    " + }, "Provider":{ "type":"structure", "members":{ @@ -6089,6 +6912,20 @@ "PRESERVE" ] }, + "ResourceConstraints":{ + "type":"structure", + "members":{ + "name":{ + "shape":"AllowedValuesConstraint", + "documentation":"

    The allowed values for resource names.

    " + }, + "weight":{ + "shape":"IntegerRangeConstraint", + "documentation":"

    The allowed range for resource weight values.

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

    Constraints for resource weight entries.

    " + }, "ResourceInUseException":{ "type":"structure", "members":{ @@ -6181,6 +7018,39 @@ "error":{"httpStatusCode":428}, "exception":true }, + "ResourceWeight":{ + "type":"structure", + "members":{ + "name":{ + "shape":"ResourceWeightName", + "documentation":"

    The name of the resource (for example, cpu or memory).

    " + }, + "weight":{ + "shape":"ResourceWeightValue", + "documentation":"

    The weight assigned to the resource for scoring. Must be between 1 and 100.

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

    A resource weight entry for the scheduler scoring strategy.

    " + }, + "ResourceWeightList":{ + "type":"list", + "member":{"shape":"ResourceWeight"}, + "documentation":"

    A list of resource weights for the scoring strategy.

    ", + "max":100 + }, + "ResourceWeightName":{ + "type":"string", + "documentation":"

    The name of a resource used in the scheduler scoring strategy.

    ", + "max":253, + "min":1 + }, + "ResourceWeightValue":{ + "type":"integer", + "documentation":"

    The weight value for a resource in the scheduler scoring strategy. Must be between 1 and 100.

    ", + "box":true, + "max":100, + "min":1 + }, "RoleArn":{ "type":"string", "max":255, @@ -6196,6 +7066,56 @@ }, "documentation":"

    The rollback configuration for the cluster version rollback.

    " }, + "ScoringStrategy":{ + "type":"structure", + "members":{ + "type":{ + "shape":"ScoringStrategyType", + "documentation":"

    The scoring strategy type. Valid values are LeastAllocated or MostAllocated.

    " + }, + "resources":{ + "shape":"ResourceWeightList", + "documentation":"

    The resource weights used for scoring nodes.

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

    The scoring strategy configuration for the NodeResourcesFit scheduler plugin.

    " + }, + "ScoringStrategyConfig":{ + "type":"structure", + "members":{ + "defaultValue":{ + "shape":"ScoringStrategy", + "documentation":"

    The default scoring strategy.

    " + }, + "constraints":{ + "shape":"ScoringStrategyConstraints", + "documentation":"

    The constraints for the scoring strategy.

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

    The scoring strategy configuration with default value and constraints.

    " + }, + "ScoringStrategyConstraints":{ + "type":"structure", + "members":{ + "scoringStrategy":{ + "shape":"AllowedValuesConstraint", + "documentation":"

    The allowed values for the scoring strategy type.

    " + }, + "resources":{ + "shape":"ResourceConstraints", + "documentation":"

    The constraints for resource weights.

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

    Constraints for the scoring strategy configuration.

    " + }, + "ScoringStrategyType":{ + "type":"string", + "documentation":"

    The scoring strategy type for the NodeResourcesFit scheduler plugin.

    ", + "enum":[ + "LeastAllocated", + "MostAllocated" + ] + }, "ServerException":{ "type":"structure", "members":{ @@ -6225,6 +7145,20 @@ "exception":true, "fault":true }, + "ServiceNodePortRange":{ + "type":"structure", + "members":{ + "minPort":{ + "shape":"Integer", + "documentation":"

    The minimum port number in the range.

    " + }, + "maxPort":{ + "shape":"Integer", + "documentation":"

    The maximum port number in the range.

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

    The port range for Kubernetes NodePort services.

    " + }, "ServiceUnavailableException":{ "type":"structure", "members":{ @@ -6405,6 +7339,13 @@ "PREFER_NO_SCHEDULE" ] }, + "TerminatedPodGcThresholdValue":{ + "type":"integer", + "documentation":"

    The threshold for the number of terminated pods before garbage collection starts.

    ", + "box":true, + "max":1000000, + "min":1 + }, "ThrottlingException":{ "type":"structure", "members":{ @@ -6727,6 +7668,18 @@ "controlPlaneScalingConfig":{ "shape":"ControlPlaneScalingConfig", "documentation":"

    The control plane scaling tier configuration. For more information, see EKS Provisioned Control Plane in the Amazon EKS User Guide.

    " + }, + "kubeApiServerConfig":{ + "shape":"KubeApiServerConfigRequest", + "documentation":"

    The Kubernetes API server configuration for the updated cluster.

    " + }, + "kubeSchedulerConfig":{ + "shape":"KubeSchedulerConfigRequest", + "documentation":"

    The Kubernetes scheduler configuration for the updated cluster.

    " + }, + "kubeControllerManagerConfig":{ + "shape":"KubeControllerManagerConfigRequest", + "documentation":"

    The Kubernetes controller manager configuration for the updated cluster.

    " } } }, @@ -6995,7 +7948,14 @@ "WarmPoolMinSize", "WarmPoolState", "WarmPoolReuseOnScaleIn", - "ControlPlaneEgressMode" + "ControlPlaneEgressMode", + "KubeApiServerConfig", + "KubeSchedulerConfig", + "KubeControllerManagerConfig", + "ActiveCertificateAuthority", + "TrustedCertificateAuthorities", + "CertificateAuthorityId", + "SigningStatus" ] }, "UpdateParams":{ @@ -7112,7 +8072,9 @@ "ControlPlaneScalingConfigUpdate", "VendedLogsUpdate", "ControlPlaneEgressUpdate", - "VersionRollback" + "VersionRollback", + "ControlPlaneComponentConfigUpdate", + "CertificateAuthorityUpdate" ] }, "UpgradePolicyRequest":{ diff --git a/services/eks/src/main/resources/codegen-resources/waiters-2.json b/services/eks/src/main/resources/codegen-resources/waiters-2.json index c06890979c8e..0db7f42d8a08 100644 --- a/services/eks/src/main/resources/codegen-resources/waiters-2.json +++ b/services/eks/src/main/resources/codegen-resources/waiters-2.json @@ -172,6 +172,31 @@ "state": "success" } ] + }, + "CertificateAuthorityUpdateComplete": { + "delay": 30, + "operation": "DescribeUpdate", + "maxAttempts": 40, + "acceptors": [ + { + "expected": "Failed", + "matcher": "path", + "state": "failure", + "argument": "update.status" + }, + { + "expected": "Cancelled", + "matcher": "path", + "state": "failure", + "argument": "update.status" + }, + { + "expected": "Successful", + "matcher": "path", + "state": "success", + "argument": "update.status" + } + ] } } } diff --git a/services/eksauth/pom.xml b/services/eksauth/pom.xml index 704955b10c92..6332aee366ad 100644 --- a/services/eksauth/pom.xml +++ b/services/eksauth/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT eksauth AWS Java SDK :: Services :: EKS Auth diff --git a/services/eksauth/src/main/resources/codegen-resources/customization.config b/services/eksauth/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/eksauth/src/main/resources/codegen-resources/customization.config +++ b/services/eksauth/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/eksauth/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/eksauth/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..de02e29918e3 --- /dev/null +++ b/services/eksauth/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,157 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-auth-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-auth.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-auth-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://eks-auth.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAAAAAkAAAADAAAAAQAAAAQF9eEIAAAAAgAAAAUF9eEIAAAAAwAAAAcAAAAGAAAABQX14QUF9eEHAAAABAAAAAgF9eEEAAAABQX14QMF9eEGAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/eksauth/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/eksauth/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 13b48f631555..000000000000 --- a/services/eksauth/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://eks-auth-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://eks-auth.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://eks-auth-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://eks-auth.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/eksauth/src/main/resources/codegen-resources/paginators-1.json b/services/eksauth/src/main/resources/codegen-resources/paginators-1.json index 5677bd8e4a2d..ea142457a6a7 100644 --- a/services/eksauth/src/main/resources/codegen-resources/paginators-1.json +++ b/services/eksauth/src/main/resources/codegen-resources/paginators-1.json @@ -1,4 +1,3 @@ { - "pagination": { - } + "pagination": {} } diff --git a/services/eksauth/src/main/resources/codegen-resources/service-2.json b/services/eksauth/src/main/resources/codegen-resources/service-2.json index 572ee10049b8..8943490819ab 100644 --- a/services/eksauth/src/main/resources/codegen-resources/service-2.json +++ b/services/eksauth/src/main/resources/codegen-resources/service-2.json @@ -2,9 +2,10 @@ "version":"2.0", "metadata":{ "apiVersion":"2023-11-26", + "auth":["aws.auth#sigv4"], "endpointPrefix":"eks-auth", - "jsonVersion":"1.1", "protocol":"rest-json", + "protocols":["rest-json"], "serviceFullName":"Amazon EKS Auth", "serviceId":"EKS Auth", "signatureVersion":"v4", @@ -64,6 +65,18 @@ "token":{ "shape":"JwtToken", "documentation":"

    The token of the Kubernetes service account for the pod.

    " + }, + "eksNodeName":{ + "shape":"String", + "documentation":"

    The Kubernetes node name of the worker node where the pod is running.

    " + }, + "instanceId":{ + "shape":"String", + "documentation":"

    The Amazon EC2 instance ID of the worker node where the pod is running.

    " + }, + "zone":{ + "shape":"String", + "documentation":"

    The Availability Zone ID of the worker node where the pod is running.

    " } } }, diff --git a/services/elasticache/pom.xml b/services/elasticache/pom.xml index 93f43732ca3f..55301ad77e5e 100644 --- a/services/elasticache/pom.xml +++ b/services/elasticache/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elasticache AWS Java SDK :: Services :: Amazon ElastiCache diff --git a/services/elasticache/src/main/resources/codegen-resources/customization.config b/services/elasticache/src/main/resources/codegen-resources/customization.config index 058279f29fbc..1e040aa53d16 100644 --- a/services/elasticache/src/main/resources/codegen-resources/customization.config +++ b/services/elasticache/src/main/resources/codegen-resources/customization.config @@ -13,8 +13,6 @@ "excludedSimpleMethods": [ "describeCacheSecurityGroups", "listAllowedNodeTypeModifications" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/elasticache/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elasticache/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..323841de0f8a --- /dev/null +++ b/services/elasticache/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticache-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticache.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticache-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticache.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticache.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elasticache/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elasticache/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c4558a6f065e..000000000000 --- a/services/elasticache/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticache-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://elasticache.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticache-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticache.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticache.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/elasticbeanstalk/pom.xml b/services/elasticbeanstalk/pom.xml index e9c84f006fb8..6723b3732b3d 100644 --- a/services/elasticbeanstalk/pom.xml +++ b/services/elasticbeanstalk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elasticbeanstalk AWS Java SDK :: Services :: AWS Elastic Beanstalk diff --git a/services/elasticbeanstalk/src/main/resources/codegen-resources/customization.config b/services/elasticbeanstalk/src/main/resources/codegen-resources/customization.config index 28d4e91910df..92ab967f4f78 100644 --- a/services/elasticbeanstalk/src/main/resources/codegen-resources/customization.config +++ b/services/elasticbeanstalk/src/main/resources/codegen-resources/customization.config @@ -42,8 +42,6 @@ "describeEvents", "listAvailableSolutionStacks", "listPlatformVersions" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bd70695ce45b --- /dev/null +++ b/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticbeanstalk-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticbeanstalk.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticbeanstalk-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticbeanstalk.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticbeanstalk.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cdf70ae58bcb..000000000000 --- a/services/elasticbeanstalk/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticbeanstalk-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://elasticbeanstalk.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticbeanstalk-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticbeanstalk.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticbeanstalk.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/elasticbeanstalk/src/main/resources/codegen-resources/service-2.json b/services/elasticbeanstalk/src/main/resources/codegen-resources/service-2.json index d4fd77188956..6b342aebe6ca 100644 --- a/services/elasticbeanstalk/src/main/resources/codegen-resources/service-2.json +++ b/services/elasticbeanstalk/src/main/resources/codegen-resources/service-2.json @@ -53,7 +53,7 @@ "errors":[ {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Add or change the operations role used by an environment. After this call is made, Elastic Beanstalk uses the associated operations role for permissions to downstream services during subsequent calls acting on this environment. For more information, see Operations roles in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    The operations role feature of Elastic Beanstalk is in beta release and is subject to change.

    Add or change the operations role used by an environment. After this call is made, Elastic Beanstalk uses the associated operations role for permissions to downstream services during subsequent calls acting on this environment.

    " }, "CheckDNSAvailability":{ "name":"CheckDNSAvailability", @@ -119,7 +119,7 @@ {"shape":"S3LocationNotInServiceRegionException"}, {"shape":"CodeBuildNotInServiceRegionException"} ], - "documentation":"

    Creates an application version for the specified application. You can create an application version from a source bundle in Amazon S3, a commit in AWS CodeCommit, or the output of an AWS CodeBuild build as follows:

    Specify a commit in an AWS CodeCommit repository with SourceBuildInformation.

    Specify a build in an AWS CodeBuild with SourceBuildInformation and BuildConfiguration.

    Specify a source bundle in S3 with SourceBundle

    Omit both SourceBuildInformation and SourceBundle to use the default sample application.

    After you create an application version with a specified Amazon S3 bucket and key location, you can't change that Amazon S3 location. If you change the Amazon S3 location, you receive an exception when you attempt to launch an environment from the application version.

    " + "documentation":"

    Creates an application version for the specified application. You can create an application version from a source bundle in Amazon S3, a commit in CodeCommit, or the output of an CodeBuild build as follows:

    Specify a commit in an CodeCommit repository with SourceBuildInformation.

    Specify a build in an CodeBuild with SourceBuildInformation and BuildConfiguration.

    Specify a source bundle in Amazon S3 with SourceBundle

    Omit both SourceBuildInformation and SourceBundle to use the default sample application.

    After you create an application version with a specified Amazon S3 bucket and key location, you can't change that Amazon S3 location. If you change the Amazon S3 location, you receive an exception when you attempt to launch an environment from the application version.

    " }, "CreateConfigurationTemplate":{ "name":"CreateConfigurationTemplate", @@ -137,7 +137,7 @@ {"shape":"TooManyBucketsException"}, {"shape":"TooManyConfigurationTemplatesException"} ], - "documentation":"

    Creates an AWS Elastic Beanstalk configuration template, associated with a specific Elastic Beanstalk application. You define application configuration settings in a configuration template. You can then use the configuration template to deploy different versions of the application with the same configuration settings.

    Templates aren't associated with any environment. The EnvironmentName response element is always null.

    Related Topics

    " + "documentation":"

    Creates an Elastic Beanstalk configuration template, associated with a specific Elastic Beanstalk application. You define application configuration settings in a configuration template. You can then use the configuration template to deploy different versions of the application with the same configuration settings.

    Templates aren't associated with any environment. The EnvironmentName response element is always null.

    Related Topics

    " }, "CreateEnvironment":{ "name":"CreateEnvironment", @@ -154,7 +154,7 @@ {"shape":"TooManyEnvironmentsException"}, {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Launches an AWS Elastic Beanstalk environment for the specified application using the specified configuration.

    " + "documentation":"

    Launches an Elastic Beanstalk environment for the specified application using the specified configuration.

    " }, "CreatePlatformVersion":{ "name":"CreatePlatformVersion", @@ -271,7 +271,7 @@ "errors":[ {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Returns attributes related to AWS Elastic Beanstalk that are associated with the calling AWS account.

    The result currently has one set of attributes—resource quotas.

    " + "documentation":"

    Returns attributes related to Elastic Beanstalk that are associated with the calling Amazon Web Services account.

    The result currently has one set of attributes—resource quotas.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeApplicationVersions":{ "name":"DescribeApplicationVersions", @@ -284,7 +284,7 @@ "shape":"ApplicationVersionDescriptionsMessage", "resultWrapper":"DescribeApplicationVersionsResult" }, - "documentation":"

    Retrieve a list of application versions.

    " + "documentation":"

    Retrieve a list of application versions.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeApplications":{ "name":"DescribeApplications", @@ -297,7 +297,7 @@ "shape":"ApplicationDescriptionsMessage", "resultWrapper":"DescribeApplicationsResult" }, - "documentation":"

    Returns the descriptions of existing applications.

    " + "documentation":"

    Returns the descriptions of existing applications.

    This action only returns information about applications that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access two of three applications. When the user calls the DescribeApplications action, the response will only include the two applications that the user has permission to access instead of all three applications. If the user doesn’t have access to any of the applications an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeConfigurationOptions":{ "name":"DescribeConfigurationOptions", @@ -313,7 +313,7 @@ "errors":[ {"shape":"TooManyBucketsException"} ], - "documentation":"

    Describes the configuration options that are used in a particular configuration template or environment, or that a specified solution stack defines. The description includes the values the options, their default values, and an indication of the required action on a running environment if an option value is changed.

    " + "documentation":"

    Describes the configuration options that are used in a particular configuration template or environment, or that a specified solution stack defines. The description includes the values the options, their default values, and an indication of the required action on a running environment if an option value is changed.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeConfigurationSettings":{ "name":"DescribeConfigurationSettings", @@ -329,7 +329,7 @@ "errors":[ {"shape":"TooManyBucketsException"} ], - "documentation":"

    Returns a description of the settings for the specified configuration set, that is, either a configuration template or the configuration set associated with a running environment.

    When describing the settings for the configuration set associated with a running environment, it is possible to receive two sets of setting descriptions. One is the deployed configuration set, and the other is a draft configuration of an environment that is either in the process of deployment or that failed to deploy.

    Related Topics

    " + "documentation":"

    Returns a description of the settings for the specified configuration set, that is, either a configuration template or the configuration set associated with a running environment.

    When describing the settings for the configuration set associated with a running environment, it is possible to receive two sets of setting descriptions. One is the deployed configuration set, and the other is a draft configuration of an environment that is either in the process of deployment or that failed to deploy.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    Related Topics

    " }, "DescribeEnvironmentHealth":{ "name":"DescribeEnvironmentHealth", @@ -346,7 +346,7 @@ {"shape":"InvalidRequestException"}, {"shape":"ElasticBeanstalkServiceException"} ], - "documentation":"

    Returns information about the overall health of the specified environment. The DescribeEnvironmentHealth operation is only available with AWS Elastic Beanstalk Enhanced Health.

    " + "documentation":"

    Returns information about the overall health of the specified environment. The DescribeEnvironmentHealth operation is only available with Elastic Beanstalk Enhanced Health.

    This action only returns information about environments that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three environments. When the user calls this action, the response will only include the one environment that the user has permission to access instead of all three environments. If the user doesn’t have access to any of the environments an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeEnvironmentManagedActionHistory":{ "name":"DescribeEnvironmentManagedActionHistory", @@ -378,7 +378,7 @@ "errors":[ {"shape":"ElasticBeanstalkServiceException"} ], - "documentation":"

    Lists an environment's upcoming and in-progress managed actions.

    " + "documentation":"

    Lists an environment's upcoming and in-progress managed actions.

    This action only returns information about environments that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three environments. When the user calls this action, the response will only include the one environment that the user has permission to access instead of all three environments. If the user doesn’t have access to any of the environments an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeEnvironmentResources":{ "name":"DescribeEnvironmentResources", @@ -394,7 +394,7 @@ "errors":[ {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Returns AWS resources for this environment.

    " + "documentation":"

    Returns Amazon Web Services resources for this environment.

    " }, "DescribeEnvironments":{ "name":"DescribeEnvironments", @@ -407,7 +407,7 @@ "shape":"EnvironmentDescriptionsMessage", "resultWrapper":"DescribeEnvironmentsResult" }, - "documentation":"

    Returns descriptions for existing environments.

    " + "documentation":"

    Returns descriptions for existing environments.

    This action only returns information about environments that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three environments. When the user calls the DescribeEnvironments action, the response will only include the one environment that the user has permission to access instead of all three environments. If the user doesn’t have access to any of the environments an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeEvents":{ "name":"DescribeEvents", @@ -420,7 +420,7 @@ "shape":"EventDescriptionsMessage", "resultWrapper":"DescribeEventsResult" }, - "documentation":"

    Returns list of event descriptions matching criteria up to the last 6 weeks.

    This action returns the most recent 1,000 events from the specified NextToken.

    " + "documentation":"

    Returns list of event descriptions matching criteria up to the last 6 weeks.

    This action returns the most recent 1,000 events from the specified NextToken.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribeInstancesHealth":{ "name":"DescribeInstancesHealth", @@ -437,7 +437,7 @@ {"shape":"InvalidRequestException"}, {"shape":"ElasticBeanstalkServiceException"} ], - "documentation":"

    Retrieves detailed information about the health of instances in your AWS Elastic Beanstalk. This operation requires enhanced health reporting.

    " + "documentation":"

    Retrieves detailed information about the health of instances in your Elastic Beanstalk environments. This operation requires enhanced health reporting.

    This action only returns information about environments that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three environments. When the user calls this action, the response will only include the one environment that the user has permission to access instead of all three environments. If the user doesn’t have access to any of the environments an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DescribePlatformVersion":{ "name":"DescribePlatformVersion", @@ -454,7 +454,7 @@ {"shape":"InsufficientPrivilegesException"}, {"shape":"ElasticBeanstalkServiceException"} ], - "documentation":"

    Describes a platform version. Provides full details. Compare to ListPlatformVersions, which provides summary information about a list of platform versions.

    For definitions of platform version and other platform-related terms, see AWS Elastic Beanstalk Platforms Glossary.

    " + "documentation":"

    Describes a platform version. Provides full details. Compare to ListPlatformVersions, which provides summary information about a list of platform versions.

    For definitions of platform version and other platform-related terms, see Elastic Beanstalk Platforms Glossary.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "DisassociateEnvironmentOperationsRole":{ "name":"DisassociateEnvironmentOperationsRole", @@ -466,7 +466,7 @@ "errors":[ {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Disassociate the operations role from an environment. After this call is made, Elastic Beanstalk uses the caller's permissions for permissions to downstream services during subsequent calls acting on this environment. For more information, see Operations roles in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    The operations role feature of Elastic Beanstalk is in beta release and is subject to change.

    Disassociate the operations role from an environment. After this call is made, Elastic Beanstalk uses the caller's permissions for permissions to downstream services during subsequent calls acting on this environment.

    " }, "ListAvailableSolutionStacks":{ "name":"ListAvailableSolutionStacks", @@ -478,7 +478,7 @@ "shape":"ListAvailableSolutionStacksResultMessage", "resultWrapper":"ListAvailableSolutionStacksResult" }, - "documentation":"

    Returns a list of the available solution stack names, with the public version first and then in reverse chronological order.

    " + "documentation":"

    Returns a list of the available solution stack names, with the public version first and then in reverse chronological order.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "ListPlatformBranches":{ "name":"ListPlatformBranches", @@ -491,7 +491,7 @@ "shape":"ListPlatformBranchesResult", "resultWrapper":"ListPlatformBranchesResult" }, - "documentation":"

    Lists the platform branches available for your account in an AWS Region. Provides summary information about each platform branch.

    For definitions of platform branch and other platform-related terms, see AWS Elastic Beanstalk Platforms Glossary.

    " + "documentation":"

    Lists the platform branches available for your account in an Amazon Web Services Region. Provides summary information about each platform branch.

    For definitions of platform branch and other platform-related terms, see Elastic Beanstalk Platforms Glossary.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "ListPlatformVersions":{ "name":"ListPlatformVersions", @@ -508,7 +508,7 @@ {"shape":"InsufficientPrivilegesException"}, {"shape":"ElasticBeanstalkServiceException"} ], - "documentation":"

    Lists the platform versions available for your account in an AWS Region. Provides summary information about each platform version. Compare to DescribePlatformVersion, which provides full details about a single platform version.

    For definitions of platform version and other platform-related terms, see AWS Elastic Beanstalk Platforms Glossary.

    " + "documentation":"

    Lists the platform versions available for your account in an Amazon Web Services Region. Provides summary information about each platform version. Compare to DescribePlatformVersion, which provides full details about a single platform version.

    This action only returns information about platform versions that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of ten platform versions. When the user calls the ListPlatformVersions action, the response will only include the one platform version that the user has permission to access instead of all ten platform versions. If the user doesn’t have access to any of the platform versions an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk environments. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    For definitions of platform version and other platform-related terms, see Elastic Beanstalk Platforms Glossary.

    " }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -526,7 +526,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ResourceTypeNotSupportedException"} ], - "documentation":"

    Return the tags applied to an AWS Elastic Beanstalk resource. The response contains a list of tag key-value pairs.

    Elastic Beanstalk supports tagging of all of its resources. For details about resource tagging, see Tagging Application Resources.

    " + "documentation":"

    Return the tags applied to an Elastic Beanstalk resource. The response contains a list of tag key-value pairs.

    Elastic Beanstalk supports tagging of all of its resources. For details about resource tagging, see Tagging Application Resources.

    This action only returns information about resources that the calling principle has IAM permissions to access. For example, consider a case where a user only has permission to access one of three resources. When the user calls the this action, the response will only include the one resource that the user has permission to access instead of all three resources. If the user doesn’t have access to any of the resources an empty result is returned.

    The AWSElasticBeanstalkReadOnly managed policy allows operators to view information about resources related to Elastic Beanstalk. For more information, see Managing Elastic Beanstalk user policies in the Elastic Beanstalk Developer Guide. For detailed instructions to attach a policy to a user or group, see the section Controlling access with managed policies in the same topic.

    " }, "RebuildEnvironment":{ "name":"RebuildEnvironment", @@ -538,7 +538,7 @@ "errors":[ {"shape":"InsufficientPrivilegesException"} ], - "documentation":"

    Deletes and recreates all of the AWS resources (for example: the Auto Scaling group, load balancer, etc.) for a specified environment and forces a restart.

    " + "documentation":"

    Deletes and recreates all of the Amazon Web Services resources (for example: the Auto Scaling group, load balancer, etc.) for a specified environment and forces a restart.

    " }, "RequestEnvironmentInfo":{ "name":"RequestEnvironmentInfo", @@ -670,7 +670,7 @@ {"shape":"InsufficientPrivilegesException"}, {"shape":"TooManyBucketsException"} ], - "documentation":"

    Updates the environment description, deploys a new application version, updates the configuration settings to an entirely new configuration template, or updates select configuration option values in the running environment.

    Attempting to update both the release and configuration is not allowed and AWS Elastic Beanstalk returns an InvalidParameterCombination error.

    When updating the configuration settings to a new template or individual settings, a draft configuration is created and DescribeConfigurationSettings for this environment returns two setting descriptions with different DeploymentStatus values.

    " + "documentation":"

    Updates the environment description, deploys a new application version, updates the configuration settings to an entirely new configuration template, or updates select configuration option values in the running environment.

    Attempting to update both the release and configuration is not allowed and Elastic Beanstalk returns an InvalidParameterCombination error.

    When updating the configuration settings to a new template or individual settings, a draft configuration is created and DescribeConfigurationSettings for this environment returns two setting descriptions with different DeploymentStatus values.

    " }, "UpdateTagsForResource":{ "name":"UpdateTagsForResource", @@ -686,7 +686,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ResourceTypeNotSupportedException"} ], - "documentation":"

    Update the list of tags applied to an AWS Elastic Beanstalk resource. Two lists can be passed: TagsToAdd for tags to add or update, and TagsToRemove.

    Elastic Beanstalk supports tagging of all of its resources. For details about resource tagging, see Tagging Application Resources.

    If you create a custom IAM user policy to control permission to this operation, specify one of the following two virtual actions (or both) instead of the API operation name:

    elasticbeanstalk:AddTags

    Controls permission to call UpdateTagsForResource and pass a list of tags to add in the TagsToAdd parameter.

    elasticbeanstalk:RemoveTags

    Controls permission to call UpdateTagsForResource and pass a list of tag keys to remove in the TagsToRemove parameter.

    For details about creating a custom user policy, see Creating a Custom User Policy.

    " + "documentation":"

    Update the list of tags applied to an Elastic Beanstalk resource. Two lists can be passed: TagsToAdd for tags to add or update, and TagsToRemove.

    Elastic Beanstalk supports tagging of all of its resources. For details about resource tagging, see Tagging Application Resources.

    If you create a custom policy to control permission to this operation, specify one of the following two virtual actions (or both) instead of the API operation name:

    elasticbeanstalk:AddTags

    Controls permission to call UpdateTagsForResource and pass a list of tags to add in the TagsToAdd parameter.

    elasticbeanstalk:RemoveTags

    Controls permission to call UpdateTagsForResource and pass a list of tag keys to remove in the TagsToRemove parameter.

    For details about creating a custom user policy, see Creating a Custom User Policy.

    " }, "ValidateConfigurationSettings":{ "name":"ValidateConfigurationSettings", @@ -831,7 +831,7 @@ "documentation":"

    Represents the average latency for the slowest X percent of requests over the last 10 seconds. Latencies are in seconds with one millisecond resolution.

    " } }, - "documentation":"

    Application request metrics for an AWS Elastic Beanstalk environment.

    " + "documentation":"

    Application request metrics for an Elastic Beanstalk environment.

    " }, "ApplicationName":{ "type":"string", @@ -854,7 +854,7 @@ "documentation":"

    Defines lifecycle settings for application versions.

    " } }, - "documentation":"

    The resource lifecycle configuration for an application. Defines lifecycle settings for resources that belong to the application, and the service role that AWS Elastic Beanstalk assumes in order to apply lifecycle settings. The version lifecycle configuration defines lifecycle settings for application versions.

    " + "documentation":"

    The resource lifecycle configuration for an application. Defines lifecycle settings for resources that belong to the application, and the service role that Elastic Beanstalk assumes in order to apply lifecycle settings. The version lifecycle configuration defines lifecycle settings for application versions.

    " }, "ApplicationResourceLifecycleDescriptionMessage":{ "type":"structure", @@ -891,16 +891,28 @@ }, "SourceBuildInformation":{ "shape":"SourceBuildInformation", - "documentation":"

    If the version's source code was retrieved from AWS CodeCommit, the location of the source code for the application version.

    " + "documentation":"

    If the version's source code was retrieved from CodeCommit, the location of the source code for the application version.

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

    Reference to the artifact from the AWS CodeBuild build.

    " + "documentation":"

    Reference to the artifact from the CodeBuild build.

    " }, "SourceBundle":{ "shape":"S3Location", "documentation":"

    The storage location of the application version's source bundle in Amazon S3.

    " }, + "ImageSource":{ + "shape":"ImageSource", + "documentation":"

    The location of the container image for the application version.

    For an application version created from an image you provide, this is that image. For one that Elastic Beanstalk builds from your source bundle, Elastic Beanstalk fills this in with the image it pushed after the build succeeds.

    " + }, + "ImageBuildConfiguration":{ + "shape":"ImageBuildConfiguration", + "documentation":"

    The settings that Elastic Beanstalk uses to build a container image from the source bundle of the application version. Not present for an application version created from an image you provide.

    " + }, + "Process":{ + "shape":"ApplicationVersionProccess", + "documentation":"

    Indicates whether Elastic Beanstalk pre-processed and validated the environment manifest (env.yaml) and configuration files (*.config files in the .ebextensions folder) in the source bundle of the application version.

    " + }, "DateCreated":{ "shape":"CreationDate", "documentation":"

    The creation date of the application version.

    " @@ -911,7 +923,7 @@ }, "Status":{ "shape":"ApplicationVersionStatus", - "documentation":"

    The processing status of the application version. Reflects the state of the application version during its creation. Many of the values are only applicable if you specified True for the Process parameter of the CreateApplicationVersion action. The following list describes the possible values.

    • Unprocessed – Application version wasn't pre-processed or validated. Elastic Beanstalk will validate configuration files during deployment of the application version to an environment.

    • Processing – Elastic Beanstalk is currently processing the application version.

    • Building – Application version is currently undergoing an AWS CodeBuild build.

    • Processed – Elastic Beanstalk was successfully pre-processed and validated.

    • Failed – Either the AWS CodeBuild build failed or configuration files didn't pass validation. This application version isn't usable.

    " + "documentation":"

    The processing status of the application version. Reflects the state of the application version during its creation. Many of the values are only applicable if you specified True for the Process parameter of the CreateApplicationVersion action. The following list describes the possible values.

    • Unprocessed – Application version wasn't pre-processed or validated. Elastic Beanstalk will validate configuration files during deployment of the application version to an environment.

    • Processing – Elastic Beanstalk is currently processing the application version.

    • Building – Application version is currently undergoing an CodeBuild build.

    • Processed – Elastic Beanstalk was successfully pre-processed and validated.

    • Failed – Either the CodeBuild build failed or configuration files didn't pass validation. This application version isn't usable.

    " } }, "documentation":"

    Describes the properties of an application version.

    " @@ -1010,6 +1022,13 @@ }, "documentation":"

    The result message containing information about the managed action.

    " }, + "ArchitectureType":{ + "type":"string", + "enum":[ + "amd64", + "arm64" + ] + }, "AssociateEnvironmentOperationsRoleMessage":{ "type":"structure", "required":[ @@ -1068,7 +1087,7 @@ }, "CodeBuildServiceRole":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that enables AWS CodeBuild to interact with dependent AWS services on behalf of the AWS account.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the Identity and Access Management (IAM) role that enables CodeBuild to interact with dependent Amazon Web Services service on behalf of the Amazon Web Services account.

    " }, "ComputeType":{ "shape":"ComputeType", @@ -1080,10 +1099,10 @@ }, "TimeoutInMinutes":{ "shape":"BoxedInt", - "documentation":"

    How long in minutes, from 5 to 480 (8 hours), for AWS CodeBuild to wait until timing out any related build that does not get marked as completed. The default is 60 minutes.

    " + "documentation":"

    How long in minutes, from 5 to 480 (8 hours), for CodeBuild to wait until timing out any related build that does not get marked as completed. The default is 60 minutes.

    " } }, - "documentation":"

    Settings for an AWS CodeBuild build.

    " + "documentation":"

    Settings for an CodeBuild build.

    " }, "Builder":{ "type":"structure", @@ -1167,11 +1186,21 @@ }, "documentation":"

    Indicates if the specified CNAME is available.

    " }, + "Cluster":{ + "type":"structure", + "members":{ + "ClusterArn":{ + "shape":"ResourceId", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon EKS cluster.

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

    Describes the Amazon EKS cluster that an environment runs on.

    " + }, "CnameAvailability":{"type":"boolean"}, "CodeBuildNotInServiceRegionException":{ "type":"structure", "members":{}, - "documentation":"

    AWS CodeBuild is not available in the specified region.

    ", + "documentation":"

    CodeBuild is not available in the specified region.

    ", "error":{ "code":"CodeBuildNotInServiceRegionException", "httpStatusCode":400, @@ -1219,7 +1248,7 @@ "members":{ "Namespace":{ "shape":"OptionNamespace", - "documentation":"

    A unique namespace identifying the option's associated AWS resource.

    " + "documentation":"

    A unique namespace identifying the option's associated Amazon Web Services resource.

    " }, "Name":{ "shape":"ConfigurationOptionName", @@ -1231,7 +1260,7 @@ }, "ChangeSeverity":{ "shape":"ConfigurationOptionSeverity", - "documentation":"

    An indication of which action is required if the value for this configuration option changes:

    • NoInterruption : There is no interruption to the environment or application availability.

    • RestartEnvironment : The environment is entirely restarted, all AWS resources are deleted and recreated, and the environment is unavailable during the process.

    • RestartApplicationServer : The environment is available the entire time. However, a short application outage occurs when the application servers on the running Amazon EC2 instances are restarted.

    " + "documentation":"

    An indication of which action is required if the value for this configuration option changes:

    • NoInterruption : There is no interruption to the environment or application availability.

    • RestartEnvironment : The environment is entirely restarted, all A resources are deleted and recreated, and the environment is unavailable during the process.

    • RestartApplicationServer : The environment is available the entire time. However, a short application outage occurs when the application servers on the running Amazon EC2 instances are restarted.

    " }, "UserDefined":{ "shape":"UserDefinedOption", @@ -1283,7 +1312,7 @@ }, "Namespace":{ "shape":"OptionNamespace", - "documentation":"

    A unique namespace that identifies the option's associated AWS resource.

    " + "documentation":"

    A unique namespace that identifies the option's associated Amazon Web Services resource.

    " }, "OptionName":{ "shape":"ConfigurationOptionName", @@ -1294,7 +1323,7 @@ "documentation":"

    The current value for the configuration option.

    " } }, - "documentation":"

    A specification identifying an individual configuration option along with its current value. For a list of possible namespaces and option values, see Option Values in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    A specification identifying an individual configuration option along with its current value. For a list of possible namespaces and option values, see Option Values in the Elastic Beanstalk Developer Guide.

    " }, "ConfigurationOptionSettingsList":{ "type":"list", @@ -1442,7 +1471,7 @@ }, "VersionLabel":{ "shape":"VersionLabel", - "documentation":"

    A label identifying this version.

    Constraint: Must be unique per application. If an application version already exists with this label for the specified application, AWS Elastic Beanstalk returns an InvalidParameterValue error.

    " + "documentation":"

    A label identifying this version.

    Constraint: Must be unique per application. If an application version already exists with this label for the specified application, Elastic Beanstalk returns an InvalidParameterValue error.

    " }, "Description":{ "shape":"Description", @@ -1450,15 +1479,15 @@ }, "SourceBuildInformation":{ "shape":"SourceBuildInformation", - "documentation":"

    Specify a commit in an AWS CodeCommit Git repository to use as the source code for the application version.

    " + "documentation":"

    Specify a commit in an CodeCommit Git repository to use as the source code for the application version.

    " }, "SourceBundle":{ "shape":"S3Location", - "documentation":"

    The Amazon S3 bucket and key that identify the location of the source bundle for this version.

    The Amazon S3 bucket must be in the same region as the environment.

    Specify a source bundle in S3 or a commit in an AWS CodeCommit repository (with SourceBuildInformation), but not both. If neither SourceBundle nor SourceBuildInformation are provided, Elastic Beanstalk uses a sample application.

    " + "documentation":"

    The Amazon S3 bucket and key that identify the location of the source bundle for this version.

    The Amazon S3 bucket must be in the same region as the environment.

    Unless you're specifying a source bundle in the bucket that Elastic Beanstalk manages in your account, you must assign a custom policy to your user, and grant Allow permission to the s3:Get* actions on your S3 object resource, for example, arn:aws:s3:::your-bucket/your-source-bundle-object.

    Specify a source bundle in Amazon S3 or a commit in an CodeCommit repository (with SourceBuildInformation), but not both. If neither SourceBundle nor SourceBuildInformation are provided, Elastic Beanstalk uses a sample application.

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

    Settings for an AWS CodeBuild build.

    " + "documentation":"

    Settings for an CodeBuild build.

    Don't specify BuildConfiguration together with ImageConfiguration, which configures a container image build instead.

    " }, "AutoCreateApplication":{ "shape":"AutoCreateApplication", @@ -1466,11 +1495,15 @@ }, "Process":{ "shape":"ApplicationVersionProccess", - "documentation":"

    Pre-processes and validates the environment manifest (env.yaml) and configuration files (*.config files in the .ebextensions folder) in the source bundle. Validating configuration files can identify issues prior to deploying the application version to an environment.

    You must turn processing on for application versions that you create using AWS CodeBuild or AWS CodeCommit. For application versions built from a source bundle in Amazon S3, processing is optional.

    The Process option validates Elastic Beanstalk configuration files. It doesn't validate your application's configuration files, like proxy server or Docker configuration.

    " + "documentation":"

    Pre-processes and validates the environment manifest (env.yaml) and configuration files (*.config files in the .ebextensions folder) in the source bundle. Validating configuration files can identify issues prior to deploying the application version to an environment.

    You must turn processing on for application versions that you create using CodeBuild or CodeCommit. For application versions built from a source bundle in Amazon S3, processing is optional.

    The Process option validates Elastic Beanstalk configuration files. It doesn't validate your application's configuration files, like proxy server or Docker configuration.

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

    Specifies the tags applied to the application version.

    Elastic Beanstalk applies these tags only to the application version. Environments that use the application version don't inherit the tags.

    " + }, + "ImageConfiguration":{ + "shape":"ImageConfiguration", + "documentation":"

    The source of the container image for this application version. You can specify an image that you built and pushed to a container registry yourself, or settings for Elastic Beanstalk to build one from your source bundle. Specify exactly one of the Source and Build members.

    Don't specify ImageConfiguration together with BuildConfiguration, which configures an CodeBuild build instead.

    " } }, "documentation":"

    " @@ -1492,11 +1525,11 @@ }, "SolutionStackName":{ "shape":"SolutionStackName", - "documentation":"

    The name of an Elastic Beanstalk solution stack (platform version) that this configuration uses. For example, 64bit Amazon Linux 2013.09 running Tomcat 7 Java 7. A solution stack specifies the operating system, runtime, and application server for a configuration template. It also determines the set of configuration options as well as the possible and default values. For more information, see Supported Platforms in the AWS Elastic Beanstalk Developer Guide.

    You must specify SolutionStackName if you don't specify PlatformArn, EnvironmentId, or SourceConfiguration.

    Use the ListAvailableSolutionStacks API to obtain a list of available solution stacks.

    " + "documentation":"

    The name of an Elastic Beanstalk solution stack (platform version) that this configuration uses. For example, 64bit Amazon Linux 2013.09 running Tomcat 7 Java 7. A solution stack specifies the operating system, runtime, and application server for a configuration template. It also determines the set of configuration options as well as the possible and default values. For more information, see Supported Platforms in the Elastic Beanstalk Developer Guide.

    You must specify SolutionStackName if you don't specify PlatformArn, EnvironmentId, or SourceConfiguration.

    Use the ListAvailableSolutionStacks API to obtain a list of available solution stacks.

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

    The Amazon Resource Name (ARN) of the custom platform. For more information, see Custom Platforms in the AWS Elastic Beanstalk Developer Guide.

    If you specify PlatformArn, then don't specify SolutionStackName.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the custom platform. For more information, see Custom Platforms in the Elastic Beanstalk Developer Guide.

    If you specify PlatformArn, then don't specify SolutionStackName.

    " }, "SourceConfiguration":{ "shape":"SourceConfiguration", @@ -1512,7 +1545,7 @@ }, "OptionSettings":{ "shape":"ConfigurationOptionSettingsList", - "documentation":"

    Option values for the Elastic Beanstalk configuration, such as the instance type. If specified, these values override the values obtained from the solution stack or the source configuration template. For a complete list of Elastic Beanstalk configuration options, see Option Values in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    Option values for the Elastic Beanstalk configuration, such as the instance type. If specified, these values override the values obtained from the solution stack or the source configuration template. For a complete list of Elastic Beanstalk configuration options, see Option Values in the Elastic Beanstalk Developer Guide.

    " }, "Tags":{ "shape":"Tags", @@ -1547,7 +1580,7 @@ }, "Tier":{ "shape":"EnvironmentTier", - "documentation":"

    Specifies the tier to use in creating this environment. The environment tier that you choose determines whether Elastic Beanstalk provisions resources to support a web application that handles HTTP(S) requests or a web application that handles background-processing tasks.

    " + "documentation":"

    Specifies the tier to use in creating this environment. The environment tier that you choose determines whether Elastic Beanstalk provisions resources on Amazon EC2 instances or on an Amazon EKS cluster, and, for Amazon EC2, whether the environment serves HTTP(S) requests or processes background tasks from a queue.

    " }, "Tags":{ "shape":"Tags", @@ -1563,15 +1596,15 @@ }, "SolutionStackName":{ "shape":"SolutionStackName", - "documentation":"

    The name of an Elastic Beanstalk solution stack (platform version) to use with the environment. If specified, Elastic Beanstalk sets the configuration values to the default values associated with the specified solution stack. For a list of current solution stacks, see Elastic Beanstalk Supported Platforms in the AWS Elastic Beanstalk Platforms guide.

    If you specify SolutionStackName, don't specify PlatformArn or TemplateName.

    " + "documentation":"

    The name of an Elastic Beanstalk solution stack (platform version) to use with the environment. If specified, Elastic Beanstalk sets the configuration values to the default values associated with the specified solution stack. For a list of current solution stacks, see Elastic Beanstalk Supported Platforms in the Elastic Beanstalk Platforms guide.

    If you specify SolutionStackName, don't specify PlatformArn or TemplateName.

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

    The Amazon Resource Name (ARN) of the custom platform to use with the environment. For more information, see Custom Platforms in the AWS Elastic Beanstalk Developer Guide.

    If you specify PlatformArn, don't specify SolutionStackName.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the custom platform to use with the environment. For more information, see Custom Platforms in the Elastic Beanstalk Developer Guide.

    If you specify PlatformArn, don't specify SolutionStackName.

    " }, "OptionSettings":{ "shape":"ConfigurationOptionSettingsList", - "documentation":"

    If specified, AWS Elastic Beanstalk sets the specified configuration options to the requested value in the configuration set for the new environment. These override the values obtained from the solution stack or the configuration template.

    " + "documentation":"

    If specified, Elastic Beanstalk sets the specified configuration options to the requested value in the configuration set for the new environment. These override the values obtained from the solution stack or the configuration template.

    " }, "OptionsToRemove":{ "shape":"OptionsSpecifierList", @@ -1579,7 +1612,7 @@ }, "OperationsRole":{ "shape":"OperationsRole", - "documentation":"

    The Amazon Resource Name (ARN) of an existing IAM role to be used as the environment's operations role. If specified, Elastic Beanstalk uses the operations role for permissions to downstream services during this call and during subsequent calls acting on this environment. To specify an operations role, you must have the iam:PassRole permission for the role. For more information, see Operations roles in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    The operations role feature of Elastic Beanstalk is in beta release and is subject to change.

    The Amazon Resource Name (ARN) of an existing IAM role to be used as the environment's operations role. If specified, Elastic Beanstalk uses the operations role for permissions to downstream services during this call and during subsequent calls acting on this environment. To specify an operations role, you must have the iam:PassRole permission for the role.

    " } }, "documentation":"

    " @@ -1791,7 +1824,7 @@ "members":{ "ResourceQuotas":{ "shape":"ResourceQuotas", - "documentation":"

    The Elastic Beanstalk resource quotas associated with the calling AWS account.

    " + "documentation":"

    The Elastic Beanstalk resource quotas associated with the calling Amazon Web Services account.

    " } } }, @@ -1822,7 +1855,7 @@ "members":{ "ApplicationNames":{ "shape":"ApplicationNamesList", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to only include those with the specified names.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to only include those with the specified names.

    " } }, "documentation":"

    Request to describe one or more applications.

    " @@ -1867,11 +1900,11 @@ }, "TemplateName":{ "shape":"ConfigurationTemplateName", - "documentation":"

    The name of the configuration template to describe.

    Conditional: You must specify either this parameter or an EnvironmentName, but not both. If you specify both, AWS Elastic Beanstalk returns an InvalidParameterCombination error. If you do not specify either, AWS Elastic Beanstalk returns a MissingRequiredParameter error.

    " + "documentation":"

    The name of the configuration template to describe.

    Conditional: You must specify either this parameter or an EnvironmentName, but not both. If you specify both, Elastic Beanstalk returns an InvalidParameterCombination error. If you do not specify either, Elastic Beanstalk returns a MissingRequiredParameter error.

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

    The name of the environment to describe.

    Condition: You must specify either this or a TemplateName, but not both. If you specify both, AWS Elastic Beanstalk returns an InvalidParameterCombination error. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to describe.

    Condition: You must specify either this or a TemplateName, but not both. If you specify both, Elastic Beanstalk returns an InvalidParameterCombination error. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " } }, "documentation":"

    Result message containing all of the configuration settings for a specified solution stack or configuration template.

    " @@ -1930,7 +1963,7 @@ "documentation":"

    The date and time that the health information was retrieved.

    " } }, - "documentation":"

    Health details for an AWS Elastic Beanstalk environment.

    " + "documentation":"

    Health details for an Elastic Beanstalk environment.

    " }, "DescribeEnvironmentManagedActionHistoryRequest":{ "type":"structure", @@ -2001,11 +2034,11 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment to retrieve AWS resource usage data.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment to retrieve Amazon Web Services resource usage data.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment to retrieve AWS resource usage data.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to retrieve Amazon Web Services resource usage data.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " } }, "documentation":"

    Request to describe the resources in an environment.

    " @@ -2015,19 +2048,19 @@ "members":{ "ApplicationName":{ "shape":"ApplicationName", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to include only those that are associated with this application.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to include only those that are associated with this application.

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

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to include only those that are associated with this application version.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to include only those that are associated with this application version.

    " }, "EnvironmentIds":{ "shape":"EnvironmentIdList", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to include only those that have the specified IDs.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to include only those that have the specified IDs.

    " }, "EnvironmentNames":{ "shape":"EnvironmentNamesList", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to include only those that have the specified names.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to include only those that have the specified names.

    " }, "IncludeDeleted":{ "shape":"IncludeDeleted", @@ -2053,31 +2086,31 @@ "members":{ "ApplicationName":{ "shape":"ApplicationName", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to include only those associated with this application.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to include only those associated with this application.

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

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those associated with this application version.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those associated with this application version.

    " }, "TemplateName":{ "shape":"ConfigurationTemplateName", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those that are associated with this environment configuration.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those that are associated with this environment configuration.

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

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those associated with this environment.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those associated with this environment.

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

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those associated with this environment.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those associated with this environment.

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

    The ARN of a custom platform version. If specified, AWS Elastic Beanstalk restricts the returned descriptions to those associated with this custom platform version.

    " + "documentation":"

    The ARN of a custom platform version. If specified, Elastic Beanstalk restricts the returned descriptions to those associated with this custom platform version.

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

    If specified, AWS Elastic Beanstalk restricts the described events to include only those associated with this request ID.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the described events to include only those associated with this request ID.

    " }, "Severity":{ "shape":"EventSeverity", @@ -2085,11 +2118,11 @@ }, "StartTime":{ "shape":"TimeFilterStart", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those that occur on or after this time.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those that occur on or after this time.

    " }, "EndTime":{ "shape":"TimeFilterEnd", - "documentation":"

    If specified, AWS Elastic Beanstalk restricts the returned descriptions to those that occur up to, but not including, the EndTime.

    " + "documentation":"

    If specified, Elastic Beanstalk restricts the returned descriptions to those that occur up to, but not including, the EndTime.

    " }, "MaxRecords":{ "shape":"MaxRecords", @@ -2107,11 +2140,11 @@ "members":{ "EnvironmentName":{ "shape":"EnvironmentName", - "documentation":"

    Specify the AWS Elastic Beanstalk environment by name.

    " + "documentation":"

    Specify the Elastic Beanstalk environment by name.

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

    Specify the AWS Elastic Beanstalk environment by ID.

    " + "documentation":"

    Specify the Elastic Beanstalk environment by ID.

    " }, "AttributeNames":{ "shape":"InstancesHealthAttributes", @@ -2140,7 +2173,7 @@ "documentation":"

    Pagination token for the next page of results, if available.

    " } }, - "documentation":"

    Detailed health information about the Amazon EC2 instances in an AWS Elastic Beanstalk environment.

    " + "documentation":"

    Detailed health information about the Amazon EC2 instances in an Elastic Beanstalk environment.

    " }, "DescribePlatformVersionRequest":{ "type":"structure", @@ -2242,7 +2275,7 @@ }, "Status":{ "shape":"EnvironmentStatus", - "documentation":"

    The current operational status of the environment:

    • Launching: Environment is in the process of initial deployment.

    • Updating: Environment is in the process of updating its configuration settings or application version.

    • Ready: Environment is available to have an action performed on it, such as update or terminate.

    • Terminating: Environment is in the shut-down process.

    • Terminated: Environment is not running.

    " + "documentation":"

    The current operational status of the environment:

    • Aborting: Environment is in the process of aborting a deployment.

    • Launching: Environment is in the process of initial deployment.

    • LinkingFrom: Environment is in the process of being linked to by another environment. See Environment links for details.

    • LinkingTo: Environment is in the process of linking to another environment. See Environment links for details.

    • Updating: Environment is in the process of updating its configuration settings or application version.

    • Ready: Environment is available to have an action performed on it, such as update or terminate.

    • Terminating: Environment is in the shut-down process.

    • Terminated: Environment is not running.

    " }, "AbortableOperationInProgress":{ "shape":"AbortableOperationInProgress", @@ -2250,7 +2283,7 @@ }, "Health":{ "shape":"EnvironmentHealth", - "documentation":"

    Describes the health status of the environment. AWS Elastic Beanstalk indicates the failure levels for a running environment:

    • Red: Indicates the environment is not responsive. Occurs when three or more consecutive failures occur for an environment.

    • Yellow: Indicates that something is wrong. Occurs when two consecutive failures occur for an environment.

    • Green: Indicates the environment is healthy and fully functional.

    • Grey: Default health for a new environment. The environment is not fully launched and health checks have not started or health checks are suspended during an UpdateEnvironment or RestartEnvironment request.

    Default: Grey

    " + "documentation":"

    Describes the health status of the environment. Elastic Beanstalk indicates the failure levels for a running environment:

    • Red: Indicates the environment is not responsive. Occurs when three or more consecutive failures occur for an environment.

    • Yellow: Indicates that something is wrong. Occurs when two consecutive failures occur for an environment.

    • Green: Indicates the environment is healthy and fully functional.

    • Grey: Default health for a new environment. The environment is not fully launched and health checks have not started or health checks are suspended during an UpdateEnvironment or RestartEnvironment request.

    Default: Grey

    " }, "HealthStatus":{ "shape":"EnvironmentHealthStatus", @@ -2258,7 +2291,7 @@ }, "Resources":{ "shape":"EnvironmentResourcesDescription", - "documentation":"

    The description of the AWS resources used by this environment.

    " + "documentation":"

    The description of the Amazon Web Services resources used by this environment.

    " }, "Tier":{ "shape":"EnvironmentTier", @@ -2274,7 +2307,7 @@ }, "OperationsRole":{ "shape":"OperationsRole", - "documentation":"

    The Amazon Resource Name (ARN) of the environment's operations role. For more information, see Operations roles in the AWS Elastic Beanstalk Developer Guide.

    " + "documentation":"

    The operations role feature of Elastic Beanstalk is in beta release and is subject to change.

    The Amazon Resource Name (ARN) of the environment's operations role.

    " } }, "documentation":"

    Describes the properties of an environment.

    " @@ -2414,6 +2447,10 @@ "shape":"AutoScalingGroupList", "documentation":"

    The AutoScalingGroups used by this environment.

    " }, + "Cluster":{ + "shape":"Cluster", + "documentation":"

    The Amazon EKS cluster that this environment runs on. This member is present only for environments in the Cluster tier.

    " + }, "Instances":{ "shape":"InstanceList", "documentation":"

    The Amazon EC2 instances used by this environment.

    " @@ -2439,7 +2476,7 @@ "documentation":"

    The queues used by this environment.

    " } }, - "documentation":"

    Describes the AWS resources in use by this environment. This data is live.

    " + "documentation":"

    Describes the Amazon Web Services resources in use by this environment. This data is live.

    " }, "EnvironmentResourceDescriptionsMessage":{ "type":"structure", @@ -2459,7 +2496,7 @@ "documentation":"

    Describes the LoadBalancer.

    " } }, - "documentation":"

    Describes the AWS resources in use by this environment. This data is not live data.

    " + "documentation":"

    Describes the Amazon Web Services resources in use by this environment. This data is not live data.

    " }, "EnvironmentStatus":{ "type":"string", @@ -2479,11 +2516,11 @@ "members":{ "Name":{ "shape":"String", - "documentation":"

    The name of this environment tier.

    Valid values:

    • For Web server tier – WebServer

    • For Worker tier – Worker

    " + "documentation":"

    The name of this environment tier.

    Valid values:

    • For Standard-mode EC2-based web server – WebServer

    • For Standard-mode EC2-based backend application with Amazon SQS – Worker

    • For Cluster-mode Amazon EKS-based applications – Cluster

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

    The type of this environment tier.

    Valid values:

    • For Web server tier – Standard

    • For Worker tier – SQS/HTTP

    " + "documentation":"

    The type of this environment tier.

    Valid values:

    • For Web server tier – Standard

    • For Worker tier – SQS/HTTP

    • For Cluster tier – EKS

    " }, "Version":{ "shape":"String", @@ -2589,7 +2626,72 @@ "max":19, "min":1 }, + "ImageBuildConfiguration":{ + "type":"structure", + "members":{ + "Type":{ + "shape":"ImageBuildType", + "documentation":"

    How Elastic Beanstalk builds the container image. Elastic Beanstalk rejects a Build that doesn't specify it.

    Valid values:

    • docker – Elastic Beanstalk builds the image from a Dockerfile in your source bundle. Specify the Dockerfile with DockerfileLocation.

    • buildpack – Elastic Beanstalk builds the image with a Cloud Native Buildpacks builder. Specify the builder with Buildpack.

    " + }, + "DockerfileLocation":{ + "shape":"String", + "documentation":"

    The path to the Dockerfile within the source bundle, relative to the root of the source bundle. For example, backend/Dockerfile.

    Elastic Beanstalk uses this member only when Type is docker. If you don't specify it, Elastic Beanstalk uses the Dockerfile at the root of the source bundle.

    " + }, + "Buildpack":{ + "shape":"String", + "documentation":"

    The Cloud Native Buildpacks builder image that Elastic Beanstalk uses to build the container image. For example, paketobuildpacks/builder-jammy-base.

    This member is required when Type is buildpack. Elastic Beanstalk doesn't provide a default builder.

    " + }, + "Architecture":{ + "shape":"ArchitectureType", + "documentation":"

    The processor architecture that Elastic Beanstalk builds the container image for. The architecture must match the architecture of the instances in the environment that you deploy the application version to.

    Valid values:

    • amd64 – x86-64 instances. This is the default.

    • arm64 – Amazon Web Services Graviton instances.

    " + }, + "CodeBuildServiceRole":{ + "shape":"NonEmptyString", + "documentation":"

    The Amazon Resource Name (ARN) of the Identity and Access Management (IAM) role that CodeBuild assumes to run the build in your Amazon Web Services account. Elastic Beanstalk rejects a Build that doesn't specify this role.

    " + }, + "ComputeType":{ + "shape":"ComputeType", + "documentation":"

    The size of the compute resources that run the build. If you don't specify it, Elastic Beanstalk uses BUILD_GENERAL1_MEDIUM.

    Valid values:

    • BUILD_GENERAL1_SMALL – Use up to 3 GB memory and 2 vCPUs for builds.

    • BUILD_GENERAL1_MEDIUM – Use up to 7 GB memory and 4 vCPUs for builds.

    • BUILD_GENERAL1_LARGE – Use up to 15 GB memory and 8 vCPUs for builds.

    " + }, + "TimeoutInMinutes":{ + "shape":"BoxedInt", + "documentation":"

    How long, in minutes from 5 to 480 (8 hours), Elastic Beanstalk waits before stopping a build that hasn't completed. The default is 60 minutes.

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

    Settings that Elastic Beanstalk uses to build a container image from the source bundle of an application version.

    " + }, + "ImageBuildType":{ + "type":"string", + "enum":[ + "docker", + "buildpack" + ] + }, + "ImageConfiguration":{ + "type":"structure", + "members":{ + "Source":{ + "shape":"ImageSource", + "documentation":"

    The location of a container image that you built and pushed to a container registry yourself. Elastic Beanstalk deploys the image without a build step.

    If you specify Source, don't specify Build or the request's SourceBundle parameter.

    " + }, + "Build":{ + "shape":"ImageBuildConfiguration", + "documentation":"

    Settings that Elastic Beanstalk uses to build a container image from the source bundle of the application version.

    If you specify Build, also specify the request's SourceBundle parameter, and don't specify Source.

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

    The source of the container image for an application version: an image that you built and pushed to a container registry yourself, or settings for Elastic Beanstalk to build one from your source bundle.

    " + }, "ImageId":{"type":"string"}, + "ImageSource":{ + "type":"structure", + "members":{ + "Uri":{ + "shape":"String", + "documentation":"

    The URI of the container image, including the registry, the repository, and the image tag or digest. For example, 111122223333.dkr.ecr.us-east-1.amazonaws.com/my-repository:latest.

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

    The location of a container image.

    " + }, "IncludeDeleted":{"type":"boolean"}, "IncludeDeletedBackTo":{"type":"timestamp"}, "Instance":{ @@ -2611,11 +2713,11 @@ "members":{ "NoData":{ "shape":"NullableInteger", - "documentation":"

    Grey. AWS Elastic Beanstalk and the health agent are reporting no data on an instance.

    " + "documentation":"

    Grey. Elastic Beanstalk and the health agent are reporting no data on an instance.

    " }, "Unknown":{ "shape":"NullableInteger", - "documentation":"

    Grey. AWS Elastic Beanstalk and the health agent are reporting an insufficient amount of data on an instance.

    " + "documentation":"

    Grey. Elastic Beanstalk and the health agent are reporting an insufficient amount of data on an instance.

    " }, "Pending":{ "shape":"NullableInteger", @@ -2676,7 +2778,7 @@ "InsufficientPrivilegesException":{ "type":"structure", "members":{}, - "documentation":"

    The specified account does not have sufficient privileges for one or more AWS services.

    ", + "documentation":"

    The specified account does not have sufficient privileges for one or more Amazon Web Services services.

    ", "error":{ "code":"InsufficientPrivilegesException", "httpStatusCode":403, @@ -2775,7 +2877,7 @@ "documentation":"

    A list of available solution stacks and their SolutionStackDescription.

    " } }, - "documentation":"

    A list of available AWS Elastic Beanstalk solution stacks.

    " + "documentation":"

    A list of available Elastic Beanstalk solution stacks.

    " }, "ListPlatformBranchesRequest":{ "type":"structure", @@ -3096,7 +3198,7 @@ }, "Namespace":{ "shape":"OptionNamespace", - "documentation":"

    A unique namespace identifying the option's associated AWS resource.

    " + "documentation":"

    A unique namespace identifying the option's associated Amazon Web Services resource.

    " }, "OptionName":{ "shape":"ConfigurationOptionName", @@ -3155,7 +3257,7 @@ }, "PlatformOwner":{ "shape":"PlatformOwner", - "documentation":"

    The AWS account ID of the person who created the platform version.

    " + "documentation":"

    The Amazon Web Services account ID of the person who created the platform version.

    " }, "PlatformName":{ "shape":"PlatformName", @@ -3327,7 +3429,7 @@ }, "PlatformOwner":{ "shape":"PlatformOwner", - "documentation":"

    The AWS account ID of the person who created the platform version.

    " + "documentation":"

    The Amazon Web Services account ID of the person who created the platform version.

    " }, "PlatformStatus":{ "shape":"PlatformStatus", @@ -3411,11 +3513,11 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment to rebuild.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment to rebuild.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment to rebuild.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to rebuild.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " } }, "documentation":"

    " @@ -3430,11 +3532,11 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment of the requested data.

    If no such environment is found, RequestEnvironmentInfo returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment of the requested data.

    If no such environment is found, RequestEnvironmentInfo returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment of the requested data.

    If no such environment is found, RequestEnvironmentInfo returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment of the requested data.

    If no such environment is found, RequestEnvironmentInfo returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " }, "InfoType":{ "shape":"EnvironmentInfoType", @@ -3467,36 +3569,36 @@ "members":{ "Maximum":{ "shape":"BoxedInt", - "documentation":"

    The maximum number of instances of this Elastic Beanstalk resource type that an AWS account can use.

    " + "documentation":"

    The maximum number of instances of this Elastic Beanstalk resource type that an Amazon Web Services account can use.

    " } }, - "documentation":"

    The AWS Elastic Beanstalk quota information for a single resource type in an AWS account. It reflects the resource's limits for this account.

    " + "documentation":"

    The Elastic Beanstalk quota information for a single resource type in an Amazon Web Services account. It reflects the resource's limits for this account.

    " }, "ResourceQuotas":{ "type":"structure", "members":{ "ApplicationQuota":{ "shape":"ResourceQuota", - "documentation":"

    The quota for applications in the AWS account.

    " + "documentation":"

    The quota for applications in the Amazon Web Services account.

    " }, "ApplicationVersionQuota":{ "shape":"ResourceQuota", - "documentation":"

    The quota for application versions in the AWS account.

    " + "documentation":"

    The quota for application versions in the Amazon Web Services account.

    " }, "EnvironmentQuota":{ "shape":"ResourceQuota", - "documentation":"

    The quota for environments in the AWS account.

    " + "documentation":"

    The quota for environments in the Amazon Web Services account.

    " }, "ConfigurationTemplateQuota":{ "shape":"ResourceQuota", - "documentation":"

    The quota for configuration templates in the AWS account.

    " + "documentation":"

    The quota for configuration templates in the Amazon Web Services account.

    " }, "CustomPlatformQuota":{ "shape":"ResourceQuota", - "documentation":"

    The quota for custom platforms in the AWS account.

    " + "documentation":"

    The quota for custom platforms in the Amazon Web Services account.

    " } }, - "documentation":"

    A set of per-resource AWS Elastic Beanstalk quotas associated with an AWS account. They reflect Elastic Beanstalk resource limits for this account.

    " + "documentation":"

    A set of per-resource Elastic Beanstalk quotas associated with an Amazon Web Services account. They reflect Elastic Beanstalk resource limits for this account.

    " }, "ResourceTagsDescriptionMessage":{ "type":"structure", @@ -3527,11 +3629,11 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment to restart the server for.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment to restart the server for.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment to restart the server for.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to restart the server for.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " } }, "documentation":"

    " @@ -3542,11 +3644,11 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the data's environment.

    If no such environment is found, returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the data's environment.

    If no such environment is found, returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the data's environment.

    If no such environment is found, returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the data's environment.

    If no such environment is found, returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " }, "InfoType":{ "shape":"EnvironmentInfoType", @@ -3883,15 +3985,15 @@ "members":{ "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment to terminate.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment to terminate.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment to terminate.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to terminate.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " }, "TerminateResources":{ "shape":"TerminateEnvironmentResources", - "documentation":"

    Indicates whether the associated AWS resources should shut down when the environment is terminated:

    • true: The specified environment as well as the associated AWS resources, such as Auto Scaling group and LoadBalancer, are terminated.

    • false: AWS Elastic Beanstalk resource management is removed from the environment, but the AWS resources continue to operate.

    For more information, see the AWS Elastic Beanstalk User Guide.

    Default: true

    Valid Values: true | false

    " + "documentation":"

    Indicates whether the associated Amazon Web Services resources should shut down when the environment is terminated:

    • true: The specified environment as well as the associated Amazon Web Services resources, such as Auto Scaling group and LoadBalancer, are terminated.

    • false: Elastic Beanstalk resource management is removed from the environment, but the Amazon Web Services resources continue to operate.

    For more information, see the Elastic Beanstalk User Guide.

    Default: true

    Valid Values: true | false

    " }, "ForceTerminate":{ "shape":"ForceTerminate", @@ -4001,7 +4103,7 @@ }, "Description":{ "shape":"Description", - "documentation":"

    A new description for the application.

    Default: If not specified, AWS Elastic Beanstalk does not update the description.

    " + "documentation":"

    A new description for the application.

    Default: If not specified, Elastic Beanstalk does not update the description.

    " } }, "documentation":"

    Request to update an application.

    " @@ -4085,11 +4187,11 @@ }, "EnvironmentId":{ "shape":"EnvironmentId", - "documentation":"

    The ID of the environment to update.

    If no environment with this ID exists, AWS Elastic Beanstalk returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The ID of the environment to update.

    If no environment with this ID exists, Elastic Beanstalk returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentName, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

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

    The name of the environment to update. If no environment with this name exists, AWS Elastic Beanstalk returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, AWS Elastic Beanstalk returns MissingRequiredParameter error.

    " + "documentation":"

    The name of the environment to update. If no environment with this name exists, Elastic Beanstalk returns an InvalidParameterValue error.

    Condition: You must specify either this or an EnvironmentId, or both. If you do not specify either, Elastic Beanstalk returns MissingRequiredParameter error.

    " }, "GroupName":{ "shape":"GroupName", @@ -4097,19 +4199,19 @@ }, "Description":{ "shape":"Description", - "documentation":"

    If this parameter is specified, AWS Elastic Beanstalk updates the description of this environment.

    " + "documentation":"

    If this parameter is specified, Elastic Beanstalk updates the description of this environment.

    " }, "Tier":{ "shape":"EnvironmentTier", - "documentation":"

    This specifies the tier to use to update the environment.

    Condition: At this time, if you change the tier version, name, or type, AWS Elastic Beanstalk returns InvalidParameterValue error.

    " + "documentation":"

    This specifies the tier to use to update the environment.

    Condition: At this time, if you change the tier version, name, or type, Elastic Beanstalk returns InvalidParameterValue error.

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

    If this parameter is specified, AWS Elastic Beanstalk deploys the named application version to the environment. If no such application version is found, returns an InvalidParameterValue error.

    " + "documentation":"

    If this parameter is specified, Elastic Beanstalk deploys the named application version to the environment. If no such application version is found, returns an InvalidParameterValue error.

    " }, "TemplateName":{ "shape":"ConfigurationTemplateName", - "documentation":"

    If this parameter is specified, AWS Elastic Beanstalk deploys this configuration template to the environment. If no such configuration template is found, AWS Elastic Beanstalk returns an InvalidParameterValue error.

    " + "documentation":"

    If this parameter is specified, Elastic Beanstalk deploys this configuration template to the environment. If no such configuration template is found, Elastic Beanstalk returns an InvalidParameterValue error.

    " }, "SolutionStackName":{ "shape":"SolutionStackName", @@ -4121,7 +4223,7 @@ }, "OptionSettings":{ "shape":"ConfigurationOptionSettingsList", - "documentation":"

    If specified, AWS Elastic Beanstalk updates the configuration set associated with the running environment and sets the specified configuration options to the requested value.

    " + "documentation":"

    If specified, Elastic Beanstalk updates the configuration set associated with the running environment and sets the specified configuration options to the requested value.

    " }, "OptionsToRemove":{ "shape":"OptionsSpecifierList", @@ -4224,5 +4326,5 @@ }, "VirtualizationType":{"type":"string"} }, - "documentation":"AWS Elastic Beanstalk

    AWS Elastic Beanstalk makes it easy for you to create, deploy, and manage scalable, fault-tolerant applications running on the Amazon Web Services cloud.

    For more information about this product, go to the AWS Elastic Beanstalk details page. The location of the latest AWS Elastic Beanstalk WSDL is https://elasticbeanstalk.s3.amazonaws.com/doc/2010-12-01/AWSElasticBeanstalk.wsdl. To install the Software Development Kits (SDKs), Integrated Development Environment (IDE) Toolkits, and command line tools that enable you to access the API, go to Tools for Amazon Web Services.

    Endpoints

    For a list of region-specific endpoints that AWS Elastic Beanstalk supports, go to Regions and Endpoints in the Amazon Web Services Glossary.

    " + "documentation":"Elastic Beanstalk

    Elastic Beanstalk makes it easy for you to create, deploy, and manage scalable, fault-tolerant applications running on the Amazon Web Services Cloud.

    For more information about this product, go to the Elastic Beanstalk details page. The location of the latest Elastic Beanstalk WSDL is https://elasticbeanstalk.s3.amazonaws.com/doc/2010-12-01/AWSElasticBeanstalk.wsdl. To install the Software Development Kits (SDKs), Integrated Development Environment (IDE) Toolkits, and command line tools that enable you to access the API, go to Tools for Amazon Web Services.

    Endpoints

    For a list of region-specific endpoints that Elastic Beanstalk supports, go to Regions and Endpoints in the Amazon Web Services Glossary.

    " } diff --git a/services/elasticloadbalancing/pom.xml b/services/elasticloadbalancing/pom.xml index 1b11f44d1009..2413b67a86ce 100644 --- a/services/elasticloadbalancing/pom.xml +++ b/services/elasticloadbalancing/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elasticloadbalancing AWS Java SDK :: Services :: Elastic Load Balancing diff --git a/services/elasticloadbalancing/src/main/resources/codegen-resources/customization.config b/services/elasticloadbalancing/src/main/resources/codegen-resources/customization.config index c3bc83768d54..08d344a3c456 100644 --- a/services/elasticloadbalancing/src/main/resources/codegen-resources/customization.config +++ b/services/elasticloadbalancing/src/main/resources/codegen-resources/customization.config @@ -10,8 +10,6 @@ "DuplicateAccessPointNameException": "DuplicateLoadBalancerNameException", "TooManyAccessPointsException": "TooManyLoadBalancersException", "InvalidEndPointException": "InvalidInstanceException" - }, - - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a97c622aee1d --- /dev/null +++ b/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6f2fa21bb448..000000000000 --- a/services/elasticloadbalancing/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/elasticloadbalancingv2/pom.xml b/services/elasticloadbalancingv2/pom.xml index cb654aebb4d4..90fa43b3bbd3 100644 --- a/services/elasticloadbalancingv2/pom.xml +++ b/services/elasticloadbalancingv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elasticloadbalancingv2 AWS Java SDK :: Services :: Elastic Load Balancing V2 diff --git a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/customization.config b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/customization.config index 00bad1ae0c5f..c448cc130e2d 100644 --- a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/customization.config +++ b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/customization.config @@ -8,8 +8,6 @@ "excludedSimpleMethods": [ "describeRules", "describeListeners" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a97c622aee1d --- /dev/null +++ b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6f2fa21bb448..000000000000 --- a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticloadbalancing.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/service-2.json b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/service-2.json index d1a97d3c20b6..ecb903aa6c8a 100644 --- a/services/elasticloadbalancingv2/src/main/resources/codegen-resources/service-2.json +++ b/services/elasticloadbalancingv2/src/main/resources/codegen-resources/service-2.json @@ -164,7 +164,7 @@ {"shape":"TooManyUniqueTargetGroupsPerLoadBalancerException"}, {"shape":"TooManyTagsException"} ], - "documentation":"

    Creates a rule for the specified listener. The listener must be associated with an Application Load Balancer.

    Each rule consists of a priority, one or more actions, one or more conditions, and up to two optional transforms. Rules are evaluated in priority order, from the lowest value to the highest value. When the conditions for a rule are met, its actions are performed. If the conditions for no rules are met, the actions for the default rule are performed. For more information, see Listener rules in the Application Load Balancers Guide.

    " + "documentation":"

    Creates a rule for the specified listener. The listener must be associated with an Application Load Balancer or a dual-stack Network Load Balancer.

    Each rule consists of a priority, one or more actions, and one or more conditions. Rules are evaluated in priority order, from the lowest value to the highest value. When the conditions for a rule are met, its actions are performed. If the conditions for no rules are met, the actions for the default rule are performed. For more information, see Listener rules in the Application Load Balancers Guide or Listener rules in the Network Load Balancers Guide.

    " }, "CreateTargetGroup":{ "name":"CreateTargetGroup", @@ -2956,7 +2956,7 @@ "members":{ "Key":{ "shape":"ListenerAttributeKey", - "documentation":"

    The name of the attribute.

    The following attribute is supported by Network Load Balancers, and Gateway Load Balancers.

    • tcp.idle_timeout.seconds - The tcp idle timeout value, in seconds. The valid range is 60-6000 seconds. The default is 350 seconds.

    The following attributes are only supported by Application Load Balancers.

    • routing.http.request.x_amzn_mtls_clientcert_serial_number.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Serial-Number HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_issuer.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Issuer HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_subject.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Subject HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_validity.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Validity HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_leaf.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Leaf HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert HTTP request header.

    • routing.http.request.x_amzn_tls_version.header_name - Enables you to modify the header name of the X-Amzn-Tls-Version HTTP request header.

    • routing.http.request.x_amzn_tls_cipher_suite.header_name - Enables you to modify the header name of the X-Amzn-Tls-Cipher-Suite HTTP request header.

    • routing.http.response.server.enabled - Enables you to allow or remove the HTTP response server header.

    • routing.http.response.strict_transport_security.header_value - Informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it using HTTP should automatically be converted to HTTPS.

    • routing.http.response.access_control_allow_origin.header_value - Specifies which origins are allowed to access the server.

    • routing.http.response.access_control_allow_methods.header_value - Returns which HTTP methods are allowed when accessing the server from a different origin.

    • routing.http.response.access_control_allow_headers.header_value - Specifies which headers can be used during the request.

    • routing.http.response.access_control_allow_credentials.header_value - Indicates whether the browser should include credentials such as cookies or authentication when making requests.

    • routing.http.response.access_control_expose_headers.header_value - Returns which headers the browser can expose to the requesting client.

    • routing.http.response.access_control_max_age.header_value - Specifies how long the results of a preflight request can be cached, in seconds.

    • routing.http.response.content_security_policy.header_value - Specifies restrictions enforced by the browser to help minimize the risk of certain types of security threats.

    • routing.http.response.x_content_type_options.header_value - Indicates whether the MIME types advertised in the Content-Type headers should be followed and not be changed.

    • routing.http.response.x_frame_options.header_value - Indicates whether the browser is allowed to render a page in a frame, iframe, embed or object.

    " + "documentation":"

    The name of the attribute.

    The following attribute is supported by Network Load Balancers, and Gateway Load Balancers.

    • tcp.idle_timeout.seconds - The tcp idle timeout value, in seconds. The valid range is 60-6000 seconds. The default is 350 seconds.

    The following attribute is only supported by Gateway Load Balancers:

    • send_tcp_reset.on_idle_timeout.enabled – Specifies whether the Gateway Load Balancer sends a TCP Reset to the sender of traffic when a TCP flow's idle timeout expires. This attribute also applies to non-SYN TCP packets received for flows that are not in the flow table. The value is true or false. The default is false.

    The following attributes are only supported by Application Load Balancers.

    • routing.http.request.x_amzn_mtls_clientcert_serial_number.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Serial-Number HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_issuer.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Issuer HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_subject.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Subject HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_validity.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Validity HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert_leaf.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert-Leaf HTTP request header.

    • routing.http.request.x_amzn_mtls_clientcert.header_name - Enables you to modify the header name of the X-Amzn-Mtls-Clientcert HTTP request header.

    • routing.http.request.x_amzn_tls_version.header_name - Enables you to modify the header name of the X-Amzn-Tls-Version HTTP request header.

    • routing.http.request.x_amzn_tls_cipher_suite.header_name - Enables you to modify the header name of the X-Amzn-Tls-Cipher-Suite HTTP request header.

    • routing.http.response.server.enabled - Enables you to allow or remove the HTTP response server header.

    • routing.http.response.strict_transport_security.header_value - Informs browsers that the site should only be accessed using HTTPS, and that any future attempts to access it using HTTP should automatically be converted to HTTPS.

    • routing.http.response.access_control_allow_origin.header_value - Specifies which origins are allowed to access the server.

    • routing.http.response.access_control_allow_methods.header_value - Returns which HTTP methods are allowed when accessing the server from a different origin.

    • routing.http.response.access_control_allow_headers.header_value - Specifies which headers can be used during the request.

    • routing.http.response.access_control_allow_credentials.header_value - Indicates whether the browser should include credentials such as cookies or authentication when making requests.

    • routing.http.response.access_control_expose_headers.header_value - Returns which headers the browser can expose to the requesting client.

    • routing.http.response.access_control_max_age.header_value - Specifies how long the results of a preflight request can be cached, in seconds.

    • routing.http.response.content_security_policy.header_value - Specifies restrictions enforced by the browser to help minimize the risk of certain types of security threats.

    • routing.http.response.x_content_type_options.header_value - Indicates whether the MIME types advertised in the Content-Type headers should be followed and not be changed.

    • routing.http.response.x_frame_options.header_value - Indicates whether the browser is allowed to render a page in a frame, iframe, embed or object.

    " }, "Value":{ "shape":"ListenerAttributeValue", @@ -3971,7 +3971,7 @@ "members":{ "Field":{ "shape":"ConditionFieldName", - "documentation":"

    The field in the HTTP request. The following are the possible values:

    • http-header

    • http-request-method

    • host-header

    • path-pattern

    • query-string

    • source-ip

    " + "documentation":"

    The name of the field. The possible values are:

    • http-header – [ALB] Matches on an HTTP header field.

    • http-request-method – [ALB] Matches on the HTTP request method.

    • host-header – [ALB] Matches on the host header.

    • path-pattern – [ALB] Matches on the URL path of the request.

    • query-string – [ALB] Matches on a query string parameter.

    • source-ip – [ALB, NLB] Matches on the source IP address. For ALB, use SourceIpConfig with Values to specify CIDR ranges. For NLB, use SourceIpConfig with IpAddressType to match the IP address type (ipv4 or ipv6).

    " }, "Values":{ "shape":"ListOfString", @@ -4006,7 +4006,7 @@ "documentation":"

    The regular expressions to match against the condition field. The maximum length of each string is 128 characters. Specify only when Field is http-header, host-header, or path-pattern.

    " } }, - "documentation":"

    Information about a condition for a rule.

    Each rule can optionally include up to one of each of the following conditions: http-request-method, host-header, path-pattern, and source-ip. Each rule can also optionally include one or more of each of the following conditions: http-header and query-string. Note that the value for a condition can't be empty.

    For more information, see Quotas for your Application Load Balancers.

    " + "documentation":"

    Information about a condition for a rule.

    Each rule can optionally include up to one of each of the following conditions: http-request-method, host-header, path-pattern, and source-ip. Each rule can also optionally include one or more of each of the following conditions: http-header and query-string. Note that the value for a condition can't be empty.

    For Network Load Balancer listener rules, the only supported condition is source-ip. Use SourceIpConfig with IpAddressType to match on the IP address type of the source traffic (ipv4 or ipv6).

    For more information, see Quotas for your Application Load Balancers.

    " }, "RuleConditionList":{ "type":"list", @@ -4214,15 +4214,26 @@ } } }, + "SourceIpAddressTypeEnum":{ + "type":"string", + "enum":[ + "ipv4", + "ipv6" + ] + }, "SourceIpConditionConfig":{ "type":"structure", "members":{ "Values":{ "shape":"ListOfString", "documentation":"

    The source IP addresses, in CIDR format. You can use both IPv4 and IPv6 addresses. Wildcards are not supported.

    If you specify multiple addresses, the condition is satisfied if the source IP address of the request matches one of the CIDR blocks. This condition is not satisfied by the addresses in the X-Forwarded-For header. To search for addresses in the X-Forwarded-For header, use an HTTP header condition.

    The total number of values must be less than, or equal to five.

    " + }, + "IpAddressType":{ + "shape":"SourceIpAddressTypeEnum", + "documentation":"

    The IP address type for Network Load Balancers.

    The valid values are:

    • ipv4 – IPv4 addresses only.

    • ipv6 – IPv6 addresses only.

    " } }, - "documentation":"

    Information about a source IP condition.

    You can use this condition to route based on the IP address of the source that connects to the load balancer. If a client is behind a proxy, this is the IP address of the proxy not the IP address of the client.

    " + "documentation":"

    Information about a source IP condition.

    You can use this condition to route based on the IP address of the source that connects to the load balancer. If a client is behind a proxy, this is the IP address of the proxy not the IP address of the client.

    For Application Load Balancers, use Values to specify CIDR ranges. For Network Load Balancers, use IpAddressType to match on the IP address type of the source traffic.

    " }, "SourceNatIpv6Prefix":{"type":"string"}, "SourceNatIpv6Prefixes":{ @@ -4521,7 +4532,7 @@ "members":{ "Key":{ "shape":"TargetGroupAttributeKey", - "documentation":"

    The name of the attribute.

    The following attributes are supported by all load balancers:

    • deregistration_delay.timeout_seconds - The amount of time, in seconds, for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds. If the target is a Lambda function, this attribute is not supported.

    • stickiness.enabled - Indicates whether target stickiness is enabled. The value is true or false. The default is false.

    • stickiness.type - Indicates the type of stickiness. The possible values are:

      • lb_cookie and app_cookie for Application Load Balancers.

      • source_ip for Network Load Balancers.

      • source_ip_dest_ip and source_ip_dest_ip_proto for Gateway Load Balancers.

    The following attributes are supported by Application Load Balancers and Network Load Balancers:

    • load_balancing.cross_zone.enabled - Indicates whether cross zone load balancing is enabled. The value is true, false or use_load_balancer_configuration. The default is use_load_balancer_configuration.

    • target_group_health.dns_failover.minimum_healthy_targets.count - The minimum number of targets that must be healthy. If the number of healthy targets is below this value, mark the zone as unhealthy in DNS, so that traffic is routed only to healthy zones. The possible values are off or an integer from 1 to the maximum number of targets. The default is 1.

    • target_group_health.dns_failover.minimum_healthy_targets.percentage - The minimum percentage of targets that must be healthy. If the percentage of healthy targets is below this value, mark the zone as unhealthy in DNS, so that traffic is routed only to healthy zones. The possible values are off or an integer from 1 to 100. The default is off.

    • target_group_health.unhealthy_state_routing.minimum_healthy_targets.count - The minimum number of targets that must be healthy. If the number of healthy targets is below this value, send traffic to all targets, including unhealthy targets. The possible values are 1 to the maximum number of targets. The default is 1.

    • target_group_health.unhealthy_state_routing.minimum_healthy_targets.percentage - The minimum percentage of targets that must be healthy. If the percentage of healthy targets is below this value, send traffic to all targets, including unhealthy targets. The possible values are off or an integer from 1 to 100. The default is off.

    The following attributes are supported only if the load balancer is an Application Load Balancer and the target is an instance or an IP address:

    • load_balancing.algorithm.type - The load balancing algorithm determines how the load balancer selects targets when routing requests. The value is round_robin, least_outstanding_requests, or weighted_random. The default is round_robin.

    • load_balancing.algorithm.anomaly_mitigation - Only available when load_balancing.algorithm.type is weighted_random. Indicates whether anomaly mitigation is enabled. The value is on or off. The default is off.

    • slow_start.duration_seconds - The time period, in seconds, during which a newly registered target receives an increasing share of the traffic to the target group. After this time period ends, the target receives its full share of traffic. The range is 30-900 seconds (15 minutes). The default is 0 seconds (disabled).

    • stickiness.app_cookie.cookie_name - Indicates the name of the application-based cookie. Names that start with the following prefixes are not allowed: AWSALB, AWSALBAPP, and AWSALBTG; they're reserved for use by the load balancer.

    • stickiness.app_cookie.duration_seconds - The time period, in seconds, during which requests from a client should be routed to the same target. After this time period expires, the application-based cookie is considered stale. The range is 1 second to 1 week (604800 seconds). The default value is 1 day (86400 seconds).

    • stickiness.lb_cookie.duration_seconds - The time period, in seconds, during which requests from a client should be routed to the same target. After this time period expires, the load balancer-generated cookie is considered stale. The range is 1 second to 1 week (604800 seconds). The default value is 1 day (86400 seconds).

    The following attribute is supported only if the load balancer is an Application Load Balancer and the target is a Lambda function:

    • lambda.multi_value_headers.enabled - Indicates whether the request and response headers that are exchanged between the load balancer and the Lambda function include arrays of values or strings. The value is true or false. The default is false. If the value is false and the request contains a duplicate header field name or query parameter key, the load balancer uses the last value sent by the client.

    The following attributes are supported only by Network Load Balancers:

    • deregistration_delay.connection_termination.enabled - Indicates whether the load balancer terminates connections at the end of the deregistration timeout. The value is true or false. For new UDP/TCP_UDP target groups the default is true. Otherwise, the default is false.

    • preserve_client_ip.enabled - Indicates whether client IP preservation is enabled. The value is true or false. The default is disabled if the target group type is IP address and the target group protocol is TCP or TLS. Otherwise, the default is enabled. Client IP preservation can't be disabled for UDP and TCP_UDP target groups.

    • proxy_protocol_v2.enabled - Indicates whether Proxy Protocol version 2 is enabled. The value is true or false. The default is false.

    • target_health_state.unhealthy.connection_termination.enabled - Indicates whether the load balancer terminates connections to unhealthy targets. The value is true or false. The default is true. This attribute can't be enabled for UDP and TCP_UDP target groups.

    • target_health_state.unhealthy.draining_interval_seconds - The amount of time for Elastic Load Balancing to wait before changing the state of an unhealthy target from unhealthy.draining to unhealthy. The range is 0-360000 seconds. The default value is 0 seconds.

      Note: This attribute can only be configured when target_health_state.unhealthy.connection_termination.enabled is false.

    The following attributes are supported only by Gateway Load Balancers:

    • target_failover.on_deregistration - Indicates how the Gateway Load Balancer handles existing flows when a target is deregistered. The possible values are rebalance and no_rebalance. The default is no_rebalance. The two attributes (target_failover.on_deregistration and target_failover.on_unhealthy) can't be set independently. The value you set for both attributes must be the same.

    • target_failover.on_unhealthy - Indicates how the Gateway Load Balancer handles existing flows when a target is unhealthy. The possible values are rebalance and no_rebalance. The default is no_rebalance. The two attributes (target_failover.on_deregistration and target_failover.on_unhealthy) can't be set independently. The value you set for both attributes must be the same.

    " + "documentation":"

    The name of the attribute.

    The following attributes are supported by all load balancers:

    • deregistration_delay.timeout_seconds - The amount of time, in seconds, for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds. If the target is a Lambda function, this attribute is not supported.

    • stickiness.enabled - Indicates whether target stickiness is enabled. The value is true or false. The default is false.

    • stickiness.type - Indicates the type of stickiness. The possible values are:

      • lb_cookie and app_cookie for Application Load Balancers.

      • source_ip for Network Load Balancers.

      • source_ip_dest_ip and source_ip_dest_ip_proto for Gateway Load Balancers.

    The following attributes are supported by Application Load Balancers and Network Load Balancers:

    • load_balancing.cross_zone.enabled - Indicates whether cross zone load balancing is enabled. The value is true, false or use_load_balancer_configuration. The default is use_load_balancer_configuration.

    • target_group_health.dns_failover.minimum_healthy_targets.count - The minimum number of targets that must be healthy. If the number of healthy targets is below this value, mark the zone as unhealthy in DNS, so that traffic is routed only to healthy zones. The possible values are off or an integer from 1 to the maximum number of targets. The default is 1.

    • target_group_health.dns_failover.minimum_healthy_targets.percentage - The minimum percentage of targets that must be healthy. If the percentage of healthy targets is below this value, mark the zone as unhealthy in DNS, so that traffic is routed only to healthy zones. The possible values are off or an integer from 1 to 100. The default is off.

    • target_group_health.unhealthy_state_routing.minimum_healthy_targets.count - The minimum number of targets that must be healthy. If the number of healthy targets is below this value, send traffic to all targets, including unhealthy targets. The possible values are 1 to the maximum number of targets. The default is 1.

    • target_group_health.unhealthy_state_routing.minimum_healthy_targets.percentage - The minimum percentage of targets that must be healthy. If the percentage of healthy targets is below this value, send traffic to all targets, including unhealthy targets. The possible values are off or an integer from 1 to 100. The default is off.

    The following attributes are supported only if the load balancer is an Application Load Balancer and the target is an instance or an IP address:

    • load_balancing.algorithm.type - The load balancing algorithm determines how the load balancer selects targets when routing requests. The value is round_robin, least_outstanding_requests, or weighted_random. The default is round_robin.

    • load_balancing.algorithm.anomaly_mitigation - Only available when load_balancing.algorithm.type is weighted_random. Indicates whether anomaly mitigation is enabled. The value is on or off. The default is off.

    • slow_start.duration_seconds - The time period, in seconds, during which a newly registered target receives an increasing share of the traffic to the target group. After this time period ends, the target receives its full share of traffic. The range is 30-900 seconds (15 minutes). The default is 0 seconds (disabled).

    • stickiness.app_cookie.cookie_name - Indicates the name of the application-based cookie. Names that start with the following prefixes are not allowed: AWSALB, AWSALBAPP, and AWSALBTG; they're reserved for use by the load balancer.

    • stickiness.app_cookie.duration_seconds - The time period, in seconds, during which requests from a client should be routed to the same target. After this time period expires, the application-based cookie is considered stale. The range is 1 second to 1 week (604800 seconds). The default value is 1 day (86400 seconds).

    • stickiness.lb_cookie.duration_seconds - The time period, in seconds, during which requests from a client should be routed to the same target. After this time period expires, the load balancer-generated cookie is considered stale. The range is 1 second to 1 week (604800 seconds). The default value is 1 day (86400 seconds).

    The following attribute is supported only if the load balancer is an Application Load Balancer and the target is a Lambda function:

    • lambda.multi_value_headers.enabled - Indicates whether the request and response headers that are exchanged between the load balancer and the Lambda function include arrays of values or strings. The value is true or false. The default is false. If the value is false and the request contains a duplicate header field name or query parameter key, the load balancer uses the last value sent by the client.

    The following attributes are supported only by Network Load Balancers:

    • deregistration_delay.connection_termination.enabled - Indicates whether the load balancer terminates connections at the end of the deregistration timeout. The value is true or false. For new UDP/TCP_UDP target groups the default is true. Otherwise, the default is false.

    • preserve_client_ip.enabled - Indicates whether client IP preservation is enabled. The value is true or false. The default is disabled if the target group type is IP address and the target group protocol is TCP or TLS. Otherwise, the default is enabled. Client IP preservation can't be disabled for UDP and TCP_UDP target groups.

    • proxy_protocol_v2.enabled - Indicates whether Proxy Protocol version 2 is enabled. The value is true or false. The default is false.

    • target_health_state.unhealthy.connection_termination.enabled - Indicates whether the load balancer terminates connections to unhealthy targets. The value is true or false. The default is true. This attribute can't be enabled for UDP and TCP_UDP target groups.

    • target_health_state.unhealthy.draining_interval_seconds - The amount of time for Elastic Load Balancing to wait before changing the state of an unhealthy target from unhealthy.draining to unhealthy. The range is 0-360000 seconds. The default value is 0 seconds.

      Note: This attribute can only be configured when target_health_state.unhealthy.connection_termination.enabled is false.

    The following attributes are supported only by Gateway Load Balancers:

    • target_failover.on_deregistration - Indicates how the Gateway Load Balancer handles existing flows when a target is deregistered. The possible values are rebalance and no_rebalance. The default is no_rebalance. The two attributes (target_failover.on_deregistration and target_failover.on_unhealthy) can't be set independently. The value you set for both attributes must be the same.

    • target_failover.on_unhealthy - Indicates how the Gateway Load Balancer handles existing flows when a target is unhealthy. The possible values are rebalance and no_rebalance. The default is no_rebalance. The two attributes (target_failover.on_deregistration and target_failover.on_unhealthy) can't be set independently. The value you set for both attributes must be the same.

    • send_tcp_reset.on_unhealthy.enabled – Specifies whether the Gateway Load Balancer sends a TCP Reset to the sender of traffic when a target becomes unhealthy. After sending the reset, the Gateway Load Balancer removes the flow entry from its flow table. The value is true or false. The default is false. This attribute does not apply when target_failover.on_unhealthy is set to rebalance. This feature requires 5-tuple flow stickiness, which the target group uses by default when stickiness.enabled is set to false.

    • send_tcp_reset.on_deregistration.enabled – Specifies whether the Gateway Load Balancer sends a TCP Reset to the sender of traffic when a target is deregistered. The reset occurs after the connection drain time has elapsed. The value is true or false. The default is false. This attribute does not apply when target_failover.on_deregistration is set to rebalance. This feature requires 5-tuple flow stickiness, which the target group uses by default when stickiness.enabled is set to false.

    " }, "Value":{ "shape":"TargetGroupAttributeValue", diff --git a/services/elasticsearch/pom.xml b/services/elasticsearch/pom.xml index 3d62fc91dfcf..7d82b42c0332 100644 --- a/services/elasticsearch/pom.xml +++ b/services/elasticsearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elasticsearch AWS Java SDK :: Services :: Amazon Elasticsearch Service diff --git a/services/elasticsearch/src/main/resources/codegen-resources/customization.config b/services/elasticsearch/src/main/resources/codegen-resources/customization.config index a2bee164c24e..a0272e6eb4d2 100644 --- a/services/elasticsearch/src/main/resources/codegen-resources/customization.config +++ b/services/elasticsearch/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ "getCompatibleElasticsearchVersions", "listDomainNames", "listElasticsearchVersions" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/elasticsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elasticsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e447bfdb707f --- /dev/null +++ b/services/elasticsearch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,251 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aos.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aos.{Region}.api.amazonwebservices.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 16, + "nodes": "/////wAAAAH/////AAAAAAAAAA8AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAsAAAAGAAAABAAAAAcF9eEMAAAABQAAAAgF9eELAAAABwX14QgAAAAJAAAACAX14QkAAAAKAAAACQX14QgF9eEKAAAABAAAAA0AAAAMAAAABgX14QYF9eEHAAAABQAAAA4F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAQAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elasticsearch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elasticsearch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b63207e77eac..000000000000 --- a/services/elasticsearch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://es-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://es-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.amazonwebservices.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://es.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://es.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/elasticsearch/src/main/resources/codegen-resources/service-2.json b/services/elasticsearch/src/main/resources/codegen-resources/service-2.json index 2baae88eb527..8347fb5bdb55 100644 --- a/services/elasticsearch/src/main/resources/codegen-resources/service-2.json +++ b/services/elasticsearch/src/main/resources/codegen-resources/service-2.json @@ -1734,6 +1734,14 @@ "AutomatedSnapshotPauseOptions":{ "shape":"AutomatedSnapshotPauseRequestOptions", "documentation":"

    Specifies the automated snapshot pause options for the domain.

    Suspending snapshots reduces data protection. You cannot restore your domain to points in time when snapshots are suspended. Use this feature only for short-term operational needs such as migrations or maintenance windows.

    Maximum suspension duration: 3 days.

    " + }, + "UseCase":{ + "shape":"DomainUseCase", + "documentation":"

    The primary use case for the domain. For valid values, see DomainUseCase.

    " + }, + "EngineMode":{ + "shape":"DomainEngineMode", + "documentation":"

    The engine mode for the domain. For valid values and requirements, see DomainEngineMode.

    " } } }, @@ -2536,6 +2544,14 @@ }, "documentation":"

    The configured endpoint options for the domain and their current status.

    " }, + "DomainEngineMode":{ + "type":"string", + "documentation":"

    The engine mode for the domain. Valid values are GENERAL (the standard Elasticsearch/OpenSearch engine) and OPTIMIZED (the cost- and performance-optimized engine for observability and log-analytics workloads). If you don't specify an engine mode, GENERAL is used. OPTIMIZED requires OpenSearch 3.5 or later, OpenSearch Optimized instance types (OR1, OR2, OM2, or OI2) for the data tier, and encryption at rest, and is available only for the OBSERVABILITY and MIXED use cases. The engine mode can't be changed after the domain is created.

    ", + "enum":[ + "GENERAL", + "OPTIMIZED" + ] + }, "DomainId":{ "type":"string", "documentation":"

    Unique identifier for an Elasticsearch domain.

    ", @@ -2652,6 +2668,16 @@ "Deleting" ] }, + "DomainUseCase":{ + "type":"string", + "documentation":"

    The primary use case for the domain, which determines the default configuration and the engine modes that are available. Valid values are SEARCH (full-text search, e-commerce, content discovery, and hybrid and semantic search), VECTOR (k-NN and semantic search, and retrieval-augmented generation), OBSERVABILITY (logs, metrics, traces, and dashboards), and MIXED (a combination of search and analytics). If you don't specify a use case, MIXED is used.

    ", + "enum":[ + "SEARCH", + "VECTOR", + "OBSERVABILITY", + "MIXED" + ] + }, "Double":{"type":"double"}, "DryRun":{"type":"boolean"}, "DryRunResults":{ @@ -2943,6 +2969,14 @@ "AutomatedSnapshotPauseOptions":{ "shape":"AutomatedSnapshotPauseOptionsStatus", "documentation":"

    Specifies AutomatedSnapshotPauseOptions for the domain.

    " + }, + "UseCase":{ + "shape":"UseCaseStatus", + "documentation":"

    The use case configured for the domain.

    " + }, + "EngineMode":{ + "shape":"EngineModeStatus", + "documentation":"

    The engine mode configured for the domain.

    " } }, "documentation":"

    The configuration of an Elasticsearch domain.

    " @@ -3068,6 +3102,14 @@ "AutomatedSnapshotPauseOptions":{ "shape":"AutomatedSnapshotPauseOptions", "documentation":"

    The current status of the Elasticsearch domain's automated snapshot pause options.

    " + }, + "UseCase":{ + "shape":"DomainUseCase", + "documentation":"

    The primary use case for the domain.

    " + }, + "EngineMode":{ + "shape":"DomainEngineMode", + "documentation":"

    The engine mode for the domain.

    " } }, "documentation":"

    The current status of an Elasticsearch domain.

    " @@ -3150,6 +3192,24 @@ "key":{"shape":"String"}, "value":{"shape":"ServiceUrl"} }, + "EngineModeStatus":{ + "type":"structure", + "required":[ + "Options", + "Status" + ], + "members":{ + "Options":{ + "shape":"DomainEngineMode", + "documentation":"

    The engine mode configured for the domain.

    " + }, + "Status":{ + "shape":"OptionStatus", + "documentation":"

    The current status of the engine mode for the domain.

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

    The status of the engine mode for the domain.

    " + }, "EngineType":{ "type":"string", "enum":[ @@ -4821,6 +4881,14 @@ "AutomatedSnapshotPauseOptions":{ "shape":"AutomatedSnapshotPauseRequestOptions", "documentation":"

    Specifies the automated snapshot pause options for the domain.

    Suspending snapshots reduces data protection. You cannot restore your domain to points in time when snapshots are suspended. Use this feature only for short-term operational needs such as migrations or maintenance windows.

    Maximum suspension duration: 3 days.

    " + }, + "UseCase":{ + "shape":"DomainUseCase", + "documentation":"

    The primary use case for the domain. For valid values, see DomainUseCase.

    " + }, + "EngineMode":{ + "shape":"DomainEngineMode", + "documentation":"

    The engine mode for the domain. For valid values and requirements, see DomainEngineMode.

    " } }, "documentation":"

    Container for the parameters to the UpdateElasticsearchDomain operation. Specifies the type and number of instances in the domain cluster.

    " @@ -5008,6 +5076,24 @@ "type":"list", "member":{"shape":"UpgradeStepItem"} }, + "UseCaseStatus":{ + "type":"structure", + "required":[ + "Options", + "Status" + ], + "members":{ + "Options":{ + "shape":"DomainUseCase", + "documentation":"

    The use case configured for the domain.

    " + }, + "Status":{ + "shape":"OptionStatus", + "documentation":"

    The current status of the use case for the domain.

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

    The status of the use case for the domain.

    " + }, "UserPoolId":{ "type":"string", "max":55, diff --git a/services/elementalinference/pom.xml b/services/elementalinference/pom.xml index 27625a6121e5..a8b938f0cf22 100644 --- a/services/elementalinference/pom.xml +++ b/services/elementalinference/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT elementalinference AWS Java SDK :: Services :: Elemental Inference diff --git a/services/elementalinference/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/elementalinference/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f29a1d44044e --- /dev/null +++ b/services/elementalinference/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elemental-inference-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elemental-inference-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elemental-inference.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elemental-inference.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/elementalinference/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/elementalinference/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8c3ad3763826..000000000000 --- a/services/elementalinference/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elemental-inference-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elemental-inference-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elemental-inference.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elemental-inference.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/elementalinference/src/main/resources/codegen-resources/paginators-1.json b/services/elementalinference/src/main/resources/codegen-resources/paginators-1.json index 7cdd5bbad194..341c991b27f3 100644 --- a/services/elementalinference/src/main/resources/codegen-resources/paginators-1.json +++ b/services/elementalinference/src/main/resources/codegen-resources/paginators-1.json @@ -11,6 +11,12 @@ "output_token": "nextToken", "limit_key": "maxResults", "result_key": "feeds" + }, + "SearchFixtures": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "fixtures" } } } diff --git a/services/elementalinference/src/main/resources/codegen-resources/service-2.json b/services/elementalinference/src/main/resources/codegen-resources/service-2.json index 60352851748d..3c62500dd692 100644 --- a/services/elementalinference/src/main/resources/codegen-resources/service-2.json +++ b/services/elementalinference/src/main/resources/codegen-resources/service-2.json @@ -114,6 +114,24 @@ "documentation":"

    Deletes the specified feed. You can delete the feed at any time. Elemental Inference doesn't block you from deleting a feed when the calling application is calling PutMedia or GetMetadata on that feed, although both these calls will start to fail. For more information about managing inactive feeds, see the Elemental Inference User Guide.

    ", "idempotent":true }, + "DeleteFeedPolicy":{ + "name":"DeleteFeedPolicy", + "http":{ + "method":"DELETE", + "requestUri":"/v1/feed/{id}/policy", + "responseCode":204 + }, + "input":{"shape":"DeleteFeedPolicyRequest"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"TooManyRequestException"} + ], + "documentation":"

    Deletes the resource-based policy attached to the specified feed. After you delete the policy, the operation revokes the cross-account access that the policy granted.

    ", + "idempotent":true + }, "DisassociateFeed":{ "name":"DisassociateFeed", "http":{ @@ -190,6 +208,46 @@ "documentation":"

    Retrieves information about the specified feed.

    ", "readonly":true }, + "GetFeedPolicy":{ + "name":"GetFeedPolicy", + "http":{ + "method":"GET", + "requestUri":"/v1/feed/{id}/policy", + "responseCode":200 + }, + "input":{"shape":"GetFeedPolicyRequest"}, + "output":{"shape":"GetFeedPolicyResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"TooManyRequestException"} + ], + "documentation":"

    Retrieves the resource-based policy attached to the specified feed.

    ", + "readonly":true + }, + "GetFixture":{ + "name":"GetFixture", + "http":{ + "method":"GET", + "requestUri":"/v1/fixtures/{fixtureId}", + "responseCode":200 + }, + "input":{"shape":"GetFixtureRequest"}, + "output":{"shape":"GetFixtureResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TooManyRequestException"}, + {"shape":"GatewayTimedOutException"} + ], + "documentation":"

    Retrieves information about the specified fixture (a sports event, such as a specific basketball game). You obtain a fixtureId from SearchFixtures, or from the clipping output of a feed.

    ", + "readonly":true + }, "ListDictionaries":{ "name":"ListDictionaries", "http":{ @@ -246,6 +304,46 @@ "documentation":"

    List all tags that are on an Elemental Inference resource in the current region.

    ", "readonly":true }, + "PutFeedPolicy":{ + "name":"PutFeedPolicy", + "http":{ + "method":"PUT", + "requestUri":"/v1/feed/{id}/policy", + "responseCode":200 + }, + "input":{"shape":"PutFeedPolicyRequest"}, + "output":{"shape":"PutFeedPolicyResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"TooManyRequestException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Attaches or replaces a resource-based policy on the specified feed. A resource-based policy grants cross-account access to the feed.

    ", + "idempotent":true + }, + "SearchFixtures":{ + "name":"SearchFixtures", + "http":{ + "method":"POST", + "requestUri":"/v1/fixtures", + "responseCode":200 + }, + "input":{"shape":"SearchFixturesRequest"}, + "output":{"shape":"SearchFixturesResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TooManyRequestException"}, + {"shape":"GatewayTimedOutException"} + ], + "documentation":"

    Searches for the fixtures (sports events, such as a specific basketball game) that are available for a sport in a date window. Each fixture in the response includes a fixtureId that you specify in the clipping output of a feed, so that Elemental Inference maps the event data for that fixture onto the clipping metadata. This operation is paginated: if there are more fixtures than fit in one page, the response includes a nextToken that you pass in a subsequent request.

    ", + "readonly":true + }, "TagResource":{ "name":"TagResource", "http":{ @@ -419,10 +517,34 @@ "callbackMetadata":{ "shape":"ResourceDescription", "documentation":"

    A string that you want Elemental Inference to always include in the event clipping metadata for this output. The string might identify the sports event in the source media, for example.

    " + }, + "dataSourceConfiguration":{ + "shape":"DataSourceConfiguration", + "documentation":"

    The data source to map onto this clipping output. This parameter is optional. When you include this parameter, Elemental Inference reads the event data for the fixture that you specify, and includes that data in the event clipping metadata for this output.

    If you omit this parameter, Elemental Inference doesn't map a data source onto this output.

    " } }, "documentation":"

    A type of OutputConfig, used when the output in a feed is for the clip feature.

    " }, + "Competitor":{ + "type":"structure", + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the competitor, as provided by the data source.

    " + }, + "isHome":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this competitor is the home side in the fixture. If true, this competitor is the home side. If false, this competitor is the away side.

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

    Contains information about one competitor in a fixture. It is used in the FixtureSummary that is in the SearchFixtures response.

    " + }, + "CompetitorList":{ + "type":"list", + "member":{"shape":"Competitor"}, + "max":30, + "min":0 + }, "ConflictException":{ "type":"structure", "required":["message"], @@ -437,6 +559,16 @@ "exception":true, "retryable":{"throttling":false} }, + "ContextualMetadataConfig":{ + "type":"structure", + "members":{ + "summaryGeneration":{ + "shape":"SummaryGenerationMode", + "documentation":"

    Specifies whether Elemental Inference generates a descriptive summary of the media content for this output.

    Valid values:

    • ENABLED (default) – Elemental Inference generates a descriptive summary along with IAB taxonomy and GARM suitability classifications.

    • DISABLED – No descriptive summary is generated.

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

    The output configuration settings for the contextual metadata feature. Use this structure when the feed output generates metadata that describes the media content.

    " + }, "CreateDictionaryRequest":{ "type":"structure", "required":[ @@ -513,6 +645,10 @@ "shape":"ResourceName", "documentation":"

    A user-friendly name for this feed.

    " }, + "accessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of an IAM role that Elemental Inference assumes to access resources in your account on your behalf. For example, the smart crop feature uses this role to read graphics-compositing templates from your Amazon S3 bucket. You specify one access role for each feed.

    " + }, "outputs":{ "shape":"CreateOutputList", "documentation":"

    An array of outputs for this feed. Each output represents a specific Elemental Inference feature. For example, there is one output type for the smart crop feature. You must specify at least one output, but you can later add outputs using AssociateFeed, or add, modify, and delete outputs using UpdateFeed.

    " @@ -554,6 +690,10 @@ "shape":"GetOutputList", "documentation":"

    Repeats the outputs that you specified in the request.

    " }, + "accessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role that you specified in the request. This property is absent if you didn't specify an IAM role.

    " + }, "status":{ "shape":"FeedStatus", "documentation":"

    The current status of the feed. After creation of the feed has succeeded, the status will be AVAILABLE.

    " @@ -601,9 +741,32 @@ }, "CroppingConfig":{ "type":"structure", - "members":{}, + "members":{ + "templateGroups":{ + "shape":"TemplateGroupList", + "documentation":"

    An array of template groups for the crop output. Each template group provides the graphics-compositing templates that Elemental Inference applies to the cropped video. You can specify from 1 to 4 template groups.

    " + } + }, "documentation":"

    A type of OutputConfig, used when the output in a feed is for the crop feature.

    " }, + "DataSourceConfiguration":{ + "type":"structure", + "required":["fixtureId"], + "members":{ + "fixtureId":{ + "shape":"FixtureId", + "documentation":"

    The ID of the fixture whose event data you want Elemental Inference to map onto this clipping output. The fixture should be the sports event in the source media that the feed is processing.

    To obtain this ID, use the SearchFixtures operation to find the fixture, then use the fixtureId from the matching FixtureSummary.

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

    Contains the data source configuration for a clipping output. It identifies the fixture whose event data Elemental Inference maps onto the clipping metadata. It is used in the dataSourceConfiguration property of a ClippingConfig.

    " + }, + "DataSourceSport":{ + "type":"string", + "enum":[ + "basketball", + "american-football" + ] + }, "DeleteDictionaryRequest":{ "type":"structure", "required":["id"], @@ -638,6 +801,18 @@ } } }, + "DeleteFeedPolicyRequest":{ + "type":"structure", + "required":["id"], + "members":{ + "id":{ + "shape":"FeedId", + "documentation":"

    The ID of the feed whose policy you want to delete.

    ", + "location":"uri", + "locationName":"id" + } + } + }, "DeleteFeedRequest":{ "type":"structure", "required":["id"], @@ -872,6 +1047,82 @@ "type":"list", "member":{"shape":"FeedSummary"} }, + "FilterName":{ + "type":"string", + "enum":["COMPETITOR"] + }, + "FilterValue":{ + "type":"string", + "max":256, + "min":1 + }, + "FilterValueList":{ + "type":"list", + "member":{"shape":"FilterValue"}, + "max":10, + "min":0 + }, + "FixtureDate":{ + "type":"string", + "pattern":"\\d{4}-\\d{2}-\\d{2}" + }, + "FixtureId":{ + "type":"string", + "max":128, + "min":1 + }, + "FixtureSummary":{ + "type":"structure", + "required":[ + "fixtureId", + "name", + "status", + "competitors" + ], + "members":{ + "fixtureId":{ + "shape":"FixtureId", + "documentation":"

    The ID of the fixture. Specify this ID in the clipping output of a feed, to identify the fixture whose event data you want Elemental Inference to map onto the clipping metadata.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the fixture, as provided by the data source. For example, the names of the two competing teams.

    " + }, + "fixtureGroup":{ + "shape":"String", + "documentation":"

    The group that the fixture belongs to, such as the competition, league, or tournament. The data source doesn't provide this information for every fixture.

    " + }, + "scheduledStart":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The scheduled start time of the fixture, as provided by the data source. The actual start time might differ.

    " + }, + "status":{ + "shape":"String", + "documentation":"

    The status of the fixture in its lifecycle, as provided by the data source. For example, Scheduled or Completed.

    " + }, + "competitors":{ + "shape":"CompetitorList", + "documentation":"

    An array of the competitors (the teams or individuals) in the fixture.

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

    Contains information about one fixture. It is used in the SearchFixtures response.

    Elemental Inference relays the information in this structure from the data source, so that you can identify the fixture that matches your source media.

    " + }, + "FixtureSummaryList":{ + "type":"list", + "member":{"shape":"FixtureSummary"} + }, + "GatewayTimedOutException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request timed out before the service returned a response. This is a temporary condition. Retry the request. If the problem persists, contact AWS Support.

    ", + "error":{"httpStatusCode":504}, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, "GetDictionaryRequest":{ "type":"structure", "required":["id"], @@ -924,6 +1175,28 @@ } } }, + "GetFeedPolicyRequest":{ + "type":"structure", + "required":["id"], + "members":{ + "id":{ + "shape":"FeedId", + "documentation":"

    The ID of the feed whose policy you want to retrieve.

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "GetFeedPolicyResponse":{ + "type":"structure", + "required":["policy"], + "members":{ + "policy":{ + "shape":"PolicyDocument", + "documentation":"

    The resource-based policy document attached to the feed.

    " + } + } + }, "GetFeedRequest":{ "type":"structure", "required":["id"], @@ -967,6 +1240,10 @@ "shape":"GetOutputList", "documentation":"

    An array of the outputs in the feed.

    " }, + "accessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of an AWS Identity and Access Management (IAM) role that Elemental Inference assumes. Elemental Inference uses this role to access resources in your account on your behalf. This property is absent if the feed doesn't have an IAM role.

    " + }, "status":{ "shape":"FeedStatus", "documentation":"

    The status of the feed.

    " @@ -981,6 +1258,53 @@ } } }, + "GetFixtureRequest":{ + "type":"structure", + "required":["fixtureId"], + "members":{ + "fixtureId":{ + "shape":"FixtureId", + "documentation":"

    The ID of the fixture to retrieve, as returned by SearchFixtures.

    ", + "location":"uri", + "locationName":"fixtureId" + } + } + }, + "GetFixtureResponse":{ + "type":"structure", + "required":[ + "fixtureId", + "name", + "status", + "competitors" + ], + "members":{ + "fixtureId":{ + "shape":"FixtureId", + "documentation":"

    The ID that you specified in the request.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the fixture, as provided by the data source. For example, the names of the two competing teams.

    " + }, + "fixtureGroup":{ + "shape":"String", + "documentation":"

    The group that the fixture belongs to, such as the competition, league, or tournament. The data source doesn't provide this information for every fixture.

    " + }, + "scheduledStart":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The scheduled start time of the fixture, as provided by the data source. The actual start time might differ.

    " + }, + "status":{ + "shape":"String", + "documentation":"

    The status of the fixture in its lifecycle, as provided by the data source. For example, Scheduled or Completed.

    " + }, + "competitors":{ + "shape":"CompetitorList", + "documentation":"

    An array of the competitors (the teams or individuals) in the fixture.

    " + } + } + }, "GetOutput":{ "type":"structure", "required":[ @@ -1016,6 +1340,12 @@ "type":"list", "member":{"shape":"GetOutput"} }, + "IamRoleArn":{ + "type":"string", + "max":255, + "min":32, + "pattern":"arn:aws[a-z\\-]*:iam::[0-9]{12}:role/.+" + }, "Integer":{ "type":"integer", "box":true @@ -1141,6 +1471,10 @@ "subtitling":{ "shape":"SubtitlingConfig", "documentation":"

    The output config type that applies to the smart subtitling feature.

    " + }, + "contextualMetadata":{ + "shape":"ContextualMetadataConfig", + "documentation":"

    The output config type that applies to the contextual metadata feature.

    " } }, "documentation":"

    Contains one typed output. It is used in the CreateOutput, GetOutput, and Update Output structures.

    ", @@ -1153,6 +1487,11 @@ "DISABLED" ] }, + "PolicyDocument":{ + "type":"string", + "max":2048, + "min":1 + }, "ProfanityFilterMode":{ "type":"string", "enum":[ @@ -1161,6 +1500,29 @@ "DROP" ] }, + "PutFeedPolicyRequest":{ + "type":"structure", + "required":[ + "id", + "policy" + ], + "members":{ + "id":{ + "shape":"FeedId", + "documentation":"

    The ID of the feed to attach the policy to.

    ", + "location":"uri", + "locationName":"id" + }, + "policy":{ + "shape":"PolicyDocument", + "documentation":"

    The resource-based policy document to attach to the feed.

    " + } + } + }, + "PutFeedPolicyResponse":{ + "type":"structure", + "members":{} + }, "ResourceArn":{ "type":"string", "pattern":"arn:aws[a-z\\-]*:elemental-inference[a-z\\-]*:[a-z0-9\\-]+:[0-9]{12}:(feed|dictionary)/[a-zA-Z0-9]{1,19}" @@ -1188,6 +1550,89 @@ }, "exception":true }, + "S3Uri":{ + "type":"string", + "max":255, + "min":10, + "pattern":"s3://[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]/.+" + }, + "SearchFilter":{ + "type":"structure", + "required":[ + "name", + "values" + ], + "members":{ + "name":{ + "shape":"FilterName", + "documentation":"

    The dimension of the fixture to filter on. Valid values: COMPETITOR.

    " + }, + "values":{ + "shape":"FilterValueList", + "documentation":"

    An array of values to match in the dimension that you specified in name. You can specify up to 10 values. A fixture appears in the results if it matches at least one of these values.

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

    A filter for a fixture search. It is used in the filters array of a SearchFixtures request.

    " + }, + "SearchFilterList":{ + "type":"list", + "member":{"shape":"SearchFilter"}, + "max":10, + "min":0 + }, + "SearchFixturesRequest":{ + "type":"structure", + "required":[ + "sport", + "startDate" + ], + "members":{ + "sport":{ + "shape":"DataSourceSport", + "documentation":"

    The sport to search for fixtures. Valid values: basketball (search for basketball fixtures), american-football (search for american-football fixtures).

    " + }, + "startDate":{ + "shape":"FixtureDate", + "documentation":"

    The first day of the search window, in UTC. The search includes fixtures that are scheduled on this day.

    Specify the date in ISO 8601 format, as YYYY-MM-DD. For example, 2026-03-14.

    " + }, + "endDate":{ + "shape":"FixtureDate", + "documentation":"

    The last day of the search window, in UTC. The search includes fixtures that are scheduled on this day. Specify the date in ISO 8601 format, as YYYY-MM-DD.

    If you omit this parameter, Elemental Inference searches only the day that you specified in startDate. The window from startDate through endDate must not exceed seven days.

    " + }, + "filters":{ + "shape":"SearchFilterList", + "documentation":"

    An array of filters that narrow the results. Each filter applies to one dimension of a fixture, such as the competitor. You can specify up to 10 filters.

    A fixture must satisfy every filter in the array in order to appear in the results. Within one filter, a fixture must match at least one of the values.

    " + }, + "maxResults":{ + "shape":"SearchFixturesRequestMaxResultsInteger", + "documentation":"

    The maximum number of fixtures to return for each API request.

    The service might return fewer fixtures than the maxResults value. When more fixtures match the search, the response also includes a nextToken value that you can use to fetch the next batch of results.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The token that identifies the batch of results that you want to see.

    For example, you submit a SearchFixtures request with maxResults set at 5. The service returns the first batch of results (up to 5) and a nextToken value. To see the next batch of results, you submit the SearchFixtures request a second time, with the same search criteria, and specify the nextToken value.

    " + } + } + }, + "SearchFixturesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "SearchFixturesResponse":{ + "type":"structure", + "required":["fixtures"], + "members":{ + "fixtures":{ + "shape":"FixtureSummaryList", + "documentation":"

    An array of FixtureSummary objects, one for each fixture that matches the search. The array is empty if no fixtures match.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The token that identifies the next batch of results. To see the next batch, submit the SearchFixtures request again, with the same search criteria, and specify this value in nextToken.

    This parameter is absent when there are no more results to return.

    " + } + } + }, "ServiceQuotaExceededException":{ "type":"structure", "required":["message"], @@ -1201,6 +1646,18 @@ }, "exception":true }, + "ServiceUnavailableException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The service is temporarily unable to handle the request. Retry the request. If the problem persists, contact AWS Support.

    ", + "error":{"httpStatusCode":503}, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, "String":{"type":"string"}, "StringList":{ "type":"list", @@ -1229,6 +1686,17 @@ }, "documentation":"

    A type of OutputConfig, used when the output in a feed is for the smart subtitling feature. smart subtitling uses automatic speech recognition (ASR) to generate live TTML subtitles from the audio in your source media.

    " }, + "SummaryGenerationMode":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, + "SyntheticTimestamp_date_time":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, "TagKey":{ "type":"string", "max":128, @@ -1267,6 +1735,36 @@ "max":256, "min":0 }, + "TemplateGroup":{ + "type":"structure", + "required":[ + "name", + "templateUris" + ], + "members":{ + "name":{ + "shape":"ResourceName", + "documentation":"

    A name for the template group.

    " + }, + "templateUris":{ + "shape":"TemplateUriList", + "documentation":"

    An array of Amazon S3 URIs that point to the graphics-compositing templates for this group. You can specify 1 or 2 URIs. Each URI must be in the form s3://bucket-name/key. Elemental Inference reads these templates using the IAM role that you specify in accessRoleArn.

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

    A named set of graphics-compositing templates used by the crop feature, specified in the templateGroups array of a CroppingConfig.

    " + }, + "TemplateGroupList":{ + "type":"list", + "member":{"shape":"TemplateGroup"}, + "max":4, + "min":1 + }, + "TemplateUriList":{ + "type":"list", + "member":{"shape":"S3Uri"}, + "max":2, + "min":1 + }, "TooManyRequestException":{ "type":"structure", "required":["message"], @@ -1392,6 +1890,10 @@ "shape":"ResourceName", "documentation":"

    Required. You can specify the existing name (to leave it unchanged) or a new name.

    " }, + "accessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of an IAM role that Elemental Inference assumes to access resources in your account on your behalf. You can specify the existing role (to leave it unchanged) or a new role. You specify one access role for each feed.

    " + }, "id":{ "shape":"FeedId", "documentation":"

    The ID of the feed to update.

    ", @@ -1435,6 +1937,10 @@ "shape":"GetOutputList", "documentation":"

    The array of outputs in the feed. You might have left this array unchanged, or you might have changed it.

    " }, + "accessRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the AWS Identity and Access Management (IAM) role for the feed, after the update. This property is absent if the feed doesn't have an IAM role.

    " + }, "status":{ "shape":"FeedStatus", "documentation":"

    The status of the feed.

    " diff --git a/services/emr/pom.xml b/services/emr/pom.xml index 2cb65bdfc91b..76c1064ecb79 100644 --- a/services/emr/pom.xml +++ b/services/emr/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT emr AWS Java SDK :: Services :: Amazon EMR diff --git a/services/emr/src/main/resources/codegen-resources/customization.config b/services/emr/src/main/resources/codegen-resources/customization.config index cf2c695c9123..710938e69f05 100644 --- a/services/emr/src/main/resources/codegen-resources/customization.config +++ b/services/emr/src/main/resources/codegen-resources/customization.config @@ -21,6 +21,5 @@ ], "deprecatedOperations": [ "DescribeJobFlows" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/emr/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/emr/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a335f7184305 --- /dev/null +++ b/services/emr/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticmapreduce-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticmapreduce.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticmapreduce-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticmapreduce.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://elasticmapreduce.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/emr/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/emr/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d65c2bfcf8f8..000000000000 --- a/services/emr/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticmapreduce-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://elasticmapreduce.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticmapreduce-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://elasticmapreduce.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://elasticmapreduce.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/emr/src/main/resources/codegen-resources/service-2.json b/services/emr/src/main/resources/codegen-resources/service-2.json index 4618dfc4320b..105b5f654cdf 100644 --- a/services/emr/src/main/resources/codegen-resources/service-2.json +++ b/services/emr/src/main/resources/codegen-resources/service-2.json @@ -1282,20 +1282,6 @@ "FAILED" ] }, - "CertificateAuthority":{ - "type":"structure", - "members":{ - "CertificateArn":{ - "shape":"XmlString", - "documentation":"

    The Amazon Resource Name (ARN) of the certificate authority in Amazon Web Services Private CA that issued the Spark Connect server certificate.

    " - }, - "CertificateData":{ - "shape":"XmlString", - "documentation":"

    The PEM-encoded root CA certificate data. Provide this certificate to your client's trust store when connecting directly to the Spark Connect server over VPC peering.

    " - } - }, - "documentation":"

    Describes the certificate authority used to establish an mTLS connection to the Spark Connect server when connecting directly over VPC peering.

    " - }, "ClientRequestToken":{ "type":"string", "max":36, @@ -5546,10 +5532,6 @@ "shape":"Long", "documentation":"

    The idle timeout, in minutes. If the session is idle for this duration, Amazon EMR automatically terminates it.

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

    The certificate authority used to establish an mTLS connection to the Spark Connect server when connecting directly over VPC peering.

    " - }, "ServerUrl":{ "shape":"XmlString", "documentation":"

    The Spark Connect server URL for the session. Use this URL with the Credentials returned by GetSessionEndpoint to connect directly to the session over VPC peering.

    " diff --git a/services/emrcontainers/pom.xml b/services/emrcontainers/pom.xml index 6a46b3d03301..3f46b6413437 100644 --- a/services/emrcontainers/pom.xml +++ b/services/emrcontainers/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT emrcontainers AWS Java SDK :: Services :: EMR Containers diff --git a/services/emrcontainers/src/main/resources/codegen-resources/customization.config b/services/emrcontainers/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/emrcontainers/src/main/resources/codegen-resources/customization.config +++ b/services/emrcontainers/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/emrcontainers/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/emrcontainers/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9b23ba1564e8 --- /dev/null +++ b/services/emrcontainers/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-containers.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/emrcontainers/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/emrcontainers/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cc470d598c6c..000000000000 --- a/services/emrcontainers/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://emr-containers-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://emr-containers.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://emr-containers.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://emr-containers-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://emr-containers.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://emr-containers.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/emrcontainers/src/main/resources/codegen-resources/service-2.json b/services/emrcontainers/src/main/resources/codegen-resources/service-2.json index 1af2d28c2942..6e0b871a5d8b 100644 --- a/services/emrcontainers/src/main/resources/codegen-resources/service-2.json +++ b/services/emrcontainers/src/main/resources/codegen-resources/service-2.json @@ -86,7 +86,7 @@ {"shape":"InternalServerException"}, {"shape":"EKSRequestThrottledException"} ], - "documentation":"

    Creates a virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " + "documentation":"

    Creates a virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, update, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " }, "DeleteJobTemplate":{ "name":"DeleteJobTemplate", @@ -116,6 +116,20 @@ ], "documentation":"

    Deletes a managed endpoint. A managed endpoint is a gateway that connects Amazon EMR Studio to Amazon EMR on EKS so that Amazon EMR Studio can communicate with your virtual cluster.

    " }, + "DeleteSecurityConfiguration":{ + "name":"DeleteSecurityConfiguration", + "http":{ + "method":"DELETE", + "requestUri":"/securityconfigurations/{securityConfigurationId}" + }, + "input":{"shape":"DeleteSecurityConfigurationRequest"}, + "output":{"shape":"DeleteSecurityConfigurationResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Deletes a security configuration.

    " + }, "DeleteVirtualCluster":{ "name":"DeleteVirtualCluster", "http":{ @@ -128,7 +142,7 @@ {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Deletes a virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " + "documentation":"

    Deletes a virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, update, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " }, "DescribeJobRun":{ "name":"DescribeJobRun", @@ -203,7 +217,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Displays detailed information about a specified virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " + "documentation":"

    Displays detailed information about a specified virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, update, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " }, "GetManagedEndpointSessionCredentials":{ "name":"GetManagedEndpointSessionCredentials", @@ -304,7 +318,7 @@ {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Lists information about the specified virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " + "documentation":"

    Lists information about the specified virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, update, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    " }, "StartJobRun":{ "name":"StartJobRun", @@ -350,6 +364,22 @@ {"shape":"ResourceNotFoundException"} ], "documentation":"

    Removes tags from resources.

    " + }, + "UpdateVirtualCluster":{ + "name":"UpdateVirtualCluster", + "http":{ + "method":"PATCH", + "requestUri":"/virtualclusters/{virtualClusterId}" + }, + "input":{"shape":"UpdateVirtualClusterRequest"}, + "output":{"shape":"UpdateVirtualClusterResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Updates a virtual cluster. Virtual cluster is a managed entity on Amazon EMR on EKS. You can create, update, describe, list and delete virtual clusters. They do not consume any additional resource in your system. A single virtual cluster maps to a single Kubernetes namespace. Given this relationship, you can model virtual clusters the same way you model Kubernetes namespaces to meet your requirements.

    ", + "idempotent":true } }, "shapes":{ @@ -366,6 +396,20 @@ "DISABLED" ] }, + "AuthenticationConfiguration":{ + "type":"structure", + "members":{ + "identityCenterConfiguration":{ + "shape":"IdentityCenterConfiguration", + "documentation":"

    The IAM Identity Center configuration to use for authentication.

    " + }, + "iamConfiguration":{ + "shape":"IAMConfiguration", + "documentation":"

    The IAM configuration to use for authentication.

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

    Contains the authentication settings for a security configuration, including Identity Center and IAM configuration options.

    " + }, "AuthorizationConfiguration":{ "type":"structure", "members":{ @@ -661,6 +705,10 @@ "tags":{ "shape":"TagMap", "documentation":"

    The tags of the managed endpoint.

    " + }, + "sessionIdleTimeoutInMinutes":{ + "shape":"SessionIdleTimeoutInMinutes", + "documentation":"

    The number of idle minutes before the managed endpoint session times out.

    " } } }, @@ -761,6 +809,14 @@ "securityConfigurationId":{ "shape":"ResourceIdString", "documentation":"

    The ID of the security configuration.

    " + }, + "sessionEnabled":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the virtual cluster has session support enabled.

    " + }, + "schedulerConfiguration":{ + "shape":"SchedulerConfiguration", + "documentation":"

    The scheduler configuration (concurrency and queue limits) to apply to the virtual cluster at creation time. When omitted, no limits are applied.

    " } } }, @@ -857,6 +913,27 @@ } } }, + "DeleteSecurityConfigurationRequest":{ + "type":"structure", + "required":["id"], + "members":{ + "id":{ + "shape":"ResourceIdString", + "documentation":"

    The ID of the security configuration to delete.

    ", + "location":"uri", + "locationName":"securityConfigurationId" + } + } + }, + "DeleteSecurityConfigurationResponse":{ + "type":"structure", + "members":{ + "id":{ + "shape":"ResourceIdString", + "documentation":"

    The ID of the deleted security configuration.

    " + } + } + }, "DeleteVirtualClusterRequest":{ "type":"structure", "required":["id"], @@ -1018,12 +1095,16 @@ "documentation":"

    The namespaces of the Amazon EKS cluster.

    " }, "nodeLabel":{ - "shape":"ResourceNameString", + "shape":"NodeLabelString", "documentation":"

    The nodeLabel of the nodes where the resources of this virtual cluster can get scheduled. It requires relevant scaling and policy engine addons.

    " } }, "documentation":"

    The information about the Amazon EKS cluster.

    " }, + "EmrIdentityCenterApplicationARN":{ + "type":"string", + "pattern":"^arn:(aws[a-zA-Z0-9-]*):sso:::application/ssoins-[0-9a-zA-Z/\\\\-_]+/apl-[0-9a-zA-Z/\\\\-_]+" + }, "EncryptionConfiguration":{ "type":"structure", "members":{ @@ -1087,6 +1168,10 @@ "shape":"UriString", "documentation":"

    The server URL of the endpoint.

    " }, + "authProxyUrl":{ + "shape":"UriString", + "documentation":"

    The authentication proxy URL of the endpoint.

    " + }, "createdAt":{ "shape":"Date", "documentation":"

    The date and time when the endpoint was created.

    " @@ -1232,18 +1317,66 @@ "shape":"Credentials", "documentation":"

    The structure containing the session credentials.

    " }, + "endpointCredentials":{ + "shape":"Credentials", + "documentation":"

    The session credentials that the operation returns.

    " + }, "expiresAt":{ "shape":"Date", "documentation":"

    The date and time when the session token will expire.

    " } } }, + "IAMConfiguration":{ + "type":"structure", + "members":{ + "systemRole":{ + "shape":"IAMRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the system role used by the security configuration.

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

    Contains the IAM settings for a security configuration, including the system role used for authentication.

    " + }, "IAMRoleArn":{ "type":"string", "max":2048, "min":20, "pattern":"^arn:(aws[a-zA-Z0-9-]*):iam::(\\d{12})?:(role((\\u002F)|(\\u002F[\\u0021-\\u007F]+\\u002F))[\\w+=,.@-]+)$" }, + "IdentityCenterConfiguration":{ + "type":"structure", + "members":{ + "enableIdentityCenter":{ + "shape":"Boolean", + "documentation":"

    Specifies whether Identity Center is enabled for the security configuration.

    " + }, + "identityCenterApplicationAssignmentRequired":{ + "shape":"Boolean", + "documentation":"

    Specifies whether user assignment is required for the Identity Center application.

    " + }, + "identityCenterInstanceARN":{ + "shape":"IdentityCenterInstanceARN", + "documentation":"

    The Amazon Resource Name (ARN) of the Identity Center instance.

    " + }, + "emrIdentityCenterApplicationARN":{ + "shape":"EmrIdentityCenterApplicationARN", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon EMR Identity Center application.

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

    Contains the IAM Identity Center settings for a security configuration, including instance ARN, application assignment requirements, and application ARN.

    " + }, + "IdentityCenterInstanceARN":{ + "type":"string", + "max":1224, + "min":10, + "pattern":"^arn:(aws[a-zA-Z0-9-]*):sso:::instance/ssoins-[0-9a-zA-Z/\\\\-_]+" + }, + "InQueueJobLimitInteger":{ + "type":"integer", + "box":true, + "max":10000, + "min":100 + }, "InTransitEncryptionConfiguration":{ "type":"structure", "members":{ @@ -1284,6 +1417,12 @@ }, "documentation":"

    Specify the driver that the job runs on. Exactly one of the two available job drivers is required, either sparkSqlJobDriver or sparkSubmitJobDriver.

    " }, + "JobLimitInteger":{ + "type":"integer", + "box":true, + "max":10000, + "min":1 + }, "JobRun":{ "type":"structure", "members":{ @@ -1854,6 +1993,16 @@ "min":1, "pattern":".*\\S.*" }, + "NodeLabelString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$" + }, + "NonNegativeInteger":{ + "type":"integer", + "min":0 + }, "ParametricCloudWatchMonitoringConfiguration":{ "type":"structure", "members":{ @@ -2012,10 +2161,44 @@ "logUri":{ "shape":"UriString", "documentation":"

    Amazon S3 destination URI for log publishing.

    " + }, + "encryptionKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the encryption key for logs.

    " } }, "documentation":"

    Amazon S3 configuration for monitoring log publishing. You can configure your jobs to send log information to Amazon S3.

    " }, + "SchedulerConfiguration":{ + "type":"structure", + "members":{ + "maxInQueueJobRuns":{ + "shape":"InQueueJobLimitInteger", + "documentation":"

    The maximum number of job runs that can be in the PENDING or SUBMITTED state at any time for the virtual cluster. When the queue is full, the service rejects StartJobRun requests with a ValidationException. If you omit this field, the service applies no queue-depth limit.

    ", + "box":true + }, + "maxConcurrentJobRuns":{ + "shape":"JobLimitInteger", + "documentation":"

    The maximum number of job runs that can be in the RUNNING state at any time for the virtual cluster. As running slots free up, queued job runs start automatically. If you omit this field, the service applies no concurrency limit.

    ", + "box":true + } + }, + "documentation":"

    The scheduler configuration for a virtual cluster on Amazon EMR on EKS. It controls how many job runs can run concurrently and how many can wait in the queue. When not set, no concurrency or queue limits are applied.

    " + }, + "SchedulerStatus":{ + "type":"structure", + "members":{ + "currentInQueueJobRuns":{ + "shape":"NonNegativeInteger", + "documentation":"

    The number of job runs currently waiting in the queue (PENDING or SUBMITTED) for the virtual cluster.

    " + }, + "currentConcurrentJobRuns":{ + "shape":"NonNegativeInteger", + "documentation":"

    The number of job runs currently in the RUNNING state for the virtual cluster.

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

    The current job-run counts for a virtual cluster, reflecting how much of the configured scheduler capacity is in use.

    " + }, "SecretsManagerArn":{ "type":"string", "max":2048, @@ -2082,6 +2265,10 @@ "authorizationConfiguration":{ "shape":"AuthorizationConfiguration", "documentation":"

    Authorization-related configuration input for the security configuration.

    " + }, + "authenticationConfiguration":{ + "shape":"AuthenticationConfiguration", + "documentation":"

    Authentication-related configuration input for the security configuration.

    " } }, "documentation":"

    Configurations related to the security configuration for the request.

    " @@ -2097,6 +2284,7 @@ "max":100, "sensitive":true }, + "SessionIdleTimeoutInMinutes":{"type":"integer"}, "SessionTagValue":{ "type":"string", "max":512, @@ -2391,6 +2579,41 @@ "type":"structure", "members":{} }, + "UpdateVirtualClusterRequest":{ + "type":"structure", + "required":[ + "id", + "clientToken" + ], + "members":{ + "id":{ + "shape":"ResourceIdString", + "documentation":"

    The ID of the virtual cluster to update.

    ", + "location":"uri", + "locationName":"virtualClusterId" + }, + "schedulerConfiguration":{ + "shape":"SchedulerConfiguration", + "documentation":"

    The scheduler configuration to apply to the virtual cluster. The new configuration fully replaces the existing one. If you omit a field, the corresponding limit is removed.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request, but does not return an error.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    Contains the parameters for a request to update a virtual cluster on Amazon EMR on EKS.

    " + }, + "UpdateVirtualClusterResponse":{ + "type":"structure", + "members":{ + "virtualCluster":{ + "shape":"VirtualCluster", + "documentation":"

    The updated virtual cluster.

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

    Contains the virtual cluster returned after a successful update request.

    " + }, "UriString":{ "type":"string", "max":10280, @@ -2440,6 +2663,18 @@ "securityConfigurationId":{ "shape":"ResourceIdString", "documentation":"

    The ID of the security configuration.

    " + }, + "sessionEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the virtual cluster has session support enabled.

    " + }, + "schedulerConfiguration":{ + "shape":"SchedulerConfiguration", + "documentation":"

    The scheduler configuration (concurrency and queue limits) applied to the virtual cluster. The service does not return this field when no scheduler limits are configured.

    " + }, + "schedulerStatus":{ + "shape":"SchedulerStatus", + "documentation":"

    The current in-queue and concurrent job-run counts for the virtual cluster.

    " } }, "documentation":"

    This entity describes a virtual cluster. A virtual cluster is a Kubernetes namespace that Amazon EMR is registered with. Amazon EMR uses virtual clusters to run jobs and host endpoints. Multiple virtual clusters can be backed by the same physical cluster. However, each virtual cluster maps to one namespace on an Amazon EKS cluster. Virtual clusters do not create any active resources that contribute to your bill or that require lifecycle management outside the service.

    " diff --git a/services/emrserverless/pom.xml b/services/emrserverless/pom.xml index 45f784d14345..289acd79ab5b 100644 --- a/services/emrserverless/pom.xml +++ b/services/emrserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT emrserverless AWS Java SDK :: Services :: EMR Serverless diff --git a/services/emrserverless/src/main/resources/codegen-resources/customization.config b/services/emrserverless/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/emrserverless/src/main/resources/codegen-resources/customization.config +++ b/services/emrserverless/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/emrserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/emrserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ea567f7760d5 --- /dev/null +++ b/services/emrserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-serverless-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://emr-serverless.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/emrserverless/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/emrserverless/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 73efb5e97a7d..000000000000 --- a/services/emrserverless/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://emr-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://emr-serverless-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://emr-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://emr-serverless.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/entityresolution/pom.xml b/services/entityresolution/pom.xml index 6d74e007ac8c..519cae73bb88 100644 --- a/services/entityresolution/pom.xml +++ b/services/entityresolution/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT entityresolution AWS Java SDK :: Services :: Entity Resolution diff --git a/services/entityresolution/src/main/resources/codegen-resources/customization.config b/services/entityresolution/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/entityresolution/src/main/resources/codegen-resources/customization.config +++ b/services/entityresolution/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/entityresolution/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/entityresolution/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..299c864327da --- /dev/null +++ b/services/entityresolution/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entityresolution-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entityresolution-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entityresolution.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entityresolution.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/entityresolution/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/entityresolution/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d42f08922e4a..000000000000 --- a/services/entityresolution/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entityresolution-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entityresolution-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entityresolution.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entityresolution.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/entityresolution/src/main/resources/codegen-resources/service-2.json b/services/entityresolution/src/main/resources/codegen-resources/service-2.json index ebb3974f97e7..7efa7d97ac53 100644 --- a/services/entityresolution/src/main/resources/codegen-resources/service-2.json +++ b/services/entityresolution/src/main/resources/codegen-resources/service-2.json @@ -106,7 +106,7 @@ {"shape":"ConflictException"}, {"shape":"ValidationException"} ], - "documentation":"

    Creates a matching workflow that defines the configuration for a data processing job. The workflow name must be unique. To modify an existing workflow, use UpdateMatchingWorkflow.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    " + "documentation":"

    Creates a matching workflow that defines the configuration for a data processing job. The workflow name must be unique. To modify an existing workflow, use UpdateMatchingWorkflow.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    " }, "CreateSchemaMapping":{ "name":"CreateSchemaMapping", @@ -139,11 +139,12 @@ "errors":[ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"} ], - "documentation":"

    Deletes the IdMappingWorkflow with a given name. This operation will succeed even if a workflow with the given name does not exist.

    ", + "documentation":"

    Deletes the IdMappingWorkflow with a given name. This operation returns a ResourceNotFoundException if a workflow with the given name does not exist.

    ", "idempotent":true }, "DeleteIdNamespace":{ @@ -158,10 +159,11 @@ "errors":[ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"}, {"shape":"ValidationException"} ], - "documentation":"

    Deletes the IdNamespace with a given name.

    ", + "documentation":"

    Deletes the IdNamespace with a given name. This operation returns a ResourceNotFoundException if an ID namespace with the given name does not exist.

    ", "idempotent":true }, "DeleteMatchingWorkflow":{ @@ -176,11 +178,12 @@ "errors":[ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"} ], - "documentation":"

    Deletes the MatchingWorkflow with a given name. This operation will succeed even if a workflow with the given name does not exist.

    ", + "documentation":"

    Deletes the MatchingWorkflow with a given name. This operation returns a ResourceNotFoundException if a workflow with the given name does not exist.

    ", "idempotent":true }, "DeletePolicyStatement":{ @@ -215,11 +218,12 @@ "errors":[ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"} ], - "documentation":"

    Deletes the SchemaMapping with a given name. This operation will succeed even if a schema with the given name does not exist. This operation will fail if there is a MatchingWorkflow object that references the SchemaMapping in the workflow's InputSourceConfig.

    ", + "documentation":"

    Deletes the SchemaMapping with a given name. This operation returns a ResourceNotFoundException if a schema with the given name does not exist. This operation will fail if there is a MatchingWorkflow object that references the SchemaMapping in the workflow's InputSourceConfig.

    ", "idempotent":true }, "GenerateMatchId":{ @@ -702,7 +706,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ValidationException"} ], - "documentation":"

    Updates an existing matching workflow. The workflow must already exist for this operation to succeed.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    ", + "documentation":"

    Updates an existing matching workflow. The workflow must already exist for this operation to succeed.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    ", "idempotent":true }, "UpdateSchemaMapping":{ @@ -1101,7 +1105,7 @@ }, "incrementalRunConfig":{ "shape":"IncrementalRunConfig", - "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    " + "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    " }, "roleArn":{ "shape":"String", @@ -1526,7 +1530,7 @@ }, "processingType":{ "shape":"ProcessingType", - "documentation":"

    The processing mode that determines how Match IDs are generated and results are saved. Each mode provides different levels of accuracy, response time, and completeness of results.

    If not specified, defaults to CONSISTENT.

    CONSISTENT: Performs immediate lookup and matching against all existing records, with results saved synchronously. Provides highest accuracy but slower response time.

    EVENTUAL (shown as Background in the console): Performs initial match ID lookup or generation immediately, with record updates processed asynchronously in the background. Offers faster initial response time, with complete matching results available later in S3.

    EVENTUAL_NO_LOOKUP (shown as Quick ID generation in the console): Generates new match IDs without checking existing matches, with updates processed asynchronously. Provides fastest response time but should only be used for records known to be unique.

    " + "documentation":"

    The processing mode that determines how Match IDs are generated and results are saved. Each mode provides different levels of accuracy, response time, and completeness of results.

    If not specified, defaults to CONSISTENT.

    CONSISTENT: Performs immediate lookup and matching against all existing records, with results saved synchronously. Provides highest accuracy but slower response time.

    EVENTUAL (shown as Background in the console): Performs initial match ID lookup or generation immediately, with record updates processed asynchronously in the background. Offers faster initial response time, with complete matching results available later in S3.

    EVENTUAL_NO_LOOKUP (shown as Quick ID generation in the console): Generates new match IDs without checking existing matches, with updates processed asynchronously. Provides fastest response time but should only be used for records known to be unique.

    Advanced matching workflows don't support the processingType field.

    " } } }, @@ -2486,10 +2490,10 @@ "members":{ "incrementalRunType":{ "shape":"IncrementalRunType", - "documentation":"

    The type of incremental run. The only valid value is IMMEDIATE. This appears as \"Automatic\" in the console.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    " + "documentation":"

    The type of incremental run. The only valid value is IMMEDIATE. This appears as \"Automatic\" in the console.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    " } }, - "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    " + "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    " }, "IncrementalRunType":{ "type":"string", @@ -3502,6 +3506,10 @@ "shape":"RuleConditionProperties", "documentation":"

    An object containing the rules for a matching workflow.

    " }, + "enableRealTimeMatching":{ + "shape":"Boolean", + "documentation":"

    Specifies whether real-time matching is enabled for the rule-based matching workflow. When you enable real-time matching, you can use the GenerateMatchId operation with the workflow.

    " + }, "providerProperties":{ "shape":"ProviderProperties", "documentation":"

    The properties of the provider service.

    " @@ -3714,7 +3722,7 @@ "SchemaInputAttributes":{ "type":"list", "member":{"shape":"SchemaInputAttribute"}, - "max":35, + "max":60, "min":2 }, "SchemaList":{ @@ -3866,7 +3874,7 @@ "type":"string", "max":64, "min":12, - "pattern":"(\\d{12})|([a-z0-9\\.]+)" + "pattern":"((\\d{12})|([a-z0-9\\.]+))" }, "StatementPrincipalList":{ "type":"list", @@ -4162,7 +4170,7 @@ }, "incrementalRunConfig":{ "shape":"IncrementalRunConfig", - "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is ML_MATCHING or PROVIDER, incremental processing is not supported.

    " + "documentation":"

    Optional. An object that defines the incremental run type. This object contains only the incrementalRunType field, which appears as \"Automatic\" in the console.

    For workflows where resolutionType is PROVIDER, incremental processing is not supported.

    " }, "roleArn":{ "shape":"String", diff --git a/services/eventbridge/pom.xml b/services/eventbridge/pom.xml index 989118a41d17..9dcaa1784667 100644 --- a/services/eventbridge/pom.xml +++ b/services/eventbridge/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT eventbridge AWS Java SDK :: Services :: EventBridge diff --git a/services/eventbridge/src/main/resources/codegen-resources/customization.config b/services/eventbridge/src/main/resources/codegen-resources/customization.config index 4aa0caa705ce..19369e8d87f4 100644 --- a/services/eventbridge/src/main/resources/codegen-resources/customization.config +++ b/services/eventbridge/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "enableEndpointAuthSchemeParams": true, "allowedEndpointAuthSchemeParams": [ "EndpointId" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/eventbridge/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/eventbridge/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..68a0e38a6824 --- /dev/null +++ b/services/eventbridge/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,330 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "EndpointId": { + "required": false, + "documentation": "Operation parameter for EndpointId", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "EndpointId" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "EndpointId" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://events.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "events", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoint.events.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "events", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoint.events.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "events", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS is not supported with EventBridge multi-region endpoints.", + "type": "error" + }, + { + "conditions": [], + "error": "EndpointId must be a valid host label.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://events.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 31, + "nodes": "/////wAAAAH/////AAAAAAAAAAQAAAADAAAAAQAAABsF9eESAAAAAQAAABkAAAAFAAAAAgAAABEAAAAGAAAAAwAAAAcF9eESAAAABAAAAAoAAAAIAAAABQAAAAkF9eERAAAACQX14QEF9eEEAAAABQAAAA4AAAALAAAACAAAAAwF9eEQAAAACgX14Q0AAAANAAAACwX14Q4F9eEPAAAABgX14QEAAAAPAAAACAAAABAF9eEMAAAACQX14QsF9eEMAAAAAwAAABIF9eESAAAABAAAABcAAAATAAAABQAAABUAAAAUAAAABwX14QUF9eEHAAAABwAAABYF9eEHAAAACQX14QMF9eEEAAAABQAAABgAAAAfAAAABgX14QEAAAAfAAAAAgAAABoAAAAbAAAAAwAAAB0AAAAbAAAABAX14QgAAAAcAAAABQX14QkF9eEKAAAABAAAAB8AAAAeAAAABwX14QIF9eEHAAAABwX14QYF9eEH" +} \ No newline at end of file diff --git a/services/eventbridge/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/eventbridge/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8f04a80e65ed..000000000000 --- a/services/eventbridge/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,615 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "EndpointId": { - "required": false, - "documentation": "Operation parameter for EndpointId", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://events.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "EndpointId" - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "EndpointId" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "events", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{EndpointId}.endpoint.events.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "events", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{EndpointId}.endpoint.events.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "events", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: FIPS is not supported with EventBridge multi-region endpoints.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "EndpointId must be a valid host label.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://events.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://events.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://events-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://events.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://events.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/evs/pom.xml b/services/evs/pom.xml index 74248bc2f271..5d70508263f7 100644 --- a/services/evs/pom.xml +++ b/services/evs/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT evs AWS Java SDK :: Services :: Evs diff --git a/services/evs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/evs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9cda059f1667 --- /dev/null +++ b/services/evs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://evs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://evs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://evs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://evs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/evs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/evs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3ff5b324eb31..000000000000 --- a/services/evs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://evs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://evs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://evs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://evs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/evs/src/main/resources/codegen-resources/service-2.json b/services/evs/src/main/resources/codegen-resources/service-2.json index 15480c726041..aa9fc52d8306 100644 --- a/services/evs/src/main/resources/codegen-resources/service-2.json +++ b/services/evs/src/main/resources/codegen-resources/service-2.json @@ -171,6 +171,22 @@ "documentation":"

    Disassociates an Elastic IP address from a public HCX VLAN. This operation is only allowed for public HCX VLANs at this time.

    ", "idempotent":true }, + "GetAccountSettings":{ + "name":"GetAccountSettings", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAccountSettingsRequest"}, + "output":{"shape":"GetAccountSettingsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns the configured EVS settings for your Amazon Web Services account in the specified Amazon Web Services Region. If no settings have been set, an empty list is returned.

    ", + "readonly":true + }, "GetDepotUrl":{ "name":"GetDepotUrl", "http":{ @@ -305,6 +321,22 @@ "documentation":"

    Lists the Windows Server License entitlements for virtual machines in an Amazon EVS environment. Returns existing entitlements for virtual machines associated with the specified environment and connector.

    ", "readonly":true }, + "PutAccountSettings":{ + "name":"PutAccountSettings", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"PutAccountSettingsRequest"}, + "output":{"shape":"PutAccountSettingsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates or updates account-level EVS settings for your Amazon Web Services account in the specified Amazon Web Services Region.

    EVS settings included in the request are created or overwritten. Settings omitted from the request retain their current values.

    ", + "idempotent":true + }, "TagResource":{ "name":"TagResource", "http":{ @@ -355,6 +387,31 @@ } }, "shapes":{ + "AccountSetting":{ + "type":"structure", + "required":[ + "name", + "value" + ], + "members":{ + "name":{ + "shape":"SettingName", + "documentation":"

    The name of the EVS setting. Valid values are:

    • vcfPortedCoreCount (type: numeric string) - The total number of VCF license cores ported to Amazon EVS for the account in that Region. The maximum value is 1,000,000 cores. This setting value is shared with Broadcom for record-keeping.

    " + }, + "value":{ + "shape":"SettingValue", + "documentation":"

    The value of the EVS setting.

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

    A regional account-level EVS setting, represented as a name and value pair.

    " + }, + "AccountSettingList":{ + "type":"list", + "member":{"shape":"AccountSetting"}, + "documentation":"

    A list of regional account-level EVS settings.

    ", + "max":100, + "min":0 + }, "AllocationId":{ "type":"string", "max":26, @@ -1196,6 +1253,21 @@ "type":"list", "member":{"shape":"String"} }, + "GetAccountSettingsRequest":{ + "type":"structure", + "members":{}, + "documentation":"

    The request for the GetAccountSettings operation.

    " + }, + "GetAccountSettingsResponse":{ + "type":"structure", + "members":{ + "settings":{ + "shape":"AccountSettingList", + "documentation":"

    A list of regional account-level EVS settings for the account. EVS settings that have never been explicitly set are omitted from the response.

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

    The response for the GetAccountSettings operation.

    " + }, "GetDepotUrlRequest":{ "type":"structure", "required":["environmentId"], @@ -1459,7 +1531,8 @@ "type":"string", "enum":[ "i4i.metal", - "i7i.metal-24xl" + "i7i.metal-24xl", + "i7i.metal-48xl" ] }, "InstanceTypeEsxVersionsInfo":{ @@ -1765,6 +1838,27 @@ "min":1, "pattern":"pg-[a-f0-9]{8}([a-f0-9]{9})?" }, + "PutAccountSettingsRequest":{ + "type":"structure", + "required":["settings"], + "members":{ + "settings":{ + "shape":"AccountSettingList", + "documentation":"

    A list of regional account-level EVS settings to create or update. Only the settings included in this list are modified.

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

    The request for the PutAccountSettings operation.

    " + }, + "PutAccountSettingsResponse":{ + "type":"structure", + "members":{ + "settings":{ + "shape":"AccountSettingList", + "documentation":"

    A list of regional account-level EVS settings, and their values, that were modified in this request.

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

    The response for the PutAccountSettings operation.

    " + }, "RequestTagMap":{ "type":"map", "key":{"shape":"TagKey"}, @@ -1866,6 +1960,20 @@ "documentation":"

    The number of one or more Amazon EVS resources exceeds the maximum allowed. For a list of Amazon EVS quotas, see Amazon EVS endpoints and quotas in the Amazon EVS User Guide. Delete some resources or request an increase in your service quota. To request an increase, see Amazon Web Services Service Quotas in the Amazon Web Services General Reference Guide.

    ", "exception":true }, + "SettingName":{ + "type":"string", + "documentation":"

    The name of a regional account-level EVS setting, such as vcfPortedCoreCount.

    ", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9]+" + }, + "SettingValue":{ + "type":"string", + "documentation":"

    The value of a regional account-level EVS setting, represented as a string.

    ", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9]+" + }, "SolutionKey":{ "type":"string", "pattern":"[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}-[a-zA-Z0-9]{5}", diff --git a/services/finspace/pom.xml b/services/finspace/pom.xml index ec46ad1fbd22..5555b376ef77 100644 --- a/services/finspace/pom.xml +++ b/services/finspace/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT finspace AWS Java SDK :: Services :: Finspace diff --git a/services/finspace/src/main/resources/codegen-resources/customization.config b/services/finspace/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/finspace/src/main/resources/codegen-resources/customization.config +++ b/services/finspace/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/finspace/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/finspace/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..aec1b9facbed --- /dev/null +++ b/services/finspace/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/finspace/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/finspace/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 41c7a20b5bb6..000000000000 --- a/services/finspace/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://finspace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/finspacedata/pom.xml b/services/finspacedata/pom.xml index c4ae5a8b92f4..3a2247b07dc3 100644 --- a/services/finspacedata/pom.xml +++ b/services/finspacedata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT finspacedata AWS Java SDK :: Services :: Finspace Data diff --git a/services/finspacedata/src/main/resources/codegen-resources/customization.config b/services/finspacedata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/finspacedata/src/main/resources/codegen-resources/customization.config +++ b/services/finspacedata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/finspacedata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/finspacedata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..557a9a18a6d5 --- /dev/null +++ b/services/finspacedata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-api-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-api.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://finspace-api.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/finspacedata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/finspacedata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 55cc0620f040..000000000000 --- a/services/finspacedata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace-api-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://finspace-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://finspace-api.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/firehose/pom.xml b/services/firehose/pom.xml index 0157f519968c..4fb249cd3b32 100644 --- a/services/firehose/pom.xml +++ b/services/firehose/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT firehose AWS Java SDK :: Services :: Amazon Kinesis Firehose diff --git a/services/firehose/src/main/resources/codegen-resources/customization.config b/services/firehose/src/main/resources/codegen-resources/customization.config index 85aba7197c80..3fc91f70a397 100644 --- a/services/firehose/src/main/resources/codegen-resources/customization.config +++ b/services/firehose/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listDeliveryStreams" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/firehose/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/firehose/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8d4e93b6a3b7 --- /dev/null +++ b/services/firehose/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://firehose-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://firehose-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://firehose.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://firehose.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/firehose/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/firehose/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b0f74afee4e0..000000000000 --- a/services/firehose/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://firehose-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://firehose-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://firehose.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://firehose.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/fis/pom.xml b/services/fis/pom.xml index 1a41e93112a4..fec636b92b6e 100644 --- a/services/fis/pom.xml +++ b/services/fis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT fis AWS Java SDK :: Services :: Fis diff --git a/services/fis/src/main/resources/codegen-resources/customization.config b/services/fis/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/fis/src/main/resources/codegen-resources/customization.config +++ b/services/fis/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/fis/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/fis/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..06ca5eae71ce --- /dev/null +++ b/services/fis/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fis.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/fis/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/fis/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d5f7034582d8..000000000000 --- a/services/fis/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://fis.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://fis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://fis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/fms/pom.xml b/services/fms/pom.xml index 34b01c2c13fc..69c5ed49576d 100644 --- a/services/fms/pom.xml +++ b/services/fms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT fms AWS Java SDK :: Services :: FMS diff --git a/services/fms/src/main/resources/codegen-resources/customization.config b/services/fms/src/main/resources/codegen-resources/customization.config index b394eea2b025..834626df3f78 100644 --- a/services/fms/src/main/resources/codegen-resources/customization.config +++ b/services/fms/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ "getNotificationChannel", "listMemberAccounts", "listPolicies" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/fms/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/fms/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..876514ad3c10 --- /dev/null +++ b/services/fms/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fms-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fms.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fms.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/fms/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/fms/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e9ff6750d4c4..000000000000 --- a/services/fms/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fms-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fms.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://fms.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/forecast/pom.xml b/services/forecast/pom.xml index 55183edce071..26e9dc3943df 100644 --- a/services/forecast/pom.xml +++ b/services/forecast/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT forecast AWS Java SDK :: Services :: Forecast diff --git a/services/forecast/src/main/resources/codegen-resources/customization.config b/services/forecast/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/forecast/src/main/resources/codegen-resources/customization.config +++ b/services/forecast/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/forecast/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/forecast/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5f6da6142216 --- /dev/null +++ b/services/forecast/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecast-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecast-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecast.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecast.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/forecast/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/forecast/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cc680847754e..000000000000 --- a/services/forecast/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecast-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecast-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecast.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://forecast.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/forecastquery/pom.xml b/services/forecastquery/pom.xml index 390a02e68940..b181b5d37655 100644 --- a/services/forecastquery/pom.xml +++ b/services/forecastquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT forecastquery AWS Java SDK :: Services :: Forecastquery diff --git a/services/forecastquery/src/main/resources/codegen-resources/customization.config b/services/forecastquery/src/main/resources/codegen-resources/customization.config index c2457f7c37ab..0db3279e44b0 100644 --- a/services/forecastquery/src/main/resources/codegen-resources/customization.config +++ b/services/forecastquery/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true - } diff --git a/services/forecastquery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/forecastquery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6180622764c0 --- /dev/null +++ b/services/forecastquery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecastquery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecastquery-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecastquery.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://forecastquery.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/forecastquery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/forecastquery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f835a3143f35..000000000000 --- a/services/forecastquery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecastquery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecastquery-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://forecastquery.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://forecastquery.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/frauddetector/pom.xml b/services/frauddetector/pom.xml index 3912e63ffb5d..2ef98f715697 100644 --- a/services/frauddetector/pom.xml +++ b/services/frauddetector/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT frauddetector AWS Java SDK :: Services :: FraudDetector diff --git a/services/frauddetector/src/main/resources/codegen-resources/customization.config b/services/frauddetector/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/frauddetector/src/main/resources/codegen-resources/customization.config +++ b/services/frauddetector/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/frauddetector/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/frauddetector/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c9f1cd241b5a --- /dev/null +++ b/services/frauddetector/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://frauddetector-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://frauddetector-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://frauddetector.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://frauddetector.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/frauddetector/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/frauddetector/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2baf23deef9d..000000000000 --- a/services/frauddetector/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://frauddetector-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://frauddetector-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://frauddetector.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://frauddetector.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/freetier/pom.xml b/services/freetier/pom.xml index d98d97f7c219..c4cdc770fce8 100644 --- a/services/freetier/pom.xml +++ b/services/freetier/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT freetier AWS Java SDK :: Services :: Free Tier diff --git a/services/freetier/src/main/resources/codegen-resources/customization.config b/services/freetier/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/freetier/src/main/resources/codegen-resources/customization.config +++ b/services/freetier/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/freetier/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/freetier/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8fed22cdff90 --- /dev/null +++ b/services/freetier/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-cn-global" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier-fips.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "freetier", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier.cn-northwest-1.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "freetier", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://freetier.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 12, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAkAAAAGAAAABQX14QUAAAAHAAAABgX14QcAAAAIAAAABwX14QgF9eEKAAAABAAAAAoF9eEEAAAABQX14QMAAAALAAAABwX14QYF9eEJAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/freetier/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/freetier/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 35c02baea537..000000000000 --- a/services/freetier/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,392 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://freetier-fips.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://freetier.us-east-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "freetier", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://freetier-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-cn-global" - ] - } - ], - "endpoint": { - "url": "https://freetier.cn-northwest-1.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "freetier", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://freetier.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://freetier-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-cn-global" - ] - } - ], - "endpoint": { - "url": "https://freetier.cn-northwest-1.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "freetier", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://freetier.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/fsx/pom.xml b/services/fsx/pom.xml index 27b1dec7c6ea..10b1c4da866b 100644 --- a/services/fsx/pom.xml +++ b/services/fsx/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT fsx AWS Java SDK :: Services :: FSx diff --git a/services/fsx/src/main/resources/codegen-resources/customization.config b/services/fsx/src/main/resources/codegen-resources/customization.config index 43360d6a47fa..3d6f14e169f6 100644 --- a/services/fsx/src/main/resources/codegen-resources/customization.config +++ b/services/fsx/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "describeBackups", "describeFileSystems" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/fsx/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/fsx/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c22f531b42df --- /dev/null +++ b/services/fsx/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fsx-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fsx-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fsx.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fsx.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/fsx/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/fsx/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2e54c396a1b3..000000000000 --- a/services/fsx/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fsx-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fsx-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://fsx.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://fsx.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/gamelift/pom.xml b/services/gamelift/pom.xml index 6a7b41654061..b981d20c42de 100644 --- a/services/gamelift/pom.xml +++ b/services/gamelift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT gamelift AWS Java SDK :: Services :: AWS GameLift diff --git a/services/gamelift/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/gamelift/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..eacc5e7b9f98 --- /dev/null +++ b/services/gamelift/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gamelift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gamelift-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gamelift.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gamelift.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/gamelift/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/gamelift/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 851262a98238..000000000000 --- a/services/gamelift/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://gamelift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://gamelift-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://gamelift.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://gamelift.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/gamelift/src/main/resources/codegen-resources/service-2.json b/services/gamelift/src/main/resources/codegen-resources/service-2.json index a2fc95cbab98..bda9eca0a4c7 100644 --- a/services/gamelift/src/main/resources/codegen-resources/service-2.json +++ b/services/gamelift/src/main/resources/codegen-resources/service-2.json @@ -165,7 +165,7 @@ {"shape":"ConflictException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Adds remote locations to an EC2 and begins populating the new locations with instances. The new instances conform to the fleet's instance type, auto-scaling, and other configuration settings.

    You can't add remote locations to a fleet that resides in an Amazon Web Services Region that doesn't support multiple locations. Fleets created prior to March 2021 can't support multiple locations.

    To add fleet locations, specify the fleet to be updated and provide a list of one or more locations.

    If successful, this operation returns the list of added locations with their status set to NEW. Amazon GameLift Servers initiates the process of starting an instance in each added location. You can track the status of each new location by monitoring location creation events using DescribeFleetEvents.

    Learn more

    Setting up fleets

    Update fleet locations

    Amazon GameLift Servers service locations for managed hosting.

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Adds remote locations to an EC2 and begins populating the new locations with instances. The new instances conform to the fleet's instance type, auto-scaling, and other configuration settings.

    You can't add remote locations to a fleet that resides in an Amazon Web Services Region that doesn't support multiple locations. Fleets created prior to March 2021 can't support multiple locations.

    To add fleet locations, specify the fleet to be updated and provide a list of one or more locations.

    If successful, this operation returns the list of added locations with their status set to NEW. Amazon GameLift Servers initiates the process of starting an instance in each added location. You can track the status of each new location by monitoring location creation events using DescribeFleetEvents.

    Learn more

    Setting up fleets

    Update fleet locations

    Amazon GameLift Servers service locations for managed hosting.

    " }, "CreateGameServerGroup":{ "name":"CreateGameServerGroup", @@ -239,6 +239,7 @@ {"shape":"LimitExceededException"}, {"shape":"ConflictException"}, {"shape":"TaggingFailedException"}, + {"shape":"UnsupportedRegionException"}, {"shape":"InternalServiceException"} ], "documentation":"

    This API works with the following fleet types: Anywhere

    Creates a custom location for use in an Anywhere fleet.

    " @@ -448,7 +449,7 @@ {"shape":"InvalidRequestException"}, {"shape":"TaggingFailedException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Deletes all resources and information related to a fleet and shuts down any currently running fleet instances, including those in remote locations.

    If the fleet being deleted has a VPC peering connection, you first need to get a valid authorization (good for 24 hours) by calling CreateVpcPeeringAuthorization. You don't need to explicitly delete the VPC peering connection.

    To delete a fleet, specify the fleet ID to be terminated. During the deletion process, the fleet status is changed to DELETING. When completed, the status switches to TERMINATED and the fleet event FLEET_DELETED is emitted.

    Learn more

    Setting up Amazon GameLift Servers Fleets

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere

    Deletes all resources and information related to a fleet and shuts down any currently running fleet instances, including those in remote locations.

    If the fleet being deleted has a VPC peering connection, you first need to get a valid authorization (good for 24 hours) by calling CreateVpcPeeringAuthorization. You don't need to explicitly delete the VPC peering connection.

    To delete a fleet, specify the fleet ID to be terminated. During the deletion process, the fleet status is changed to DELETING. When completed, the status switches to TERMINATED and the fleet event FLEET_DELETED is emitted.

    Learn more

    Setting up Amazon GameLift Servers Fleets

    " }, "DeleteFleetLocations":{ "name":"DeleteFleetLocations", @@ -465,7 +466,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Removes locations from a multi-location fleet. When deleting a location, all game server process and all instances that are still active in the location are shut down.

    To delete fleet locations, identify the fleet ID and provide a list of the locations to be deleted.

    If successful, GameLift sets the location status to DELETING, and begins to shut down existing server processes and terminate instances in each location being deleted. When completed, the location status changes to TERMINATED.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Removes locations from a multi-location fleet. When deleting a location, all game server process and all instances that are still active in the location are shut down.

    To delete fleet locations, identify the fleet ID and provide a list of the locations to be deleted.

    If successful, GameLift sets the location status to DELETING, and begins to shut down existing server processes and terminate instances in each location being deleted. When completed, the location status changes to TERMINATED.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " }, "DeleteGameServerGroup":{ "name":"DeleteGameServerGroup", @@ -512,6 +513,7 @@ {"shape":"UnauthorizedException"}, {"shape":"InvalidRequestException"}, {"shape":"NotFoundException"}, + {"shape":"UnsupportedRegionException"}, {"shape":"InternalServiceException"} ], "documentation":"

    This API works with the following fleet types: Anywhere

    Deletes a custom location.

    Before deleting a custom location, review any fleets currently using the custom location and deregister the location if it is in use. For more information, see DeregisterCompute.

    " @@ -564,7 +566,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2

    Deletes a fleet scaling policy. Once deleted, the policy is no longer in force and Amazon GameLift Servers removes all record of it. To delete a scaling policy, specify both the scaling policy name and the fleet ID it is associated with.

    To temporarily suspend scaling policies, use StopFleetActions. This operation suspends all policies for the fleet.

    " + "documentation":"

    This API works with the following fleet types: EC2, Container

    Deletes a fleet scaling policy. Once deleted, the policy is no longer in force and Amazon GameLift Servers removes all record of it. To delete a scaling policy, specify both the scaling policy name and the fleet ID it is associated with.

    To temporarily suspend scaling policies, use StopFleetActions. This operation suspends all policies for the fleet.

    " }, "DeleteScript":{ "name":"DeleteScript", @@ -626,7 +628,8 @@ {"shape":"UnauthorizedException"}, {"shape":"InvalidRequestException"}, {"shape":"NotFoundException"}, - {"shape":"InternalServiceException"} + {"shape":"InternalServiceException"}, + {"shape":"UnsupportedRegionException"} ], "documentation":"

    This API works with the following fleet types: Anywhere

    Removes a compute resource from an Anywhere fleet. Deregistered computes can no longer host game sessions through Amazon GameLift Servers. Use this operation with an Anywhere fleet that doesn't use the Amazon GameLift Servers Agent For Anywhere fleets with the Agent, the Agent handles all compute registry tasks for you.

    To deregister a compute, call this operation from the compute that's being deregistered and specify the compute name and the fleet ID.

    " }, @@ -844,7 +847,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Retrieves information on a fleet's remote locations, including life-cycle status and any suspended fleet activity.

    This operation can be used in the following ways:

    • To get data for specific locations, provide a fleet identifier and a list of locations. Location data is returned in the order that it is requested.

    • To get data for all locations, provide a fleet identifier only. Location data is returned in no particular order.

    When requesting attributes for multiple locations, use the pagination parameters to retrieve results as a set of sequential pages.

    If successful, a LocationAttributes object is returned for each requested location. If the fleet does not have a requested location, no information is returned.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Retrieves information on a fleet's remote locations, including life-cycle status and any suspended fleet activity.

    This operation can be used in the following ways:

    • To get data for specific locations, provide a fleet identifier and a list of locations. Location data is returned in the order that it is requested.

    • To get data for all locations, provide a fleet identifier only. Location data is returned in no particular order.

    When requesting attributes for multiple locations, use the pagination parameters to retrieve results as a set of sequential pages.

    If successful, a LocationAttributes object is returned for each requested location. If the fleet does not have a requested location, no information is returned.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    " }, "DescribeFleetLocationCapacity":{ "name":"DescribeFleetLocationCapacity", @@ -861,7 +864,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Retrieves the resource capacity settings for a fleet location. The data returned includes the current capacity (number of EC2 instances) and some scaling settings for the requested fleet location. For a managed container fleet, this operation also returns counts for game server container groups.

    Use this operation to retrieve capacity information for a fleet's remote location or home Region (you can also retrieve home Region capacity by calling DescribeFleetCapacity).

    To retrieve capacity data, identify a fleet and location.

    If successful, a FleetCapacity object is returned for the requested fleet location.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    GameLift metrics for fleets

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Retrieves the resource capacity settings for a fleet location. The data returned includes the current capacity (number of EC2 instances) and some scaling settings for the requested fleet location. For a managed container fleet, this operation also returns counts for game server container groups.

    Use this operation to retrieve capacity information for a fleet's remote location or home Region (you can also retrieve home Region capacity by calling DescribeFleetCapacity).

    To retrieve capacity data, identify a fleet and location.

    If successful, a FleetCapacity object is returned for the requested fleet location.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    GameLift metrics for fleets

    " }, "DescribeFleetLocationUtilization":{ "name":"DescribeFleetLocationUtilization", @@ -878,7 +881,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Retrieves current usage data for a fleet location. Utilization data provides a snapshot of current game hosting activity at the requested location. Use this operation to retrieve utilization information for a fleet's remote location or home Region (you can also retrieve home Region utilization by calling DescribeFleetUtilization).

    To retrieve utilization data, identify a fleet and location.

    If successful, a FleetUtilization object is returned for the requested fleet location.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    GameLift metrics for fleets

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere

    Retrieves current usage data for a fleet location. Utilization data provides a snapshot of current game hosting activity at the requested location. Use this operation to retrieve utilization information for a fleet's remote location or home Region (you can also retrieve home Region utilization by calling DescribeFleetUtilization).

    To retrieve utilization data, identify a fleet and location.

    If successful, a FleetUtilization object is returned for the requested fleet location.

    Learn more

    Setting up Amazon GameLift Servers fleets

    Amazon GameLift Servers service locations for managed hosting

    GameLift metrics for fleets

    " }, "DescribeFleetPortSettings":{ "name":"DescribeFleetPortSettings", @@ -895,7 +898,7 @@ {"shape":"UnauthorizedException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Retrieves a fleet's inbound connection permissions. Connection permissions specify IP addresses and port settings that incoming traffic can use to access server processes in the fleet. Game server processes that are running in the fleet must use a port that falls within this range.

    Use this operation in the following ways:

    • To retrieve the port settings for a fleet, identify the fleet's unique identifier.

    • To check the status of recent updates to a fleet remote location, specify the fleet ID and a location. Port setting updates can take time to propagate across all locations.

    If successful, a set of IpPermission objects is returned for the requested fleet ID. When specifying a location, this operation returns a pending status. If the requested fleet has been deleted, the result set is empty.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " + "documentation":"

    This API works with the following fleet types: EC2

    Retrieves a fleet's inbound connection permissions. Connection permissions specify IP addresses and port settings that incoming traffic can use to access server processes in the fleet. Game server processes that are running in the fleet must use a port that falls within this range.

    Use this operation in the following ways:

    • To retrieve the port settings for a fleet, identify the fleet's unique identifier.

    • To check the status of recent updates to a fleet remote location, specify the fleet ID and a location. Port setting updates can take time to propagate across all locations.

    If successful, a set of IpPermission objects is returned for the requested fleet ID. When specifying a location, this operation returns a pending status. If the requested fleet has been deleted, the result set is empty.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " }, "DescribeFleetUtilization":{ "name":"DescribeFleetUtilization", @@ -911,7 +914,7 @@ {"shape":"InvalidRequestException"}, {"shape":"UnauthorizedException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Retrieves utilization statistics for one or more fleets. Utilization data provides a snapshot of how the fleet's hosting resources are currently being used. For fleets with remote locations, this operation retrieves data for the fleet's home Region only. See DescribeFleetLocationUtilization to get utilization statistics for a fleet's remote locations.

    This operation can be used in the following ways:

    • To get utilization data for one or more specific fleets, provide a list of fleet IDs or fleet ARNs.

    • To get utilization data for all fleets, do not provide a fleet identifier.

    When requesting multiple fleets, use the pagination parameters to retrieve results as a set of sequential pages.

    If successful, a FleetUtilization object is returned for each requested fleet ID, unless the fleet identifier is not found. Each fleet utilization object includes a Location property, which is set to the fleet's home Region.

    Some API operations may limit the number of fleet IDs allowed in one request. If a request exceeds this limit, the request fails and the error message includes the maximum allowed.

    Learn more

    Setting up Amazon GameLift Servers Fleets

    GameLift Metrics for Fleets

    " + "documentation":"

    This API works with the following fleet types: EC2

    Retrieves utilization statistics for one or more fleets. Utilization data provides a snapshot of how the fleet's hosting resources are currently being used. For fleets with remote locations, this operation retrieves data for the fleet's home Region only. See DescribeFleetLocationUtilization to get utilization statistics for a fleet's remote locations.

    This operation can be used in the following ways:

    • To get utilization data for one or more specific fleets, provide a list of fleet IDs or fleet ARNs.

    • To get utilization data for all fleets, do not provide a fleet identifier.

    When requesting multiple fleets, use the pagination parameters to retrieve results as a set of sequential pages.

    If successful, a FleetUtilization object is returned for each requested fleet ID, unless the fleet identifier is not found. Each fleet utilization object includes a Location property, which is set to the fleet's home Region.

    Some API operations may limit the number of fleet IDs allowed in one request. If a request exceeds this limit, the request fails and the error message includes the maximum allowed.

    Learn more

    Setting up Amazon GameLift Servers Fleets

    GameLift Metrics for Fleets

    " }, "DescribeGameServer":{ "name":"DescribeGameServer", @@ -1139,7 +1142,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2

    Retrieves all scaling policies applied to a fleet.

    To get a fleet's scaling policies, specify the fleet ID. You can filter this request by policy status, such as to retrieve only active scaling policies. Use the pagination parameters to retrieve results as a set of sequential pages. If successful, set of ScalingPolicy objects is returned for the fleet.

    A fleet may have all of its scaling policies suspended. This operation does not affect the status of the scaling policies, which remains ACTIVE.

    " + "documentation":"

    This API works with the following fleet types: EC2, Container

    Retrieves all scaling policies applied to a fleet.

    To get a fleet's scaling policies, specify the fleet ID. You can filter this request by policy status, such as to retrieve only active scaling policies. Use the pagination parameters to retrieve results as a set of sequential pages. If successful, set of ScalingPolicy objects is returned for the fleet.

    A fleet may have all of its scaling policies suspended. This operation does not affect the status of the scaling policies, which remains ACTIVE.

    " }, "DescribeScript":{ "name":"DescribeScript", @@ -1493,7 +1496,7 @@ {"shape":"NotFoundException"}, {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: EC2

    Creates or updates a scaling policy for a fleet. Scaling policies are used to automatically scale a fleet's hosting capacity to meet player demand. An active scaling policy instructs Amazon GameLift Servers to track a fleet metric and automatically change the fleet's capacity when a certain threshold is reached. There are two types of scaling policies: target-based and rule-based. Use a target-based policy to quickly and efficiently manage fleet scaling; this option is the most commonly used. Use rule-based policies when you need to exert fine-grained control over auto-scaling.

    Fleets can have multiple scaling policies of each type in force at the same time; you can have one target-based policy, one or multiple rule-based scaling policies, or both. We recommend caution, however, because multiple auto-scaling policies can have unintended consequences.

    Learn more about how to work with auto-scaling in Set Up Fleet Automatic Scaling.

    Target-based policy

    A target-based policy tracks a single metric: PercentAvailableGameSessions. This metric tells us how much of a fleet's hosting capacity is ready to host game sessions but is not currently in use. This is the fleet's buffer; it measures the additional player demand that the fleet could handle at current capacity. With a target-based policy, you set your ideal buffer size and leave it to Amazon GameLift Servers to take whatever action is needed to maintain that target.

    For example, you might choose to maintain a 10% buffer for a fleet that has the capacity to host 100 simultaneous game sessions. This policy tells Amazon GameLift Servers to take action whenever the fleet's available capacity falls below or rises above 10 game sessions. Amazon GameLift Servers will start new instances or stop unused instances in order to return to the 10% buffer.

    To create or update a target-based policy, specify a fleet ID and name, and set the policy type to \"TargetBased\". Specify the metric to track (PercentAvailableGameSessions) and reference a TargetConfiguration object with your desired buffer value. Exclude all other parameters. On a successful request, the policy name is returned. The scaling policy is automatically in force as soon as it's successfully created. If the fleet's auto-scaling actions are temporarily suspended, the new policy will be in force once the fleet actions are restarted.

    Rule-based policy

    A rule-based policy tracks specified fleet metric, sets a threshold value, and specifies the type of action to initiate when triggered. With a rule-based policy, you can select from several available fleet metrics. Each policy specifies whether to scale up or scale down (and by how much), so you need one policy for each type of action.

    For example, a policy may make the following statement: \"If the percentage of idle instances is greater than 20% for more than 15 minutes, then reduce the fleet capacity by 10%.\"

    A policy's rule statement has the following structure:

    If [MetricName] is [ComparisonOperator] [Threshold] for [EvaluationPeriods] minutes, then [ScalingAdjustmentType] to/by [ScalingAdjustment].

    To implement the example, the rule statement would look like this:

    If [PercentIdleInstances] is [GreaterThanThreshold] [20] for [15] minutes, then [PercentChangeInCapacity] to/by [10].

    To create or update a scaling policy, specify a unique combination of name and fleet ID, and set the policy type to \"RuleBased\". Specify the parameter values for a policy rule statement. On a successful request, the policy name is returned. Scaling policies are automatically in force as soon as they're successfully created. If the fleet's auto-scaling actions are temporarily suspended, the new policy will be in force once the fleet actions are restarted.

    " + "documentation":"

    This API works with the following fleet types: EC2, Container

    Creates or updates a scaling policy for a fleet. Scaling policies are used to automatically scale a fleet's hosting capacity to meet player demand. An active scaling policy instructs Amazon GameLift Servers to track a fleet metric and automatically change the fleet's capacity when a certain threshold is reached. There are two types of scaling policies: target-based and rule-based. Use a target-based policy to quickly and efficiently manage fleet scaling; this option is the most commonly used. Use rule-based policies when you need to exert fine-grained control over auto-scaling.

    Fleets can have multiple scaling policies of each type in force at the same time; you can have one target-based policy, one or multiple rule-based scaling policies, or both. We recommend caution, however, because multiple auto-scaling policies can have unintended consequences.

    Learn more about how to work with auto-scaling in Set Up Fleet Automatic Scaling.

    Target-based policy

    A target-based policy tracks a single metric: PercentAvailableGameSessions. This metric tells us how much of a fleet's hosting capacity is ready to host game sessions but is not currently in use. This is the fleet's buffer; it measures the additional player demand that the fleet could handle at current capacity. With a target-based policy, you set your ideal buffer size and leave it to Amazon GameLift Servers to take whatever action is needed to maintain that target.

    For example, you might choose to maintain a 10% buffer for a fleet that has the capacity to host 100 simultaneous game sessions. This policy tells Amazon GameLift Servers to take action whenever the fleet's available capacity falls below or rises above 10 game sessions. Amazon GameLift Servers will start new instances or stop unused instances in order to return to the 10% buffer.

    To create or update a target-based policy, specify a fleet ID and name, and set the policy type to \"TargetBased\". Specify the metric to track (PercentAvailableGameSessions) and reference a TargetConfiguration object with your desired buffer value. Exclude all other parameters. On a successful request, the policy name is returned. The scaling policy is automatically in force as soon as it's successfully created. If the fleet's auto-scaling actions are temporarily suspended, the new policy will be in force once the fleet actions are restarted.

    Rule-based policy

    A rule-based policy tracks specified fleet metric, sets a threshold value, and specifies the type of action to initiate when triggered. With a rule-based policy, you can select from several available fleet metrics. Each policy specifies whether to scale up or scale down (and by how much), so you need one policy for each type of action.

    For example, a policy may make the following statement: \"If the percentage of idle instances is greater than 20% for more than 15 minutes, then reduce the fleet capacity by 10%.\"

    A policy's rule statement has the following structure:

    If [MetricName] is [ComparisonOperator] [Threshold] for [EvaluationPeriods] minutes, then [ScalingAdjustmentType] to/by [ScalingAdjustment].

    To implement the example, the rule statement would look like this:

    If [PercentIdleInstances] is [GreaterThanThreshold] [20] for [15] minutes, then [PercentChangeInCapacity] to/by [10].

    To create or update a scaling policy, specify a unique combination of name and fleet ID, and set the policy type to \"RuleBased\". Specify the parameter values for a policy rule statement. On a successful request, the policy name is returned. Scaling policies are automatically in force as soon as they're successfully created. If the fleet's auto-scaling actions are temporarily suspended, the new policy will be in force once the fleet actions are restarted.

    " }, "RegisterCompute":{ "name":"RegisterCompute", @@ -1509,9 +1512,10 @@ {"shape":"ConflictException"}, {"shape":"InternalServiceException"}, {"shape":"NotReadyException"}, - {"shape":"LimitExceededException"} + {"shape":"LimitExceededException"}, + {"shape":"UnsupportedRegionException"} ], - "documentation":"

    This API works with the following fleet types: Anywhere, Container

    Registers a compute resource in an Amazon GameLift Servers Anywhere fleet.

    For an Anywhere fleet that's running the Amazon GameLift Servers Agent, the Agent handles all compute registry tasks for you. For an Anywhere fleet that doesn't use the Agent, call this operation to register fleet computes.

    To register a compute, give the compute a name (must be unique within the fleet) and specify the compute resource's DNS name or IP address. Provide a fleet ID and a fleet location to associate with the compute being registered. You can optionally include the path to a TLS certificate on the compute resource.

    If successful, this operation returns compute details, including an Amazon GameLift Servers SDK endpoint or Agent endpoint. Game server processes running on the compute can use this endpoint to communicate with the Amazon GameLift Servers service. Each server process includes the SDK endpoint in its call to the Amazon GameLift Servers server SDK action InitSDK().

    To view compute details, call DescribeCompute with the compute name.

    Learn more

    " + "documentation":"

    This API works with the following fleet types: Anywhere

    Registers a compute resource in an Amazon GameLift Servers Anywhere fleet.

    For an Anywhere fleet that's running the Amazon GameLift Servers Agent, the Agent handles all compute registry tasks for you. For an Anywhere fleet that doesn't use the Agent, call this operation to register fleet computes.

    To register a compute, give the compute a name (must be unique within the fleet) and specify the compute resource's DNS name or IP address. Provide a fleet ID and a fleet location to associate with the compute being registered. You can optionally include the path to a TLS certificate on the compute resource.

    If successful, this operation returns compute details, including an Amazon GameLift Servers SDK endpoint or Agent endpoint. Game server processes running on the compute can use this endpoint to communicate with the Amazon GameLift Servers service. Each server process includes the SDK endpoint in its call to the Amazon GameLift Servers server SDK action InitSDK().

    To view compute details, call DescribeCompute with the compute name.

    Learn more

    " }, "RegisterGameServer":{ "name":"RegisterGameServer", @@ -1866,7 +1870,7 @@ {"shape":"InvalidRequestException"}, {"shape":"UnauthorizedException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Anywhere, Container

    Updates a fleet's mutable attributes, such as game session protection and resource creation limits.

    To update fleet attributes, specify the fleet ID and the property values that you want to change. If successful, Amazon GameLift Servers returns the identifiers for the updated fleet.

    A managed fleet's runtime environment, which depends on the fleet's Amazon Machine Image {AMI} version, can't be updated. You must create a new fleet. As a best practice, we recommend replacing your managed fleets every 30 days to maintain a secure and up-to-date runtime environment for your hosted game servers. For guidance, see Security best practices for Amazon GameLift Servers.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " + "documentation":"

    This API works with the following fleet types: EC2, Anywhere

    Updates a fleet's mutable attributes, such as game session protection and resource creation limits.

    To update fleet attributes, specify the fleet ID and the property values that you want to change. If successful, Amazon GameLift Servers returns the identifiers for the updated fleet.

    A managed fleet's runtime environment, which depends on the fleet's Amazon Machine Image {AMI} version, can't be updated. You must create a new fleet. As a best practice, we recommend replacing your managed fleets every 30 days to maintain a secure and up-to-date runtime environment for your hosted game servers. For guidance, see Security best practices for Amazon GameLift Servers.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " }, "UpdateFleetCapacity":{ "name":"UpdateFleetCapacity", @@ -1905,7 +1909,7 @@ {"shape":"InvalidRequestException"}, {"shape":"UnauthorizedException"} ], - "documentation":"

    This API works with the following fleet types: EC2, Container

    Updates permissions that allow inbound traffic to connect to game sessions in the fleet.

    To update settings, specify the fleet ID to be updated and specify the changes to be made. List the permissions you want to add in InboundPermissionAuthorizations, and permissions you want to remove in InboundPermissionRevocations. Permissions to be removed must match existing fleet permissions.

    If successful, the fleet identifiers for the updated fleet are returned. For fleets with remote locations, port setting updates can take time to propagate across all locations. You can check the status of updates in each location by calling DescribeFleetPortSettings with a location name.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " + "documentation":"

    This API works with the following fleet types: EC2

    Updates permissions that allow inbound traffic to connect to game sessions in the fleet.

    To update settings, specify the fleet ID to be updated and specify the changes to be made. List the permissions you want to add in InboundPermissionAuthorizations, and permissions you want to remove in InboundPermissionRevocations. Permissions to be removed must match existing fleet permissions.

    If successful, the fleet identifiers for the updated fleet are returned. For fleets with remote locations, port setting updates can take time to propagate across all locations. You can check the status of updates in each location by calling DescribeFleetPortSettings with a location name.

    Learn more

    Setting up Amazon GameLift Servers fleets

    " }, "UpdateGameServer":{ "name":"UpdateGameServer", @@ -2110,15 +2114,17 @@ }, "AliasArn":{ "type":"string", - "pattern":"^arn:.*:alias\\/alias-\\S+" + "pattern":"^arn:.*:alias\\/alias-\\S+$" }, "AliasId":{ "type":"string", - "pattern":"^alias-\\S+" + "pattern":"^alias-\\S+$" }, "AliasIdOrArn":{ "type":"string", - "pattern":"^alias-\\S+|^arn:.*:alias\\/alias-\\S+" + "max":512, + "min":1, + "pattern":"^(alias-\\S+|arn:.*:alias\\/alias-\\S+)$" }, "AliasList":{ "type":"list", @@ -2144,7 +2150,7 @@ "type":"string", "max":512, "min":1, - "pattern":"[a-zA-Z0-9:/-]+" + "pattern":"^[a-zA-Z0-9:/-]+$" }, "AttributeValue":{ "type":"structure", @@ -2172,7 +2178,7 @@ "type":"string", "max":256, "min":0, - "pattern":"[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]*" + "pattern":"^[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]*$" }, "AwsCredentials":{ "type":"structure", @@ -2253,15 +2259,17 @@ }, "BuildArn":{ "type":"string", - "pattern":"^arn:.*:build\\/build-\\S+" + "pattern":"^arn:.*:build\\/build-\\S+$" }, "BuildId":{ "type":"string", - "pattern":"^build-\\S+" + "pattern":"^build-\\S+$" }, "BuildIdOrArn":{ "type":"string", - "pattern":"^build-\\S+|^arn:.*:build\\/build-\\S+" + "max":512, + "min":1, + "pattern":"^(build-\\S+|arn:.*:build\\/build-\\S+)$" }, "BuildList":{ "type":"list", @@ -2416,13 +2424,13 @@ "ComputeArn":{ "type":"string", "max":1024, - "pattern":"^arn:.*:compute\\/[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?" + "pattern":"^arn:.*:compute\\/[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?$" }, "ComputeAuthToken":{ "type":"string", "max":64, "min":1, - "pattern":"^[a-zA-Z0-9\\-]+" + "pattern":"^[a-zA-Z0-9\\-]+$" }, "ComputeList":{ "type":"list", @@ -2432,12 +2440,12 @@ "type":"string", "max":128, "min":1, - "pattern":"^[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?" + "pattern":"^[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?$" }, "ComputeNameOrArn":{ "type":"string", "max":1024, - "pattern":"^[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?$|^arn:.*:compute\\/[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?" + "pattern":"^([a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?|arn:.*:compute\\/[a-zA-Z0-9\\-]+(\\/[a-zA-Z0-9\\-]+)?)$" }, "ComputeStatus":{ "type":"string", @@ -2638,7 +2646,7 @@ }, "Status":{ "shape":"ContainerFleetStatus", - "documentation":"

    The current status of the container fleet.

    • PENDING -- A new container fleet has been requested.

    • CREATING -- A new container fleet resource is being created.

    • CREATED -- A new container fleet resource has been created. No fleet instances have been deployed.

    • ACTIVATING -- New container fleet instances are being deployed.

    • ACTIVE -- The container fleet has been deployed and is ready to host game sessions.

    • UPDATING -- Updates to the container fleet is being updated. A deployment is in progress.

    " + "documentation":"

    The current status of the container fleet.

    • PENDING -- A new container fleet has been requested.

    • CREATING -- A new container fleet resource is being created.

    • CREATED -- A new container fleet resource has been created. No fleet instances have been deployed.

    • ACTIVATING -- New container fleet instances are being deployed.

    • ACTIVE -- The container fleet has been deployed and is ready to host game sessions.

    • UPDATING -- Updates to the container fleet is being updated. A deployment is in progress.

    • EXPIRED -- The container fleet has been expired. The fleet is scaled down to zero instances and cannot host new game sessions.

    " }, "DeploymentDetails":{ "shape":"DeploymentDetails", @@ -2680,7 +2688,7 @@ }, "Status":{ "shape":"ContainerFleetLocationStatus", - "documentation":"

    The status of fleet activity in the location.

    • PENDING -- A new container fleet has been requested.

    • CREATING -- A new container fleet resource is being created.

    • CREATED -- A new container fleet resource has been created. No fleet instances have been deployed.

    • ACTIVATING -- New container fleet instances are being deployed.

    • ACTIVE -- The container fleet has been deployed and is ready to host game sessions.

    • UPDATING -- Updates to the container fleet is being updated. A deployment is in progress.

    " + "documentation":"

    The status of fleet activity in the location.

    • PENDING -- A new container fleet has been requested.

    • CREATING -- A new container fleet resource is being created.

    • CREATED -- A new container fleet resource has been created. No fleet instances have been deployed.

    • ACTIVATING -- New container fleet instances are being deployed.

    • ACTIVE -- The container fleet has been deployed and is ready to host game sessions.

    • UPDATING -- Updates to the container fleet is being updated. A deployment is in progress.

    • EXPIRED -- The container fleet has been expired. The fleet is scaled down to zero instances and cannot host new game sessions.

    " }, "PlayerGatewayStatus":{ "shape":"PlayerGatewayStatus", @@ -2702,7 +2710,8 @@ "ACTIVATING", "ACTIVE", "UPDATING", - "DELETING" + "DELETING", + "EXPIRED" ] }, "ContainerFleetRemoveAttribute":{ @@ -2724,7 +2733,8 @@ "ACTIVATING", "ACTIVE", "UPDATING", - "DELETING" + "DELETING", + "EXPIRED" ] }, "ContainerGroupDefinition":{ @@ -2949,6 +2959,12 @@ "max":10, "min":1 }, + "ContainerNameQueryFilter":{ + "type":"string", + "max":128, + "min":1, + "pattern":"^[a-zA-Z0-9\\-_]+$" + }, "ContainerOperatingSystem":{ "type":"string", "enum":["AMAZON_LINUX_2023"] @@ -3863,19 +3879,20 @@ "CustomEventData":{ "type":"string", "max":256, - "min":0 + "min":0, + "sensitive":true }, "CustomInputLocationStringModel":{ "type":"string", "max":64, "min":8, - "pattern":"^custom-[A-Za-z0-9\\-]+" + "pattern":"^custom-[A-Za-z0-9\\-]+$" }, "CustomLocationNameOrArnModel":{ "type":"string", "max":128, "min":1, - "pattern":"^custom-[A-Za-z0-9\\-]+|^arn:.*:location\\/custom-\\S+" + "pattern":"^(custom-[A-Za-z0-9\\-]+|arn:.*:location\\/custom-\\S+)$" }, "DeleteAliasInput":{ "type":"structure", @@ -4353,7 +4370,7 @@ "documentation":"

    A unique identifier for the fleet instance to retrieve port mappings for.

    When ContainerGroupType is PER_INSTANCE, this parameter is required.

    When ContainerGroupType is GAME_SERVER, this parameter is optional. If you provide an instance ID, it must match the instance that's running the specified compute. If the instance ID doesn't match, the request fails with an InvalidRequestException.

    " }, "ContainerName":{ - "shape":"NonZeroAnd128MaxAsciiString", + "shape":"ContainerNameQueryFilter", "documentation":"

    A container name to filter the results. When provided, the operation returns port mappings for the specified container only. If no container with the specified name exists in the container group, the request fails with a NotFoundException.

    If not provided, the operation returns port mappings for all containers in the container group.

    " } } @@ -5224,7 +5241,7 @@ "type":"string", "max":256, "min":1, - "pattern":"^[0-9a-zA-Z_\\-\\.]+" + "pattern":"^[0-9a-zA-Z_\\-\\.]+$" }, "Double":{"type":"double"}, "DoubleObject":{"type":"double"}, @@ -5795,7 +5812,28 @@ "m7i.48xlarge", "r7a.24xlarge", "r7a.32xlarge", - "r7a.48xlarge" + "r7a.48xlarge", + "c8a.medium", + "c8a.large", + "c8a.xlarge", + "c8a.2xlarge", + "c8i.large", + "c8i.xlarge", + "c8i.2xlarge", + "c9g.medium", + "c9g.large", + "c9g.xlarge", + "c9g.2xlarge", + "m8a.medium", + "m8a.large", + "m8a.xlarge", + "m8a.2xlarge", + "m8i.large", + "m8i.xlarge", + "m8i.2xlarge", + "m9g.large", + "m9g.xlarge", + "m9g.2xlarge" ] }, "Event":{ @@ -5811,7 +5849,7 @@ }, "EventCode":{ "shape":"EventCode", - "documentation":"

    The type of event being logged.

    Fleet state transition events:

    • FLEET_CREATED -- A fleet resource was successfully created with a status of NEW. Event messaging includes the fleet ID.

    • FLEET_STATE_DOWNLOADING -- Fleet status changed from NEW to DOWNLOADING. Amazon GameLift Servers is downloading the compressed build and running install scripts.

    • FLEET_STATE_VALIDATING -- Fleet status changed from DOWNLOADING to VALIDATING. Amazon GameLift Servers has successfully installed build and is now validating the build files.

    • FLEET_STATE_BUILDING -- Fleet status changed from VALIDATING to BUILDING. Amazon GameLift Servers has successfully verified the build files and is now launching a fleet instance.

    • FLEET_STATE_ACTIVATING -- Fleet status changed from BUILDING to ACTIVATING. Amazon GameLift Servers is launching a game server process on the fleet instance and is testing its connectivity with the Amazon GameLift Servers service.

    • FLEET_STATE_ACTIVE -- The fleet's status changed from ACTIVATING to ACTIVE. The fleet is now ready to host game sessions.

    • FLEET_STATE_ERROR -- The Fleet's status changed to ERROR. Describe the fleet event message for more details.

    Fleet creation events (ordered by fleet creation activity):

    • FLEET_BINARY_DOWNLOAD_FAILED -- The build failed to download to the fleet instance.

    • FLEET_CREATION_EXTRACTING_BUILD -- The game server build was successfully downloaded to an instance, and Amazon GameLift Serversis now extracting the build files from the uploaded build. Failure at this stage prevents a fleet from moving to ACTIVE status. Logs for this stage display a list of the files that are extracted and saved on the instance. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_CREATION_RUNNING_INSTALLER -- The game server build files were successfully extracted, and Amazon GameLift Servers is now running the build's install script (if one is included). Failure in this stage prevents a fleet from moving to ACTIVE status. Logs for this stage list the installation steps and whether or not the install completed successfully. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_CREATION_COMPLETED_INSTALLER -- The game server build files were successfully installed and validation of the installation will begin soon.

    • FLEET_CREATION_FAILED_INSTALLER -- The installed failed while attempting to install the build files. This event indicates that the failure occurred before Amazon GameLift Servers could start validation.

    • FLEET_CREATION_VALIDATING_RUNTIME_CONFIG -- The build process was successful, and the GameLift is now verifying that the game server launch paths, which are specified in the fleet's runtime configuration, exist. If any listed launch path exists, Amazon GameLift Servers tries to launch a game server process and waits for the process to report ready. Failures in this stage prevent a fleet from moving to ACTIVE status. Logs for this stage list the launch paths in the runtime configuration and indicate whether each is found. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_VALIDATION_LAUNCH_PATH_NOT_FOUND -- Validation of the runtime configuration failed because the executable specified in a launch path does not exist on the instance.

    • FLEET_VALIDATION_EXECUTABLE_RUNTIME_FAILURE -- Validation of the runtime configuration failed because the executable specified in a launch path failed to run on the fleet instance.

    • FLEET_VALIDATION_TIMED_OUT -- Validation of the fleet at the end of creation timed out. Try fleet creation again.

    • FLEET_ACTIVATION_FAILED -- The fleet failed to successfully complete one of the steps in the fleet activation process. This event code indicates that the game build was successfully downloaded to a fleet instance, built, and validated, but was not able to start a server process. For more information, see Debug Fleet Creation Issues.

    • FLEET_ACTIVATION_FAILED_NO_INSTANCES -- Fleet creation was not able to obtain any instances based on the input fleet attributes. Try again at a different time or choose a different combination of fleet attributes such as fleet type, instance type, etc.

    • FLEET_INITIALIZATION_FAILED -- A generic exception occurred during fleet creation. Describe the fleet event message for more details.

    VPC peering events:

    • FLEET_VPC_PEERING_SUCCEEDED -- A VPC peering connection has been established between the VPC for an Amazon GameLift Servers fleet and a VPC in your Amazon Web Services account.

    • FLEET_VPC_PEERING_FAILED -- A requested VPC peering connection has failed. Event details and status information provide additional detail. A common reason for peering failure is that the two VPCs have overlapping CIDR blocks of IPv4 addresses. To resolve this, change the CIDR block for the VPC in your Amazon Web Services account. For more information on VPC peering failures, see https://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide/invalid-peering-configurations.html

    • FLEET_VPC_PEERING_DELETED -- A VPC peering connection has been successfully deleted.

    Spot instance events:

    • INSTANCE_INTERRUPTED -- A spot instance was interrupted by EC2 with a two-minute notification.

    • INSTANCE_RECYCLED -- A spot instance was determined to have a high risk of interruption and is scheduled to be recycled once it has no active game sessions.

    Server process events:

    • SERVER_PROCESS_INVALID_PATH -- The game server executable or script could not be found based on the Fleet runtime configuration. Check that the launch path is correct based on the operating system of the Fleet.

    • SERVER_PROCESS_SDK_INITIALIZATION_TIMEOUT -- The server process did not call InitSDK() within the time expected (5 minutes). Check your game session log to see why InitSDK() was not called in time. This event is not emitted for managed container fleets and Anywhere fleets unless they're deployed with the Amazon GameLift Servers Agent.

    • SERVER_PROCESS_PROCESS_READY_TIMEOUT -- The server process did not call ProcessReady() within the time expected (5 minutes) after calling InitSDK(). Check your game session log to see why ProcessReady() was not called in time.

    • SERVER_PROCESS_CRASHED -- The server process exited without calling ProcessEnding(). Check your game session log to see why ProcessEnding() was not called.

    • SERVER_PROCESS_TERMINATED_UNHEALTHY -- The server process did not report a valid health check for too long and was therefore terminated by GameLift. Check your game session log to see if the thread became stuck processing a synchronous task for too long.

    • SERVER_PROCESS_FORCE_TERMINATED -- The server process did not exit cleanly within the time expected after OnProcessTerminate() was sent. Check your game session log to see why termination took longer than expected.

    • SERVER_PROCESS_PROCESS_EXIT_TIMEOUT -- The server process did not exit cleanly within the time expected (30 seconds) after calling ProcessEnding(). Check your game session log to see why termination took longer than expected.

    Game session events:

    • GAME_SESSION_ACTIVATION_TIMEOUT -- GameSession failed to activate within the expected time. Check your game session log to see why ActivateGameSession() took longer to complete than expected.

    Other fleet events:

    • FLEET_SCALING_EVENT -- A change was made to the fleet's capacity settings (desired instances, minimum/maximum scaling limits). Event messaging includes the new capacity settings.

    • FLEET_NEW_GAME_SESSION_PROTECTION_POLICY_UPDATED -- A change was made to the fleet's game session protection policy setting. Event messaging includes both the old and new policy setting.

    • FLEET_DELETED -- A request to delete a fleet was initiated.

    • GENERIC_EVENT -- An unspecified event has occurred.

    " + "documentation":"

    The type of event being logged.

    Fleet state transition events:

    • FLEET_CREATED -- A fleet resource was successfully created with a status of NEW. Event messaging includes the fleet ID.

    • FLEET_STATE_DOWNLOADING -- Fleet status changed from NEW to DOWNLOADING. Amazon GameLift Servers is downloading the compressed build and running install scripts.

    • FLEET_STATE_VALIDATING -- Fleet status changed from DOWNLOADING to VALIDATING. Amazon GameLift Servers has successfully installed build and is now validating the build files.

    • FLEET_STATE_BUILDING -- Fleet status changed from VALIDATING to BUILDING. Amazon GameLift Servers has successfully verified the build files and is now launching a fleet instance.

    • FLEET_STATE_ACTIVATING -- Fleet status changed from BUILDING to ACTIVATING. Amazon GameLift Servers is launching a game server process on the fleet instance and is testing its connectivity with the Amazon GameLift Servers service.

    • FLEET_STATE_ACTIVE -- The fleet's status changed from ACTIVATING to ACTIVE. The fleet is now ready to host game sessions.

    • FLEET_STATE_ERROR -- The Fleet's status changed to ERROR. Describe the fleet event message for more details.

    Fleet creation events (ordered by fleet creation activity):

    • FLEET_BINARY_DOWNLOAD_FAILED -- The build failed to download to the fleet instance.

    • FLEET_CREATION_EXTRACTING_BUILD -- The game server build was successfully downloaded to an instance, and Amazon GameLift Serversis now extracting the build files from the uploaded build. Failure at this stage prevents a fleet from moving to ACTIVE status. Logs for this stage display a list of the files that are extracted and saved on the instance. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_CREATION_RUNNING_INSTALLER -- The game server build files were successfully extracted, and Amazon GameLift Servers is now running the build's install script (if one is included). Failure in this stage prevents a fleet from moving to ACTIVE status. Logs for this stage list the installation steps and whether or not the install completed successfully. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_CREATION_COMPLETED_INSTALLER -- The game server build files were successfully installed and validation of the installation will begin soon.

    • FLEET_CREATION_FAILED_INSTALLER -- The installed failed while attempting to install the build files. This event indicates that the failure occurred before Amazon GameLift Servers could start validation.

    • FLEET_CREATION_VALIDATING_RUNTIME_CONFIG -- The build process was successful, and the GameLift is now verifying that the game server launch paths, which are specified in the fleet's runtime configuration, exist. If any listed launch path exists, Amazon GameLift Servers tries to launch a game server process and waits for the process to report ready. Failures in this stage prevent a fleet from moving to ACTIVE status. Logs for this stage list the launch paths in the runtime configuration and indicate whether each is found. Access the logs by using the URL in PreSignedLogUrl.

    • FLEET_VALIDATION_LAUNCH_PATH_NOT_FOUND -- Validation of the runtime configuration failed because the executable specified in a launch path does not exist on the instance.

    • FLEET_VALIDATION_EXECUTABLE_RUNTIME_FAILURE -- Validation of the runtime configuration failed because the executable specified in a launch path failed to run on the fleet instance.

    • FLEET_VALIDATION_TIMED_OUT -- Validation of the fleet at the end of creation timed out. Try fleet creation again.

    • FLEET_ACTIVATION_FAILED -- The fleet failed to successfully complete one of the steps in the fleet activation process. This event code indicates that the game build was successfully downloaded to a fleet instance, built, and validated, but was not able to start a server process. For more information, see Debug Fleet Creation Issues.

    • FLEET_ACTIVATION_FAILED_NO_INSTANCES -- Fleet creation was not able to obtain any instances based on the input fleet attributes. Try again at a different time or choose a different combination of fleet attributes such as fleet type, instance type, etc.

    • FLEET_INITIALIZATION_FAILED -- A generic exception occurred during fleet creation. Describe the fleet event message for more details.

    VPC peering events:

    • FLEET_VPC_PEERING_SUCCEEDED -- A VPC peering connection has been established between the VPC for an Amazon GameLift Servers fleet and a VPC in your Amazon Web Services account.

    • FLEET_VPC_PEERING_FAILED -- A requested VPC peering connection has failed. Event details and status information provide additional detail. A common reason for peering failure is that the two VPCs have overlapping CIDR blocks of IPv4 addresses. To resolve this, change the CIDR block for the VPC in your Amazon Web Services account. For more information on VPC peering failures, see https://docs.aws.amazon.com/AmazonVPC/latest/PeeringGuide/invalid-peering-configurations.html

    • FLEET_VPC_PEERING_DELETED -- A VPC peering connection has been successfully deleted.

    Spot instance events:

    • INSTANCE_INTERRUPTED -- A spot instance was interrupted by EC2 with a two-minute notification.

    • INSTANCE_RECYCLED -- A spot instance was determined to have a high risk of interruption and is scheduled to be recycled once it has no active game sessions.

    Server process events:

    • SERVER_PROCESS_INVALID_PATH -- The game server executable or script could not be found based on the Fleet runtime configuration. Check that the launch path is correct based on the operating system of the Fleet.

    • SERVER_PROCESS_SDK_INITIALIZATION_TIMEOUT -- The server process did not call InitSDK() within the time expected (5 minutes). Check your game session log to see why InitSDK() was not called in time. This event is not emitted for managed container fleets and Anywhere fleets unless they're deployed with the Amazon GameLift Servers Agent.

    • SERVER_PROCESS_PROCESS_READY_TIMEOUT -- The server process did not call ProcessReady() within the time expected (5 minutes) after calling InitSDK(). Check your game session log to see why ProcessReady() was not called in time.

    • SERVER_PROCESS_CRASHED -- The server process exited without calling ProcessEnding(). Check your game session log to see why ProcessEnding() was not called.

    • SERVER_PROCESS_TERMINATED_UNHEALTHY -- The server process did not report a valid health check for too long and was therefore terminated by GameLift. Check your game session log to see if the thread became stuck processing a synchronous task for too long.

    • SERVER_PROCESS_FORCE_TERMINATED -- The server process did not exit cleanly within the time expected after OnProcessTerminate() was sent. Check your game session log to see why termination took longer than expected.

    • SERVER_PROCESS_PROCESS_EXIT_TIMEOUT -- The server process did not exit cleanly within the time expected (30 seconds) after calling ProcessEnding(). Check your game session log to see why termination took longer than expected.

    Game session events:

    • GAME_SESSION_ACTIVATION_TIMEOUT -- GameSession failed to activate within the expected time. Check your game session log to see why ActivateGameSession() took longer to complete than expected.

    Other fleet events:

    • FLEET_SCALING_EVENT -- A change was made to the fleet's capacity settings (desired instances, minimum/maximum scaling limits). Event messaging includes the new capacity settings.

    • FLEET_NEW_GAME_SESSION_PROTECTION_POLICY_UPDATED -- A change was made to the fleet's game session protection policy setting. Event messaging includes both the old and new policy setting.

    • FLEET_DELETED -- A request to delete a fleet was initiated.

    • FLEET_EXPIRED -- The fleet has been expired. The fleet is scaled down to zero instances and can no longer host game sessions.

    • GENERIC_EVENT -- An unspecified event has occurred.

    " }, "Message":{ "shape":"NonEmptyString", @@ -5830,7 +5868,8 @@ "documentation":"

    The number of times that this event occurred.

    " } }, - "documentation":"

    Log entry describing an event that involves Amazon GameLift Servers resources (such as a fleet). In addition to tracking activity, event codes and messages can provide additional information for troubleshooting and debugging problems.

    " + "documentation":"

    Log entry describing an event that involves Amazon GameLift Servers resources (such as a fleet). In addition to tracking activity, event codes and messages can provide additional information for troubleshooting and debugging problems.

    ", + "sensitive":true }, "EventCode":{ "type":"string", @@ -5838,6 +5877,7 @@ "GENERIC_EVENT", "FLEET_CREATED", "FLEET_DELETED", + "FLEET_EXPIRED", "FLEET_SCALING_EVENT", "FLEET_STATE_DOWNLOADING", "FLEET_STATE_VALIDATING", @@ -5976,7 +6016,7 @@ }, "Status":{ "shape":"FleetStatus", - "documentation":"

    Current status of the fleet. Possible fleet statuses include the following:

    • NEW -- A new fleet resource has been defined and Amazon GameLift Servers has started creating the fleet. Desired instances is set to 1.

    • DOWNLOADING/VALIDATING/BUILDING -- Amazon GameLift Servers is download the game server build, running install scripts, and then validating the build files. When complete, Amazon GameLift Servers launches a fleet instance.

    • ACTIVATING -- Amazon GameLift Servers is launching a game server process and testing its connectivity with the Amazon GameLift Servers service.

    • ACTIVE -- The fleet is now ready to host game sessions.

    • ERROR -- An error occurred when downloading, validating, building, or activating the fleet.

    • DELETING -- Hosts are responding to a delete fleet request.

    • TERMINATED -- The fleet no longer exists.

    " + "documentation":"

    Current status of the fleet. Possible fleet statuses include the following:

    • NEW -- A new fleet resource has been defined and Amazon GameLift Servers has started creating the fleet. Desired instances is set to 1.

    • DOWNLOADING/VALIDATING/BUILDING -- Amazon GameLift Servers is download the game server build, running install scripts, and then validating the build files. When complete, Amazon GameLift Servers launches a fleet instance.

    • ACTIVATING -- Amazon GameLift Servers is launching a game server process and testing its connectivity with the Amazon GameLift Servers service.

    • ACTIVE -- The fleet is now ready to host game sessions.

    • ERROR -- An error occurred when downloading, validating, building, or activating the fleet.

    • EXPIRED -- The fleet has been expired. The fleet is scaled down to zero instances and cannot host new game sessions.

    • DELETING -- Hosts are responding to a delete fleet request.

    • TERMINATED -- The fleet no longer exists.

    " }, "BuildId":{ "shape":"BuildId", @@ -6062,7 +6102,7 @@ "type":"string", "max":256, "min":1, - "pattern":"[a-zA-Z0-9:/-]+" + "pattern":"^[a-zA-Z0-9:/-]+$" }, "FleetCapacity":{ "type":"structure", @@ -6160,7 +6200,7 @@ "type":"string", "max":128, "min":1, - "pattern":"^[a-z]*fleet-[a-zA-Z0-9\\-]+" + "pattern":"^[a-z]*fleet-[a-zA-Z0-9\\-]+$" }, "FleetIdList":{ "type":"list", @@ -6190,7 +6230,8 @@ "DELETING", "ERROR", "TERMINATED", - "NOT_FOUND" + "NOT_FOUND", + "EXPIRED" ] }, "FleetType":{ @@ -6286,7 +6327,8 @@ }, "GamePropertyValue":{ "type":"string", - "max":96 + "max":96, + "sensitive":true }, "GameServer":{ "type":"structure", @@ -6346,7 +6388,7 @@ "type":"string", "max":512, "min":1, - "pattern":".*\\S.*" + "pattern":"^.*\\S.*$" }, "GameServerContainerDefinition":{ "type":"structure", @@ -6465,7 +6507,8 @@ "type":"string", "max":1024, "min":1, - "pattern":".*\\S.*" + "pattern":"^.*\\S.*$", + "sensitive":true }, "GameServerGroup":{ "type":"structure", @@ -6535,7 +6578,7 @@ "type":"string", "max":256, "min":1, - "pattern":"^arn:.*:gameservergroup\\/[a-zA-Z0-9-\\.]*" + "pattern":"^arn:.*:gameservergroup\\/[a-zA-Z0-9-\\.]*$" }, "GameServerGroupAutoScalingPolicy":{ "type":"structure", @@ -6657,13 +6700,13 @@ "type":"string", "max":128, "min":1, - "pattern":"[a-zA-Z0-9-\\.]+" + "pattern":"^[a-zA-Z0-9-\\.]+$" }, "GameServerGroupNameOrArn":{ "type":"string", "max":256, "min":1, - "pattern":"[a-zA-Z0-9-\\.]+|^arn:.*:gameservergroup\\/[a-zA-Z0-9-\\.]+" + "pattern":"^([a-zA-Z0-9-\\.]+|arn:.*:gameservergroup\\/[a-zA-Z0-9-\\.]+)$" }, "GameServerGroupStatus":{ "type":"string", @@ -6689,7 +6732,7 @@ "type":"string", "max":128, "min":3, - "pattern":"[a-zA-Z0-9-\\.]+" + "pattern":"^[a-zA-Z0-9-\\.]+$" }, "GameServerInstance":{ "type":"structure", @@ -6904,7 +6947,8 @@ "GameSessionData":{ "type":"string", "max":4096, - "min":1 + "min":1, + "sensitive":true }, "GameSessionDetail":{ "type":"structure", @@ -7078,7 +7122,7 @@ "type":"string", "max":256, "min":1, - "pattern":"^arn:.*:gamesessionqueue\\/[a-zA-Z0-9-]+" + "pattern":"^arn:.*:gamesessionqueue\\/[a-zA-Z0-9-]+$" }, "GameSessionQueueDestination":{ "type":"structure", @@ -7102,13 +7146,13 @@ "type":"string", "max":128, "min":1, - "pattern":"[a-zA-Z0-9-]+" + "pattern":"^[a-zA-Z0-9-]+$" }, "GameSessionQueueNameOrArn":{ "type":"string", "max":256, "min":1, - "pattern":"[a-zA-Z0-9-]+|^arn:.*:gamesessionqueue\\/[a-zA-Z0-9-]+" + "pattern":"^([a-zA-Z0-9-]+|arn:.*:gamesessionqueue\\/[a-zA-Z0-9-]+)$" }, "GameSessionQueueNameOrArnList":{ "type":"list", @@ -7245,7 +7289,8 @@ "shape":"NonZeroAndMaxString", "documentation":"

    Location of the requested game session logs, available for download. This URL is valid for 15 minutes, after which S3 will reject any download request using this URL. You can request a new URL any time within the 14-day period that the logs are retained.

    " } - } + }, + "sensitive":true }, "GetInstanceAccessInput":{ "type":"structure", @@ -7313,7 +7358,7 @@ "type":"string", "max":48, "min":1, - "pattern":"[a-zA-Z0-9-]+" + "pattern":"^[a-zA-Z0-9-]+$" }, "IdempotentParameterMismatchException":{ "type":"structure", @@ -7439,7 +7484,9 @@ }, "InstanceId":{ "type":"string", - "pattern":"[a-zA-Z0-9\\.-]+" + "max":256, + "min":1, + "pattern":"^[a-zA-Z0-9\\.-]+$" }, "InstanceList":{ "type":"list", @@ -7501,7 +7548,7 @@ "type":"string", "max":128, "min":1, - "pattern":"^[0-9A-Fa-f\\:\\.]+", + "pattern":"^[0-9A-Fa-f\\:\\.]+$", "sensitive":true }, "IpPermission":{ @@ -7546,13 +7593,14 @@ }, "IpRange":{ "type":"string", - "pattern":"[^\\s]+", + "pattern":"^[^\\s]+$", "sensitive":true }, "LargeGameSessionData":{ "type":"string", "max":262144, - "min":1 + "min":1, + "sensitive":true }, "LatencyMap":{ "type":"map", @@ -7563,25 +7611,25 @@ "type":"string", "max":1024, "min":1, - "pattern":"[A-Za-z0-9_:.+\\/\\\\\\- =@;{},?'\\[\\]\"]+" + "pattern":"^[A-Za-z0-9_:.+\\/\\\\\\- =@;{},?'\\[\\]\"]+$" }, "LaunchPathStringModel":{ "type":"string", "max":1024, "min":1, - "pattern":"[A-Za-z0-9_:.+\\/\\\\\\- ]+" + "pattern":"^[A-Za-z0-9_:.+\\/\\\\\\- ]+$" }, "LaunchTemplateId":{ "type":"string", "max":255, "min":1, - "pattern":"[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]+" + "pattern":"^[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]+$" }, "LaunchTemplateName":{ "type":"string", "max":128, "min":3, - "pattern":"[a-zA-Z0-9\\(\\)\\.\\-/_]+" + "pattern":"^[a-zA-Z0-9\\(\\)\\.\\-/_]+$" }, "LaunchTemplateSpecification":{ "type":"structure", @@ -7605,7 +7653,7 @@ "type":"string", "max":128, "min":1, - "pattern":"[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]+" + "pattern":"^[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\r\\n\\t]+$" }, "LimitExceededException":{ "type":"structure", @@ -8097,7 +8145,7 @@ "type":"string", "max":128, "min":1, - "pattern":"^arn:.*:location\\/custom-\\S+" + "pattern":"^arn:.*:location\\/custom-\\S+$" }, "LocationAttributes":{ "type":"structure", @@ -8211,7 +8259,7 @@ "type":"string", "max":64, "min":1, - "pattern":"^[A-Za-z0-9\\-]+" + "pattern":"^[A-Za-z0-9\\-]+$" }, "LocationUpdateStatus":{ "type":"string", @@ -8262,7 +8310,7 @@ "type":"string", "max":512, "min":1, - "pattern":"[a-zA-Z0-9:/\\-\\*]+" + "pattern":"^[a-zA-Z0-9:/\\-\\*]+$" }, "ManagedCapacityConfiguration":{ "type":"structure", @@ -8299,7 +8347,8 @@ "MatchmakerData":{ "type":"string", "max":390000, - "min":1 + "min":1, + "sensitive":true }, "MatchmakingAcceptanceTimeoutInteger":{ "type":"integer", @@ -8383,7 +8432,7 @@ "MatchmakingConfigurationArn":{ "type":"string", "documentation":"Data type used for Matchmaking Configuration ARN.", - "pattern":"^arn:.*:matchmakingconfiguration\\/[a-zA-Z0-9-\\.]*" + "pattern":"^arn:.*:matchmakingconfiguration\\/[a-zA-Z0-9-\\.]*$" }, "MatchmakingConfigurationList":{ "type":"list", @@ -8393,7 +8442,7 @@ "type":"string", "max":256, "min":1, - "pattern":"[a-zA-Z0-9-\\.]*|^arn:.*:matchmakingconfiguration\\/[a-zA-Z0-9-\\.]*" + "pattern":"^([a-zA-Z0-9-\\.]*|arn:.*:matchmakingconfiguration\\/[a-zA-Z0-9-\\.]*)$" }, "MatchmakingConfigurationNameList":{ "type":"list", @@ -8419,7 +8468,7 @@ "MatchmakingIdStringModel":{ "type":"string", "max":128, - "pattern":"[a-zA-Z0-9-\\.]*" + "pattern":"^[a-zA-Z0-9-\\.]*$" }, "MatchmakingRequestTimeoutInteger":{ "type":"integer", @@ -8452,7 +8501,7 @@ "MatchmakingRuleSetArn":{ "type":"string", "documentation":"Data type used for Matchmaking RuleSet ARN.", - "pattern":"^arn:.*:matchmakingruleset\\/[a-zA-Z0-9-\\.]*" + "pattern":"^arn:.*:matchmakingruleset\\/[a-zA-Z0-9-\\.]*$" }, "MatchmakingRuleSetList":{ "type":"list", @@ -8462,7 +8511,7 @@ "type":"string", "max":256, "min":1, - "pattern":"[a-zA-Z0-9-\\.]*|^arn:.*:matchmakingruleset\\/[a-zA-Z0-9-\\.]*" + "pattern":"^([a-zA-Z0-9-\\.]*|arn:.*:matchmakingruleset\\/[a-zA-Z0-9-\\.]*)$" }, "MatchmakingRuleSetNameList":{ "type":"list", @@ -8580,7 +8629,7 @@ "type":"string", "max":1024, "min":1, - "pattern":".*\\S.*" + "pattern":"^.*\\S.*$" }, "NonEmptyString":{ "type":"string", @@ -8771,7 +8820,8 @@ "PlayerData":{ "type":"string", "max":2048, - "min":1 + "min":1, + "sensitive":true }, "PlayerDataMap":{ "type":"map", @@ -8928,7 +8978,9 @@ }, "PlayerSessionId":{ "type":"string", - "pattern":"^psess-\\S+" + "max":128, + "min":1, + "pattern":"^psess-\\S+$" }, "PlayerSessionList":{ "type":"list", @@ -9078,13 +9130,14 @@ "type":"string", "max":256, "min":0, - "pattern":"[\\s\\S]*" + "pattern":"^[\\s\\S]*$", + "sensitive":true }, "QueueSnsArnStringModel":{ "type":"string", "max":300, "min":0, - "pattern":"[a-zA-Z0-9:_-]*(\\.fifo)?" + "pattern":"^[a-zA-Z0-9:_-]*(\\.fifo)?$" }, "RegisterComputeInput":{ "type":"structure", @@ -9459,15 +9512,17 @@ }, "ScriptArn":{ "type":"string", - "pattern":"^arn:.*:script\\/script-\\S+" + "pattern":"^arn:.*:script\\/script-\\S+$" }, "ScriptId":{ "type":"string", - "pattern":"^script-\\S+" + "pattern":"^script-\\S+$" }, "ScriptIdOrArn":{ "type":"string", - "pattern":"^script-\\S+|^arn:.*:script\\/script-\\S+" + "max":512, + "min":1, + "pattern":"^(script-\\S+|arn:.*:script\\/script-\\S+)$" }, "ScriptList":{ "type":"list", @@ -9566,7 +9621,7 @@ "type":"string", "max":300, "min":0, - "pattern":"[a-zA-Z0-9:_/-]*(.fifo)?" + "pattern":"^[a-zA-Z0-9:_/-]*(\\.fifo)?$" }, "SortOrder":{ "type":"string", diff --git a/services/gameliftstreams/pom.xml b/services/gameliftstreams/pom.xml index 68070b5865ec..9c6e6134c196 100644 --- a/services/gameliftstreams/pom.xml +++ b/services/gameliftstreams/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT gameliftstreams AWS Java SDK :: Services :: Game Lift Streams diff --git a/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..270ef20dfb9c --- /dev/null +++ b/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gameliftstreams-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://gameliftstreams.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index df2994a2b033..000000000000 --- a/services/gameliftstreams/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://gameliftstreams-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://gameliftstreams.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/gameliftstreams/src/main/resources/codegen-resources/paginators-1.json b/services/gameliftstreams/src/main/resources/codegen-resources/paginators-1.json index a396ef461b74..50ae824770c2 100644 --- a/services/gameliftstreams/src/main/resources/codegen-resources/paginators-1.json +++ b/services/gameliftstreams/src/main/resources/codegen-resources/paginators-1.json @@ -23,6 +23,12 @@ "output_token": "NextToken", "limit_key": "MaxResults", "result_key": "Items" + }, + "ListStreamUrls": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Items" } } } diff --git a/services/gameliftstreams/src/main/resources/codegen-resources/service-2.json b/services/gameliftstreams/src/main/resources/codegen-resources/service-2.json index 05b71737313a..196cf64ad74b 100644 --- a/services/gameliftstreams/src/main/resources/codegen-resources/service-2.json +++ b/services/gameliftstreams/src/main/resources/codegen-resources/service-2.json @@ -130,6 +130,27 @@ ], "documentation":"

    Enables clients to reconnect to a stream session while preserving all session state and data in the disconnected session. This reconnection process can be initiated when a stream session is in either PENDING_CLIENT_RECONNECTION or ACTIVE status. The process works as follows:

    1. Initial disconnect:

      • When a client disconnects or loses connection, the stream session transitions from CONNECTED to PENDING_CLIENT_RECONNECTION

    2. Reconnection time window:

      • Clients have ConnectionTimeoutSeconds (defined in StartStreamSession) to reconnect before session termination

      • Your backend server must call CreateStreamSessionConnection to initiate reconnection

      • Session transitions to RECONNECTING status

    3. Reconnection completion:

      • On successful CreateStreamSessionConnection, session status changes to ACTIVE

      • Provide the new connection information to the requesting client

      • Client must establish connection within ConnectionTimeoutSeconds

      • Session terminates automatically if client fails to connect in time

    For more information about the stream session lifecycle, see Stream sessions in the Amazon GameLift Streams Developer Guide.

    To begin re-connecting to an existing stream session, specify the stream group ID and stream session ID that you want to reconnect to, and the signal request to use with the stream.

    " }, + "CreateStreamUrl":{ + "name":"CreateStreamUrl", + "http":{ + "method":"POST", + "requestUri":"/streamgroups/{Identifier}/streamurls", + "responseCode":201 + }, + "input":{"shape":"CreateStreamUrlInput"}, + "output":{"shape":"CreateStreamUrlOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"} + ], + "documentation":"

    Creates a stream URL that grants temporary access to a stream session in a web browser without requiring an Amazon Web Services account or client integration.

    You can use the stream URL to start a stream session up to the number of times set by UsageLimit, until it expires after UrlExpiresAfterMinutes. Each successful use starts a new stream session.

    To make the request idempotent, provide a ClientToken.

    ", + "idempotent":true + }, "DeleteApplication":{ "name":"DeleteApplication", "http":{ @@ -263,6 +284,44 @@ "documentation":"

    Retrieves properties for a Amazon GameLift Streams stream session resource. Specify the Amazon Resource Name (ARN) of the stream session that you want to retrieve and its stream group ARN. If the operation is successful, it returns properties for the requested resource.

    ", "readonly":true }, + "GetStreamUrl":{ + "name":"GetStreamUrl", + "http":{ + "method":"GET", + "requestUri":"/streamgroups/{Identifier}/streamurls/{StreamUrlIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetStreamUrlInput"}, + "output":{"shape":"GetStreamUrlOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Retrieves properties for a stream URL, including its current status, usage, and the stream sessions started through it.

    If you delete the stream group or application that backs the stream URL, this operation updates the status of the stream URL to REVOKED.

    ", + "readonly":true + }, + "ListApplicationShaderCaches":{ + "name":"ListApplicationShaderCaches", + "http":{ + "method":"GET", + "requestUri":"/applications/{Identifier}/shadercaches", + "responseCode":200 + }, + "input":{"shape":"ListApplicationShaderCachesInput"}, + "output":{"shape":"ListApplicationShaderCachesOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Lists the shader caches associated with an Amazon GameLift Streams application. Each shader cache entry includes its status, associated stream groups, and size in bytes.

    Returns shader caches associated with the specified Amazon GameLift Streams application in all statuses.

    ", + "readonly":true + }, "ListApplications":{ "name":"ListApplications", "http":{ @@ -336,6 +395,24 @@ "documentation":"

    Retrieves a list of Amazon GameLift Streams stream sessions that this user account has access to.

    In the returned list of stream sessions, the ExportFilesMetadata property only shows the Status value. To get the OutpurUri and StatusReason values, use GetStreamSession.

    We don't recommend using this operation to regularly check stream session statuses because it's costly. Instead, to check status updates for a specific stream session, use GetStreamSession.

    ", "readonly":true }, + "ListStreamUrls":{ + "name":"ListStreamUrls", + "http":{ + "method":"GET", + "requestUri":"/streamurls", + "responseCode":200 + }, + "input":{"shape":"ListStreamUrlsInput"}, + "output":{"shape":"ListStreamUrlsOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Retrieves a list of the stream URLs in the current Amazon Web Services Region for your Amazon Web Services account. You can filter the results by status or by stream group. Use the pagination parameters to retrieve results as a set of sequential pages. If you delete the stream group or application that backs a stream URL, this operation updates that stream URL's status to REVOKED.

    ", + "readonly":true + }, "ListTagsForResource":{ "name":"ListTagsForResource", "http":{ @@ -372,6 +449,24 @@ "documentation":"

    Removes a set of remote locations from this stream group. To remove a location, the stream group must be in ACTIVE status. When you remove a location, Amazon GameLift Streams releases allocated compute resources in that location. Stream sessions can no longer start from removed locations in a stream group. Amazon GameLift Streams also deletes the content files of all associated applications that were in Amazon GameLift Streams's internal Amazon S3 bucket at this location.

    You cannot remove the Amazon Web Services Region location where you initially created this stream group, known as the primary location. However, you can set the stream capacity to zero to avoid incurring costs for allocated compute resources in that location.

    ", "idempotent":true }, + "RevokeStreamUrl":{ + "name":"RevokeStreamUrl", + "http":{ + "method":"POST", + "requestUri":"/streamgroups/{Identifier}/streamurls/{StreamUrlIdentifier}/revoke", + "responseCode":204 + }, + "input":{"shape":"RevokeStreamUrlInput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Revokes a stream URL so that it can no longer start new stream sessions. By default, stream sessions that are already running continue until they end on their own. To also end running sessions, set RevocationMode to REVOKE_AND_TERMINATE_SESSIONS.

    Revoking a stream URL is permanent. The status of the stream URL changes to REVOKED.

    ", + "idempotent":true + }, "StartStreamSession":{ "name":"StartStreamSession", "http":{ @@ -961,6 +1056,155 @@ } } }, + "CreateStreamUrlInput":{ + "type":"structure", + "required":[ + "Identifier", + "ApplicationIdentifier", + "Protocol", + "UrlExpiresAfterMinutes", + "Locations" + ], + "members":{ + "Identifier":{ + "shape":"Identifier", + "documentation":"

    An Amazon Resource Name (ARN) or ID that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4. Example ID: sg-1AB2C3De4.

    The stream session runs in this stream group.

    ", + "location":"uri", + "locationName":"Identifier" + }, + "ApplicationIdentifier":{ + "shape":"Identifier", + "documentation":"

    An Amazon Resource Name (ARN) or ID that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6. Example ID: a-9ZY8X7Wv6.

    This application must be associated with the stream group.

    " + }, + "Protocol":{ + "shape":"Protocol", + "documentation":"

    The data transport protocol for the stream session. Amazon GameLift Streams supports WebRTC.

    " + }, + "UrlExpiresAfterMinutes":{ + "shape":"UrlExpiresAfterMinutes", + "documentation":"

    The number of minutes after creation that the stream URL remains valid. After this period, the status of the stream URL changes to EXPIRED and it can no longer start stream sessions. The minimum is 1 minute. For the maximum, see Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "UsageLimit":{ + "shape":"UsageLimit", + "documentation":"

    The maximum number of times the stream URL can start a stream session. Each successful use reduces the remaining uses by one. The minimum is 1, and the default is 1. For the maximum, see Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "Description":{ + "shape":"Description", + "documentation":"

    A descriptive label for the stream URL.

    " + }, + "Locations":{ + "shape":"LocationList", + "documentation":"

    A list of locations, in order of preference, where Amazon GameLift Streams can place the stream session. Specify each location by its Amazon Web Services Region code, for example us-east-1. For a complete list of locations that Amazon GameLift Streams supports, refer to Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "SessionLengthSeconds":{ + "shape":"SessionLengthSeconds", + "documentation":"

    The maximum length of time, in seconds, that a stream session started from this stream URL can run. Valid values are 1-86400 seconds (1 second to 24 hours). The default is 43200 seconds (12 hours).

    " + }, + "AdditionalLaunchArgs":{ + "shape":"GameLaunchArgList", + "documentation":"

    A list of CLI arguments that are sent to the streaming server when a stream session launches. You can use this to configure the application or stream session details. You can also provide custom arguments that Amazon GameLift Streams passes to your game client.

    AdditionalEnvironmentVariables and AdditionalLaunchArgs have similar purposes. AdditionalEnvironmentVariables passes data using environment variables; while AdditionalLaunchArgs passes data using command-line arguments.

    " + }, + "AdditionalEnvironmentVariables":{ + "shape":"EnvironmentVariables", + "documentation":"

    A set of options that you can use to control the stream session runtime environment, expressed as a set of key-value pairs. You can use this to configure the application or stream session details. You can also provide custom environment variables that Amazon GameLift Streams passes to your game client.

    If you want to debug your application with environment variables, we recommend that you do so in a local environment outside of Amazon GameLift Streams. For more information, refer to the Compatibility Guidance in the troubleshooting section of the Developer Guide.

    AdditionalEnvironmentVariables and AdditionalLaunchArgs have similar purposes. AdditionalEnvironmentVariables passes data using environment variables; while AdditionalLaunchArgs passes data using command-line arguments.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon GameLift Streams assumes during stream sessions started from this stream URL. For more information, see Provide AWS credentials to your streaming application in the Amazon GameLift Streams Developer Guide.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The display settings, such as resolution, for stream sessions started from this stream URL.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure this request is idempotent. If you retry a request with the same ClientToken, Amazon GameLift Streams returns the original response without performing the operation again.

    ", + "idempotencyToken":true + } + } + }, + "CreateStreamUrlOutput":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the stream URL across all Amazon Web Services Regions. Format is arn:aws:gameliftstreams:[AWS Region]:[AWS account]:streamurl/[stream group resource ID]/[stream URL resource ID].

    " + }, + "StreamUrlId":{ + "shape":"Id", + "documentation":"

    The unique identifier for the stream URL resource, for example su-1AB2C3De4.

    " + }, + "StreamUrl":{ + "shape":"StreamSessionStreamUrl", + "documentation":"

    The shareable stream URL. Distribute this URL to end users so that they can start and play a stream session in a hosted web player. Treat the stream URL as a secret. Anyone who has it can start a stream session until the stream URL expires, is revoked, or reaches its usage limit.

    " + }, + "Status":{ + "shape":"StreamUrlStatus", + "documentation":"

    The current status of the stream URL. Possible statuses include the following:

    • ACTIVE: The stream URL is valid and can start stream sessions.

    • EXPIRED: The stream URL has passed its expiration time and can no longer start stream sessions.

    • REVOKED: The stream URL was revoked and can no longer start stream sessions.

    • LIMIT_REACHED: The stream URL has been used the maximum number of times and can no longer start stream sessions.

    " + }, + "StatusReason":{ + "shape":"StreamUrlStatusReason", + "documentation":"

    Additional information about why the stream URL is in its current status. Amazon GameLift Streams populates this value when the status is REVOKED. Possible values include the following:

    • userRevoked: You revoked the stream URL.

    • revokedAndTerminatingSessions: You revoked the stream URL and Amazon GameLift Streams is ending its running stream sessions.

    • revokedAndSessionsTerminated: You revoked the stream URL and its running stream sessions have ended.

    • streamGroupDeleted: The stream group was deleted, which revoked the stream URL.

    • applicationDeleted: The application was deleted, which revoked the stream URL.

    " + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the stream URL expires and stops accepting new stream sessions. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    A timestamp that indicates when this resource was created. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "UsageLimit":{ + "shape":"UsageLimit", + "documentation":"

    The maximum number of times the stream URL can start a stream session.

    " + }, + "RemainingUses":{ + "shape":"RemainingUses", + "documentation":"

    The number of times the stream URL can still be used to start a stream session.

    " + }, + "StreamGroupArn":{ + "shape":"Arn", + "documentation":"

    The stream group that runs the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4.

    " + }, + "ApplicationArn":{ + "shape":"Arn", + "documentation":"

    The application that runs in the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6.

    " + }, + "Protocol":{ + "shape":"Protocol", + "documentation":"

    The data transport protocol used for stream sessions started from this stream URL.

    " + }, + "Locations":{ + "shape":"LocationList", + "documentation":"

    The list of locations, in order of preference, where Amazon GameLift Streams places the stream session. For a complete list of locations that Amazon GameLift Streams supports, refer to Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "SessionLengthSeconds":{ + "shape":"SessionLengthSeconds", + "documentation":"

    The maximum length of time, in seconds, that a stream session started from this stream URL can run.

    " + }, + "Description":{ + "shape":"Description", + "documentation":"

    The descriptive label for the stream URL.

    " + }, + "AdditionalLaunchArgs":{ + "shape":"GameLaunchArgList", + "documentation":"

    The command-line arguments passed to the application when a stream session starts.

    " + }, + "AdditionalEnvironmentVariables":{ + "shape":"EnvironmentVariables", + "documentation":"

    The environment variables made available to the application when a stream session starts.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon GameLift Streams assumes during stream sessions started from this stream URL. For more information, see Provide AWS credentials to your streaming application in the Amazon GameLift Streams Developer Guide.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The display settings, such as resolution, for stream sessions started from this stream URL.

    " + } + } + }, "DefaultApplication":{ "type":"structure", "members":{ @@ -1037,6 +1281,16 @@ } } }, + "DisplayConfiguration":{ + "type":"structure", + "members":{ + "Resolution":{ + "shape":"Resolution", + "documentation":"

    The resolution to apply to the stream session's virtual monitor. When specified, this value overrides the default resolution of 1920 × 1080.

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

    The virtual monitor settings for a stream session, including the resolution. If not specified, the stream session uses the default resolution of 1920 × 1080.

    " + }, "EnvironmentVariables":{ "type":"map", "key":{"shape":"EnvironmentVariablesKeyString"}, @@ -1052,7 +1306,7 @@ }, "EnvironmentVariablesValueString":{ "type":"string", - "max":1024, + "max":4096, "min":0 }, "ExecutablePath":{ @@ -1386,9 +1640,131 @@ "ExportFilesMetadata":{ "shape":"ExportFilesMetadata", "documentation":"

    Provides details about the stream session's exported files.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of the AWS Identity and Access Management (IAM) role that Amazon GameLift Streams assumes on behalf of your application during the stream session.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The configuration for the stream session's virtual monitor.

    " + } + } + }, + "GetStreamUrlInput":{ + "type":"structure", + "required":[ + "Identifier", + "StreamUrlIdentifier" + ], + "members":{ + "Identifier":{ + "shape":"Identifier", + "documentation":"

    An Amazon Resource Name (ARN) or ID that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4. Example ID: sg-1AB2C3De4.

    This is the stream group that owns the stream URL.

    ", + "location":"uri", + "locationName":"Identifier" + }, + "StreamUrlIdentifier":{ + "shape":"Identifier", + "documentation":"

    The unique identifier of the stream URL. Specify a stream URL ID or Amazon Resource Name (ARN). Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamurl/sg-1AB2C3De4/su-1AB2C3De4. Example ID: su-1AB2C3De4.

    ", + "location":"uri", + "locationName":"StreamUrlIdentifier" + } + } + }, + "GetStreamUrlOutput":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the stream URL across all Amazon Web Services Regions. Format is arn:aws:gameliftstreams:[AWS Region]:[AWS account]:streamurl/[stream group resource ID]/[stream URL resource ID].

    " + }, + "StreamUrlId":{ + "shape":"Id", + "documentation":"

    The unique identifier for the stream URL resource, for example su-1AB2C3De4.

    " + }, + "StreamUrl":{ + "shape":"StreamSessionStreamUrl", + "documentation":"

    The shareable stream URL. Distribute this URL to end users so that they can start and play a stream session in a hosted web player. Treat the stream URL as a secret. Anyone who has it can start a stream session until the stream URL expires, is revoked, or reaches its usage limit.

    " + }, + "Status":{ + "shape":"StreamUrlStatus", + "documentation":"

    The current status of the stream URL. Possible statuses include the following:

    • ACTIVE: The stream URL is valid and can start stream sessions.

    • EXPIRED: The stream URL has passed its expiration time and can no longer start stream sessions.

    • REVOKED: The stream URL was revoked and can no longer start stream sessions.

    • LIMIT_REACHED: The stream URL has been used the maximum number of times and can no longer start stream sessions.

    " + }, + "StatusReason":{ + "shape":"StreamUrlStatusReason", + "documentation":"

    Additional information about why the stream URL is in its current status. Amazon GameLift Streams populates this value when the status is REVOKED. Possible values include the following:

    • userRevoked: You revoked the stream URL.

    • revokedAndTerminatingSessions: You revoked the stream URL and Amazon GameLift Streams is ending its running stream sessions.

    • revokedAndSessionsTerminated: You revoked the stream URL and its running stream sessions have ended.

    • streamGroupDeleted: The stream group was deleted, which revoked the stream URL.

    • applicationDeleted: The application was deleted, which revoked the stream URL.

    " + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the stream URL expires and stops accepting new stream sessions. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    A timestamp that indicates when this resource was created. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "UsageLimit":{ + "shape":"UsageLimit", + "documentation":"

    The maximum number of times the stream URL can start a stream session.

    " + }, + "RemainingUses":{ + "shape":"RemainingUses", + "documentation":"

    The number of times the stream URL can still be used to start a stream session.

    " + }, + "StreamGroupArn":{ + "shape":"Arn", + "documentation":"

    The stream group that runs the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4.

    " + }, + "ApplicationArn":{ + "shape":"Arn", + "documentation":"

    The application that runs in the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6.

    " + }, + "Protocol":{ + "shape":"Protocol", + "documentation":"

    The data transport protocol used for stream sessions started from this stream URL.

    " + }, + "Locations":{ + "shape":"LocationList", + "documentation":"

    The list of locations, in order of preference, where Amazon GameLift Streams places the stream session. For a complete list of locations that Amazon GameLift Streams supports, refer to Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "SessionLengthSeconds":{ + "shape":"SessionLengthSeconds", + "documentation":"

    The maximum length of time, in seconds, that a stream session started from this stream URL can run.

    " + }, + "Description":{ + "shape":"Description", + "documentation":"

    The descriptive label for the stream URL.

    " + }, + "AdditionalLaunchArgs":{ + "shape":"GameLaunchArgList", + "documentation":"

    The command-line arguments passed to the application when a stream session starts.

    " + }, + "AdditionalEnvironmentVariables":{ + "shape":"EnvironmentVariables", + "documentation":"

    The environment variables made available to the application when a stream session starts.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon GameLift Streams assumes during stream sessions started from this stream URL. For more information, see Provide AWS credentials to your streaming application in the Amazon GameLift Streams Developer Guide.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The display settings, such as resolution, for stream sessions started from this stream URL.

    " + }, + "StreamSessions":{ + "shape":"StreamSessionSummaryList", + "documentation":"

    A list of the stream sessions that have been started through this stream URL.

    " } } }, + "IamRoleArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws[a-zA-Z-]*:iam::\\d{12}:role/.+", + "sensitive":true + }, "Id":{ "type":"string", "max":32, @@ -1432,6 +1808,27 @@ "max":5, "min":1 }, + "ListApplicationShaderCachesInput":{ + "type":"structure", + "required":["Identifier"], + "members":{ + "Identifier":{ + "shape":"Identifier", + "documentation":"

    An Amazon Resource Name (ARN) or ID that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6. Example ID: a-9ZY8X7Wv6.

    ", + "location":"uri", + "locationName":"Identifier" + } + } + }, + "ListApplicationShaderCachesOutput":{ + "type":"structure", + "members":{ + "Items":{ + "shape":"ShaderCacheSummaryList", + "documentation":"

    A collection of shader cache metadata for the specified Amazon GameLift Streams application. Each item includes the shader cache status, associated stream groups, and storage size.

    " + } + } + }, "ListApplicationsInput":{ "type":"structure", "members":{ @@ -1583,6 +1980,48 @@ } } }, + "ListStreamUrlsInput":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"StreamUrlStatus", + "documentation":"

    Filters the list to stream URLs with the specified status.

    • ACTIVE: The stream URL is valid and can start stream sessions.

    • EXPIRED: The stream URL has passed its expiration time and can no longer start stream sessions.

    • REVOKED: The stream URL was revoked and can no longer start stream sessions.

    • LIMIT_REACHED: The stream URL has been used the maximum number of times and can no longer start stream sessions.

    ", + "location":"querystring", + "locationName":"Status" + }, + "StreamGroupIdentifier":{ + "shape":"Identifier", + "documentation":"

    Filters the list to stream URLs that belong to the specified stream group.

    This value is an Amazon Resource Name (ARN) or ID that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4. Example ID: sg-1AB2C3De4.

    ", + "location":"querystring", + "locationName":"StreamGroupIdentifier" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token that marks the start of the next set of results. Use this token when you retrieve results as sequential pages. To get the first page of results, omit a token value. To get the remaining pages, provide the token returned with the previous result set.

    ", + "location":"querystring", + "locationName":"NextToken" + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return per page. Valid values are 1-100. The default is 25.

    ", + "location":"querystring", + "locationName":"MaxResults" + } + } + }, + "ListStreamUrlsOutput":{ + "type":"structure", + "members":{ + "Items":{ + "shape":"StreamUrlSummaryList", + "documentation":"

    A collection of stream URL summaries. Each summary includes the identity, status, and usage of the stream URL, but not its full configuration.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    A token that marks the start of the next sequential page of results. If an operation doesn't return a token, you've reached the end of the list.

    " + } + } + }, "ListTagsForResourceRequest":{ "type":"structure", "required":["ResourceArn"], @@ -1715,6 +2154,10 @@ "max":100, "min":1 }, + "Long":{ + "type":"long", + "box":true + }, "MaxResults":{ "type":"integer", "box":true, @@ -1752,6 +2195,11 @@ "type":"string", "enum":["WebRTC"] }, + "RemainingUses":{ + "type":"integer", + "box":true, + "min":0 + }, "RemoveStreamGroupLocationsInput":{ "type":"structure", "required":[ @@ -1798,6 +2246,36 @@ "type":"list", "member":{"shape":"ReplicationStatus"} }, + "Resolution":{ + "type":"structure", + "required":[ + "Width", + "Height" + ], + "members":{ + "Width":{ + "shape":"ResolutionWidth", + "documentation":"

    The width of the stream session's virtual monitor, in pixels. The value must be an even number.

    " + }, + "Height":{ + "shape":"ResolutionHeight", + "documentation":"

    The height of the stream session's virtual monitor, in pixels. The value must be an even number.

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

    Contains the width and height dimensions, in pixels, that define the resolution of the stream session's virtual monitor. The total number of pixels (width × height) must not exceed 2,073,600 (equivalent to 1920 × 1080).

    " + }, + "ResolutionHeight":{ + "type":"integer", + "box":true, + "max":4096, + "min":320 + }, + "ResolutionWidth":{ + "type":"integer", + "box":true, + "max":4096, + "min":320 + }, "ResourceNotFoundException":{ "type":"structure", "required":["Message"], @@ -1814,6 +2292,38 @@ }, "exception":true }, + "RevocationMode":{ + "type":"string", + "enum":[ + "REVOKE_URL", + "REVOKE_AND_TERMINATE_SESSIONS" + ] + }, + "RevokeStreamUrlInput":{ + "type":"structure", + "required":[ + "Identifier", + "StreamUrlIdentifier" + ], + "members":{ + "Identifier":{ + "shape":"Identifier", + "documentation":"

    An Amazon Resource Name (ARN) or ID that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4. Example ID: sg-1AB2C3De4.

    This is the stream group that owns the stream URL.

    ", + "location":"uri", + "locationName":"Identifier" + }, + "StreamUrlIdentifier":{ + "shape":"Identifier", + "documentation":"

    The unique identifier of the stream URL to revoke. Specify a stream URL ID or Amazon Resource Name (ARN). Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamurl/sg-1AB2C3De4/su-1AB2C3De4. Example ID: su-1AB2C3De4.

    ", + "location":"uri", + "locationName":"StreamUrlIdentifier" + }, + "RevocationMode":{ + "shape":"RevocationMode", + "documentation":"

    Controls what happens to running stream sessions when you revoke the stream URL. If you do not specify a value, the default is REVOKE_URL. Possible values include the following:

    • REVOKE_URL: Stops the stream URL from starting new stream sessions. Running sessions continue until they end.

    • REVOKE_AND_TERMINATE_SESSIONS: Stops new stream sessions and ends any running stream sessions.

    " + } + } + }, "RuntimeEnvironment":{ "type":"structure", "required":[ @@ -1872,6 +2382,56 @@ "max":86400, "min":1 }, + "ShaderCacheStatus":{ + "type":"string", + "enum":[ + "INITIALIZED", + "PROCESSING", + "READY", + "DELETING", + "ERROR" + ] + }, + "ShaderCacheSummary":{ + "type":"structure", + "required":[ + "Identifier", + "ApplicationArn" + ], + "members":{ + "Identifier":{ + "shape":"Identifier", + "documentation":"

    A unique identifier for the shader cache, formatted as a 32-character hexadecimal string. Format is 1271e693c50b940e228582f1ccdd4e27.

    " + }, + "ApplicationArn":{ + "shape":"Arn", + "documentation":"

    An Amazon Resource Name (ARN) that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6.

    " + }, + "Status":{ + "shape":"ShaderCacheStatus", + "documentation":"

    The current status of the shader cache. Possible statuses include the following:

    • INITIALIZED: Amazon GameLift Streams received the request and is preparing the shader cache.

    • PROCESSING: Amazon GameLift Streams is replicating the shader cache to the streaming locations in the associated stream groups.

    • READY: The shader cache is replicated and available for use in stream sessions.

    • DELETING: Amazon GameLift Streams is deleting the shader cache.

    • ERROR: An error occurred during shader cache processing. Create a new shader cache to try again.

    " + }, + "LastUpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    A timestamp that indicates when this resource was last updated. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "StorageBytes":{ + "shape":"Long", + "documentation":"

    The total storage used by all compiled shader files in this shader cache, in bytes.

    " + }, + "AssociatedStreamGroups":{ + "shape":"ArnList", + "documentation":"

    The stream groups compatible with this shader cache. Compatibility is based on GPU type and GPU driver version. For more information on shader cache compatibility, see Shader caches in the Amazon GameLift Streams Developer Guide.

    This value is a set of Amazon Resource Names (ARNs) that uniquely identify stream group resources. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4.

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

    Describes a shader cache associated with an Amazon GameLift Streams application.

    " + }, + "ShaderCacheSummaryList":{ + "type":"list", + "member":{"shape":"ShaderCacheSummary"}, + "max":1000, + "min":0 + }, "SignalRequest":{ "type":"string", "min":1, @@ -1944,6 +2504,14 @@ "PerformanceStatsConfiguration":{ "shape":"PerformanceStatsConfiguration", "documentation":"

    Configuration settings for sharing the stream session's performance stats with the client

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of an AWS Identity and Access Management (IAM) role that Amazon GameLift Streams assumes on your behalf during the stream session. The role grants Amazon GameLift Streams permission to obtain temporary credentials for your application. The role's trust policy must allow the gameliftstreams.amazonaws.com service principal to assume it. The role name must start with GameLiftStreams-.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The configuration for the stream session's virtual monitor, including the resolution settings.

    If not specified, Amazon GameLift Streams uses the default resolution of 1920 × 1080.

    " } } }, @@ -2033,6 +2601,14 @@ "ExportFilesMetadata":{ "shape":"ExportFilesMetadata", "documentation":"

    Provides details about the stream session's exported files.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of the AWS Identity and Access Management (IAM) role that Amazon GameLift Streams assumes on behalf of your application during the stream session.

    " + }, + "DisplayConfiguration":{ + "shape":"DisplayConfiguration", + "documentation":"

    The configuration for the stream session's virtual monitor.

    " } } }, @@ -2170,6 +2746,7 @@ "invalidSignalRequest", "placementTimeout", "applicationLogS3DestinationError", + "assumeRoleFailed", "applicationExit", "connectionTimeout", "reconnectionTimeout", @@ -2178,6 +2755,12 @@ "apiTerminated" ] }, + "StreamSessionStreamUrl":{ + "type":"string", + "max":2048, + "min":1, + "sensitive":true + }, "StreamSessionSummary":{ "type":"structure", "members":{ @@ -2220,6 +2803,10 @@ "Location":{ "shape":"LocationName", "documentation":"

    The location where Amazon GameLift Streams hosts and streams your application. For example, us-east-1. For a complete list of locations that Amazon GameLift Streams supports, refer to Regions, quotas, and limitations in the Amazon GameLift Streams Developer Guide.

    " + }, + "RoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of the AWS Identity and Access Management (IAM) role that Amazon GameLift Streams assumes on behalf of your application during the stream session.

    " } }, "documentation":"

    Describes an Amazon GameLift Streams stream session. To retrieve additional details for the stream session, call GetStreamSession.

    " @@ -2229,6 +2816,88 @@ "member":{"shape":"StreamSessionSummary"} }, "StreamUrl":{"type":"string"}, + "StreamUrlStatus":{ + "type":"string", + "enum":[ + "ACTIVE", + "EXPIRED", + "REVOKED", + "LIMIT_REACHED" + ] + }, + "StreamUrlStatusReason":{ + "type":"string", + "enum":[ + "userRevoked", + "revokedAndTerminatingSessions", + "revokedAndSessionsTerminated", + "streamGroupDeleted", + "applicationDeleted" + ] + }, + "StreamUrlSummary":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the stream URL across all Amazon Web Services Regions. Format is arn:aws:gameliftstreams:[AWS Region]:[AWS account]:streamurl/[stream group resource ID]/[stream URL resource ID].

    " + }, + "StreamUrlId":{ + "shape":"Id", + "documentation":"

    The unique identifier for the stream URL resource, for example su-1AB2C3De4.

    " + }, + "StreamUrl":{ + "shape":"StreamSessionStreamUrl", + "documentation":"

    The shareable stream URL. Distribute this URL to end users so that they can start and play a stream session in a hosted web player. Treat the stream URL as a secret. Anyone who has it can start a stream session until the stream URL expires, is revoked, or reaches its usage limit.

    " + }, + "Status":{ + "shape":"StreamUrlStatus", + "documentation":"

    The current status of the stream URL. Possible statuses include the following:

    • ACTIVE: The stream URL is valid and can start stream sessions.

    • EXPIRED: The stream URL has passed its expiration time and can no longer start stream sessions.

    • REVOKED: The stream URL was revoked and can no longer start stream sessions.

    • LIMIT_REACHED: The stream URL has been used the maximum number of times and can no longer start stream sessions.

    " + }, + "StatusReason":{ + "shape":"StreamUrlStatusReason", + "documentation":"

    Additional information about why the stream URL is in its current status. Amazon GameLift Streams populates this value when the status is REVOKED. Possible values include the following:

    • userRevoked: You revoked the stream URL.

    • revokedAndTerminatingSessions: You revoked the stream URL and Amazon GameLift Streams is ending its running stream sessions.

    • revokedAndSessionsTerminated: You revoked the stream URL and its running stream sessions have ended.

    • streamGroupDeleted: The stream group was deleted, which revoked the stream URL.

    • applicationDeleted: The application was deleted, which revoked the stream URL.

    " + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the stream URL expires and stops accepting new stream sessions. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    A timestamp that indicates when this resource was created. Timestamps are expressed using in ISO8601 format, such as: 2022-12-27T22:29:40+00:00 (UTC).

    " + }, + "UsageLimit":{ + "shape":"UsageLimit", + "documentation":"

    The maximum number of times the stream URL can start a stream session.

    " + }, + "RemainingUses":{ + "shape":"RemainingUses", + "documentation":"

    The number of times the stream URL can still be used to start a stream session.

    " + }, + "StreamGroupArn":{ + "shape":"Arn", + "documentation":"

    The stream group that runs the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the stream group resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:streamgroup/sg-1AB2C3De4.

    " + }, + "ApplicationArn":{ + "shape":"Arn", + "documentation":"

    The application that runs in the stream sessions.

    This value is an Amazon Resource Name (ARN) that uniquely identifies the application resource. Example ARN: arn:aws:gameliftstreams:us-west-2:111122223333:application/a-9ZY8X7Wv6.

    " + }, + "SessionLengthSeconds":{ + "shape":"SessionLengthSeconds", + "documentation":"

    The maximum length of time, in seconds, that a stream session started from this stream URL can run.

    " + }, + "Description":{ + "shape":"Description", + "documentation":"

    The descriptive label for the stream URL.

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

    Describes a stream URL. This is a summary view that omits the full configuration, such as launch arguments and display settings. To retrieve the complete configuration, call GetStreamUrl.

    " + }, + "StreamUrlSummaryList":{ + "type":"list", + "member":{"shape":"StreamUrlSummary"} + }, "String":{"type":"string"}, "TagKey":{ "type":"string", @@ -2515,6 +3184,16 @@ } } }, + "UrlExpiresAfterMinutes":{ + "type":"integer", + "box":true, + "min":1 + }, + "UsageLimit":{ + "type":"integer", + "box":true, + "min":1 + }, "UserId":{ "type":"string", "max":1024, diff --git a/services/geomaps/pom.xml b/services/geomaps/pom.xml index 1efde4b0ab89..b0d074f794ca 100644 --- a/services/geomaps/pom.xml +++ b/services/geomaps/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT geomaps AWS Java SDK :: Services :: Geo Maps diff --git a/services/geomaps/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/geomaps/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..88b84f6ab2c0 --- /dev/null +++ b/services/geomaps/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,254 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://maps.geo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://maps.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://maps.geo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://maps.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-maps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-maps-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-maps.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-maps.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAA4AAAAGAAAABAAAAA4AAAAHAAAABQAAAAoAAAAIAAAABwAAAAkF9eEOAAAACAX14QwF9eENAAAABgAAAAwAAAALAAAABwX14QkF9eELAAAABwAAAA0F9eEKAAAACAX14QgF9eEJAAAABQAAABAAAAAPAAAABwX14QcF9eEEAAAABwX14QUF9eEGAAAABQX14QEAAAASAAAABwX14QIF9eED" +} \ No newline at end of file diff --git a/services/geomaps/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/geomaps/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b294fe7804e7..000000000000 --- a/services/geomaps/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,688 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://maps.geo.{Region}.{PartitionResult#dnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://maps.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://maps.geo-fips.{Region}.{PartitionResult#dnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://maps.geo.{Region}.{PartitionResult#dualStackDnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://maps.geo.{Region}.{PartitionResult#dnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://maps.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://maps.geo-fips.{Region}.{PartitionResult#dnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://maps.geo.{Region}.{PartitionResult#dualStackDnsSuffix}/v2", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-maps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-maps-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-maps.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://geo-maps.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/geomaps/src/main/resources/codegen-resources/endpoint-tests.json b/services/geomaps/src/main/resources/codegen-resources/endpoint-tests.json index a225a2a27805..41471110b2ef 100644 --- a/services/geomaps/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/geomaps/src/main/resources/codegen-resources/endpoint-tests.json @@ -37,7 +37,7 @@ "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://maps.geo-fips.us-east-1.api.aws/v2" + "url": "https://maps.geo-fips.us-east-1.api.aws" } }, "params": { @@ -50,7 +50,7 @@ "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://maps.geo-fips.us-east-1.amazonaws.com/v2" + "url": "https://maps.geo-fips.us-east-1.amazonaws.com" } }, "params": { @@ -63,7 +63,7 @@ "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://maps.geo.us-east-1.api.aws/v2" + "url": "https://maps.geo.us-east-1.api.aws" } }, "params": { @@ -76,7 +76,7 @@ "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://maps.geo.us-east-1.amazonaws.com/v2" + "url": "https://maps.geo.us-east-1.amazonaws.com" } }, "params": { @@ -271,7 +271,7 @@ "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://maps.geo-fips.us-gov-west-1.api.aws/v2" + "url": "https://maps.geo-fips.us-gov-west-1.api.aws" } }, "params": { @@ -284,7 +284,7 @@ "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://maps.geo-fips.us-gov-west-1.amazonaws.com/v2" + "url": "https://maps.geo-fips.us-gov-west-1.amazonaws.com" } }, "params": { @@ -297,7 +297,7 @@ "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://maps.geo.us-gov-west-1.api.aws/v2" + "url": "https://maps.geo.us-gov-west-1.api.aws" } }, "params": { @@ -310,7 +310,7 @@ "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://maps.geo.us-gov-west-1.amazonaws.com/v2" + "url": "https://maps.geo.us-gov-west-1.amazonaws.com" } }, "params": { diff --git a/services/geomaps/src/main/resources/codegen-resources/service-2.json b/services/geomaps/src/main/resources/codegen-resources/service-2.json index 1bfd53ede697..f9f003d570b4 100644 --- a/services/geomaps/src/main/resources/codegen-resources/service-2.json +++ b/services/geomaps/src/main/resources/codegen-resources/service-2.json @@ -17,7 +17,7 @@ "name":"GetGlyphs", "http":{ "method":"GET", - "requestUri":"/glyphs/{FontStack}/{FontUnicodeRange}", + "requestUri":"/v2/glyphs/{FontStack}/{FontUnicodeRange}", "responseCode":200 }, "input":{"shape":"GetGlyphsRequest"}, @@ -29,7 +29,7 @@ "name":"GetSprites", "http":{ "method":"GET", - "requestUri":"/styles/{Style}/{ColorScheme}/{Variant}/sprites/{FileName}", + "requestUri":"/v2/styles/{Style}/{ColorScheme}/{Variant}/sprites/{FileName}", "responseCode":200 }, "input":{"shape":"GetSpritesRequest"}, @@ -41,7 +41,7 @@ "name":"GetStaticMap", "http":{ "method":"GET", - "requestUri":"/static/{FileName}", + "requestUri":"/v2/static/{FileName}", "responseCode":200 }, "input":{"shape":"GetStaticMapRequest"}, @@ -52,14 +52,14 @@ {"shape":"ValidationException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    This operation is not supported in ap-southeast-1 and ap-southeast-5 regions for GrabMaps customers.

    GetStaticMap provides high-quality static map images with customizable options. You can modify the map's appearance and overlay additional information. It's an ideal solution for applications requiring tailored static map snapshots.

    For more information, see the following topics in the Amazon Location Service Developer Guide:

    ", + "documentation":"

    GetStaticMap provides high-quality static map images with customizable options. You can modify the map's appearance and overlay additional information. It's an ideal solution for applications requiring tailored static map snapshots. Not supported in ap-southeast-1 and ap-southeast-5 regions for GrabMaps customers.

    For more information, see the following topics in the Amazon Location Service Developer Guide:

    ", "readonly":true }, "GetStyleDescriptor":{ "name":"GetStyleDescriptor", "http":{ "method":"GET", - "requestUri":"/styles/{Style}/descriptor", + "requestUri":"/v2/styles/{Style}/descriptor", "responseCode":200 }, "input":{"shape":"GetStyleDescriptorRequest"}, @@ -71,7 +71,7 @@ "name":"GetTile", "http":{ "method":"GET", - "requestUri":"/tiles/{Tileset}/{Z}/{X}/{Y}", + "requestUri":"/v2/tiles/{Tileset}/{Z}/{X}/{Y}", "responseCode":200 }, "input":{"shape":"GetTileRequest"}, @@ -550,6 +550,18 @@ "location":"querystring", "locationName":"buildings" }, + "PoiDensity":{ + "shape":"PoiDensity", + "documentation":"

    Controls how densely points of interest are rendered on the map. The density value controls the zoom level at which each category of points of interest appears, and how quickly less prominent points of interest are revealed as you zoom in. Denser values display more points of interest at lower zoom levels.

    Use Off to hide all points of interest. When you omit this parameter, the map renders at Default density.

    The difference between density values is most noticeable at mid-range zoom levels. At high zoom levels, all density values converge on displaying every available point of interest.

    This parameter is valid only for the Standard and Hybrid map styles. In ap-southeast-1 and ap-southeast-5 regions for GrabMaps customers, this parameter is valid only for the Standard map style.

    ", + "location":"querystring", + "locationName":"poi-density" + }, + "PoiCategories":{ + "shape":"PoiCategoryList", + "documentation":"

    Renders only the specified categories of points of interest. When you omit this parameter, the map renders all categories.

    The following categories are currently supported:

    • FoodAndDrink

    • Entertainment

    • SightsAndMuseums

    • Transportation

    • Accommodations

    • LeisureAndOutdoor

    • Shopping

    • BusinessAndServices

    • FacilitiesAndBuildings

    Specify each category as a separate poi-categories query parameter. Duplicate values are rejected.

    This parameter has no effect when poi-density is set to Off, which hides all points of interest regardless of category.

    This parameter is valid only for the Standard and Hybrid map styles. In ap-southeast-1 and ap-southeast-5 regions for GrabMaps customers, this parameter is valid only for the Standard map style.

    ", + "location":"querystring", + "locationName":"poi-categories" + }, "Key":{ "shape":"ApiKey", "documentation":"

    Optional: The API key to be used for authorization. Either an API key or valid SigV4 signature must be provided when making a request.

    ", @@ -732,6 +744,37 @@ "Satellite" ] }, + "PoiCategory":{ + "type":"string", + "enum":[ + "FoodAndDrink", + "Entertainment", + "SightsAndMuseums", + "Transportation", + "Accommodations", + "LeisureAndOutdoor", + "Shopping", + "BusinessAndServices", + "FacilitiesAndBuildings" + ] + }, + "PoiCategoryList":{ + "type":"list", + "member":{"shape":"PoiCategory"}, + "max":9, + "min":0 + }, + "PoiDensity":{ + "type":"string", + "enum":[ + "Off", + "VerySparse", + "Sparse", + "Default", + "Dense", + "VeryDense" + ] + }, "PositionString":{ "type":"string", "max":36, @@ -907,5 +950,5 @@ "enum":["Default"] } }, - "documentation":"

    Integrate high-quality base map data into your applications using MapLibre. Capabilities include:

    • Access to comprehensive base map data, allowing you to tailor the map display to your specific needs.

    • Multiple pre-designed map styles suited for various application types, such as navigation, logistics, or data visualization.

    • Generation of static map images for scenarios where interactive maps aren't suitable, such as:

      • Embedding in emails or documents

      • Displaying in low-bandwidth environments

      • Creating printable maps

      • Enhancing application performance by reducing client-side rendering

    " + "documentation":"

    Integrate high-quality base map data into your applications using MapLibre. Capabilities include:

    • Access to comprehensive base map data, allowing you to tailor the map display to your specific needs. See GetTile.

    • Multiple pre-designed map styles suited for various application types, such as navigation, logistics, or data visualization. See GetStyleDescriptor.

    • Generation of static map images for scenarios where interactive maps aren't suitable. See GetStaticMap. Use cases include:

      • Embedding in emails or documents

      • Displaying in low-bandwidth environments

      • Creating printable maps

      • Enhancing application performance by reducing client-side rendering

    " } diff --git a/services/geoplaces/pom.xml b/services/geoplaces/pom.xml index 4922315fb00c..0f1190f711f5 100644 --- a/services/geoplaces/pom.xml +++ b/services/geoplaces/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT geoplaces AWS Java SDK :: Services :: Geo Places diff --git a/services/geoplaces/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/geoplaces/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7de81cb265fb --- /dev/null +++ b/services/geoplaces/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,254 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://places.geo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://places.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://places.geo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://places.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-places-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-places-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-places.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-places.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAA4AAAAGAAAABAAAAA4AAAAHAAAABQAAAAoAAAAIAAAABwAAAAkF9eEOAAAACAX14QwF9eENAAAABgAAAAwAAAALAAAABwX14QkF9eELAAAABwAAAA0F9eEKAAAACAX14QgF9eEJAAAABQAAABAAAAAPAAAABwX14QcF9eEEAAAABwX14QUF9eEGAAAABQX14QEAAAASAAAABwX14QIF9eED" +} \ No newline at end of file diff --git a/services/geoplaces/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/geoplaces/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e9487731de32..000000000000 --- a/services/geoplaces/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,688 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://places.geo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://places.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://places.geo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://places.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://places.geo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://places.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://places.geo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://places.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-places-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-places-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-places.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://geo-places.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/georoutes/pom.xml b/services/georoutes/pom.xml index 795be43452e3..36fe70f7acd1 100644 --- a/services/georoutes/pom.xml +++ b/services/georoutes/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT georoutes AWS Java SDK :: Services :: Geo Routes diff --git a/services/georoutes/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/georoutes/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..41413e58246d --- /dev/null +++ b/services/georoutes/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,290 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo.{Region}.us-gov.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo-fips.{Region}.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo-fips.{Region}.us-gov.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://routes.geo.{Region}.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-routes-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-routes-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-routes.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-routes.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 21, + "nodes": "/////wAAAAH/////AAAAAAAAABQAAAADAAAAAQAAAAQF9eETAAAAAgAAAAUF9eETAAAAAwAAAAwAAAAGAAAABAAAAAsAAAAHAAAABQAAAAoAAAAIAAAABgAAAAkF9eESAAAABwX14RAF9eERAAAABgX14QsF9eEIAAAABgX14QcF9eEEAAAABAAAABMAAAANAAAABQAAABIAAAAOAAAABgAAABAAAAAPAAAACAX14Q4F9eEPAAAABwAAABEF9eENAAAACAX14QwF9eENAAAABgX14QkF9eEKAAAABgX14QUF9eEGAAAAAwX14QEAAAAVAAAABgX14QIF9eED" +} \ No newline at end of file diff --git a/services/georoutes/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/georoutes/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 923fe4a0f613..000000000000 --- a/services/georoutes/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,688 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://routes.geo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://routes.geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://routes.geo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://routes.geo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://routes.geo.{Region}.us-gov.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://routes.geo-fips.{Region}.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://routes.geo-fips.{Region}.us-gov.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://routes.geo.{Region}.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-routes-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-routes-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-routes.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://geo-routes.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/glacier/pom.xml b/services/glacier/pom.xml index b11a7cbd9601..6d1b76b0a098 100644 --- a/services/glacier/pom.xml +++ b/services/glacier/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT glacier AWS Java SDK :: Services :: Amazon Glacier diff --git a/services/glacier/src/main/resources/codegen-resources/customization.config b/services/glacier/src/main/resources/codegen-resources/customization.config index 599e24d4dcc5..3a7a549e4270 100644 --- a/services/glacier/src/main/resources/codegen-resources/customization.config +++ b/services/glacier/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "customErrorCodeFieldName": "code", "shapeModifiers" : { "UploadArchiveInput" : { diff --git a/services/glacier/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/glacier/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2218d8239e9e --- /dev/null +++ b/services/glacier/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glacier-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glacier.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glacier-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glacier.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glacier.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/glacier/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/glacier/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 07cda416672b..000000000000 --- a/services/glacier/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://glacier-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://glacier.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://glacier-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://glacier.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://glacier.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/globalaccelerator/pom.xml b/services/globalaccelerator/pom.xml index 4b1d96e3e7ff..f5fd733d8e8b 100644 --- a/services/globalaccelerator/pom.xml +++ b/services/globalaccelerator/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT globalaccelerator AWS Java SDK :: Services :: Global Accelerator diff --git a/services/globalaccelerator/src/main/resources/codegen-resources/customization.config b/services/globalaccelerator/src/main/resources/codegen-resources/customization.config index 980868643100..97ee95353214 100644 --- a/services/globalaccelerator/src/main/resources/codegen-resources/customization.config +++ b/services/globalaccelerator/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "defaultSimpleMethodTestRegion": "US_WEST_2", "excludedSimpleMethods": [ "describeAcceleratorAttributes" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6a998b52c7db --- /dev/null +++ b/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://globalaccelerator-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://globalaccelerator-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://globalaccelerator.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://globalaccelerator.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fbf43782ab9f..000000000000 --- a/services/globalaccelerator/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://globalaccelerator-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://globalaccelerator-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://globalaccelerator.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://globalaccelerator.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/glue/pom.xml b/services/glue/pom.xml index d777220f8c7b..e208739d9287 100644 --- a/services/glue/pom.xml +++ b/services/glue/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 glue diff --git a/services/glue/src/main/resources/codegen-resources/customization.config b/services/glue/src/main/resources/codegen-resources/customization.config index da22aaad9103..9a6245c00e53 100644 --- a/services/glue/src/main/resources/codegen-resources/customization.config +++ b/services/glue/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "*" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/glue/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/glue/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..46f2a46ca636 --- /dev/null +++ b/services/glue/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glue-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glue-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glue.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://glue.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/glue/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/glue/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a2b58b475956..000000000000 --- a/services/glue/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://glue-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://glue-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://glue.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://glue.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/glue/src/main/resources/codegen-resources/service-2.json b/services/glue/src/main/resources/codegen-resources/service-2.json index 1d82708b5b74..491ac63eac8d 100644 --- a/services/glue/src/main/resources/codegen-resources/service-2.json +++ b/services/glue/src/main/resources/codegen-resources/service-2.json @@ -174,6 +174,21 @@ ], "documentation":"

    Retrieves a list of data quality results for the specified result IDs.

    " }, + "BatchGetDataQualityRulesetEvaluationRun":{ + "name":"BatchGetDataQualityRulesetEvaluationRun", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"BatchGetDataQualityRulesetEvaluationRunRequest"}, + "output":{"shape":"BatchGetDataQualityRulesetEvaluationRunResponse"}, + "errors":[ + {"shape":"InvalidInputException"}, + {"shape":"OperationTimeoutException"}, + {"shape":"InternalServiceException"} + ], + "documentation":"

    Retrieves the details of multiple evaluation runs in a single request.

    " + }, "BatchGetDevEndpoints":{ "name":"BatchGetDevEndpoints", "http":{ @@ -2139,6 +2154,23 @@ ], "documentation":"

    Retrieves the security configuration for a specified catalog.

    " }, + "GetDataCatalogExportConfiguration":{ + "name":"GetDataCatalogExportConfiguration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetDataCatalogExportConfigurationInput"}, + "output":{"shape":"GetDataCatalogExportConfigurationOutput"}, + "errors":[ + {"shape":"InvalidInputException"}, + {"shape":"EntityNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the current export configuration for the Glue Data Catalog. The export configuration controls whether catalog metadata is exported to S3 Tables.

    ", + "readonly":true + }, "GetDataQualityModel":{ "name":"GetDataQualityModel", "http":{ @@ -3512,6 +3544,25 @@ ], "documentation":"

    List integration resource properties for a single customer. It supports the filters, maxRecords and markers.

    " }, + "ListIntegrationTableProperties":{ + "name":"ListIntegrationTableProperties", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListIntegrationTablePropertiesRequest"}, + "output":{"shape":"ListIntegrationTablePropertiesResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"}, + {"shape":"EntityNotFoundException"}, + {"shape":"InternalServiceException"}, + {"shape":"InvalidInputException"} + ], + "documentation":"

    Lists the integration table properties in your account. This operation supports filtering and pagination.

    " + }, "ListIterableForms":{ "name":"ListIterableForms", "http":{ @@ -3775,6 +3826,7 @@ {"shape":"AccessDeniedException"}, {"shape":"InternalServiceException"}, {"shape":"InvalidInputException"}, + {"shape":"EntityNotFoundException"}, {"shape":"ConcurrentModificationException"}, {"shape":"ThrottlingException"} ], @@ -3813,6 +3865,23 @@ ], "documentation":"

    Sets the security configuration for a specified catalog. After the configuration has been set, the specified encryption is applied to every catalog write thereafter.

    " }, + "PutDataCatalogExportConfiguration":{ + "name":"PutDataCatalogExportConfiguration", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"PutDataCatalogExportConfigurationInput"}, + "output":{"shape":"PutDataCatalogExportConfigurationOutput"}, + "errors":[ + {"shape":"InvalidInputException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServiceException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates or updates the export configuration for the Glue Data Catalog. Use this operation to enable or disable the export of catalog metadata to S3 Tables.

    " + }, "PutDataQualityProfileAnnotation":{ "name":"PutDataQualityProfileAnnotation", "http":{ @@ -4272,7 +4341,7 @@ {"shape":"ResourceNumberLimitExceededException"}, {"shape":"InvalidInputException"} ], - "documentation":"

    Starts a materialized view refresh task run, for a specified table and columns.

    " + "documentation":"

    Starts a materialized view refresh task run for a specified materialized view.

    " }, "StartTrigger":{ "name":"StartTrigger", @@ -4388,7 +4457,7 @@ {"shape":"InvalidInputException"}, {"shape":"OperationTimeoutException"} ], - "documentation":"

    Stops a materialized view refresh task run, for a specified table and columns.

    " + "documentation":"

    Stops a materialized view refresh task run for a specified materialized view.

    " }, "StopSession":{ "name":"StopSession", @@ -5580,6 +5649,14 @@ "shape":"AssetId", "documentation":"

    The unique identifier of the asset to associate glossary terms with.

    " }, + "IterableFormName":{ + "shape":"IterableFormName", + "documentation":"

    The name of the iterable form. When specified along with itemIdentifier, the glossary terms are associated with an item within the iterable form rather than the asset itself.

    " + }, + "ItemIdentifier":{ + "shape":"ItemIdentifier", + "documentation":"

    The identifier of the item within the iterable form. Required when iterableFormName is specified.

    " + }, "GlossaryTermIdentifiers":{ "shape":"GlossaryTermIdList", "documentation":"

    The list of glossary term identifiers to associate with the asset.

    " @@ -5598,6 +5675,14 @@ "shape":"AssetId", "documentation":"

    The unique identifier of the asset.

    " }, + "IterableFormName":{ + "shape":"IterableFormName", + "documentation":"

    The name of the iterable form, if the association targets an item.

    " + }, + "ItemIdentifier":{ + "shape":"ItemIdentifier", + "documentation":"

    The identifier of the item within the iterable form, if applicable.

    " + }, "GlossaryTerms":{ "shape":"GlossaryTermIdList", "documentation":"

    The glossary terms now associated with the asset.

    " @@ -6195,6 +6280,29 @@ } } }, + "BatchGetDataQualityRulesetEvaluationRunRequest":{ + "type":"structure", + "required":["RunIds"], + "members":{ + "RunIds":{ + "shape":"DataQualityRulesetEvaluationRunIdList", + "documentation":"

    A list of unique run identifiers for the evaluation runs to retrieve.

    " + } + } + }, + "BatchGetDataQualityRulesetEvaluationRunResponse":{ + "type":"structure", + "members":{ + "Runs":{ + "shape":"DataQualityRulesetEvaluationRunsList", + "documentation":"

    A list of evaluation run details for the requested run IDs.

    " + }, + "RunsNotFound":{ + "shape":"DataQualityRulesetEvaluationRunIdList", + "documentation":"

    A list of run IDs that were not found.

    " + } + } + }, "BatchGetDevEndpointsRequest":{ "type":"structure", "required":["DevEndpointNames"], @@ -6665,6 +6773,28 @@ "max":900, "min":1 }, + "BetweenConfiguration":{ + "type":"structure", + "members":{ + "LowBoundKey":{ + "shape":"String", + "documentation":"

    The parameter name used for the lower bound value in a BETWEEN filter operation.

    " + }, + "HighBoundKey":{ + "shape":"String", + "documentation":"

    The parameter name used for the upper bound value in a BETWEEN filter operation.

    " + }, + "Template":{ + "shape":"String", + "documentation":"

    A template string for constructing the BETWEEN filter expression.

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

    Configuration that defines how BETWEEN range filter operations are translated into REST API request parameters.

    " + }, + "BinEdges":{ + "type":"list", + "member":{"shape":"GenericString"} + }, "BinaryColumnStatisticsData":{ "type":"structure", "required":[ @@ -7440,6 +7570,28 @@ }, "documentation":"

    Specifies a data store in the Glue Data Catalog.

    " }, + "CatalogTableConfigOptions":{ + "type":"structure", + "members":{ + "DatabaseName":{ + "shape":"NameString", + "documentation":"

    The name of the database in the Glue Data Catalog.

    " + }, + "TableName":{ + "shape":"NameString", + "documentation":"

    The name of the table in the Glue Data Catalog.

    " + }, + "S3Location":{ + "shape":"UriString", + "documentation":"

    The Amazon S3 location for storing the results.

    " + }, + "CatalogId":{ + "shape":"NameString", + "documentation":"

    A unique identifier for the Glue Data Catalog.

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

    The configuration for a Glue Data Catalog table used to store data quality results.

    " + }, "CatalogTablesList":{ "type":"list", "member":{"shape":"NameString"}, @@ -8982,6 +9134,11 @@ "member":{"shape":"ConnectionString"}, "max":1000 }, + "ConnectionStringToStringMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, "ConnectionType":{ "type":"string", "enum":[ @@ -9346,6 +9503,10 @@ "PropertyType":{ "shape":"PropertyType", "documentation":"

    The data type of this property

    " + }, + "Format":{ + "shape":"String", + "documentation":"

    A format template for the property value that defines how the value should be formatted before sending it in API requests. Use {value} as a placeholder for the actual property value (for example, SSWS {value}).

    " } }, "documentation":"

    Defines a property configuration for connection types, default values, and where the property should be used in requests.

    " @@ -9384,6 +9545,10 @@ "min":1 }, "ContinuousSync":{"type":"boolean"}, + "Count":{ + "type":"list", + "member":{"shape":"NullableInteger"} + }, "Crawl":{ "type":"structure", "members":{ @@ -11945,6 +12110,10 @@ "EvaluatedMetrics":{ "shape":"EvaluatedMetricsMap", "documentation":"

    A map of metrics associated with the evaluation of the analyzer.

    " + }, + "EvaluatedDistributions":{ + "shape":"EvaluatedDistributionsMap", + "documentation":"

    A map of distribution metrics associated with the evaluation of the analyzer.

    " } }, "documentation":"

    Describes the result of the evaluation of a data quality analyzer.

    " @@ -11994,6 +12163,30 @@ "CustomLogGroupPrefix":{ "shape":"GenericString", "documentation":"

    A custom prefix for the CloudWatch log group names. When specified, evaluation run logs are written to <CustomLogGroupPrefix>/error and <CustomLogGroupPrefix>/output instead of the default /aws-glue/data-quality/error and /aws-glue/data-quality/output log groups.

    " + }, + "RowLevelResults":{ + "shape":"RowLevelResultsOptions", + "documentation":"

    The configuration for writing row-level evaluation results to a Glue Data Catalog table.

    " + }, + "ProfilingResults":{ + "shape":"ProfilingResultsOptions", + "documentation":"

    The configuration for writing profiling results to a Glue Data Catalog table.

    " + }, + "ObservationScope":{ + "shape":"ObservationConfiguration", + "documentation":"

    The scope of the observation for the evaluation run. Specifies whether anomaly detection is enabled or disabled.

    " + }, + "ObservationMode":{ + "shape":"ObservationMode", + "documentation":"

    The observation mode for the evaluation run. Specifies how anomaly detection bounds are calculated.

    " + }, + "DataQualityRuleResults":{ + "shape":"DataQualityRuleResultsOptions", + "documentation":"

    The configuration for writing rule results to a Glue Data Catalog table.

    " + }, + "ObservationResults":{ + "shape":"ObservationResultsOptions", + "documentation":"

    The configuration for writing observation results to a Glue Data Catalog table.

    " } }, "documentation":"

    Additional run options you can specify for an evaluation run.

    " @@ -12227,6 +12420,16 @@ "type":"list", "member":{"shape":"DataQualityResult"} }, + "DataQualityRuleRecommendationRunAdditionalRunOptions":{ + "type":"structure", + "members":{ + "CustomLogGroupPrefix":{ + "shape":"GenericString", + "documentation":"

    A custom prefix for the CloudWatch log group names. When specified, recommendation run logs are written to <CustomLogGroupPrefix>/error and <CustomLogGroupPrefix>/output instead of the default /aws-glue/data-quality/error and /aws-glue/data-quality/output log groups.

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

    Additional run options you can specify for a recommendation run.

    " + }, "DataQualityRuleRecommendationRunDescription":{ "type":"structure", "members":{ @@ -12245,6 +12448,14 @@ "DataSource":{ "shape":"DataSource", "documentation":"

    The data source (Glue table) associated with the recommendation run.

    " + }, + "CreatedRulesetName":{ + "shape":"NameString", + "documentation":"

    The name of the ruleset that was created by the recommendation run.

    " + }, + "RecommendationMode":{ + "shape":"RecommendationMode", + "documentation":"

    The mode that Glue Data Quality uses to recommend rules.

    The default is BASIC.

    " } }, "documentation":"

    Describes the result of a data quality rule recommendation run.

    " @@ -12331,6 +12542,80 @@ "max":2000, "min":0 }, + "DataQualityRuleResultsOptions":{ + "type":"structure", + "members":{ + "WriteDataQualityRuleResultsEnabled":{ + "shape":"NullableBoolean", + "documentation":"

    Set to true to write data quality rule results.

    " + }, + "CatalogTableConfig":{ + "shape":"CatalogTableConfigOptions", + "documentation":"

    The Glue Data Catalog table configuration for storing the rule results.

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

    The configuration for writing data quality rule results.

    " + }, + "DataQualityRulesetEvaluationRun":{ + "type":"structure", + "members":{ + "RunId":{ + "shape":"HashString", + "documentation":"

    The unique run identifier associated with this run.

    " + }, + "DataSource":{"shape":"DataSource"}, + "Role":{ + "shape":"RoleString", + "documentation":"

    An IAM role supplied to encrypt the results of the run.

    " + }, + "NumberOfWorkers":{ + "shape":"NullableInteger", + "documentation":"

    The number of G.1X workers to be used in the run. The default is 5.

    " + }, + "Timeout":{ + "shape":"Timeout", + "documentation":"

    The timeout for a run in minutes. This is the maximum time that a run can consume resources before it is terminated and enters TIMEOUT status. The default is 2,880 minutes (48 hours).

    " + }, + "AdditionalRunOptions":{"shape":"DataQualityEvaluationRunAdditionalRunOptions"}, + "Status":{ + "shape":"TaskStatusType", + "documentation":"

    The status for this run.

    " + }, + "ErrorString":{ + "shape":"GenericString", + "documentation":"

    The error strings that are associated with the run.

    " + }, + "StartedOn":{ + "shape":"Timestamp", + "documentation":"

    The date and time when this run started.

    " + }, + "LastModifiedOn":{ + "shape":"Timestamp", + "documentation":"

    A timestamp. The last point in time when this run was modified.

    " + }, + "CompletedOn":{ + "shape":"Timestamp", + "documentation":"

    The date and time when this run was completed.

    " + }, + "ExecutionTime":{ + "shape":"ExecutionTime", + "documentation":"

    The amount of time (in seconds) that the run consumed resources.

    " + }, + "RulesetNames":{ + "shape":"RulesetNames", + "documentation":"

    A list of ruleset names for the run.

    " + }, + "ResultIds":{ + "shape":"DataQualityResultIdList", + "documentation":"

    A list of result IDs for the data quality results for the run.

    " + }, + "AdditionalDataSources":{ + "shape":"DataSourceMap", + "documentation":"

    A map of reference strings to additional data sources you can specify for an evaluation run.

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

    The details of a data quality ruleset evaluation run.

    " + }, "DataQualityRulesetEvaluationRunDescription":{ "type":"structure", "members":{ @@ -12376,10 +12661,20 @@ }, "documentation":"

    The filter criteria.

    " }, + "DataQualityRulesetEvaluationRunIdList":{ + "type":"list", + "member":{"shape":"HashString"}, + "max":100, + "min":1 + }, "DataQualityRulesetEvaluationRunList":{ "type":"list", "member":{"shape":"DataQualityRulesetEvaluationRunDescription"} }, + "DataQualityRulesetEvaluationRunsList":{ + "type":"list", + "member":{"shape":"DataQualityRulesetEvaluationRun"} + }, "DataQualityRulesetFilterCriteria":{ "type":"structure", "members":{ @@ -12798,6 +13093,14 @@ "AssetIdentifier":{ "shape":"AssetId", "documentation":"

    The unique identifier of the asset.

    " + }, + "IterableFormName":{ + "shape":"IterableFormName", + "documentation":"

    The name of the iterable form, if the deletion targets an item.

    " + }, + "ItemIdentifier":{ + "shape":"ItemIdentifier", + "documentation":"

    The identifier of the item within the iterable form, if applicable.

    " } } }, @@ -14105,6 +14408,14 @@ "shape":"AssetId", "documentation":"

    The unique identifier of the asset to disassociate glossary terms from.

    " }, + "IterableFormName":{ + "shape":"IterableFormName", + "documentation":"

    The name of the iterable form. When specified along with itemIdentifier, the glossary terms are disassociated from an item within the iterable form rather than the asset itself.

    " + }, + "ItemIdentifier":{ + "shape":"ItemIdentifier", + "documentation":"

    The identifier of the item within the iterable form. Required when iterableFormName is specified.

    " + }, "GlossaryTermIdentifiers":{ "shape":"GlossaryTermIdList", "documentation":"

    The list of glossary term identifiers to disassociate from the asset.

    " @@ -14123,6 +14434,14 @@ "shape":"AssetId", "documentation":"

    The unique identifier of the asset.

    " }, + "IterableFormName":{ + "shape":"IterableFormName", + "documentation":"

    The name of the iterable form, if the disassociation targets an item.

    " + }, + "ItemIdentifier":{ + "shape":"ItemIdentifier", + "documentation":"

    The identifier of the item within the iterable form, if applicable.

    " + }, "GlossaryTerms":{ "shape":"GlossaryTermIdList", "documentation":"

    The remaining glossary terms associated with the asset.

    " @@ -14134,6 +14453,38 @@ "max":128, "min":1 }, + "DistributionData":{ + "type":"structure", + "members":{ + "BinEdges":{ + "shape":"BinEdges", + "documentation":"

    The bin edge values for the distribution.

    " + }, + "Count":{ + "shape":"Count", + "documentation":"

    The frequency count for each bin in the distribution.

    " + }, + "DataType":{ + "shape":"NameString", + "documentation":"

    The data type of the column for the distribution.

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

    The distribution data for a statistic.

    " + }, + "DistributionResultsOptions":{ + "type":"structure", + "members":{ + "WriteDistributionResultsEnabled":{ + "shape":"NullableBoolean", + "documentation":"

    Set to true to write distribution results.

    " + }, + "CatalogTableConfig":{ + "shape":"CatalogTableConfigOptions", + "documentation":"

    The Glue Data Catalog table configuration for storing the distribution results.

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

    The configuration for writing distribution results.

    " + }, "Double":{"type":"double"}, "DoubleColumnStatisticsData":{ "type":"structure", @@ -14635,6 +14986,12 @@ }, "documentation":"

    Specifies your data quality evaluation criteria.

    " }, + "EvaluatedDistributionsMap":{ + "type":"map", + "key":{"shape":"NameString"}, + "value":{"shape":"DistributionData"}, + "sensitive":true + }, "EvaluatedMetricsMap":{ "type":"map", "key":{"shape":"NameString"}, @@ -14728,6 +15085,20 @@ "NONE" ] }, + "ExportEncryptionConfiguration":{ + "type":"structure", + "members":{ + "SseAlgorithm":{ + "shape":"SseAlgorithm", + "documentation":"

    The server-side encryption algorithm used for the exported data. Valid values are AES256 and aws:kms.

    " + }, + "KmsKeyArn":{ + "shape":"KmsKeyArnString", + "documentation":"

    The ARN of the KMS key used to encrypt the exported data.

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

    The encryption configuration for exported data catalog metadata.

    " + }, "ExportLabelsTaskRunProperties":{ "type":"structure", "members":{ @@ -14738,6 +15109,25 @@ }, "documentation":"

    Specifies configuration properties for an exporting labels task run.

    " }, + "ExportSetting":{ + "type":"string", + "documentation":"

    The export setting for the data catalog.

    ", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, + "ExportStatus":{ + "type":"string", + "documentation":"

    The current status of the data catalog export.

    ", + "enum":[ + "ENABLING", + "ENABLED", + "DISABLING", + "DISABLED", + "FAILED" + ] + }, "ExtendedString":{ "type":"string", "pattern":"[\\s\\S]*" @@ -14999,6 +15389,30 @@ "FieldDataType":{ "shape":"FieldDataType", "documentation":"

    The data type of the field.

    " + }, + "ResponseDateFormat":{ + "shape":"String", + "documentation":"

    The format pattern for parsing date values from API responses. Required when the API uses a non-ISO-8601 format. Accepts Java DateTimeFormatter patterns (for example, EEE, d MMM yyyy HH:mm:ss Z), EPOCH_SECONDS for Unix epoch seconds, or EPOCH_MILLIS for Unix epoch milliseconds.

    " + }, + "IsPartitionable":{ + "shape":"Bool", + "documentation":"

    Indicates whether this field can be used for partitioning queries to the data source.

    " + }, + "IsNullable":{ + "shape":"Bool", + "documentation":"

    Indicates whether this field can contain null values.

    " + }, + "IsQueryable":{ + "shape":"Bool", + "documentation":"

    Indicates whether this field can be used in filter predicates when querying data.

    " + }, + "IsOrderable":{ + "shape":"Bool", + "documentation":"

    Indicates whether this field can be used for ordering results.

    " + }, + "FilterOverrides":{ + "shape":"FilterOverrides", + "documentation":"

    Per-field overrides for filter behavior, allowing customization of how filters are applied to this specific field.

    " } }, "documentation":"

    Defines a field in an entity schema for REST connector data sources, specifying the field name and data type.

    " @@ -15092,16 +15506,47 @@ "shape":"OneInput", "documentation":"

    The data inputs identified by their node names.

    " }, - "LogicalOperator":{ - "shape":"FilterLogicalOperator", - "documentation":"

    The operator used to filter rows by comparing the key value to a specified value.

    " + "LogicalOperator":{ + "shape":"FilterLogicalOperator", + "documentation":"

    The operator used to filter rows by comparing the key value to a specified value.

    " + }, + "Filters":{ + "shape":"FilterExpressions", + "documentation":"

    Specifies a filter expression.

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

    Specifies a transform that splits a dataset into two, based on a filter condition.

    " + }, + "FilterConfiguration":{ + "type":"structure", + "required":["FilterMode"], + "members":{ + "FilterMode":{ + "shape":"FilterMode", + "documentation":"

    The strategy for applying filters to requests. Use QUERY_PARAMS to pass filters as individual query parameters, or FILTER_STRING to construct a single filter expression string.

    " + }, + "OperatorMappings":{ + "shape":"ConnectionStringToStringMap", + "documentation":"

    A map of logical filter operators to their API-specific string representations. Supported operator keys are: EQUAL_TO, NOT_EQUAL_TO, LESS_THAN, GREATER_THAN, LESS_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO, CONTAINS, BETWEEN, AND, and OR.

    " + }, + "DateTimeFormat":{ + "shape":"String", + "documentation":"

    The global date and time format for filter expressions. Accepts Java DateTimeFormatter patterns (for example, EEE, d MMM yyyy HH:mm:ss Z), EPOCH_SECONDS for Unix epoch seconds, or EPOCH_MILLIS for Unix epoch milliseconds. If not specified, values are passed as-is in ISO-8601 format.

    " + }, + "StripQuotes":{ + "shape":"Bool", + "documentation":"

    Indicates whether surrounding double quotes should be stripped from filter values before processing.

    " }, - "Filters":{ - "shape":"FilterExpressions", - "documentation":"

    Specifies a filter expression.

    " + "BetweenConfiguration":{ + "shape":"BetweenConfiguration", + "documentation":"

    Configuration for handling BETWEEN range filter operations.

    " + }, + "FilterStringConfiguration":{ + "shape":"FilterStringConfiguration", + "documentation":"

    Configuration for constructing filter expressions when FilterMode is set to FILTER_STRING.

    " } }, - "documentation":"

    Specifies a transform that splits a dataset into two, based on a filter condition.

    " + "documentation":"

    Configuration that defines how filter predicates are applied to REST API requests, supporting both query parameter and filter string strategies.

    " }, "FilterExpression":{ "type":"structure", @@ -15136,6 +15581,14 @@ "OR" ] }, + "FilterMode":{ + "type":"string", + "documentation":"

    The strategy used to apply filter predicates to REST API requests.

    ", + "enum":[ + "QUERY_PARAMS", + "FILTER_STRING" + ] + }, "FilterOperation":{ "type":"string", "enum":[ @@ -15159,6 +15612,28 @@ "NE" ] }, + "FilterOverrides":{ + "type":"structure", + "members":{ + "FieldName":{ + "shape":"String", + "documentation":"

    An override for the field name to use in filter expressions, if different from the schema field name.

    " + }, + "OperatorMappings":{ + "shape":"ConnectionStringToStringMap", + "documentation":"

    A map of logical filter operators to their field-specific API representations, overriding the global operator mappings. Supported operator keys are: EQUAL_TO, NOT_EQUAL_TO, LESS_THAN, GREATER_THAN, LESS_THAN_OR_EQUAL_TO, GREATER_THAN_OR_EQUAL_TO, CONTAINS, BETWEEN, AND, and OR.

    " + }, + "BetweenConfiguration":{ + "shape":"BetweenConfiguration", + "documentation":"

    Field-specific configuration for handling BETWEEN range filter operations.

    " + }, + "DateTimeFormat":{ + "shape":"String", + "documentation":"

    The date and time format for filter expressions on this field, overriding the global DateTimeFormat. Accepts Java DateTimeFormatter patterns (for example, EEE, d MMM yyyy HH:mm:ss Z), EPOCH_SECONDS for Unix epoch seconds, or EPOCH_MILLIS for Unix epoch milliseconds.

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

    Configuration that defines per-field overrides for filter behavior, allowing individual fields to customize how filter operations are applied.

    " + }, "FilterPredicate":{ "type":"string", "max":100000, @@ -15170,6 +15645,25 @@ "min":0, "pattern":"[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\t]*" }, + "FilterStringConfiguration":{ + "type":"structure", + "required":["QueryParameterName"], + "members":{ + "QueryParameterName":{ + "shape":"String", + "documentation":"

    The query parameter name used to send the constructed filter expression string in API requests.

    " + }, + "QuoteStringValues":{ + "shape":"Bool", + "documentation":"

    Indicates whether string and date values should be wrapped with a quote character in the filter expression.

    " + }, + "QuoteCharacter":{ + "shape":"String", + "documentation":"

    The character used to quote values when QuoteStringValues is true. Defaults to double quotes if not specified.

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

    Configuration for constructing filter expression strings when using the FILTER_STRING filter mode.

    " + }, "FilterValue":{ "type":"structure", "required":[ @@ -15395,7 +15889,8 @@ "shape":"IterableFormMap", "documentation":"

    The iterable forms available on the asset, keyed by form name (for example, columns). Use the form name with ListIterableForms or BatchGetIterableForms to retrieve the form's items.

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

    The asset metadata returned by the GetAsset operation.

    " }, "GetAssetTypeRequest":{ "type":"structure", @@ -16043,6 +16538,40 @@ } } }, + "GetDataCatalogExportConfigurationInput":{ + "type":"structure", + "members":{} + }, + "GetDataCatalogExportConfigurationOutput":{ + "type":"structure", + "members":{ + "ExportSetting":{ + "shape":"ExportSetting", + "documentation":"

    The export setting for the data catalog. Valid values are ENABLED and DISABLED.

    " + }, + "Status":{ + "shape":"ExportStatus", + "documentation":"

    The current status of the export. Valid values are ENABLING, ENABLED, DISABLING, DISABLED, and FAILED.

    " + }, + "EncryptionConfiguration":{ + "shape":"ExportEncryptionConfiguration", + "documentation":"

    The encryption configuration for the exported data.

    " + }, + "S3TableBucketArn":{ + "shape":"S3TableBucketArn", + "documentation":"

    The ARN of the S3 Tables bucket where catalog metadata is exported.

    " + }, + "CreatedAt":{ + "shape":"CreatedAt", + "documentation":"

    The timestamp at which the export configuration was created.

    " + }, + "UpdatedAt":{ + "shape":"UpdatedAt", + "documentation":"

    The timestamp at which the export configuration was last updated.

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

    The export configuration returned by the GetDataCatalogExportConfiguration operation.

    " + }, "GetDataQualityModelRequest":{ "type":"structure", "required":["ProfileId"], @@ -16207,7 +16736,7 @@ }, "Role":{ "shape":"RoleString", - "documentation":"

    An IAM role supplied to encrypt the results of the run.

    " + "documentation":"

    The IAM role that Glue assumes to access resources for the run.

    " }, "NumberOfWorkers":{ "shape":"NullableInteger", @@ -16252,6 +16781,14 @@ "DataQualitySecurityConfiguration":{ "shape":"NameString", "documentation":"

    The name of the security configuration created with the data quality encryption option.

    " + }, + "AdditionalRunOptions":{ + "shape":"DataQualityRuleRecommendationRunAdditionalRunOptions", + "documentation":"

    Additional run options you can specify for a recommendation run.

    " + }, + "RecommendationMode":{ + "shape":"RecommendationMode", + "documentation":"

    The mode that Glue Data Quality uses to recommend rules.

    The default is BASIC.

    " } }, "documentation":"

    The response for the Data Quality rule recommendation run.

    " @@ -19946,6 +20483,58 @@ ] }, "IntegrationString":{"type":"string"}, + "IntegrationTableProperties":{ + "type":"structure", + "required":[ + "ResourceArn", + "TableName" + ], + "members":{ + "ResourceArn":{ + "shape":"String512", + "documentation":"

    The connection ARN of the source, or the database ARN of the target.

    " + }, + "TableName":{ + "shape":"String128", + "documentation":"

    The name of the source table to be replicated.

    " + }, + "SourceTableConfig":{ + "shape":"SourceTableConfig", + "documentation":"

    A structure for the source table configuration.

    " + }, + "TargetTableConfig":{ + "shape":"TargetTableConfig", + "documentation":"

    A structure for the target table configuration.

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

    The properties of a single integration table, including the resource ARN, the table name, and the source or target table configuration.

    " + }, + "IntegrationTablePropertiesFilter":{ + "type":"structure", + "members":{ + "Name":{ + "shape":"String128", + "documentation":"

    The name of the filter. Supported filter keys are SourceArn, TargetArn, SourceTableName, and TargetTableName.

    " + }, + "Values":{ + "shape":"IntegrationTablePropertiesFilterValues", + "documentation":"

    A list of filter values.

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

    A key-value filter used to narrow the list of integration table properties returned by ListIntegrationTableProperties. Specify a filter key and one or more values to match.

    " + }, + "IntegrationTablePropertiesFilterList":{ + "type":"list", + "member":{"shape":"IntegrationTablePropertiesFilter"} + }, + "IntegrationTablePropertiesFilterValues":{ + "type":"list", + "member":{"shape":"String128"} + }, + "IntegrationTablePropertiesList":{ + "type":"list", + "member":{"shape":"IntegrationTableProperties"} + }, "IntegrationTagsList":{ "type":"list", "member":{"shape":"Tag"} @@ -21189,6 +21778,10 @@ "type":"string", "pattern":"^$|arn:aws[a-z0-9-]*:kms:.*" }, + "KmsKeyArnString":{ + "type":"string", + "pattern":"arn:aws[-a-z0-9]*:kms:[-a-z0-9]*:[0-9]{12}:key/.+" + }, "LabelCount":{"type":"integer"}, "LabelingSetGenerationTaskRunProperties":{ "type":"structure", @@ -21570,6 +22163,10 @@ "MaxResults":{ "shape":"PageSize", "documentation":"

    The maximum number of results to return.

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

    A list of key-value pair tags to filter recommendation runs.

    " } } }, @@ -21882,7 +22479,7 @@ "type":"structure", "members":{ "Marker":{ - "shape":"String1024", + "shape":"String4096", "documentation":"

    This is the pagination token for next page, initial value is null.

    " }, "Filters":{ @@ -21903,11 +22500,41 @@ "documentation":"

    A list of integration resource property meeting the filter criteria.

    " }, "Marker":{ - "shape":"String1024", + "shape":"String4096", "documentation":"

    This is the pagination token for the next page.

    " } } }, + "ListIntegrationTablePropertiesRequest":{ + "type":"structure", + "members":{ + "Marker":{ + "shape":"String4096", + "documentation":"

    The pagination token for the next page of results. The initial value is null.

    " + }, + "Filters":{ + "shape":"IntegrationTablePropertiesFilterList", + "documentation":"

    A list of filters. Supported filter keys are SourceArn, TargetArn, SourceTableName, and TargetTableName.

    " + }, + "MaxRecords":{ + "shape":"IntegrationInteger", + "documentation":"

    The maximum number of records to return in the response.

    " + } + } + }, + "ListIntegrationTablePropertiesResponse":{ + "type":"structure", + "members":{ + "IntegrationTablePropertiesList":{ + "shape":"IntegrationTablePropertiesList", + "documentation":"

    A list of integration table properties meeting the filter criteria.

    " + }, + "Marker":{ + "shape":"String4096", + "documentation":"

    The pagination token for the next page. Returns null if there are no more results.

    " + } + } + }, "ListIterableFormsRequest":{ "type":"structure", "required":[ @@ -22029,7 +22656,7 @@ }, "TableName":{ "shape":"NameString", - "documentation":"

    The name of the table for which statistics is generated.

    " + "documentation":"

    The name of the materialized view.

    " }, "MaxResults":{ "shape":"PageSize", @@ -22673,7 +23300,10 @@ "MaterializedViewRefreshTaskNotRunningException":{ "type":"structure", "members":{ - "Message":{"shape":"MessageString"} + "Message":{ + "shape":"MessageString", + "documentation":"

    A message describing the problem.

    " + } }, "documentation":"

    Exception thrown when stopping a task that is not in running state.

    ", "exception":true @@ -22695,7 +23325,7 @@ }, "TableName":{ "shape":"TableName", - "documentation":"

    The name of the table for which statistics is generated.

    " + "documentation":"

    The name of the materialized view.

    " }, "CatalogId":{ "shape":"CatalogIdString", @@ -22703,7 +23333,7 @@ }, "Role":{ "shape":"Role", - "documentation":"

    The IAM role that the service assumes to generate statistics.

    " + "documentation":"

    The IAM role that the service assumes to run the materialized view refresh task.

    " }, "Status":{ "shape":"MaterializedViewRefreshState", @@ -22747,7 +23377,10 @@ "MaterializedViewRefreshTaskRunningException":{ "type":"structure", "members":{ - "Message":{"shape":"MessageString"} + "Message":{ + "shape":"MessageString", + "documentation":"

    A message describing the problem.

    " + } }, "documentation":"

    Exception thrown when a task is already in running state.

    ", "exception":true @@ -22759,7 +23392,10 @@ "MaterializedViewRefreshTaskStoppingException":{ "type":"structure", "members":{ - "Message":{"shape":"MessageString"} + "Message":{ + "shape":"MessageString", + "documentation":"

    A message describing the problem.

    " + } }, "documentation":"

    Exception thrown when a task is already in stopping state.

    ", "exception":true @@ -23291,6 +23927,10 @@ "type":"integer", "box":true }, + "NullableLong":{ + "type":"long", + "box":true + }, "NullableString":{ "type":"string", "box":true @@ -23392,6 +24032,34 @@ }, "documentation":"

    A structure containing properties for OAuth2 in the CreateConnection request.

    " }, + "ObservationConfiguration":{ + "type":"string", + "enum":[ + "ALL", + "NONE" + ] + }, + "ObservationMode":{ + "type":"string", + "enum":[ + "SCHEDULED", + "FIXED" + ] + }, + "ObservationResultsOptions":{ + "type":"structure", + "members":{ + "WriteObservationResultsEnabled":{ + "shape":"NullableBoolean", + "documentation":"

    Set to true to write observation results.

    " + }, + "CatalogTableConfig":{ + "shape":"CatalogTableConfigOptions", + "documentation":"

    The Glue Data Catalog table configuration for storing the observation results.

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

    The configuration for writing observation results.

    " + }, "OffsetConfiguration":{ "type":"structure", "required":[ @@ -24242,6 +24910,24 @@ }, "documentation":"

    Specifies the job and session values that an admin configures in an Glue usage profile.

    " }, + "ProfilingResultsOptions":{ + "type":"structure", + "members":{ + "WriteProfilingResultsEnabled":{ + "shape":"NullableBoolean", + "documentation":"

    Set to true to write profiling results.

    " + }, + "CatalogTableConfig":{ + "shape":"CatalogTableConfigOptions", + "documentation":"

    The Glue Data Catalog table configuration for storing the profiling results.

    " + }, + "DistributionResults":{ + "shape":"DistributionResultsOptions", + "documentation":"

    The configuration for writing distribution results.

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

    The configuration for writing profiling results.

    " + }, "PropertiesMap":{ "type":"map", "key":{"shape":"PropertyName"}, @@ -24558,6 +25244,39 @@ "type":"structure", "members":{} }, + "PutDataCatalogExportConfigurationInput":{ + "type":"structure", + "required":["ExportSetting"], + "members":{ + "ExportSetting":{ + "shape":"ExportSetting", + "documentation":"

    The export setting for the data catalog. Specify ENABLED to start exporting catalog metadata to S3 Tables, or DISABLED to stop exporting. This field is required.

    " + }, + "EncryptionConfiguration":{ + "shape":"ExportEncryptionConfiguration", + "documentation":"

    The encryption configuration for the exported data. If not specified, the default encryption settings are used.

    " + }, + "ClientToken":{ + "shape":"HashString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + } + } + }, + "PutDataCatalogExportConfigurationOutput":{ + "type":"structure", + "members":{ + "ExportSetting":{ + "shape":"ExportSetting", + "documentation":"

    The export setting for the data catalog.

    " + }, + "EncryptionConfiguration":{ + "shape":"ExportEncryptionConfiguration", + "documentation":"

    The encryption configuration for the exported data.

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

    The export configuration returned by the PutDataCatalogExportConfiguration operation.

    " + }, "PutDataQualityProfileAnnotationRequest":{ "type":"structure", "required":[ @@ -24913,6 +25632,14 @@ "max":16, "min":1 }, + "RecommendationMode":{ + "type":"string", + "documentation":"

    Specifies the mode for how Glue Data Quality recommends rules.

    • BASIC uses an Glue job to analyze table data and recommend rules. This value is the default.

    • ADVANCED uses Amazon Athena to analyze table data and Amazon Bedrock to recommend rules.

    ", + "enum":[ + "BASIC", + "ADVANCED" + ] + }, "Record":{ "type":"structure", "members":{}, @@ -25443,6 +26170,14 @@ }, "documentation":"

    Configuration that defines HTTP request and response handling, validation endpoints, and entity configurations for REST API interactions.

    " }, + "ResultTypeEnum":{ + "type":"string", + "enum":[ + "ALL", + "PASSED_ONLY", + "FAILED_ONLY" + ] + }, "ResumeWorkflowRunRequest":{ "type":"structure", "required":[ @@ -25527,6 +26262,24 @@ }, "documentation":"

    Specifies a route node that directs data to different output paths based on defined filtering conditions.

    " }, + "RowLevelResultsOptions":{ + "type":"structure", + "members":{ + "MaxRowsToWrite":{ + "shape":"NullableInteger", + "documentation":"

    The maximum number of rows to write in the results.

    " + }, + "ResultType":{ + "shape":"ResultTypeEnum", + "documentation":"

    The result type to include in the row-level results output.

    " + }, + "CatalogTableConfig":{ + "shape":"CatalogTableConfigOptions", + "documentation":"

    The Glue Data Catalog table configuration for storing the results.

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

    The configuration for writing row-level evaluation results.

    " + }, "RowTag":{"type":"string"}, "RuleMetricsMap":{ "type":"map", @@ -26608,6 +27361,7 @@ }, "documentation":"

    Specifies additional connection options for the Amazon S3 data store.

    " }, + "S3TableBucketArn":{"type":"string"}, "S3Target":{ "type":"structure", "members":{ @@ -26972,7 +27726,8 @@ "shape":"SearchNextToken", "documentation":"

    A continuation token, present if the current segment is not the last.

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

    The search results returned by the SearchAssets operation.

    " }, "SearchAttribute":{ "type":"string", @@ -27739,6 +28494,10 @@ "PaginationConfiguration":{ "shape":"PaginationConfiguration", "documentation":"

    Configuration for handling paginated responses from the REST API, supporting both cursor-based and offset-based pagination strategies.

    " + }, + "FilterConfiguration":{ + "shape":"FilterConfiguration", + "documentation":"

    Configuration for applying filter pushdown to REST API requests, defining how filter predicates are translated into query parameters or filter strings.

    " } }, "documentation":"

    Configuration that defines how to make requests to endpoints, including request methods, paths, parameters, and response handling.

    " @@ -27915,6 +28674,23 @@ }, "documentation":"

    Specifies a target that uses an Apache Spark connector.

    " }, + "SparkPipelineInfoKey":{ + "type":"string", + "max":128, + "min":1 + }, + "SparkPipelineInfoMap":{ + "type":"map", + "key":{"shape":"SparkPipelineInfoKey"}, + "value":{"shape":"SparkPipelineInfoValue"}, + "max":50, + "min":0 + }, + "SparkPipelineInfoValue":{ + "type":"string", + "max":2048, + "min":0 + }, "SparkSQL":{ "type":"structure", "required":[ @@ -28027,6 +28803,7 @@ "type":"string", "pattern":"([\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDC00-\\uDBFF\\uDFFF\\s])*" }, + "SseAlgorithm":{"type":"string"}, "StartBlueprintRunRequest":{ "type":"structure", "required":[ @@ -28166,7 +28943,7 @@ }, "Role":{ "shape":"RoleString", - "documentation":"

    An IAM role supplied to encrypt the results of the run.

    " + "documentation":"

    The IAM role that Glue assumes to access resources for the run.

    For more information, see Configure IAM permissions for Glue Data Quality.

    " }, "NumberOfWorkers":{ "shape":"NullableInteger", @@ -28187,6 +28964,14 @@ "ClientToken":{ "shape":"HashString", "documentation":"

    Used for idempotency and is recommended to be set to a random ID (such as a UUID) to avoid creating or starting multiple instances of the same resource.

    " + }, + "AdditionalRunOptions":{ + "shape":"DataQualityRuleRecommendationRunAdditionalRunOptions", + "documentation":"

    Additional run options you can specify for a recommendation run.

    " + }, + "RecommendationMode":{ + "shape":"RecommendationMode", + "documentation":"

    The mode that Glue Data Quality uses to recommend rules.

    The default is BASIC.

    " } }, "documentation":"

    The request of the Data Quality rule recommendation request.

    " @@ -28439,7 +29224,7 @@ }, "TableName":{ "shape":"NameString", - "documentation":"

    The name of the table to generate run the materialized view refresh task.

    " + "documentation":"

    The name of the materialized view to run the refresh task for.

    " }, "FullRefresh":{ "shape":"NullableBoolean", @@ -28709,6 +29494,10 @@ "shape":"double", "documentation":"

    The value of the statistic.

    " }, + "DistributionValue":{ + "shape":"DistributionData", + "documentation":"

    The distribution value for the statistic.

    " + }, "EvaluationLevel":{ "shape":"StatisticEvaluationLevel", "documentation":"

    The evaluation level of the statistic. Possible values: Dataset, Column, Multicolumn.

    " @@ -28843,7 +29632,7 @@ }, "TableName":{ "shape":"NameString", - "documentation":"

    The name of the table to generate statistics.

    " + "documentation":"

    The name of the materialized view.

    " } } }, @@ -28991,11 +29780,6 @@ "documentation":"

    Specifies options related to data preview for viewing a sample of your data.

    " }, "String":{"type":"string"}, - "String1024":{ - "type":"string", - "max":1024, - "min":1 - }, "String128":{ "type":"string", "max":128, @@ -29006,6 +29790,11 @@ "max":2048, "min":1 }, + "String4096":{ + "type":"string", + "max":4096, + "min":1 + }, "String512":{ "type":"string", "max":512, @@ -29048,6 +29837,49 @@ "key":{"shape":"NullableString"}, "value":{"shape":"NullableString"} }, + "SubObjectSourceType":{ + "type":"string", + "enum":[ + "HIVE_PARQUET", + "HIVE_ORC", + "HIVE_CSV", + "HIVE_JSON", + "PLAIN_PARQUET", + "ICEBERG" + ] + }, + "SubObjectStatistics":{ + "type":"structure", + "members":{ + "SourceType":{ + "shape":"SubObjectSourceType", + "documentation":"

    The source type of the sub-object (for example, its table format), which identifies the sub-object.

    " + }, + "GlueVersionId":{ + "shape":"NullableString", + "documentation":"

    The Glue version ID of the sub-object that the statistics were captured for.

    " + }, + "PartitionCount":{ + "shape":"NullableLong", + "documentation":"

    The number of sub-object partitions selected for that refresh. Not present for unpartitioned sub-objects.

    " + }, + "FileCount":{ + "shape":"NullableLong", + "documentation":"

    The number of sub-object data files selected for that refresh.

    " + }, + "TotalFileBytes":{ + "shape":"NullableLong", + "documentation":"

    The total size, in bytes, of the data files counted by FileCount.

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

    Statistics for one sub-object referenced by a materialized view, recorded when the materialized view was created or last fully refreshed. These values describe what that refresh selected from the sub-object, which can be a subset of the table when the materialized view's definition limits the data it reads. The fields present depend on the sub-object's format.

    " + }, + "SubObjectsStatisticsList":{ + "type":"list", + "member":{"shape":"SubObjectStatistics"}, + "max":250, + "min":0 + }, "SupportedDialect":{ "type":"structure", "members":{ @@ -29651,6 +30483,10 @@ "TargetTableName":{ "shape":"String128", "documentation":"

    The optional name of a target table.

    " + }, + "IntegrationArn":{ + "shape":"String128", + "documentation":"

    The ARN of the integration that owns this target table configuration.

    " } }, "documentation":"

    Properties used by the target leg to partition the data on the target.

    " @@ -31821,9 +32657,17 @@ "shape":"ViewSubObjectVersionIdsList", "documentation":"

    List of the Apache Iceberg table versions referenced by the materialized view.

    " }, + "SubObjectsStatistics":{ + "shape":"SubObjectsStatisticsList", + "documentation":"

    Statistics captured for each sub-object referenced by the materialized view as of its most recent refresh, such as the source type, Glue version ID, and the partition, file, and byte counts. Each entry describes one sub-object, identified by its source type.

    " + }, "Representations":{ "shape":"ViewRepresentationList", "documentation":"

    A list of representations.

    " + }, + "SparkPipelineInfo":{ + "shape":"SparkPipelineInfoMap", + "documentation":"

    A map of key-value pairs containing Spark Declarative Pipelines (SDP) information for the materialized view.

    " } }, "documentation":"

    A structure containing details for representations.

    " @@ -31866,6 +32710,14 @@ "SubObjectVersionIds":{ "shape":"ViewSubObjectVersionIdsList", "documentation":"

    List of the Apache Iceberg table versions referenced by the materialized view.

    " + }, + "SubObjectsStatistics":{ + "shape":"SubObjectsStatisticsList", + "documentation":"

    Statistics for each sub-object referenced by the materialized view, such as the source type, Glue version ID, and the partition, file, and byte counts. Each entry describes one sub-object, identified by its source type.

    " + }, + "SparkPipelineInfo":{ + "shape":"SparkPipelineInfoMap", + "documentation":"

    A map of key-value pairs containing Spark Declarative Pipelines (SDP) information for the materialized view.

    " } }, "documentation":"

    A structure containing details for creating or updating an Glue view.

    " diff --git a/services/grafana/pom.xml b/services/grafana/pom.xml index f76d913cd77e..c928c07ec624 100644 --- a/services/grafana/pom.xml +++ b/services/grafana/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT grafana AWS Java SDK :: Services :: Grafana diff --git a/services/grafana/src/main/resources/codegen-resources/customization.config b/services/grafana/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/grafana/src/main/resources/codegen-resources/customization.config +++ b/services/grafana/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/grafana/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/grafana/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..564ffe1716bf --- /dev/null +++ b/services/grafana/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://grafana-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://grafana-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://grafana.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://grafana.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/grafana/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/grafana/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index dbcccf763641..000000000000 --- a/services/grafana/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://grafana-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://grafana-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://grafana.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://grafana.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/greengrass/pom.xml b/services/greengrass/pom.xml index 667834d7c79f..f16e766e742f 100644 --- a/services/greengrass/pom.xml +++ b/services/greengrass/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT greengrass AWS Java SDK :: Services :: AWS Greengrass diff --git a/services/greengrass/src/main/resources/codegen-resources/customization.config b/services/greengrass/src/main/resources/codegen-resources/customization.config index 96ee6ad2eca2..3bfe9fa9ed42 100644 --- a/services/greengrass/src/main/resources/codegen-resources/customization.config +++ b/services/greengrass/src/main/resources/codegen-resources/customization.config @@ -23,6 +23,5 @@ "createSubscriptionDefinition", "createResourceDefinition", "createSoftwareUpdateJob" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/greengrass/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/greengrass/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1e4f3c5c916a --- /dev/null +++ b/services/greengrass/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,276 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "dataplane-us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "dataplane-us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-ats.iot.us-gov-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "greengrass", + "signingRegion": "us-gov-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-ats.iot.us-gov-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "greengrass", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAACQX14QwAAAAIAAAACgX14Q0F9eEOAAAABQX14QoF9eELAAAABAAAAA4AAAALAAAABgAAAAwF9eEJAAAABwX14QYAAAANAAAACAX14QcF9eEIAAAABQAAAA8F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/greengrass/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/greengrass/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e4cc3e4d9c34..000000000000 --- a/services/greengrass/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,406 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://greengrass-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://greengrass-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://greengrass.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "dataplane-us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass-ats.iot.us-gov-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "greengrass", - "signingRegion": "us-gov-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "dataplane-us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass-ats.iot.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "greengrass", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://greengrass.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/greengrassv2/pom.xml b/services/greengrassv2/pom.xml index 55996047f67f..6bac6b22aeef 100644 --- a/services/greengrassv2/pom.xml +++ b/services/greengrassv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT greengrassv2 AWS Java SDK :: Services :: Greengrass V2 diff --git a/services/greengrassv2/src/main/resources/codegen-resources/customization.config b/services/greengrassv2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/greengrassv2/src/main/resources/codegen-resources/customization.config +++ b/services/greengrassv2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/greengrassv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/greengrassv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1e4f3c5c916a --- /dev/null +++ b/services/greengrassv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,276 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "dataplane-us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "dataplane-us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-ats.iot.us-gov-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "greengrass", + "signingRegion": "us-gov-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass-ats.iot.us-gov-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "greengrass", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://greengrass.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAACQX14QwAAAAIAAAACgX14Q0F9eEOAAAABQX14QoF9eELAAAABAAAAA4AAAALAAAABgAAAAwF9eEJAAAABwX14QYAAAANAAAACAX14QcF9eEIAAAABQAAAA8F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/greengrassv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/greengrassv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e4cc3e4d9c34..000000000000 --- a/services/greengrassv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,406 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://greengrass-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://greengrass-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://greengrass.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "dataplane-us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass-ats.iot.us-gov-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "greengrass", - "signingRegion": "us-gov-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "dataplane-us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://greengrass-ats.iot.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "greengrass", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://greengrass.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/groundstation/pom.xml b/services/groundstation/pom.xml index fd6513196c5d..3db9e9eb45d2 100644 --- a/services/groundstation/pom.xml +++ b/services/groundstation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT groundstation AWS Java SDK :: Services :: GroundStation diff --git a/services/groundstation/src/main/resources/codegen-resources/customization.config b/services/groundstation/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/groundstation/src/main/resources/codegen-resources/customization.config +++ b/services/groundstation/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/groundstation/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/groundstation/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b2919a6d77ec --- /dev/null +++ b/services/groundstation/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://groundstation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://groundstation-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://groundstation.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://groundstation.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/groundstation/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/groundstation/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 333c154071f2..000000000000 --- a/services/groundstation/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://groundstation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://groundstation-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://groundstation.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://groundstation.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/guardduty/pom.xml b/services/guardduty/pom.xml index c52dcf7c6395..745a6af87838 100644 --- a/services/guardduty/pom.xml +++ b/services/guardduty/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 guardduty diff --git a/services/guardduty/src/main/resources/codegen-resources/customization.config b/services/guardduty/src/main/resources/codegen-resources/customization.config index eddcd509d138..2a0f8b4cc9ac 100644 --- a/services/guardduty/src/main/resources/codegen-resources/customization.config +++ b/services/guardduty/src/main/resources/codegen-resources/customization.config @@ -8,6 +8,5 @@ "createDetector", "declineInvitations", "deleteInvitations" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/guardduty/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/guardduty/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3b6783d863ea --- /dev/null +++ b/services/guardduty/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://guardduty-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://guardduty.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://guardduty-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://guardduty.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://guardduty.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/guardduty/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/guardduty/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1da1e8280883..000000000000 --- a/services/guardduty/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://guardduty-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://guardduty.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://guardduty-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://guardduty.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://guardduty.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/guardduty/src/main/resources/codegen-resources/paginators-1.json b/services/guardduty/src/main/resources/codegen-resources/paginators-1.json index ce9f16542a1c..ac5faf2f918e 100644 --- a/services/guardduty/src/main/resources/codegen-resources/paginators-1.json +++ b/services/guardduty/src/main/resources/codegen-resources/paginators-1.json @@ -22,6 +22,24 @@ "limit_key": "MaxResults", "result_key": "Resources" }, + "ListCustomDetectionRuleAssociations": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "RuleAssociations" + }, + "ListCustomDetectionRuleOrgConfigurations": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Configurations" + }, + "ListCustomDetectionRules": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Rules" + }, "ListDetectors": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/guardduty/src/main/resources/codegen-resources/service-2.json b/services/guardduty/src/main/resources/codegen-resources/service-2.json index 2c77e634e653..ff20a4ac8f58 100644 --- a/services/guardduty/src/main/resources/codegen-resources/service-2.json +++ b/services/guardduty/src/main/resources/codegen-resources/service-2.json @@ -60,6 +60,42 @@ ], "documentation":"

    Archives GuardDuty findings that are specified by the list of finding IDs.

    Only the administrator account can archive findings. Member accounts don't have permission to archive findings from their accounts.

    " }, + "CreateCustomDetectionRuleAssociation":{ + "name":"CreateCustomDetectionRuleAssociation", + "http":{ + "method":"POST", + "requestUri":"/custom-detection-rule/association", + "responseCode":200 + }, + "input":{"shape":"CreateCustomDetectionRuleAssociationRequest"}, + "output":{"shape":"CreateCustomDetectionRuleAssociationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Enables a custom detection rule for your account by creating an association. You specify the rule and the mode in which it operates.

    " + }, + "CreateCustomDetectionRuleOrgConfiguration":{ + "name":"CreateCustomDetectionRuleOrgConfiguration", + "http":{ + "method":"POST", + "requestUri":"/custom-detection-rule/org-configuration", + "responseCode":200 + }, + "input":{"shape":"CreateCustomDetectionRuleOrgConfigurationRequest"}, + "output":{"shape":"CreateCustomDetectionRuleOrgConfigurationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates an organization-level configuration that enables a custom detection rule across your organization. This operation is available only to the delegated administrator account.

    " + }, "CreateDetector":{ "name":"CreateDetector", "http":{ @@ -245,6 +281,43 @@ ], "documentation":"

    Declines invitations sent to the current member account by Amazon Web Services accounts specified by their account IDs.

    " }, + "DeleteCustomDetectionRuleAssociation":{ + "name":"DeleteCustomDetectionRuleAssociation", + "http":{ + "method":"DELETE", + "requestUri":"/custom-detection-rule/rule/{RuleId}/association/{AssociationId}", + "responseCode":200 + }, + "input":{"shape":"DeleteCustomDetectionRuleAssociationRequest"}, + "output":{"shape":"DeleteCustomDetectionRuleAssociationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Disables a custom detection rule by deleting its association. This operation is idempotent.

    ", + "idempotent":true + }, + "DeleteCustomDetectionRuleOrgConfiguration":{ + "name":"DeleteCustomDetectionRuleOrgConfiguration", + "http":{ + "method":"DELETE", + "requestUri":"/custom-detection-rule/org-configuration/{RuleId}", + "responseCode":200 + }, + "input":{"shape":"DeleteCustomDetectionRuleOrgConfigurationRequest"}, + "output":{"shape":"DeleteCustomDetectionRuleOrgConfigurationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Deletes the organization-level configuration for a custom detection rule. This operation is available only to the delegated administrator account.

    ", + "idempotent":true + }, "DeleteDetector":{ "name":"DeleteDetector", "http":{ @@ -548,6 +621,60 @@ ], "documentation":"

    Retrieves aggregated statistics for your account. If you are a GuardDuty administrator, you can retrieve the statistics for all the resources associated with the active member accounts in your organization who have enabled Runtime Monitoring and have the GuardDuty security agent running on their resources.

    " }, + "GetCustomDetectionRule":{ + "name":"GetCustomDetectionRule", + "http":{ + "method":"GET", + "requestUri":"/custom-detection-rule/rule/{RuleId}", + "responseCode":200 + }, + "input":{"shape":"GetCustomDetectionRuleRequest"}, + "output":{"shape":"GetCustomDetectionRuleResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns details for a custom detection rule in GuardDuty, including its detection logic.

    ", + "readonly":true + }, + "GetCustomDetectionRuleAssociation":{ + "name":"GetCustomDetectionRuleAssociation", + "http":{ + "method":"GET", + "requestUri":"/custom-detection-rule/rule/{RuleId}/association/{AssociationId}", + "responseCode":200 + }, + "input":{"shape":"GetCustomDetectionRuleAssociationRequest"}, + "output":{"shape":"GetCustomDetectionRuleAssociationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns details for a custom detection rule association.

    ", + "readonly":true + }, + "GetCustomDetectionRuleOrgConfiguration":{ + "name":"GetCustomDetectionRuleOrgConfiguration", + "http":{ + "method":"GET", + "requestUri":"/custom-detection-rule/org-configuration/{RuleId}", + "responseCode":200 + }, + "input":{"shape":"GetCustomDetectionRuleOrgConfigurationRequest"}, + "output":{"shape":"GetCustomDetectionRuleOrgConfigurationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns the organization-level configuration for a custom detection rule.

    ", + "readonly":true + }, "GetDetector":{ "name":"GetDetector", "http":{ @@ -869,6 +996,57 @@ ], "documentation":"

    Lists coverage details for your GuardDuty account. If you're a GuardDuty administrator, you can retrieve all resources associated with the active member accounts in your organization.

    Make sure the accounts have Runtime Monitoring enabled and GuardDuty agent running on their resources.

    " }, + "ListCustomDetectionRuleAssociations":{ + "name":"ListCustomDetectionRuleAssociations", + "http":{ + "method":"GET", + "requestUri":"/custom-detection-rule/association", + "responseCode":200 + }, + "input":{"shape":"ListCustomDetectionRuleAssociationsRequest"}, + "output":{"shape":"ListCustomDetectionRuleAssociationsResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns all custom detection rule associations for your account. You can filter by rule ID and mode.

    ", + "readonly":true + }, + "ListCustomDetectionRuleOrgConfigurations":{ + "name":"ListCustomDetectionRuleOrgConfigurations", + "http":{ + "method":"GET", + "requestUri":"/custom-detection-rule/org-configuration", + "responseCode":200 + }, + "input":{"shape":"ListCustomDetectionRuleOrgConfigurationsRequest"}, + "output":{"shape":"ListCustomDetectionRuleOrgConfigurationsResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns all organization-level configurations for custom detection rules. You can filter the results by status.

    ", + "readonly":true + }, + "ListCustomDetectionRules":{ + "name":"ListCustomDetectionRules", + "http":{ + "method":"POST", + "requestUri":"/custom-detection-rule/rule", + "responseCode":200 + }, + "input":{"shape":"ListCustomDetectionRulesRequest"}, + "output":{"shape":"ListCustomDetectionRulesResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns all available custom detection rules in GuardDuty. You can filter the results by data source, severity, tactic, technique, and service.

    ", + "readonly":true + }, "ListDetectors":{ "name":"ListDetectors", "http":{ @@ -1206,6 +1384,44 @@ ], "documentation":"

    Removes tags from a resource.

    " }, + "UpdateCustomDetectionRuleAssociation":{ + "name":"UpdateCustomDetectionRuleAssociation", + "http":{ + "method":"PUT", + "requestUri":"/custom-detection-rule/rule/{RuleId}/association/{AssociationId}", + "responseCode":200 + }, + "input":{"shape":"UpdateCustomDetectionRuleAssociationRequest"}, + "output":{"shape":"UpdateCustomDetectionRuleAssociationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the mode of an existing custom detection rule association.

    ", + "idempotent":true + }, + "UpdateCustomDetectionRuleOrgConfiguration":{ + "name":"UpdateCustomDetectionRuleOrgConfiguration", + "http":{ + "method":"PUT", + "requestUri":"/custom-detection-rule/org-configuration/{RuleId}", + "responseCode":200 + }, + "input":{"shape":"UpdateCustomDetectionRuleOrgConfigurationRequest"}, + "output":{"shape":"UpdateCustomDetectionRuleOrgConfigurationResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"InternalServerErrorException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the organization-level configuration for a custom detection rule, including the mode and include/exclude account lists.

    ", + "idempotent":true + }, "UpdateDetector":{ "name":"UpdateDetector", "http":{ @@ -1708,6 +1924,35 @@ }, "documentation":"

    Contains information about actions.

    " }, + "Activities":{ + "type":"list", + "member":{"shape":"Activity"}, + "documentation":"

    A list of activities that were observed for a signal.

    ", + "max":100, + "min":0 + }, + "Activity":{ + "type":"structure", + "required":["Type"], + "members":{ + "Type":{ + "shape":"ActivityType", + "documentation":"

    The type of the observed activity.

    ", + "locationName":"type" + }, + "Api":{ + "shape":"ApiCall", + "documentation":"

    Contains information about the API call that was observed, when the activity type is API_CALL.

    ", + "locationName":"api" + } + }, + "documentation":"

    Contains information about an activity, such as an API call, that was observed for a signal.

    " + }, + "ActivityType":{ + "type":"string", + "documentation":"

    The type of an observed activity.

    ", + "enum":["API_CALL"] + }, "Actor":{ "type":"structure", "required":["Id"], @@ -1948,6 +2193,52 @@ "key":{"shape":"String"}, "value":{"shape":"AnomalyObject"} }, + "ApiCall":{ + "type":"structure", + "members":{ + "Operation":{ + "shape":"ApiCallOperationString", + "documentation":"

    The name of the API operation that was invoked.

    ", + "locationName":"operation" + }, + "Service":{ + "shape":"ApiCallServiceString", + "documentation":"

    The service that the API operation was invoked against.

    ", + "locationName":"service" + }, + "Error":{ + "shape":"ApiCallErrorString", + "documentation":"

    The error code that was returned, if the API call failed.

    ", + "locationName":"error" + }, + "UserAgent":{ + "shape":"ApiCallUserAgentString", + "documentation":"

    User agent in the request to the API operation

    ", + "locationName":"userAgent" + } + }, + "documentation":"

    Contains information about an API call that was observed as part of an activity.

    " + }, + "ApiCallErrorString":{ + "type":"string", + "max":512, + "min":0 + }, + "ApiCallOperationString":{ + "type":"string", + "max":512, + "min":0 + }, + "ApiCallServiceString":{ + "type":"string", + "max":512, + "min":0 + }, + "ApiCallUserAgentString":{ + "type":"string", + "max":1024, + "min":0 + }, "ArchiveFindingsRequest":{ "type":"structure", "required":[ @@ -1972,6 +2263,127 @@ "type":"structure", "members":{} }, + "AssociationDetail":{ + "type":"structure", + "required":[ + "AssociationId", + "Arn", + "RuleId", + "AccountId", + "Mode", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "AssociationId":{ + "shape":"AssociationId", + "documentation":"

    The unique identifier for the association.

    ", + "locationName":"associationId" + }, + "Arn":{ + "shape":"DetectionRuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the association.

    ", + "locationName":"arn" + }, + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "AccountId":{ + "shape":"AccountId", + "documentation":"

    The Amazon Web Services account ID associated with this rule association.

    ", + "locationName":"accountId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association was last updated.

    ", + "locationName":"updatedAt" + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association expires.

    ", + "locationName":"expiresAt" + } + }, + "documentation":"

    Contains the full details of a custom detection rule association.

    " + }, + "AssociationId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]{1,64}" + }, + "AssociationMode":{ + "type":"string", + "enum":[ + "LIVE", + "DRY_RUN" + ] + }, + "AssociationSummary":{ + "type":"structure", + "required":[ + "AssociationId", + "Arn", + "RuleId", + "Mode", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "AssociationId":{ + "shape":"AssociationId", + "documentation":"

    The unique identifier for the association.

    ", + "locationName":"associationId" + }, + "Arn":{ + "shape":"DetectionRuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the association.

    ", + "locationName":"arn" + }, + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association was last updated.

    ", + "locationName":"updatedAt" + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the association expires.

    ", + "locationName":"expiresAt" + } + }, + "documentation":"

    Contains summary information about a custom detection rule association.

    " + }, + "AssociationSummaryList":{ + "type":"list", + "member":{"shape":"AssociationSummary"} + }, "AutoEnableMembers":{ "type":"string", "enum":[ @@ -2083,6 +2495,121 @@ }, "exception":true }, + "BedrockGuardrail":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"BedrockGuardrailArnString", + "documentation":"

    The ARN of the Bedrock guardrail.

    ", + "locationName":"arn" + }, + "Version":{ + "shape":"BedrockGuardrailVersionString", + "documentation":"

    The version of the Bedrock guardrail.

    ", + "locationName":"version" + } + }, + "documentation":"

    Contains information about a Bedrock guardrail associated with a finding.

    " + }, + "BedrockGuardrailArnString":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:aws(-[^:]+)?:bedrock:[a-z0-9-]{1,20}:[0-9]{12}:guardrail/[a-z0-9]+" + }, + "BedrockGuardrailDetails":{ + "type":"structure", + "members":{ + "GuardrailArn":{ + "shape":"BedrockGuardrailDetailsGuardrailArnString", + "documentation":"

    The ARN of the Bedrock guardrail. This field is deprecated. Use the guardrails list instead.

    ", + "deprecated":true, + "deprecatedMessage":"Use guardrails list instead", + "deprecatedSince":"2026-07-13", + "locationName":"guardrailArn" + }, + "GuardrailVersion":{ + "shape":"BedrockGuardrailDetailsGuardrailVersionString", + "documentation":"

    The version of the Bedrock guardrail. This field is deprecated. Use the guardrails list instead.

    ", + "deprecated":true, + "deprecatedMessage":"Use guardrails list instead", + "deprecatedSince":"2026-07-13", + "locationName":"guardrailVersion" + }, + "Guardrails":{ + "shape":"BedrockGuardrails", + "documentation":"

    The list of Bedrock guardrails associated with the finding.

    ", + "locationName":"guardrails" + }, + "GuardrailAction":{ + "shape":"GuardrailAction", + "documentation":"

    Indicates whether the guardrail intervened or not.

    ", + "locationName":"guardrailAction" + }, + "GuardrailSource":{ + "shape":"GuardrailSource", + "documentation":"

    Indicates whether the guardrail was applied on the input or output of the model invocation.

    ", + "locationName":"guardrailSource" + }, + "ContentPolicyFilters":{ + "shape":"ContentPolicyFilters", + "documentation":"

    The list of content policy filters that matched during the guardrail evaluation.

    ", + "locationName":"contentPolicyFilters" + } + }, + "documentation":"

    Contains information about the Bedrock guardrail that was involved in a finding.

    " + }, + "BedrockGuardrailDetailsGuardrailArnString":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:aws(-[^:]+)?:bedrock:[a-z0-9-]{1,20}:[0-9]{12}:guardrail/[a-z0-9]+" + }, + "BedrockGuardrailDetailsGuardrailVersionString":{ + "type":"string", + "max":8, + "min":1, + "pattern":"(([1-9][0-9]{0,7})|(DRAFT))" + }, + "BedrockGuardrailResource":{ + "type":"structure", + "members":{ + "Version":{ + "shape":"BedrockGuardrailResourceVersionString", + "documentation":"

    The version of the Amazon Bedrock guardrail. Valid values are a numeric version, DRAFT, or ENFORCED.

    ", + "locationName":"version" + }, + "GuardrailAction":{ + "shape":"GuardrailAction", + "documentation":"

    Indicates whether the guardrail intervened during the model invocation.

    ", + "locationName":"guardrailAction" + }, + "GuardrailSource":{ + "shape":"GuardrailSource", + "documentation":"

    Indicates whether the guardrail was applied on the input or output of the model invocation.

    ", + "locationName":"guardrailSource" + } + }, + "documentation":"

    Contains details about an Amazon Bedrock guardrail evaluated during a model invocation.

    " + }, + "BedrockGuardrailResourceVersionString":{ + "type":"string", + "max":8, + "min":1, + "pattern":"(([1-9][0-9]{0,7})|(DRAFT)|(ENFORCED))" + }, + "BedrockGuardrailVersionString":{ + "type":"string", + "max":8, + "min":1, + "pattern":"(([1-9][0-9]{0,7})|(DRAFT)|(ENFORCED))" + }, + "BedrockGuardrails":{ + "type":"list", + "member":{"shape":"BedrockGuardrail"}, + "max":10, + "min":0 + }, "Behavior":{ "type":"map", "key":{"shape":"String"}, @@ -2330,6 +2857,15 @@ "max":50, "min":1 }, + "ConfidenceLevel":{ + "type":"string", + "enum":[ + "HIGH", + "MEDIUM", + "LOW", + "NONE" + ] + }, "ConflictException":{ "type":"structure", "members":{ @@ -2439,9 +2975,55 @@ "type":"list", "member":{"shape":"ContainerUid"} }, - "Containers":{ + "Containers":{ + "type":"list", + "member":{"shape":"Container"} + }, + "ContentPolicyFilter":{ + "type":"structure", + "members":{ + "Type":{ + "shape":"ContentPolicyFilterType", + "documentation":"

    The type of content that was filtered by the guardrail.

    ", + "locationName":"type" + }, + "Confidence":{ + "shape":"ConfidenceLevel", + "documentation":"

    The confidence level that the content matched the filter.

    ", + "locationName":"confidence" + }, + "Action":{ + "shape":"ContentPolicyFilterAction", + "documentation":"

    The action taken by the guardrail filter.

    ", + "locationName":"action" + } + }, + "documentation":"

    Contains information about a content policy filter that matched during a guardrail evaluation.

    " + }, + "ContentPolicyFilterAction":{ + "type":"string", + "enum":[ + "BLOCKED", + "NONE" + ] + }, + "ContentPolicyFilterType":{ + "type":"string", + "enum":[ + "PROMPT_ATTACK", + "JAILBREAK", + "HATE", + "INSULTS", + "SEXUAL", + "VIOLENCE", + "MISCONDUCT" + ] + }, + "ContentPolicyFilters":{ "type":"list", - "member":{"shape":"Container"} + "member":{"shape":"ContentPolicyFilter"}, + "max":10, + "min":0 }, "ContinuousScanDetails":{ "type":"structure", @@ -2774,6 +3356,86 @@ "UNHEALTHY" ] }, + "CreateCustomDetectionRuleAssociationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. Maximum 64 characters.

    ", + "idempotencyToken":true, + "locationName":"clientToken" + }, + "Tags":{ + "shape":"TagMap", + "documentation":"

    The tags to be added to the new custom detection rule association resource.

    ", + "locationName":"tags" + } + } + }, + "CreateCustomDetectionRuleAssociationResponse":{ + "type":"structure", + "required":["RuleAssociation"], + "members":{ + "RuleAssociation":{ + "shape":"AssociationDetail", + "documentation":"

    The details of the newly created custom detection rule association.

    ", + "locationName":"ruleAssociation" + } + } + }, + "CreateCustomDetectionRuleOrgConfigurationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The execution mode of the organization configuration. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "IncludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    The account IDs to include in the organization configuration. Mutually exclusive with ExcludeAccountIds.

    ", + "locationName":"includeAccountIds" + }, + "ExcludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    The account IDs to exclude from the organization configuration. Mutually exclusive with IncludeAccountIds.

    ", + "locationName":"excludeAccountIds" + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time.

    ", + "idempotencyToken":true, + "locationName":"clientToken" + } + } + }, + "CreateCustomDetectionRuleOrgConfigurationResponse":{ + "type":"structure", + "members":{} + }, "CreateDetectorRequest":{ "type":"structure", "required":["Enable"], @@ -3587,6 +4249,56 @@ }, "documentation":"

    Contains information on the server side encryption method used in the S3 bucket. See S3 Server-Side Encryption for more information.

    " }, + "DeleteCustomDetectionRuleAssociationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "AssociationId" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "AssociationId":{ + "shape":"AssociationId", + "documentation":"

    The unique identifier for the association to delete.

    ", + "location":"uri", + "locationName":"AssociationId" + } + } + }, + "DeleteCustomDetectionRuleAssociationResponse":{ + "type":"structure", + "members":{} + }, + "DeleteCustomDetectionRuleOrgConfigurationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The execution mode of the organization configuration to delete. Valid values: LIVE | DRY_RUN.

    ", + "location":"querystring", + "locationName":"mode" + } + } + }, + "DeleteCustomDetectionRuleOrgConfigurationResponse":{ + "type":"structure", + "members":{} + }, "DeleteDetectorRequest":{ "type":"structure", "required":["DetectorId"], @@ -4061,6 +4773,217 @@ }, "documentation":"

    Contains information about the detected behavior.

    " }, + "DetectionRuleAccountIds":{ + "type":"list", + "member":{"shape":"AccountId"}, + "max":50000, + "min":0 + }, + "DetectionRuleArn":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"arn:[a-zA-Z0-9\\-]+:[a-zA-Z0-9\\-]+:[a-zA-Z0-9\\-]*:([0-9]*|aws):.+" + }, + "DetectionRuleConfigurationStatus":{ + "type":"string", + "enum":[ + "ACTIVE", + "PROCESSING", + "FAILED" + ] + }, + "DetectionRuleDataSource":{ + "type":"string", + "enum":["CloudTrailManagementEvent"] + }, + "DetectionRuleDescription":{ + "type":"string", + "max":1024, + "min":1 + }, + "DetectionRuleFilter":{ + "type":"structure", + "required":[ + "Name", + "Values" + ], + "members":{ + "Name":{ + "shape":"FilterFieldName", + "documentation":"

    The name of the field to filter by.

    ", + "locationName":"name" + }, + "Values":{ + "shape":"DetectionRuleFilterValues", + "documentation":"

    The values to match against the specified filter name.

    ", + "locationName":"values" + }, + "Condition":{ + "shape":"DetectionRuleFilterCondition", + "documentation":"

    The condition to apply to the filter. For example, EQUALS or CONTAINS.

    ", + "locationName":"condition" + } + }, + "documentation":"

    Contains filter criteria for listing custom detection rules or associations.

    " + }, + "DetectionRuleFilterCondition":{ + "type":"string", + "enum":[ + "EQUALS", + "CONTAINS" + ] + }, + "DetectionRuleFilterList":{ + "type":"list", + "member":{"shape":"DetectionRuleFilter"}, + "max":100, + "min":0 + }, + "DetectionRuleFilterValue":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9 _.\\-:/]+" + }, + "DetectionRuleFilterValues":{ + "type":"list", + "member":{"shape":"DetectionRuleFilterValue"}, + "max":50, + "min":1 + }, + "DetectionRuleMaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "DetectionRuleOrgConfiguration":{ + "type":"structure", + "required":[ + "RuleId", + "Mode", + "Status", + "IncludeAccountIds", + "ExcludeAccountIds", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The execution mode of the organization configuration. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "Status":{ + "shape":"DetectionRuleConfigurationStatus", + "documentation":"

    The configuration status. Valid values: ACTIVE | PROCESSING | FAILED.

    ", + "locationName":"status" + }, + "StatusReason":{ + "shape":"String", + "documentation":"

    The reason for the current configuration status.

    ", + "locationName":"statusReason" + }, + "IncludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    A list of member account IDs included in the organization configuration. Mutually exclusive with ExcludeAccountIds.

    ", + "locationName":"includeAccountIds" + }, + "ExcludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    A list of member account IDs excluded from the organization configuration. Mutually exclusive with IncludeAccountIds.

    ", + "locationName":"excludeAccountIds" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration was last updated.

    ", + "locationName":"updatedAt" + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration expires.

    ", + "locationName":"expiresAt" + } + }, + "documentation":"

    Contains the organization-level configuration for a custom detection rule.

    " + }, + "DetectionRuleOrgConfigurationSummary":{ + "type":"structure", + "required":[ + "RuleId", + "Mode", + "Status", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode.

    ", + "locationName":"mode" + }, + "Status":{ + "shape":"DetectionRuleConfigurationStatus", + "documentation":"

    The configuration status.

    ", + "locationName":"status" + }, + "StatusReason":{ + "shape":"String", + "documentation":"

    The reason for the current configuration status.

    ", + "locationName":"statusReason" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration was last updated.

    ", + "locationName":"updatedAt" + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the organization configuration expires.

    ", + "locationName":"expiresAt" + } + }, + "documentation":"

    Contains summary information about an organization-level configuration for a custom detection rule.

    " + }, + "DetectionRuleOrgConfigurationSummaryList":{ + "type":"list", + "member":{"shape":"DetectionRuleOrgConfigurationSummary"} + }, + "DetectionRuleServiceName":{ + "type":"string", + "max":128, + "min":1 + }, + "DetectionRuleSeverity":{ + "type":"string", + "enum":[ + "CRITICAL", + "HIGH", + "MEDIUM", + "LOW" + ] + }, "DetectionSource":{ "type":"string", "enum":[ @@ -4123,6 +5046,7 @@ "LAMBDA_NETWORK_LOGS", "EKS_RUNTIME_MONITORING", "RUNTIME_MONITORING", + "AI_PROTECTION", "AI_ANALYST" ] }, @@ -4194,6 +5118,7 @@ "LAMBDA_NETWORK_LOGS", "EKS_RUNTIME_MONITORING", "RUNTIME_MONITORING", + "AI_PROTECTION", "AI_ANALYST" ] }, @@ -4989,6 +5914,18 @@ "max":512, "min":0 }, + "FilterFieldName":{ + "type":"string", + "enum":[ + "name", + "description", + "dataSource", + "severity", + "tactic", + "technique", + "service" + ] + }, "FilterName":{ "type":"string", "max":64, @@ -5006,6 +5943,11 @@ "max":100, "min":1 }, + "FilterVersion":{ + "type":"long", + "box":true, + "min":1 + }, "Finding":{ "type":"structure", "required":[ @@ -5150,7 +6092,17 @@ "CLOUDFORMATION_STACK", "EC2_LAUNCH_TEMPLATE", "EC2_VPC", - "EC2_IMAGE" + "EC2_IMAGE", + "BEDROCK_CUSTOM_MODEL", + "BEDROCK_IMPORTED_MODEL", + "BEDROCK_PROVISIONED_MODEL", + "BEDROCK_CUSTOM_MODEL_DEPLOYMENT", + "BEDROCK_INFERENCE_PROFILE", + "BEDROCK_APPLICATION_INFERENCE_PROFILE", + "BEDROCK_PROMPT", + "BEDROCK_PROMPT_ROUTER", + "BEDROCK_GUARDRAIL", + "SAGEMAKER_ENDPOINT" ] }, "FindingStatisticType":{ @@ -5288,7 +6240,8 @@ "LAMBDA_NETWORK_LOGS", "EKS_RUNTIME_MONITORING", "EC2_RUNTIME_MONITORING", - "FARGATE_RUNTIME_MONITORING" + "FARGATE_RUNTIME_MONITORING", + "AI_PROTECTION" ] }, "GeoLocation":{ @@ -5365,6 +6318,98 @@ } } }, + "GetCustomDetectionRuleAssociationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "AssociationId" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "AssociationId":{ + "shape":"AssociationId", + "documentation":"

    The unique identifier for the association.

    ", + "location":"uri", + "locationName":"AssociationId" + } + } + }, + "GetCustomDetectionRuleAssociationResponse":{ + "type":"structure", + "required":["RuleAssociation"], + "members":{ + "RuleAssociation":{ + "shape":"AssociationDetail", + "documentation":"

    The details of the custom detection rule association.

    ", + "locationName":"ruleAssociation" + }, + "Tags":{ + "shape":"TagMap", + "documentation":"

    The tags associated with the custom detection rule association resource.

    ", + "locationName":"tags" + } + } + }, + "GetCustomDetectionRuleOrgConfigurationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The execution mode of the organization configuration to retrieve. Valid values: LIVE | DRY_RUN.

    ", + "location":"querystring", + "locationName":"mode" + } + } + }, + "GetCustomDetectionRuleOrgConfigurationResponse":{ + "type":"structure", + "required":["Configuration"], + "members":{ + "Configuration":{ + "shape":"DetectionRuleOrgConfiguration", + "documentation":"

    The details of the organization configuration.

    ", + "locationName":"configuration" + } + } + }, + "GetCustomDetectionRuleRequest":{ + "type":"structure", + "required":["RuleId"], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + } + } + }, + "GetCustomDetectionRuleResponse":{ + "type":"structure", + "required":["Rule"], + "members":{ + "Rule":{ + "shape":"RuleDetail", + "documentation":"

    The details of the custom detection rule.

    ", + "locationName":"rule" + } + } + }, "GetDetectorRequest":{ "type":"structure", "required":["DetectorId"], @@ -5482,10 +6527,25 @@ "documentation":"

    Represents the criteria to be used in the filter for querying findings.

    ", "locationName":"findingCriteria" }, - "Tags":{ - "shape":"TagMap", - "documentation":"

    The tags of the filter resource.

    ", - "locationName":"tags" + "Tags":{ + "shape":"TagMap", + "documentation":"

    The tags of the filter resource.

    ", + "locationName":"tags" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the filter was created. This field is not available for filters that were created before the lifecycle metadata feature was enabled (legacy filters).

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the filter was last updated. For legacy filters, this field is present only after the filter has been updated at least once since the lifecycle metadata feature was enabled.

    ", + "locationName":"updatedAt" + }, + "Version":{ + "shape":"FilterVersion", + "documentation":"

    The version of the filter. Every time the filter is updated, the version increments by 1. This field is not available for legacy filters that were created before the lifecycle metadata feature was enabled.

    ", + "locationName":"version" } } }, @@ -6380,6 +7440,20 @@ "type":"string", "pattern":"arn:[A-Za-z_.-]{1,20}:guardduty:[A-Za-z0-9_/.-]{0,63}:\\d+:detector/[A-Za-z0-9_/.-]{32,264}" }, + "GuardrailAction":{ + "type":"string", + "enum":[ + "GUARDRAIL_INTERVENED", + "NONE" + ] + }, + "GuardrailSource":{ + "type":"string", + "enum":[ + "INPUT", + "OUTPUT" + ] + }, "HighestSeverityThreatDetails":{ "type":"structure", "members":{ @@ -7507,6 +8581,126 @@ } } }, + "ListCustomDetectionRuleAssociationsRequest":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"DetectionRuleMaxResults", + "documentation":"

    The maximum number of results to return in a single page. Minimum value of 1, maximum value of 100.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token from a previous response. Use this token to retrieve the next page of results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule to filter associations by.

    ", + "location":"querystring", + "locationName":"ruleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode to filter associations by.

    ", + "location":"querystring", + "locationName":"mode" + } + } + }, + "ListCustomDetectionRuleAssociationsResponse":{ + "type":"structure", + "required":["RuleAssociations"], + "members":{ + "RuleAssociations":{ + "shape":"AssociationSummaryList", + "documentation":"

    A list of custom detection rule association summaries.

    ", + "locationName":"ruleAssociations" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token to retrieve the next page of results. If this field is empty, there are no additional results.

    ", + "locationName":"nextToken" + } + } + }, + "ListCustomDetectionRuleOrgConfigurationsRequest":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"DetectionRuleMaxResults", + "documentation":"

    The maximum number of results to return in a single page. Minimum value of 1, maximum value of 100.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token from a previous response. Use this token to retrieve the next page of results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "Status":{ + "shape":"DetectionRuleConfigurationStatus", + "documentation":"

    The configuration status to filter by.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListCustomDetectionRuleOrgConfigurationsResponse":{ + "type":"structure", + "required":["Configurations"], + "members":{ + "Configurations":{ + "shape":"DetectionRuleOrgConfigurationSummaryList", + "documentation":"

    A list of organization configurations for custom detection rules.

    ", + "locationName":"configurations" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token to retrieve the next page of results. If this field is empty, there are no additional results.

    ", + "locationName":"nextToken" + } + } + }, + "ListCustomDetectionRulesRequest":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"DetectionRuleMaxResults", + "documentation":"

    The maximum number of results to return in a single page. Minimum value of 1, maximum value of 100.

    ", + "locationName":"maxResults" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token from a previous response. Use this token to retrieve the next page of results.

    ", + "locationName":"nextToken" + }, + "Filters":{ + "shape":"DetectionRuleFilterList", + "documentation":"

    A list of filter criteria to apply when listing custom detection rules.

    ", + "locationName":"filters" + } + } + }, + "ListCustomDetectionRulesResponse":{ + "type":"structure", + "required":["Rules"], + "members":{ + "Rules":{ + "shape":"RuleSummaryList", + "documentation":"

    A list of custom detection rule summaries.

    ", + "locationName":"rules" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A pagination token to retrieve the next page of results. If this field is empty, there are no additional results.

    ", + "locationName":"nextToken" + } + } + }, "ListDetectorsRequest":{ "type":"structure", "members":{ @@ -8707,6 +9901,36 @@ "DISABLED" ] }, + "MitreTactic":{ + "type":"string", + "max":255, + "min":1 + }, + "MitreTechnique":{ + "type":"string", + "max":255, + "min":1 + }, + "ModelDetail":{ + "type":"structure", + "members":{ + "ModelId":{ + "shape":"ModelDetailModelIdString", + "documentation":"

    The identifier of the AI model.

    ", + "locationName":"modelId" + } + }, + "documentation":"

    Contains information about the AI model involved in a finding.

    " + }, + "ModelDetailModelIdString":{ + "type":"string", + "max":2048, + "min":1 + }, + "ModelDetails":{ + "type":"list", + "member":{"shape":"ModelDetail"} + }, "Name":{ "type":"string", "max":300, @@ -8952,6 +10176,10 @@ "max":5, "min":0 }, + "ObservationNumbers":{ + "type":"list", + "member":{"shape":"Long"} + }, "ObservationTexts":{ "type":"list", "member":{"shape":"String"} @@ -8963,6 +10191,11 @@ "shape":"ObservationTexts", "documentation":"

    The text that was unusual.

    ", "locationName":"text" + }, + "Number":{ + "shape":"ObservationNumbers", + "documentation":"

    The numeric values that were unusual.

    ", + "locationName":"number" } }, "documentation":"

    Contains information about the observed behavior.

    " @@ -8983,7 +10216,8 @@ "RDS_LOGIN_EVENTS", "LAMBDA_NETWORK_LOGS", "EKS_RUNTIME_MONITORING", - "RUNTIME_MONITORING" + "RUNTIME_MONITORING", + "AI_PROTECTION" ] }, "OrgFeatureAdditionalConfiguration":{ @@ -9613,12 +10847,17 @@ "FREQUENT", "INFREQUENT", "UNSEEN", - "RARE" + "RARE", + "COUNT", + "AVERAGE" ] }, "ProfileType":{ "type":"string", - "enum":["FREQUENCY"] + "enum":[ + "FREQUENCY", + "VOLUME" + ] }, "PublicAccess":{ "type":"structure", @@ -9850,6 +11089,10 @@ "shape":"String", "documentation":"

    The name of the backup vault containing the recovery point.

    ", "locationName":"backupVaultName" + }, + "ContinuousScanDetails":{ + "shape":"ScanConfigurationContinuousScanDetails", + "locationName":"continuousScanDetails" } }, "documentation":"

    Contains details about the backup recovery point.

    " @@ -10009,6 +11252,16 @@ "shape":"RecoveryPointDetails", "documentation":"

    Contains details about the backup recovery point that was scanned.

    ", "locationName":"recoveryPointDetails" + }, + "BedrockGuardrailDetails":{ + "shape":"BedrockGuardrailDetails", + "documentation":"

    Contains information about the Bedrock guardrail that was involved in a finding.

    ", + "locationName":"bedrockGuardrailDetails" + }, + "ModelDetails":{ + "shape":"ModelDetails", + "documentation":"

    Contains information about the AI models involved in a finding.

    ", + "locationName":"modelDetails" } }, "documentation":"

    Contains information about the Amazon Web Services resource associated with the activity that prompted GuardDuty to generate a finding.

    " @@ -10099,6 +11352,11 @@ "shape":"CloudformationStack", "documentation":"

    Contains detailed information about the CloudFormation stack associated with the activity that prompted GuardDuty to generate a finding.

    ", "locationName":"cloudformationStack" + }, + "BedrockGuardrail":{ + "shape":"BedrockGuardrailResource", + "documentation":"

    Contains detailed information about the Amazon Bedrock guardrail associated with the activity that prompted GuardDuty to generate a finding.

    ", + "locationName":"bedrockGuardrail" } }, "documentation":"

    Contains information about the Amazon Web Services resource that is associated with the activity that prompted GuardDuty to generate a finding.

    " @@ -10262,6 +11520,218 @@ "max":300, "min":1 }, + "RuleDefinition":{ + "type":"structure", + "required":["Expression"], + "members":{ + "Expression":{ + "shape":"RuleExpression", + "documentation":"

    The detection logic expression for the rule.

    ", + "locationName":"expression" + } + }, + "documentation":"

    Contains the detection logic for a custom detection rule.

    " + }, + "RuleDetail":{ + "type":"structure", + "required":[ + "RuleId", + "Arn", + "Name", + "Description", + "Severity", + "DataSource", + "Tactic", + "Technique", + "Service", + "Definition", + "CreatedAt" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the rule.

    ", + "locationName":"ruleId" + }, + "Arn":{ + "shape":"DetectionRuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    ", + "locationName":"arn" + }, + "Name":{ + "shape":"RuleName", + "documentation":"

    The display name of the rule.

    ", + "locationName":"name" + }, + "Description":{ + "shape":"DetectionRuleDescription", + "documentation":"

    A description of what the rule detects.

    ", + "locationName":"description" + }, + "Severity":{ + "shape":"DetectionRuleSeverity", + "documentation":"

    The severity level assigned to findings generated by this rule.

    ", + "locationName":"severity" + }, + "DataSource":{ + "shape":"DetectionRuleDataSource", + "documentation":"

    The data source that the rule analyzes.

    ", + "locationName":"dataSource" + }, + "Tactic":{ + "shape":"MitreTactic", + "documentation":"

    The MITRE ATT&CK tactic associated with the rule.

    ", + "locationName":"tactic" + }, + "Technique":{ + "shape":"MitreTechnique", + "documentation":"

    The MITRE ATT&CK technique associated with the rule.

    ", + "locationName":"technique" + }, + "Service":{ + "shape":"DetectionRuleServiceName", + "documentation":"

    The Amazon Web Services service associated with the rule.

    ", + "locationName":"service" + }, + "Definition":{ + "shape":"RuleDefinition", + "documentation":"

    The detection logic definition for the rule.

    ", + "locationName":"definition" + }, + "Language":{ + "shape":"RuleLanguage", + "documentation":"

    The language used for the detection logic expression.

    ", + "locationName":"language" + }, + "Schema":{ + "shape":"RuleSchema", + "documentation":"

    The schema version used by the rule definition.

    ", + "locationName":"schema" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the rule was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the rule was last updated.

    ", + "locationName":"updatedAt" + } + }, + "documentation":"

    Contains the full details of a custom detection rule, including its detection logic.

    " + }, + "RuleExpression":{ + "type":"string", + "max":4096, + "min":1 + }, + "RuleId":{ + "type":"string", + "max":100, + "min":1, + "pattern":"[a-z0-9]+(-[a-z0-9]+)*" + }, + "RuleLanguage":{ + "type":"string", + "enum":["SQL"] + }, + "RuleName":{ + "type":"string", + "max":255, + "min":1 + }, + "RuleSchema":{ + "type":"string", + "enum":["CloudTrail"] + }, + "RuleSummary":{ + "type":"structure", + "required":[ + "RuleId", + "Arn", + "Name", + "Description", + "Severity", + "DataSource", + "Tactic", + "Technique", + "Service", + "CreatedAt" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the rule.

    ", + "locationName":"ruleId" + }, + "Arn":{ + "shape":"DetectionRuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    ", + "locationName":"arn" + }, + "Name":{ + "shape":"RuleName", + "documentation":"

    The display name of the rule.

    ", + "locationName":"name" + }, + "Description":{ + "shape":"DetectionRuleDescription", + "documentation":"

    A description of what the rule detects.

    ", + "locationName":"description" + }, + "Severity":{ + "shape":"DetectionRuleSeverity", + "documentation":"

    The severity level assigned to findings generated by this rule.

    ", + "locationName":"severity" + }, + "DataSource":{ + "shape":"DetectionRuleDataSource", + "documentation":"

    The data source that the rule analyzes.

    ", + "locationName":"dataSource" + }, + "Tactic":{ + "shape":"MitreTactic", + "documentation":"

    The MITRE ATT&CK tactic associated with the rule.

    ", + "locationName":"tactic" + }, + "Technique":{ + "shape":"MitreTechnique", + "documentation":"

    The MITRE ATT&CK technique associated with the rule.

    ", + "locationName":"technique" + }, + "Service":{ + "shape":"DetectionRuleServiceName", + "documentation":"

    The Amazon Web Services service associated with the rule.

    ", + "locationName":"service" + }, + "Language":{ + "shape":"RuleLanguage", + "documentation":"

    The language used for the detection logic expression.

    ", + "locationName":"language" + }, + "Schema":{ + "shape":"RuleSchema", + "documentation":"

    The schema version used by the rule definition.

    ", + "locationName":"schema" + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the rule was created.

    ", + "locationName":"createdAt" + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the rule was last updated.

    ", + "locationName":"updatedAt" + } + }, + "documentation":"

    Contains summary information about a custom detection rule.

    " + }, + "RuleSummaryList":{ + "type":"list", + "member":{"shape":"RuleSummary"} + }, "RuntimeContext":{ "type":"structure", "members":{ @@ -11466,6 +12936,11 @@ "shape":"Indicators", "documentation":"

    Contains information about the indicators associated with the signals.

    ", "locationName":"signalIndicators" + }, + "Activities":{ + "shape":"Activities", + "documentation":"

    Contains information about the activities, such as API calls, that were observed for this signal.

    ", + "locationName":"activities" } }, "documentation":"

    Contains information about the signals involved in the attack sequence.

    " @@ -12051,6 +13526,71 @@ "type":"structure", "members":{} }, + "UpdateCustomDetectionRuleAssociationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "AssociationId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "AssociationId":{ + "shape":"AssociationId", + "documentation":"

    The unique identifier for the association to update.

    ", + "location":"uri", + "locationName":"AssociationId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The rule execution mode. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + } + } + }, + "UpdateCustomDetectionRuleAssociationResponse":{ + "type":"structure", + "members":{} + }, + "UpdateCustomDetectionRuleOrgConfigurationRequest":{ + "type":"structure", + "required":[ + "RuleId", + "Mode" + ], + "members":{ + "RuleId":{ + "shape":"RuleId", + "documentation":"

    The unique identifier for the custom detection rule.

    ", + "location":"uri", + "locationName":"RuleId" + }, + "Mode":{ + "shape":"AssociationMode", + "documentation":"

    The execution mode of the organization configuration. Valid values: LIVE | DRY_RUN.

    ", + "locationName":"mode" + }, + "IncludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    The account IDs to include in the organization configuration. Mutually exclusive with ExcludeAccountIds.

    ", + "locationName":"includeAccountIds" + }, + "ExcludeAccountIds":{ + "shape":"DetectionRuleAccountIds", + "documentation":"

    The account IDs to exclude from the organization configuration. Mutually exclusive with IncludeAccountIds.

    ", + "locationName":"excludeAccountIds" + } + } + }, + "UpdateCustomDetectionRuleOrgConfigurationResponse":{ + "type":"structure", + "members":{} + }, "UpdateDetectorRequest":{ "type":"structure", "required":["DetectorId"], @@ -12627,7 +14167,8 @@ "EC2_RUNTIME_MONITORING", "FARGATE_RUNTIME_MONITORING", "RDS_DBI_PROTECTION_PROVISIONED", - "RDS_DBI_PROTECTION_SERVERLESS" + "RDS_DBI_PROTECTION_SERVERLESS", + "AI_PROTECTION" ] }, "UsageFeatureList":{ diff --git a/services/health/pom.xml b/services/health/pom.xml index f237edff73a9..bacdedab026b 100644 --- a/services/health/pom.xml +++ b/services/health/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT health AWS Java SDK :: Services :: AWS Health APIs and Notifications diff --git a/services/health/src/main/resources/codegen-resources/customization.config b/services/health/src/main/resources/codegen-resources/customization.config index dbff7768d1f9..168cf96cb232 100644 --- a/services/health/src/main/resources/codegen-resources/customization.config +++ b/services/health/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "describeEvents", "describeEntityAggregates", "describeEventTypes" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/health/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/health/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..007148d94015 --- /dev/null +++ b/services/health/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,345 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-global" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-cn-global" + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://health-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://health.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://health-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://global.health.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "health", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://global.health.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "health", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://health.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 24, + "nodes": "/////wAAAAH/////AAAAAAAAABYAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAABIAAAAGAAAABAAAAA4AAAAHAAAABQAAAA4AAAAIAAAABgAAAA4AAAAJAAAABwAAAA4AAAAKAAAACAAAAA4AAAALAAAACgAAAA4AAAAMAAAACwAAAA4AAAANAAAADAX14QEF9eECAAAADAAAABEAAAAPAAAADgX14QoAAAAQAAAADwX14QsF9eEMAAAADQX14QcF9eEIAAAACQAAABQAAAATAAAADAX14QYF9eEJAAAADAAAABUF9eECAAAADQX14QEF9eEGAAAAAwAAABgAAAAXAAAADAX14QMF9eEFAAAADAX14QMF9eEE" +} \ No newline at end of file diff --git a/services/health/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/health/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0dc9da01e68d..000000000000 --- a/services/health/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,582 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://health-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://health.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://health-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://health-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://health.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://global.health.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "health", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-cn-global" - ] - } - ], - "endpoint": { - "url": "https://global.health.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "health", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://health.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/healthlake/pom.xml b/services/healthlake/pom.xml index a09ace93e4b0..164d7f0549eb 100644 --- a/services/healthlake/pom.xml +++ b/services/healthlake/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT healthlake AWS Java SDK :: Services :: Health Lake diff --git a/services/healthlake/src/main/resources/codegen-resources/customization.config b/services/healthlake/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/healthlake/src/main/resources/codegen-resources/customization.config +++ b/services/healthlake/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/healthlake/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/healthlake/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..15bccaad5e35 --- /dev/null +++ b/services/healthlake/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://healthlake-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://healthlake-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://healthlake.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://healthlake.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/healthlake/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/healthlake/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index db9b0522f264..000000000000 --- a/services/healthlake/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://healthlake-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://healthlake-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://healthlake.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://healthlake.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/healthlake/src/main/resources/codegen-resources/paginators-1.json b/services/healthlake/src/main/resources/codegen-resources/paginators-1.json index d103dbc646cf..25fed47848a8 100644 --- a/services/healthlake/src/main/resources/codegen-resources/paginators-1.json +++ b/services/healthlake/src/main/resources/codegen-resources/paginators-1.json @@ -1,5 +1,23 @@ { "pagination": { + "ListDataTransformationJobs": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Items" + }, + "ListDataTransformationProfileVersions": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Items" + }, + "ListDataTransformationProfiles": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Items" + }, "ListFHIRDatastores": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/healthlake/src/main/resources/codegen-resources/service-2.json b/services/healthlake/src/main/resources/codegen-resources/service-2.json index 9084f4a40e00..dd3650d88f8d 100644 --- a/services/healthlake/src/main/resources/codegen-resources/service-2.json +++ b/services/healthlake/src/main/resources/codegen-resources/service-2.json @@ -2,6 +2,7 @@ "version":"2.0", "metadata":{ "apiVersion":"2017-07-01", + "auth":["aws.auth#sigv4"], "endpointPrefix":"healthlake", "jsonVersion":"1.0", "protocol":"json", @@ -12,10 +13,29 @@ "signatureVersion":"v4", "signingName":"healthlake", "targetPrefix":"HealthLake", - "uid":"healthlake-2017-07-01", - "auth":["aws.auth#sigv4"] + "uid":"healthlake-2017-07-01" }, "operations":{ + "CreateDataTransformationProfile":{ + "name":"CreateDataTransformationProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateDataTransformationProfileRequest"}, + "output":{"shape":"CreateDataTransformationProfileResponse"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates a data transformation profile in DRAFT state. Specify a built-in starter profile, an existing profile version, raw profile content, or a sample data file as the source.

    ", + "endpoint":{"hostPrefix":"datatransformation."} + }, "CreateFHIRDatastore":{ "name":"CreateFHIRDatastore", "http":{ @@ -25,13 +45,32 @@ "input":{"shape":"CreateFHIRDatastoreRequest"}, "output":{"shape":"CreateFHIRDatastoreResponse"}, "errors":[ - {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Create a FHIR-enabled data store.

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

    Deletes a data transformation profile and all its versions, including the DRAFT and all published versions.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "idempotent":true + }, "DeleteFHIRDatastore":{ "name":"DeleteFHIRDatastore", "http":{ @@ -41,15 +80,34 @@ "input":{"shape":"DeleteFHIRDatastoreRequest"}, "output":{"shape":"DeleteFHIRDatastoreResponse"}, "errors":[ + {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], "documentation":"

    Delete a FHIR-enabled data store.

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

    Describes a data transformation job, including its current status, configuration, and progress information.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "readonly":true + }, "DescribeFHIRDatastore":{ "name":"DescribeFHIRDatastore", "http":{ @@ -59,9 +117,9 @@ "input":{"shape":"DescribeFHIRDatastoreRequest"}, "output":{"shape":"DescribeFHIRDatastoreResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Get properties for a FHIR-enabled data store.

    " @@ -75,9 +133,9 @@ "input":{"shape":"DescribeFHIRExportJobRequest"}, "output":{"shape":"DescribeFHIRExportJobResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Get FHIR export job properties.

    " @@ -91,12 +149,86 @@ "input":{"shape":"DescribeFHIRImportJobRequest"}, "output":{"shape":"DescribeFHIRImportJobResponse"}, "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Get the import job properties to learn more about the job or job progress.

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

    Retrieves a data transformation profile's metadata and profile content at a specific version. Specify version 0 to retrieve the DRAFT, a version number between 1 and 99 to retrieve a specific published version, or omit the version to retrieve the latest published version.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "readonly":true + }, + "ListDataTransformationJobs":{ + "name":"ListDataTransformationJobs", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDataTransformationJobsRequest"}, + "output":{"shape":"ListDataTransformationJobsResponse"}, + "errors":[ {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Get the import job properties to learn more about the job or job progress.

    " + "documentation":"

    Lists data transformation jobs for your Amazon Web Services account. Results can be filtered by status, job name, and submit time window. Results are paginated. Use the NextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "readonly":true + }, + "ListDataTransformationProfileVersions":{ + "name":"ListDataTransformationProfileVersions", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDataTransformationProfileVersionsRequest"}, + "output":{"shape":"ListDataTransformationProfileVersionsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists all versions of a specific data transformation profile (DRAFT and published), in reverse chronological order (newest first). Use GetDataTransformationProfile to retrieve profile content. Results are paginated. Use the NextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "readonly":true + }, + "ListDataTransformationProfiles":{ + "name":"ListDataTransformationProfiles", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDataTransformationProfilesRequest"}, + "output":{"shape":"ListDataTransformationProfilesResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists all data transformation profiles in your account, returning the latest version summary for each. Use GetDataTransformationProfile to retrieve profile content. Results are paginated. Use the NextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "readonly":true }, "ListFHIRDatastores":{ "name":"ListFHIRDatastores", @@ -107,8 +239,8 @@ "input":{"shape":"ListFHIRDatastoresRequest"}, "output":{"shape":"ListFHIRDatastoresResponse"}, "errors":[ - {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    List all FHIR-enabled data stores in a user’s account, regardless of data store status.

    " @@ -122,10 +254,10 @@ "input":{"shape":"ListFHIRExportJobsRequest"}, "output":{"shape":"ListFHIRExportJobsResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Lists all FHIR export jobs associated with an account and their statuses.

    " @@ -139,10 +271,10 @@ "input":{"shape":"ListFHIRImportJobsRequest"}, "output":{"shape":"ListFHIRImportJobsResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    List all FHIR import jobs associated with an account and their statuses.

    " @@ -156,11 +288,67 @@ "input":{"shape":"ListTagsForResourceRequest"}, "output":{"shape":"ListTagsForResourceResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"} ], "documentation":"

    Returns a list of all existing tags associated with a data store.

    " }, + "PublishDataTransformationProfile":{ + "name":"PublishDataTransformationProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"PublishDataTransformationProfileRequest"}, + "output":{"shape":"PublishDataTransformationProfileResponse"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Promotes the current DRAFT version of a data transformation profile to a new immutable published version. Also supports rollback by publishing from a previously published version.

    ", + "endpoint":{"hostPrefix":"datatransformation."} + }, + "RestoreFHIRDatastore":{ + "name":"RestoreFHIRDatastore", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"RestoreFHIRDatastoreRequest"}, + "output":{"shape":"RestoreFHIRDatastoreResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Restore a backup-enabled data store to a point in time. Creates a new data store from the backup.

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

    Starts an asynchronous data transformation job that converts source files from Amazon Simple Storage Service (Amazon S3) and writes the output to Amazon S3 or HealthLake.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "idempotent":true + }, "StartFHIRExportJob":{ "name":"StartFHIRExportJob", "http":{ @@ -170,10 +358,11 @@ "input":{"shape":"StartFHIRExportJobRequest"}, "output":{"shape":"StartFHIRExportJobResponse"}, "errors":[ - {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, + {"shape":"FailedDependencyException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Start a FHIR export job.

    " @@ -187,10 +376,11 @@ "input":{"shape":"StartFHIRImportJobRequest"}, "output":{"shape":"StartFHIRImportJobResponse"}, "errors":[ - {"shape":"ValidationException"}, {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, + {"shape":"FailedDependencyException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Start importing bulk FHIR data into an ACTIVE data store. The import job imports FHIR data found in the InputDataConfig object and stores processing results in the JobOutputDataConfig object.

    " @@ -204,8 +394,8 @@ "input":{"shape":"TagResourceRequest"}, "output":{"shape":"TagResourceResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"} ], "documentation":"

    Add a user-specifed key and value tag to a data store.

    " }, @@ -218,11 +408,30 @@ "input":{"shape":"UntagResourceRequest"}, "output":{"shape":"UntagResourceResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"} + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"} ], "documentation":"

    Remove a user-specifed key and value tag from a data store.

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

    Updates the DRAFT version (version 0) of a data transformation profile with new profile content. The update replaces all existing DRAFT content.

    ", + "endpoint":{"hostPrefix":"datatransformation."}, + "idempotent":true + }, "UpdateFHIRDatastore":{ "name":"UpdateFHIRDatastore", "http":{ @@ -232,30 +441,127 @@ "input":{"shape":"UpdateFHIRDatastoreRequest"}, "output":{"shape":"UpdateFHIRDatastoreResponse"}, "errors":[ - {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], "documentation":"

    Update the properties of a FHIR-enabled data store.

    " + }, + "UpdateProfileWithAgent":{ + "name":"UpdateProfileWithAgent", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateProfileWithAgentRequest"}, + "output":{"shape":"UpdateProfileWithAgentResponse"}, + "errors":[ + {"shape":"NotImplementedOperationException"}, + {"shape":"ConversationNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"AgentMessageOutOfContextException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"UnsupportedMIMETypeException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"UnauthorizedException"} + ], + "documentation":"

    Updates a data transformation profile using chat-based interaction with an agent. Supports multi-turn conversations for iteratively customizing profiles.

    ", + "endpoint":{"hostPrefix":"datatransformation."} } }, "shapes":{ "AccessDeniedException":{ "type":"structure", "members":{ - "Message":{"shape":"String"} + "Message":{"shape":"HealthLakeString"} }, "documentation":"

    Access is denied. Your account is not authorized to perform this operation.

    ", "exception":true }, + "AgentInputMessage":{ + "type":"structure", + "required":[ + "Body", + "Type" + ], + "members":{ + "Body":{ + "shape":"AgentMessageString", + "documentation":"

    The text of your message to the agent.

    " + }, + "Type":{ + "shape":"AgentInputMessageType", + "documentation":"

    The type of input message, which determines how the agent processes your request. Valid values:

    • normal: A regular message to the agent.

    • confirmation_response: A response to a confirmation request from the agent.

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

    Represents a message sent to the agent during chat-based profile customization.

    " + }, + "AgentInputMessageType":{ + "type":"string", + "enum":[ + "normal", + "confirmation_response" + ] + }, + "AgentMessageOutOfContextException":{ + "type":"structure", + "required":["Message"], + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    The agent message does not fit within the current conversation context. Start a new conversation or provide a message that relates to the current profile customization session.

    ", + "exception":true + }, + "AgentMessageString":{ + "type":"string", + "max":40960, + "min":1, + "sensitive":true + }, + "AgentOutputMessage":{ + "type":"structure", + "required":[ + "Body", + "Type" + ], + "members":{ + "Body":{ + "shape":"AgentMessageString", + "documentation":"

    The text of the agent's response.

    " + }, + "Type":{ + "shape":"AgentOutputMessageType", + "documentation":"

    The type of output message, which indicates how to interpret the agent's response.

    " + }, + "OptionsList":{ + "shape":"DataTransformationChatOptionsList", + "documentation":"

    A list of selectable options presented when the response type is options.

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

    Represents a response message from the agent during chat-based profile customization.

    " + }, + "AgentOutputMessageType":{ + "type":"string", + "enum":[ + "INITIAL_GREETING", + "normal", + "confirmation", + "complete", + "error", + "options", + "choices" + ] + }, "AmazonResourceName":{ "type":"string", "max":1011, "min":1, - "pattern":"^arn:aws((-us-gov)|(-iso)|(-iso-b)|(-cn))?:healthlake:[a-z0-9-]+:\\d{12}:datastore\\/fhir\\/.{32}" + "pattern":"arn:aws((-us-gov)|(-iso)|(-iso-b)|(-cn))?:healthlake:[a-z0-9-]+:\\d{12}:(datastore\\/fhir\\/.{32}|dataTransformationProfile\\/[a-f0-9]{32})" }, "AnalyticsConfiguration":{ "type":"structure", @@ -286,18 +592,78 @@ "AWS_AUTH" ] }, - "Boolean":{"type":"boolean"}, + "BackupConfiguration":{ + "type":"structure", + "members":{ + "Status":{ + "shape":"BackupStatus", + "documentation":"

    The backup status of the data store.

    " + }, + "BackupType":{ + "shape":"BackupType", + "documentation":"

    The type of backup.

    " + }, + "RetentionPeriodInDays":{ + "shape":"BackupRetentionPeriodInDays", + "documentation":"

    The number of days backup data is retained.

    " + }, + "BackupTagsEnabled":{ + "shape":"HealthLakeBoolean", + "documentation":"

    Specifies whether tags are included in backups.

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

    The backup configuration for the data store.

    " + }, + "BackupRetentionPeriodInDays":{ + "type":"integer", + "box":true, + "max":30, + "min":1 + }, + "BackupStatus":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, + "BackupType":{ + "type":"string", + "enum":["CONTINUOUS"] + }, + "Boolean":{ + "type":"boolean", + "box":true + }, "BoundedLengthString":{ "type":"string", + "documentation":"

    A bounded-length string value.

    ", "max":5000, "min":1, "pattern":"[\\P{M}\\p{M}]{1,5000}" }, + "BoundedString":{ + "type":"string", + "max":2048, + "min":1 + }, + "ChangeDescription":{ + "type":"string", + "max":1000, + "min":0 + }, + "ClientToken":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9-]+" + }, "ClientTokenString":{ "type":"string", + "documentation":"

    A client-provided idempotency token.

    ", "max":64, "min":1, - "pattern":"^[a-zA-Z0-9-]+$" + "pattern":"[a-zA-Z0-9-]+" }, "CmkType":{ "type":"string", @@ -310,11 +676,136 @@ "ConflictException":{ "type":"structure", "members":{ - "Message":{"shape":"String"} + "Message":{"shape":"HealthLakeString"} }, "documentation":"

    The data store is in a transition state and the user requested action cannot be performed.

    ", "exception":true }, + "ContinuousBackupRestoreConfiguration":{ + "type":"structure", + "members":{ + "RestorePointTime":{ + "shape":"HealthLakeTimestamp", + "documentation":"

    The point in time to restore the data store to, specified as a UTC timestamp.

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

    Configuration for continuous backup (point-in-time) restore.

    " + }, + "ConversationIdString":{ + "type":"string", + "max":36, + "min":1 + }, + "ConversationNotFoundException":{ + "type":"structure", + "required":["Message"], + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    The specified conversation identifier does not exist. Verify the conversation ID or omit it to start a new conversation.

    ", + "exception":true + }, + "CreateDataTransformationProfileRequest":{ + "type":"structure", + "required":[ + "SourceFormat", + "Source", + "ProfileName" + ], + "members":{ + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format that this profile converts from (Consolidated Clinical Document Architecture (C-CDA) or Comma-separated values (CSV)).

    " + }, + "Source":{ + "shape":"CreateDataTransformationProfileSource", + "documentation":"

    The source for the initial profile content. Specify a built-in starter profile, an existing profile version to clone, raw profile content for CI/CD workflows, or a sample data file in Amazon S3.

    " + }, + "KmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services Key Management Service (Amazon Web Services KMS) key identifier used to encrypt the profile content at rest.

    " + }, + "ProfileDescription":{ + "shape":"ProfileDescription", + "documentation":"

    A human-readable description of the profile's purpose.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    A name for the data transformation profile.

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

    The tags to associate with the profile at creation time.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request but does not return an error.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    The request parameters for the CreateDataTransformationProfile operation.

    " + }, + "CreateDataTransformationProfileResponse":{ + "type":"structure", + "required":[ + "ProfileId", + "Version", + "SourceFormat", + "TargetFormat", + "ProfileName", + "LastUpdatedAt" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the created profile.

    " + }, + "Version":{ + "shape":"ProfileVersion", + "documentation":"

    The version number of the newly created profile. The starting version is always 0, which indicates the profile is in DRAFT state.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format of the profile.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format. Always FHIR_R4.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the created profile.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the profile was last updated.

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

    The response from the CreateDataTransformationProfile operation.

    " + }, + "CreateDataTransformationProfileSource":{ + "type":"structure", + "members":{ + "StarterProfile":{ + "shape":"StarterProfileSource", + "documentation":"

    Creates the profile from a built-in starter profile. Valid only when the source format is Consolidated Clinical Document Architecture (C-CDA).

    " + }, + "ExistingVersionedProfileId":{ + "shape":"ExistingVersionedProfileSource", + "documentation":"

    Creates the profile by cloning an existing profile at a specific version.

    " + }, + "ProfileMapping":{ + "shape":"ProfileMappingSource", + "documentation":"

    Creates the profile from raw profile content that you provide directly. Use this variant for continuous integration and continuous delivery (CI/CD) workflows.

    " + }, + "SampleData":{ + "shape":"SampleDataSource", + "documentation":"

    Creates the profile from a sample data file stored in Amazon S3. Valid only when the source format is Comma-separated values (CSV).

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

    The source for initial content when creating a data transformation profile. Specify exactly one variant: a built-in starter profile, an existing profile version to clone, raw profile content, or a sample data file.

    ", + "union":true + }, "CreateFHIRDatastoreRequest":{ "type":"structure", "required":["DatastoreTypeVersion"], @@ -359,6 +850,10 @@ "ProfileConfiguration":{ "shape":"ProfileConfiguration", "documentation":"

    The profile configuration for the data store.

    " + }, + "BackupConfiguration":{ + "shape":"BackupConfiguration", + "documentation":"

    The backup configuration for the data store.

    " } } }, @@ -385,13 +880,197 @@ }, "DatastoreEndpoint":{ "shape":"BoundedLengthString", - "documentation":"

    The AWS endpoint created for the data store.

    " + "documentation":"

    The Amazon Web Services endpoint created for the data store.

    " } } }, + "DataTransformationChatOptionString":{ + "type":"string", + "max":1024, + "min":1, + "sensitive":true + }, + "DataTransformationChatOptionsList":{ + "type":"list", + "member":{"shape":"DataTransformationChatOptionString"} + }, + "DataTransformationIamRoleArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws(-[^:]+)?:iam::[0-9]{12}:role/.+" + }, + "DataTransformationJobId":{ + "type":"string", + "max":32, + "min":1, + "pattern":"[a-zA-Z0-9-]+" + }, + "DataTransformationJobName":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*" + }, + "DataTransformationNextToken":{ + "type":"string", + "max":2048, + "min":1 + }, + "DataTransformationProfileSummary":{ + "type":"structure", + "required":[ + "ProfileId", + "Version", + "SourceFormat", + "TargetFormat" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile.

    " + }, + "Version":{ + "shape":"ProfileVersion", + "documentation":"

    The latest version number of the profile.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format that this profile converts from.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format of the profile.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the profile.

    " + }, + "ProfileDescription":{ + "shape":"ProfileDescription", + "documentation":"

    A description of the profile's purpose.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the profile was last updated.

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

    Contains summary information about a data transformation profile. To retrieve profile content, call GetDataTransformationProfile.

    " + }, + "DataTransformationProfileSummaryList":{ + "type":"list", + "member":{"shape":"DataTransformationProfileSummary"} + }, + "DataTransformationProfileVersionSummary":{ + "type":"structure", + "required":[ + "ProfileId", + "Version", + "SourceFormat", + "TargetFormat" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile.

    " + }, + "Version":{ + "shape":"ProfileVersion", + "documentation":"

    The version number.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format that this profile converts from.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format of the profile.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the profile.

    " + }, + "ChangeDescription":{ + "shape":"ChangeDescription", + "documentation":"

    A description of what changed in this version.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when this version was last updated.

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

    Contains summary information about a specific version of a data transformation profile. To retrieve profile content, call GetDataTransformationProfile.

    " + }, + "DataTransformationProfileVersionSummaryList":{ + "type":"list", + "member":{"shape":"DataTransformationProfileVersionSummary"} + }, + "DataTransformationS3Configuration":{ + "type":"structure", + "required":[ + "S3Uri", + "KmsKeyId" + ], + "members":{ + "S3Uri":{ + "shape":"DataTransformationS3Uri", + "documentation":"

    The Amazon S3 URI where HealthLake writes the converted output files.

    " + }, + "KmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services Key Management Service (Amazon Web Services KMS) key identifier used to encrypt the transformation job output written to Amazon S3.

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

    The Amazon S3 output configuration for a data transformation job, including the output location and encryption settings.

    " + }, + "DataTransformationS3Uri":{ + "type":"string", + "max":2048, + "min":8, + "pattern":"s3://[a-z0-9][a-z0-9.\\-]{1,61}[a-z0-9](/.+)?" + }, + "DataTransformationTagKey":{ + "type":"string", + "documentation":"

    The key of the tag. Tag keys are case-sensitive and must be unique per resource.

    ", + "max":128, + "min":1 + }, + "DataTransformationTagValue":{ + "type":"string", + "documentation":"

    The value of the tag. Tag values are case-sensitive and can be empty strings.

    ", + "max":256, + "min":0 + }, "DatastoreArn":{ "type":"string", - "pattern":"^arn:aws((-us-gov)|(-iso)|(-iso-b)|(-cn))?:healthlake:[a-zA-Z0-9-]+:[0-9]{12}:datastore/.+?" + "documentation":"

    The ARN of a data store.

    ", + "pattern":"arn:aws((-us-gov)|(-iso)|(-iso-b)|(-cn))?:healthlake:[a-zA-Z0-9-]+:[0-9]{12}:datastore/.+?" + }, + "DatastoreBackupStatus":{ + "type":"structure", + "members":{ + "Configuration":{ + "shape":"BackupConfiguration", + "documentation":"

    The backup configuration for the data store.

    " + }, + "BackupEnabledAt":{ + "shape":"HealthLakeTimestamp", + "documentation":"

    The time backup was enabled on the data store.

    " + }, + "EarliestRestorePoint":{ + "shape":"HealthLakeTimestamp", + "documentation":"

    The earliest point in time the data store can be restored to.

    " + }, + "LatestRestorePoint":{ + "shape":"HealthLakeTimestamp", + "documentation":"

    The latest point in time the data store can be restored to.

    " + }, + "ScheduledPermanentDeletionTime":{ + "shape":"HealthLakeTimestamp", + "documentation":"

    The time the retained backup data is scheduled for permanent deletion.

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

    The backup status information for the data store.

    " }, "DatastoreFilter":{ "type":"structure", @@ -405,11 +1084,11 @@ "documentation":"

    Filter data store results by status.

    " }, "CreatedBefore":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Filter to set cutoff dates for records. All data stores created before the specified date are included in the results.

    " }, "CreatedAfter":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Filter to set cutoff dates for records. All data stores created after the specified date are included in the results.

    " } }, @@ -417,15 +1096,17 @@ }, "DatastoreId":{ "type":"string", + "documentation":"

    The identifier of a data store.

    ", "max":32, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)" }, "DatastoreName":{ "type":"string", + "documentation":"

    The name of a data store.

    ", "max":256, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)" }, "DatastoreProperties":{ "type":"structure", @@ -454,7 +1135,7 @@ "documentation":"

    The data store status.

    " }, "CreatedAt":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    The time the data store was created.

    " }, "DatastoreTypeVersion":{ @@ -462,8 +1143,8 @@ "documentation":"

    The FHIR release version supported by the data store. Current support is for version R4.

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

    The AWS endpoint for the data store.

    " + "shape":"HealthLakeString", + "documentation":"

    The Amazon Web Services endpoint for the data store.

    " }, "SseConfiguration":{ "shape":"SseConfiguration", @@ -492,6 +1173,10 @@ "ProfileConfiguration":{ "shape":"ProfileConfiguration", "documentation":"

    The profile configuration for the data store.

    " + }, + "BackupStatusInfo":{ + "shape":"DatastoreBackupStatus", + "documentation":"

    The backup status information for the data store.

    " } }, "documentation":"

    The data store properties.

    " @@ -502,6 +1187,7 @@ }, "DatastoreStatus":{ "type":"string", + "documentation":"

    The status of a data store.

    ", "enum":[ "CREATING", "ACTIVE", @@ -512,9 +1198,48 @@ "UPDATE_FAILED" ] }, + "DateTime":{"type":"timestamp"}, + "DefaultEnabledBoolean":{ + "type":"boolean", + "documentation":"

    Specifies whether the feature is enabled. Defaults to true when not specified.

    ", + "box":true + }, "DefaultProfiles":{ "type":"list", - "member":{"shape":"String"} + "member":{"shape":"HealthLakeString"} + }, + "DeleteDataTransformationProfileRequest":{ + "type":"structure", + "required":["ProfileId"], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile to delete.

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

    The request parameters for the DeleteDataTransformationProfile operation.

    " + }, + "DeleteDataTransformationProfileResponse":{ + "type":"structure", + "required":[ + "ProfileId", + "DeletionTime" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the deleted profile.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the deleted profile.

    " + }, + "DeletionTime":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the profile was deleted.

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

    The response from the DeleteDataTransformationProfile operation.

    " }, "DeleteFHIRDatastoreRequest":{ "type":"structure", @@ -522,7 +1247,7 @@ "members":{ "DatastoreId":{ "shape":"DatastoreId", - "documentation":"

    The AWS-generated identifier for the data store to be deleted.

    " + "documentation":"

    The Amazon Web Services-generated identifier for the data store to be deleted.

    " } } }, @@ -537,11 +1262,11 @@ "members":{ "DatastoreId":{ "shape":"DatastoreId", - "documentation":"

    The AWS-generated ID for the deleted data store.

    " + "documentation":"

    The Amazon Web Services-generated ID for the deleted data store.

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

    The Amazon Resource Name (ARN) that grants access permission to AWS HealthLake.

    " + "documentation":"

    The Amazon Resource Name (ARN) that grants access permission to HealthLake.

    " }, "DatastoreStatus":{ "shape":"DatastoreStatus", @@ -549,10 +1274,32 @@ }, "DatastoreEndpoint":{ "shape":"BoundedLengthString", - "documentation":"

    The AWS endpoint of the data store to be deleted.

    " + "documentation":"

    The Amazon Web Services endpoint of the data store to be deleted.

    " } } }, + "DescribeDataTransformationJobRequest":{ + "type":"structure", + "required":["JobId"], + "members":{ + "JobId":{ + "shape":"DataTransformationJobId", + "documentation":"

    The unique identifier of the data transformation job to describe.

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

    The request parameters for the DescribeDataTransformationJob operation.

    " + }, + "DescribeDataTransformationJobResponse":{ + "type":"structure", + "required":["TransformationJobProperties"], + "members":{ + "TransformationJobProperties":{ + "shape":"TransformationJobProperties", + "documentation":"

    The properties of the data transformation job, including status, configuration, and progress information.

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

    The response from the DescribeDataTransformationJob operation.

    " + }, "DescribeFHIRDatastoreRequest":{ "type":"structure", "required":["DatastoreId"], @@ -629,6 +1376,7 @@ }, "EncryptionKeyID":{ "type":"string", + "documentation":"

    The identifier of an encryption key.

    ", "max":400, "min":1, "pattern":"(arn:aws((-us-gov)|(-iso)|(-iso-b)|(-cn))?:kms:)?([a-z]{2}-[a-z]+(-[a-z]+)?-\\d:)?(\\d{12}:)?(((key/)?[a-zA-Z0-9-_]+)|(alias/[a-zA-Z0-9:/_-]+))" @@ -659,6 +1407,24 @@ "max":4096, "min":1 }, + "ExistingVersionedProfileSource":{ + "type":"structure", + "required":[ + "ProfileId", + "Version" + ], + "members":{ + "ProfileId":{ + "shape":"String", + "documentation":"

    The unique identifier of the existing profile to clone from.

    " + }, + "Version":{ + "shape":"Integer", + "documentation":"

    The version number of the existing profile to clone from.

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

    Identifies an existing data transformation profile and version to clone when creating a new profile.

    " + }, "ExportJobProperties":{ "type":"structure", "required":[ @@ -682,11 +1448,11 @@ "documentation":"

    The export job status.

    " }, "SubmitTime":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    The time the export job was initiated.

    " }, "EndTime":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    The time the export job completed.

    " }, "DatastoreId":{ @@ -714,12 +1480,113 @@ }, "FHIRVersion":{ "type":"string", + "documentation":"

    The FHIR version supported by the data store.

    ", "enum":["R4"] }, - "GenericDouble":{"type":"double"}, - "GenericLong":{"type":"long"}, + "FailedDependencyException":{ + "type":"structure", + "members":{ + "Message":{ + "shape":"HealthLakeString", + "documentation":"

    A message describing the error.

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

    A dependent service failed to fulfill the request.

    ", + "exception":true + }, + "GenericDouble":{ + "type":"double", + "documentation":"

    A double-precision floating-point number.

    ", + "box":true + }, + "GenericLong":{ + "type":"long", + "documentation":"

    A long integer value.

    ", + "box":true + }, + "GetDataTransformationProfileRequest":{ + "type":"structure", + "required":["ProfileId"], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile to retrieve.

    " + }, + "ProfileVersion":{ + "shape":"ProfileVersion", + "documentation":"

    The version number to retrieve. Specify 0 to retrieve the DRAFT version. If you omit this parameter, the service returns the latest published version.

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

    The request parameters for the GetDataTransformationProfile operation.

    " + }, + "GetDataTransformationProfileResponse":{ + "type":"structure", + "required":[ + "ProfileId", + "Version", + "SourceFormat", + "TargetFormat", + "ProfileMapping", + "LastUpdatedAt" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile.

    " + }, + "Version":{ + "shape":"ProfileVersion", + "documentation":"

    The version number of the retrieved profile.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format of the profile.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format of the profile.

    " + }, + "ProfileMapping":{ + "shape":"ProfileMapping", + "documentation":"

    The profile content as a map of file paths to content strings.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the profile.

    " + }, + "ProfileDescription":{ + "shape":"ProfileDescription", + "documentation":"

    The description of the profile.

    " + }, + "ChangeDescription":{ + "shape":"ChangeDescription", + "documentation":"

    A description of what changed in this version.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when this version was last updated.

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

    The response from the GetDataTransformationProfile operation.

    " + }, + "HealthLakeBoolean":{ + "type":"boolean", + "documentation":"

    A boolean value.

    " + }, + "HealthLakeString":{ + "type":"string", + "documentation":"

    A general-purpose string value.

    ", + "max":10000, + "min":0, + "pattern":"[\\P{M}\\p{M}]{0,10000}" + }, + "HealthLakeTimestamp":{ + "type":"timestamp", + "documentation":"

    A timestamp value.

    " + }, "IamRoleArn":{ "type":"string", + "documentation":"

    The IAM role ARN for data access.

    ", "max":2048, "min":20, "pattern":"arn:aws(-[^:]+)?:iam::[0-9]{12}:role/.+" @@ -730,10 +1597,10 @@ "members":{ "AuthorizationStrategy":{ "shape":"AuthorizationStrategy", - "documentation":"

    The authorization strategy selected when the HealthLake data store is created.

    HealthLake provides support for both SMART on FHIR V1 and V2 as described below.

    • SMART_ON_FHIR_V1 – Support for only SMART on FHIR V1, which includes read (read/search) and write (create/update/delete) permissions.

    • SMART_ON_FHIR – Support for both SMART on FHIR V1 and V2, which includes create, read, update, delete, and search permissions.

    • AWS_AUTH – The default HealthLake authorization strategy; not affiliated with SMART on FHIR.

    " + "documentation":"

    The authorization strategy selected when the HealthLake data store is created.

    HealthLake provides support for both SMART on FHIR V1 and V2 as described below.

    • SMART_ON_FHIR_V1 – Support for only SMART on FHIR V1, which includes read (read/search) and write (create/update/delete) permissions.

    • SMART_ON_FHIR – Support for both SMART on FHIR V1 and V2, which includes create, read, update, delete, and search permissions.

    • Amazon Web Services_AUTH – The default HealthLake authorization strategy; not affiliated with SMART on FHIR.

    " }, "FineGrainedAuthorizationEnabled":{ - "shape":"Boolean", + "shape":"HealthLakeBoolean", "documentation":"

    The parameter to enable SMART on FHIR fine-grained authorization for the data store.

    " }, "Metadata":{ @@ -770,11 +1637,11 @@ "documentation":"

    The import job status.

    " }, "SubmitTime":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    The time the import job was submitted for processing.

    " }, "EndTime":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    The time the import job was completed.

    " }, "DatastoreId":{ @@ -792,7 +1659,7 @@ }, "DataAccessRoleArn":{ "shape":"IamRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) that grants AWS HealthLake access to the input data.

    " + "documentation":"

    The Amazon Resource Name (ARN) that grants HealthLake access to the input data.

    " }, "Message":{ "shape":"Message", @@ -814,16 +1681,20 @@ "members":{ "S3Uri":{ "shape":"S3Uri", - "documentation":"

    The S3Uri is the user-specified S3 location of the FHIR data to be imported into AWS HealthLake.

    " + "documentation":"

    The S3Uri is the user-specified Amazon S3 location of the FHIR data to be imported into HealthLake.

    " } }, "documentation":"

    The import job input properties.

    ", "union":true }, + "Integer":{ + "type":"integer", + "box":true + }, "InternalServerException":{ "type":"structure", "members":{ - "Message":{"shape":"String"} + "Message":{"shape":"HealthLakeString"} }, "documentation":"

    An unknown internal error occurred in the service.

    ", "exception":true, @@ -831,26 +1702,28 @@ }, "JobId":{ "type":"string", + "documentation":"

    The unique identifier of a job.

    ", "max":32, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)" }, "JobName":{ "type":"string", + "documentation":"

    The human-readable name of a job.

    ", "max":64, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)" }, "JobProgressReport":{ "type":"structure", "members":{ "TotalNumberOfScannedFiles":{ "shape":"GenericLong", - "documentation":"

    The number of files scanned from the S3 input bucket.

    " + "documentation":"

    The number of files scanned from the Amazon S3 input bucket.

    " }, "TotalSizeOfScannedFilesInMB":{ "shape":"GenericDouble", - "documentation":"

    The size (in MB) of files scanned from the S3 input bucket.

    " + "documentation":"

    The size (in MB) of files scanned from the Amazon S3 input bucket.

    " }, "TotalNumberOfImportedFiles":{ "shape":"GenericLong", @@ -858,7 +1731,7 @@ }, "TotalNumberOfResourcesScanned":{ "shape":"GenericLong", - "documentation":"

    The number of resources scanned from the S3 input bucket.

    " + "documentation":"

    The number of resources scanned from the Amazon S3 input bucket.

    " }, "TotalNumberOfResourcesImported":{ "shape":"GenericLong", @@ -870,17 +1743,54 @@ }, "TotalNumberOfFilesReadWithCustomerError":{ "shape":"GenericLong", - "documentation":"

    The number of files that failed to be read from the S3 input bucket due to customer error.

    " + "documentation":"

    The number of files that failed to be read from the Amazon S3 input bucket due to customer error.

    " + }, + "TotalNumberOfScannedNonFhirFiles":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR files scanned from the Amazon S3 input bucket.

    " + }, + "TotalSizeOfScannedNonFhirFilesInMB":{ + "shape":"GenericDouble", + "documentation":"

    The size (in MB) of non-FHIR files scanned from the Amazon S3 input bucket.

    " + }, + "TotalNumberOfImportedNonFhirFiles":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR files imported.

    " + }, + "TotalNumberOfNonFhirResourcesScanned":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR resources scanned from the Amazon S3 input bucket.

    " + }, + "TotalNumberOfNonFhirResourcesImported":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR resources imported.

    " + }, + "TotalNumberOfNonFhirResourcesWithCustomerError":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR resources that failed due to customer error.

    " + }, + "TotalNumberOfNonFhirFilesReadWithCustomerError":{ + "shape":"GenericLong", + "documentation":"

    The number of non-FHIR files that failed to be read from the Amazon S3 input bucket due to customer error.

    " }, "Throughput":{ "shape":"GenericDouble", "documentation":"

    The transaction rate the import job is processed at.

    " + }, + "TotalFilesConverted":{ + "shape":"GenericLong", + "documentation":"

    Number of CCDA files successfully transformed during the import's transformation phase. Populated only for import jobs that use the two-Step-Function (transformation + ingestion) flow; null for legacy single-SF imports and for pure FHIR imports that skip transformation.

    " + }, + "TotalResourcesGenerated":{ + "shape":"GenericLong", + "documentation":"

    Number of FHIR resources produced by the transformation phase. Populated only for import jobs that use the two-Step-Function flow; null for legacy single-SF imports and for pure FHIR imports.

    " } }, "documentation":"

    The progress report for the import job.

    " }, "JobStatus":{ "type":"string", + "documentation":"

    The status of a job.

    ", "enum":[ "SUBMITTED", "QUEUED", @@ -907,7 +1817,12 @@ "documentation":"

    The Key Management Service (KMS) encryption key id/alias used to encrypt the data store contents at rest.

    " } }, - "documentation":"

    The customer-managed-key (CMK) used when creating a data store. If a customer-owned key is not specified, an AWS-owned key is used for encryption.

    " + "documentation":"

    The customer-managed-key (CMK) used when creating a data store. If a customer-owned key is not specified, an Amazon Web Services-owned key is used for encryption.

    " + }, + "KmsKeyId":{ + "type":"string", + "max":2048, + "min":1 }, "LambdaArn":{ "type":"string", @@ -915,6 +1830,119 @@ "min":49, "pattern":"arn:aws:lambda:[a-z]{2}-[a-z]+-\\d{1}:\\d{12}:function:[a-zA-Z0-9\\-_\\.]+(:(\\$LATEST|[a-zA-Z0-9\\-_]+))?" }, + "ListDataTransformationJobsRequest":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of jobs to return per page. If you don't specify a value, the service returns up to 100 results.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token from a previous response. Pass this value to retrieve the next page of results.

    " + }, + "JobStatus":{ + "shape":"TransformationJobStatus", + "documentation":"

    Filters the results to include only jobs with the specified status.

    " + }, + "JobName":{ + "shape":"DataTransformationJobName", + "documentation":"

    Filters the results to include only jobs with the specified name.

    " + }, + "SubmittedAfter":{ + "shape":"DateTime", + "documentation":"

    Filters the results to include only jobs submitted at or after this timestamp.

    " + }, + "SubmittedBefore":{ + "shape":"DateTime", + "documentation":"

    Filters the results to include only jobs submitted at or before this timestamp.

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

    The request parameters for the ListDataTransformationJobs operation.

    " + }, + "ListDataTransformationJobsResponse":{ + "type":"structure", + "required":["Items"], + "members":{ + "Items":{ + "shape":"TransformationJobSummaryList", + "documentation":"

    The list of data transformation job summaries.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token to use in the next request. If this value is null, there are no more results.

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

    The response from the ListDataTransformationJobs operation.

    " + }, + "ListDataTransformationProfileVersionsRequest":{ + "type":"structure", + "required":["ProfileId"], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile whose versions to list.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of profile versions to return per page. If you don't specify a value, the service returns up to 100 results.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token from a previous response. Pass this value to retrieve the next page of results.

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

    The request parameters for the ListDataTransformationProfileVersions operation.

    " + }, + "ListDataTransformationProfileVersionsResponse":{ + "type":"structure", + "required":["Items"], + "members":{ + "Items":{ + "shape":"DataTransformationProfileVersionSummaryList", + "documentation":"

    The list of data transformation profile version summaries.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token to use in the next request. If this value is null, there are no more results.

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

    The response from the ListDataTransformationProfileVersions operation.

    " + }, + "ListDataTransformationProfilesRequest":{ + "type":"structure", + "required":["SourceFormat"], + "members":{ + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    Filters the results by source data format.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of profiles to return per page. If you don't specify a value, the service returns up to 100 results.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token from a previous response. Pass this value to retrieve the next page of results.

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

    The request parameters for the ListDataTransformationProfiles operation.

    " + }, + "ListDataTransformationProfilesResponse":{ + "type":"structure", + "required":["Items"], + "members":{ + "Items":{ + "shape":"DataTransformationProfileSummaryList", + "documentation":"

    The list of data transformation profile summaries.

    " + }, + "NextToken":{ + "shape":"DataTransformationNextToken", + "documentation":"

    The pagination token to use in the next request. If this value is null, there are no more results.

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

    The response from the ListDataTransformationProfiles operation.

    " + }, "ListFHIRDatastoresRequest":{ "type":"structure", "members":{ @@ -971,11 +1999,11 @@ "documentation":"

    Limits the response to export jobs with the specified job status.

    " }, "SubmittedBefore":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Limits the response to FHIR export jobs submitted before a user- specified date.

    " }, "SubmittedAfter":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Limits the response to FHIR export jobs submitted after a user-specified date.

    " } } @@ -1019,11 +2047,11 @@ "documentation":"

    Limits the response to the import job with the specified job status.

    " }, "SubmittedBefore":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Limits the response to FHIR import jobs submitted before a user- specified date.

    " }, "SubmittedAfter":{ - "shape":"Timestamp", + "shape":"HealthLakeTimestamp", "documentation":"

    Limits the response to FHIR import jobs submitted after a user-specified date.

    " } } @@ -1061,20 +2089,35 @@ } } }, + "Long":{ + "type":"long", + "box":true + }, + "MaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, "MaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return per page.

    ", + "box":true, "max":500, "min":1 }, "Message":{ "type":"string", + "documentation":"

    A message associated with a job or error.

    ", "max":2048, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-%@]*)" }, "NextToken":{ "type":"string", + "documentation":"

    An opaque pagination token.

    ", "max":8192, + "min":0, "pattern":"\\p{ASCII}{0,8192}" }, "NlpConfiguration":{ @@ -1091,11 +2134,21 @@ "type":"string", "enum":[ "ENABLED", - "DISABLED", "ENABLING", + "DISABLED", "DISABLING" ] }, + "NotImplementedOperationException":{ + "type":"structure", + "required":["Message"], + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    The requested operation is not yet available. Check the service documentation for a list of supported operations.

    ", + "exception":true, + "fault":true + }, "OutputDataConfig":{ "type":"structure", "members":{ @@ -1120,6 +2173,7 @@ }, "PreloadDataType":{ "type":"string", + "documentation":"

    The type of preloaded data.

    ", "enum":["SYNTHEA"] }, "ProfileConfiguration":{ @@ -1129,16 +2183,219 @@ "shape":"DefaultProfiles", "documentation":"

    The list of default profiles for the data store.

    " } - }, - "documentation":"

    The profile configuration for a data store.

    " + }, + "documentation":"

    The profile configuration for a data store.

    " + }, + "ProfileDescription":{ + "type":"string", + "max":1000, + "min":0 + }, + "ProfileIdString":{ + "type":"string", + "max":32, + "min":32, + "pattern":"[a-f0-9]{32}" + }, + "ProfileMapping":{ + "type":"map", + "key":{"shape":"ProfileMappingKey"}, + "value":{"shape":"ProfileMappingValue"}, + "max":500, + "min":1, + "sensitive":true + }, + "ProfileMappingKey":{ + "type":"string", + "max":500, + "min":1 + }, + "ProfileMappingSource":{ + "type":"structure", + "required":["ProfileMapping"], + "members":{ + "ProfileMapping":{ + "shape":"StringMap", + "documentation":"

    The content as a map of file paths to profile strings.

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

    Contains raw content to use as the source when creating a data transformation profile directly from a mapping.

    ", + "sensitive":true + }, + "ProfileMappingValue":{ + "type":"string", + "max":102400, + "min":0 + }, + "ProfileNameString":{ + "type":"string", + "max":256, + "min":1 + }, + "ProfileVersion":{ + "type":"integer", + "box":true, + "max":99, + "min":0 + }, + "PublishDataTransformationProfileRequest":{ + "type":"structure", + "required":[ + "ProfileId", + "SourceFormat" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile to publish.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format of the profile.

    " + }, + "FromExistingVersion":{ + "shape":"ProfileVersion", + "documentation":"

    The version number of a previously published version to republish as the new latest version. Use this parameter for rollback scenarios. If you omit this parameter, the service publishes the current DRAFT version.

    " + }, + "ChangeDescription":{ + "shape":"ChangeDescription", + "documentation":"

    A description of what changed or why this version is being published.

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

    The request parameters for the PublishDataTransformationProfile operation.

    " + }, + "PublishDataTransformationProfileResponse":{ + "type":"structure", + "required":[ + "ProfileId", + "Version", + "SourceFormat", + "TargetFormat", + "LastUpdatedAt" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the published profile.

    " + }, + "Version":{ + "shape":"ProfileVersion", + "documentation":"

    The new version number that was created.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format of the profile.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format of the profile.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the published profile.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the profile was last updated.

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

    The response from the PublishDataTransformationProfile operation.

    " + }, + "ResourceNotFoundException":{ + "type":"structure", + "members":{ + "Message":{"shape":"HealthLakeString"} + }, + "documentation":"

    The requested data store was not found.

    ", + "exception":true + }, + "RestoreConfiguration":{ + "type":"structure", + "members":{ + "ContinuousBackupRestoreConfiguration":{ + "shape":"ContinuousBackupRestoreConfiguration", + "documentation":"

    Configuration for restoring from continuous backup to a specific point in time.

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

    Specifies the type and parameters for the restore operation.

    ", + "union":true + }, + "RestoreFHIRDatastoreRequest":{ + "type":"structure", + "required":[ + "SourceDatastoreId", + "RestoreConfiguration" + ], + "members":{ + "SourceDatastoreId":{ + "shape":"DatastoreId", + "documentation":"

    The identifier of the source data store to restore from.

    " + }, + "RestoreConfiguration":{ + "shape":"RestoreConfiguration", + "documentation":"

    The restore configuration specifying the type and parameters for the restore.

    " + }, + "DatastoreName":{ + "shape":"DatastoreName", + "documentation":"

    The name for the restored data store.

    " + }, + "SseConfiguration":{ + "shape":"SseConfiguration", + "documentation":"

    The server-side encryption key configuration for the restored data store.

    " + }, + "ClientToken":{ + "shape":"ClientTokenString", + "documentation":"

    An optional user-provided token to ensure API idempotency of the restore.

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

    The resource tags applied to the restored data store.

    " + }, + "IdentityProviderConfiguration":{ + "shape":"IdentityProviderConfiguration", + "documentation":"

    The identity provider configuration for the restored data store.

    " + }, + "AnalyticsConfiguration":{ + "shape":"AnalyticsConfiguration", + "documentation":"

    The analytics configuration for the restored data store.

    " + }, + "NlpConfiguration":{ + "shape":"NlpConfiguration", + "documentation":"

    The NLP configuration for the restored data store.

    " + }, + "ProfileConfiguration":{ + "shape":"ProfileConfiguration", + "documentation":"

    The profile configuration for the restored data store.

    " + } + } }, - "ResourceNotFoundException":{ + "RestoreFHIRDatastoreResponse":{ "type":"structure", + "required":[ + "DatastoreId", + "DatastoreArn", + "DatastoreStatus", + "DatastoreEndpoint" + ], "members":{ - "Message":{"shape":"String"} - }, - "documentation":"

    The requested data store was not found.

    ", - "exception":true + "DatastoreId":{ + "shape":"DatastoreId", + "documentation":"

    The restored data store identifier.

    " + }, + "DatastoreArn":{ + "shape":"DatastoreArn", + "documentation":"

    The Amazon Resource Name (ARN) for the restored data store.

    " + }, + "DatastoreStatus":{ + "shape":"DatastoreStatus", + "documentation":"

    The restored data store status.

    " + }, + "DatastoreEndpoint":{ + "shape":"BoundedLengthString", + "documentation":"

    The AWS endpoint for the restored data store.

    " + } + } }, "S3Configuration":{ "type":"structure", @@ -1149,20 +2406,57 @@ "members":{ "S3Uri":{ "shape":"S3Uri", - "documentation":"

    The S3Uri is the user-specified S3 location of the FHIR data to be imported into AWS HealthLake.

    " + "documentation":"

    The S3Uri is the user-specified Amazon S3 location of the FHIR data to be imported into HealthLake.

    " }, "KmsKeyId":{ "shape":"EncryptionKeyID", - "documentation":"

    The Key Management Service (KMS) key ID used to access the S3 bucket.

    " + "documentation":"

    The Key Management Service (KMS) key ID used to access the Amazon S3 bucket.

    " } }, - "documentation":"

    The configuration of the S3 bucket for either an import or export job. This includes assigning access permissions.

    " + "documentation":"

    The configuration of the Amazon S3 bucket for either an import or export job. This includes assigning access permissions.

    " }, "S3Uri":{ "type":"string", + "documentation":"

    The S3 URI for data import or export.

    ", "max":1024, + "min":0, "pattern":"s3://[a-z0-9][\\.\\-a-z0-9]{1,61}[a-z0-9](/.*)?" }, + "SampleDataS3Uri":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"s3://[a-z0-9][a-z0-9.\\-]{1,61}[a-z0-9](/.*)?" + }, + "SampleDataSource":{ + "type":"structure", + "required":["S3Uri"], + "members":{ + "S3Uri":{ + "shape":"SampleDataS3Uri", + "documentation":"

    The Amazon S3 URI of the sample data file.

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

    Identifies a sample data file in Amazon S3 to use as the source when creating a data transformation profile. Valid only when the source format is Comma-separated values (CSV).

    " + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "members":{ + "Message":{ + "shape":"HealthLakeString", + "documentation":"

    A message describing the error.

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

    The request exceeds the service quota.

    ", + "exception":true + }, + "SourceFormat":{ + "type":"string", + "enum":[ + "CCDA", + "CSV" + ] + }, "SseConfiguration":{ "type":"structure", "required":["KmsEncryptionConfig"], @@ -1174,6 +2468,69 @@ }, "documentation":"

    The server-side encryption key configuration for a customer-provided encryption key.

    " }, + "StartDataTransformationJobRequest":{ + "type":"structure", + "required":[ + "InputDataConfig", + "OutputDataConfig", + "DataAccessRoleArn", + "ClientToken", + "ProfileId" + ], + "members":{ + "InputDataConfig":{ + "shape":"TransformationInputDataConfig", + "documentation":"

    The Amazon S3 location and format of the source files to transform.

    " + }, + "OutputDataConfig":{ + "shape":"TransformationOutputDataConfig", + "documentation":"

    The Amazon S3 output location and Amazon Web Services Key Management Service (Amazon Web Services KMS) encryption configuration.

    " + }, + "DataAccessRoleArn":{ + "shape":"DataTransformationIamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Web Services Identity and Access Management (IAM) role that HealthLake assumes to read from and write to the specified Amazon S3 locations.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request but does not return an error.

    " + }, + "JobName":{ + "shape":"DataTransformationJobName", + "documentation":"

    A descriptive name for the data transformation job.

    " + }, + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the data transformation profile to use for conversion.

    " + }, + "DriftDetectionEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether drift detection is enabled for this job. When enabled, HealthLake writes a drift report to the output Amazon S3 location alongside the converted files.

    " + }, + "ProvenanceEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether FHIR R4 Provenance resource generation is enabled for this transformation job. When provenance is enabled, the service also generates related DocumentReference and Device resources. If you don't specify a value, the default is true. To disable provenance output, set this parameter to false.

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

    The request parameters for the StartDataTransformationJob operation.

    " + }, + "StartDataTransformationJobResponse":{ + "type":"structure", + "required":[ + "JobId", + "JobStatus" + ], + "members":{ + "JobId":{ + "shape":"DataTransformationJobId", + "documentation":"

    The unique identifier assigned to the data transformation job.

    " + }, + "JobStatus":{ + "shape":"TransformationJobStatus", + "documentation":"

    The initial status of the data transformation job.

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

    The response from the StartDataTransformationJob operation.

    " + }, "StartFHIRExportJobRequest":{ "type":"structure", "required":[ @@ -1250,7 +2607,7 @@ }, "DataAccessRoleArn":{ "shape":"IamRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) that grants access permission to AWS HealthLake.

    " + "documentation":"

    The Amazon Resource Name (ARN) that grants access permission to HealthLake.

    " }, "ClientToken":{ "shape":"ClientTokenString", @@ -1260,6 +2617,22 @@ "ValidationLevel":{ "shape":"ValidationLevel", "documentation":"

    The validation level of the import job.

    " + }, + "ProfileId":{ + "shape":"BoundedLengthString", + "documentation":"

    The data transformation profile identifier to use for the import job.

    " + }, + "InputFormat":{ + "shape":"BoundedLengthString", + "documentation":"

    The input format of the data to be imported.

    " + }, + "DriftDetectionEnabled":{ + "shape":"HealthLakeBoolean", + "documentation":"

    Specifies whether to enable drift detection for the import job.

    " + }, + "ProvenanceEnabled":{ + "shape":"DefaultEnabledBoolean", + "documentation":"

    Specifies whether to enable provenance for the import job.

    " } } }, @@ -1284,10 +2657,22 @@ } } }, - "String":{ - "type":"string", - "max":10000, - "pattern":"[\\P{M}\\p{M}]{0,10000}" + "StarterProfileSource":{ + "type":"structure", + "required":["StarterProfileName"], + "members":{ + "StarterProfileName":{ + "shape":"String", + "documentation":"

    The name of the built-in starter profile.

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

    Identifies a built-in starter profile to use as the source when creating a data transformation profile. Valid only when the source format is Consolidated Clinical Document Architecture (C-CDA).

    " + }, + "String":{"type":"string"}, + "StringMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} }, "Tag":{ "type":"structure", @@ -1311,7 +2696,7 @@ "type":"string", "max":128, "min":1, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)" }, "TagKeyList":{ "type":"list", @@ -1325,6 +2710,14 @@ "max":200, "min":0 }, + "TagMap":{ + "type":"map", + "key":{"shape":"DataTransformationTagKey"}, + "value":{"shape":"DataTransformationTagValue"}, + "documentation":"

    A map of tag keys to tag values associated with the resource.

    ", + "max":50, + "min":0 + }, "TagResourceRequest":{ "type":"structure", "required":[ @@ -1350,17 +2743,216 @@ "type":"string", "max":256, "min":0, - "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$" + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)" + }, + "TargetFormat":{ + "type":"string", + "enum":["FHIR_R4"] }, "ThrottlingException":{ "type":"structure", "members":{ - "Message":{"shape":"String"} + "Message":{"shape":"HealthLakeString"} }, "documentation":"

    The user has exceeded their maximum number of allowed calls to the given API.

    ", "exception":true }, - "Timestamp":{"type":"timestamp"}, + "TransformationInputDataConfig":{ + "type":"structure", + "required":["S3Uri"], + "members":{ + "S3Uri":{ + "shape":"DataTransformationS3Uri", + "documentation":"

    The Amazon S3 URI of the input data to transform.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The format of the source data files (C-CDA or CSV).

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

    The Amazon S3 location and source format configuration for input data in a transformation job.

    " + }, + "TransformationJobProgressReport":{ + "type":"structure", + "required":[ + "TotalFilesScanned", + "TotalFilesConverted", + "TotalFilesFailed", + "TotalResourcesGenerated" + ], + "members":{ + "TotalFilesScanned":{ + "shape":"Long", + "documentation":"

    The total number of source files scanned by the job.

    " + }, + "TotalFilesConverted":{ + "shape":"Long", + "documentation":"

    The total number of source files successfully converted.

    " + }, + "TotalFilesFailed":{ + "shape":"Long", + "documentation":"

    The total number of source files that failed conversion.

    " + }, + "TotalResourcesGenerated":{ + "shape":"Long", + "documentation":"

    The total number of FHIR R4 resources generated across all converted files.

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

    Contains progress metrics for a data transformation job, including counts of files scanned, converted, and failed.

    " + }, + "TransformationJobProperties":{ + "type":"structure", + "required":[ + "JobId", + "JobStatus", + "InputDataConfig", + "OutputDataConfig", + "DataAccessRoleArn", + "SubmitTime" + ], + "members":{ + "JobId":{ + "shape":"DataTransformationJobId", + "documentation":"

    The unique identifier of the data transformation job.

    " + }, + "JobStatus":{ + "shape":"TransformationJobStatus", + "documentation":"

    The current status of the data transformation job.

    " + }, + "InputDataConfig":{ + "shape":"TransformationInputDataConfig", + "documentation":"

    The Amazon S3 location and format of the source files for this job.

    " + }, + "OutputDataConfig":{ + "shape":"TransformationOutputDataConfig", + "documentation":"

    The Amazon S3 location and encryption configuration for the converted output.

    " + }, + "DataAccessRoleArn":{ + "shape":"DataTransformationIamRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Web Services Identity and Access Management (IAM) role that grants HealthLake access to the specified Amazon S3 locations. HealthLake assumes this role to read input files and write output files.

    " + }, + "SubmitTime":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the job was submitted.

    " + }, + "JobName":{ + "shape":"DataTransformationJobName", + "documentation":"

    The name of the data transformation job.

    " + }, + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the data transformation profile used for this job.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the data transformation profile used for this job.

    " + }, + "ProfileVersion":{ + "shape":"Integer", + "documentation":"

    The version number of the data transformation profile used for this job.

    " + }, + "EndTime":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the job completed or failed.

    " + }, + "DriftDetectionEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether drift detection is enabled for this job. When enabled, HealthLake writes a drift report to the output Amazon S3 location alongside the converted files.

    " + }, + "ProvenanceEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether FHIR R4 Provenance resource generation is enabled for this transformation job. When provenance is enabled, the service also generates related DocumentReference and Device resources.

    " + }, + "Message":{ + "shape":"BoundedString", + "documentation":"

    An informational message about the job, such as an error description if the job failed.

    " + }, + "JobProgressReport":{ + "shape":"TransformationJobProgressReport", + "documentation":"

    The progress report for the data transformation job, including counts of files processed and resources generated.

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

    Contains the properties of a data transformation job, including its status, configuration, and progress information. You retrieve this structure by calling DescribeDataTransformationJob.

    " + }, + "TransformationJobStatus":{ + "type":"string", + "enum":[ + "SUBMITTED", + "QUEUED", + "IN_PROGRESS", + "COMPLETED", + "COMPLETED_WITH_ERRORS", + "FAILED" + ] + }, + "TransformationJobSummary":{ + "type":"structure", + "required":[ + "JobId", + "JobStatus", + "SubmitTime" + ], + "members":{ + "JobId":{ + "shape":"DataTransformationJobId", + "documentation":"

    The unique identifier of the job.

    " + }, + "JobStatus":{ + "shape":"TransformationJobStatus", + "documentation":"

    The current status of the job.

    " + }, + "SubmitTime":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the job was submitted.

    " + }, + "JobName":{ + "shape":"DataTransformationJobName", + "documentation":"

    The name of the job.

    " + }, + "EndTime":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the job completed.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format for this job.

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

    Contains summary information about a data transformation job. To retrieve full job details, call DescribeDataTransformationJob.

    " + }, + "TransformationJobSummaryList":{ + "type":"list", + "member":{"shape":"TransformationJobSummary"} + }, + "TransformationOutputDataConfig":{ + "type":"structure", + "required":["S3Configuration"], + "members":{ + "S3Configuration":{ + "shape":"DataTransformationS3Configuration", + "documentation":"

    The Amazon S3 output location and Amazon Web Services Key Management Service (Amazon Web Services KMS) encryption configuration.

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

    The Amazon S3 output location and encryption configuration for a transformation job.

    " + }, + "UnauthorizedException":{ + "type":"structure", + "required":["Message"], + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    You are not authorized to make this request. Verify that your Amazon Web Services credentials are valid and that you have the required permissions.

    ", + "exception":true + }, + "UnsupportedMIMETypeException":{ + "type":"structure", + "required":["Message"], + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    The content type in your request is not supported. Use a supported content type for this operation.

    ", + "exception":true + }, "UntagResourceRequest":{ "type":"structure", "required":[ @@ -1382,6 +2974,60 @@ "type":"structure", "members":{} }, + "UpdateDataTransformationProfileRequest":{ + "type":"structure", + "required":[ + "ProfileId", + "ProfileMapping" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile to update.

    " + }, + "ProfileMapping":{ + "shape":"ProfileMapping", + "documentation":"

    The new profile content for the DRAFT version. This is a full replacement of all profile files.

    " + }, + "ChangeDescription":{ + "shape":"ChangeDescription", + "documentation":"

    A description of what changed in this update.

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

    The request parameters for the UpdateDataTransformationProfile operation.

    " + }, + "UpdateDataTransformationProfileResponse":{ + "type":"structure", + "required":[ + "ProfileId", + "SourceFormat", + "TargetFormat", + "LastUpdatedAt" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the updated profile.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format of the profile.

    " + }, + "TargetFormat":{ + "shape":"TargetFormat", + "documentation":"

    The target output format of the profile.

    " + }, + "ProfileName":{ + "shape":"ProfileNameString", + "documentation":"

    The name of the updated profile.

    " + }, + "LastUpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the profile was last updated.

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

    The response from the UpdateDataTransformationProfile operation.

    " + }, "UpdateFHIRDatastoreRequest":{ "type":"structure", "required":["DatastoreId"], @@ -1394,14 +3040,14 @@ "shape":"DatastoreName", "documentation":"

    The data store name.

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

    The natural language processing (NLP) configuration for the data store.

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

    The analytics configuration for the data store.

    " }, + "NlpConfiguration":{ + "shape":"NlpConfiguration", + "documentation":"

    The natural language processing (NLP) configuration for the data store.

    " + }, "ProfileConfiguration":{ "shape":"ProfileConfiguration", "documentation":"

    The profile configuration for the data store.

    " @@ -1409,6 +3055,10 @@ "IdentityProviderConfiguration":{ "shape":"IdentityProviderConfiguration", "documentation":"

    The identity provider configuration for the data store.

    " + }, + "BackupConfiguration":{ + "shape":"BackupConfiguration", + "documentation":"

    The backup configuration for the data store.

    " } } }, @@ -1422,16 +3072,62 @@ } } }, + "UpdateProfileWithAgentRequest":{ + "type":"structure", + "required":[ + "ProfileId", + "SourceFormat", + "InputMessage" + ], + "members":{ + "ProfileId":{ + "shape":"ProfileIdString", + "documentation":"

    The unique identifier of the profile to update via the agent.

    " + }, + "SourceFormat":{ + "shape":"SourceFormat", + "documentation":"

    The source data format for the transformation.

    " + }, + "InputMessage":{ + "shape":"AgentInputMessage", + "documentation":"

    The message to send to the agent.

    " + }, + "ConversationId":{ + "shape":"ConversationIdString", + "documentation":"

    The conversation identifier for multi-turn interactions. Omit to start a new conversation.

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

    The request parameters for the UpdateProfileWithAgent operation.

    " + }, + "UpdateProfileWithAgentResponse":{ + "type":"structure", + "required":[ + "AgentResponse", + "ConversationId" + ], + "members":{ + "AgentResponse":{ + "shape":"AgentOutputMessage", + "documentation":"

    The response message from the agent.

    " + }, + "ConversationId":{ + "shape":"ConversationIdString", + "documentation":"

    The conversation identifier to use for follow-up messages in this conversation.

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

    The response from the UpdateProfileWithAgent operation.

    " + }, "ValidationException":{ "type":"structure", "members":{ - "Message":{"shape":"String"} + "Message":{"shape":"HealthLakeString"} }, "documentation":"

    The user input parameter was invalid.

    ", "exception":true }, "ValidationLevel":{ "type":"string", + "documentation":"

    The level of FHIR validation to apply.

    ", "enum":[ "strict", "structure-only", @@ -1439,5 +3135,5 @@ ] } }, - "documentation":"

    This is the AWS HealthLake API Reference. For an introduction to the service, see What is AWS HealthLake? in the AWS HealthLake Developer Guide.

    " + "documentation":"

    This is the HealthLake API Reference. For an introduction to the service, see What is HealthLake? in the HealthLake Developer Guide.

    " } diff --git a/services/healthlake/src/main/resources/codegen-resources/waiters-2.json b/services/healthlake/src/main/resources/codegen-resources/waiters-2.json index ba6478fa841e..60b26c0b4b56 100644 --- a/services/healthlake/src/main/resources/codegen-resources/waiters-2.json +++ b/services/healthlake/src/main/resources/codegen-resources/waiters-2.json @@ -1,105 +1,114 @@ { - "version": 2, - "waiters": { - "FHIRDatastoreActive": { - "operation": "DescribeFHIRDatastore", - "delay": 60, - "maxAttempts": 360, - "acceptors": [ - { - "state": "success", - "matcher": "path", - "argument": "DatastoreProperties.DatastoreStatus", - "expected": "ACTIVE" - }, - { - "state": "failure", - "matcher": "path", - "argument": "DatastoreProperties.DatastoreStatus", - "expected": "CREATE_FAILED" - }, - { - "state": "failure", - "matcher": "path", - "argument": "DatastoreProperties.DatastoreStatus", - "expected": "DELETED" - } - ] + "version" : 2, + "waiters" : { + "DataTransformationJobCompleted" : { + "delay" : 30, + "maxAttempts" : 5, + "operation" : "DescribeDataTransformationJob", + "acceptors" : [ { + "matcher" : "path", + "argument" : "TransformationJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED" + }, { + "matcher" : "path", + "argument" : "TransformationJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED_WITH_ERRORS" + }, { + "matcher" : "path", + "argument" : "TransformationJobProperties.JobStatus", + "state" : "failure", + "expected" : "FAILED" + }, { + "matcher" : "error", + "state" : "failure", + "expected" : "ResourceNotFoundException" + } ] }, - "FHIRDatastoreDeleted": { - "operation": "DescribeFHIRDatastore", - "delay": 120, - "maxAttempts": 360, - "acceptors": [ - { - "state": "success", - "matcher": "path", - "argument": "DatastoreProperties.DatastoreStatus", - "expected": "DELETED" - } - ] + "FHIRDatastoreActive" : { + "delay" : 60, + "maxAttempts" : 5, + "operation" : "DescribeFHIRDatastore", + "acceptors" : [ { + "matcher" : "path", + "argument" : "DatastoreProperties.DatastoreStatus", + "state" : "success", + "expected" : "ACTIVE" + }, { + "matcher" : "path", + "argument" : "DatastoreProperties.DatastoreStatus", + "state" : "failure", + "expected" : "CREATE_FAILED" + }, { + "matcher" : "path", + "argument" : "DatastoreProperties.DatastoreStatus", + "state" : "failure", + "expected" : "DELETED" + } ] }, - "FHIRExportJobCompleted": { - "operation": "DescribeFHIRExportJob", - "delay": 120, - "maxAttempts": 360, - "acceptors": [ - { - "state": "success", - "matcher": "path", - "argument": "ExportJobProperties.JobStatus", - "expected": "COMPLETED" - }, - { - "state": "success", - "matcher": "path", - "argument": "ExportJobProperties.JobStatus", - "expected": "COMPLETED_WITH_ERRORS" - }, - { - "state": "failure", - "matcher": "path", - "argument": "ExportJobProperties.JobStatus", - "expected": "CANCEL_COMPLETED" - }, - { - "state": "failure", - "matcher": "path", - "argument": "ExportJobProperties.JobStatus", - "expected": "FAILED" - }, - { - "state": "failure", - "matcher": "path", - "argument": "ExportJobProperties.JobStatus", - "expected": "CANCEL_FAILED" - } - ] + "FHIRDatastoreDeleted" : { + "delay" : 120, + "maxAttempts" : 5, + "operation" : "DescribeFHIRDatastore", + "acceptors" : [ { + "matcher" : "path", + "argument" : "DatastoreProperties.DatastoreStatus", + "state" : "success", + "expected" : "DELETED" + } ] }, - "FHIRImportJobCompleted": { - "operation": "DescribeFHIRImportJob", - "delay": 120, - "maxAttempts": 720, - "acceptors": [ - { - "state": "success", - "matcher": "path", - "argument": "ImportJobProperties.JobStatus", - "expected": "COMPLETED" - }, - { - "state": "success", - "matcher": "path", - "argument": "ImportJobProperties.JobStatus", - "expected": "COMPLETED_WITH_ERRORS" - }, - { - "state": "failure", - "matcher": "path", - "argument": "ImportJobProperties.JobStatus", - "expected": "FAILED" - } - ] + "FHIRExportJobCompleted" : { + "delay" : 120, + "maxAttempts" : 5, + "operation" : "DescribeFHIRExportJob", + "acceptors" : [ { + "matcher" : "path", + "argument" : "ExportJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED" + }, { + "matcher" : "path", + "argument" : "ExportJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED_WITH_ERRORS" + }, { + "matcher" : "path", + "argument" : "ExportJobProperties.JobStatus", + "state" : "failure", + "expected" : "CANCEL_COMPLETED" + }, { + "matcher" : "path", + "argument" : "ExportJobProperties.JobStatus", + "state" : "failure", + "expected" : "FAILED" + }, { + "matcher" : "path", + "argument" : "ExportJobProperties.JobStatus", + "state" : "failure", + "expected" : "CANCEL_FAILED" + } ] + }, + "FHIRImportJobCompleted" : { + "delay" : 120, + "maxAttempts" : 5, + "operation" : "DescribeFHIRImportJob", + "acceptors" : [ { + "matcher" : "path", + "argument" : "ImportJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED" + }, { + "matcher" : "path", + "argument" : "ImportJobProperties.JobStatus", + "state" : "success", + "expected" : "COMPLETED_WITH_ERRORS" + }, { + "matcher" : "path", + "argument" : "ImportJobProperties.JobStatus", + "state" : "failure", + "expected" : "FAILED" + } ] } } } \ No newline at end of file diff --git a/services/iam/pom.xml b/services/iam/pom.xml index e7e644daaefd..75a4abf2b4a6 100644 --- a/services/iam/pom.xml +++ b/services/iam/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iam AWS Java SDK :: Services :: AWS IAM diff --git a/services/iam/src/main/resources/codegen-resources/customization.config b/services/iam/src/main/resources/codegen-resources/customization.config index 5e7617844693..c806d70bb621 100644 --- a/services/iam/src/main/resources/codegen-resources/customization.config +++ b/services/iam/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { - "enableGenerateCompiledEndpointRules": true, "verifiedSimpleMethods": [ "createAccessKey", "deleteAccountPasswordPolicy", diff --git a/services/iam/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iam/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..79a01ad77f3c --- /dev/null +++ b/services/iam/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,816 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.global.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.cn-north-1.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.us-gov.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.us-gov.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.api.aws.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.aws.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.api.aws.scloud", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.aws.scloud", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.eu-isoe-west-1.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.api.cloud-aws.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.cloud-aws.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.us-isof-south-1.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.api.aws.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.aws.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.eusc-de-east-1.amazonaws.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.amazonaws.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.global.api.amazonwebservices.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.api.amazonwebservices.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 43, + "nodes": "/////wAAAAH/////AAAAAAAAACoAAAADAAAAAQAAAAQF9eEpAAAAAgAAAAUF9eEpAAAAAwAAACcAAAAGAAAABAAAACQAAAAHAAAABQAAACMAAAAIAAAABgAAACAAAAAJAAAABwAAABQAAAAKAAAACAAAAA8AAAALAAAACQX14RIAAAAMAAAACgX14RYAAAANAAAACwX14RoAAAAOAAAADAX14R4F9eEoAAAACQX14RQAAAAQAAAACgX14RgAAAARAAAACwX14RwAAAASAAAADAX14SAAAAATAAAADQX14SYF9eEnAAAACAAAABoAAAAVAAAACQX14RMAAAAWAAAACgX14RcAAAAXAAAACwX14RsAAAAYAAAADAX14R8AAAAZAAAADgX14SQF9eElAAAACQX14RUAAAAbAAAACgX14RkAAAAcAAAACwX14R0AAAAdAAAADAX14SEAAAAeAAAADQAAAB8F9eEjAAAADgX14SIF9eEjAAAABwAAACIAAAAhAAAACAX14RAF9eEOAAAACAX14REF9eEPAAAACAX14QwF9eENAAAABwAAACYAAAAlAAAACAX14QgF9eEKAAAACAX14QkF9eELAAAABwAAACkAAAAoAAAACAX14QYF9eEEAAAACAX14QcF9eEFAAAABwX14QEAAAArAAAACAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iam/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iam/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bad185dfe692..000000000000 --- a/services/iam/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,1122 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://iam.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://iam-fips.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://iam.global.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-north-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.cn-north-1.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-north-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://iam.us-gov.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://iam.us-gov.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.us-gov.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.us-gov.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam-fips.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam-fips.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.eu-isoe-west-1.cloud.adc-e.uk", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eu-isoe-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.us-isof-south-1.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://iam.eusc-de-east-1.amazonaws.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iam-fips.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iam-fips.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iam.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iam.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/iam/src/main/resources/codegen-resources/endpoint-tests.json b/services/iam/src/main/resources/codegen-resources/endpoint-tests.json index a38a2c02fcbd..04a9c4d8b090 100644 --- a/services/iam/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/iam/src/main/resources/codegen-resources/endpoint-tests.json @@ -125,7 +125,7 @@ "authSchemes": [ { "name": "sigv4", - "signingRegion": "cn-northwest-1" + "signingRegion": "cn-north-1" } ] }, @@ -146,7 +146,7 @@ "authSchemes": [ { "name": "sigv4", - "signingRegion": "cn-northwest-1" + "signingRegion": "cn-north-1" } ] }, diff --git a/services/iam/src/main/resources/codegen-resources/service-2.json b/services/iam/src/main/resources/codegen-resources/service-2.json index 6c7ba9090749..2a7b4c985c62 100644 --- a/services/iam/src/main/resources/codegen-resources/service-2.json +++ b/services/iam/src/main/resources/codegen-resources/service-2.json @@ -29,6 +29,31 @@ ], "documentation":"

    Accepts a delegation request, granting the requested temporary access.

    Once the delegation request is accepted, it is eligible to send the exchange token to the partner. The SendDelegationToken API has to be explicitly called to send the delegation token.

    At the time of acceptance, IAM records the details and the state of the identity that called this API. This is the identity that gets mapped to the delegated credential.

    An accepted request may be rejected before the exchange token is sent to the partner.

    " }, + "AcquireRole":{ + "name":"AcquireRole", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AcquireRoleRequest"}, + "output":{ + "shape":"AcquireRoleResponse", + "resultWrapper":"AcquireRoleResult" + }, + "errors":[ + {"shape":"LimitExceededException"}, + {"shape":"InvalidInputException"}, + {"shape":"EntityAlreadyExistsException"}, + {"shape":"RoleModifiedException"}, + {"shape":"NameConflictException"}, + {"shape":"MalformedPolicyDocumentException"}, + {"shape":"ConcurrentModificationException"}, + {"shape":"ServiceFailureException"}, + {"shape":"NoSuchEntityException"}, + {"shape":"RoleTemplateDisabledException"} + ], + "documentation":"

    Creates an IAM role from the specified role template. The new role takes its configuration—including its name, path, trust policy, inline and managed policies, permissions boundary, tags, and maximum session duration—from the role template version that you specify. For more information about roles, see IAM roles in the IAM User Guide.

    If the template version defines parameters, use the ReplacementValues parameter to supply the values that the service substitutes into the role during creation.

    " + }, "AddClientIDToOpenIDConnectProvider":{ "name":"AddClientIDToOpenIDConnectProvider", "http":{ @@ -1066,6 +1091,23 @@ ], "documentation":"

    Retrieves the password policy for the Amazon Web Services account. This tells you the complexity requirements and mandatory rotation periods for the IAM user passwords in your account. For more information about using a password policy, see Managing an IAM password policy.

    " }, + "GetAccountProperties":{ + "name":"GetAccountProperties", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAccountPropertiesRequest"}, + "output":{ + "shape":"GetAccountPropertiesResponse", + "resultWrapper":"GetAccountPropertiesResult" + }, + "errors":[ + {"shape":"InvalidInputException"}, + {"shape":"ServiceFailureException"} + ], + "documentation":"

    Retrieves the account-level properties for the caller's Amazon Web Services account. Account properties are configuration settings that control account-wide IAM features such as Role Manager.

    The service returns properties as key-value pairs in Namespace/PropertyName format. Each namespace groups related configuration settings. Use PutAccountProperties to modify these properties.

    " + }, "GetAccountSummary":{ "name":"GetAccountSummary", "http":{ @@ -1112,7 +1154,7 @@ {"shape":"NoSuchEntityException"}, {"shape":"InvalidInputException"} ], - "documentation":"

    Gets a list of all of the context keys referenced in all the IAM policies that are attached to the specified IAM entity. The entity can be an IAM user, group, or role. If you specify a user, then the request also includes all of the policies attached to groups that the user is a member of.

    You can optionally include a list of one or more additional policies, specified as strings. If you want to include only a list of policies by string, use GetContextKeysForCustomPolicy instead.

    Note: This operation discloses information about the permissions granted to other users. If you do not want users to see other user's permissions, then consider allowing them to use GetContextKeysForCustomPolicy instead.

    Context keys are variables maintained by Amazon Web Services and its services that provide details about the context of an API query request. Context keys can be evaluated by testing against a value in an IAM policy. Use GetContextKeysForPrincipalPolicy to understand what key names and values you must supply when you call SimulatePrincipalPolicy.

    " + "documentation":"

    Gets a list of all of the context keys referenced in all the IAM policies that are attached to the specified IAM entity. The entity can be an IAM user, group, or role. If you specify a user, then the request also includes all of the policies attached to groups that the user is a member of.

    You can optionally include a list of one or more additional policies, specified as strings. If you want to include only a list of policies by string, use GetContextKeysForCustomPolicy instead.

    Note: This operation discloses information about the permissions granted to other users. If you do not want users to see other user's permissions, then consider allowing them to use GetContextKeysForCustomPolicy instead.

    Context keys are variables maintained by Amazon Web Services and its services that provide details about the context of an API query request. Context keys can be evaluated by testing against a value in an IAM policy. Use GetContextKeysForPrincipalPolicy to understand what key names and values you must supply when you call SimulatePrincipalPolicy. This operation doesn't return context keys referenced by service control policies (SCPs). Only context keys referenced by the identity-based policies attached to the specified entity, and any additional policies that you provide, are included.

    " }, "GetCredentialReport":{ "name":"GetCredentialReport", @@ -1371,6 +1413,24 @@ ], "documentation":"

    Retrieves the specified inline policy document that is embedded with the specified IAM role.

    Policies returned by this operation are URL-encoded compliant with RFC 3986. You can use a URL decoding method to convert the policy back to plain JSON text. For example, if you use Java, you can use the decode method of the java.net.URLDecoder utility class in the Java SDK. Other languages and SDKs provide similar functionality, and some SDKs do this decoding automatically.

    An IAM role can also have managed policies attached to it. To retrieve a managed policy document that is attached to a role, use GetPolicy to determine the policy's default version, then use GetPolicyVersion to retrieve the policy document.

    For more information about policies, see Managed policies and inline policies in the IAM User Guide.

    For more information about roles, see IAM roles in the IAM User Guide.

    " }, + "GetRoleTemplateVersion":{ + "name":"GetRoleTemplateVersion", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetRoleTemplateVersionRequest"}, + "output":{ + "shape":"GetRoleTemplateVersionResponse", + "resultWrapper":"GetRoleTemplateVersionResult" + }, + "errors":[ + {"shape":"NoSuchEntityException"}, + {"shape":"InvalidInputException"}, + {"shape":"ServiceFailureException"} + ], + "documentation":"

    Retrieves information about a version of the specified role template. Role templates define a reusable configuration—including role name and path patterns, trust policy, inline and managed policies, permissions boundary, tags, and maximum session duration—that you use to create IAM roles with AcquireRole.

    If you do not specify a minor version, the service returns the template's default minor version.

    " + }, "GetSAMLProvider":{ "name":"GetSAMLProvider", "http":{ @@ -2119,6 +2179,24 @@ }, "documentation":"

    Lists the virtual MFA devices defined in the Amazon Web Services account by assignment status. If you do not specify an assignment status, the operation returns a list of all virtual MFA devices. Assignment status can be Assigned, Unassigned, or Any.

    IAM resource-listing operations return a subset of the available attributes for the resource. For example, this operation does not return tags, even though they are an attribute of the returned object. To view tag information for a virtual MFA device, see ListMFADeviceTags.

    You can paginate the results using the MaxItems and Marker parameters.

    " }, + "PutAccountProperties":{ + "name":"PutAccountProperties", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"PutAccountPropertiesRequest"}, + "output":{ + "shape":"PutAccountPropertiesResponse", + "resultWrapper":"PutAccountPropertiesResult" + }, + "errors":[ + {"shape":"InvalidInputException"}, + {"shape":"ConcurrentModificationException"}, + {"shape":"ServiceFailureException"} + ], + "documentation":"

    Sets account-level properties for the caller's Amazon Web Services account. Account properties are configuration settings that control account-wide IAM features such as Role Manager.

    Specify properties as key-value pairs in Namespace/PropertyName format. All properties in a single request must belong to the same namespace. Use GetAccountProperties to view the current properties.

    " + }, "PutGroupPolicy":{ "name":"PutGroupPolicy", "http":{ @@ -2344,7 +2422,7 @@ {"shape":"InvalidInputException"}, {"shape":"PolicyEvaluationException"} ], - "documentation":"

    Simulate how a set of IAM policies and optionally a resource-based policy works with a list of API operations and Amazon Web Services resources to determine the policies' effective permissions. The policies are provided as strings.

    The simulation does not perform the API operations; it only checks the authorization to determine if the simulated policies allow or deny the operations. You can simulate resources that don't exist in your account.

    If you want to simulate existing policies that are attached to an IAM user, group, or role, use SimulatePrincipalPolicy instead.

    Context keys are variables that are maintained by Amazon Web Services and its services and which provide details about the context of an API query request. You can use the Condition element of an IAM policy to evaluate context keys. To get the list of context keys that the policies require for correct simulation, use GetContextKeysForCustomPolicy.

    If the output is long, you can use MaxItems and Marker parameters to paginate the results.

    The IAM policy simulator evaluates statements in the identity-based policy and the inputs that you provide during simulation. The policy simulator results can differ from your live Amazon Web Services environment. We recommend that you check your policies against your live Amazon Web Services environment after testing using the policy simulator to confirm that you have the desired results. For more information about using the policy simulator, see Testing IAM policies with the IAM policy simulator in the IAM User Guide.

    " + "documentation":"

    Simulate how a set of IAM policies and optionally a resource-based policy works with a list of API operations and Amazon Web Services resources to determine the policies' effective permissions. The policies are provided as strings.

    The simulation does not perform the API operations; it only checks the authorization to determine if the simulated policies allow or deny the operations. You can simulate resources that don't exist in your account.

    If you want to simulate existing policies that are attached to an IAM user, group, or role, use SimulatePrincipalPolicy instead.

    Context keys are variables that are maintained by Amazon Web Services and its services and which provide details about the context of an API query request. You can use the Condition element of an IAM policy to evaluate context keys. To get the list of context keys that the policies require for correct simulation, use GetContextKeysForCustomPolicy.

    If the output is long, you can use MaxItems and Marker parameters to paginate the results.

    The IAM policy simulator evaluates statements in identity-based policies, service control policies (SCPs) including their condition keys and resource scoping, and the inputs that you provide during simulation. The policy simulator results can differ from your live Amazon Web Services environment. We recommend that you check your policies against your live Amazon Web Services environment after testing using the policy simulator to confirm that you have the desired results. For more information about using the policy simulator, see Testing IAM policies with the IAM policy simulator in the IAM User Guide.

    " }, "SimulatePrincipalPolicy":{ "name":"SimulatePrincipalPolicy", @@ -2362,7 +2440,7 @@ {"shape":"InvalidInputException"}, {"shape":"PolicyEvaluationException"} ], - "documentation":"

    Simulate how a set of IAM policies attached to an IAM entity works with a list of API operations and Amazon Web Services resources to determine the policies' effective permissions. The entity can be an IAM user, group, or role. If you specify a user, then the simulation also includes all of the policies that are attached to groups that the user belongs to. You can simulate resources that don't exist in your account.

    You can optionally include a list of one or more additional policies specified as strings to include in the simulation. If you want to simulate only policies specified as strings, use SimulateCustomPolicy instead.

    You can also optionally include one resource-based policy to be evaluated with each of the resources included in the simulation for IAM users only.

    The simulation does not perform the API operations; it only checks the authorization to determine if the simulated policies allow or deny the operations.

    Note: This operation discloses information about the permissions granted to other users. If you do not want users to see other user's permissions, then consider allowing them to use SimulateCustomPolicy instead.

    Context keys are variables maintained by Amazon Web Services and its services that provide details about the context of an API query request. You can use the Condition element of an IAM policy to evaluate context keys. To get the list of context keys that the policies require for correct simulation, use GetContextKeysForPrincipalPolicy.

    If the output is long, you can use the MaxItems and Marker parameters to paginate the results.

    The IAM policy simulator evaluates statements in the identity-based policy and the inputs that you provide during simulation. The policy simulator results can differ from your live Amazon Web Services environment. We recommend that you check your policies against your live Amazon Web Services environment after testing using the policy simulator to confirm that you have the desired results. For more information about using the policy simulator, see Testing IAM policies with the IAM policy simulator in the IAM User Guide.

    " + "documentation":"

    Simulate how a set of IAM policies attached to an IAM entity works with a list of API operations and Amazon Web Services resources to determine the policies' effective permissions. The entity can be an IAM user, group, or role. If you specify a user, then the simulation also includes all of the policies that are attached to groups that the user belongs to. You can simulate resources that don't exist in your account.

    You can optionally include a list of one or more additional policies specified as strings to include in the simulation. If you want to simulate only policies specified as strings, use SimulateCustomPolicy instead.

    You can also optionally include one resource-based policy to be evaluated with each of the resources included in the simulation for IAM users only.

    The simulation does not perform the API operations; it only checks the authorization to determine if the simulated policies allow or deny the operations.

    For cross-account simulations, EvalDecisionDetails returns the decision for each policy type (identity-based policy, resource-based policy, and permissions boundary). This helps you identify which policy type is responsible for an allow or deny decision when policies span multiple accounts.

    Note: This operation discloses information about the permissions granted to other users. If you do not want users to see other user's permissions, then consider allowing them to use SimulateCustomPolicy instead.

    Context keys are variables maintained by Amazon Web Services and its services that provide details about the context of an API query request. You can use the Condition element of an IAM policy to evaluate context keys. To get the list of context keys that the policies require for correct simulation, use GetContextKeysForPrincipalPolicy.

    If the output is long, you can use the MaxItems and Marker parameters to paginate the results.

    The IAM policy simulator evaluates statements in identity-based policies, service control policies (SCPs) including their condition keys and resource scoping, and the inputs that you provide during simulation. The policy simulator results can differ from your live Amazon Web Services environment. We recommend that you check your policies against your live Amazon Web Services environment after testing using the policy simulator to confirm that you have the desired results. For more information about using the policy simulator, see Testing IAM policies with the IAM policy simulator in the IAM User Guide.

    " }, "TagInstanceProfile":{ "name":"TagInstanceProfile", @@ -3049,6 +3127,34 @@ "documentation":"

    The request was rejected because the account making the request is not the management account or delegated administrator account for centralized root access.

    ", "exception":true }, + "AcquireRoleRequest":{ + "type":"structure", + "required":["TemplateArn"], + "members":{ + "TemplateArn":{ + "shape":"arnType", + "documentation":"

    The Amazon Resource Name (ARN) of the role template to create the role from.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + }, + "TemplateMinorVersion":{ + "shape":"integerType", + "documentation":"

    The minor version of the role template to use. If you do not specify a minor version, the service uses the template's default minor version.

    " + }, + "ReplacementValues":{ + "shape":"mapStringReplacementValueEntry", + "documentation":"

    A map of values to substitute for the parameters that are defined in the role template version. Each key is a parameter name from the template, and each value is a structure that contains the replacement values for that parameter.

    " + } + } + }, + "AcquireRoleResponse":{ + "type":"structure", + "required":["Role"], + "members":{ + "Role":{ + "shape":"Role", + "documentation":"

    A structure that contains details about the IAM role that was created.

    " + } + } + }, "ActionNameListType":{ "type":"list", "member":{"shape":"ActionNameType"} @@ -3199,6 +3305,20 @@ }, "documentation":"

    Contains information about an attached policy.

    An attached policy is a managed policy that has been attached to a user, group, or role. This data type is used as a response element in the ListAttachedGroupPolicies, ListAttachedRolePolicies, ListAttachedUserPolicies, and GetAccountAuthorizationDetails operations.

    For more information about managed policies, refer to Managed policies and inline policies in the IAM User Guide.

    " }, + "AttachmentName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\w+=,.@-]+" + }, + "AttachmentType":{ + "type":"string", + "enum":[ + "user", + "group", + "role" + ] + }, "BootstrapDatum":{ "type":"blob", "sensitive":true @@ -4565,7 +4685,7 @@ }, "EvalResourceName":{ "shape":"ResourceNameType", - "documentation":"

    The ARN of the resource that the indicated API operation was tested on.

    " + "documentation":"

    The ARN template for the simulated resource type (for example, arn:${Partition}:s3:::${BucketName}/${KeyName}), or * if no ARN format is defined for the action. This is not a specific customer-provided resource ARN. To find the decision for a specific resource, use ResourceSpecificResults.

    If you previously relied on EvalResourceName to identify which specific resource a result applies to, you must now use the EvalResourceName field within individual entries in ResourceSpecificResults instead.

    " }, "EvalDecision":{ "shape":"PolicyEvaluationDecisionType", @@ -4573,15 +4693,15 @@ }, "MatchedStatements":{ "shape":"StatementListType", - "documentation":"

    A list of the statements in the input policies that determine the result for this scenario. Remember that even if multiple statements allow the operation on the resource, if only one statement denies that operation, then the explicit deny overrides any allow. In addition, the deny statement is the only entry included in the result.

    " + "documentation":"

    A list of the statements in the input policies that determine the result for this scenario. Remember that even if multiple statements allow the operation on the resource, if only one statement denies that operation, then the explicit deny overrides any allow. In addition, the deny statement is the only entry included in the result.

    In the top-level result, this field contains the union of matched statements across all requested resources. Only statements that contributed to the reported decision are included. For per-resource matched statements, see ResourceSpecificResults. This field doesn't include statements from service control policies (SCPs). Only statements from identity-based and resource-based policies appear here.

    " }, "MissingContextValues":{ "shape":"ContextKeyNamesResultListType", - "documentation":"

    A list of context keys that are required by the included input policies but that were not provided by one of the input parameters. This list is used when the resource in a simulation is \"*\", either explicitly, or when the ResourceArns parameter blank. If you include a list of resources, then any missing context values are instead included under the ResourceSpecificResults section. To discover the context keys used by a set of policies, you can call GetContextKeysForCustomPolicy or GetContextKeysForPrincipalPolicy.

    " + "documentation":"

    A list of context keys that are required by the included input policies but that were not provided by one of the input parameters. This list is used when the resource in a simulation is \"*\", either explicitly, or when the ResourceArns parameter blank. If you include a list of resources, then any missing context values are instead included under the ResourceSpecificResults section. To discover the context keys used by a set of policies, you can call GetContextKeysForCustomPolicy or GetContextKeysForPrincipalPolicy.

    In the top-level result, this field contains the deduplicated set of missing context values across all requested resources. This field doesn't include context keys referenced by service control policies (SCPs). Only context keys referenced by identity-based and resource-based policies appear here.

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

    A structure that details how Organizations and its service control policies affect the results of the simulation. Only applies if the simulated user's account is part of an organization.

    " + "documentation":"

    A structure that details how Organizations and its service control policies affect the results of the simulation. Only applies if the simulated user's account is part of an organization.

    For resources that don't support organization-level evaluation, this field is omitted from the top-level result. For per-resource details, see ResourceSpecificResults.

    " }, "PermissionsBoundaryDecisionDetail":{ "shape":"PermissionsBoundaryDecisionDetail", @@ -4589,14 +4709,14 @@ }, "EvalDecisionDetails":{ "shape":"EvalDecisionDetailsType", - "documentation":"

    Additional details about the results of the cross-account evaluation decision. This parameter is populated for only cross-account simulations. It contains a brief summary of how each policy type contributes to the final evaluation decision.

    If the simulation evaluates policies within the same account and includes a resource ARN, then the parameter is present but the response is empty. If the simulation evaluates policies within the same account and specifies all resources (*), then the parameter is not returned.

    When you make a cross-account request, Amazon Web Services evaluates the request in the trusting account and the trusted account. The request is allowed only if both evaluations return true. For more information about how policies are evaluated, see Evaluating policies within a single account.

    If an Organizations SCP included in the evaluation denies access, the simulation ends. In this case, policy evaluation does not proceed any further and this parameter is not returned.

    " + "documentation":"

    Additional details about the results of the cross-account evaluation decision. This parameter is populated for only cross-account simulations. It contains a brief summary of how each policy type contributes to the final evaluation decision.

    In the top-level result, this map reports the most restrictive decision per policy type across all requested resources.

    If the simulation evaluates policies within the same account and includes a resource ARN, then the parameter is present but the response is empty. If the simulation evaluates policies within the same account and specifies all resources (*), then the parameter is not returned.

    When you make a cross-account request, Amazon Web Services evaluates the request in the trusting account and the trusted account. The request is allowed only if both evaluations return true. For more information about how policies are evaluated, see Evaluating policies within a single account.

    If an Organizations SCP included in the evaluation denies access, the simulation ends. In this case, policy evaluation does not proceed any further and this parameter is not returned.

    " }, "ResourceSpecificResults":{ "shape":"ResourceSpecificResultListType", "documentation":"

    The individual results of the simulation of the API operation specified in EvalActionName on each resource.

    " } }, - "documentation":"

    Contains the results of a simulation.

    This data type is used by the return parameter of SimulateCustomPolicy and SimulatePrincipalPolicy .

    " + "documentation":"

    Contains the results of a simulation.

    This data type is used by the return parameter of SimulateCustomPolicy and SimulatePrincipalPolicy .

    The simulator now returns a single EvaluationResult per action, regardless of how many resource ARNs are provided. Previously, simulating one action against N resources returned N evaluation results, each containing the same aggregate decision. The top-level fields (EvalDecision, MatchedStatements, MissingContextValues, EvalDecisionDetails) now represent the aggregate decision across all requested resources. The top-level EvalDecision reflects the most restrictive decision across all resources (for example, if any resource produces explicitDeny, the top-level decision is explicitDeny).

    To see the decision for each individual resource, use ResourceSpecificResults. If your application parses evaluation results per resource ARN, update your code to read per-resource decisions from ResourceSpecificResults rather than from the top-level result.

    " }, "EvaluationResultsListType":{ "type":"list", @@ -4783,6 +4903,19 @@ }, "documentation":"

    Contains the response to a successful GetAccountPasswordPolicy request.

    " }, + "GetAccountPropertiesRequest":{ + "type":"structure", + "members":{} + }, + "GetAccountPropertiesResponse":{ + "type":"structure", + "members":{ + "Properties":{ + "shape":"accountPropertiesMapType", + "documentation":"

    A map of account property key-value pairs. Keys are in the format Namespace/PropertyName.

    " + } + } + }, "GetAccountSummaryResponse":{ "type":"structure", "members":{ @@ -5289,6 +5422,30 @@ }, "documentation":"

    Contains the response to a successful GetRole request.

    " }, + "GetRoleTemplateVersionRequest":{ + "type":"structure", + "required":["TemplateArn"], + "members":{ + "TemplateArn":{ + "shape":"arnType", + "documentation":"

    The Amazon Resource Name (ARN) of the role template whose version you want to retrieve.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + }, + "MinorVersion":{ + "shape":"minorVersionType", + "documentation":"

    The minor version of the role template to retrieve. If you do not specify a minor version, the service returns the template's default minor version.

    " + } + } + }, + "GetRoleTemplateVersionResponse":{ + "type":"structure", + "required":["RoleTemplateVersion"], + "members":{ + "RoleTemplateVersion":{ + "shape":"RoleTemplateVersion", + "documentation":"

    A structure that contains details about the requested role template version.

    " + } + } + }, "GetSAMLProviderRequest":{ "type":"structure", "required":["SAMLProviderArn"], @@ -5659,6 +5816,47 @@ }, "documentation":"

    Contains information about an IAM group, including all of the group's policies.

    This data type is used as a response element in the GetAccountAuthorizationDetails operation.

    " }, + "InlinePolicy":{ + "type":"structure", + "required":[ + "PolicyName", + "PolicyDocument" + ], + "members":{ + "PolicyName":{ + "shape":"policyNameType", + "documentation":"

    The name of the inline policy.

    " + }, + "PolicyDocument":{ + "shape":"policyDocumentType", + "documentation":"

    The inline policy document.

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

    Contains an inline policy template that the service embeds in roles that you create from a role template.

    " + }, + "InlinePolicyIdentifierType":{ + "type":"structure", + "required":[ + "PolicyName", + "AttachmentType", + "AttachmentName" + ], + "members":{ + "PolicyName":{ + "shape":"policyNameType", + "documentation":"

    The name of the inline policy.

    " + }, + "AttachmentType":{ + "shape":"AttachmentType", + "documentation":"

    The type of IAM entity that the inline policy is attached to.

    " + }, + "AttachmentName":{ + "shape":"AttachmentName", + "documentation":"

    The name of the IAM user, group, or role that the inline policy is attached to. Wildcard characters are supported to match multiple entities: use at most one * (matches any sequence of characters, including none), and any number of ? (each matches exactly one character).

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

    Identifies one or more inline policies that are embedded in IAM users, groups, or roles, by the name of the policy together with the type and name of the entity that it is attached to. Wildcard characters in the entity name can match multiple entities, so a single identifier can select more than one attached inline policy.

    " + }, "InstanceProfile":{ "type":"structure", "required":[ @@ -7216,6 +7414,19 @@ "type":"list", "member":{"shape":"ManagedPolicyDetail"} }, + "NameConflictException":{ + "type":"structure", + "members":{ + "message":{"shape":"nameConflictMessage"} + }, + "documentation":"

    The request was rejected because the resulting role name conflicts with an existing role in the account.

    ", + "error":{ + "code":"NameConflict", + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, "NoSuchEntityException":{ "type":"structure", "members":{ @@ -7260,6 +7471,16 @@ }, "exception":true }, + "OrderedOrganizationPolicyType":{ + "type":"structure", + "members":{ + "ServiceControlPolicyInputList":{ + "shape":"SimulationPolicyListType", + "documentation":"

    A list of SCP documents that apply at this level of the Organizations hierarchy. Each document is specified as a string containing the complete, valid JSON text of an SCP.

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

    Represents one level of an Organizations hierarchy—the organization root, an organizational unit (OU), or an account—together with the service control policies (SCPs) that apply at that level. Each element in the list represents one level of the hierarchy, ordered from the organization root down to the account.

    For more information about SCPs, see Service control policies (SCPs) in the Organizations User Guide.

    " + }, "OrganizationIdType":{ "type":"string", "max":34, @@ -7277,6 +7498,11 @@ "documentation":"

    The request was rejected because your organization does not have All features enabled. For more information, see Available feature sets in the Organizations User Guide.

    ", "exception":true }, + "OrganizationPolicyListType":{ + "type":"list", + "member":{"shape":"OrderedOrganizationPolicyType"}, + "max":7 + }, "OrganizationsDecisionDetail":{ "type":"structure", "members":{ @@ -7287,6 +7513,44 @@ }, "documentation":"

    Contains information about the effect that Organizations has on a policy simulation.

    " }, + "ParameterDefinition":{ + "type":"structure", + "required":[ + "Name", + "Type" + ], + "members":{ + "Name":{ + "shape":"parameterNameType", + "documentation":"

    The name of the parameter.

    " + }, + "Type":{ + "shape":"parameterTypeType", + "documentation":"

    The data type of the parameter. Valid values are String, StringList, Number, NumberList, Arn, and ArnList.

    " + }, + "SubType":{ + "shape":"parameterSubTypeType", + "documentation":"

    An optional subtype that further constrains the values that are allowed for the parameter.

    " + }, + "Description":{ + "shape":"parameterDescriptionType", + "documentation":"

    A description of the parameter.

    " + }, + "IsRequired":{ + "shape":"booleanType", + "documentation":"

    Specifies whether you must supply a value for the parameter when you create a role from the template.

    " + }, + "DefaultValue":{ + "shape":"parameterDefaultValueType", + "documentation":"

    The value that the service uses for the parameter when you do not supply one.

    " + }, + "Immutable":{ + "shape":"booleanType", + "documentation":"

    Specifies whether you can change the parameter value after you create the role.

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

    Defines a parameter that a role template accepts. You supply values for these parameters when you create a role with AcquireRole.

    " + }, "PasswordPolicy":{ "type":"structure", "members":{ @@ -7445,6 +7709,11 @@ }, "exception":true }, + "PolicyExclusionsListType":{ + "type":"list", + "member":{"shape":"PolicyIdentifier"}, + "max":256 + }, "PolicyGrantingServiceAccess":{ "type":"structure", "required":[ @@ -7490,6 +7759,36 @@ "type":"list", "member":{"shape":"PolicyGroup"} }, + "PolicyIdentifier":{ + "type":"structure", + "members":{ + "PolicyType":{ + "shape":"PolicyIdentifierPolicyType", + "documentation":"

    The policy type to identify. All policies of the specified type are matched.

    " + }, + "PolicyArn":{ + "shape":"arnType", + "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Web Services managed policy or a customer managed policy that is attached to an IAM user, group, or role. Wildcard characters are supported in the resource name portion of the ARN to match multiple managed policies: use at most one * (matches any sequence of characters, including none), and any number of ? (each matches exactly one character).

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + }, + "InlinePolicyIdentifier":{ + "shape":"InlinePolicyIdentifierType", + "documentation":"

    An inline policy identifier consisting of a policy name and the entity it is attached to. Wildcard characters (* and ?) in the entity name can match multiple entities.

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

    Identifies one or more policies as a union type. Specify exactly one of PolicyType, PolicyArn, or InlinePolicyIdentifier to identify policies by their type, by Amazon Resource Name (ARN), or by the name of an inline policy and the entity it is attached to.

    ", + "union":true + }, + "PolicyIdentifierPolicyType":{ + "type":"string", + "enum":[ + "inline", + "aws-managed", + "user-managed", + "permission-boundary", + "scp", + "rcp" + ] + }, "PolicyIdentifierType":{"type":"string"}, "PolicyNotAttachableException":{ "type":"structure", @@ -7621,6 +7920,20 @@ }, "documentation":"

    Contains the row and column of a location of a Statement element in a policy document.

    This data type is used as a member of the Statement type.

    " }, + "PutAccountPropertiesRequest":{ + "type":"structure", + "required":["Properties"], + "members":{ + "Properties":{ + "shape":"accountPropertiesMapType", + "documentation":"

    A map of property key-value pairs to set. All keys must belong to the same namespace.

    Each key uses the format Namespace/PropertyName. The key must contain exactly one / separating the namespace from the property name, and cannot start or end with /.

    The service validates each value based on the property key's expected type. For example, boolean properties expect true or false.

    " + } + } + }, + "PutAccountPropertiesResponse":{ + "type":"structure", + "members":{} + }, "PutGroupPolicyRequest":{ "type":"structure", "required":[ @@ -7795,6 +8108,17 @@ } } }, + "ReplacementValueEntry":{ + "type":"structure", + "required":["Values"], + "members":{ + "Values":{ + "shape":"replacementValueListType", + "documentation":"

    The list of replacement values for the template parameter.

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

    Contains the list of replacement values for a single template parameter used when creating a role from a role template.

    " + }, "ReportContentType":{"type":"blob"}, "ReportFormatType":{ "type":"string", @@ -7977,6 +8301,10 @@ "RoleLastUsed":{ "shape":"RoleLastUsed", "documentation":"

    Contains information about the last time that an IAM role was used. This includes the date and time and the Region in which the role was last used. Activity is only reported for the trailing 400 days. This period can be shorter if your Region began supporting these features within the last year. The role might have been used more than 400 days ago. For more information, see Regions where data is tracked in the IAM user Guide.

    " + }, + "SourceRoleTemplate":{ + "shape":"SourceRoleTemplate", + "documentation":"

    Contains information about the role template that this role was created from. This member is present only for roles created with AcquireRole.

    " } }, "documentation":"

    Contains information about an IAM role. This structure is returned as a response element in several API operations that interact with roles.

    " @@ -8046,6 +8374,130 @@ }, "documentation":"

    Contains information about the last time that an IAM role was used. This includes the date and time and the Region in which the role was last used. Activity is only reported for the trailing 400 days. This period can be shorter if your Region began supporting these features within the last year. The role might have been used more than 400 days ago. For more information, see Regions where data is tracked in the IAM user Guide.

    This data type is returned as a response element in the GetRole and GetAccountAuthorizationDetails operations.

    " }, + "RoleModifiedException":{ + "type":"structure", + "members":{ + "message":{"shape":"roleModifiedMessage"} + }, + "documentation":"

    The request was rejected because someone modified the role template while the service was creating the role. Wait a few minutes and try the request again.

    ", + "error":{ + "code":"RoleModified", + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "RoleTemplateDisabledException":{ + "type":"structure", + "members":{ + "message":{"shape":"roleTemplateDisabledMessage"} + }, + "documentation":"

    The request was rejected because the specified role template is disabled. A disabled role template cannot be used to create new roles. Contact your administrator to enable the role template, or use a different role template.

    ", + "error":{ + "code":"RoleTemplateDisabled", + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "RoleTemplateVersion":{ + "type":"structure", + "members":{ + "TemplateArn":{ + "shape":"arnType", + "documentation":"

    The Amazon Resource Name (ARN) that identifies the role template.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + }, + "TemplateName":{ + "shape":"roleTemplateNameType", + "documentation":"

    The friendly name that identifies the role template.

    " + }, + "TemplateVersionId":{ + "shape":"idType", + "documentation":"

    The identifier of the role template version.

    " + }, + "Description":{ + "shape":"roleTemplateDescriptionType", + "documentation":"

    The description of the role template.

    " + }, + "MajorVersion":{ + "shape":"integerType", + "documentation":"

    The major version number of the role template.

    " + }, + "DefaultMinorVersion":{ + "shape":"minorVersionType", + "documentation":"

    The minor version that the service uses by default when you create a role from this template without specifying a minor version.

    " + }, + "ManagedByType":{ + "shape":"managedByTypeType", + "documentation":"

    Indicates that the role template is managed by an Amazon Web Services service.

    " + }, + "ManagedByValue":{ + "shape":"managedByValueType", + "documentation":"

    The identifier of the Amazon Web Services service that manages the role template.

    " + }, + "Enabled":{ + "shape":"booleanType", + "documentation":"

    Specifies whether the role template is enabled. When a template is disabled, you cannot create roles from it.

    " + }, + "MinorVersion":{ + "shape":"minorVersionType", + "documentation":"

    The minor version number of this role template version.

    " + }, + "RoleNamePattern":{ + "shape":"roleNamePatternType", + "documentation":"

    The pattern that is used to generate the name of a role that is created from this template. The pattern can include @{parameter} placeholders that are replaced with the values you supply in the ReplacementValues parameter of AcquireRole.

    " + }, + "RolePathPattern":{ + "shape":"rolePathPatternType", + "documentation":"

    The pattern that is used to generate the path of a role that is created from this template.

    " + }, + "RoleDescriptionPattern":{ + "shape":"roleDescriptionPatternType", + "documentation":"

    The pattern that is used to generate the description of a role that is created from this template.

    " + }, + "AssumeRolePolicyDocumentTemplate":{ + "shape":"policyDocumentType", + "documentation":"

    The trust policy template that grants an entity permission to assume roles that you create from this template.

    " + }, + "InlinePolicyTemplates":{ + "shape":"inlinePolicyTemplateListType", + "documentation":"

    A list of inline policy templates that the service embeds in roles that you create from this template.

    " + }, + "ManagedPolicyArns":{ + "shape":"managedPolicyArnListType", + "documentation":"

    A list of the ARNs of the managed policies that the service attaches to roles that you create from this template.

    " + }, + "PermissionBoundaryArn":{ + "shape":"arnType", + "documentation":"

    The ARN of the policy that sets the permissions boundary for roles that you create from this template.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + }, + "ParametersDefinition":{ + "shape":"parametersDefinitionListType", + "documentation":"

    A list of the parameters that are defined for this role template version. You supply values for these parameters when you create a role with AcquireRole.

    " + }, + "RoleTagsTemplate":{ + "shape":"tagTemplateListType", + "documentation":"

    A list of tag templates that are applied to roles that are created from this template.

    " + }, + "MaxSessionDuration":{ + "shape":"roleMaxSessionDurationType", + "documentation":"

    The maximum session duration (in seconds) for roles that are created from this template.

    " + }, + "VersionEnabled":{ + "shape":"booleanType", + "documentation":"

    Specifies whether this specific minor version of the role template is enabled.

    " + }, + "CreateTimestamp":{ + "shape":"dateType", + "documentation":"

    The date and time, in ISO 8601 date-time format, when the role template version was created.

    " + }, + "UpdateTimestamp":{ + "shape":"dateType", + "documentation":"

    The date and time, in ISO 8601 date-time format, when the role template version was last updated.

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

    Contains information about a version of an IAM role template, including the configuration that is used to create roles with AcquireRole. This structure is returned as a response element by the GetRoleTemplateVersion operation.

    " + }, "RoleUsageListType":{ "type":"list", "member":{"shape":"RoleUsageType"} @@ -8501,6 +8953,10 @@ "shape":"SimulationPolicyListType", "documentation":"

    The IAM permissions boundary policy to simulate. The permissions boundary sets the maximum permissions that an IAM entity can have. You can input only one permissions boundary when you pass a policy to this operation. For more information about permissions boundaries, see Permissions boundaries for IAM entities in the IAM User Guide. The policy input is specified as a string that contains the complete, valid JSON text of a permissions boundary policy.

    The maximum length of the policy document that you can pass in this operation, including whitespace, is listed below. To view the maximum character counts of a managed policy with no whitespaces, see IAM and STS character quotas.

    The regex pattern used to validate this parameter is a string of characters consisting of the following:

    • Any printable ASCII character ranging from the space character (\\u0020) through the end of the ASCII character range

    • The printable characters in the Basic Latin and Latin-1 Supplement character set (through \\u00FF)

    • The special characters tab (\\u0009), line feed (\\u000A), and carriage return (\\u000D)

    " }, + "OrderedOrganizationPolicyInputList":{ + "shape":"OrganizationPolicyListType", + "documentation":"

    An ordered list of service control policies (SCPs) to include in the simulation. Each element represents one level of an Organizations hierarchy, from the organization root to the account.

    The simulator evaluates SCPs in the order that you provide, consistent with how Organizations enforces SCPs. The first element must represent the organization root, and the last element must represent the account. Any elements between them represent organizational units (OUs) in descending order.

    Use this parameter to simulate the effect of an SCP hierarchy without calling SimulatePrincipalPolicy.

    " + }, "ActionNames":{ "shape":"ActionNameListType", "documentation":"

    A list of names of API operations to evaluate in the simulation. Each operation is evaluated against each resource. Each operation must include the service identifier, such as iam:CreateUser. This operation does not support using wildcards (*) in an action name.

    " @@ -8519,7 +8975,7 @@ }, "CallerArn":{ "shape":"ResourceNameType", - "documentation":"

    The ARN of the IAM user that you want to use as the simulated caller of the API operations. CallerArn is required if you include a ResourcePolicy so that the policy's Principal element has a value to use in evaluating the policy.

    You can specify only the ARN of an IAM user. You cannot specify the ARN of an assumed role, federated user, or a service principal.

    " + "documentation":"

    The ARN of the IAM user, group, or role that you want to use as the simulated caller of the API operations. CallerArn is required if you include a ResourcePolicy so that the policy's Principal element has a value to use in evaluating the policy.

    You cannot specify the ARN of an assumed role, federated user, or a service principal.

    " }, "ContextEntries":{ "shape":"ContextEntryListType", @@ -8576,6 +9032,10 @@ "shape":"SimulationPolicyListType", "documentation":"

    The IAM permissions boundary policy to simulate. The permissions boundary sets the maximum permissions that the entity can have. You can input only one permissions boundary when you pass a policy to this operation. An IAM entity can only have one permissions boundary in effect at a time. For example, if a permissions boundary is attached to an entity and you pass in a different permissions boundary policy using this parameter, then the new permissions boundary policy is used for the simulation. For more information about permissions boundaries, see Permissions boundaries for IAM entities in the IAM User Guide. The policy input is specified as a string containing the complete, valid JSON text of a permissions boundary policy.

    The maximum length of the policy document that you can pass in this operation, including whitespace, is listed below. To view the maximum character counts of a managed policy with no whitespaces, see IAM and STS character quotas.

    The regex pattern used to validate this parameter is a string of characters consisting of the following:

    • Any printable ASCII character ranging from the space character (\\u0020) through the end of the ASCII character range

    • The printable characters in the Basic Latin and Latin-1 Supplement character set (through \\u00FF)

    • The special characters tab (\\u0009), line feed (\\u000A), and carriage return (\\u000D)

    " }, + "PolicyExclusionList":{ + "shape":"PolicyExclusionsListType", + "documentation":"

    A list of policies to exclude from the simulation. Use this parameter to test what the simulation result would be if a policy were removed, without changing which policies are actually attached to the principal identified by PolicySourceArn.

    Each entry is a PolicyIdentifier that identifies one or more policies to exclude by policy type, by Amazon Resource Name (ARN), or by the name of an inline policy and the entity it is attached to.

    Syntactically invalid identifiers, such as malformed ARNs or wildcards in disallowed positions, cause the request to fail with an InvalidInput error. Syntactically valid identifiers that don't match any attached policy are ignored. Resource control policies (RCPs) are not supported in this release; identifiers that target RCPs are also ignored.

    " + }, "ActionNames":{ "shape":"ActionNameListType", "documentation":"

    A list of names of API operations to evaluate in the simulation. Each operation is evaluated for each resource. Each operation must include the service identifier, such as iam:CreateUser.

    " @@ -8594,7 +9054,7 @@ }, "CallerArn":{ "shape":"ResourceNameType", - "documentation":"

    The ARN of the IAM user that you want to specify as the simulated caller of the API operations. If you do not specify a CallerArn, it defaults to the ARN of the user that you specify in PolicySourceArn, if you specified a user. If you include both a PolicySourceArn (for example, arn:aws:iam::123456789012:user/David) and a CallerArn (for example, arn:aws:iam::123456789012:user/Bob), the result is that you simulate calling the API operations as Bob, as if Bob had David's policies.

    You can specify only the ARN of an IAM user. You cannot specify the ARN of an assumed role, federated user, or a service principal.

    CallerArn is required if you include a ResourcePolicy and the PolicySourceArn is not the ARN for an IAM user. This is required so that the resource-based policy's Principal element has a value to use in evaluating the policy.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " + "documentation":"

    The ARN of the IAM user, group, or role that you want to specify as the simulated caller of the API operations. If you do not specify a CallerArn, it defaults to the ARN of the user, group, or role that you specify in PolicySourceArn. If you include both a PolicySourceArn (for example, arn:aws:iam::123456789012:user/David) and a CallerArn (for example, arn:aws:iam::123456789012:user/Bob), the result is that you simulate calling the API operations as Bob, as if Bob had David's policies.

    You can specify the ARN of an IAM user, group, or role. You cannot specify the ARN of an assumed role, federated user, or a service principal.

    CallerArn is required if you include a ResourcePolicy and the PolicySourceArn is not the ARN for an IAM user, group, or role. This is required so that the resource-based policy's Principal element has a value to use in evaluating the policy.

    For more information about ARNs, see Amazon Resource Names (ARNs) in the Amazon Web Services General Reference.

    " }, "ContextEntries":{ "shape":"ContextEntryListType", @@ -8618,6 +9078,24 @@ "type":"list", "member":{"shape":"policyDocumentType"} }, + "SourceRoleTemplate":{ + "type":"structure", + "required":[ + "TemplateArn", + "TemplateMinorVersion" + ], + "members":{ + "TemplateArn":{ + "shape":"arnType", + "documentation":"

    The Amazon Resource Name (ARN) of the role template that the role was created from.

    " + }, + "TemplateMinorVersion":{ + "shape":"integerType", + "documentation":"

    The minor version of the role template that was used to create the role.

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

    Contains information about the role template that a role was created from.

    " + }, "Statement":{ "type":"structure", "members":{ @@ -8781,6 +9259,24 @@ } } }, + "TagTemplate":{ + "type":"structure", + "required":[ + "Key", + "Value" + ], + "members":{ + "Key":{ + "shape":"tagTemplateKeyType", + "documentation":"

    The key name of the tag.

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

    The value associated with the tag key.

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

    Represents a tag that is applied to roles that are created from a role template. The key and value can include @{parameter} placeholders that are replaced with template parameter values when the role is created.

    " + }, "TagUserRequest":{ "type":"structure", "required":[ @@ -9561,6 +10057,23 @@ "type":"string", "pattern":"\\d{12}" }, + "accountPropertiesMapType":{ + "type":"map", + "key":{"shape":"accountPropertyKeyType"}, + "value":{"shape":"accountPropertyValueType"} + }, + "accountPropertyKeyType":{ + "type":"string", + "max":50, + "min":1, + "pattern":"^[A-Za-z][A-Za-z0-9/_-]*$" + }, + "accountPropertyValueType":{ + "type":"string", + "documentation":"String representation of the property value. The service will validate and coerce the value based on the property key's expected type. For example, integer properties expect numeric strings, and boolean properties expect \"true\" or \"false\".", + "max":1024, + "min":1 + }, "allUsers":{ "type":"boolean", "box":true @@ -9733,6 +10246,10 @@ "min":16, "pattern":"[\\w]+" }, + "inlinePolicyTemplateListType":{ + "type":"list", + "member":{"shape":"InlinePolicy"} + }, "instanceProfileListType":{ "type":"list", "member":{"shape":"InstanceProfile"}, @@ -9776,6 +10293,25 @@ }, "malformedCertificateMessage":{"type":"string"}, "malformedPolicyDocumentMessage":{"type":"string"}, + "managedByTypeType":{ + "type":"string", + "enum":["Service"] + }, + "managedByValueType":{ + "type":"string", + "max":128, + "min":1 + }, + "managedPolicyArnListType":{ + "type":"list", + "member":{"shape":"arnType"} + }, + "mapStringReplacementValueEntry":{ + "type":"map", + "key":{"shape":"stringType"}, + "value":{"shape":"ReplacementValueEntry"}, + "max":30 + }, "markerType":{ "type":"string", "max":320, @@ -9803,6 +10339,8 @@ "max":128, "min":6 }, + "minorVersionType":{"type":"integer"}, + "nameConflictMessage":{"type":"string"}, "noSuchEntityMessage":{"type":"string"}, "notesType":{ "type":"string", @@ -9832,6 +10370,38 @@ "min":20, "pattern":"^[a-zA-Z0-9:/+=,.@_-]+$" }, + "parameterDefaultValueType":{ + "type":"string", + "max":1024 + }, + "parameterDescriptionType":{ + "type":"string", + "max":1000 + }, + "parameterNameType":{ + "type":"string", + "max":128, + "min":1 + }, + "parameterSubTypeType":{ + "type":"string", + "max":256 + }, + "parameterTypeType":{ + "type":"string", + "enum":[ + "String", + "StringList", + "Number", + "NumberList", + "Arn", + "ArnList" + ] + }, + "parametersDefinitionListType":{ + "type":"list", + "member":{"shape":"ParameterDefinition"} + }, "passwordPolicyViolationMessage":{"type":"string"}, "passwordReusePreventionType":{ "type":"integer", @@ -10008,6 +10578,12 @@ "min":1, "pattern":"^http(s?)://[a-zA-Z0-9._/-]*(\\?[a-zA-Z0-9._=&-]*)?(#[a-zA-Z0-9._/-]*)?$" }, + "replacementValueListType":{ + "type":"list", + "member":{"shape":"stringType"}, + "max":20, + "min":1 + }, "reportGenerationLimitExceededMessage":{"type":"string"}, "requestMessageType":{ "type":"string", @@ -10026,6 +10602,11 @@ "pattern":"[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u00A1-\\u00FF]+" }, "responseMarkerType":{"type":"string"}, + "roleDescriptionPatternType":{ + "type":"string", + "max":512, + "min":1 + }, "roleDescriptionType":{ "type":"string", "max":1000, @@ -10045,16 +10626,40 @@ "max":43200, "min":3600 }, + "roleModifiedMessage":{"type":"string"}, + "roleNamePatternType":{ + "type":"string", + "max":256, + "min":1 + }, "roleNameType":{ "type":"string", "max":64, "min":1, "pattern":"[\\w+=,.@-]+" }, + "rolePathPatternType":{ + "type":"string", + "max":256, + "min":1, + "pattern":"/[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u00A1-\\u00FF]*/" + }, "rolePermissionRestrictionArnListType":{ "type":"list", "member":{"shape":"arnType"} }, + "roleTemplateDescriptionType":{ + "type":"string", + "max":512, + "pattern":"[\\u0009\\u000A\\u000D\\u0020-\\u007E\\u00A1-\\u00FF]*" + }, + "roleTemplateDisabledMessage":{"type":"string"}, + "roleTemplateNameType":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\w+=,.\\-]+" + }, "serialNumberType":{ "type":"string", "max":256, @@ -10223,6 +10828,23 @@ "member":{"shape":"Tag"}, "max":50 }, + "tagTemplateKeyType":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@{}]+" + }, + "tagTemplateListType":{ + "type":"list", + "member":{"shape":"TagTemplate"}, + "max":50 + }, + "tagTemplateValueType":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@{}]*" + }, "tagValueType":{ "type":"string", "max":256, diff --git a/services/iamtoolbox/pom.xml b/services/iamtoolbox/pom.xml new file mode 100644 index 000000000000..df375e29de24 --- /dev/null +++ b/services/iamtoolbox/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + iamtoolbox + AWS Java SDK :: Services :: IAM Toolbox + The AWS Java SDK for IAM Toolbox module holds the client classes that are used for + communicating with IAM Toolbox. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.iamtoolbox + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d8b3fadd44db --- /dev/null +++ b/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-toolbox-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-toolbox-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-toolbox.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iam-toolbox.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-tests.json b/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..5b37eeea76f1 --- /dev/null +++ b/services/iamtoolbox/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,270 @@ +{ + "testCases": [ + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region cn-north-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region cn-north-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region cn-north-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region cn-north-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-gov-east-1.api.aws" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-gov-east-1.api.aws" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox-fips.us-isob-east-1.sc2s.sgov.gov" + } + }, + "params": { + "Region": "us-isob-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://iam-toolbox.us-isob-east-1.sc2s.sgov.gov" + } + }, + "params": { + "Region": "us-isob-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For custom endpoint with region set and fips disabled and dualstack disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with region not set and fips disabled and dualstack disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with fips enabled and dualstack disabled", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with fips disabled and dualstack enabled", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "Missing region", + "expect": { + "error": "Invalid Configuration: Missing Region" + } + } + ], + "version": "1.0" +} \ No newline at end of file diff --git a/services/iamtoolbox/src/main/resources/codegen-resources/paginators-1.json b/services/iamtoolbox/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..b75364b2a2c8 --- /dev/null +++ b/services/iamtoolbox/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,9 @@ +{ + "pagination": { + "GetRequestAuthorizationDetails": { + "input_token": "nextToken", + "output_token": "nextToken", + "result_key": "evaluations" + } + } +} diff --git a/services/iamtoolbox/src/main/resources/codegen-resources/service-2.json b/services/iamtoolbox/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..0d51fac0f066 --- /dev/null +++ b/services/iamtoolbox/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,302 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2018-05-10", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"iam-toolbox", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"IAM Toolbox (Preview)", + "serviceId":"IAM Toolbox", + "signatureVersion":"v4", + "signingName":"iam", + "uid":"iam-toolbox-2018-05-10" + }, + "operations":{ + "GetRequestAuthorizationDetails":{ + "name":"GetRequestAuthorizationDetails", + "http":{ + "method":"GET", + "requestUri":"/authorization-details/{authorizationId}", + "responseCode":200 + }, + "input":{"shape":"GetRequestAuthorizationDetailsInput"}, + "output":{"shape":"GetRequestAuthorizationDetailsOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the authorization details for a specific access denied request. The details include the request context, the evaluations performed, and the policies that were evaluated.

    Use this operation to understand why a request was denied. Supported services include an authorization ID in the access denied error message. Pass that ID to this operation to retrieve the details.

    Authorization details are available for at least 24 hours after the denial.

    To use this operation, you must have the iam:GetRequestAuthorizationDetails permission.

    ", + "readonly":true + } + }, + "shapes":{ + "AccessDeniedException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The caller does not have sufficient access to perform this action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "AttachedTo":{ + "type":"structure", + "members":{ + "arn":{ + "shape":"AttachedToArnString", + "documentation":"

    The ARN of the entity that the policy is attached to. The ARN format depends on the policy type:

    • For identity, session, and permissions boundary policies, this is the principal ARN (for example, an IAM role or user ARN).

    • For resource-based policies, this is the resource ARN.

    • For organization control policies (SCPs and RCPs), this is the AWS Organizations ARN of the account, organizational unit, or root.

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

    An entity that a policy is attached to, identified by its ARN.

    " + }, + "AttachedToArnString":{ + "type":"string", + "pattern":"arn:[^:]*:[^:]*:[^:]*:[^:]*:.*" + }, + "AttachedToList":{ + "type":"list", + "member":{"shape":"AttachedTo"}, + "documentation":"

    A list of entities that a policy is attached to.

    " + }, + "AuthorizationContext":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"Document"}, + "documentation":"

    The map of context keys and their values in the request context. Context keys vary by service and request type.

    " + }, + "Boolean":{ + "type":"boolean", + "box":true + }, + "Document":{ + "type":"structure", + "members":{}, + "document":true + }, + "EvaluatedEffect":{ + "type":"string", + "documentation":"

    The result of a policy evaluation.

    ", + "enum":[ + "ALLOW", + "EXPLICIT_DENY", + "IMPLICIT_DENY" + ] + }, + "Evaluation":{ + "type":"structure", + "required":[ + "action", + "resource" + ], + "members":{ + "action":{ + "shape":"String", + "documentation":"

    The action evaluated for this request (for example, iam:PassRole).

    " + }, + "resource":{ + "shape":"String", + "documentation":"

    The resource that the action targeted. This is typically a resource ARN, but can be a wildcard ARN that matches multiple resources, or empty for actions that are not resource-specific.

    " + }, + "context":{ + "shape":"AuthorizationContext", + "documentation":"

    The context keys and values specific to this evaluation. These are applied on top of the request context.

    " + }, + "evaluatedEffect":{ + "shape":"EvaluatedEffect", + "documentation":"

    The result of the evaluation. Valid values:

    • ALLOW - The action was allowed.

    • EXPLICIT_DENY - The action was explicitly denied by a policy.

    • IMPLICIT_DENY - The action was denied because no policy allowed it.

    " + }, + "matchedPolicies":{ + "shape":"MatchedPolicyList", + "documentation":"

    The policies that matched during evaluation of this action and resource. An implicit denial produces no matched policies.

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

    Represents an individual evaluation for a single action and resource pair. This includes the context, the resulting effect, and any policies that matched.

    " + }, + "Evaluations":{ + "type":"list", + "member":{"shape":"Evaluation"}, + "documentation":"

    A list of evaluations.

    " + }, + "GetRequestAuthorizationDetailsInput":{ + "type":"structure", + "required":["authorizationId"], + "members":{ + "authorizationId":{ + "shape":"GetRequestAuthorizationDetailsInputAuthorizationIdString", + "documentation":"

    The authorization ID received in the access denied error message. This ID identifies the specific request to retrieve details for.

    ", + "location":"uri", + "locationName":"authorizationId" + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The pagination token from a previous call, used to retrieve the next page of evaluations. Omit this value on the first call.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "GetRequestAuthorizationDetailsInputAuthorizationIdString":{ + "type":"string", + "pattern":"[0123456789abcdefghijklmnopqrstuvwxyz]+" + }, + "GetRequestAuthorizationDetailsOutput":{ + "type":"structure", + "required":[ + "requestContext", + "evaluations", + "policies" + ], + "members":{ + "requestContext":{ + "shape":"AuthorizationContext", + "documentation":"

    The request context is the set of context keys and values that apply to the entire request and are shared by all evaluations.

    " + }, + "evaluations":{ + "shape":"Evaluations", + "documentation":"

    The list of evaluations for this request. Each evaluation shows how a single action and resource pair was evaluated. This includes the context, the effect, and any policies that matched.

    " + }, + "policies":{ + "shape":"PolicyInfoList", + "documentation":"

    The list of policies that were evaluated.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The pagination token for retrieving the next page of evaluations. This value is absent when there are no more results.

    " + } + } + }, + "InternalServerException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    An unexpected error occurred while processing the request. Try again.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, + "MatchedPolicy":{ + "type":"structure", + "required":["uri"], + "members":{ + "uri":{ + "shape":"String", + "documentation":"

    The URI of the policy. This cross-references an entry in the top-level policies list. The value depends on the policy type:

    • For managed policies, this is the policy ARN.

    • For inline policies, this is an opaque identifier.

    " + }, + "matchedStatements":{ + "shape":"MatchedStatementList", + "documentation":"

    The statements within the policy that matched during the evaluation.

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

    A policy that matched during evaluation, referenced by URI. The URI corresponds to a policy in the top-level policies list.

    " + }, + "MatchedPolicyList":{ + "type":"list", + "member":{"shape":"MatchedPolicy"}, + "documentation":"

    A list of policies that matched during an evaluation.

    " + }, + "MatchedStatement":{ + "type":"structure", + "members":{ + "sid":{ + "shape":"String", + "documentation":"

    The statement ID (Sid). If the statement has no Sid, one is generated for reference.

    " + }, + "evaluatedEffect":{ + "shape":"StatementEffect", + "documentation":"

    The evaluated effect of this statement. Valid values:

    • ALLOW - The statement allows the action.

    • DENY - The statement denies the action.

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

    A statement that matched during evaluation.

    " + }, + "MatchedStatementList":{ + "type":"list", + "member":{"shape":"MatchedStatement"}, + "documentation":"

    A list of statements that matched within a policy.

    " + }, + "PolicyInfo":{ + "type":"structure", + "members":{ + "type":{ + "shape":"PolicyType", + "documentation":"

    The type of policy. Valid values:

    • IDENTITY_BASED_POLICY - An identity-based policy attached to an IAM user, group, or role.

    • PERMISSIONS_BOUNDARY - A permissions boundary for an IAM entity.

    • RESOURCE_BASED_POLICY - A resource-based policy attached to a resource.

    • RESOURCE_CONTROL_POLICY - A resource control policy (RCP) in AWS Organizations.

    • SERVICE_CONTROL_POLICY - A service control policy (SCP) in AWS Organizations.

    • SESSION_POLICY - A session policy passed during role assumption or federation.

    • VPC_ENDPOINT_POLICY - A VPC endpoint policy.

    " + }, + "inline":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this is an inline policy (true) or a managed policy (false).

    " + }, + "uri":{ + "shape":"String", + "documentation":"

    A URI that identifies the policy. Use this URI to cross-reference the policy with the matching policies in each evaluation. The value depends on the policy type:

    • For managed policies, this is the policy ARN.

    • For inline policies, which have no ARN, this is an opaque identifier.

    " + }, + "attachedTo":{ + "shape":"AttachedToList", + "documentation":"

    The entities that the policy is attached to. For identity, session, and resource-based policies, this is typically a single entity. For organization control policies (SCPs and RCPs), it can be multiple entities at different levels of the organization hierarchy.

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

    Contains details about a policy evaluated during authorization. Details include the policy type, whether it is inline or managed, a URI that identifies it, and the entities it is attached to.

    " + }, + "PolicyInfoList":{ + "type":"list", + "member":{"shape":"PolicyInfo"}, + "documentation":"

    A list of policy details.

    " + }, + "PolicyType":{ + "type":"string", + "documentation":"

    The policy type.

    ", + "enum":[ + "IDENTITY_BASED_POLICY", + "RESOURCE_BASED_POLICY", + "PERMISSIONS_BOUNDARY", + "SESSION_POLICY", + "SERVICE_CONTROL_POLICY", + "RESOURCE_CONTROL_POLICY", + "VPC_ENDPOINT_POLICY" + ] + }, + "ResourceNotFoundException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The requested authorization details do not exist in this region or have expired. Verify that the authorization ID from the access denied error message is correct and the call is made in the region where the denial occurred. Ensure that the calling principal belongs to the same account or organization as the original denied request.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "StatementEffect":{ + "type":"string", + "documentation":"

    The effect of a matched statement.

    ", + "enum":[ + "ALLOW", + "DENY" + ] + }, + "String":{"type":"string"}, + "ValidationException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request is malformed or is missing one or more required parameters. Check the request parameters and try again.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + } + }, + "documentation":"

    Contains APIs to work with AWS Identity and Access Management (IAM).

    " +} diff --git a/services/iamtoolbox/src/main/resources/codegen-resources/waiters-2.json b/services/iamtoolbox/src/main/resources/codegen-resources/waiters-2.json new file mode 100644 index 000000000000..13f60ee66be6 --- /dev/null +++ b/services/iamtoolbox/src/main/resources/codegen-resources/waiters-2.json @@ -0,0 +1,5 @@ +{ + "version": 2, + "waiters": { + } +} diff --git a/services/identitystore/pom.xml b/services/identitystore/pom.xml index 17d430b62640..8b5daac52161 100644 --- a/services/identitystore/pom.xml +++ b/services/identitystore/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT identitystore AWS Java SDK :: Services :: Identitystore diff --git a/services/identitystore/src/main/resources/codegen-resources/customization.config b/services/identitystore/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/identitystore/src/main/resources/codegen-resources/customization.config +++ b/services/identitystore/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/identitystore/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/identitystore/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c8b1f9bc559c --- /dev/null +++ b/services/identitystore/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identitystore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identitystore.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identitystore-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identitystore.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://identitystore.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/identitystore/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/identitystore/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 82e88753dad9..000000000000 --- a/services/identitystore/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://identitystore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://identitystore.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://identitystore-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://identitystore.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://identitystore.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/imagebuilder/pom.xml b/services/imagebuilder/pom.xml index 40c0145640e7..a22da1d6154a 100644 --- a/services/imagebuilder/pom.xml +++ b/services/imagebuilder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT imagebuilder AWS Java SDK :: Services :: Imagebuilder diff --git a/services/imagebuilder/src/main/resources/codegen-resources/customization.config b/services/imagebuilder/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/imagebuilder/src/main/resources/codegen-resources/customization.config +++ b/services/imagebuilder/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/imagebuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/imagebuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5d2e73c48f37 --- /dev/null +++ b/services/imagebuilder/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://imagebuilder-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://imagebuilder.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://imagebuilder-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://imagebuilder.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://imagebuilder.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/imagebuilder/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/imagebuilder/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 77ad47f0d8f7..000000000000 --- a/services/imagebuilder/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://imagebuilder-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://imagebuilder.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://imagebuilder-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://imagebuilder.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://imagebuilder.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/imagebuilder/src/main/resources/codegen-resources/service-2.json b/services/imagebuilder/src/main/resources/codegen-resources/service-2.json index 9bea2d695d8d..084b923b076b 100644 --- a/services/imagebuilder/src/main/resources/codegen-resources/service-2.json +++ b/services/imagebuilder/src/main/resources/codegen-resources/service-2.json @@ -33,7 +33,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    CancelImageCreation cancels the creation of Image. This operation can only be used on images in a non-terminal state.

    " + "documentation":"

    Cancels the creation of an image. This operation can only be used on images in a non-terminal state. Cancellation is asynchronous: the request returns immediately, then Image Builder stops the running build and moves the image to the CANCELLED state. Output resources that the build already created, such as AMIs and snapshots, aren't removed.

    " }, "CancelLifecycleExecution":{ "name":"CancelLifecycleExecution", @@ -53,7 +53,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Cancel a specific image lifecycle policy runtime instance.

    " + "documentation":"

    Cancels a lifecycle execution – a single run of lifecycle actions that a lifecycle policy or a StartResourceStateUpdate request started. You can only cancel an execution that hasn't reached a terminal state. Cancellation is asynchronous and doesn't undo completed lifecycle actions.

    " }, "CreateComponent":{ "name":"CreateComponent", @@ -77,7 +77,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"DryRunOperationException"} ], - "documentation":"

    Creates a new component that can be used to build, validate, test, and assess your image. The component is based on a YAML document that you specify using exactly one of the following methods:

    • Inline, using the data property in the request body.

    • A URL that points to a YAML document file stored in Amazon S3, using the uri property in the request body.

    " + "documentation":"

    Creates a new component that can be used to build, validate, test, and assess your image. The component is based on a YAML document that you specify using exactly one of the following methods:

    • Inline, using the data property in the request body.

    • A URL that points to a YAML document file stored in Amazon S3, using the uri property in the request body.

    Image Builder determines the component type from the document. If the document contains a single phase named test, the component type is TEST. Otherwise, the component type is BUILD.

    " }, "CreateContainerRecipe":{ "name":"CreateContainerRecipe", @@ -98,7 +98,8 @@ {"shape":"InvalidVersionNumberException"}, {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Creates a new container recipe. Container recipes define how images are configured, tested, and assessed.

    " }, @@ -121,9 +122,10 @@ {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, {"shape":"InvalidParameterCombinationException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Creates a new distribution configuration. Distribution configurations define and configure the outputs of your pipeline.

    " + "documentation":"

    Creates a new distribution configuration. Distribution configurations define and configure the outputs for your images, including the target Regions, accounts, and settings for each Region.

    " }, "CreateImage":{ "name":"CreateImage", @@ -144,7 +146,7 @@ {"shape":"ResourceInUseException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Creates a new image. This request will create a new image along with all of the configured output resources defined in the distribution configuration. You must specify exactly one recipe for your image, using either a ContainerRecipeArn or an ImageRecipeArn.

    " + "documentation":"

    Creates a new image along with all configured output resources defined in the distribution configuration. You must specify exactly one recipe for your image, using either a containerRecipeArn or an imageRecipeArn.

    The response returns as soon as Image Builder creates the new image resource. The image build process runs asynchronously. To check its progress, call GetImage and check the image status.

    " }, "CreateImagePipeline":{ "name":"CreateImagePipeline", @@ -164,9 +166,10 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Creates a new image pipeline. Image pipelines enable you to automate the creation and distribution of images.

    " + "documentation":"

    Creates a new image pipeline. Use image pipelines to automate the creation and distribution of images. You must specify exactly one recipe for the pipeline, using either a containerRecipeArn or an imageRecipeArn.

    " }, "CreateImageRecipe":{ "name":"CreateImageRecipe", @@ -187,7 +190,8 @@ {"shape":"InvalidVersionNumberException"}, {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Creates a new image recipe. Image recipes define how images are configured, tested, and assessed.

    " }, @@ -209,7 +213,8 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Creates a new infrastructure configuration. An infrastructure configuration defines the environment in which your image will be built and tested.

    " }, @@ -231,9 +236,10 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"}, {"shape":"ResourceAlreadyExistsException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ServiceQuotaExceededException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Create a lifecycle policy resource.

    " + "documentation":"

    Creates a lifecycle policy resource.

    " }, "CreateWorkflow":{ "name":"CreateWorkflow", @@ -257,7 +263,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"DryRunOperationException"} ], - "documentation":"

    Create a new workflow or a new version of an existing workflow.

    " + "documentation":"

    Creates a new workflow or a new version of an existing workflow. If a workflow with the same name and semantic version already exists, and your request changes its configuration, Image Builder creates a new build version. If the configuration is identical to the latest build version, the request fails because that workflow configuration already exists.

    " }, "DeleteComponent":{ "name":"DeleteComponent", @@ -276,7 +282,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes a component build version.

    " + "documentation":"

    Deletes a component build version. The request fails with ResourceDependencyException if an image recipe or container recipe references this component version. It also fails if the component build version is shared with other accounts.

    " }, "DeleteContainerRecipe":{ "name":"DeleteContainerRecipe", @@ -295,7 +301,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes a container recipe.

    " + "documentation":"

    Deletes a container recipe. The request fails with ResourceDependencyException if the recipe is shared with other accounts, or if an image pipeline references it.

    " }, "DeleteDistributionConfiguration":{ "name":"DeleteDistributionConfiguration", @@ -314,7 +320,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes a distribution configuration.

    " + "documentation":"

    Deletes a distribution configuration. You can't delete a configuration that an image pipeline still references. The request fails with ResourceDependencyException. Update or delete the referencing pipelines first.

    " }, "DeleteImage":{ "name":"DeleteImage", @@ -333,7 +339,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes an Image Builder image resource. This does not delete any EC2 AMIs or ECR container images that are created during the image build process. You must clean those up separately, using the appropriate Amazon EC2 or Amazon ECR console actions, or API or CLI commands.

    " + "documentation":"

    Deletes an Image Builder image resource. This does not delete any EC2 AMIs or ECR container images that are created during the image build process. You must clean those up separately, using the appropriate Amazon EC2 or Amazon ECR console actions, or API or CLI commands.

    The request fails with ResourceDependencyException if the image is shared with other accounts, or if other resources depend on it. It also fails while the image build is still running. Cancel an in-progress build with CancelImageCreation before you delete the image.

    " }, "DeleteImagePipeline":{ "name":"DeleteImagePipeline", @@ -352,7 +358,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes an image pipeline.

    " + "documentation":"

    Deletes an image pipeline. Images that the pipeline created aren't deleted - remove those separately with DeleteImage. You can delete a pipeline while a build that it started is still running. The build continues independently.

    " }, "DeleteImageRecipe":{ "name":"DeleteImageRecipe", @@ -390,7 +396,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes an infrastructure configuration.

    " + "documentation":"

    Deletes an infrastructure configuration. You can't delete a configuration that an image pipeline still references. The request fails with ResourceDependencyException. Update or delete the referencing pipelines first.

    " }, "DeleteLifecyclePolicy":{ "name":"DeleteLifecyclePolicy", @@ -409,7 +415,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Delete the specified lifecycle policy resource.

    " + "documentation":"

    Deletes the specified lifecycle policy resource. Deleting the policy removes its schedule, so no further lifecycle runs occur for that policy. If a lifecycle execution is in progress for the policy, Image Builder cancels it. Deletion doesn't revert actions that the policy already applied to your resources.

    " }, "DeleteWorkflow":{ "name":"DeleteWorkflow", @@ -428,7 +434,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceDependencyException"} ], - "documentation":"

    Deletes a specific workflow resource.

    " + "documentation":"

    Deletes a specific workflow resource. You can't delete a workflow build version while an image pipeline references it. The request fails with ResourceDependencyException.

    " }, "DistributeImage":{ "name":"DistributeImage", @@ -470,7 +476,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets a component object.

    " + "documentation":"

    Retrieves a component object.

    " }, "GetComponentPolicy":{ "name":"GetComponentPolicy", @@ -488,7 +494,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets a component policy.

    " + "documentation":"

    Retrieves a component policy.

    " }, "GetContainerRecipe":{ "name":"GetContainerRecipe", @@ -542,7 +548,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets a distribution configuration.

    " + "documentation":"

    Retrieves a distribution configuration.

    " }, "GetImage":{ "name":"GetImage", @@ -560,7 +566,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an image.

    " + "documentation":"

    Retrieves an image.

    " }, "GetImagePipeline":{ "name":"GetImagePipeline", @@ -578,7 +584,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an image pipeline.

    " + "documentation":"

    Retrieves an image pipeline.

    " }, "GetImagePolicy":{ "name":"GetImagePolicy", @@ -596,7 +602,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an image policy.

    " + "documentation":"

    Retrieves an image policy.

    " }, "GetImageRecipe":{ "name":"GetImageRecipe", @@ -614,7 +620,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an image recipe.

    " + "documentation":"

    Retrieves an image recipe.

    " }, "GetImageRecipePolicy":{ "name":"GetImageRecipePolicy", @@ -632,7 +638,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an image recipe policy.

    " + "documentation":"

    Retrieves an image recipe policy.

    " }, "GetInfrastructureConfiguration":{ "name":"GetInfrastructureConfiguration", @@ -650,7 +656,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Gets an infrastructure configuration.

    " + "documentation":"

    Retrieves an infrastructure configuration.

    " }, "GetLifecycleExecution":{ "name":"GetLifecycleExecution", @@ -668,7 +674,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get the runtime information that was logged for a specific runtime instance of the lifecycle policy.

    " + "documentation":"

    Retrieves runtime information for a lifecycle execution – a single run of lifecycle actions that a lifecycle policy or a StartResourceStateUpdate request started.

    " }, "GetLifecyclePolicy":{ "name":"GetLifecyclePolicy", @@ -686,7 +692,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get details for the specified image lifecycle policy.

    " + "documentation":"

    Retrieves details for the specified image lifecycle policy.

    " }, "GetMarketplaceResource":{ "name":"GetMarketplaceResource", @@ -704,7 +710,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Verify the subscription and perform resource dependency checks on the requested Amazon Web Services Marketplace resource. For Amazon Web Services Marketplace components, the response contains fields to download the components and their artifacts.

    " + "documentation":"

    Verifies the subscription and performs resource dependency checks on the requested Amazon Web Services Marketplace resource. The caller must be entitled to the resource. For Amazon Web Services Marketplace components, the response contains fields to download the components and their artifacts.

    " }, "GetWorkflow":{ "name":"GetWorkflow", @@ -722,7 +728,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get a workflow resource object.

    " + "documentation":"

    Retrieves a workflow resource object.

    " }, "GetWorkflowExecution":{ "name":"GetWorkflowExecution", @@ -740,7 +746,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get the runtime information that was logged for a specific runtime instance of the workflow.

    " + "documentation":"

    Retrieves runtime information for a specific runtime instance of the workflow.

    " }, "GetWorkflowStepExecution":{ "name":"GetWorkflowStepExecution", @@ -758,7 +764,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get the runtime information that was logged for a specific runtime instance of the workflow step.

    " + "documentation":"

    Retrieves runtime information for a specific runtime instance of the workflow step.

    " }, "ImportComponent":{ "name":"ImportComponent", @@ -780,7 +786,7 @@ {"shape":"ResourceInUseException"}, {"shape":"InvalidParameterCombinationException"} ], - "documentation":"

    Imports a component and transforms its data into a component document.

    " + "documentation":"

    Imports a component and transforms its data into a component document. For the SHELL format, Image Builder wraps your script in a component document with a single step that runs the script.

    " }, "ImportDiskImage":{ "name":"ImportDiskImage", @@ -797,7 +803,7 @@ {"shape":"AccessDeniedException"}, {"shape":"TooManyRequestsException"} ], - "documentation":"

    Import a Windows operating system image from a verified Microsoft ISO disk file. The following disk images are supported:

    • Windows 11 Enterprise

    " + "documentation":"

    Imports a Windows operating system image from a verified Microsoft ISO disk file. The following disk images are supported:

    • Windows 11 Enterprise

    The response returns as soon as Image Builder creates the new image resource in the PENDING state. The conversion from ISO file to AMI then runs asynchronously on an EC2 instance that Image Builder launches with the specified infrastructure configuration.

    " }, "ImportVmImage":{ "name":"ImportVmImage", @@ -812,7 +818,7 @@ {"shape":"ClientException"}, {"shape":"ServiceUnavailableException"} ], - "documentation":"

    When you export your virtual machine (VM) from its virtualization environment, that process creates a set of one or more disk container files that act as snapshots of your VM’s environment, settings, and data. The Amazon EC2 API ImportImage action uses those files to import your VM and create an AMI. To import using the CLI command, see import-image

    You can reference the task ID from the VM import to pull in the AMI that the import created as the base image for your Image Builder recipe.

    " + "documentation":"

    Creates an Image Builder image resource from an Amazon EC2 VM import task. The response returns as soon as Image Builder creates the image resource in the PENDING state. Image Builder then monitors the import task asynchronously. When the task completes, Image Builder records the AMI that it produced as the new image's output resource and marks the image AVAILABLE. You can then use the imported image as the base image for your recipes.

    To create the VM import task, use the Amazon EC2 API ImportImage operation, or the import-image CLI command.

    " }, "ListComponentBuildVersions":{ "name":"ListComponentBuildVersions", @@ -831,7 +837,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Returns the list of component build versions for the specified component version Amazon Resource Name (ARN).

    " + "documentation":"

    Returns a list of component build versions for the specified component version ARN. You can only list build versions for components that your account owns. Deprecated build versions aren't included in the results.

    " }, "ListComponents":{ "name":"ListComponents", @@ -850,7 +856,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Returns the list of components that can be filtered by name, or by using the listed filters to streamline results. Newly created components can take up to two minutes to appear in the ListComponents API Results.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    Returns the list of components that you have access to. By default, the response doesn't include components in the DEPRECATED state. To list deprecated components, use the status filter with the value DEPRECATED.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "ListContainerRecipes":{ "name":"ListContainerRecipes", @@ -927,7 +933,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    List the Packages that are associated with an Image Build Version, as determined by Amazon Web Services Systems Manager Inventory at build time.

    " + "documentation":"

    Lists the packages that are associated with an image build version, as determined by Amazon Web Services Systems Manager Inventory at build time.

    " }, "ListImagePipelineImages":{ "name":"ListImagePipelineImages", @@ -1004,7 +1010,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Returns a list of image scan aggregations for your account. You can filter by the type of key that Image Builder uses to group results. For example, if you want to get a list of findings by severity level for one of your pipelines, you might specify your pipeline with the imagePipelineArn filter. If you don't specify a filter, Image Builder returns an aggregation for your account.

    To streamline results, you can use the following filters in your request:

    • accountId

    • imageBuildVersionArn

    • imagePipelineArn

    • vulnerabilityId

    " + "documentation":"

    Returns a list of image scan aggregations for your account. You can filter by the type of key that Image Builder uses to group results. For example, if you want to get a list of findings by severity level for one of your pipelines, you might specify your pipeline with the imagePipelineArn filter. If you don't specify a filter, Image Builder returns an aggregation for your account.

    To streamline results, you can use the following filters in your request:

    • imageBuildVersionArn

    • imagePipelineArn

    • vulnerabilityId

    " }, "ListImageScanFindings":{ "name":"ListImageScanFindings", @@ -1023,7 +1029,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Returns a list of image scan findings for your account.

    " + "documentation":"

    Returns a list of image scan findings for your account. Amazon Inspector generates the findings when it scans images that have scanning enabled.

    " }, "ListImages":{ "name":"ListImages", @@ -1042,7 +1048,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Returns the list of images that you have access to. Newly created images can take up to two minutes to appear in the ListImages API Results.

    " + "documentation":"

    Returns the list of images that you have access to.

    " }, "ListInfrastructureConfigurations":{ "name":"ListInfrastructureConfigurations", @@ -1080,7 +1086,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    List resources that the runtime instance of the image lifecycle identified for lifecycle actions.

    " + "documentation":"

    Lists resources that the runtime instance of the image lifecycle identified for lifecycle actions.

    " }, "ListLifecycleExecutions":{ "name":"ListLifecycleExecutions", @@ -1099,7 +1105,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get the lifecycle runtime history for the specified resource.

    " + "documentation":"

    Retrieves the lifecycle runtime history for the specified resource.

    " }, "ListLifecyclePolicies":{ "name":"ListLifecyclePolicies", @@ -1118,7 +1124,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get a list of lifecycle policies in your Amazon Web Services account.

    " + "documentation":"

    Retrieves a list of lifecycle policies in your Amazon Web Services account.

    " }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -1152,7 +1158,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Get a list of workflow steps that are waiting for action for workflows in your Amazon Web Services account.

    " + "documentation":"

    Lists the workflow steps in your Amazon Web Services account that have paused at a WaitForAction step, and are waiting for you to respond. To send a response, call SendWorkflowStepAction.

    " }, "ListWorkflowBuildVersions":{ "name":"ListWorkflowBuildVersions", @@ -1228,7 +1234,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Lists workflow build versions based on filtering parameters.

    " + "documentation":"

    Lists workflow versions based on filtering parameters. To list the build versions of a specific workflow version, call ListWorkflowBuildVersions.

    " }, "PutComponentPolicy":{ "name":"PutComponentPolicy", @@ -1248,7 +1254,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Applies a policy to a component. We recommend that you call the RAM API CreateResourceShare to share resources. If you call the Image Builder API PutComponentPolicy, you must also call the RAM API PromoteResourceShareCreatedFromPolicy in order for the resource to be visible to all principals with whom the resource is shared.

    " + "documentation":"

    Applies a policy to a component. The preferred way to share resources is with the RAM API CreateResourceShare. If you use the PutComponentPolicy operation instead, you must also call the RAM API PromoteResourceShareCreatedFromPolicy. Otherwise, the resource isn't visible to the principals that it's shared with.

    " }, "PutContainerRecipePolicy":{ "name":"PutContainerRecipePolicy", @@ -1268,7 +1274,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Applies a policy to a container image. We recommend that you call the RAM API CreateResourceShare (https://docs.aws.amazon.com//ram/latest/APIReference/API_CreateResourceShare.html) to share resources. If you call the Image Builder API PutContainerImagePolicy, you must also call the RAM API PromoteResourceShareCreatedFromPolicy (https://docs.aws.amazon.com//ram/latest/APIReference/API_PromoteResourceShareCreatedFromPolicy.html) in order for the resource to be visible to all principals with whom the resource is shared.

    " + "documentation":"

    Applies a policy to a container recipe. The preferred way to share resources is with the RAM API CreateResourceShare. If you use the PutContainerRecipePolicy operation instead, you must also call the RAM API PromoteResourceShareCreatedFromPolicy. Otherwise, the resource isn't visible to the principals that it's shared with.

    " }, "PutImagePolicy":{ "name":"PutImagePolicy", @@ -1288,7 +1294,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Applies a policy to an image. We recommend that you call the RAM API CreateResourceShare to share resources. If you call the Image Builder API PutImagePolicy, you must also call the RAM API PromoteResourceShareCreatedFromPolicy in order for the resource to be visible to all principals with whom the resource is shared.

    " + "documentation":"

    Applies a policy to an image. The preferred way to share resources is with the RAM API CreateResourceShare. If you use the PutImagePolicy operation instead, you must also call the RAM API PromoteResourceShareCreatedFromPolicy. Otherwise, the resource isn't visible to the principals that it's shared with.

    " }, "PutImageRecipePolicy":{ "name":"PutImageRecipePolicy", @@ -1308,7 +1314,7 @@ {"shape":"ForbiddenException"}, {"shape":"CallRateLimitExceededException"} ], - "documentation":"

    Applies a policy to an image recipe. We recommend that you call the RAM API CreateResourceShare to share resources. If you call the Image Builder API PutImageRecipePolicy, you must also call the RAM API PromoteResourceShareCreatedFromPolicy in order for the resource to be visible to all principals with whom the resource is shared.

    " + "documentation":"

    Applies a policy to an image recipe. The preferred way to share resources is with the RAM API CreateResourceShare. If you use the PutImageRecipePolicy operation instead, you must also call the RAM API PromoteResourceShareCreatedFromPolicy. Otherwise, the resource isn't visible to the principals that it's shared with.

    " }, "RetryImage":{ "name":"RetryImage", @@ -1328,7 +1334,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    RetryImage retries an image distribution without rebuilding the image.

    " + "documentation":"

    Retries a failed or canceled image build without rebuilding the phases that already completed. The image re-runs asynchronously in place: the same build version returns to the test or distribution phase where it failed and continues from there. No new image build version is created. Retry is only supported for AMI-based images.

    " }, "SendWorkflowStepAction":{ "name":"SendWorkflowStepAction", @@ -1350,7 +1356,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Pauses or resumes image creation when the associated workflow runs a WaitForAction step.

    " + "documentation":"

    Sends an action to a workflow step that has paused at a WaitForAction step, so that image creation can continue. To find the steps that are waiting for an action, call ListWaitingWorkflowSteps.

    " }, "StartImagePipelineExecution":{ "name":"StartImagePipelineExecution", @@ -1371,7 +1377,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Manually triggers a pipeline to create an image.

    " + "documentation":"

    Manually triggers a pipeline to create an image. You can start a build this way whether the pipeline is enabled or disabled. The response returns as soon as Image Builder creates the new image resource and queues the build. Use the returned imageBuildVersionArn with GetImage to track build progress.

    " }, "StartResourceStateUpdate":{ "name":"StartResourceStateUpdate", @@ -1392,7 +1398,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Begin asynchronous resource state update for lifecycle changes to the specified image resources.

    " + "documentation":"

    Begins an ad-hoc state change for the specified image build version. This is a one-time operation - if you schedule the update, it runs only once. If the request includes underlying resources, or schedules the update far enough in the future, Image Builder runs the update as an asynchronous lifecycle execution and returns its identifier. Otherwise, for target states other than DELETED, the state change applies immediately. If a request that starts a lifecycle execution arrives while the image already has one in progress, Image Builder rejects it.

    " }, "TagResource":{ "name":"TagResource", @@ -1443,7 +1449,7 @@ {"shape":"ResourceInUseException"}, {"shape":"InvalidParameterCombinationException"} ], - "documentation":"

    Updates a new distribution configuration. Distribution configurations define and configure the outputs of your pipeline.

    " + "documentation":"

    Updates a distribution configuration. Distribution configurations define and configure the outputs for your images, including the target Regions, accounts, and settings for each Region.

    This operation doesn't support selective updates. The request replaces the stored configuration, so include every setting that you want to keep.

    " }, "UpdateImagePipeline":{ "name":"UpdateImagePipeline", @@ -1463,7 +1469,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Updates an image pipeline. Image pipelines enable you to automate the creation and distribution of images. You must specify exactly one recipe for your image, using either a containerRecipeArn or an imageRecipeArn.

    UpdateImagePipeline does not support selective updates for the pipeline. You must specify all of the required properties in the update request, not just the properties that have changed.

    " + "documentation":"

    Updates an image pipeline. Use image pipelines to automate the creation and distribution of images. You must specify exactly one recipe for your image, using either a containerRecipeArn or an imageRecipeArn. The recipe must be the same type, image or container, as the pipeline's current recipe.

    UpdateImagePipeline does not support selective updates. The request replaces the pipeline's entire configuration, so include every setting that you want to keep. Any optional property that you omit is removed or reset to its default.

    " }, "UpdateInfrastructureConfiguration":{ "name":"UpdateInfrastructureConfiguration", @@ -1483,7 +1489,7 @@ {"shape":"CallRateLimitExceededException"}, {"shape":"ResourceInUseException"} ], - "documentation":"

    Updates a new infrastructure configuration. An infrastructure configuration defines the environment in which your image will be built and tested.

    " + "documentation":"

    Updates an infrastructure configuration. An infrastructure configuration defines the environment in which Image Builder builds and tests your image.

    This operation doesn't support selective updates. The request replaces the configuration, so include every setting that you want to keep. Omitted optional properties are cleared.

    " }, "UpdateLifecyclePolicy":{ "name":"UpdateLifecyclePolicy", @@ -1504,7 +1510,7 @@ {"shape":"ResourceInUseException"}, {"shape":"InvalidParameterCombinationException"} ], - "documentation":"

    Update the specified lifecycle policy.

    " + "documentation":"

    Updates the specified lifecycle policy. The request replaces the existing policy configuration rather than merging changes, so re-specify every setting that you want to keep. The resourceType must match the existing policy's value.

    " } }, "shapes":{ @@ -1546,11 +1552,11 @@ "members":{ "systemsManagerAgent":{ "shape":"SystemsManagerAgent", - "documentation":"

    Contains settings for the Systems Manager agent on your build instance.

    " + "documentation":"

    The Systems Manager agent settings for your build instance. This setting applies to Linux and macOS build instances only. Requests that set it for a recipe with a Windows base image are rejected.

    " }, "userDataOverride":{ "shape":"UserDataOverride", - "documentation":"

    Use this property to provide commands or a command script to run when you launch your build instance.

    The userDataOverride property replaces any commands that Image Builder might have added to ensure that Systems Manager is installed on your Linux build instance. If you override the user data, make sure that you add commands to install Systems Manager, if it is not pre-installed on your base image.

    The user data is always base 64 encoded. For example, the following commands are encoded as IyEvYmluL2Jhc2gKbWtkaXIgLXAgL3Zhci9iYi8KdG91Y2ggL3Zhci$:

    #!/bin/bash

    mkdir -p /var/bb/

    touch /var

    " + "documentation":"

    Use this property to provide commands or a command script to run when you launch your build instance.

    The userDataOverride property replaces any commands that Image Builder might have added to ensure that Systems Manager is installed on your Linux build instance. If you override the user data, make sure that you add commands to install Systems Manager, if it is not pre-installed on your base image.

    The user data is always base 64 encoded. For example, the following commands are encoded as IyEvYmluL2Jhc2gKbWtkaXIgLXAgL3Zhci9iYi8KdG91Y2ggL3Zhcg==:

    #!/bin/bash

    mkdir -p /var/bb/

    touch /var

    " } }, "documentation":"

    In addition to your infrastructure configuration, these settings provide an extra layer of control over your build instances. You can also specify commands to run on launch for all of your build instances.

    Image Builder does not automatically install the Systems Manager agent on Windows instances. If your base image includes the Systems Manager agent, then the AMI that you create will also include the agent. For Linux instances, if the base image does not already include the Systems Manager agent, Image Builder installs it. For Linux instances where Image Builder installs the Systems Manager agent, you can choose whether to keep it for the AMI that you create.

    " @@ -1574,7 +1580,10 @@ "shape":"NonEmptyString", "documentation":"

    The description of the Amazon EC2 AMI. Minimum and maximum length are in characters.

    " }, - "state":{"shape":"ImageState"}, + "state":{ + "shape":"ImageState", + "documentation":"

    The state of the AMI, which includes the status and, if applicable, the reason for that status.

    " + }, "accountId":{ "shape":"NonEmptyString", "documentation":"

    The account ID of the owner of the AMI.

    " @@ -1587,15 +1596,15 @@ "members":{ "name":{ "shape":"AmiNameString", - "documentation":"

    The name of the output AMI.

    " + "documentation":"

    The name of the output AMI. The name must include the {{ imagebuilder:buildDate }} dynamic tag so that each build produces a uniquely named AMI. If you don't specify a name, Image Builder names the output AMI with the image name followed by the build timestamp, for example my-image 2022-10-26T22-30-05.912619Z.

    " }, "description":{ "shape":"NonEmptyString", - "documentation":"

    The description of the AMI distribution configuration. Minimum and maximum length are in characters.

    " + "documentation":"

    The description to apply to the distributed AMI. Image Builder sets this as the output AMI's description in each target Region and account. If you don't specify a description, the AMI in the build Region uses the image recipe's description, if the recipe has one. Copies distributed to other Regions and accounts don't receive a default description.

    " }, "targetAccountIds":{ "shape":"AccountList", - "documentation":"

    The ID of an account to which you want to distribute an image.

    " + "documentation":"

    The Amazon Web Services account IDs to distribute the AMI to in this Region. Each listed account receives its own copy of the output AMI. If you don't specify accounts, Image Builder distributes the AMI only to your own account.

    " }, "amiTags":{ "shape":"TagMap", @@ -1651,7 +1660,7 @@ "documentation":"

    The number of consecutive scheduled image pipeline executions that must fail before Image Builder automatically disables the pipeline.

    " } }, - "documentation":"

    Defines the rules by which an image pipeline is automatically disabled when it fails.

    " + "documentation":"

    Defines the rules by which an image pipeline is automatically disabled when it fails. By default, if the schedule doesn't include an auto-disable policy, Image Builder disables the pipeline after 5 consecutive failed scheduled builds.

    " }, "Boolean":{"type":"boolean"}, "BuildType":{ @@ -1668,7 +1677,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, - "documentation":"

    You have exceeded the permitted request rate for the specific operation.

    ", + "documentation":"

    You have exceeded the permitted request rate for the Amazon EC2 APIs that Image Builder calls on your behalf. Retry with an increasing or variable delay between requests.

    ", "error":{"httpStatusCode":429}, "exception":true }, @@ -1685,7 +1694,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -1720,7 +1729,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -1730,7 +1739,7 @@ "members":{ "lifecycleExecutionId":{ "shape":"LifecycleExecutionId", - "documentation":"

    The unique identifier for the image lifecycle runtime instance that was canceled.

    " + "documentation":"

    The unique identifier of the lifecycle execution that the cancellation request applies to. The cancellation completes asynchronously.

    " } } }, @@ -1739,7 +1748,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, - "documentation":"

    These errors are usually caused by a client action, such as using an action or resource on behalf of a user that doesn't have permissions to use the action or resource, or specifying an invalid resource identifier.

    ", + "documentation":"

    A generic client error. This error usually indicates that the request failed a validation check, such as when a downstream service rejects a configured value.

    ", "error":{"httpStatusCode":400}, "exception":true }, @@ -1793,7 +1802,7 @@ }, "owner":{ "shape":"NonEmptyString", - "documentation":"

    The owner of the component.

    " + "documentation":"

    The owner of the component. The value is your account ID for components that you own, the sharing account's ID for shared components, or Amazon, ThirdParty, or AWSMarketplace.

    " }, "data":{ "shape":"ComponentData", @@ -1805,7 +1814,7 @@ }, "encrypted":{ "shape":"NullableBoolean", - "documentation":"

    The encryption status of the component.

    " + "documentation":"

    Indicates whether the component data is encrypted at rest. Image Builder encrypts all component data at rest, so this value is always true. This field is retained for backward compatibility.

    " }, "dateCreated":{ "shape":"DateTime", @@ -1832,7 +1841,7 @@ }, "ComponentBuildVersionArn":{ "type":"string", - "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):component/[a-z0-9-_]+/[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+$" + "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?|third-party):component/[a-z0-9-_]+/[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+$" }, "ComponentConfiguration":{ "type":"structure", @@ -1840,14 +1849,14 @@ "members":{ "componentArn":{ "shape":"ComponentVersionArnOrBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the component.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the component. You can specify a build version ARN, or a component version ARN whose version segments can use x wildcards, for example 1.x.x.

    " }, "parameters":{ "shape":"ComponentParameterList", - "documentation":"

    A group of parameter settings that Image Builder uses to configure the component for a specific recipe.

    " + "documentation":"

    A group of parameter settings that Image Builder uses to configure the component for a specific recipe. You must supply a value for every component parameter that has no default value, and you can only supply parameters that the component defines.

    " } }, - "documentation":"

    Configuration details of the component.

    " + "documentation":"

    Configuration details of the component. You can specify each component only once in a recipe, regardless of version. Components with a status of DEPRECATED or DISABLED can't be added to new recipes.

    " }, "ComponentConfigurationList":{ "type":"list", @@ -1855,6 +1864,32 @@ "min":1 }, "ComponentData":{"type":"string"}, + "ComponentFailureContext":{ + "type":"structure", + "members":{ + "componentArn":{ + "shape":"ComponentBuildVersionArn", + "documentation":"

    The Amazon Resource Name (ARN) of the component build version that failed.

    " + }, + "phaseName":{ + "shape":"NonEmptyString", + "documentation":"

    The name of the phase in the component document where the failure occurred, such as build, validate, or test.

    " + }, + "stepName":{ + "shape":"NonEmptyString", + "documentation":"

    The name of the step in the component document that failed.

    " + }, + "action":{ + "shape":"NonEmptyString", + "documentation":"

    The action that the failed step runs, for example ExecuteBash.

    " + }, + "errorMessage":{ + "shape":"NonEmptyMaxLengthString", + "documentation":"

    The error message from the step that failed. Image Builder truncates messages that are longer than 1024 characters. The component log in Amazon CloudWatch Logs contains the full output.

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

    Contains details about the component that caused the image creation process to fail. The details identify the first step that failed when the component ran.

    " + }, "ComponentFormat":{ "type":"string", "enum":["SHELL"] @@ -1944,7 +1979,7 @@ "members":{ "status":{ "shape":"ComponentStatus", - "documentation":"

    The current state of the component.

    " + "documentation":"

    The current state of the component. Components with a status of DEPRECATED or DISABLED can't be added to new recipes.

    " }, "reason":{ "shape":"NonEmptyString", @@ -1994,7 +2029,7 @@ }, "owner":{ "shape":"NonEmptyString", - "documentation":"

    The owner of the component.

    " + "documentation":"

    The owner of the component. The value is your account ID for components that you own, the sharing account's ID for shared components, or Amazon, ThirdParty, or AWSMarketplace.

    " }, "description":{ "shape":"NonEmptyString", @@ -2002,11 +2037,11 @@ }, "changeDescription":{ "shape":"NonEmptyString", - "documentation":"

    The change description for the current version of the component.

    " + "documentation":"

    The change description for this version of the component.

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

    The original creation date of the component.

    " + "documentation":"

    The date that Image Builder created this version of the component.

    " }, "tags":{ "shape":"TagMap", @@ -2047,7 +2082,7 @@ }, "version":{ "shape":"VersionNumber", - "documentation":"

    The semantic version of the component.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    The semantic version of the component.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "description":{ "shape":"NonEmptyString", @@ -2059,7 +2094,7 @@ }, "supportedOsVersions":{ "shape":"OsVersionList", - "documentation":"

    he operating system (OS) version supported by the component. If the OS information is available, a prefix match is performed against the base image OS version during image recipe creation.

    " + "documentation":"

    The operating system (OS) version supported by the component. If OS information is available, Image Builder performs a prefix match against the base image OS version during image recipe creation.

    " }, "type":{ "shape":"ComponentType", @@ -2067,7 +2102,7 @@ }, "owner":{ "shape":"NonEmptyString", - "documentation":"

    The owner of the component.

    " + "documentation":"

    The owner of the component. The value is your account ID for components that you own, the sharing account's ID for shared components, or Amazon, ThirdParty, or AWSMarketplace.

    " }, "dateCreated":{ "shape":"DateTime", @@ -2082,15 +2117,15 @@ "documentation":"

    Contains product codes that are used for billing purposes for Amazon Web Services Marketplace components.

    " } }, - "documentation":"

    The defining characteristics of a specific version of an Amazon Web Services TOE component.

    " + "documentation":"

    The defining characteristics of a specific version of a component.

    " }, "ComponentVersionArn":{ "type":"string", - "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):component/[a-z0-9-_]+/[0-9]+\\.[0-9]+\\.[0-9]+$" + "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?|third-party):component/[a-z0-9-_]+/[0-9]+\\.[0-9]+\\.[0-9]+$" }, "ComponentVersionArnOrBuildVersionArn":{ "type":"string", - "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):component/[a-z0-9-_]+/(?:(?:([0-9]+|x)\\.([0-9]+|x)\\.([0-9]+|x))|(?:[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+))$" + "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?|third-party):component/[a-z0-9-_]+/(?:(?:([0-9]+|x)\\.([0-9]+|x)\\.([0-9]+|x))|(?:[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+))$" }, "ComponentVersionList":{ "type":"list", @@ -2112,7 +2147,7 @@ "documentation":"

    A list of URIs for containers created in the context Region.

    " } }, - "documentation":"

    A container encapsulates the runtime environment for an application.

    " + "documentation":"

    Details of the container images that are output resources of an image build in a given Amazon Web Services Region: the Region, and the URIs of the container images.

    " }, "ContainerDistributionConfiguration":{ "type":"structure", @@ -2124,14 +2159,14 @@ }, "containerTags":{ "shape":"StringList", - "documentation":"

    Tags that are attached to the container distribution configuration.

    " + "documentation":"

    Tags that Image Builder applies to the distributed container image in the target repository. These are repository image tags, not resource tags.

    " }, "targetRepository":{ "shape":"TargetContainerRepository", "documentation":"

    The destination repository for the container distribution configuration.

    " } }, - "documentation":"

    Container distribution settings for encryption, licensing, and sharing in a specific Region.

    " + "documentation":"

    Defines how the output container image is distributed in a specific Amazon Web Services Region: the target repository, the image tags to apply to the distributed image, and an optional description.

    " }, "ContainerList":{ "type":"list", @@ -2158,7 +2193,7 @@ }, "platform":{ "shape":"Platform", - "documentation":"

    The system platform for the container, such as Windows or Linux.

    " + "documentation":"

    The system platform for the container. Container recipes support only the Linux and Windows platforms.

    " }, "owner":{ "shape":"NonEmptyString", @@ -2166,11 +2201,11 @@ }, "version":{ "shape":"VersionNumber", - "documentation":"

    The semantic version of the container recipe.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    The semantic version of the container recipe.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "components":{ "shape":"ComponentConfigurationList", - "documentation":"

    Build and test components that are included in the container recipe. Recipes require a minimum of one build component, and can have a maximum of 20 build and test components in any combination.

    " + "documentation":"

    Build and test components that are included in the container recipe. A recipe can contain a maximum of 20 build and test components in any combination, by default. This maximum is an adjustable quota. For more information, see EC2 Image Builder endpoints and quotas in the Amazon Web Services General Reference.

    " }, "instanceConfiguration":{ "shape":"InstanceConfiguration", @@ -2178,15 +2213,15 @@ }, "dockerfileTemplateData":{ "shape":"DockerFileTemplate", - "documentation":"

    Dockerfiles are text documents that are used to build Docker containers, and ensure that they contain all of the elements required by the application running inside. The template data consists of contextual variables where Image Builder places build information or scripts, based on your container image recipe.

    " + "documentation":"

    The Dockerfile template that Image Builder uses to build the container image. The template can include contextual variables that Image Builder replaces with build information at build time. For the contextual variables that the template can include, see Create a new version of a container recipe in the EC2 Image Builder User Guide.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies which KMS key is used to encrypt the container image for distribution to the target Region. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide.

    " + "documentation":"

    The KMS key that Image Builder uses to encrypt the recipe's Dockerfile template data at rest. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide. If you don't specify a key, Image Builder encrypts the template data with a KMS key that Image Builder owns. This key isn't used to encrypt the output container image.

    " }, "encrypted":{ "shape":"NullableBoolean", - "documentation":"

    A flag that indicates if the target container is encrypted.

    " + "documentation":"

    Specifies whether the recipe's Dockerfile template data is encrypted at rest. Image Builder encrypts all Dockerfile template data at rest, so this value is always true. This field is retained for backward compatibility, and doesn't describe encryption of the output container image.

    " }, "parentImage":{ "shape":"NonEmptyString", @@ -2209,7 +2244,7 @@ "documentation":"

    The destination repository for the container image.

    " } }, - "documentation":"

    A container recipe.

    " + "documentation":"

    Defines how Image Builder builds and tests a container image: the base image, components to apply, the Dockerfile template, the build and test instance configuration, and the target repository for the output image.

    " }, "ContainerRecipeArn":{ "type":"string", @@ -2232,7 +2267,7 @@ }, "platform":{ "shape":"Platform", - "documentation":"

    The system platform for the container, such as Windows or Linux.

    " + "documentation":"

    The system platform for the container. Container recipes support only the Linux and Windows platforms.

    " }, "owner":{ "shape":"NonEmptyString", @@ -2255,7 +2290,7 @@ "documentation":"

    Tags that are attached to the container recipe.

    " } }, - "documentation":"

    A summary of a container recipe

    " + "documentation":"

    A summary of a container recipe.

    " }, "ContainerRecipeSummaryList":{ "type":"list", @@ -2280,11 +2315,11 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the component.

    " + "documentation":"

    The name of the component. Image Builder generates the component ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. If a component with the same name and semantic version already exists in your account in the same Amazon Web Services Region, the request creates a new build version for it. If the content is also identical to the latest build version, the request fails because the component already exists.

    " }, "semanticVersion":{ "shape":"VersionNumber", - "documentation":"

    The semantic version of the component. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " + "documentation":"

    The semantic version of the component. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "description":{ "shape":"NonEmptyString", @@ -2308,11 +2343,11 @@ }, "uri":{ "shape":"Uri", - "documentation":"

    The uri of a YAML component document file. This must be an S3 URL (s3://bucket/key), and the requester must have permission to access the S3 bucket it points to. If you use Amazon S3, you can specify component content up to your service quota.

    Alternatively, you can specify the YAML document inline, using the component data property. You cannot specify both properties.

    " + "documentation":"

    The uri of a YAML component document file. This must be an S3 URL (s3://bucket/key), and you must have permission to access the S3 bucket it points to. If you use Amazon S3, you can specify component content up to your service quota for component size, which is 64 KB by default.

    Alternatively, you can specify the YAML document inline, using the component data property. You cannot specify both properties.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the KMS key used to encrypt this component. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide.

    " + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the KMS key used to encrypt this component. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide. If you don't specify a key, Image Builder encrypts the component data with a KMS key that Image Builder owns.

    " }, "tags":{ "shape":"TagMap", @@ -2320,12 +2355,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "dryRun":{ "shape":"Boolean", - "documentation":"

    Validates the required permissions for the operation and the request parameters, without actually making the request, and provides an error response. Upon a successful request, the error response is DryRunOperationException.

    " + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2346,7 +2381,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -2367,7 +2402,7 @@ }, "name":{ "shape":"ResourceName", - "documentation":"

    The name of the container recipe.

    " + "documentation":"

    The name of the container recipe. The recipe name, combined with the semantic version, must be unique to your account in each Amazon Web Services Region. Image Builder generates the container recipe ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name.

    " }, "description":{ "shape":"NonEmptyString", @@ -2375,11 +2410,11 @@ }, "semanticVersion":{ "shape":"WildcardVersionNumber", - "documentation":"

    The semantic version of the container recipe. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " + "documentation":"

    The semantic version of the container recipe. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "components":{ "shape":"ComponentConfigurationList", - "documentation":"

    The components included in the container recipe.

    " + "documentation":"

    The components included in the container recipe. You can specify each component only one time in a recipe.

    " }, "instanceConfiguration":{ "shape":"InstanceConfiguration", @@ -2387,23 +2422,23 @@ }, "dockerfileTemplateData":{ "shape":"InlineDockerFileTemplate", - "documentation":"

    The Dockerfile template used to build your image as an inline data blob.

    " + "documentation":"

    The Dockerfile template used to build your image, as an inline data blob. You must specify exactly one of the dockerfileTemplateData or dockerfileTemplateUri properties. For the contextual variables that the template can include, see Create a new version of a container recipe in the EC2 Image Builder User Guide.

    " }, "dockerfileTemplateUri":{ "shape":"Uri", - "documentation":"

    The Amazon S3 URI for the Dockerfile that will be used to build your container image.

    " + "documentation":"

    The Amazon S3 URI for the Dockerfile template that is used to build your container image. You must have permission to read the object. Image Builder reads the object once, when it creates the recipe, and stores its content in the recipe. Later changes to the S3 object don't affect the recipe. You must specify exactly one of the dockerfileTemplateData or dockerfileTemplateUri properties.

    " }, "platformOverride":{ "shape":"Platform", - "documentation":"

    Specifies the operating system platform when you use a custom base image.

    " + "documentation":"

    Specifies the operating system platform when you use a custom base image. Container recipes support only the Linux and Windows platforms.

    " }, "imageOsVersionOverride":{ "shape":"NonEmptyString", - "documentation":"

    Specifies the operating system version for the base image.

    " + "documentation":"

    Specifies the operating system version for the base image. Use this property only when the base image is a container image from a registry. When the base image is an Image Builder image, the operating system version comes from the parent image.

    " }, "parentImage":{ "shape":"NonEmptyString", - "documentation":"

    The base image for the container recipe.

    " + "documentation":"

    The base image for the container recipe. This can be an Image Builder image resource ARN or a container image URI from a registry, for example amazonlinux:latest.

    " }, "tags":{ "shape":"TagMap", @@ -2415,7 +2450,7 @@ }, "targetRepository":{ "shape":"TargetContainerRepository", - "documentation":"

    The destination repository for the container image.

    " + "documentation":"

    The destination repository for the container image. The Amazon ECR repository must already exist in the Amazon Web Services Region where the build runs.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", @@ -2423,8 +2458,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2445,7 +2484,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -2459,7 +2498,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the distribution configuration.

    " + "documentation":"

    The name of the distribution configuration. Distribution configuration names must be unique to your account in each Amazon Web Services Region. Image Builder generates the distribution configuration ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name.

    " }, "description":{ "shape":"NonEmptyString", @@ -2467,7 +2506,7 @@ }, "distributions":{ "shape":"DistributionList", - "documentation":"

    The distributions of the distribution configuration.

    " + "documentation":"

    The distribution settings for the configuration. Each entry defines how output images are distributed in one target Amazon Web Services Region. A Region can appear at most once in the list.

    " }, "tags":{ "shape":"TagMap", @@ -2475,8 +2514,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2507,7 +2550,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the image pipeline.

    " + "documentation":"

    The name of the image pipeline. Pipeline names must be unique to your account in each Amazon Web Services Region. Image Builder generates the pipeline ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name.

    " }, "description":{ "shape":"NonEmptyString", @@ -2515,35 +2558,35 @@ }, "imageRecipeArn":{ "shape":"ImageRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that will be used to configure images created by this image pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that configures images created by this image pipeline. You must specify either this property or containerRecipeArn, but not both.

    " }, "containerRecipeArn":{ "shape":"ContainerRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container recipe that is used to configure images created by this container pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container recipe that is used to configure images created by this container pipeline. You must specify either this property or imageRecipeArn, but not both.

    " }, "infrastructureConfigurationArn":{ "shape":"InfrastructureConfigurationArn", - "documentation":"

    The Amazon Resource Name (ARN) of the infrastructure configuration that will be used to build images created by this image pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the infrastructure configuration that builds images created by this image pipeline.

    " }, "distributionConfigurationArn":{ "shape":"DistributionConfigurationArn", - "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that will be used to configure and distribute images created by this image pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that configures and distributes images created by this image pipeline.

    " }, "imageTestsConfiguration":{ "shape":"ImageTestsConfiguration", - "documentation":"

    The image test configuration of the image pipeline.

    " + "documentation":"

    Specifies the test settings that Image Builder applies to images that this pipeline creates. If you don't provide test settings, Image Builder stores a default configuration with image tests enabled.

    " }, "enhancedImageMetadataEnabled":{ "shape":"NullableBoolean", - "documentation":"

    Collects additional information about the image being created, including the operating system (OS) version and package list. This information is used to enhance the overall experience of using EC2 Image Builder. Enabled by default.

    " + "documentation":"

    Specifies whether to collect additional information about the image being created, including the operating system (OS) version and package list. Defaults to true.

    " }, "schedule":{ "shape":"Schedule", - "documentation":"

    The schedule of the image pipeline.

    " + "documentation":"

    The schedule of the image pipeline. If you don't provide a schedule, the pipeline runs only when you call StartImagePipelineExecution.

    " }, "status":{ "shape":"PipelineStatus", - "documentation":"

    The status of the image pipeline.

    " + "documentation":"

    The status of the image pipeline. If you don't specify a status, it defaults to ENABLED. A disabled pipeline doesn't run on its schedule, but you can still start builds manually.

    " }, "tags":{ "shape":"TagMap", @@ -2551,20 +2594,20 @@ }, "imageTags":{ "shape":"TagMap", - "documentation":"

    The tags to be applied to the images produced by this pipeline.

    " + "documentation":"

    The tags that Image Builder applies to the Image Builder image resource that this pipeline's scheduled executions create. These tags don't apply to the output AMI. To tag output AMIs, use amiTags in the pipeline's distribution configuration.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "imageScanningConfiguration":{ "shape":"ImageScanningConfiguration", - "documentation":"

    Contains settings for vulnerability scans.

    " + "documentation":"

    Contains settings for vulnerability scans that Amazon Inspector runs against the test instance during image creation.

    " }, "workflows":{ "shape":"WorkflowConfigurationList", - "documentation":"

    Contains an array of workflow configuration objects.

    " + "documentation":"

    The array of workflow configuration objects for builds that this pipeline starts. You must also specify executionRole when you provide workflows.

    " }, "executionRole":{ "shape":"RoleNameOrArn", @@ -2573,6 +2616,10 @@ "loggingConfiguration":{ "shape":"PipelineLoggingConfiguration", "documentation":"

    Specifies the logging configuration for the image pipeline. Use this to define custom CloudWatch Logs log groups for your pipeline execution logs and image build logs. The service manages log groups with names starting with /aws/imagebuilder/ using the service-linked role. For custom log group names outside of this prefix, you must also provide an executionRole.

    " + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2604,7 +2651,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the image recipe.

    " + "documentation":"

    The name of the image recipe. The recipe name, combined with the semantic version, must be unique to your account in each Amazon Web Services Region. Image Builder generates the image recipe ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name.

    " }, "description":{ "shape":"NonEmptyString", @@ -2612,19 +2659,19 @@ }, "semanticVersion":{ "shape":"WildcardVersionNumber", - "documentation":"

    The semantic version of the image recipe. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " + "documentation":"

    The semantic version of the image recipe. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "components":{ "shape":"ComponentConfigurationList", - "documentation":"

    The components included in the image recipe.

    " + "documentation":"

    The components included in the image recipe. Components are optional. A recipe with no components bakes the base image without additional customization. You can specify each component only one time in a recipe. Components with a status of DEPRECATED or DISABLED can't be added to new recipes.

    " }, "parentImage":{ "shape":"NonEmptyString", - "documentation":"

    The base image for customizations specified in the image recipe. You can specify the parent image using one of the following options:

    • AMI ID

    • Image Builder image Amazon Resource Name (ARN)

    • Amazon Web Services Systems Manager (SSM) Parameter Store Parameter, prefixed by ssm:, followed by the parameter name or ARN.

    • Amazon Web Services Marketplace product ID

    If you enter an AMI ID or an SSM parameter that contains the AMI ID, you must have access to the AMI, and the AMI must be in the source Region.

    " + "documentation":"

    The base image for customizations specified in the image recipe. You can specify the parent image using one of the following options:

    • AMI ID

    • Image Builder image Amazon Resource Name (ARN)

    • Amazon Web Services Systems Manager (SSM) Parameter Store Parameter, prefixed by ssm:, followed by the parameter name or ARN.

    • Amazon Web Services Marketplace product ID

    If you enter an AMI ID or an SSM parameter that contains the AMI ID, you must have access to the AMI. The AMI must also be in the Region where you're creating the recipe.

    " }, "blockDeviceMappings":{ "shape":"InstanceBlockDeviceMappings", - "documentation":"

    The block device mappings of the image recipe.

    " + "documentation":"

    The block device mappings that Image Builder applies to the build instance and the output AMI. For example, you can override the size of the base image's root volume or attach additional EBS volumes.

    " }, "tags":{ "shape":"TagMap", @@ -2632,11 +2679,11 @@ }, "workingDirectory":{ "shape":"NonEmptyString", - "documentation":"

    The working directory used during build and test workflows.

    " + "documentation":"

    The working directory used during build and test workflows. If you don't specify a working directory, Image Builder uses /tmp for Linux and macOS build instances, and C:/ for Windows build instances.

    " }, "additionalInstanceConfiguration":{ "shape":"AdditionalInstanceConfiguration", - "documentation":"

    Specify additional settings and launch scripts for your build instances.

    " + "documentation":"

    The additional settings and launch scripts for your build instances.

    " }, "amiTags":{ "shape":"TagMap", @@ -2648,8 +2695,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2670,7 +2721,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -2683,15 +2734,15 @@ "members":{ "imageRecipeArn":{ "shape":"ImageRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that defines how images are configured, tested, and assessed.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that defines how images are configured, tested, and assessed. You must specify either this property or containerRecipeArn, but not both.

    " }, "containerRecipeArn":{ "shape":"ContainerRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container recipe that defines how images are configured and tested.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container recipe that defines how images are configured and tested. You must specify either this property or imageRecipeArn, but not both.

    " }, "distributionConfigurationArn":{ "shape":"DistributionConfigurationArn", - "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that defines and configures the outputs of your pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that defines and configures the outputs of the image build. If you don't specify a distribution configuration, Image Builder creates the output image only in the account and Amazon Web Services Region where the build runs.

    " }, "infrastructureConfigurationArn":{ "shape":"InfrastructureConfigurationArn", @@ -2699,11 +2750,11 @@ }, "imageTestsConfiguration":{ "shape":"ImageTestsConfiguration", - "documentation":"

    The image tests configuration of the image.

    " + "documentation":"

    Settings that determine whether Image Builder runs tests on the image after building it. Image tests are enabled by default.

    " }, "enhancedImageMetadataEnabled":{ "shape":"NullableBoolean", - "documentation":"

    Collects additional information about the image being created, including the operating system (OS) version and package list. This information is used to enhance the overall experience of using EC2 Image Builder. Enabled by default.

    " + "documentation":"

    Specifies whether to collect additional information about the image being created, including the operating system (OS) version and package list. Defaults to true.

    " }, "tags":{ "shape":"TagMap", @@ -2711,24 +2762,24 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "imageScanningConfiguration":{ "shape":"ImageScanningConfiguration", - "documentation":"

    Contains settings for vulnerability scans.

    " + "documentation":"

    Settings for vulnerability scans that Amazon Inspector runs during image creation. For AMI output, Amazon Inspector scans the test instance. For container output, Amazon Inspector scans the container image that Image Builder pushes to the Amazon ECR repository specified in ecrConfiguration.

    " }, "workflows":{ "shape":"WorkflowConfigurationList", - "documentation":"

    Contains an array of workflow configuration objects.

    " + "documentation":"

    The array of workflow configuration objects for the build. If you specify workflows, they replace the default workflows that Image Builder otherwise runs for the build, and you must also provide an executionRole.

    " }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions. This property is required if you specify workflows. If you don't provide a role, Image Builder uses the Image Builder service-linked role in your account, and creates it if it doesn't exist.

    " }, "loggingConfiguration":{ "shape":"ImageLoggingConfiguration", - "documentation":"

    Define logging configuration for the image build process.

    " + "documentation":"

    The CloudWatch Logs log group where Image Builder sends the image build logs. If you specify a log group name outside of the /aws/imagebuilder/ namespace, you must also provide an executionRole that has permission to write to that log group.

    " } } }, @@ -2749,7 +2800,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -2763,7 +2814,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the infrastructure configuration.

    " + "documentation":"

    The name of the infrastructure configuration. Infrastructure configuration names must be unique to your account in each Amazon Web Services Region. Image Builder generates the infrastructure configuration ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name.

    " }, "description":{ "shape":"NonEmptyString", @@ -2771,11 +2822,11 @@ }, "instanceTypes":{ "shape":"InstanceTypeList", - "documentation":"

    The instance types of the infrastructure configuration. You can specify one or more instance types to use for this build. The service will pick one of these instance types based on availability.

    " + "documentation":"

    The instance types of the infrastructure configuration. You can specify one or more instance types to use for this build. Image Builder picks one of these instance types based on availability. If you don't specify instance types, Image Builder selects compatible instance types automatically. If you specify a Dedicated Host, Image Builder uses only instance types that the host supports.

    " }, "instanceProfileName":{ "shape":"InstanceProfileNameType", - "documentation":"

    The instance profile to associate with the instance used to customize your Amazon EC2 AMI.

    " + "documentation":"

    The instance profile to associate with the instance used to customize your Amazon EC2 AMI. The instance profile must exist in your account.

    " }, "securityGroupIds":{ "shape":"SecurityGroupIds", @@ -2783,11 +2834,11 @@ }, "subnetId":{ "shape":"NonEmptyString", - "documentation":"

    The subnet ID in which to place the instance used to customize your Amazon EC2 AMI.

    " + "documentation":"

    The subnet ID in which to place the instance used to customize your Amazon EC2 AMI. If you specify subnetId, you must also specify one or more security group IDs in securityGroupIds. Otherwise, the request fails.

    " }, "logging":{ "shape":"Logging", - "documentation":"

    The logging configuration of the infrastructure configuration.

    " + "documentation":"

    The logging configuration of the infrastructure configuration. When you configure S3 logs, Image Builder writes logs from the build and test process to the specified bucket under the key prefix.

    " }, "keyPair":{ "shape":"NonEmptyString", @@ -2795,19 +2846,19 @@ }, "terminateInstanceOnFailure":{ "shape":"NullableBoolean", - "documentation":"

    The terminate instance on failure setting of the infrastructure configuration. Set to false if you want Image Builder to retain the instance used to configure your AMI if the build or test phase of your workflow fails.

    " + "documentation":"

    Specifies whether to terminate the instance on failure. Set to false if you want Image Builder to retain the instance used to configure your AMI if the build or test phase of your workflow fails. Defaults to true.

    " }, "snsTopicArn":{ "shape":"SnsTopicArn", - "documentation":"

    The Amazon Resource Name (ARN) for the SNS topic to which we send image build event notifications.

    EC2 Image Builder is unable to send notifications to SNS topics that are encrypted using keys from other accounts. The key that is used to encrypt the SNS topic must reside in the account that the Image Builder service runs under.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the SNS topic to which Image Builder sends image build event notifications. Specify a standard topic. Image Builder doesn't support FIFO topics. Image Builder validates the topic when you create or update the configuration. You must have permission to publish to the topic.

    EC2 Image Builder can't send notifications to SNS topics that are encrypted using keys from other accounts. If your SNS topic is encrypted, the key must be owned by the same account that owns your Image Builder resources.

    " }, "resourceTags":{ "shape":"ResourceTagMap", - "documentation":"

    The metadata tags to assign to the Amazon EC2 instance that Image Builder launches during the build process. Tags are formatted as key value pairs.

    " + "documentation":"

    The metadata tags to assign to the Amazon EC2 instance that Image Builder launches during the build process. Tags are formatted as key value pairs. Tag keys can't begin with aws: or match one of the following reserved keys: CreatedBy, Ec2ImageBuilderArn, Name, or Tags.

    " }, "instanceMetadataOptions":{ "shape":"InstanceMetadataOptions", - "documentation":"

    The instance metadata options that you can set for the HTTP requests that pipeline builds use to launch EC2 build and test instances.

    " + "documentation":"

    The instance metadata service (IMDS) settings that Image Builder applies to the EC2 build and test instances it launches during image creation. If you don't set these options, the EC2 launch defaults for the instance apply. For more information about instance metadata options, see one of the following links:

    " }, "tags":{ "shape":"TagMap", @@ -2815,12 +2866,16 @@ }, "placement":{ "shape":"Placement", - "documentation":"

    The instance placement settings that define where the instances that are launched from your image will run.

    " + "documentation":"

    The instance placement settings that define where the build and test instances that Image Builder launches during image creation run. These settings don't affect instances that you launch from the output image.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2854,7 +2909,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the lifecycle policy to create.

    " + "documentation":"

    The name of the lifecycle policy to create. Policy names must be unique to your account in each Amazon Web Services Region. Image Builder generates the policy ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. You can't change the name after creation.

    " }, "description":{ "shape":"NonEmptyString", @@ -2862,23 +2917,23 @@ }, "status":{ "shape":"LifecyclePolicyStatus", - "documentation":"

    Indicates whether the lifecycle policy resource is enabled.

    " + "documentation":"

    Indicates whether the lifecycle policy resource is enabled. If you don't specify a status, it defaults to ENABLED. Only enabled policies run on their schedule.

    " }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to run lifecycle actions.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to run lifecycle actions. You must have permission to pass the role, and the role's trust policy must allow the Image Builder service principal to assume it.

    " }, "resourceType":{ "shape":"LifecyclePolicyResourceType", - "documentation":"

    The type of Image Builder resource that the lifecycle policy applies to.

    " + "documentation":"

    The type of Image Builder resource that the lifecycle policy applies to. The resource type determines the allowed rule actions: policies for AMI-based Image Builder images support DELETE, DEPRECATE, and DISABLE, and policies for container-based Image Builder images support only DELETE. You can't change the resource type after creation.

    " }, "policyDetails":{ "shape":"LifecyclePolicyDetails", - "documentation":"

    Configuration details for the lifecycle policy rules.

    " + "documentation":"

    Configuration details for the lifecycle policy rules. A policy can contain at most one rule per action type: one DELETE, one DEPRECATE, and one DISABLE.

    " }, "resourceSelection":{ "shape":"LifecyclePolicyResourceSelection", - "documentation":"

    Selection criteria for the resources that the lifecycle policy applies to.

    " + "documentation":"

    Selection criteria for the resources that the lifecycle policy applies to. You must specify exactly one selection criteria: either recipes or a tag map, not both.

    " }, "tags":{ "shape":"TagMap", @@ -2886,8 +2941,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true + }, + "dryRun":{ + "shape":"Boolean", + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2915,11 +2974,11 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the workflow to create.

    " + "documentation":"

    The name of the workflow to create. Image Builder generates the workflow ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. If a workflow with the same name and semantic version already exists in your account in the same Amazon Web Services Region, the request creates a new build version for it. If the content is also identical to the latest build version, the request fails because the workflow already exists.

    " }, "semanticVersion":{ "shape":"VersionNumber", - "documentation":"

    The semantic version of this workflow resource. The semantic version syntax adheres to the following rules.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " + "documentation":"

    The semantic version of this workflow resource. The semantic version syntax adheres to the following rules.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "description":{ "shape":"NonEmptyString", @@ -2931,15 +2990,15 @@ }, "data":{ "shape":"InlineWorkflowData", - "documentation":"

    Contains the UTF-8 encoded YAML document content for the workflow. Alternatively, you can specify the uri of a YAML document file stored in Amazon S3. However, you cannot specify both properties.

    " + "documentation":"

    The UTF-8 encoded YAML document content for the workflow, up to 16,000 characters. For larger documents, store the document in Amazon S3 and specify the uri property instead. You must specify exactly one of the data or uri properties.

    " }, "uri":{ "shape":"Uri", - "documentation":"

    The uri of a YAML component document file. This must be an S3 URL (s3://bucket/key), and the requester must have permission to access the S3 bucket it points to. If you use Amazon S3, you can specify component content up to your service quota.

    Alternatively, you can specify the YAML document inline, using the component data property. You cannot specify both properties.

    " + "documentation":"

    The uri of a YAML workflow document file stored in Amazon S3. This must be an S3 URL (s3://bucket/key), and you must have permission to access the S3 bucket it points to. A workflow document that you provide from Amazon S3 can be up to your service quota for workflow size.

    Alternatively, you can specify the YAML document inline, using the workflow data property. You must specify exactly one of the data or uri properties.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the KMS key used to encrypt this workflow resource. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide.

    " + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the KMS key used to encrypt this workflow resource. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide. If you don't specify a key, Image Builder encrypts the workflow document with a KMS key that Image Builder owns.

    " }, "tags":{ "shape":"TagMap", @@ -2947,16 +3006,16 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "type":{ "shape":"WorkflowType", - "documentation":"

    The phase in the image build process for which the workflow resource is responsible.

    " + "documentation":"

    The image creation stage that this workflow applies to. Image Builder validates the workflow document steps against the stage you specify.

    " }, "dryRun":{ "shape":"Boolean", - "documentation":"

    Validates the required permissions for the operation and the request parameters, without actually making the request, and provides an error response. Upon a successful request, the error response is DryRunOperationException.

    " + "documentation":"

    Validates the required permissions and request parameters without performing the operation. If validation succeeds, the operation returns a DryRunOperationException error response.

    " } } }, @@ -2973,7 +3032,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -2997,7 +3056,7 @@ "documentation":"

    The source of the CVSS score.

    " } }, - "documentation":"

    Amazon Inspector generates a risk score for each finding. This score helps you to prioritize findings, to focus on the most critical findings and the most vulnerable resources. The score uses the Common Vulnerability Scoring System (CVSS) format. This format is a modification of the base CVSS score that the National Vulnerability Database (NVD) provides. For more information about severity levels, see Severity levels for Amazon Inspector findings in the Amazon Inspector User Guide.

    " + "documentation":"

    A CVSS score for the vulnerability, as published by the vulnerability source. Sources include the National Vulnerability Database (NVD) and the operating system vendor's security feed. A finding can include CVSS scores from multiple sources and CVSS versions.

    " }, "CvssScoreAdjustment":{ "type":"structure", @@ -3026,7 +3085,7 @@ }, "cvssSource":{ "shape":"NonEmptyString", - "documentation":"

    The source of the finding.

    " + "documentation":"

    The source of the CVSS data that the Amazon Inspector score for the finding is based on, for example NVD or a vendor security feed.

    " }, "version":{ "shape":"NonEmptyString", @@ -3042,7 +3101,7 @@ }, "adjustments":{ "shape":"CvssScoreAdjustmentList", - "documentation":"

    An object that contains details about an adjustment that Amazon Inspector made to the CVSS score for the finding.

    " + "documentation":"

    The adjustments that Amazon Inspector applied to the base CVSS score to produce its own score for the finding. The list is empty when Amazon Inspector made no adjustments.

    " } }, "documentation":"

    Details about the source of the score, and the factors that determined the adjustments to create the final score.

    " @@ -3289,7 +3348,7 @@ "members":{ "sourceImage":{ "shape":"NonEmptyString", - "documentation":"

    The source image to distribute. Specify an AMI identifier, SSM parameter path, or Image Builder image Amazon Resource Name (ARN). When you specify an Image Builder image Amazon Resource Name (ARN), the image must be in the AVAILABLE state.

    " + "documentation":"

    The source image to distribute. You can specify the source in any of the following formats:

    • An AMI ID.

    • An Amazon Web Services Systems Manager Parameter Store reference, prefixed by ssm:, followed by the parameter name or ARN.

    • An Image Builder image Amazon Resource Name (ARN). An image version ARN resolves to the latest available build version.

    Whichever format you use, the source must resolve to an AMI in the current Amazon Web Services Region.

    " }, "distributionConfigurationArn":{ "shape":"DistributionConfigurationArn", @@ -3301,11 +3360,11 @@ }, "tags":{ "shape":"TagMap", - "documentation":"

    The tags to apply to the distributed image.

    " + "documentation":"

    The tags to apply to the new Image Builder image resource that this operation creates. To tag the output AMIs, use amiTags in the distribution configuration.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "loggingConfiguration":{ @@ -3323,7 +3382,7 @@ }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image to be distributed.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the new Image Builder image resource that this operation creates to track the distribution. Use this ARN with GetImage to monitor distribution progress.

    " } } }, @@ -3388,7 +3447,7 @@ }, "timeoutMinutes":{ "shape":"DistributionTimeoutMinutes", - "documentation":"

    The maximum duration in minutes for this distribution configuration.

    " + "documentation":"

    A property that Image Builder doesn't use. You can't set this property when you create or update a distribution configuration, and it has no effect on distribution behavior.

    " }, "dateCreated":{ "shape":"DateTime", @@ -3403,7 +3462,7 @@ "documentation":"

    The tags of the distribution configuration.

    " } }, - "documentation":"

    A distribution configuration.

    " + "documentation":"

    Defines how Image Builder distributes the output of an image build. You can configure:

    • The Regions to distribute the image to.

    • The Region-specific settings to apply, such as output AMI names, launch permissions for other Amazon Web Services accounts, and target container repositories.

    " }, "DistributionConfigurationArn":{ "type":"string", @@ -3438,7 +3497,7 @@ }, "regions":{ "shape":"RegionList", - "documentation":"

    A list of Regions where the container image is distributed to.

    " + "documentation":"

    A list of the Regions that the distribution configuration distributes images to.

    " } }, "documentation":"

    A high-level overview of a distribution configuration.

    " @@ -3447,6 +3506,20 @@ "type":"list", "member":{"shape":"DistributionConfigurationSummary"} }, + "DistributionFailureContext":{ + "type":"structure", + "members":{ + "errorMessage":{ + "shape":"NonEmptyMaxLengthString", + "documentation":"

    The error message for the distribution failure.

    " + }, + "regionFailures":{ + "shape":"RegionFailureList", + "documentation":"

    The details about the failure for each Region where the image didn't finish distribution or configuration.

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

    Contains details about a failure that occurred while Image Builder distributed the image or applied configuration to the distributed image.

    " + }, "DistributionList":{ "type":"list", "member":{"shape":"Distribution"} @@ -3471,15 +3544,15 @@ "members":{ "encrypted":{ "shape":"NullableBoolean", - "documentation":"

    Use to configure device encryption.

    " + "documentation":"

    Specifies whether to encrypt the device.

    " }, "deleteOnTermination":{ "shape":"NullableBoolean", - "documentation":"

    Use to configure delete on termination of the associated device.

    " + "documentation":"

    Specifies whether to delete the associated device on termination.

    " }, "iops":{ "shape":"EbsIopsInteger", - "documentation":"

    Use to configure device IOPS.

    " + "documentation":"

    The IOPS value for the device. Required only when volumeType is io1 or io2.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", @@ -3491,11 +3564,11 @@ }, "volumeSize":{ "shape":"EbsVolumeSizeInteger", - "documentation":"

    Use to override the device's volume size.

    " + "documentation":"

    Overrides the volume size for the device.

    " }, "volumeType":{ "shape":"EbsVolumeType", - "documentation":"

    Use to override the device's volume type.

    " + "documentation":"

    Overrides the volume type for the device.

    " }, "throughput":{ "shape":"EbsVolumeThroughput", @@ -3536,7 +3609,7 @@ "members":{ "repositoryName":{ "shape":"NonEmptyString", - "documentation":"

    The name of the container repository that Amazon Inspector scans to identify findings for your container images. The name includes the path for the repository location. If you don’t provide this information, Image Builder creates a repository in your account named image-builder-image-scanning-repository for vulnerability scans of your output container images.

    " + "documentation":"

    The name of the container repository where Image Builder pushes the container image for the vulnerability scan. Provide the repository name only (a namespace path is allowed, but not the registry hostname); the repository must already exist in your account. If you don't specify a repository name, Image Builder creates the default repository image-builder-image-scanning-repository in your account.

    " }, "containerTags":{ "shape":"StringList", @@ -3557,11 +3630,11 @@ "members":{ "enabled":{ "shape":"Boolean", - "documentation":"

    A Boolean that represents the current state of faster launching for the Windows AMI. Set to true to start using Windows faster launching, or false to stop using it.

    " + "documentation":"

    Specifies whether to enable Windows fast launch on the output AMI during distribution. A value of false means Image Builder takes no fast-launch action for this configuration.

    " }, "snapshotConfiguration":{ "shape":"FastLaunchSnapshotConfiguration", - "documentation":"

    Configuration settings for managing the number of snapshots that are created from pre-provisioned instances for the Windows AMI when faster launching is enabled.

    " + "documentation":"

    Configuration settings for managing the number of snapshots that are created from pre-provisioned instances for the Windows AMI when Windows fast launch is enabled.

    " }, "maxParallelLaunches":{ "shape":"MaxParallelLaunches", @@ -3576,7 +3649,7 @@ "documentation":"

    The owner account ID for the fast-launch enabled Windows AMI.

    " } }, - "documentation":"

    Define and configure faster launching for output Windows AMIs.

    " + "documentation":"

    Defines and configures EC2 Fast Launch for output Windows AMIs.

    " }, "FastLaunchConfigurationList":{ "type":"list", @@ -3589,18 +3662,18 @@ "members":{ "launchTemplateId":{ "shape":"LaunchTemplateId", - "documentation":"

    The ID of the launch template to use for faster launching for a Windows AMI.

    " + "documentation":"

    The ID of the launch template to use for Windows fast launch for a Windows AMI.

    " }, "launchTemplateName":{ "shape":"NonEmptyString", - "documentation":"

    The name of the launch template to use for faster launching for a Windows AMI.

    " + "documentation":"

    The name of the launch template to use for Windows fast launch for a Windows AMI.

    " }, "launchTemplateVersion":{ "shape":"NonEmptyString", - "documentation":"

    The version of the launch template to use for faster launching for a Windows AMI.

    " + "documentation":"

    The version of the launch template to use for Windows fast launch for a Windows AMI.

    " } }, - "documentation":"

    Identifies the launch template that the associated Windows AMI uses for launching an instance when faster launching is enabled.

    You can specify either the launchTemplateName or the launchTemplateId, but not both.

    " + "documentation":"

    Identifies the launch template that the associated Windows AMI uses for launching an instance when Windows fast launch is enabled.

    You can specify either the launchTemplateName or the launchTemplateId, but not both.

    " }, "FastLaunchSnapshotConfiguration":{ "type":"structure", @@ -3686,7 +3759,7 @@ "members":{ "componentBuildVersionArn":{ "shape":"ComponentVersionArnOrBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the component that you want to get. Regex requires the suffix /\\d+$.

    ", + "documentation":"

    The Amazon Resource Name (ARN) of the component that you want to get. You can specify a build version ARN, or a component version ARN. The version can use the x wildcard in trailing positions, for example 1.0.x or 1.x.x. Version ARNs resolve to the latest available matching component build version.

    ", "location":"querystring", "locationName":"componentBuildVersionArn" } @@ -3705,7 +3778,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -3730,7 +3803,7 @@ }, "policy":{ "shape":"ResourcePolicyDocument", - "documentation":"

    The container recipe policy object that is returned.

    " + "documentation":"

    The resource policy for the container recipe, as a JSON policy document. If no policy has been applied, the response contains an empty JSON object ({}).

    " } } }, @@ -3759,7 +3832,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -3834,7 +3907,7 @@ }, "policy":{ "shape":"ResourcePolicyDocument", - "documentation":"

    The image policy object.

    " + "documentation":"

    The resource policy for the image, as a JSON policy document. If the image has no policy applied, the response contains an empty JSON object ({}).

    " } } }, @@ -3859,7 +3932,7 @@ }, "policy":{ "shape":"ResourcePolicyDocument", - "documentation":"

    The image recipe policy object.

    " + "documentation":"

    The resource policy for the image recipe, as a JSON policy document. If no policy has been applied, the response contains an empty JSON object ({}).

    " } } }, @@ -3869,7 +3942,7 @@ "members":{ "imageRecipeArn":{ "shape":"ImageRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that you want to retrieve.

    ", + "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that you want to retrieve. You can use the x wildcard in trailing version positions to retrieve the latest matching version, for example x.x.x or 1.x.x.

    ", "location":"querystring", "locationName":"imageRecipeArn" } @@ -3888,7 +3961,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -3898,7 +3971,7 @@ "members":{ "imageBuildVersionArn":{ "shape":"ImageVersionArnOrBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image that you want to get.

    ", + "documentation":"

    The Amazon Resource Name (ARN) of the image that you want to get. You can specify a full build version ARN, or a version ARN with or without wildcards (x.x.x, 1.x.x, or 1.0.x). A version or wildcard ARN resolves to the latest matching build version that has reached AVAILABLE status. Builds that were later deprecated, disabled, or deleted don't resolve. To get an image in any other state, such as a failed or in-progress build, specify the full build version ARN.

    ", "location":"querystring", "locationName":"imageBuildVersionArn" } @@ -3917,7 +3990,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -3954,7 +4027,7 @@ "members":{ "lifecycleExecutionId":{ "shape":"LifecycleExecutionId", - "documentation":"

    Use the unique identifier for a runtime instance of the lifecycle policy to get runtime details.

    ", + "documentation":"

    The unique identifier for a runtime instance of the lifecycle policy.

    ", "location":"querystring", "locationName":"lifecycleExecutionId" } @@ -3986,7 +4059,7 @@ "members":{ "lifecyclePolicy":{ "shape":"LifecyclePolicy", - "documentation":"

    The Amazon Resource Name (ARN) of the image lifecycle policy resource that was returned.

    " + "documentation":"

    The details of the lifecycle policy that the request retrieved.

    " } } }, @@ -4007,7 +4080,7 @@ }, "resourceLocation":{ "shape":"MarketplaceResourceLocation", - "documentation":"

    The bucket path that you can specify to download the resource from Amazon S3.

    " + "documentation":"

    The Amazon S3 location of the component artifact to retrieve, in s3://bucket/key form.

    " } } }, @@ -4020,7 +4093,7 @@ }, "url":{ "shape":"NonEmptyString", - "documentation":"

    The obfuscated S3 URL to download the component artifact from.

    " + "documentation":"

    A time-limited presigned URL for downloading the component artifact from Amazon S3.

    " }, "data":{ "shape":"NonEmptyString", @@ -4057,7 +4130,7 @@ }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image resource build version that the specified runtime instance of the workflow created.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image build version that owns the specified runtime instance of the workflow.

    " }, "type":{ "shape":"WorkflowType", @@ -4065,7 +4138,7 @@ }, "status":{ "shape":"WorkflowExecutionStatus", - "documentation":"

    The current runtime status for the specified runtime instance of the workflow.

    " + "documentation":"

    The current runtime status for the specified runtime instance of the workflow. COMPLETED, FAILED, ROLLBACK_COMPLETED, CANCELLED, and SKIPPED are terminal states.

    " }, "message":{ "shape":"WorkflowExecutionMessage", @@ -4073,7 +4146,7 @@ }, "totalStepCount":{ "shape":"WorkflowStepCount", - "documentation":"

    The total number of steps in the specified runtime instance of the workflow that ran. This number should equal the sum of the step counts for steps that succeeded, were skipped, and failed.

    " + "documentation":"

    The total number of steps that the workflow document defines for this runtime instance of the workflow. Image Builder sets this count before any steps run. The sum of succeeded, skipped, and failed steps only reaches this total if every step finishes in one of those states.

    " }, "totalStepsSucceeded":{ "shape":"WorkflowStepCount", @@ -4097,7 +4170,7 @@ }, "parallelGroup":{ "shape":"ParallelGroup", - "documentation":"

    Test workflows are defined within named runtime groups. The parallel group is a named group that contains one or more test workflows.

    " + "documentation":"

    The name of the parallel group that this runtime instance of the workflow ran in, if configured. Parallel groups apply only to test workflows.

    " } } }, @@ -4107,7 +4180,7 @@ "members":{ "workflowBuildVersionArn":{ "shape":"WorkflowVersionArnOrBuildVersionArn", - "documentation":"

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

    ", + "documentation":"

    The Amazon Resource Name (ARN) of the workflow resource that you want to get. You can specify a build version ARN, or a version ARN with or without wildcards (x) in its version segments. Image Builder resolves version and wildcard ARNs to the most recent matching build version.

    ", "location":"querystring", "locationName":"workflowBuildVersionArn" } @@ -4122,7 +4195,7 @@ }, "latestVersionReferences":{ "shape":"LatestVersionReferences", - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " } } }, @@ -4132,7 +4205,7 @@ "members":{ "stepExecutionId":{ "shape":"WorkflowStepExecutionId", - "documentation":"

    Use the unique identifier for a specific runtime instance of the workflow step to get runtime details for that step.

    ", + "documentation":"

    The unique identifier for the runtime instance of the workflow step that you want to get runtime details for. To get the identifiers for the steps that ran in a workflow, call ListWorkflowStepExecutions.

    ", "location":"querystring", "locationName":"stepExecutionId" } @@ -4147,7 +4220,7 @@ }, "stepExecutionId":{ "shape":"WorkflowStepExecutionId", - "documentation":"

    The unique identifier for the runtime version of the workflow step that you specified in the request.

    " + "documentation":"

    The unique identifier for the runtime instance of the workflow step that you specified in the request.

    " }, "workflowBuildVersionArn":{ "shape":"WorkflowBuildVersionArn", @@ -4159,7 +4232,7 @@ }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image resource build version that the specified runtime instance of the workflow step creates.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image build version that owns the specified runtime instance of the workflow step.

    " }, "name":{ "shape":"WorkflowStepName", @@ -4175,11 +4248,11 @@ }, "status":{ "shape":"WorkflowStepExecutionStatus", - "documentation":"

    The current status for the specified runtime version of the workflow step.

    " + "documentation":"

    The current status for the specified runtime instance of the workflow step.

    " }, "rollbackStatus":{ "shape":"WorkflowStepExecutionRollbackStatus", - "documentation":"

    Reports on the rollback status of the specified runtime version of the workflow step, if applicable.

    " + "documentation":"

    Reports on the rollback status of the specified runtime instance of the workflow step, if applicable. Rollback runs when the workflow execution fails, and undoes the work that completed steps performed.

    " }, "message":{ "shape":"WorkflowStepMessage", @@ -4187,15 +4260,15 @@ }, "inputs":{ "shape":"WorkflowStepInputs", - "documentation":"

    Input parameters that Image Builder provided for the specified runtime instance of the workflow step.

    " + "documentation":"

    Input parameters that Image Builder provided for the specified runtime instance of the workflow step, as a JSON-encoded string.

    " }, "outputs":{ "shape":"WorkflowStepOutputs", - "documentation":"

    The file names that the specified runtime version of the workflow step created as output.

    " + "documentation":"

    The output values that the specified runtime instance of the workflow step produced, as a JSON-encoded string. For example, a step that launches an instance outputs the instance ID. If the step failed, this field contains the error message.

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

    The timestamp when the specified runtime version of the workflow step started.

    " + "documentation":"

    The timestamp when the specified runtime instance of the workflow step started.

    " }, "endTime":{ "shape":"DateTime", @@ -4203,11 +4276,19 @@ }, "onFailure":{ "shape":"NonEmptyString", - "documentation":"

    The action to perform if the workflow step fails.

    " + "documentation":"

    The action that the workflow takes if this step fails, as configured in the workflow document. Abort fails the workflow and rolls back completed steps. Continue proceeds to the next step. If the step doesn't set a value, it defaults to Abort.

    " }, "timeoutSeconds":{ "shape":"WorkflowStepTimeoutSecondsInteger", - "documentation":"

    The maximum duration in seconds for this step to complete its action.

    " + "documentation":"

    The maximum duration in seconds for this step to complete its action. If the workflow document doesn't set a timeout for the step, Image Builder applies the default timeout for the step's action. This field returns that value.

    " + }, + "attemptNumber":{ + "shape":"WorkflowStepAttemptCount", + "documentation":"

    The current attempt number for the specified runtime instance of the workflow step. The first run is attempt one. The number increases by one for each retry.

    " + }, + "maxAttempts":{ + "shape":"WorkflowStepAttemptCount", + "documentation":"

    The maximum number of attempts allowed for the specified runtime instance of the workflow step, based on the retry configuration in the workflow document. If the step doesn't configure retries, the maximum is one attempt.

    " } } }, @@ -4245,8 +4326,8 @@ "documentation":"

    The name of the image.

    " }, "version":{ - "shape":"VersionNumber", - "documentation":"

    The semantic version of the image.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "shape":"VersionNumberWithBuild", + "documentation":"

    The semantic version of the image.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "platform":{ "shape":"Platform", @@ -4274,11 +4355,11 @@ }, "sourcePipelineName":{ "shape":"ResourceName", - "documentation":"

    The name of the image pipeline that created this image.

    " + "documentation":"

    The name of the image pipeline that created this image. Image Builder doesn't return this field for new images. Use sourcePipelineArn instead.

    " }, "sourcePipelineArn":{ "shape":"Arn", - "documentation":"

    The Amazon Resource Name (ARN) of the image pipeline that created this image.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image pipeline that created this image. This field is only present for images that a pipeline execution created.

    " }, "infrastructureConfiguration":{ "shape":"InfrastructureConfiguration", @@ -4290,7 +4371,7 @@ }, "imageTestsConfiguration":{ "shape":"ImageTestsConfiguration", - "documentation":"

    The image tests that ran when that Image Builder created this image.

    " + "documentation":"

    The image test settings that Image Builder used when it created this image.

    " }, "dateCreated":{ "shape":"DateTime", @@ -4318,7 +4399,7 @@ }, "imageScanningConfiguration":{ "shape":"ImageScanningConfiguration", - "documentation":"

    Contains settings for vulnerability scans.

    " + "documentation":"

    Settings for the vulnerability scans that Amazon Inspector runs for this image. For AMI output, Amazon Inspector scans the test instance during image creation. For container output, Amazon Inspector scans the container image in its Amazon ECR repository.

    " }, "deprecationTime":{ "shape":"DateTimeTimestamp", @@ -4334,14 +4415,14 @@ }, "workflows":{ "shape":"WorkflowConfigurationList", - "documentation":"

    Contains the build and test workflows that are associated with the image.

    " + "documentation":"

    The build, test, and distribution workflow configurations that are associated with the image.

    " }, "loggingConfiguration":{ "shape":"ImageLoggingConfiguration", "documentation":"

    The logging configuration that's defined for the image. Image Builder uses the defined settings to direct execution log output during image creation.

    " } }, - "documentation":"

    An Image Builder image resource that keeps track of all of the settings used to create, configure, and distribute output for that image. You must specify exactly one recipe for the image – either a container recipe (containerRecipe), which creates a container image, or an image recipe (imageRecipe), which creates an AMI.

    " + "documentation":"

    An Image Builder image resource that keeps track of all of the settings used to create, configure, and distribute output for that image. An image that Image Builder built from a recipe contains exactly one recipe – either a container recipe (containerRecipe), which creates a container image, or an image recipe (imageRecipe), which creates an AMI. Imported images don't contain a recipe.

    " }, "ImageAggregation":{ "type":"structure", @@ -4368,7 +4449,51 @@ }, "ImageBuilderArn":{ "type":"string", - "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):(?:image-recipe|container-recipe|infrastructure-configuration|distribution-configuration|component|image|image-pipeline|lifecycle-policy|workflow\\/(?:build|test|distribution))/[a-z0-9-_]+(?:/(?:(?:x|[0-9]+)\\.(?:x|[0-9]+)\\.(?:x|[0-9]+))(?:/[0-9]+)?)?$" + "pattern":"^arn:aws[^:]*:imagebuilder:[^:]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?|third-party):(?:image-recipe|container-recipe|infrastructure-configuration|distribution-configuration|component|image|image-pipeline|lifecycle-policy|workflow\\/(?:build|test|distribution))/[a-z0-9-_]+(?:/(?:(?:x|[0-9]+)\\.(?:x|[0-9]+)\\.(?:x|[0-9]+))(?:/[0-9]+)?)?$" + }, + "ImageConfigurationStep":{ + "type":"string", + "enum":[ + "ASSOCIATE_LICENSES", + "UPDATE_LAUNCH_TEMPLATES", + "PUT_SSM_PARAMETERS", + "UPDATE_FAST_LAUNCH_CONFIGURATIONS", + "EXPORT_AMI" + ] + }, + "ImageFailureContext":{ + "type":"structure", + "members":{ + "imageStatus":{ + "shape":"ImageStatus", + "documentation":"

    The status that the image had when the failure occurred. This indicates the stage of the image creation process where the image failed, for example BUILDING or DISTRIBUTING.

    " + }, + "workflowExecutionId":{ + "shape":"WorkflowExecutionId", + "documentation":"

    The unique identifier of the workflow execution that was running when the image failed.

    " + }, + "workflowArn":{ + "shape":"WorkflowBuildVersionArn", + "documentation":"

    The Amazon Resource Name (ARN) of the workflow build version that was running when the image failed.

    " + }, + "stepExecutionId":{ + "shape":"WorkflowStepExecutionId", + "documentation":"

    The unique identifier of the workflow step execution that failed.

    " + }, + "failedStep":{ + "shape":"WorkflowStepName", + "documentation":"

    The name of the workflow step that failed, as it appears in the workflow document.

    " + }, + "componentFailure":{ + "shape":"ComponentFailureContext", + "documentation":"

    The details about the component that failed, if the failure occurred while a component was running.

    " + }, + "distributionFailure":{ + "shape":"DistributionFailureContext", + "documentation":"

    The details about the distribution failure, if the failure occurred while Image Builder distributed or configured the image.

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

    Contains details about the failure when the image creation process fails. Properties appear in the failure context when the related information is available for the failure.

    " }, "ImageLoggingConfiguration":{ "type":"structure", @@ -4392,7 +4517,7 @@ "documentation":"

    The version of the package that's reported to the operating system package manager.

    " } }, - "documentation":"

    A software package that's installed on top of the base image to create a customized image.

    " + "documentation":"

    A software package that's installed on an image, as detected by Amazon Web Services Systems Manager Inventory at build time. The list includes packages that shipped with the base image.

    " }, "ImagePackageList":{ "type":"list", @@ -4415,11 +4540,11 @@ }, "platform":{ "shape":"Platform", - "documentation":"

    The platform of the image pipeline.

    " + "documentation":"

    The platform of the image pipeline, inherited from the recipe that the pipeline uses.

    " }, "enhancedImageMetadataEnabled":{ "shape":"NullableBoolean", - "documentation":"

    Collects additional information about the image being created, including the operating system (OS) version and package list. This information is used to enhance the overall experience of using EC2 Image Builder. Enabled by default.

    " + "documentation":"

    Specifies whether to collect additional information about the image being created, including the operating system (OS) version and package list. Defaults to true.

    " }, "imageRecipeArn":{ "shape":"Arn", @@ -4447,7 +4572,7 @@ }, "status":{ "shape":"PipelineStatus", - "documentation":"

    The status of the image pipeline.

    " + "documentation":"

    The status of the image pipeline. A disabled pipeline doesn't run on its schedule, but you can still start builds manually. Image Builder can also disable a pipeline automatically when consecutive scheduled builds fail.

    " }, "dateCreated":{ "shape":"DateTime", @@ -4459,7 +4584,7 @@ }, "dateLastRun":{ "shape":"DateTime", - "documentation":"

    This is no longer supported, and does not return a value.

    " + "documentation":"

    The date on which this image pipeline was last run.

    " }, "lastRunStatus":{ "shape":"ImageStatus", @@ -4475,11 +4600,11 @@ }, "imageScanningConfiguration":{ "shape":"ImageScanningConfiguration", - "documentation":"

    Contains settings for vulnerability scans.

    " + "documentation":"

    Contains settings for vulnerability scans that Amazon Inspector runs against the test instance during image creation.

    " }, "imageTags":{ "shape":"TagMap", - "documentation":"

    The tags to be applied to the images produced by this pipeline.

    " + "documentation":"

    The tags that Image Builder applies to the Image Builder image resource that this pipeline's scheduled executions create. These tags don't apply to the output AMI. Builds that you start manually use the tags from the StartImagePipelineExecution request instead.

    " }, "executionRole":{ "shape":"RoleNameOrArn", @@ -4491,14 +4616,14 @@ }, "loggingConfiguration":{ "shape":"PipelineLoggingConfiguration", - "documentation":"

    Defines logging configuration for the output image.

    " + "documentation":"

    The CloudWatch Logs configuration for the pipeline: the log group for image build logs and the log group for pipeline execution logs.

    " }, "consecutiveFailures":{ "shape":"ConsecutiveFailures", - "documentation":"

    Image Builder tracks the number of consecutive failures for scheduled pipeline executions and takes one of the following actions each time it runs on a schedule:

    • If the pipeline execution is successful, the number of consecutive failures resets to zero.

    • If the pipeline execution fails, Image Builder increments the number of consecutive failures. If the failure count exceeds the limit defined in the AutoDisablePolicy, Image Builder disables the pipeline.

    The consecutive failure count is also reset to zero under the following conditions:

    • The pipeline runs manually and succeeds.

    • The pipeline configuration is updated.

    If the pipeline runs manually and fails, the count remains the same. The next scheduled run continues to increment where it left off before.

    " + "documentation":"

    Image Builder tracks the number of consecutive failures for scheduled pipeline executions and takes one of the following actions each time it runs on a schedule:

    • If the pipeline execution is successful, the number of consecutive failures resets to zero.

    • If the pipeline execution fails, Image Builder increments the number of consecutive failures. If the failure count reaches the limit defined in the AutoDisablePolicy, Image Builder disables the pipeline.

    The consecutive failure count is also reset to zero under the following conditions:

    • The pipeline runs manually and succeeds.

    • The pipeline configuration is updated.

    If the pipeline runs manually and fails, the count remains the same. The next scheduled run continues to increment where it left off before.

    " } }, - "documentation":"

    Details of an image pipeline.

    " + "documentation":"

    Defines the automation configuration for building, testing, and distributing images. A pipeline references the resources that its builds use, such as the recipe and infrastructure configuration. It also holds the settings that control its builds, such as the schedule and custom workflows.

    " }, "ImagePipelineAggregation":{ "type":"structure", @@ -4531,7 +4656,7 @@ }, "type":{ "shape":"ImageType", - "documentation":"

    Specifies which type of image is created by the recipe - an AMI or a container image.

    " + "documentation":"

    The output image type. For an image recipe, this is always AMI. Container images are built from container recipes, a separate resource. This field isn't currently returned in responses.

    " }, "name":{ "shape":"ResourceName", @@ -4555,7 +4680,7 @@ }, "components":{ "shape":"ComponentConfigurationList", - "documentation":"

    The components that are included in the image recipe. Recipes require a minimum of one build component, and can have a maximum of 20 build and test components in any combination.

    " + "documentation":"

    The components that are included in the image recipe. A recipe can contain a maximum of 20 build and test components in any combination, by default. This maximum is an adjustable quota. For more information, see EC2 Image Builder endpoints and quotas in the Amazon Web Services General Reference.

    " }, "parentImage":{ "shape":"NonEmptyString", @@ -4575,11 +4700,11 @@ }, "workingDirectory":{ "shape":"NonEmptyString", - "documentation":"

    The working directory to be used during build and test workflows.

    " + "documentation":"

    The working directory used during build and test workflows. If you don't specify a working directory, Image Builder uses /tmp for Linux and macOS build instances, and C:/ for Windows build instances.

    " }, "additionalInstanceConfiguration":{ "shape":"AdditionalInstanceConfiguration", - "documentation":"

    Before you create a new AMI, Image Builder launches temporary Amazon EC2 instances to build and test your image configuration. Instance configuration adds a layer of control over those instances. You can define settings and add scripts to run when an instance is launched from your AMI.

    " + "documentation":"

    Before you create a new AMI, Image Builder launches temporary Amazon EC2 instances to build and test your image configuration. Instance configuration adds a layer of control over those instances. You can define settings and add scripts to run when Image Builder launches your build instance.

    " }, "amiTags":{ "shape":"TagMap", @@ -4667,7 +4792,7 @@ }, "severity":{ "shape":"NonEmptyString", - "documentation":"

    The severity of the finding.

    " + "documentation":"

    The severity of the finding. For more information, see Severity levels for Amazon Inspector findings in the Amazon Inspector User Guide.

    " }, "firstObservedAt":{ "shape":"DateTimeTimestamp", @@ -4691,10 +4816,10 @@ }, "fixAvailable":{ "shape":"NonEmptyString", - "documentation":"

    Details about whether a fix is available for any of the packages that are identified in the finding through a version update.

    " + "documentation":"

    Details about whether a fix is available for any of the packages that are identified in the finding through a version update. Valid values include:

    • YES – A fix is available for all of the packages identified in the finding.

    • NO – No fix is available.

    • PARTIAL – A fix is available for some, but not all, of the packages identified in the finding.

    " } }, - "documentation":"

    Contains details about a vulnerability scan finding.

    " + "documentation":"

    Contains details about a vulnerability scan finding that Amazon Inspector generated for an image.

    " }, "ImageScanFindingAggregation":{ "type":"structure", @@ -4727,7 +4852,7 @@ "members":{ "name":{ "shape":"FilterName", - "documentation":"

    The name of the image scan finding filter. Filter names are case-sensitive.

    " + "documentation":"

    The name of the image scan finding filter. Filter names are case-sensitive. Valid filter names are:

    • imageBuildVersionArn – Filters findings by the image build version that was scanned.

    • imagePipelineArn – Filters findings by the pipeline that created the scanned image.

    • vulnerabilityId – Filters findings by vulnerability ID, for example a CVE ID.

    • severity – Filters findings by severity level.

    " }, "values":{ "shape":"ImageScanFindingsFilterValues", @@ -4758,7 +4883,7 @@ "members":{ "status":{ "shape":"ImageScanStatus", - "documentation":"

    The current state of vulnerability scans for the image.

    " + "documentation":"

    The current state of vulnerability scans for the image. The scan starts as PENDING and moves through SCANNING and COLLECTING to COMPLETED. Image Builder sets the status to ABANDONED if the image reaches a terminal state before the scan finding collection completes. A scan can also end as FAILED or TIMED_OUT.

    " }, "reason":{ "shape":"NonEmptyString", @@ -4784,7 +4909,7 @@ "members":{ "imageScanningEnabled":{ "shape":"NullableBoolean", - "documentation":"

    A setting that indicates whether Image Builder keeps a snapshot of the vulnerability scans that Amazon Inspector runs against the build instance when you create a new image.

    " + "documentation":"

    Specifies whether Amazon Inspector scans for vulnerabilities when you create a new image, and whether Image Builder saves the findings. Amazon Inspector must be enabled in the account. Image tests must also be enabled. For AMI output, Amazon Inspector scans the test instance. For container output, Amazon Inspector scans the container image that Image Builder pushes to the Amazon ECR repository from your ecrConfiguration settings.

    " }, "ecrConfiguration":{ "shape":"EcrConfiguration", @@ -4807,11 +4932,15 @@ "members":{ "status":{ "shape":"ImageStatus", - "documentation":"

    The status of the image.

    " + "documentation":"

    The status of the image. A new image moves through build, test, and distribution statuses during creation, and ends in the AVAILABLE, FAILED, or CANCELLED state. The DEPRECATED, DISABLED, and DELETED statuses come from later resource management actions.

    " }, "reason":{ "shape":"NonEmptyString", "documentation":"

    The reason for the status of the image.

    " + }, + "failureContext":{ + "shape":"ImageFailureContext", + "documentation":"

    The details about the failure, for images that failed to complete. Image Builder only sets this property when the image status is FAILED.

    " } }, "documentation":"

    Image status and the reason for that status.

    " @@ -4849,7 +4978,7 @@ "documentation":"

    Specifies whether this image produces an AMI or a container image.

    " }, "version":{ - "shape":"VersionNumber", + "shape":"VersionNumberWithBuild", "documentation":"

    The version of the image.

    " }, "platform":{ @@ -4912,11 +5041,11 @@ "members":{ "imageTestsEnabled":{ "shape":"NullableBoolean", - "documentation":"

    Determines if tests should run after building the image. Image Builder defaults to enable tests to run following the image build, before image distribution.

    " + "documentation":"

    Specifies whether tests run after building the image. When enabled, tests run after the image build and before image distribution. Defaults to true.

    " }, "timeoutMinutes":{ "shape":"ImageTestsTimeoutMinutes", - "documentation":"

    The maximum time in minutes that tests are permitted to run.

    The timeout property is not currently active. This value is ignored.

    " + "documentation":"

    The maximum time in minutes that tests are permitted to run. If you don't specify a value, Image Builder stores and returns 720.

    The timeout property is not currently active. This value is ignored.

    " } }, "documentation":"

    Configure image tests for your pipeline build. Tests run after building the image, to verify that the AMI or container image is valid before distributing it.

    " @@ -4950,7 +5079,7 @@ }, "version":{ "shape":"VersionNumber", - "documentation":"

    Details for a specific version of an Image Builder image. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    The semantic version of the image. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "platform":{ "shape":"Platform", @@ -4958,7 +5087,7 @@ }, "osVersion":{ "shape":"OsVersion", - "documentation":"

    The operating system version of the Amazon EC2 build instance. For example, Amazon Linux 2, Ubuntu 18, or Microsoft Windows Server 2019.

    " + "documentation":"

    The operating system version of the image. For example, Amazon Linux 2023 or Microsoft Windows Server 2022.

    " }, "owner":{ "shape":"NonEmptyString", @@ -5004,11 +5133,11 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the component.

    " + "documentation":"

    The name of the component. Image Builder generates the component ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. If a component with the same name and semantic version already exists in your account in the same Amazon Web Services Region, the request creates a new build version for it. If the content is also identical to the latest build version, the request fails because the component already exists.

    " }, "semanticVersion":{ "shape":"VersionNumber", - "documentation":"

    The semantic version of the component. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    The semantic version of the component. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "description":{ "shape":"NonEmptyString", @@ -5032,15 +5161,15 @@ }, "data":{ "shape":"NonEmptyString", - "documentation":"

    The data of the component. Used to specify the data inline. Either data or uri can be used to specify the data within the component.

    " + "documentation":"

    The data of the component. For the SHELL format, this is the plain script content. You must specify exactly one of the data or uri properties. For scripts that exceed the inline length constraint, use the uri property.

    " }, "uri":{ "shape":"Uri", - "documentation":"

    The uri of the component. Must be an Amazon S3 URL and the requester must have permission to access the Amazon S3 bucket. If you use Amazon S3, you can specify component content up to your service quota. Either data or uri can be used to specify the data within the component.

    " + "documentation":"

    The uri of the component. Must be an Amazon S3 URL and you must have permission to access the Amazon S3 bucket. If you use Amazon S3, you can specify component content up to your service quota. Either data or uri can be used to specify the data within the component.

    " }, "kmsKeyId":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the KMS key used to encrypt this component. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key that is used to encrypt this component. This can be either the Key ARN or the Alias ARN. For more information, see Key identifiers (KeyId) in the Key Management Service Developer Guide. If you don't specify a key, Image Builder encrypts the component data with a KMS key that Image Builder owns.

    " }, "tags":{ "shape":"TagMap", @@ -5048,7 +5177,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -5084,7 +5213,7 @@ "members":{ "name":{ "shape":"ResourceName", - "documentation":"

    The name of the image resource that's created from the import.

    " + "documentation":"

    The name of the image resource that's created from the import. Image Builder generates the image ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. If an image with the same name and semantic version already exists in your account in the same Amazon Web Services Region, the import creates a new build version for it.

    " }, "semanticVersion":{ "shape":"VersionNumber", @@ -5100,11 +5229,11 @@ }, "osVersion":{ "shape":"OsVersion", - "documentation":"

    The operating system version for the imported image. Allowed values include the following: Microsoft Windows 11.

    " + "documentation":"

    The operating system version for the imported image. The only supported value is Microsoft Windows 11.

    " }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions to import an image from a Microsoft ISO file.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions to import an image from a Microsoft ISO file. If you don't provide a role, Image Builder uses the Image Builder service-linked role in your account, and creates it if it doesn't exist.

    " }, "infrastructureConfigurationArn":{ "shape":"InfrastructureConfigurationArn", @@ -5112,11 +5241,11 @@ }, "uri":{ "shape":"Uri", - "documentation":"

    The uri of the ISO disk file that's stored in Amazon S3.

    " + "documentation":"

    The uri of the ISO disk file that's stored in Amazon S3, in s3://bucket/key format. The key must end with the .iso, .ISO, or .Iso extension, and the bucket must be owned by the account that makes the request.

    " }, "loggingConfiguration":{ "shape":"ImageLoggingConfiguration", - "documentation":"

    Define logging configuration for the image build process.

    " + "documentation":"

    The CloudWatch Logs log group where Image Builder sends the import logs. If you specify a log group name outside of the /aws/imagebuilder/ namespace, you must also provide an executionRole that has permission to write to that log group.

    " }, "tags":{ "shape":"TagMap", @@ -5132,7 +5261,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -5146,7 +5275,7 @@ }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the output AMI that was created from the ISO disk file.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the Image Builder image resource that this request created. The AMI doesn't exist yet when the response returns. The import runs asynchronously, and the output AMI appears in the image's output resources when the import completes.

    " } } }, @@ -5162,11 +5291,11 @@ "members":{ "name":{ "shape":"NonEmptyString", - "documentation":"

    The name of the base image that is created by the import process.

    " + "documentation":"

    The name of the base image that is created by the import process. Image Builder generates the image ARN from a normalized form of the name, so names that differ only in case, spaces, or underscores count as the same name. If an image with the same name and semantic version already exists in your account in the same Amazon Web Services Region, the import creates a new build version for it.

    " }, "semanticVersion":{ "shape":"VersionNumber", - "documentation":"

    The semantic version to attach to the base image that was created during the import process. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes you can assign any positive integer value, including zero, with an upper limit of 2^30-1, or 1073741823 for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " + "documentation":"

    The semantic version to attach to the base image that was created during the import process. This version follows the semantic version syntax.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Assignment: For the first three nodes, you can assign any positive integer value, including zero. The upper limit is 2^30-1, or 1073741823, for each node. Image Builder automatically assigns the build number to the fourth node.

    Patterns: You can use any numeric pattern that adheres to the assignment requirements for the nodes that you can assign. For example, you might choose a software version pattern, such as 1.0.0, or a date, such as 2021.01.01.

    " }, "description":{ "shape":"NonEmptyString", @@ -5182,11 +5311,11 @@ }, "vmImportTaskId":{ "shape":"NonEmptyString", - "documentation":"

    The importTaskId (API) or ImportTaskId (CLI) from the Amazon EC2 VM import process. Image Builder retrieves information from the import process to pull in the AMI that is created from the VM source as the base image for your recipe.

    " + "documentation":"

    The importTaskId (API) or ImportTaskId (CLI) from the Amazon EC2 VM import process. The import task doesn't need to be complete when you call ImportVmImage - Image Builder monitors the task and finishes creating the image when the task completes.

    " }, "loggingConfiguration":{ "shape":"ImageLoggingConfiguration", - "documentation":"

    Define logging configuration for the image build process.

    " + "documentation":"

    The CloudWatch Logs log group where Image Builder sends the import logs. For ImportVmImage, the log group name must be within the /aws/imagebuilder/ namespace.

    " }, "tags":{ "shape":"TagMap", @@ -5194,7 +5323,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -5208,7 +5337,7 @@ }, "imageArn":{ "shape":"Arn", - "documentation":"

    The Amazon Resource Name (ARN) of the AMI that was created during the VM import process. This AMI is used as the base image for the recipe that imported the VM.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the Image Builder image resource that this request created. Image Builder records the AMI from the VM import task in the image's output resources after the task completes.

    " }, "clientToken":{ "shape":"ClientToken", @@ -5249,7 +5378,7 @@ }, "logging":{ "shape":"Logging", - "documentation":"

    The logging configuration of the infrastructure configuration.

    " + "documentation":"

    The logging configuration of the infrastructure configuration. When you configure S3 logs, Image Builder writes logs from the build and test process to the specified bucket under the key prefix.

    " }, "keyPair":{ "shape":"NonEmptyString", @@ -5257,11 +5386,11 @@ }, "terminateInstanceOnFailure":{ "shape":"NullableBoolean", - "documentation":"

    The terminate instance on failure configuration of the infrastructure configuration.

    " + "documentation":"

    Indicates whether Image Builder terminates the build and test instances when the image build fails. When false, Image Builder retains the instance so that you can debug it.

    " }, "snsTopicArn":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) for the SNS topic to which we send image build event notifications.

    EC2 Image Builder is unable to send notifications to SNS topics that are encrypted using keys from other accounts. The key that is used to encrypt the SNS topic must reside in the account that the Image Builder service runs under.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the SNS topic to which Image Builder sends image build event notifications. Specify a standard topic. Image Builder doesn't support FIFO topics.

    EC2 Image Builder can't send notifications to SNS topics that are encrypted using keys from other accounts. If your SNS topic is encrypted, the key must be owned by the same account that owns your Image Builder resources.

    " }, "dateCreated":{ "shape":"DateTime", @@ -5273,7 +5402,7 @@ }, "resourceTags":{ "shape":"ResourceTagMap", - "documentation":"

    The tags attached to the resource created by Image Builder.

    " + "documentation":"

    The metadata tags assigned to the Amazon EC2 build and test instances that Image Builder launches during image creation.

    " }, "instanceMetadataOptions":{ "shape":"InstanceMetadataOptions", @@ -5285,7 +5414,7 @@ }, "placement":{ "shape":"Placement", - "documentation":"

    The instance placement settings that define where the instances that are launched from your image will run.

    " + "documentation":"

    The instance placement settings that define where the build and test instances that Image Builder launches during image creation run. These settings don't affect instances that you launch from the output image.

    " } }, "documentation":"

    Details of the infrastructure configuration.

    " @@ -5319,7 +5448,7 @@ }, "resourceTags":{ "shape":"ResourceTagMap", - "documentation":"

    The tags attached to the image created by Image Builder.

    " + "documentation":"

    The metadata tags assigned to the Amazon EC2 build and test instances that Image Builder launches during image creation.

    " }, "tags":{ "shape":"TagMap", @@ -5335,10 +5464,10 @@ }, "placement":{ "shape":"Placement", - "documentation":"

    The instance placement settings that define where the instances that are launched from your image will run.

    " + "documentation":"

    The instance placement settings that define where the build and test instances that Image Builder launches during image creation run. These settings don't affect instances that you launch from the output image.

    " } }, - "documentation":"

    The infrastructure used when building Amazon EC2 AMIs.

    " + "documentation":"

    Contains a high-level summary of an infrastructure configuration, including the environment settings that Image Builder uses to build and test images.

    " }, "InfrastructureConfigurationSummaryList":{ "type":"list", @@ -5367,7 +5496,7 @@ "members":{ "adjustedCvss":{ "shape":"CvssScoreDetails", - "documentation":"

    An object that contains details about an adjustment that Amazon Inspector made to the CVSS score for the finding.

    " + "documentation":"

    The CVSS score that Amazon Inspector assigned to the finding after applying its adjustments. It includes the score source, CVSS version, scoring vector, and the adjustments applied.

    " } }, "documentation":"

    Information about the factors that influenced the score that Amazon Inspector assigned for a finding.

    " @@ -5381,15 +5510,15 @@ }, "ebs":{ "shape":"EbsInstanceBlockDeviceSpecification", - "documentation":"

    Use to manage Amazon EBS-specific configuration for this mapping.

    " + "documentation":"

    The Amazon EBS-specific configuration for this mapping.

    " }, "virtualName":{ "shape":"NonEmptyString", - "documentation":"

    Use to manage instance ephemeral devices.

    " + "documentation":"

    The virtual device name for instance ephemeral devices.

    " }, "noDevice":{ "shape":"EmptyString", - "documentation":"

    Use to remove a mapping from the base image.

    " + "documentation":"

    Specifies a mapping to remove from the base image.

    " } }, "documentation":"

    Defines block device mappings for the instance used to configure your image.

    " @@ -5407,7 +5536,7 @@ }, "blockDeviceMappings":{ "shape":"InstanceBlockDeviceMappings", - "documentation":"

    Defines the block devices to attach for building an instance from this Image Builder AMI.

    " + "documentation":"

    Defines the block device mappings for the EC2 instance that Image Builder launches to build and test your container image.

    " } }, "documentation":"

    Defines a custom base AMI and block device mapping configurations of an instance used for building and testing container images.

    " @@ -5417,14 +5546,14 @@ "members":{ "httpTokens":{ "shape":"HttpTokens", - "documentation":"

    Indicates whether a signed token header is required for instance metadata retrieval requests. The values affect the response as follows:

    • required – When you retrieve the IAM role credentials, version 2.0 credentials are returned in all cases.

    • optional – You can include a signed token header in your request to retrieve instance metadata, or you can leave it out. If you include it, version 2.0 credentials are returned for the IAM role. Otherwise, version 1.0 credentials are returned.

    The default setting is optional.

    " + "documentation":"

    Indicates whether a signed token header is required for instance metadata retrieval requests. The values affect the response as follows:

    • required – When you retrieve the IAM role credentials, version 2.0 credentials are returned in all cases.

    • optional – You can include a signed token header in your request to retrieve instance metadata, or you can leave it out. If you include it, version 2.0 credentials are returned for the IAM role. Otherwise, version 1.0 credentials are returned.

    If you don't set a value, the EC2 launch default applies to the build and test instances. That default depends on the base AMI and any account-level instance metadata defaults. For more information, see Configure the instance metadata options in the Amazon EC2 User Guide .

    " }, "httpPutResponseHopLimit":{ "shape":"HttpPutResponseHopLimit", - "documentation":"

    Limit the number of hops that an instance metadata request can traverse to reach its destination. The default is one hop. However, if HTTP tokens are required, container image builds need a minimum of two hops.

    " + "documentation":"

    Limit the number of hops that an instance metadata request can traverse to reach its destination. If you don't set a value, the EC2 launch default for the instance applies. If HTTP tokens are required, container image builds need a minimum of two hops.

    " } }, - "documentation":"

    The instance metadata options that apply to the HTTP requests that pipeline builds use to launch EC2 build and test instances. For more information about instance metadata options, see Configure the instance metadata options in the Amazon EC2 User Guide for Linux instances, or Configure the instance metadata options in the Amazon EC2 Windows Guide for Windows instances.

    " + "documentation":"

    The instance metadata service (IMDS) settings that Image Builder applies to the EC2 build and test instances it launches. These settings control how software on those instances retrieves instance metadata and IAM role credentials.

    " }, "InstanceProfileNameType":{ "type":"string", @@ -5451,7 +5580,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, - "documentation":"

    You have specified two or more mutually exclusive parameters. Review the error message for details.

    ", + "documentation":"

    You have specified a combination of parameters that isn't valid. For example, two mutually exclusive parameters, or a parameter without its required companion parameter. Review the error message for details.

    ", "error":{"httpStatusCode":400}, "exception":true }, @@ -5478,7 +5607,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, - "documentation":"

    You have requested an action that that the service doesn't support.

    ", + "documentation":"

    The request is malformed or otherwise invalid. Verify the request and try again.

    ", "error":{"httpStatusCode":400}, "exception":true }, @@ -5511,18 +5640,18 @@ "documentation":"

    The latest version Amazon Resource Name (ARN) with the same patch version of the Image Builder resource.

    " } }, - "documentation":"

    The resource ARNs with different wildcard variations of semantic versioning.

    " + "documentation":"

    A set of wildcard version ARNs that always reference the latest version of the resource. ARNs are included for the latest version overall, and for the latest versions within the same major, minor, and patch levels.

    " }, "LaunchPermissionConfiguration":{ "type":"structure", "members":{ "userIds":{ "shape":"AccountList", - "documentation":"

    The Amazon Web Services account ID.

    " + "documentation":"

    The Amazon Web Services account IDs to grant launch permission to. Each listed account can use the distributed AMI to launch instances.

    " }, "userGroups":{ "shape":"StringList", - "documentation":"

    The name of the group.

    " + "documentation":"

    The name of the group that you want to grant launch permission to. The only supported value is all, which makes the distributed AMI public.

    " }, "organizationArns":{ "shape":"OrganizationArnList", @@ -5533,7 +5662,7 @@ "documentation":"

    The ARN for an Organizations organizational unit (OU) that you want to share your AMI with. For more information about key concepts for Organizations, see Organizations terminology and concepts.

    " } }, - "documentation":"

    Describes the configuration for a launch permission. The launch permission modification request is sent to the Amazon EC2 ModifyImageAttribute API on behalf of the user for each Region they have selected to distribute the AMI. To make an AMI public, set the launch permission authorized accounts to all. See the examples for making an AMI public at Amazon EC2 ModifyImageAttribute.

    " + "documentation":"

    Describes the configuration for a launch permission. The launch permission modification request is sent to the Amazon EC2 ModifyImageAttribute API on behalf of the user for each Region they have selected to distribute the AMI. To make an AMI public, set userGroups to the value all. See the examples for making an AMI public at Amazon EC2 ModifyImageAttribute.

    " }, "LaunchTemplateConfiguration":{ "type":"structure", @@ -5549,7 +5678,7 @@ }, "setDefaultVersion":{ "shape":"Boolean", - "documentation":"

    Set the specified Amazon EC2 launch template as the default launch template for the specified account.

    ", + "documentation":"

    Specifies whether to make the new launch template version that Image Builder creates the default version of the launch template. If you don't set a value, Image Builder treats it as true.

    ", "box":true } }, @@ -5588,11 +5717,11 @@ }, "resourcesImpactedSummary":{ "shape":"LifecycleExecutionResourcesImpactedSummary", - "documentation":"

    Contains information about associated resources that are identified for action by the runtime instance of the lifecycle policy.

    " + "documentation":"

    A summary flag that indicates whether the lifecycle execution identified any resources to take lifecycle actions on.

    " }, "state":{ "shape":"LifecycleExecutionState", - "documentation":"

    Runtime state that reports if the policy action ran successfully, failed, or was skipped.

    " + "documentation":"

    Runtime state that reports whether the lifecycle execution is in progress, succeeded, or failed.

    " }, "startTime":{ "shape":"DateTimeTimestamp", @@ -5622,7 +5751,7 @@ }, "state":{ "shape":"LifecycleExecutionResourceState", - "documentation":"

    The runtime state for the lifecycle execution.

    " + "documentation":"

    The runtime state of the lifecycle action for this resource.

    " }, "action":{ "shape":"LifecycleExecutionResourceAction", @@ -5656,7 +5785,7 @@ "members":{ "name":{ "shape":"LifecycleExecutionResourceActionName", - "documentation":"

    The name of the resource that was identified for a lifecycle policy action.

    " + "documentation":"

    The name of the lifecycle action that was identified for the resource.

    " }, "reason":{ "shape":"NonEmptyString", @@ -5706,10 +5835,10 @@ "members":{ "hasImpactedResources":{ "shape":"Boolean", - "documentation":"

    Indicates whether an image resource that was identified for a lifecycle action has associated resources that are also impacted.

    " + "documentation":"

    Indicates whether the lifecycle execution identified any resources to take lifecycle actions on.

    " } }, - "documentation":"

    Contains details for an image resource that was identified for a lifecycle action.

    " + "documentation":"

    Contains an indicator that shows whether the lifecycle execution identified any resources to take lifecycle actions on.

    " }, "LifecycleExecutionSnapshotResource":{ "type":"structure", @@ -5775,7 +5904,7 @@ }, "status":{ "shape":"LifecyclePolicyStatus", - "documentation":"

    Indicates whether the lifecycle policy resource is enabled.

    " + "documentation":"

    Indicates whether the lifecycle policy resource is enabled. Only enabled policies run on their schedule. Disabling or deleting a policy removes its schedule and cancels any in-flight lifecycle execution.

    " }, "executionRole":{ "shape":"RoleNameOrArn", @@ -5787,7 +5916,7 @@ }, "policyDetails":{ "shape":"LifecyclePolicyDetails", - "documentation":"

    The configuration details for a lifecycle policy resource.

    " + "documentation":"

    The list of rules for the lifecycle policy. Each rule pairs an action with a filter and optional exclusion rules. A policy can contain at most one rule per action type.

    " }, "resourceSelection":{ "shape":"LifecyclePolicyResourceSelection", @@ -5810,7 +5939,7 @@ "documentation":"

    To help manage your lifecycle policy resources, you can assign your own metadata to each resource in the form of tags. Each tag consists of a key and an optional value, both of which you define.

    " } }, - "documentation":"

    The configuration details for a lifecycle policy resource.

    " + "documentation":"

    Defines a lifecycle policy resource: its identity, status, execution role, resource type, rules, resource selection, timestamps, and tags.

    " }, "LifecyclePolicyArn":{ "type":"string", @@ -5837,7 +5966,7 @@ "documentation":"

    Additional rules to specify resources that should be exempt from policy actions.

    " } }, - "documentation":"

    The configuration details for a lifecycle policy resource.

    " + "documentation":"

    Defines one lifecycle policy rule: the action to take, the filter that determines which resources the rule applies to, and optional exclusion rules.

    " }, "LifecyclePolicyDetailAction":{ "type":"structure", @@ -5845,14 +5974,14 @@ "members":{ "type":{ "shape":"LifecyclePolicyDetailActionType", - "documentation":"

    Specifies the lifecycle action to take.

    " + "documentation":"

    Specifies the lifecycle action to take. DELETE deletes the image resource and, with includeResources, also removes distributed AMIs, snapshots, or container images. DEPRECATE and DISABLE set the corresponding status on the image resource and, if includeResources.amis is set, on its distributed AMIs.

    " }, "includeResources":{ "shape":"LifecyclePolicyDetailActionIncludeResources", - "documentation":"

    Specifies the resources that the lifecycle policy applies to.

    " + "documentation":"

    Specifies which underlying resources the action extends to beyond the Image Builder image resource itself: distributed AMIs, their snapshots, or distributed container images. DELETE rules can include all three, DEPRECATE and DISABLE rules can include AMIs only, and you can only include snapshots together with AMIs.

    " } }, - "documentation":"

    Contains selection criteria for the lifecycle policy.

    " + "documentation":"

    Contains the action configuration for a lifecycle policy rule: the action to take, and which underlying resources the action extends to.

    " }, "LifecyclePolicyDetailActionIncludeResources":{ "type":"structure", @@ -5907,15 +6036,15 @@ }, "sharedAccounts":{ "shape":"AccountList", - "documentation":"

    Specifies Amazon Web Services accounts whose resources are excluded from the lifecycle action.

    " + "documentation":"

    The lifecycle action doesn't apply to AMIs that are shared with any of the specified Amazon Web Services accounts.

    " }, "lastLaunched":{ "shape":"LifecyclePolicyDetailExclusionRulesAmisLastLaunched", - "documentation":"

    Specifies configuration details for Image Builder to exclude the most recent resources from lifecycle actions.

    " + "documentation":"

    Configures Image Builder to exclude AMIs that were launched within the specified time period from lifecycle actions. AMIs with no recorded last-launched time aren't excluded by this rule.

    " }, "tagMap":{ "shape":"TagMap", - "documentation":"

    Lists tags that should be excluded from lifecycle actions for the AMIs that have them.

    " + "documentation":"

    Lifecycle actions don't apply to AMIs that have any of these tags. Both the key and the value must match.

    " } }, "documentation":"

    Defines criteria for AMIs that are excluded from lifecycle actions.

    " @@ -5933,7 +6062,7 @@ }, "unit":{ "shape":"LifecyclePolicyTimeUnit", - "documentation":"

    Defines the unit of time that the lifecycle policy uses to calculate elapsed time since the last instance launched from the AMI. For example: days, weeks, months, or years.

    " + "documentation":"

    Defines the unit of time that the lifecycle policy uses to calculate elapsed time since the last launch.

    " } }, "documentation":"

    Defines criteria to exclude AMIs from lifecycle actions based on the last time they were used to launch an instance.

    " @@ -5952,7 +6081,7 @@ "members":{ "type":{ "shape":"LifecyclePolicyDetailFilterType", - "documentation":"

    Filter resources based on either age or count.

    " + "documentation":"

    Filter resources based on either AGE or COUNT. You can only use the count filter with the DELETE action type.

    " }, "value":{ "shape":"LifecyclePolicyDetailFilterValue", @@ -6004,7 +6133,7 @@ "documentation":"

    A list of tags that are used as selection criteria for the Image Builder image resources that the lifecycle policy applies to.

    " } }, - "documentation":"

    Resource selection criteria for the lifecycle policy.

    " + "documentation":"

    Resource selection criteria for the lifecycle policy. You must provide exactly one selection criteria: either recipes or a tag map, not both.

    " }, "LifecyclePolicyResourceSelectionRecipe":{ "type":"structure", @@ -6049,7 +6178,7 @@ "members":{ "arn":{ "shape":"LifecyclePolicyArn", - "documentation":"

    The Amazon Resource Name (ARN) of the lifecycle policy summary resource.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the lifecycle policy.

    " }, "name":{ "shape":"ResourceName", @@ -6108,16 +6237,16 @@ "members":{ "componentVersionArn":{ "shape":"ComponentVersionArn", - "documentation":"

    The component version Amazon Resource Name (ARN) whose versions you want to list.

    " + "documentation":"

    The component version ARN whose build versions you want to list. The ARN must specify an exact version, without a build number suffix. If you don't specify an ARN, Image Builder returns build versions for the components that your account owns.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6130,7 +6259,7 @@ }, "componentSummaryList":{ "shape":"ComponentSummaryList", - "documentation":"

    The list of component summaries for the specified semantic version.

    " + "documentation":"

    The list of component summaries. Each summary represents one build version of the specified component version, or of the components that your account owns if you didn't specify an ARN. Deprecated build versions aren't included.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6143,24 +6272,24 @@ "members":{ "owner":{ "shape":"Ownership", - "documentation":"

    Filters results based on the type of owner for the component. By default, this request returns a list of components that your account owns. To see results for other types of owners, you can specify components that Amazon manages, third party components, or components that other accounts have shared with you.

    " + "documentation":"

    Filters results based on the type of owner for the component. By default, this request returns a list of components that your account owns. To see results for other types of owners, you can specify components that Amazon manages, components from the Amazon Web Services Marketplace, third party components, or components that other accounts have shared with you.

    " }, "filters":{ "shape":"FilterList", - "documentation":"

    Use the following filters to streamline results:

    • description

    • name

    • platform

    • supportedOsVersion

    • type

    • version

    " + "documentation":"

    Use the following filters to streamline results:

    • description

    • name

    • platform

    • productCodes

    • status

    • supportedOsVersion

    • type

    • version

    " }, "byName":{ "shape":"Boolean", - "documentation":"

    Returns the list of components for the specified name.

    " + "documentation":"

    Specifies whether to return one entry per component name, with all versions of each component aggregated. Defaults to false, which returns one entry per component version. You can't combine this option with the version filter.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6186,7 +6315,7 @@ "members":{ "owner":{ "shape":"Ownership", - "documentation":"

    Returns container recipes belonging to the specified owner, that have been shared with you. You can omit this field to return container recipes belonging to your account.

    " + "documentation":"

    Returns container recipes belonging to the specified owner, that have been shared with you. You can omit this field to return container recipes belonging to your account. For container recipes, the valid owner values are Self, Shared, and Amazon.

    " }, "filters":{ "shape":"FilterList", @@ -6194,12 +6323,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6229,12 +6358,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6260,7 +6389,7 @@ "members":{ "imageVersionArn":{ "shape":"ImageVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image whose build versions you want to retrieve.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image version whose build versions you want to retrieve. The ARN must specify an exact version (<major>.<minor>.<patch>) - wildcards aren't allowed. This parameter is optional. If you don't specify it, Image Builder returns build versions for all of the images in your account.

    " }, "filters":{ "shape":"FilterList", @@ -6268,12 +6397,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6300,16 +6429,16 @@ "members":{ "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    Filter results for the ListImagePackages request by the Image Build Version ARN

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image build version whose packages you want to list. The value must be a full build version ARN.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6344,12 +6473,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6379,12 +6508,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6418,12 +6547,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6447,10 +6576,13 @@ "ListImageScanFindingAggregationsRequest":{ "type":"structure", "members":{ - "filter":{"shape":"Filter"}, + "filter":{ + "shape":"Filter", + "documentation":"

    A filter name and value pair that determines the type of aggregation that Image Builder returns. Use one of the following filter names:

    • imageBuildVersionArn

    • imagePipelineArn

    • vulnerabilityId

    If you don't specify a filter, Image Builder returns an aggregation for your account.

    " + }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6480,16 +6612,16 @@ "members":{ "filters":{ "shape":"ImageScanFindingsFilterList", - "documentation":"

    An array of name value pairs that you can use to filter your results. You can use the following filters to streamline results:

    • imageBuildVersionArn

    • imagePipelineArn

    • vulnerabilityId

    • severity

    If you don't request a filter, then all findings in your account are listed.

    " + "documentation":"

    An array of name value pairs that you can use to filter your results. You can use the following filters to streamline results:

    • imageBuildVersionArn – Filters findings by the image build version that was scanned.

    • imagePipelineArn – Filters findings by the pipeline that created the scanned image.

    • vulnerabilityId – Filters findings by vulnerability ID, for example a CVE ID.

    • severity – Filters findings by severity level.

    If you don't request a filter, then all findings in your account are listed.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6515,7 +6647,7 @@ "members":{ "owner":{ "shape":"Ownership", - "documentation":"

    The owner defines which images you want to list. By default, this request will only show images owned by your account. You can use this field to specify if you want to view images owned by yourself, by Amazon, or those images that have been shared with you by other customers.

    " + "documentation":"

    Filters the list to images owned by you, by Amazon, or shared with you by other accounts. By default, only your account's images are returned.

    " }, "filters":{ "shape":"FilterList", @@ -6523,20 +6655,20 @@ }, "byName":{ "shape":"Boolean", - "documentation":"

    Requests a list of images with a specific recipe name.

    " + "documentation":"

    Specifies whether to return one entry per image name, with all versions of each image aggregated. Defaults to false, which returns one entry per image version. You can't combine this option with the version filter.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " }, "includeDeprecated":{ "shape":"NullableBoolean", - "documentation":"

    Includes deprecated images in the response list.

    " + "documentation":"

    Specifies whether to include deprecated Amazon-managed images in the results. Deprecated images that you own are always returned. Defaults to false.

    " } } }, @@ -6549,7 +6681,7 @@ }, "imageVersionList":{ "shape":"ImageVersionList", - "documentation":"

    The list of image semantic versions.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Filtering: With semantic versioning, you have the flexibility to use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " + "documentation":"

    The list of image semantic versions.

    The semantic version has four nodes: <major>.<minor>.<patch>/<build>. You can assign values for the first three, and can filter on all of them.

    Filtering: You can use wildcards (x) to specify the most recent versions or nodes when selecting the base image or components for your recipe. When you use a wildcard in any node, all nodes to the right of the first wildcard must also be wildcards.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6566,12 +6698,12 @@ }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6598,20 +6730,20 @@ "members":{ "lifecycleExecutionId":{ "shape":"LifecycleExecutionId", - "documentation":"

    Use the unique identifier for a runtime instance of the lifecycle policy to get runtime details.

    " + "documentation":"

    The unique identifier for a runtime instance of the lifecycle policy.

    " }, "parentResourceId":{ "shape":"NonEmptyString", - "documentation":"

    You can leave this empty to get a list of Image Builder resources that were identified for lifecycle actions.

    To get a list of associated resources that are impacted for an individual resource (the parent), specify its Amazon Resource Name (ARN). Associated resources are produced from your image and distributed when you run a build, such as AMIs or container images stored in ECR repositories.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an image build version to get the output resources for, such as AMIs or container images in Amazon ECR. You can get this value from the resourceId in the top-level response. If you leave this property empty, the response lists the Image Builder resources that the lifecycle execution identified for lifecycle actions. If the image build version that you specify in parentResourceId wasn't part of this lifecycle execution, the response contains an empty list.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6620,7 +6752,7 @@ "members":{ "lifecycleExecutionId":{ "shape":"LifecycleExecutionId", - "documentation":"

    Runtime details for the specified runtime instance of the lifecycle policy.

    " + "documentation":"

    The unique identifier for the runtime instance of the lifecycle policy.

    " }, "lifecycleExecutionState":{ "shape":"LifecycleExecutionState", @@ -6642,16 +6774,16 @@ "members":{ "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " }, "resourceArn":{ "shape":"ImageBuilderArn", - "documentation":"

    The Amazon Resource Name (ARN) of the resource for which to get a list of lifecycle runtime instances.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the resource for which to list lifecycle executions. Specify a lifecycle policy ARN to list its executions, or an image build version ARN to list the executions that StartResourceStateUpdate started for that image. Other ARN types aren't valid for this request.

    " } } }, @@ -6673,16 +6805,16 @@ "members":{ "filters":{ "shape":"FilterList", - "documentation":"

    Streamline results based on one of the following values: Name, Status.

    " + "documentation":"

    Use the following filters to streamline results: name, resourceType, and status. Filter names are matched exactly as shown.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6725,12 +6857,12 @@ "members":{ "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6739,7 +6871,7 @@ "members":{ "steps":{ "shape":"WorkflowStepExecutionList", - "documentation":"

    An array of the workflow steps that are waiting for action in your Amazon Web Services account.

    " + "documentation":"

    An array of the workflow steps that are waiting for action in your Amazon Web Services account. Each step is paused at a WaitForAction step, and remains in the list until you respond with SendWorkflowStepAction or the wait times out.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6752,16 +6884,16 @@ "members":{ "workflowVersionArn":{ "shape":"WorkflowWildcardVersionArn", - "documentation":"

    The Amazon Resource Name (ARN) of the workflow resource for which to get a list of build versions.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the workflow resource for which to get a list of build versions. The version segments can contain wildcards (x) to match multiple versions of the workflow. If you don't specify an ARN, the response lists build versions for all of the workflows in your account.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6770,7 +6902,7 @@ "members":{ "workflowSummaryList":{ "shape":"WorkflowSummaryList", - "documentation":"

    A list that contains metadata for the workflow builds that have run for the workflow resource specified in the request.

    " + "documentation":"

    A list that contains metadata for the build versions of the workflow resource specified in the request.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6784,12 +6916,12 @@ "members":{ "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", @@ -6806,7 +6938,7 @@ }, "workflowExecutions":{ "shape":"WorkflowExecutionsList", - "documentation":"

    Contains an array of runtime details that represents each time a workflow ran for the requested image build version.

    " + "documentation":"

    An array of runtime details that represents each time a workflow ran for the requested image build version. Image Builder retains workflow execution records for a limited time, so this array can be empty for older image build versions.

    " }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", @@ -6814,7 +6946,7 @@ }, "message":{ "shape":"ImageBuildMessage", - "documentation":"

    The output message from the list action, if applicable.

    " + "documentation":"

    The failure reason for the image build version, if it's in a failed state. This comes from the image itself, not from an individual workflow, so it's available even when no workflow executions remain for the image.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6828,12 +6960,12 @@ "members":{ "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " }, "workflowExecutionId":{ "shape":"WorkflowExecutionId", @@ -6879,24 +7011,24 @@ "members":{ "owner":{ "shape":"Ownership", - "documentation":"

    Used to get a list of workflow build version filtered by the identity of the creator.

    " + "documentation":"

    Filters results based on the workflow owner. By default, this request returns the workflows that your account owns (Self). Specify Amazon to list the workflows that Image Builder manages. Image Builder rejects the Shared and ThirdParty owner values for workflows, and AWSMarketplace returns no results.

    " }, "filters":{ "shape":"FilterList", - "documentation":"

    Used to streamline search results.

    " + "documentation":"

    Filters to narrow the list of workflows. You can filter on name, version, description, and type.

    " }, "byName":{ "shape":"Boolean", - "documentation":"

    Specify all or part of the workflow name to streamline results.

    " + "documentation":"

    Specifies whether to return one entry per workflow name, with all versions of each workflow aggregated. Defaults to false, which returns one entry per workflow version. You can't combine this option with the version filter.

    " }, "maxResults":{ "shape":"RestrictedInteger", - "documentation":"

    Specify the maximum number of items to return in a request.

    ", + "documentation":"

    The maximum number of items to return in a single request.

    ", "box":true }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    A token to specify where to start paginating. This is the nextToken from a previously truncated response.

    " + "documentation":"

    A token to specify where to start paginating. Use the nextToken value from a previously truncated response.

    " } } }, @@ -6905,7 +7037,7 @@ "members":{ "workflowVersionList":{ "shape":"WorkflowVersionList", - "documentation":"

    A list of workflow build versions that match the request criteria.

    " + "documentation":"

    A list of workflow versions that match the request criteria.

    " }, "nextToken":{ "shape":"PaginationToken", @@ -6945,6 +7077,11 @@ "type":"integer", "min":1 }, + "NonEmptyMaxLengthString":{ + "type":"string", + "max":384000, + "min":1 + }, "NonEmptyString":{ "type":"string", "max":1024, @@ -7002,11 +7139,11 @@ "members":{ "amis":{ "shape":"AmiList", - "documentation":"

    The Amazon EC2 AMIs created by this image.

    " + "documentation":"

    The Amazon EC2 AMIs created by this image. The list contains one entry per AMI, including copies that distribution created in each target Amazon Web Services Region and account.

    " }, "containers":{ "shape":"ContainerList", - "documentation":"

    Container images that the pipeline has generated and stored in the output repository.

    " + "documentation":"

    The container images that Image Builder created when it built this image, stored in the output Amazon ECR repository.

    " } }, "documentation":"

    The resources produced by this image.

    " @@ -7041,7 +7178,7 @@ }, "cvss":{ "shape":"CvssScoreList", - "documentation":"

    CVSS scores for one or more vulnerabilities that Amazon Inspector identified for a package.

    " + "documentation":"

    The CVSS scores for the vulnerability in this finding, as published by the vulnerability sources. Sources include NVD and the operating system vendor, and scores can span CVSS versions.

    " }, "relatedVulnerabilities":{ "shape":"VulnerabilityIdList", @@ -7122,11 +7259,11 @@ }, "hostId":{ "shape":"NonEmptyString", - "documentation":"

    The ID of the Dedicated Host on which build and test instances run. This only applies if tenancy is host. If you specify the host ID, you must not specify the resource group ARN. If you specify both, Image Builder returns an error.

    " + "documentation":"

    The ID of the Dedicated Host on which build and test instances run. This only applies if tenancy is host.

    " }, "hostResourceGroupArn":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon Resource Name (ARN) of the host resource group in which to launch build and test instances. This only applies if tenancy is host. If you specify the resource group ARN, you must not specify the host ID. If you specify both, Image Builder returns an error.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the host resource group in which to launch build and test instances. This only applies if tenancy is host.

    " } }, "documentation":"

    By default, EC2 instances run on shared tenancy hardware. This means that multiple Amazon Web Services accounts might share the same physical hardware. When you use dedicated hardware, the physical server that hosts your instances is dedicated to your Amazon Web Services account. Instance placement settings contain the details for the physical hardware where instances that Image Builder launches during image creation will run.

    " @@ -7242,7 +7379,7 @@ }, "policy":{ "shape":"ResourcePolicyDocument", - "documentation":"

    The policy to apply.

    " + "documentation":"

    The resource policy to apply to the image, as a JSON policy document. Image Builder validates the policy with Amazon Web Services RAM before applying it, and rejects invalid policies with InvalidParameterValueException.

    " } } }, @@ -7289,6 +7426,46 @@ } } }, + "RegionFailure":{ + "type":"structure", + "members":{ + "region":{ + "shape":"NonEmptyString", + "documentation":"

    The Region where the failure occurred.

    " + }, + "status":{ + "shape":"RegionFailureStatus", + "documentation":"

    The failure status for the Region. Indicates whether the process failed, was canceled, or timed out.

    " + }, + "imageConfigurationStep":{ + "shape":"ImageConfigurationStep", + "documentation":"

    The image configuration step where the failure occurred. Image Builder sets this property when the failure happened during post-distribution configuration, such as launch template updates or virtual machine (VM) export. This property doesn't appear for failures that occurred while Image Builder copied the image to the Region.

    " + }, + "errorMessage":{ + "shape":"NonEmptyMaxLengthString", + "documentation":"

    The error message for the failure in the Region.

    " + }, + "targetAccountId":{ + "shape":"AccountId", + "documentation":"

    The account ID of the account that the image was distributed to in the Region.

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

    Contains details about a distribution or image configuration failure for a single Region.

    " + }, + "RegionFailureList":{ + "type":"list", + "member":{"shape":"RegionFailure"}, + "max":256, + "min":1 + }, + "RegionFailureStatus":{ + "type":"string", + "enum":[ + "FAILED", + "CANCELLED", + "TIMED_OUT" + ] + }, "RegionList":{ "type":"list", "member":{"shape":"NonEmptyString"} @@ -7381,15 +7558,18 @@ "members":{ "status":{ "shape":"ResourceStatus", - "documentation":"

    Shows the current lifecycle policy action that was applied to an impacted resource.

    " + "documentation":"

    The status to which you want to move the image resource. Set the status to AVAILABLE to restore an image that's currently deprecated or disabled.

    " } }, - "documentation":"

    The current state of an impacted resource.

    " + "documentation":"

    The state to apply to the image resource in a resource state update request.

    " }, "ResourceStateUpdateExclusionRules":{ "type":"structure", "members":{ - "amis":{"shape":"LifecyclePolicyDetailExclusionRulesAmis"} + "amis":{ + "shape":"LifecyclePolicyDetailExclusionRulesAmis", + "documentation":"

    Defines criteria for AMIs that Image Builder should exclude from the resource state update.

    " + } }, "documentation":"

    Additional rules to specify resources that should be exempt from ad-hoc lifecycle actions.

    " }, @@ -7398,7 +7578,7 @@ "members":{ "amis":{ "shape":"Boolean", - "documentation":"

    Specifies whether the lifecycle action should apply to distributed AMIs

    " + "documentation":"

    Specifies whether the lifecycle action should apply to distributed AMIs.

    " }, "snapshots":{ "shape":"Boolean", @@ -7409,7 +7589,7 @@ "documentation":"

    Specifies whether the lifecycle action should apply to distributed containers.

    " } }, - "documentation":"

    Specifies if the lifecycle policy should apply actions to selected resources.

    " + "documentation":"

    Specifies which underlying resources the resource state update applies to, in addition to the Image Builder image resource itself: distributed AMIs and their snapshots for AMI images, or distributed container images for container images.

    " }, "ResourceStatus":{ "type":"string", @@ -7441,11 +7621,11 @@ "members":{ "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", - "documentation":"

    The source image Amazon Resource Name (ARN) to retry.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image build version that you want to retry. The image must be in the FAILED or CANCELLED state.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -7494,18 +7674,18 @@ "documentation":"

    The Amazon S3 path for the bucket where the output disk images for your VM are stored.

    " } }, - "documentation":"

    Properties that configure export from your build instance to a compatible file format for your VM.

    " + "documentation":"

    Properties that configure exporting the output image to a disk image file in an Amazon S3 bucket, in a format that's compatible with your VMs.

    " }, "S3Logs":{ "type":"structure", "members":{ "s3BucketName":{ "shape":"NonEmptyString", - "documentation":"

    The S3 bucket in which to store the logs.

    " + "documentation":"

    The name of an existing Amazon S3 bucket where Image Builder saves build logs. The bucket isn't validated when you create or update the configuration, and Image Builder doesn't create it. The instance profile associated with this infrastructure configuration must have permission to write to the bucket.

    " }, "s3KeyPrefix":{ "shape":"NonEmptyString", - "documentation":"

    The Amazon S3 path to the bucket where the logs are stored.

    " + "documentation":"

    The Amazon S3 key prefix under which Image Builder writes build and test logs in the bucket.

    " } }, "documentation":"

    Amazon S3 logging configuration.

    " @@ -7515,15 +7695,15 @@ "members":{ "scheduleExpression":{ "shape":"NonEmptyString", - "documentation":"

    The cron expression determines how often EC2 Image Builder evaluates your pipelineExecutionStartCondition.

    For information on how to format a cron expression in Image Builder, see Use cron expressions in EC2 Image Builder.

    " + "documentation":"

    The expression determines how often EC2 Image Builder evaluates your pipelineExecutionStartCondition. You can specify a cron expression, or a rate expression such as rate(1 day).

    For information on how to format a cron expression in Image Builder, see Use cron expressions in EC2 Image Builder.

    " }, "timezone":{ "shape":"Timezone", - "documentation":"

    The timezone that applies to the scheduling expression. For example, \"Etc/UTC\", \"America/Los_Angeles\" in the IANA timezone format. If not specified this defaults to UTC.

    " + "documentation":"

    The timezone that applies to the scheduling expression. Specify a value in IANA timezone format, for example Etc/UTC or America/Los_Angeles. If not specified, this defaults to UTC.

    " }, "pipelineExecutionStartCondition":{ "shape":"PipelineExecutionStartCondition", - "documentation":"

    The start condition configures when the pipeline should trigger a new image build, as follows. If no value is set Image Builder defaults to EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE.

    • EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE (default) – When you use semantic version filters on the base image or components in your image recipe, EC2 Image Builder builds a new image only when there are new versions of the base image or components in your recipe that match the filter.

      For semantic version syntax, see CreateComponent.

    • EXPRESSION_MATCH_ONLY – This condition builds a new image every time the CRON expression matches the current time.

    " + "documentation":"

    The start condition configures when the pipeline should trigger a new image build, as follows. If no value is set Image Builder defaults to EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE.

    • EXPRESSION_MATCH_AND_DEPENDENCY_UPDATES_AVAILABLE (default) – When you use semantic version filters on the base image or components in your image recipe, EC2 Image Builder builds a new image only when there are new versions of the base image or components in your recipe that match the filter.

      For semantic version syntax, see CreateComponent.

    • EXPRESSION_MATCH_ONLY – This condition builds a new image every time the CRON expression matches the current time.

    If the recipe references its base image through an Amazon Web Services Systems Manager Parameter Store parameter, a change in the parameter's value also counts as an available dependency update.

    " }, "autoDisablePolicy":{ "shape":"AutoDisablePolicy", @@ -7547,7 +7727,7 @@ "members":{ "stepExecutionId":{ "shape":"WorkflowStepExecutionId", - "documentation":"

    Uniquely identifies the workflow step that sent the step action.

    " + "documentation":"

    Uniquely identifies the waiting workflow step that you send the action to. To get this identifier, call ListWaitingWorkflowSteps.

    " }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", @@ -7555,7 +7735,7 @@ }, "action":{ "shape":"WorkflowStepActionType", - "documentation":"

    The action to perform on the paused workflow step. The workflow step must be in a waiting state to accept an action. The request fails if the step has already timed out or been actioned.

    " + "documentation":"

    The action to perform on the paused workflow step. RESUME completes the waiting step, and the workflow continues. STOP fails the step, and the step's onFailure setting determines whether the workflow continues or aborts. The workflow step must be in a waiting state to accept an action. The request fails if the step has already timed out or been actioned.

    " }, "reason":{ "shape":"NonEmptyString", @@ -7563,7 +7743,7 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -7573,7 +7753,7 @@ "members":{ "stepExecutionId":{ "shape":"WorkflowStepExecutionId", - "documentation":"

    The workflow step that sent the step action.

    " + "documentation":"

    The unique identifier for the workflow step that received the action, as specified in the request.

    " }, "imageBuildVersionArn":{ "shape":"ImageBuildVersionArn", @@ -7590,7 +7770,7 @@ "members":{ "message":{"shape":"ErrorMessage"} }, - "documentation":"

    This exception is thrown when the service encounters an unrecoverable exception.

    ", + "documentation":"

    An internal server error occurred while Image Builder processed the request. Retrying the request may succeed.

    ", "error":{"httpStatusCode":500}, "exception":true }, @@ -7654,7 +7834,7 @@ }, "dataType":{ "shape":"SsmParameterDataType", - "documentation":"

    The data type specifies what type of value the Parameter contains. We recommend that you use data type aws:ec2:image.

    " + "documentation":"

    The type of value the parameter contains. We recommend the aws:ec2:image data type.

    " } }, "documentation":"

    Configuration for a single Parameter in the Amazon Web Services Systems Manager (SSM) Parameter Store in a given Region.

    " @@ -7689,12 +7869,12 @@ }, "clientToken":{ "shape":"ClientToken", - "documentation":"

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "tags":{ "shape":"TagMap", - "documentation":"

    Specify tags for Image Builder to apply to the image resource that's created When it starts pipeline execution.

    " + "documentation":"

    The tags for Image Builder to apply to the image resource that's created when pipeline execution starts.

    " } } }, @@ -7733,23 +7913,23 @@ }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) of the IAM role that’s used to update image state.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) of the IAM role that's used to update image state. You must provide this property together with includeResources. Neither is valid without the other.

    " }, "includeResources":{ "shape":"ResourceStateUpdateIncludeResources", - "documentation":"

    Specifies which image resources to include in the state update. When specified, the lifecycle action applies to underlying resources. These resources include AMIs, snapshots, and containers in addition to the Image Builder image resource. Requires executionRole to also be specified. To delete an image and its underlying resources, you must specify includeResources. To delete only the Image Builder image record without affecting underlying resources, use the DeleteImage API instead.

    " + "documentation":"

    Specifies which underlying resources to update, in addition to the Image Builder image resource itself. Snapshots and containers are only valid for the DELETED state. To set an image to DELETED, you must include its underlying resources. To delete only the Image Builder image record, use the DeleteImage operation instead.

    " }, "exclusionRules":{ "shape":"ResourceStateUpdateExclusionRules", - "documentation":"

    Skip action on the image resource and associated resources if specified exclusion rules are met.

    " + "documentation":"

    Rules that Image Builder evaluates against each of the image's AMIs. Matching AMIs and their snapshots are skipped. Exclusion rules only take effect when the request includes AMIs. If the target state is DELETED and any resource was skipped, the Image Builder image resource itself is also retained. For the DEPRECATED and DISABLED target states, Image Builder updates the image resource's state regardless of exclusions.

    " }, "updateAt":{ "shape":"DateTimeTimestamp", - "documentation":"

    Specifies the timestamp when the state transition takes effect. Use this parameter only when the target status is DEPRECATED. The value must be a future time.

    " + "documentation":"

    The timestamp that indicates when resources are updated by a lifecycle action. This property is valid only when the target status is DEPRECATED, and the value must be a future time. If you don't specify a value, Image Builder begins the state update right away. For a scheduled deprecation, included AMIs get their EC2 deprecation time set immediately, and Image Builder schedules the image resource to transition to DEPRECATED at that time.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -7759,7 +7939,7 @@ "members":{ "lifecycleExecutionId":{ "shape":"LifecycleExecutionId", - "documentation":"

    Identifies the lifecycle runtime instance that started the resource state update.

    " + "documentation":"

    Identifies the lifecycle execution that performs the resource state update. Image Builder only returns this field when it started a lifecycle execution for the update. Use it with GetLifecycleExecution to track progress.

    " }, "resourceArn":{ "shape":"ImageBuildVersionArn", @@ -7776,10 +7956,10 @@ "members":{ "uninstallAfterBuild":{ "shape":"NullableBoolean", - "documentation":"

    Controls whether the Systems Manager agent is removed from your final build image, prior to creating the new AMI. If this is set to true, then the agent is removed from the final image. If it's set to false, then the agent is left in, so that it is included in the new AMI. default value is false.

    The default behavior of uninstallAfterBuild is to remove the SSM Agent if it was installed by EC2 Image Builder

    " + "documentation":"

    Specifies whether the Systems Manager agent is removed from your final build image before Image Builder creates the new AMI. If true, the agent is removed. If false, the agent is kept, so that it's included in the AMI. If you don't set this property, Image Builder removes the agent only if Image Builder installed the agent during the build. An agent that was pre-installed on the base image is kept.

    " } }, - "documentation":"

    Contains settings for the Systems Manager agent on your build instance.

    " + "documentation":"

    Contains settings for the Systems Manager agent on your build instance. This setting applies to Linux and macOS build instances only. Requests that set it for a recipe with a Windows base image are rejected.

    " }, "TagKey":{ "type":"string", @@ -7840,7 +8020,7 @@ }, "repositoryName":{ "shape":"NonEmptyString", - "documentation":"

    The name of the container repository where the output container image is stored. This name is prefixed by the repository location. For example, <repository location url>/repository_name.

    " + "documentation":"

    The name of the container repository where the output container image is stored. Provide the repository name only (a namespace path such as team-a/my-repo is allowed, but not the registry hostname).

    " } }, "documentation":"

    The container repository where the output container image is stored.

    " @@ -7921,11 +8101,11 @@ }, "distributions":{ "shape":"DistributionList", - "documentation":"

    The distributions of the distribution configuration.

    " + "documentation":"

    The distribution settings for the configuration. Each entry defines how output images are distributed in one target Amazon Web Services Region. A Region can appear at most once in the list. This list replaces the configuration's existing distributions entirely.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -7965,60 +8145,60 @@ }, "imageRecipeArn":{ "shape":"ImageRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that will be used to configure images updated by this image pipeline.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the image recipe that configures images created by this image pipeline. You must specify either this property or containerRecipeArn, but not both.

    " }, "containerRecipeArn":{ "shape":"ContainerRecipeArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container pipeline to update.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container recipe that is used to configure images created by this container pipeline. You must specify either this property or imageRecipeArn, but not both.

    " }, "infrastructureConfigurationArn":{ "shape":"InfrastructureConfigurationArn", - "documentation":"

    The Amazon Resource Name (ARN) of the infrastructure configuration that Image Builder uses to build images that this image pipeline has updated.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the infrastructure configuration that Image Builder uses to build images created by this image pipeline.

    " }, "distributionConfigurationArn":{ "shape":"DistributionConfigurationArn", - "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that Image Builder uses to configure and distribute images that this image pipeline has updated.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the distribution configuration that Image Builder uses to configure and distribute images created by this image pipeline.

    " }, "imageTestsConfiguration":{ "shape":"ImageTestsConfiguration", - "documentation":"

    The image test configuration of the image pipeline.

    " + "documentation":"

    Specifies the test settings that Image Builder applies to images that this pipeline creates. If you don't provide test settings, Image Builder stores a default configuration with image tests enabled.

    " }, "enhancedImageMetadataEnabled":{ "shape":"NullableBoolean", - "documentation":"

    Collects additional information about the image being created, including the operating system (OS) version and package list. This information is used to enhance the overall experience of using EC2 Image Builder. Enabled by default.

    " + "documentation":"

    Specifies whether to collect additional information about the image being created, including the operating system (OS) version and package list. Defaults to true.

    " }, "schedule":{ "shape":"Schedule", - "documentation":"

    The schedule of the image pipeline.

    " + "documentation":"

    The schedule of the image pipeline. Because the update replaces the entire configuration, omitting this property removes any existing schedule. The pipeline then runs only when you call StartImagePipelineExecution.

    " }, "status":{ "shape":"PipelineStatus", - "documentation":"

    The status of the image pipeline.

    " + "documentation":"

    The status of the image pipeline. Defaults to ENABLED when omitted. To keep a pipeline disabled, include this property set to DISABLED in your update request.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true }, "imageScanningConfiguration":{ "shape":"ImageScanningConfiguration", - "documentation":"

    Contains settings for vulnerability scans.

    " + "documentation":"

    Contains settings for vulnerability scans that Amazon Inspector runs against the test instance during image creation.

    " }, "workflows":{ "shape":"WorkflowConfigurationList", - "documentation":"

    Contains the workflows to run for the pipeline.

    " + "documentation":"

    The array of workflow configuration objects for builds that this pipeline starts. You must also specify executionRole when you provide workflows.

    " }, "loggingConfiguration":{ "shape":"PipelineLoggingConfiguration", - "documentation":"

    Update logging configuration for the output image that's created when the pipeline runs.

    " + "documentation":"

    Specifies the logging configuration for the image pipeline. Use this to define custom CloudWatch Logs log groups for your pipeline execution logs and image build logs. The service manages log groups with names starting with /aws/imagebuilder/ using the service-linked role. For custom log group names outside of this prefix, you must also provide an executionRole.

    " }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to perform workflow actions. If you omit this property, the pipeline reverts to the Image Builder service-linked role.

    " }, "imageTags":{ "shape":"TagMap", - "documentation":"

    The tags to be applied to the images produced by this pipeline.

    " + "documentation":"

    The tags that Image Builder applies to the Image Builder image resource that this pipeline's scheduled executions create. These tags don't apply to the output AMI. To tag output AMIs, use amiTags in the pipeline's distribution configuration.

    " } } }, @@ -8057,11 +8237,11 @@ }, "instanceTypes":{ "shape":"InstanceTypeList", - "documentation":"

    The instance types of the infrastructure configuration. You can specify one or more instance types to use for this build. The service will pick one of these instance types based on availability.

    " + "documentation":"

    The instance types of the infrastructure configuration. You can specify one or more instance types to use for this build. Image Builder picks one of these instance types based on availability. If you don't specify instance types, Image Builder selects compatible instance types automatically. If you specify a Dedicated Host, Image Builder uses only instance types that the host supports.

    " }, "instanceProfileName":{ "shape":"InstanceProfileNameType", - "documentation":"

    The instance profile to associate with the instance used to customize your Amazon EC2 AMI.

    " + "documentation":"

    The instance profile to associate with the instance used to customize your Amazon EC2 AMI. The instance profile must exist in your account.

    " }, "securityGroupIds":{ "shape":"SecurityGroupIds", @@ -8069,11 +8249,11 @@ }, "subnetId":{ "shape":"NonEmptyString", - "documentation":"

    The subnet ID to place the instance used to customize your Amazon EC2 AMI in.

    " + "documentation":"

    The subnet ID in which to place the instance used to customize your Amazon EC2 AMI. If you specify subnetId, you must also specify one or more security group IDs in securityGroupIds. Otherwise, the request fails.

    " }, "logging":{ "shape":"Logging", - "documentation":"

    The logging configuration of the infrastructure configuration.

    " + "documentation":"

    The logging configuration of the infrastructure configuration. When you configure S3 logs, Image Builder writes logs from the build and test process to the specified bucket under the key prefix.

    " }, "keyPair":{ "shape":"NonEmptyString", @@ -8081,27 +8261,27 @@ }, "terminateInstanceOnFailure":{ "shape":"NullableBoolean", - "documentation":"

    The terminate instance on failure setting of the infrastructure configuration. Set to false if you want Image Builder to retain the instance used to configure your AMI if the build or test phase of your workflow fails.

    " + "documentation":"

    Specifies whether to terminate the instance on failure. Set to false if you want Image Builder to retain the instance used to configure your AMI if the build or test phase of your workflow fails. Defaults to true.

    " }, "snsTopicArn":{ "shape":"SnsTopicArn", - "documentation":"

    The Amazon Resource Name (ARN) for the SNS topic to which we send image build event notifications.

    EC2 Image Builder is unable to send notifications to SNS topics that are encrypted using keys from other accounts. The key that is used to encrypt the SNS topic must reside in the account that the Image Builder service runs under.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the SNS topic to which Image Builder sends image build event notifications. Specify a standard topic. Image Builder doesn't support FIFO topics. Image Builder validates the topic when you create or update the configuration. You must have permission to publish to the topic.

    EC2 Image Builder can't send notifications to SNS topics that are encrypted using keys from other accounts. If your SNS topic is encrypted, the key must be owned by the same account that owns your Image Builder resources.

    " }, "resourceTags":{ "shape":"ResourceTagMap", - "documentation":"

    The tags attached to the resource created by Image Builder.

    " + "documentation":"

    The metadata tags to assign to the Amazon EC2 instance that Image Builder launches during the build process. Tags are formatted as key value pairs. Tag keys can't begin with aws: or match one of the following reserved keys: CreatedBy, Ec2ImageBuilderArn, Name, or Tags.

    " }, "instanceMetadataOptions":{ "shape":"InstanceMetadataOptions", - "documentation":"

    The instance metadata options that you can set for the HTTP requests that pipeline builds use to launch EC2 build and test instances. For more information about instance metadata options, see one of the following links:

    " + "documentation":"

    The instance metadata service (IMDS) settings that Image Builder applies to the EC2 build and test instances it launches during image creation. If you don't set these options, the EC2 launch defaults for the instance apply. For more information about instance metadata options, see one of the following links:

    " }, "placement":{ "shape":"Placement", - "documentation":"

    The instance placement settings that define where the instances that are launched from your image will run.

    " + "documentation":"

    The instance placement settings that define where the build and test instances that Image Builder launches during image creation run. These settings don't affect instances that you launch from the output image.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -8140,19 +8320,19 @@ }, "description":{ "shape":"NonEmptyString", - "documentation":"

    Optional description for the lifecycle policy.

    " + "documentation":"

    Optional description for the lifecycle policy. Because the update replaces the entire configuration, omitting this property removes any existing description.

    " }, "status":{ "shape":"LifecyclePolicyStatus", - "documentation":"

    Indicates whether the lifecycle policy resource is enabled.

    " + "documentation":"

    Indicates whether the lifecycle policy resource is enabled. Defaults to ENABLED when omitted, so updating a disabled policy without setting this property re-enables it.

    " }, "executionRole":{ "shape":"RoleNameOrArn", - "documentation":"

    The name or Amazon Resource Name (ARN) of the IAM role that Image Builder uses to update the lifecycle policy.

    " + "documentation":"

    The name or Amazon Resource Name (ARN) for the IAM role you create that grants Image Builder access to run lifecycle actions.

    " }, "resourceType":{ "shape":"LifecyclePolicyResourceType", - "documentation":"

    The type of image resource that the lifecycle policy applies to.

    " + "documentation":"

    The type of image resource that the lifecycle policy applies to. The value must match the policy's existing resource type. You can't change the resource type of an existing lifecycle policy.

    " }, "policyDetails":{ "shape":"LifecyclePolicyDetails", @@ -8160,11 +8340,11 @@ }, "resourceSelection":{ "shape":"LifecyclePolicyResourceSelection", - "documentation":"

    Selection criteria for resources that the lifecycle policy applies to.

    " + "documentation":"

    Selection criteria for resources that the lifecycle policy applies to. You must specify exactly one selection criteria: either recipes or a tag map, not both.

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

    Unique, case-sensitive identifier you provide to ensure idempotency of the request. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure that the operation runs no more than one time. If you retry a request with the same client token, Image Builder returns the original response without running the operation again. For more information, see Ensuring idempotency in the Amazon EC2 API Reference.

    ", "idempotencyToken":true } } @@ -8189,6 +8369,12 @@ "type":"string", "pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+$" }, + "VersionNumberWithBuild":{ + "type":"string", + "max":64, + "min":5, + "pattern":"^[0-9]+\\.[0-9]+\\.[0-9]+(?:/[0-9]+)?$" + }, "VulnerabilityId":{"type":"string"}, "VulnerabilityIdAggregation":{ "type":"structure", @@ -8303,7 +8489,7 @@ }, "type":{ "shape":"WorkflowType", - "documentation":"

    Specifies the image creation stage that the workflow applies to. Image Builder currently supports build and test workflows.

    " + "documentation":"

    The image creation stage that the workflow applies to.

    " }, "state":{ "shape":"WorkflowState", @@ -8327,14 +8513,14 @@ }, "tags":{ "shape":"TagMap", - "documentation":"

    The tags that apply to the workflow resource

    " + "documentation":"

    The tags that apply to the workflow resource.

    " }, "parameters":{ "shape":"WorkflowParameterDetailList", - "documentation":"

    An array of input parameters that that the image workflow uses to control actions or configure settings.

    " + "documentation":"

    An array of input parameters that the image workflow uses to control actions or configure settings.

    " } }, - "documentation":"

    Defines a process that Image Builder uses to build and test images during the image creation process.

    " + "documentation":"

    Defines a process that Image Builder runs during the build, test, or distribution stage of the image creation process.

    " }, "WorkflowBuildVersionArn":{ "type":"string", @@ -8359,7 +8545,7 @@ }, "onFailure":{ "shape":"OnWorkflowFailure", - "documentation":"

    The action to take if the workflow fails.

    " + "documentation":"

    The action to take if the workflow fails. With CONTINUE, a failed workflow is logged and image creation proceeds to the next workflow. If you don't set a value, the image build fails when the workflow fails. You can only set this property for test workflows.

    " } }, "documentation":"

    Contains control settings and configurable inputs for a workflow resource.

    " @@ -8403,7 +8589,7 @@ }, "totalStepCount":{ "shape":"WorkflowStepCount", - "documentation":"

    The total number of steps in the workflow. This should equal the sum of the step counts for steps that succeeded, were skipped, and failed.

    " + "documentation":"

    The total number of steps that the workflow document defines for this runtime instance of the workflow. Image Builder sets this count before any steps run. The sum of succeeded, skipped, and failed steps only reaches this total if every step finishes in one of those states.

    " }, "totalStepsSucceeded":{ "shape":"WorkflowStepCount", @@ -8431,7 +8617,7 @@ }, "retried":{ "shape":"NullableBoolean", - "documentation":"

    Indicates retry status for this runtime instance of the workflow.

    " + "documentation":"

    Indicates whether a retry of the image build superseded this runtime instance of the workflow. When you retry a failed image build, Image Builder sets this flag to true on the original workflow executions that the retry re-ran.

    " } }, "documentation":"

    Metadata that includes details and status from this runtime instance of the workflow.

    " @@ -8453,10 +8639,6 @@ "type":"list", "member":{"shape":"WorkflowExecutionMetadata"} }, - "WorkflowNameArn":{ - "type":"string", - "pattern":"^arn:aws(?:-[a-z]+)*:imagebuilder:[a-z]{2,}(?:-[a-z]+)+-[0-9]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):workflow/(build|test|distribution)/[a-z0-9-_]+/x\\.x\\.x$" - }, "WorkflowParameter":{ "type":"structure", "required":[ @@ -8494,7 +8676,7 @@ }, "type":{ "shape":"WorkflowParameterType", - "documentation":"

    The type of input this parameter provides. The currently supported value is \"string\".

    " + "documentation":"

    The type of input this parameter provides. Supported values are string, integer, boolean, and stringList.

    " }, "defaultValue":{ "shape":"WorkflowParameterValueList", @@ -8549,7 +8731,7 @@ "documentation":"

    Describes how or why the workflow changed state.

    " } }, - "documentation":"

    A group of fields that describe the current status of workflow.

    " + "documentation":"

    A group of fields that describe the current status of the workflow.

    " }, "WorkflowStatus":{ "type":"string", @@ -8566,6 +8748,10 @@ "STOP" ] }, + "WorkflowStepAttemptCount":{ + "type":"integer", + "min":1 + }, "WorkflowStepCount":{"type":"integer"}, "WorkflowStepDescription":{ "type":"string", @@ -8604,7 +8790,7 @@ "documentation":"

    The timestamp when the workflow step started.

    " } }, - "documentation":"

    Contains runtime details for an instance of a workflow that ran for the associated image build version.

    " + "documentation":"

    Contains runtime details for a workflow step that has paused at a WaitForAction step, and is waiting for you to send an action.

    " }, "WorkflowStepExecutionId":{ "type":"string", @@ -8677,11 +8863,11 @@ }, "inputs":{ "shape":"WorkflowStepInputs", - "documentation":"

    Input parameters that Image Builder provides for the workflow step.

    " + "documentation":"

    Input parameters that Image Builder provides for the workflow step, as a JSON-encoded string.

    " }, "outputs":{ "shape":"WorkflowStepOutputs", - "documentation":"

    The file names that the workflow step created as output for this runtime instance of the workflow.

    " + "documentation":"

    The output values that the workflow step produced for this runtime instance of the workflow, as a JSON-encoded string. For example, a step that launches an instance outputs the instance ID. If the step failed, this field contains the error message.

    " }, "startTime":{ "shape":"DateTime", @@ -8690,6 +8876,14 @@ "endTime":{ "shape":"DateTime", "documentation":"

    The timestamp when the workflow step finished.

    " + }, + "attemptNumber":{ + "shape":"WorkflowStepAttemptCount", + "documentation":"

    The current attempt number for the workflow step. The first run is attempt one. The number increases by one for each retry.

    " + }, + "maxAttempts":{ + "shape":"WorkflowStepAttemptCount", + "documentation":"

    The maximum number of attempts allowed for the workflow step, based on the retry configuration in the workflow document. If the step doesn't configure retries, the maximum is one attempt.

    " } }, "documentation":"

    Runtime details and status for the workflow step.

    " @@ -8708,7 +8902,7 @@ "type":"structure", "members":{ "arn":{ - "shape":"WorkflowNameArn", + "shape":"WorkflowBuildVersionArn", "documentation":"

    The Amazon Resource Name (ARN) of the workflow resource.

    " }, "name":{ @@ -8729,7 +8923,7 @@ }, "type":{ "shape":"WorkflowType", - "documentation":"

    The image creation stage that this workflow applies to. Image Builder currently supports build and test stage workflows.

    " + "documentation":"

    The image creation stage that this workflow applies to.

    " }, "owner":{ "shape":"NonEmptyString", @@ -8766,7 +8960,7 @@ "type":"structure", "members":{ "arn":{ - "shape":"WorkflowVersionArn", + "shape":"WorkflowWildcardVersionArn", "documentation":"

    The Amazon Resource Name (ARN) of the workflow resource.

    " }, "name":{ @@ -8783,7 +8977,7 @@ }, "type":{ "shape":"WorkflowType", - "documentation":"

    The image creation stage that this workflow applies to. Image Builder currently supports build and test stage workflows.

    " + "documentation":"

    The image creation stage that this workflow applies to.

    " }, "owner":{ "shape":"NonEmptyString", @@ -8796,10 +8990,6 @@ }, "documentation":"

    Contains details about this version of the workflow.

    " }, - "WorkflowVersionArn":{ - "type":"string", - "pattern":"^arn:aws(?:-[a-z]+)*:imagebuilder:[a-z]{2,}(?:-[a-z]+)+-[0-9]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):workflow/(build|test|distribution)/[a-z0-9-_]+/[0-9]+\\.[0-9]+\\.[0-9]+$" - }, "WorkflowVersionArnOrBuildVersionArn":{ "type":"string", "pattern":"^arn:aws(?:-[a-z]+)*:imagebuilder:[a-z]{2,}(?:-[a-z]+)+-[0-9]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):workflow/(build|test|distribution)/[a-z0-9-_]+/(?:(?:([0-9]+|x)\\.([0-9]+|x)\\.([0-9]+|x))|(?:[0-9]+\\.[0-9]+\\.[0-9]+/[0-9]+))$" @@ -8813,5 +9003,5 @@ "pattern":"^arn:aws(?:-[a-z]+)*:imagebuilder:[a-z]{2,}(?:-[a-z]+)+-[0-9]+:(?:[0-9]{12}|aws(?:-[a-z-]+)?):workflow/(build|test|distribution)/[a-z0-9-_]+/(?:[0-9]+|x)\\.(?:[0-9]+|x)\\.(?:[0-9]+|x)$" } }, - "documentation":"

    EC2 Image Builder is a fully managed Amazon Web Services service that makes it easier to automate the creation, management, and deployment of customized, secure, and up-to-date \"golden\" server images that are pre-installed and pre-configured with software and settings to meet specific IT standards.

    " + "documentation":"

    EC2 Image Builder automates the creation, management, and deployment of customized, secure, and up-to-date server images. You can build Amazon Machine Images (AMIs) and container images that are pre-installed and pre-configured with software and settings to meet specific IT standards.

    For an introduction to the service concepts that these API operations work with, see How Image Builder works in the EC2 Image Builder User Guide.

    " } diff --git a/services/inspector/pom.xml b/services/inspector/pom.xml index 8303946be2ec..801d3f1d8649 100644 --- a/services/inspector/pom.xml +++ b/services/inspector/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT inspector AWS Java SDK :: Services :: Amazon Inspector Service diff --git a/services/inspector/src/main/resources/codegen-resources/customization.config b/services/inspector/src/main/resources/codegen-resources/customization.config index a709750374d8..0dc602cddc19 100644 --- a/services/inspector/src/main/resources/codegen-resources/customization.config +++ b/services/inspector/src/main/resources/codegen-resources/customization.config @@ -54,6 +54,5 @@ } ] } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/inspector/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/inspector/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5dc356adce96 --- /dev/null +++ b/services/inspector/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/inspector/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/inspector/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cffa8e6ec3c6..000000000000 --- a/services/inspector/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://inspector.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/inspector2/pom.xml b/services/inspector2/pom.xml index 61e1e3f633ad..8d8964b9aed1 100644 --- a/services/inspector2/pom.xml +++ b/services/inspector2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT inspector2 AWS Java SDK :: Services :: Inspector2 diff --git a/services/inspector2/src/main/resources/codegen-resources/customization.config b/services/inspector2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/inspector2/src/main/resources/codegen-resources/customization.config +++ b/services/inspector2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/inspector2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/inspector2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c643daafd2da --- /dev/null +++ b/services/inspector2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/inspector2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/inspector2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7c8e310d31de..000000000000 --- a/services/inspector2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://inspector2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/inspector2/src/main/resources/codegen-resources/service-2.json b/services/inspector2/src/main/resources/codegen-resources/service-2.json index 60d48e2a6e32..3302d7127fdd 100644 --- a/services/inspector2/src/main/resources/codegen-resources/service-2.json +++ b/services/inspector2/src/main/resources/codegen-resources/service-2.json @@ -3941,10 +3941,6 @@ "lastUpdateOn":{ "shape":"Timestamp", "documentation":"

    The timestamp when the code security integration was last updated.

    " - }, - "tags":{ - "shape":"TagMap", - "documentation":"

    The tags associated with the code security integration.

    " } }, "documentation":"

    A summary of information about a code security integration.

    " @@ -4034,10 +4030,6 @@ "scopeSettings":{ "shape":"ScopeSettings", "documentation":"

    The scope settings that define which repositories will be scanned. If the ScopeSetting parameter is ALL the scan configuration applies to all existing and future projects imported into Amazon Inspector.

    " - }, - "tags":{ - "shape":"TagMap", - "documentation":"

    The tags associated with the scan configuration.

    " } }, "documentation":"

    A summary of information about a code security scan configuration.

    " @@ -4461,7 +4453,7 @@ "type":"string", "max":128, "min":1, - "pattern":"(?!aws:)[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*" + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*" }, "ConnectorTagMap":{ "type":"map", @@ -6131,7 +6123,9 @@ "DAYS_30", "DAYS_60", "DAYS_90", - "DAYS_180" + "DAYS_180", + "DAYS_3", + "DAYS_7" ] }, "EcrPullDateRescanMode":{ @@ -6163,7 +6157,9 @@ "DAYS_180", "DAYS_14", "DAYS_60", - "DAYS_90" + "DAYS_90", + "DAYS_3", + "DAYS_7" ] }, "EcrRescanDurationState":{ @@ -7482,13 +7478,13 @@ "shape":"Timestamp", "documentation":"

    The timestamp when the code security integration was last updated.

    " }, - "tags":{ - "shape":"TagMap", - "documentation":"

    The tags associated with the code security integration.

    " - }, "authorizationUrl":{ "shape":"AuthorizationUrl", "documentation":"

    The URL used to authorize the integration with the repository provider. This is only returned if reauthorization is required to fix a connection issue. Otherwise, it is null.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags associated with the code security integration.

    " } } }, @@ -9525,7 +9521,7 @@ "type":"string", "max":512, "min":1, - "pattern":"(?:/(?:\\.[-\\w]+|[-\\w]+(?:\\.[-\\w]+)?))+/?" + "pattern":"(?:(?:/(?:\\.[-\\w]+|[-\\w]+(?:[. ][-\\w]+)*))+/?|[A-Za-z]:\\\\(?:[-\\w]+(?:[. ][-\\w]+)*\\\\)*[-\\w]+(?:[. ][-\\w]+)*)" }, "PathList":{ "type":"list", @@ -10078,6 +10074,50 @@ "lambdaFunctionTags":{ "shape":"ResourceMapFilterList", "documentation":"

    The Amazon Web Services Lambda function tags used as resource filter criteria.

    " + }, + "cloudProvider":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud providers used as resource filter criteria.

    " + }, + "cloudProviderAccountId":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud provider account IDs used as resource filter criteria.

    " + }, + "cloudProviderOrgId":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud provider organization IDs used as resource filter criteria.

    " + }, + "cloudProviderRegion":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud provider regions used as resource filter criteria.

    " + }, + "cloudVmInstanceTags":{ + "shape":"ResourceMapFilterList", + "documentation":"

    The cloud VM instance tags used as resource filter criteria.

    " + }, + "cloudContainerImageTags":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud container image tags used as resource filter criteria.

    " + }, + "cloudContainerRepositoryName":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud container repository names used as resource filter criteria.

    " + }, + "cloudContainerRegistryName":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud container registry names used as resource filter criteria.

    " + }, + "cloudServerlessFunctionName":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud serverless function names used as resource filter criteria.

    " + }, + "cloudServerlessFunctionRuntime":{ + "shape":"ResourceStringFilterList", + "documentation":"

    The cloud serverless function runtimes used as resource filter criteria.

    " + }, + "cloudServerlessFunctionTags":{ + "shape":"ResourceMapFilterList", + "documentation":"

    The cloud serverless function tags used as resource filter criteria.

    " } }, "documentation":"

    The resource filter criteria for a Software bill of materials (SBOM) report.

    " diff --git a/services/inspectorscan/pom.xml b/services/inspectorscan/pom.xml index f33cbb6043b4..443225cbd37a 100644 --- a/services/inspectorscan/pom.xml +++ b/services/inspectorscan/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT inspectorscan AWS Java SDK :: Services :: Inspector Scan diff --git a/services/inspectorscan/src/main/resources/codegen-resources/customization.config b/services/inspectorscan/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/inspectorscan/src/main/resources/codegen-resources/customization.config +++ b/services/inspectorscan/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/inspectorscan/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/inspectorscan/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..66f8f555a641 --- /dev/null +++ b/services/inspectorscan/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-scan-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-scan-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-scan.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://inspector-scan.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/inspectorscan/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/inspectorscan/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 731b24c9b992..000000000000 --- a/services/inspectorscan/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-scan-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-scan-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-scan.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://inspector-scan.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/interconnect/pom.xml b/services/interconnect/pom.xml index a691990a7a78..bef19d7fd16f 100644 --- a/services/interconnect/pom.xml +++ b/services/interconnect/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT interconnect AWS Java SDK :: Services :: Interconnect diff --git a/services/interconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/interconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1ddbaffbf563 --- /dev/null +++ b/services/interconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://interconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://interconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/interconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/interconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0186432003b0..000000000000 --- a/services/interconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://interconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://interconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/internetmonitor/pom.xml b/services/internetmonitor/pom.xml index 67acf9df019d..b4833915d760 100644 --- a/services/internetmonitor/pom.xml +++ b/services/internetmonitor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT internetmonitor AWS Java SDK :: Services :: Internet Monitor diff --git a/services/internetmonitor/src/main/resources/codegen-resources/customization.config b/services/internetmonitor/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/internetmonitor/src/main/resources/codegen-resources/customization.config +++ b/services/internetmonitor/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/internetmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/internetmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f076d9855442 --- /dev/null +++ b/services/internetmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://internetmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://internetmonitor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://internetmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://internetmonitor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/internetmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/internetmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f8a7e9c09e25..000000000000 --- a/services/internetmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://internetmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://internetmonitor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://internetmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://internetmonitor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/invoicing/pom.xml b/services/invoicing/pom.xml index aebd13a2296f..35b4a0ffcb7e 100644 --- a/services/invoicing/pom.xml +++ b/services/invoicing/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT invoicing AWS Java SDK :: Services :: Invoicing diff --git a/services/invoicing/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/invoicing/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6125bc2c42d8 --- /dev/null +++ b/services/invoicing/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,118 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://invoicing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://invoicing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/invoicing/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/invoicing/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4ad3058ca7b9..000000000000 --- a/services/invoicing/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://invoicing-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://invoicing.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/invoicing/src/main/resources/codegen-resources/paginators-1.json b/services/invoicing/src/main/resources/codegen-resources/paginators-1.json index 505da93c9523..bfe2ff3b6f18 100644 --- a/services/invoicing/src/main/resources/codegen-resources/paginators-1.json +++ b/services/invoicing/src/main/resources/codegen-resources/paginators-1.json @@ -17,6 +17,18 @@ "output_token": "NextToken", "limit_key": "MaxResults", "result_key": "ProcurementPortalPreferences" + }, + "ListProcurementPortalSuppliers": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "ProcurementPortalSuppliers" + }, + "ListProcurementPortals": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "ProcurementPortals" } } } diff --git a/services/invoicing/src/main/resources/codegen-resources/service-2.json b/services/invoicing/src/main/resources/codegen-resources/service-2.json index c5d786935e52..4394b33595b8 100644 --- a/services/invoicing/src/main/resources/codegen-resources/service-2.json +++ b/services/invoicing/src/main/resources/codegen-resources/service-2.json @@ -213,6 +213,41 @@ ], "documentation":"

    This feature API is subject to changing at any time. For more information, see the Amazon Web Services Service Terms (Betas and Previews).

    Retrieves a list of procurement portal preferences associated with the Amazon Web Services account.

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

    Returns the suppliers configured for a specified procurement portal, including supplier identifiers and associated metadata. For faster, more reliable responses, use pagination.

    ", + "readonly":true + }, + "ListProcurementPortals":{ + "name":"ListProcurementPortals", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListProcurementPortalsRequest"}, + "output":{"shape":"ListProcurementPortalsResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Returns the Amazon Web Services-supported procurement portals for e-invoice delivery and purchase order retrieval. Each entry includes the portal identifier, name, and default feature configurations, which define the supported document and attachment types. For faster, more reliable responses, use pagination.

    ", + "readonly":true + }, "ListTagsForResource":{ "name":"ListTagsForResource", "http":{ @@ -251,6 +286,24 @@ "documentation":"

    This feature API is subject to changing at any time. For more information, see the Amazon Web Services Service Terms (Betas and Previews).

    Updates an existing procurement portal preference configuration. This operation can modify settings for e-invoice delivery and purchase order retrieval.

    ", "idempotent":true }, + "SendProcurementPortalValidation":{ + "name":"SendProcurementPortalValidation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"SendProcurementPortalValidationRequest"}, + "output":{"shape":"SendProcurementPortalValidationResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    This feature API is subject to changing at any time. For more information, see the Amazon Web Services Service Terms (Betas and Previews).

    Sends a validation request for a procurement portal preference. This operation initiates the validation process by issuing a validation code that confirms ownership and connectivity of the configured procurement portal endpoint. Use VerifyProcurementPortalValidation to submit the received code and complete validation.

    ", + "idempotent":true + }, "TagResource":{ "name":"TagResource", "http":{ @@ -323,6 +376,24 @@ ], "documentation":"

    This feature API is subject to changing at any time. For more information, see the Amazon Web Services Service Terms (Betas and Previews).

    Updates the status of a procurement portal preference, including the activation state of e-invoice delivery and purchase order retrieval features.

    ", "idempotent":true + }, + "VerifyProcurementPortalValidation":{ + "name":"VerifyProcurementPortalValidation", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"VerifyProcurementPortalValidationRequest"}, + "output":{"shape":"VerifyProcurementPortalValidationResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    This feature API is subject to changing at any time. For more information, see the Amazon Web Services Service Terms (Betas and Previews).

    Submits a validation code to complete the validation of a procurement portal preference. Use this operation after calling SendProcurementPortalValidation to confirm ownership and connectivity of the configured procurement portal endpoint.

    ", + "idempotent":true } }, "shapes":{ @@ -491,6 +562,12 @@ "max":1, "min":1 }, + "CountryCode":{ + "type":"string", + "max":2, + "min":2, + "pattern":"[A-Z]{2}" + }, "CreateInvoiceUnitRequest":{ "type":"structure", "required":[ @@ -845,6 +922,16 @@ }, "documentation":"

    The organization name providing Amazon Web Services services.

    " }, + "FeatureConfigurations":{ + "type":"structure", + "members":{ + "InvoiceConfiguration":{ + "shape":"InvoiceConfiguration", + "documentation":"

    The invoice configuration settings for the procurement portal.

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

    Contains the default feature configuration settings for a procurement portal.

    " + }, "FeesBreakdown":{ "type":"structure", "members":{ @@ -1004,6 +1091,20 @@ "exception":true, "fault":true }, + "InvoiceConfiguration":{ + "type":"structure", + "members":{ + "DocumentTypes":{ + "shape":"EinvoiceDeliveryDocumentTypes", + "documentation":"

    The e-invoice document types supported by the procurement portal.

    " + }, + "AttachmentTypes":{ + "shape":"EinvoiceDeliveryAttachmentTypes", + "documentation":"

    The attachment types supported by the procurement portal for e-invoice delivery.

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

    Specifies the supported document types and attachment types for invoice delivery to a procurement portal.

    " + }, "InvoiceCurrencyAmount":{ "type":"structure", "members":{ @@ -1412,6 +1513,65 @@ } } }, + "ListProcurementPortalSuppliersRequest":{ + "type":"structure", + "required":["PortalIdentifier"], + "members":{ + "PortalIdentifier":{ + "shape":"ProcurementPortalIdString", + "documentation":"

    The unique identifier of the procurement portal for which to list suppliers. Use the PortalIdentifier value returned by ListProcurementPortals.

    " + }, + "NextToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The token for the next set of results. You received this token from a previous call.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. To retrieve the remaining results, make another call with the returned NextToken value. Default is 100.

    " + } + } + }, + "ListProcurementPortalSuppliersResponse":{ + "type":"structure", + "required":["ProcurementPortalSuppliers"], + "members":{ + "ProcurementPortalSuppliers":{ + "shape":"ProcurementPortalSuppliers", + "documentation":"

    The list of suppliers configured for the specified procurement portal.

    " + }, + "NextToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The token to use to retrieve the next set of results, or null if there are no more results.

    " + } + } + }, + "ListProcurementPortalsRequest":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The token for the next set of results. You received this token from a previous call.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. To retrieve the remaining results, make another call with the returned NextToken value. Default is 100.

    " + } + } + }, + "ListProcurementPortalsResponse":{ + "type":"structure", + "required":["ProcurementPortals"], + "members":{ + "ProcurementPortals":{ + "shape":"ProcurementPortals", + "documentation":"

    The list of procurement portals available for configuration.

    " + }, + "NextToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The token to use to retrieve the next set of results, or null if there are no more results.

    " + } + } + }, "ListTagsForResourceRequest":{ "type":"structure", "required":["ResourceArn"], @@ -1458,6 +1618,44 @@ "min":1, "pattern":"[\\S\\s]*" }, + "ProcurementPortal":{ + "type":"structure", + "required":[ + "PortalIdentifier", + "PortalName" + ], + "members":{ + "PortalIdentifier":{ + "shape":"ProcurementPortalIdString", + "documentation":"

    The unique identifier of the procurement portal.

    " + }, + "PortalName":{ + "shape":"ProcurementPortalName", + "documentation":"

    The name of the procurement portal.

    " + }, + "PortalDisplayName":{ + "shape":"BasicString", + "documentation":"

    The display name of the procurement portal.

    " + }, + "DefaultFeatureConfigurations":{ + "shape":"FeatureConfigurations", + "documentation":"

    The default feature configurations for the procurement portal.

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

    Contains metadata for a procurement portal, including the portal identifier, name, and default feature configurations.

    " + }, + "ProcurementPortalEnv":{ + "type":"string", + "documentation":"

    The environment of a procurement portal supplier. PROD indicates the production environment. TEST indicates the sandbox or test environment.

    ", + "enum":[ + "PROD", + "TEST" + ] + }, + "ProcurementPortalIdString":{ + "type":"string", + "min":1 + }, "ProcurementPortalName":{ "type":"string", "enum":[ @@ -1598,6 +1796,7 @@ "type":"string", "enum":[ "PENDING_VERIFICATION", + "VALIDATED", "TEST_INITIALIZED", "TEST_INITIALIZATION_FAILED", "TEST_FAILED", @@ -1694,6 +1893,37 @@ }, "documentation":"

    Provides a summary of a procurement portal preference, including key identifiers and status information.

    " }, + "ProcurementPortalSupplier":{ + "type":"structure", + "required":["SupplierIdentifier"], + "members":{ + "SupplierIdentifier":{ + "shape":"SupplierIdString", + "documentation":"

    The unique identifier of the supplier within the procurement portal.

    " + }, + "SellerOfRecord":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The Amazon Web Services seller of record associated with the supplier—the Amazon Web Services legal entity that issues invoices for the account (for example, AWS_INC or AWS_EUROPE).

    " + }, + "CountryCode":{ + "shape":"CountryCode", + "documentation":"

    The two-letter ISO 3166-1 alpha-2 country code associated with the supplier.

    " + }, + "Environment":{ + "shape":"ProcurementPortalEnv", + "documentation":"

    The environment identifier for the supplier in the procurement portal. PROD for production env, or TEST for sandbox/test env.

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

    Contains metadata for a supplier configured within a procurement portal.

    " + }, + "ProcurementPortalSuppliers":{ + "type":"list", + "member":{"shape":"ProcurementPortalSupplier"} + }, + "ProcurementPortals":{ + "type":"list", + "member":{"shape":"ProcurementPortal"} + }, "ProfileList":{ "type":"list", "member":{"shape":"InvoiceProfile"} @@ -1901,6 +2131,31 @@ "max":100, "min":0 }, + "SendProcurementPortalValidationRequest":{ + "type":"structure", + "required":["ProcurementPortalPreferenceArn"], + "members":{ + "ProcurementPortalPreferenceArn":{ + "shape":"ProcurementPortalPreferenceArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the procurement portal preference to validate.

    " + }, + "ClientToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure idempotency of the request.

    ", + "idempotencyToken":true + } + } + }, + "SendProcurementPortalValidationResponse":{ + "type":"structure", + "required":["ProcurementPortalPreferenceArn"], + "members":{ + "ProcurementPortalPreferenceArn":{ + "shape":"ProcurementPortalPreferenceArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the procurement portal preference for which the validation request was sent.

    " + } + } + }, "SensitiveBasicStringWithoutSpace":{ "type":"string", "max":1024, @@ -1962,6 +2217,10 @@ "type":"string", "enum":["NetworkID"] }, + "SupplierIdString":{ + "type":"string", + "min":1 + }, "TagResourceRequest":{ "type":"structure", "required":[ @@ -2278,6 +2537,38 @@ "other" ] }, + "VerifyProcurementPortalValidationRequest":{ + "type":"structure", + "required":[ + "ProcurementPortalPreferenceArn", + "Code" + ], + "members":{ + "ProcurementPortalPreferenceArn":{ + "shape":"ProcurementPortalPreferenceArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the procurement portal preference to validate.

    " + }, + "Code":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    The validation code received from the procurement portal in response to a previous SendProcurementPortalValidation request.

    " + }, + "ClientToken":{ + "shape":"BasicStringWithoutSpace", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure idempotency of the request.

    ", + "idempotencyToken":true + } + } + }, + "VerifyProcurementPortalValidationResponse":{ + "type":"structure", + "required":["ProcurementPortalPreferenceArn"], + "members":{ + "ProcurementPortalPreferenceArn":{ + "shape":"ProcurementPortalPreferenceArnString", + "documentation":"

    The Amazon Resource Name (ARN) of the procurement portal preference for which validation was completed.

    " + } + } + }, "Year":{ "type":"integer", "box":true, diff --git a/services/iot/pom.xml b/services/iot/pom.xml index 10f27c968634..4231e78c1371 100644 --- a/services/iot/pom.xml +++ b/services/iot/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iot AWS Java SDK :: Services :: AWS IoT diff --git a/services/iot/src/main/resources/codegen-resources/customization.config b/services/iot/src/main/resources/codegen-resources/customization.config index c26c974f03b0..bb14e64d5230 100644 --- a/services/iot/src/main/resources/codegen-resources/customization.config +++ b/services/iot/src/main/resources/codegen-resources/customization.config @@ -48,6 +48,5 @@ "AssetPropertyVariant": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/iot/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iot/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4b63985258d4 --- /dev/null +++ b/services/iot/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,251 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot.{Region}.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iot.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 16, + "nodes": "/////wAAAAH/////AAAAAAAAAA8AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAsAAAAGAAAABQAAAAoAAAAHAAAABwX14QoAAAAIAAAACAX14QsAAAAJAAAACQX14QoF9eEMAAAABgX14QgF9eEJAAAABAAAAA0AAAAMAAAABQX14QUF9eEHAAAABQAAAA4F9eEGAAAABgX14QQF9eEFAAAAAwX14QEAAAAQAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/iot/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iot/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fdafdf21d3c4..000000000000 --- a/services/iot/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iot-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iot.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://iot.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://iot.{Region}.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://iot.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iot.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iot/src/main/resources/codegen-resources/service-2.json b/services/iot/src/main/resources/codegen-resources/service-2.json index 1bebb06b81f5..446177528ec1 100644 --- a/services/iot/src/main/resources/codegen-resources/service-2.json +++ b/services/iot/src/main/resources/codegen-resources/service-2.json @@ -153,7 +153,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Associates a Device Defender security profile with a thing group or this account. Each thing group or account can have up to five security profiles associated with it.

    Requires permission to access the AttachSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Associates a Device Defender security profile with a thing group or this account. Each thing group or account can have up to five security profiles associated with it.

    Requires permission to access the AttachSecurityProfile action.

    " }, "AttachThingPrincipal":{ "name":"AttachThingPrincipal", @@ -237,7 +237,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Cancels a Device Defender ML Detect mitigation action.

    Requires permission to access the CancelDetectMitigationActionsTask action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Cancels a Device Defender ML Detect mitigation action.

    Requires permission to access the CancelDetectMitigationActionsTask action.

    " }, "CancelJob":{ "name":"CancelJob", @@ -428,7 +428,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Use this API to define a Custom Metric published by your devices to Device Defender.

    Requires permission to access the CreateCustomMetric action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Use this API to define a Custom Metric published by your devices to Device Defender.

    Requires permission to access the CreateCustomMetric action.

    " }, "CreateDimension":{ "name":"CreateDimension", @@ -445,7 +445,7 @@ {"shape":"ResourceAlreadyExistsException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Create a dimension that you can use to limit the scope of a metric used in a security profile for IoT Device Defender. For example, using a TOPIC_FILTER dimension, you can narrow down the scope of the metric only to MQTT topics whose name match the pattern specified in the dimension.

    Requires permission to access the CreateDimension action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Create a dimension that you can use to limit the scope of a metric used in a security profile for IoT Device Defender. For example, using a TOPIC_FILTER dimension, you can narrow down the scope of the metric only to MQTT topics whose name match the pattern specified in the dimension.

    Requires permission to access the CreateDimension action.

    " }, "CreateDomainConfiguration":{ "name":"CreateDomainConfiguration", @@ -781,7 +781,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Creates a Device Defender security profile.

    Requires permission to access the CreateSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Creates a Device Defender security profile.

    Requires permission to access the CreateSecurityProfile action.

    " }, "CreateStream":{ "name":"CreateStream", @@ -1060,7 +1060,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Deletes a Device Defender detect custom metric.

    Requires permission to access the DeleteCustomMetric action.

    Before you can delete a custom metric, you must first remove the custom metric from all security profiles it's a part of. The security profile associated with the custom metric can be found using the ListSecurityProfiles API with metricName set to your custom metric name.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Deletes a Device Defender detect custom metric.

    Requires permission to access the DeleteCustomMetric action.

    Before you can delete a custom metric, you must first remove the custom metric from all security profiles it's a part of. The security profile associated with the custom metric can be found using the ListSecurityProfiles API with metricName set to your custom metric name.

    " }, "DeleteDimension":{ "name":"DeleteDimension", @@ -1075,7 +1075,7 @@ {"shape":"InvalidRequestException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Removes the specified dimension from your Amazon Web Services accounts.

    Requires permission to access the DeleteDimension action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Removes the specified dimension from your Amazon Web Services accounts.

    Requires permission to access the DeleteDimension action.

    " }, "DeleteDomainConfiguration":{ "name":"DeleteDomainConfiguration", @@ -1384,7 +1384,7 @@ {"shape":"InternalFailureException"}, {"shape":"VersionConflictException"} ], - "documentation":"

    Deletes a Device Defender security profile.

    Requires permission to access the DeleteSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Deletes a Device Defender security profile.

    Requires permission to access the DeleteSecurityProfile action.

    " }, "DeleteStream":{ "name":"DeleteStream", @@ -1703,7 +1703,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Gets information about a Device Defender detect custom metric.

    Requires permission to access the DescribeCustomMetric action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Gets information about a Device Defender detect custom metric.

    Requires permission to access the DescribeCustomMetric action.

    " }, "DescribeDefaultAuthorizer":{ "name":"DescribeDefaultAuthorizer", @@ -1737,7 +1737,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Gets information about a Device Defender ML Detect mitigation action.

    Requires permission to access the DescribeDetectMitigationActionsTask action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Gets information about a Device Defender ML Detect mitigation action.

    Requires permission to access the DescribeDetectMitigationActionsTask action.

    " }, "DescribeDimension":{ "name":"DescribeDimension", @@ -1753,7 +1753,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Provides details about a dimension that is defined in your Amazon Web Services accounts.

    Requires permission to access the DescribeDimension action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Provides details about a dimension that is defined in your Amazon Web Services accounts.

    Requires permission to access the DescribeDimension action.

    " }, "DescribeDomainConfiguration":{ "name":"DescribeDomainConfiguration", @@ -2018,7 +2018,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Gets information about a Device Defender security profile.

    Requires permission to access the DescribeSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Gets information about a Device Defender security profile.

    Requires permission to access the DescribeSecurityProfile action.

    " }, "DescribeStream":{ "name":"DescribeStream", @@ -2156,7 +2156,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Disassociates a Device Defender security profile from a thing group or from this account.

    Requires permission to access the DetachSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Disassociates a Device Defender security profile from a thing group or from this account.

    Requires permission to access the DetachSecurityProfile action.

    " }, "DetachThingPrincipal":{ "name":"DetachThingPrincipal", @@ -2241,7 +2241,7 @@ {"shape":"InternalFailureException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Returns a Device Defender's ML Detect Security Profile training model's status.

    Requires permission to access the GetBehaviorModelTrainingSummaries action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Returns a Device Defender's ML Detect Security Profile training model's status.

    Requires permission to access the GetBehaviorModelTrainingSummaries action.

    " }, "GetBucketsAggregation":{ "name":"GetBucketsAggregation", @@ -2626,7 +2626,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Lists the active violations for a given Device Defender security profile.

    Requires permission to access the ListActiveViolations action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists the active violations for a given Device Defender security profile.

    Requires permission to access the ListActiveViolations action.

    " }, "ListAttachedPolicies":{ "name":"ListAttachedPolicies", @@ -2867,7 +2867,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Lists your Device Defender detect custom metrics.

    Requires permission to access the ListCustomMetrics action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists your Device Defender detect custom metrics.

    Requires permission to access the ListCustomMetrics action.

    " }, "ListDetectMitigationActionsExecutions":{ "name":"ListDetectMitigationActionsExecutions", @@ -2882,7 +2882,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Lists mitigation actions executions for a Device Defender ML Detect Security Profile.

    Requires permission to access the ListDetectMitigationActionsExecutions action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists mitigation actions executions for a Device Defender ML Detect Security Profile.

    Requires permission to access the ListDetectMitigationActionsExecutions action.

    " }, "ListDetectMitigationActionsTasks":{ "name":"ListDetectMitigationActionsTasks", @@ -2897,7 +2897,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    List of Device Defender ML Detect mitigation actions tasks.

    Requires permission to access the ListDetectMitigationActionsTasks action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    List of Device Defender ML Detect mitigation actions tasks.

    Requires permission to access the ListDetectMitigationActionsTasks action.

    " }, "ListDimensions":{ "name":"ListDimensions", @@ -2912,7 +2912,7 @@ {"shape":"InvalidRequestException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    List the set of dimensions that are defined for your Amazon Web Services accounts.

    Requires permission to access the ListDimensions action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    List the set of dimensions that are defined for your Amazon Web Services accounts.

    Requires permission to access the ListDimensions action.

    " }, "ListDomainConfigurations":{ "name":"ListDomainConfigurations", @@ -3362,7 +3362,7 @@ {"shape":"InternalFailureException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Lists the Device Defender security profiles you've created. You can filter security profiles by dimension or custom metric.

    Requires permission to access the ListSecurityProfiles action.

    dimensionName and metricName cannot be used in the same request.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists the Device Defender security profiles you've created. You can filter security profiles by dimension or custom metric.

    Requires permission to access the ListSecurityProfiles action.

    dimensionName and metricName cannot be used in the same request.

    " }, "ListSecurityProfilesForTarget":{ "name":"ListSecurityProfilesForTarget", @@ -3378,7 +3378,7 @@ {"shape":"InternalFailureException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Lists the Device Defender security profiles attached to a target (thing group).

    Requires permission to access the ListSecurityProfilesForTarget action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists the Device Defender security profiles attached to a target (thing group).

    Requires permission to access the ListSecurityProfilesForTarget action.

    " }, "ListStreams":{ "name":"ListStreams", @@ -3446,7 +3446,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Lists the targets (thing groups) associated with a given Device Defender security profile.

    Requires permission to access the ListTargetsForSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists the targets (thing groups) associated with a given Device Defender security profile.

    Requires permission to access the ListTargetsForSecurityProfile action.

    " }, "ListThingGroups":{ "name":"ListThingGroups", @@ -3675,7 +3675,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Lists the Device Defender security profile violations discovered during the given time period. You can use filters to limit the results to those alerts issued for a particular security profile, behavior, or thing (device).

    Requires permission to access the ListViolationEvents action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Lists the Device Defender security profile violations discovered during the given time period. You can use filters to limit the results to those alerts issued for a particular security profile, behavior, or thing (device).

    Requires permission to access the ListViolationEvents action.

    " }, "PutVerificationStateOnViolation":{ "name":"PutVerificationStateOnViolation", @@ -3690,7 +3690,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Set a verification state and provide a description of that verification state on a violation (detect alarm).

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Set a verification state and provide a description of that verification state on a violation (detect alarm).

    " }, "RegisterCACertificate":{ "name":"RegisterCACertificate", @@ -3973,7 +3973,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Starts a Device Defender ML Detect mitigation actions task.

    Requires permission to access the StartDetectMitigationActionsTask action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Starts a Device Defender ML Detect mitigation actions task.

    Requires permission to access the StartDetectMitigationActionsTask action.

    " }, "StartOnDemandAuditTask":{ "name":"StartOnDemandAuditTask", @@ -4266,7 +4266,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Updates a Device Defender detect custom metric.

    Requires permission to access the UpdateCustomMetric action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Updates a Device Defender detect custom metric.

    Requires permission to access the UpdateCustomMetric action.

    " }, "UpdateDimension":{ "name":"UpdateDimension", @@ -4282,7 +4282,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Updates the definition for a dimension. You cannot change the type of a dimension after it is created (you can delete it and recreate it).

    Requires permission to access the UpdateDimension action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Updates the definition for a dimension. You cannot change the type of a dimension after it is created (you can delete it and recreate it).

    Requires permission to access the UpdateDimension action.

    " }, "UpdateDomainConfiguration":{ "name":"UpdateDomainConfiguration", @@ -4544,7 +4544,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Updates a Device Defender security profile.

    Requires permission to access the UpdateSecurityProfile action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Updates a Device Defender security profile.

    Requires permission to access the UpdateSecurityProfile action.

    " }, "UpdateStream":{ "name":"UpdateStream", @@ -4665,7 +4665,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Validates a Device Defender security profile behaviors specification.

    Requires permission to access the ValidateSecurityProfileBehaviors action.

    " + "documentation":"

    The IoT Device Defender detect feature will no longer be available to new customers starting August 31, 2026. If you would like to use the detect feature, sign up prior to August 31, 2026. To learn about alternatives to IoT Device Defender detect, see IoT Device Defender detect feature availability change in the IoT Device Defender Developer Guide. There is no change to IoT Device Defender audit availability.

    Validates a Device Defender security profile behaviors specification.

    Requires permission to access the ValidateSecurityProfileBehaviors action.

    " } }, "shapes":{ @@ -4840,6 +4840,10 @@ "location":{ "shape":"LocationAction", "documentation":"

    The Amazon Location Service rule action sends device location updates from an MQTT message to an Amazon Location tracker resource.

    " + }, + "influxDB":{ + "shape":"InfluxDBAction", + "documentation":"

    Write data to an InfluxDB database.

    " } }, "documentation":"

    Describes the actions associated with a rule.

    " @@ -13380,6 +13384,239 @@ }, "documentation":"

    Provides additional selections for named shadows and geolocation data.

    To add named shadows to your fleet indexing configuration, set namedShadowIndexingMode to be ON and specify your shadow names in namedShadowNames filter.

    To add geolocation data to your fleet indexing configuration:

    • If you store geolocation data in a class/unnamed shadow, set thingIndexingMode to be REGISTRY_AND_SHADOW and specify your geolocation data in geoLocations filter.

    • If you store geolocation data in a named shadow, set namedShadowIndexingMode to be ON, add the shadow name in namedShadowNames filter, and specify your geolocation data in geoLocations filter. For more information, see Managing fleet indexing.

    " }, + "InfluxDBAction":{ + "type":"structure", + "required":[ + "destinationArn", + "roleArn", + "databaseName", + "tableName" + ], + "members":{ + "destinationArn":{ + "shape":"AwsArn", + "documentation":"

    The ARN of the InfluxDB topic rule destination that identifies the InfluxDB instance to write to.

    " + }, + "roleArn":{ + "shape":"AwsArn", + "documentation":"

    The ARN of the role that grants permission to retrieve the InfluxDB API token from Amazon Web Services Secrets Manager.

    " + }, + "databaseName":{ + "shape":"InfluxDBDatabaseName", + "documentation":"

    The name of the InfluxDB database to write to. In InfluxDB 2, this is the name of the bucket.

    " + }, + "tableName":{ + "shape":"InfluxDBTableName", + "documentation":"

    The name of the table to write the data point to. This is the measurement name of the InfluxDB line protocol record.

    Accepts substitution templates.

    " + }, + "organization":{ + "shape":"InfluxDBOrganization", + "documentation":"

    The name of the InfluxDB organization that owns the database.

    A write to an InfluxDB 2 instance fails if this value isn't set. This value isn't used when the destination is an InfluxDB 3 instance.

    " + }, + "tags":{ + "shape":"InfluxDBTagMap", + "documentation":"

    The set of tags to write with each data point. Tags are the indexed metadata of an InfluxDB data point.

    Tag names and tag values accept substitution templates. A tag name can't use the @{...} per-element form. A tag name must resolve to the same value for every element of an array payload.

    " + }, + "timestampUnit":{ + "shape":"InfluxDBTimestampUnit", + "documentation":"

    The precision of the timestamp written with each data point. Valid values are s (seconds), ms (milliseconds), us (microseconds), and ns (nanoseconds).

    If omitted, the topic rule action uses ms.

    " + }, + "batchConfig":{ + "shape":"InfluxDBBatchConfig", + "documentation":"

    The batching configuration for the action. When present, IoT collects data points from multiple messages and writes them to InfluxDB in a single request.

    If omitted, each message is written to InfluxDB in its own request.

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

    The InfluxDB rule action converts the message payload into InfluxDB line protocol. It writes the result to a table in an InfluxDB database. The database can be an Amazon Timestream for InfluxDB instance or a self-managed InfluxDB cluster.

    The action connects to InfluxDB through an InfluxDB topic rule destination, which must be in the ENABLED state before the action can write data.

    " + }, + "InfluxDBBatchAcrossTopics":{"type":"boolean"}, + "InfluxDBBatchConfig":{ + "type":"structure", + "members":{ + "maxBatchSize":{ + "shape":"InfluxDBMaxBatchSize", + "documentation":"

    The maximum number of data points to collect in a batch.

    If you don't specify a value, this limit doesn't apply. IoT then closes each batch when another configured limit is reached.

    " + }, + "maxBatchOpenMs":{ + "shape":"InfluxDBMaxBatchOpenMs", + "documentation":"

    The maximum length of time, in milliseconds, to keep a batch open before writing it to InfluxDB.

    If you don't specify a value, this limit doesn't apply. IoT then closes each batch when another configured limit is reached.

    " + }, + "maxBatchSizeBytes":{ + "shape":"InfluxDBMaxBatchSizeBytes", + "documentation":"

    The maximum size of a batch, in bytes, before IoT writes it to InfluxDB.

    If you don't specify a value, this limit doesn't apply. IoT then closes each batch when another configured limit is reached.

    " + }, + "batchAcrossTopics":{ + "shape":"InfluxDBBatchAcrossTopics", + "documentation":"

    Specifies whether to collect data points from different topics into the same batch.

    If omitted or false, IoT batches data points for each topic separately.

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

    The batching configuration of an InfluxDB rule action. IoT closes a batch and writes it to InfluxDB when the first of the configured limits is reached.

    " + }, + "InfluxDBDatabaseName":{ + "type":"string", + "max":64, + "min":2, + "pattern":"^[^_\\\"][^\\\"]+$" + }, + "InfluxDBDestinationConfiguration":{ + "type":"structure", + "required":[ + "endpoint", + "influxDBVersion", + "secretId" + ], + "members":{ + "endpoint":{ + "shape":"Url", + "documentation":"

    The URL of the InfluxDB instance to write to.

    " + }, + "influxDBVersion":{ + "shape":"InfluxDBVersion", + "documentation":"

    The major version of the InfluxDB instance. Valid values are V2 and V3.

    " + }, + "secretId":{ + "shape":"InfluxDBSecretId", + "documentation":"

    The ARN or name of the Amazon Web Services Secrets Manager secret that contains the InfluxDB API token.

    " + }, + "secretType":{ + "shape":"InfluxDBSecretType", + "documentation":"

    The type of the secret that contains the InfluxDB API token. Valid values are SecretString and SecretBinary.

    If omitted, IoT reads the secret as a string.

    " + }, + "secretKey":{ + "shape":"InfluxDBSecretKey", + "documentation":"

    The key to read from the secret value when the secret contains a JSON object. If omitted, IoT uses the entire secret value as the InfluxDB API token.

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

    The configuration of an InfluxDB topic rule destination.

    " + }, + "InfluxDBDestinationProperties":{ + "type":"structure", + "members":{ + "endpoint":{ + "shape":"Url", + "documentation":"

    The URL of the InfluxDB instance that the destination writes to.

    " + }, + "influxDBVersion":{ + "shape":"InfluxDBVersion", + "documentation":"

    The major version of the InfluxDB instance. Valid values are V2 and V3.

    " + }, + "secretId":{ + "shape":"InfluxDBSecretId", + "documentation":"

    The ARN or name of the Amazon Web Services Secrets Manager secret that contains the InfluxDB API token.

    " + }, + "secretType":{ + "shape":"InfluxDBSecretType", + "documentation":"

    The type of the secret that contains the InfluxDB API token. Valid values are SecretString and SecretBinary.

    " + }, + "secretKey":{ + "shape":"InfluxDBSecretKey", + "documentation":"

    The key that is read from the secret value when the secret contains a JSON object.

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

    The properties of an existing InfluxDB topic rule destination, as returned by CreateTopicRuleDestination and GetTopicRuleDestination.

    " + }, + "InfluxDBDestinationSummary":{ + "type":"structure", + "members":{ + "endpoint":{ + "shape":"Url", + "documentation":"

    The URL of the InfluxDB instance that the destination writes to.

    " + }, + "influxDBVersion":{ + "shape":"InfluxDBVersion", + "documentation":"

    The major version of the InfluxDB instance. Valid values are V2 and V3.

    " + }, + "secretId":{ + "shape":"InfluxDBSecretId", + "documentation":"

    The ARN or name of the Amazon Web Services Secrets Manager secret that contains the InfluxDB API token.

    " + }, + "secretType":{ + "shape":"InfluxDBSecretType", + "documentation":"

    The type of the secret that contains the InfluxDB API token. Valid values are SecretString and SecretBinary.

    " + }, + "secretKey":{ + "shape":"InfluxDBSecretKey", + "documentation":"

    The key that is read from the secret value when the secret contains a JSON object.

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

    A summary of an InfluxDB topic rule destination, as returned by ListTopicRuleDestinations. For the full set of destination properties, see InfluxDBDestinationProperties.

    " + }, + "InfluxDBMaxBatchOpenMs":{ + "type":"integer", + "max":1000, + "min":5 + }, + "InfluxDBMaxBatchSize":{ + "type":"integer", + "max":500, + "min":1 + }, + "InfluxDBMaxBatchSizeBytes":{ + "type":"integer", + "max":131072, + "min":100 + }, + "InfluxDBOrganization":{ + "type":"string", + "max":64, + "min":1 + }, + "InfluxDBSecretId":{ + "type":"string", + "max":512, + "min":1 + }, + "InfluxDBSecretKey":{ + "type":"string", + "max":128, + "min":1 + }, + "InfluxDBSecretType":{ + "type":"string", + "enum":[ + "SecretString", + "SecretBinary" + ] + }, + "InfluxDBTableName":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"^[^_].*$" + }, + "InfluxDBTagMap":{ + "type":"map", + "key":{"shape":"InfluxDBTagName"}, + "value":{"shape":"InfluxDBTagValue"}, + "max":498, + "min":0 + }, + "InfluxDBTagName":{ + "type":"string", + "max":256, + "min":1, + "pattern":"^[^_].*$" + }, + "InfluxDBTagValue":{ + "type":"string", + "max":1024, + "min":1 + }, + "InfluxDBTimestampUnit":{ + "type":"string", + "enum":[ + "s", + "ms", + "us", + "ns" + ] + }, + "InfluxDBVersion":{ + "type":"string", + "enum":[ + "V2", + "V3" + ] + }, "InlineDocument":{"type":"string"}, "InputName":{ "type":"string", @@ -21118,6 +21355,10 @@ "vpcProperties":{ "shape":"VpcDestinationProperties", "documentation":"

    Properties of the virtual private cloud (VPC) connection.

    " + }, + "influxDBProperties":{ + "shape":"InfluxDBDestinationProperties", + "documentation":"

    The properties of an InfluxDB topic rule destination, as returned by CreateTopicRuleDestination and GetTopicRuleDestination.

    " } }, "documentation":"

    A topic rule destination.

    " @@ -21132,6 +21373,10 @@ "vpcConfiguration":{ "shape":"VpcDestinationConfiguration", "documentation":"

    Configuration of the virtual private cloud (VPC) connection.

    " + }, + "influxDBConfiguration":{ + "shape":"InfluxDBDestinationConfiguration", + "documentation":"

    The configuration of an InfluxDB topic rule destination, which you specify when you call CreateTopicRuleDestination.

    " } }, "documentation":"

    Configuration of the topic rule destination.

    " @@ -21185,6 +21430,10 @@ "vpcDestinationSummary":{ "shape":"VpcDestinationSummary", "documentation":"

    Information about the virtual private cloud (VPC) connection.

    " + }, + "influxDBSummary":{ + "shape":"InfluxDBDestinationSummary", + "documentation":"

    A summary of an InfluxDB topic rule destination, as returned by ListTopicRuleDestinations.

    " } }, "documentation":"

    Information about the topic rule destination.

    " diff --git a/services/iotdataplane/pom.xml b/services/iotdataplane/pom.xml index 486df17ff1da..2e20fa920986 100644 --- a/services/iotdataplane/pom.xml +++ b/services/iotdataplane/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotdataplane AWS Java SDK :: Services :: AWS IoT Data Plane diff --git a/services/iotdataplane/src/main/resources/codegen-resources/customization.config b/services/iotdataplane/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotdataplane/src/main/resources/codegen-resources/customization.config +++ b/services/iotdataplane/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8734c7471643 --- /dev/null +++ b/services/iotdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,395 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ca-central-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "cn-north-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.ca-central-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-east-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-west-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.iot-fips.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.ats.iot.cn-north-1.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot.{Region}.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-ats.iot.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 24, + "nodes": "/////wAAAAH/////AAAAAAAAABcAAAADAAAAAQAAAAQF9eEVAAAAAgAAAAUF9eEVAAAAAwAAAAwAAAAGAAAABAAAAAsAAAAHAAAACAX14REAAAAIAAAACgX14RIAAAAJAAAACwX14RMAAAAKAAAADAX14RIF9eEUAAAABQX14Q8F9eEQAAAABAAAABUAAAANAAAABgAAAA4F9eEOAAAABwX14QYAAAAPAAAACQX14QcAAAAQAAAADQX14QgAAAARAAAADgX14QkAAAASAAAADwX14QoAAAATAAAAEAX14QsAAAAUAAAAEQX14QwF9eENAAAABQAAABYF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAYAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9d5f58b6ca7c..000000000000 --- a/services/iotdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,541 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data-ats.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ca-central-1" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.ca-central-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-2" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-east-2.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-1" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-2" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-west-2.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://data.iot-fips.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://data-ats.iot-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data-ats.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "cn-north-1" - ] - } - ], - "endpoint": { - "url": "https://data.ats.iot.cn-north-1.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://data-ats.iot.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://data-ats.iot.{Region}.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://data-ats.iot.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://data-ats.iot.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotdeviceadvisor/pom.xml b/services/iotdeviceadvisor/pom.xml index e5909834bac7..dc573ff59ce2 100644 --- a/services/iotdeviceadvisor/pom.xml +++ b/services/iotdeviceadvisor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotdeviceadvisor AWS Java SDK :: Services :: Iot Device Advisor diff --git a/services/iotdeviceadvisor/src/main/resources/codegen-resources/customization.config b/services/iotdeviceadvisor/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotdeviceadvisor/src/main/resources/codegen-resources/customization.config +++ b/services/iotdeviceadvisor/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..023d2a3f6c6f --- /dev/null +++ b/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotdeviceadvisor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotdeviceadvisor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotdeviceadvisor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotdeviceadvisor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7b4830bd5d4e..000000000000 --- a/services/iotdeviceadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotdeviceadvisor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotdeviceadvisor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotdeviceadvisor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.iotdeviceadvisor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotfleetwise/pom.xml b/services/iotfleetwise/pom.xml index 6b65e02e6d0b..79b7bfa449fc 100644 --- a/services/iotfleetwise/pom.xml +++ b/services/iotfleetwise/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotfleetwise AWS Java SDK :: Services :: Io T Fleet Wise diff --git a/services/iotfleetwise/src/main/resources/codegen-resources/customization.config b/services/iotfleetwise/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotfleetwise/src/main/resources/codegen-resources/customization.config +++ b/services/iotfleetwise/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0b01d2f4dfcf --- /dev/null +++ b/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotfleetwise-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotfleetwise-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotfleetwise.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotfleetwise.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4612fa02b701..000000000000 --- a/services/iotfleetwise/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotfleetwise-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotfleetwise-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotfleetwise.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iotfleetwise.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotjobsdataplane/pom.xml b/services/iotjobsdataplane/pom.xml index c835ffd7c99e..74eaaf2b3eb9 100644 --- a/services/iotjobsdataplane/pom.xml +++ b/services/iotjobsdataplane/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotjobsdataplane AWS Java SDK :: Services :: IoT Jobs Data Plane diff --git a/services/iotjobsdataplane/src/main/resources/codegen-resources/customization.config b/services/iotjobsdataplane/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotjobsdataplane/src/main/resources/codegen-resources/customization.config +++ b/services/iotjobsdataplane/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..46343a704c20 --- /dev/null +++ b/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.jobs.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.jobs.iot-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.jobs.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.jobs.iot.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8f3f6b73a0ec..000000000000 --- a/services/iotjobsdataplane/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.jobs.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.jobs.iot-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.jobs.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://data.jobs.iot.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotmanagedintegrations/pom.xml b/services/iotmanagedintegrations/pom.xml index d926ff3acb42..5d5a0313d3b6 100644 --- a/services/iotmanagedintegrations/pom.xml +++ b/services/iotmanagedintegrations/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotmanagedintegrations AWS Java SDK :: Services :: IoT Managed Integrations diff --git a/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b7f64c37306f --- /dev/null +++ b/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotmanagedintegrations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotmanagedintegrations.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index caae57a18ec9..000000000000 --- a/services/iotmanagedintegrations/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://api.iotmanagedintegrations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.iotmanagedintegrations.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/iotsecuretunneling/pom.xml b/services/iotsecuretunneling/pom.xml index e34658d6b257..267f7a550dd9 100644 --- a/services/iotsecuretunneling/pom.xml +++ b/services/iotsecuretunneling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotsecuretunneling AWS Java SDK :: Services :: IoTSecureTunneling diff --git a/services/iotsecuretunneling/src/main/resources/codegen-resources/customization.config b/services/iotsecuretunneling/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotsecuretunneling/src/main/resources/codegen-resources/customization.config +++ b/services/iotsecuretunneling/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b74d60b56636 --- /dev/null +++ b/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,269 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iot-tunneling-fips.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iot-tunneling-fips.{Region}.api.amazonwebservices.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.tunneling.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.tunneling.iot-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iot-tunneling.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iot-tunneling.{Region}.api.amazonwebservices.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.tunneling.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.tunneling.iot.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 19, + "nodes": "/////wAAAAH/////AAAAAAAAABIAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAAsAAAAGAAAABAAAAAcF9eEOAAAABQAAAAgF9eENAAAABwX14QoAAAAJAAAACAX14QsAAAAKAAAACQX14QoF9eEMAAAABAAAAA0AAAAMAAAABgX14QgF9eEJAAAABQAAAA4F9eEHAAAABgAAAA8F9eEHAAAABwX14QQAAAAQAAAACAX14QUAAAARAAAACQX14QQF9eEGAAAAAwX14QEAAAATAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4f5b2ff6bbff..000000000000 --- a/services/iotsecuretunneling/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,464 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling-fips.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling-fips.{Region}.api.amazonwebservices.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling-fips.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.tunneling.iot-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.tunneling.iot-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling.{Region}.api.amazonwebservices.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.iot-tunneling.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.tunneling.iot.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.tunneling.iot.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotsitewise/pom.xml b/services/iotsitewise/pom.xml index 3bbd0e64d569..950cf9acef38 100644 --- a/services/iotsitewise/pom.xml +++ b/services/iotsitewise/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotsitewise AWS Java SDK :: Services :: Io T Site Wise diff --git a/services/iotsitewise/src/main/resources/codegen-resources/customization.config b/services/iotsitewise/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/iotsitewise/src/main/resources/codegen-resources/customization.config +++ b/services/iotsitewise/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/iotsitewise/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotsitewise/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7b930b4986c2 --- /dev/null +++ b/services/iotsitewise/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotsitewise-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotsitewise-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotsitewise.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotsitewise.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotsitewise/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotsitewise/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a508440d6fca..000000000000 --- a/services/iotsitewise/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotsitewise-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotsitewise-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotsitewise.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iotsitewise.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotsitewise/src/main/resources/codegen-resources/paginators-1.json b/services/iotsitewise/src/main/resources/codegen-resources/paginators-1.json index 5225464f4b61..ac7a5cf4c2a3 100644 --- a/services/iotsitewise/src/main/resources/codegen-resources/paginators-1.json +++ b/services/iotsitewise/src/main/resources/codegen-resources/paginators-1.json @@ -14,6 +14,12 @@ "output_token": "nextToken", "limit_key": "maxResults" }, + "DescribePipelineExecution": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "computeNodeExecutionDetails" + }, "ExecuteQuery": { "input_token": "nextToken", "output_token": "nextToken", @@ -38,6 +44,18 @@ "limit_key": "maxResults", "result_key": "interpolatedAssetPropertyValues" }, + "GetQueryResults": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "rows" + }, + "GetSearchResults": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "searchResults" + }, "ListAccessPolicies": { "input_token": "nextToken", "output_token": "nextToken", @@ -50,6 +68,12 @@ "limit_key": "maxResults", "result_key": "actionSummaries" }, + "ListApplications": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "applications" + }, "ListAssetModelCompositeModels": { "input_token": "nextToken", "output_token": "nextToken", @@ -128,12 +152,36 @@ "limit_key": "maxResults", "result_key": "dashboardSummaries" }, + "ListDatasetDataSegmentRelationships": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "dataSegmentRelationshipSummaries" + }, + "ListDatasetDataSegments": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "dataSegments" + }, + "ListDatasetExportJobs": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "jobs" + }, "ListDatasets": { "input_token": "nextToken", "output_token": "nextToken", "limit_key": "maxResults", "result_key": "datasetSummaries" }, + "ListEnrichmentJobs": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "jobs" + }, "ListExecutions": { "input_token": "nextToken", "output_token": "nextToken", @@ -152,6 +200,18 @@ "limit_key": "maxResults", "result_key": "interfaceRelationshipSummaries" }, + "ListPipelineExecutions": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "pipelineExecutionSummaries" + }, + "ListPipelines": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "pipelineSummaries" + }, "ListPortals": { "input_token": "nextToken", "output_token": "nextToken", @@ -170,11 +230,35 @@ "limit_key": "maxResults", "result_key": "projectSummaries" }, + "ListQueries": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "queries" + }, + "ListSearches": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "searchSummaries" + }, + "ListTasks": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "taskSummaries" + }, "ListTimeSeries": { "input_token": "nextToken", "output_token": "nextToken", "limit_key": "maxResults", "result_key": "TimeSeriesSummaries" + }, + "ListWorkspaces": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "workspaceSummaries" } } } diff --git a/services/iotsitewise/src/main/resources/codegen-resources/service-2.json b/services/iotsitewise/src/main/resources/codegen-resources/service-2.json index 162eb7910624..32153a382e8f 100644 --- a/services/iotsitewise/src/main/resources/codegen-resources/service-2.json +++ b/services/iotsitewise/src/main/resources/codegen-resources/service-2.json @@ -50,6 +50,26 @@ "documentation":"

    Associates a time series (data stream) with an asset property.

    ", "endpoint":{"hostPrefix":"api."} }, + "BatchAssociateDataSegmentsToDataset":{ + "name":"BatchAssociateDataSegmentsToDataset", + "http":{ + "method":"POST", + "requestUri":"/datasets/{datasetId}/data-segments/associate", + "responseCode":200 + }, + "input":{"shape":"BatchAssociateDataSegmentsToDatasetRequest"}, + "output":{"shape":"BatchAssociateDataSegmentsToDatasetResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Associates a batch of data segments with a curated dataset. Data segments are time-bounded slices of time series data selected from source session datasets. Data segments that belong to the same time series can't overlap in time, regardless of which dataset they belong to.

    ", + "endpoint":{"hostPrefix":"api."} + }, "BatchAssociateProjectAssets":{ "name":"BatchAssociateProjectAssets", "http":{ @@ -66,9 +86,46 @@ {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Associates a group (batch) of assets with an IoT SiteWise Monitor project.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Associates a group (batch) of assets with an IoT SiteWise Monitor project.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "BatchDeleteDatasetDataSegments":{ + "name":"BatchDeleteDatasetDataSegments", + "http":{ + "method":"POST", + "requestUri":"/datasets/{datasetId}/data-segments/batch-delete" + }, + "input":{"shape":"BatchDeleteDatasetDataSegmentsRequest"}, + "output":{"shape":"BatchDeleteDatasetDataSegmentsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictingOperationException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes a batch of data segments from a session dataset. Deleting a data segment deletes the underlying time series data for the segment's time range.

    ", + "endpoint":{"hostPrefix":"api."} + }, + "BatchDisassociateDataSegmentsFromDataset":{ + "name":"BatchDisassociateDataSegmentsFromDataset", + "http":{ + "method":"POST", + "requestUri":"/datasets/{datasetId}/data-segments/disassociate", + "responseCode":200 + }, + "input":{"shape":"BatchDisassociateDataSegmentsFromDatasetRequest"}, + "output":{"shape":"BatchDisassociateDataSegmentsFromDatasetResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Disassociates a batch of data segments from a curated dataset. Disassociating a data segment doesn't delete the underlying data in the source session dataset.

    ", + "endpoint":{"hostPrefix":"api."} + }, "BatchDisassociateProjectAssets":{ "name":"BatchDisassociateProjectAssets", "http":{ @@ -158,6 +215,69 @@ "documentation":"

    Sends a list of asset property values to IoT SiteWise. Each value is a timestamp-quality-value (TQV) data point. For more information, see Ingesting data using the API in the IoT SiteWise User Guide.

    To identify an asset property, you must specify one of the following:

    • The assetId and propertyId of an asset property.

    • A propertyAlias, which is a data stream alias (for example, /company/windfarm/3/turbine/7/temperature). To define an asset property's alias, see UpdateAssetProperty.

    With respect to Unix epoch time, IoT SiteWise accepts only TQVs that have a timestamp of no more than 7 days in the past and no more than 10 minutes in the future. IoT SiteWise rejects timestamps outside of the inclusive range of [-7 days, +10 minutes] and returns a TimestampOutOfRangeException error.

    For each asset property, IoT SiteWise overwrites TQVs with duplicate timestamps unless the newer TQV has a different quality. For example, if you store a TQV {T1, GOOD, V1}, then storing {T1, GOOD, V2} replaces the existing TQV.

    IoT SiteWise authorizes access to each BatchPutAssetPropertyValue entry individually. For more information, see BatchPutAssetPropertyValue authorization in the IoT SiteWise User Guide.

    ", "endpoint":{"hostPrefix":"data."} }, + "CancelEnrichmentJob":{ + "name":"CancelEnrichmentJob", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/enrichment-jobs/{jobId}/cancel", + "responseCode":200 + }, + "input":{"shape":"CancelEnrichmentJobRequest"}, + "output":{"shape":"CancelEnrichmentJobResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Cancels a running or pending enrichment job. This is an idempotent operation—calling it multiple times with the same jobId is safe and returns the current status.

    Behavior

    • Jobs in PENDING or RUNNING status transition to CANCELLED
    • Jobs in RUNNING state may not be cancellable once they have progressed to certain processing stages
    • Jobs already in terminal states (COMPLETED, FAILED, TIMED_OUT) cannot be cancelled; the operation returns a ConflictingOperationException
    • Cancelling an already-CANCELLED job is a no-op and returns the current status (idempotent behavior)
    • The API responds immediately after recording the cancellation
    • Cleanup of job resources happens asynchronously in the background

    When to Cancel

    Cancel a job when:

    • The job is taking longer than expected
    • The job was created with incorrect parameters
    • You no longer need the results

    Idempotency

    You can safely retry cancellation requests. Calling CancelEnrichmentJob multiple times for the same job returns the current status without error as long as the job is not in a terminal state other than CANCELLED.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, + "CancelPipelineExecution":{ + "name":"CancelPipelineExecution", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}/executions/{pipelineExecutionId}/cancel", + "responseCode":202 + }, + "input":{"shape":"CancelPipelineExecutionRequest"}, + "output":{"shape":"CancelPipelineExecutionResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Cancels a pipeline execution in the specified workspace. If the execution is not in a terminal state (such as NOT_STARTED or RUNNING), it transitions to CANCELLING and asynchronously to CANCELLED. This operation is idempotent: calling it on an execution that is already CANCELLING or CANCELLED returns success with the current state. Calling it on a terminal execution (SUCCEEDED or FAILED) returns a conflict error. You can optionally provide a reason; it is returned in the stateDetails field when you describe the execution.

    ", + "endpoint":{"hostPrefix":"data."} + }, + "CancelQuery":{ + "name":"CancelQuery", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/queries/{queryId}/cancel", + "responseCode":202 + }, + "input":{"shape":"CancelQueryRequest"}, + "output":{"shape":"CancelQueryResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Cancels a running query.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, "CreateAccessPolicy":{ "name":"CreateAccessPolicy", "http":{ @@ -174,9 +294,31 @@ {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Creates an access policy that grants the specified identity (IAM Identity Center user, IAM Identity Center group, or IAM user) access to the specified IoT SiteWise Monitor portal or project resource.

    Support for access policies that use an SSO Group as the identity is not supported at this time.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Creates an access policy that grants the specified identity (IAM Identity Center user, IAM Identity Center group, or IAM user) access to the specified IoT SiteWise Monitor portal or project resource.

    Support for access policies that use an SSO Group as the identity is not supported at this time.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "CreateApplication":{ + "name":"CreateApplication", + "http":{ + "method":"POST", + "requestUri":"/applications", + "responseCode":200 + }, + "input":{"shape":"CreateApplicationRequest"}, + "output":{"shape":"CreateApplicationResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Creates a new application for the workspace and IdC application provided

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "CreateAsset":{ "name":"CreateAsset", "http":{ @@ -259,7 +401,7 @@ {"shape":"LimitExceededException"}, {"shape":"ConflictingOperationException"} ], - "documentation":"

    Defines a job to ingest data to IoT SiteWise from Amazon S3. For more information, see Create a bulk import job (CLI) in the Amazon Simple Storage Service User Guide.

    Before you create a bulk import job, you must enable IoT SiteWise warm tier or IoT SiteWise cold tier. For more information about how to configure storage settings, see PutStorageConfiguration.

    Bulk import is designed to store historical data to IoT SiteWise.

    • Newly ingested data in the hot tier triggers notifications and computations.

    • After data moves from the hot tier to the warm or cold tier based on retention settings, it does not trigger computations or notifications.

    • Data older than 7 days does not trigger computations or notifications.

    ", + "documentation":"

    Defines a job to ingest data to IoT SiteWise from Amazon S3. For more information, see Create a bulk import job (CLI) in the Amazon Simple Storage Service User Guide.

    Before you create a bulk import job that ingests data into time series outside of a workspace, you must enable IoT SiteWise warm tier or IoT SiteWise cold tier. For more information about how to configure storage settings, see PutStorageConfiguration. This requirement doesn't apply to bulk import jobs that ingest data into a session dataset in a workspace (jobs that specify a workspaceName and datasetId). Those jobs don't use IoT SiteWise warm or cold tier storage.

    Bulk import is designed to store historical data to IoT SiteWise.

    • Newly ingested data in the hot tier triggers notifications and computations.

    • After data moves from the hot tier to the warm or cold tier based on retention settings, it does not trigger computations or notifications.

    • Data older than 7 days does not trigger computations or notifications.

    ", "endpoint":{"hostPrefix":"data."} }, "CreateComputationModel":{ @@ -299,7 +441,7 @@ {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Creates a dashboard in an IoT SiteWise Monitor project.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Creates a dashboard in an IoT SiteWise Monitor project.

    ", "endpoint":{"hostPrefix":"monitor."} }, "CreateDataset":{ @@ -320,9 +462,51 @@ {"shape":"LimitExceededException"}, {"shape":"ConflictingOperationException"} ], - "documentation":"

    Creates a dataset to connect an external datasource.

    ", + "documentation":"

    Creates a dataset. Session and curated datasets are created in a workspace. A session dataset contains data segments of time series data, and a curated dataset curates data segments selected from source session datasets. A dataset that connects to an external datasource is created outside of a workspace.

    ", "endpoint":{"hostPrefix":"api."} }, + "CreateDatasetExportJob":{ + "name":"CreateDatasetExportJob", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/dataset-export-jobs", + "responseCode":202 + }, + "input":{"shape":"CreateDatasetExportJobRequest"}, + "output":{"shape":"CreateDatasetExportJobResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Starts an asynchronous job that exports dataset and time-series data from a workspace to Amazon S3. The operation returns a jobId immediately; poll DescribeDatasetExportJob to track progress and ListDatasetExportJobs to enumerate a workspace's jobs.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, + "CreateEnrichmentJob":{ + "name":"CreateEnrichmentJob", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/enrichment-jobs", + "responseCode":200 + }, + "input":{"shape":"CreateEnrichmentJobRequest"}, + "output":{"shape":"CreateEnrichmentJobResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"LimitExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Creates an asynchronous enrichment job to analyze time-series sensor data. The operation returns immediately with job details while processing continues in the background.

    Idempotency

    Include a clientToken to make the operation idempotent. If you submit the same request with the same token within the idempotency window, you receive the original job details without creating a duplicate.

    Prerequisites

    Before creating a job, ensure:

    • The workspace is in ACTIVE state (not being deleted)
    • You have IAM permissions for the workspace, dataset, and time-series resources
    • You have KMS Decrypt permission on the workspace's customer-managed encryption key
    • No duplicate job (same workspace, dataset, property, and job type) is currently running

    Workflow

    1. Submit the job with configuration specifying which video data to analyze and the time range
    2. Capture the jobId from the response
    3. Use DescribeEnrichmentJob to monitor progress and check job status
    4. When status reaches a terminal state (COMPLETED, FAILED, TIMED_OUT, CANCELLED), check results
    5. For COMPLETED jobs, query IoT SiteWise for semantic search on video events

    Error Handling

    • ConflictingOperationException: A duplicate job is already running for the same configuration
    • InvalidRequestException: Invalid parameters (e.g., both timeSeriesId and propertyAlias specified)
    • AccessDeniedException: Insufficient IAM or KMS permissions
    • LimitExceededException: Too many concurrent jobs or requests
    ", + "endpoint":{"hostPrefix":"data."} + }, "CreateGateway":{ "name":"CreateGateway", "http":{ @@ -342,6 +526,28 @@ "documentation":"

    Creates a gateway, which is a virtual or edge device that delivers industrial data streams from local servers to IoT SiteWise. For more information, see Ingesting data using a gateway in the IoT SiteWise User Guide.

    ", "endpoint":{"hostPrefix":"api."} }, + "CreatePipeline":{ + "name":"CreatePipeline", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/pipelines", + "responseCode":200 + }, + "input":{"shape":"CreatePipelineRequest"}, + "output":{"shape":"CreatePipelineResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Creates a new pipeline in the specified workspace. A pipeline defines a directed acyclic graph (DAG) of compute nodes, where each node references a task and can declare dependencies on other nodes. Cyclic dependencies are not allowed. Nodes without dependencies run in parallel, while nodes with dependencies wait for all upstream nodes to complete successfully before starting.

    You can set environment variables at the pipeline level that are shared across all compute nodes, and override them at the individual compute node level.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "CreatePortal":{ "name":"CreatePortal", "http":{ @@ -358,7 +564,7 @@ {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Creates a portal, which can contain projects and dashboards. IoT SiteWise Monitor uses IAM Identity Center or IAM to authenticate portal users and manage user permissions.

    Before you can sign in to a new portal, you must add at least one identity to that portal. For more information, see Adding or removing portal administrators in the IoT SiteWise User Guide.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Creates a portal, which can contain projects and dashboards. IoT SiteWise Monitor uses IAM Identity Center or IAM to authenticate portal users and manage user permissions.

    Before you can sign in to a new portal, you must add at least one identity to that portal. For more information, see Adding or removing portal administrators in the IoT SiteWise User Guide.

    ", "endpoint":{"hostPrefix":"monitor."} }, "CreateProject":{ @@ -377,9 +583,50 @@ {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Creates a project in the specified portal.

    Make sure that the project name and description don't contain confidential information.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Creates a project in the specified portal.

    Make sure that the project name and description don't contain confidential information.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "CreateTask":{ + "name":"CreateTask", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/tasks", + "responseCode":200 + }, + "input":{"shape":"CreateTaskRequest"}, + "output":{"shape":"CreateTaskResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Creates a new task in the specified workspace. A task defines a reusable containerized compute workload that can be referenced by one or more pipeline compute nodes.

    Specify a containerTaskConfiguration for custom container workloads with configurable ECR image, processing type, processing unit, and environment variables.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, + "CreateWorkspace":{ + "name":"CreateWorkspace", + "http":{ + "method":"POST", + "requestUri":"/workspaces" + }, + "input":{"shape":"CreateWorkspaceRequest"}, + "output":{"shape":"CreateWorkspaceResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ConflictingOperationException"}, + {"shape":"LimitExceededException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Creates a workspace in IoT SiteWise. A workspace isolates its resources, such as datasets, time series, pipelines, and tasks, and their data from other workspaces, and has its own quotas and throttling limits. You must specify an encryption configuration when you create a workspace. The operation returns immediately with the workspace in the CREATING state. Provisioning completes asynchronously, after which the workspace state is ACTIVE, or FAILED if provisioning doesn't complete.

    ", + "endpoint":{"hostPrefix":"api."} + }, "DeleteAccessPolicy":{ "name":"DeleteAccessPolicy", "http":{ @@ -398,6 +645,27 @@ "documentation":"

    Deletes an access policy that grants the specified identity access to the specified IoT SiteWise Monitor resource. You can use this operation to revoke access to an IoT SiteWise Monitor resource.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "DeleteApplication":{ + "name":"DeleteApplication", + "http":{ + "method":"DELETE", + "requestUri":"/workspaces/{workspaceName}/applications/{id}", + "responseCode":204 + }, + "input":{"shape":"DeleteApplicationRequest"}, + "output":{"shape":"DeleteApplicationResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Deletes an application by ID

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "DeleteAsset":{ "name":"DeleteAsset", "http":{ @@ -529,7 +797,7 @@ {"shape":"ThrottlingException"}, {"shape":"ConflictingOperationException"} ], - "documentation":"

    Deletes a dataset. This cannot be undone.

    ", + "documentation":"

    Deletes a dataset. This can't be undone. Deleting a session dataset also deletes the underlying time series data in the session. You can't delete a session dataset while a curated dataset references its data segments. First delete the curated dataset or disassociate the data segments. Deleting a curated dataset doesn't delete the underlying data in the source session datasets.

    ", "endpoint":{"hostPrefix":"api."} }, "DeleteGateway":{ @@ -549,6 +817,27 @@ "documentation":"

    Deletes a gateway from IoT SiteWise. When you delete a gateway, some of the gateway's files remain in your gateway's file system.

    ", "endpoint":{"hostPrefix":"api."} }, + "DeletePipeline":{ + "name":"DeletePipeline", + "http":{ + "method":"DELETE", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}", + "responseCode":200 + }, + "input":{"shape":"DeletePipelineRequest"}, + "output":{"shape":"DeletePipelineResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Deletes a pipeline from the specified workspace. A pipeline cannot be deleted if it has any active executions. Wait for all executions to complete before attempting to delete the pipeline, or use CancelPipelineExecution to stop a running execution.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "DeletePortal":{ "name":"DeletePortal", "http":{ @@ -586,6 +875,27 @@ "documentation":"

    Deletes a project from IoT SiteWise Monitor.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "DeleteTask":{ + "name":"DeleteTask", + "http":{ + "method":"DELETE", + "requestUri":"/workspaces/{workspaceName}/tasks/{taskName}", + "responseCode":200 + }, + "input":{"shape":"DeleteTaskRequest"}, + "output":{"shape":"DeleteTaskResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Deletes a task from the specified workspace. A task cannot be deleted if it is currently referenced by any existing pipeline. Remove the task from all pipelines before attempting to delete it.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "DeleteTimeSeries":{ "name":"DeleteTimeSeries", "http":{ @@ -600,9 +910,29 @@ {"shape":"ThrottlingException"}, {"shape":"ConflictingOperationException"} ], - "documentation":"

    Deletes a time series (data stream). If you delete a time series that's associated with an asset property, the asset property still exists, but the time series will no longer be associated with this asset property.

    To identify a time series, do one of the following:

    • If the time series isn't associated with an asset property, specify the alias of the time series.

    • If the time series is associated with an asset property, specify one of the following:

      • The alias of the time series.

      • The assetId and propertyId that identifies the asset property.

    ", + "documentation":"

    Deletes a time series (data stream). If you delete a time series that's associated with an asset property, the asset property still exists, but the time series will no longer be associated with this asset property. You can't delete a time series until all of its data segments have been deleted from session datasets.

    To identify a time series, do one of the following:

    • If the time series isn't associated with an asset property, specify the alias of the time series.

    • If the time series is associated with an asset property, specify one of the following:

      • The alias of the time series.

      • The assetId and propertyId that identifies the asset property.

    ", "endpoint":{"hostPrefix":"api."} }, + "DeleteWorkspace":{ + "name":"DeleteWorkspace", + "http":{ + "method":"DELETE", + "requestUri":"/workspaces/{workspaceName}" + }, + "input":{"shape":"DeleteWorkspaceRequest"}, + "output":{"shape":"DeleteWorkspaceResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ConflictingOperationException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Deletes a workspace. Before you delete a workspace, you must delete all resources contained in or associated with the workspace, such as datasets, time series, pipelines, and tasks.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "DescribeAccessPolicy":{ "name":"DescribeAccessPolicy", "http":{ @@ -638,6 +968,26 @@ "documentation":"

    Retrieves information about an action.

    ", "endpoint":{"hostPrefix":"api."} }, + "DescribeApplication":{ + "name":"DescribeApplication", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/applications/{id}", + "responseCode":200 + }, + "input":{"shape":"DescribeApplicationRequest"}, + "output":{"shape":"DescribeApplicationResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Retrieves Application details based on the ID

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "DescribeAsset":{ "name":"DescribeAsset", "http":{ @@ -826,6 +1176,26 @@ "documentation":"

    Retrieves information about a dataset.

    ", "endpoint":{"hostPrefix":"api."} }, + "DescribeDatasetExportJob":{ + "name":"DescribeDatasetExportJob", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/dataset-export-jobs/{jobId}", + "responseCode":200 + }, + "input":{"shape":"DescribeDatasetExportJobRequest"}, + "output":{"shape":"DescribeDatasetExportJobResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves information about a dataset export job.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "DescribeDefaultEncryptionConfiguration":{ "name":"DescribeDefaultEncryptionConfiguration", "http":{ @@ -836,12 +1206,35 @@ "output":{"shape":"DescribeDefaultEncryptionConfigurationResponse"}, "errors":[ {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Retrieves information about the default encryption configuration for the Amazon Web Services account in the default or specified Region. For more information, see Key management in the IoT SiteWise User Guide.

    ", "endpoint":{"hostPrefix":"api."} }, + "DescribeEnrichmentJob":{ + "name":"DescribeEnrichmentJob", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/enrichment-jobs/{jobId}", + "responseCode":200 + }, + "input":{"shape":"DescribeEnrichmentJobRequest"}, + "output":{"shape":"DescribeEnrichmentJobResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Retrieves detailed information about a specific enrichment job, including its current status, configuration, and timestamps.

    Use Cases

    • Monitor job progress by checking status updates with DescribeEnrichmentJob
    • Retrieve the complete job configuration submitted during creation
    • Debug failed jobs by examining the failureMessage field
    • Track job lifecycle with creation, update, completion, and cancellation timestamps

    Status Monitoring

    Jobs progress through statuses: PENDING → RUNNING → terminal state

    Terminal states:

    • COMPLETED: Job finished successfully; query IoT SiteWise for semantic search results
    • FAILED: Job encountered an error; check failureMessage for details
    • TIMED_OUT: Job exceeded maximum processing time
    • CANCELLED: Job was cancelled via CancelEnrichmentJob

    Response Fields

    The response includes:

    • Current job status and type
    • Full job configuration as originally submitted
    • Lifecycle timestamps (created, updated, completed, cancelled)
    • Failure details if status is FAILED
    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "DescribeExecution":{ "name":"DescribeExecution", "http":{ @@ -910,15 +1303,55 @@ "documentation":"

    Retrieves the current IoT SiteWise logging options.

    ", "endpoint":{"hostPrefix":"api."} }, - "DescribePortal":{ - "name":"DescribePortal", + "DescribePipeline":{ + "name":"DescribePipeline", "http":{ "method":"GET", - "requestUri":"/portals/{portalId}", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}", "responseCode":200 }, - "input":{"shape":"DescribePortalRequest"}, - "output":{"shape":"DescribePortalResponse"}, + "input":{"shape":"DescribePipelineRequest"}, + "output":{"shape":"DescribePipelineResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific pipeline in a workspace.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, + "DescribePipelineExecution":{ + "name":"DescribePipelineExecution", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}/executions/{pipelineExecutionId}", + "responseCode":200 + }, + "input":{"shape":"DescribePipelineExecutionRequest"}, + "output":{"shape":"DescribePipelineExecutionResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific pipeline execution, including the overall execution status and the status of each individual compute node. Use this operation to monitor execution progress and inspect per-node results, environment variables, and error details.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, + "DescribePortal":{ + "name":"DescribePortal", + "http":{ + "method":"GET", + "requestUri":"/portals/{portalId}", + "responseCode":200 + }, + "input":{"shape":"DescribePortalRequest"}, + "output":{"shape":"DescribePortalResponse"}, "errors":[ {"shape":"InvalidRequestException"}, {"shape":"ResourceNotFoundException"}, @@ -946,6 +1379,46 @@ "documentation":"

    Retrieves information about a project.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "DescribeQuery":{ + "name":"DescribeQuery", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/queries/{queryId}", + "responseCode":200 + }, + "input":{"shape":"DescribeQueryRequest"}, + "output":{"shape":"DescribeQueryResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves information about a query, including its status.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, + "DescribeSearch":{ + "name":"DescribeSearch", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/searches/{searchId}", + "responseCode":200 + }, + "input":{"shape":"DescribeSearchRequest"}, + "output":{"shape":"DescribeSearchResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns the current status and metadata of a single search, including the query that was submitted, the search type, and — when the search has failed — the reason. Use this to poll a search started with StartSearch until it reaches a terminal status (SUCCEEDED or FAILED).

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "DescribeStorageConfiguration":{ "name":"DescribeStorageConfiguration", "http":{ @@ -965,6 +1438,26 @@ "documentation":"

    Retrieves information about the storage configuration for IoT SiteWise.

    ", "endpoint":{"hostPrefix":"api."} }, + "DescribeTask":{ + "name":"DescribeTask", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/tasks/{taskName}", + "responseCode":200 + }, + "input":{"shape":"DescribeTaskRequest"}, + "output":{"shape":"DescribeTaskResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific task in a workspace.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "DescribeTimeSeries":{ "name":"DescribeTimeSeries", "http":{ @@ -982,6 +1475,25 @@ "documentation":"

    Retrieves information about a time series (data stream).

    To identify a time series, do one of the following:

    • If the time series isn't associated with an asset property, specify the alias of the time series.

    • If the time series is associated with an asset property, specify one of the following:

      • The alias of the time series.

      • The assetId and propertyId that identifies the asset property.

    ", "endpoint":{"hostPrefix":"api."} }, + "DescribeWorkspace":{ + "name":"DescribeWorkspace", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}" + }, + "input":{"shape":"DescribeWorkspaceRequest"}, + "output":{"shape":"DescribeWorkspaceResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Retrieves information about a workspace.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "DisassociateAssets":{ "name":"DisassociateAssets", "http":{ @@ -1110,6 +1622,26 @@ "documentation":"

    Gets the history of an asset property's values. For more information, see Querying historical values in the IoT SiteWise User Guide.

    To identify an asset property, you must specify one of the following:

    • The assetId and propertyId of an asset property.

    • A propertyAlias, which is a data stream alias (for example, /company/windfarm/3/turbine/7/temperature). To define an asset property's alias, see UpdateAssetProperty.

    ", "endpoint":{"hostPrefix":"data."} }, + "GetCaptureData":{ + "name":"GetCaptureData", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/get-capture-data", + "responseCode":200 + }, + "input":{"shape":"GetCaptureDataRequest"}, + "output":{"shape":"GetCaptureDataResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves video data for a specific time range.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "GetInterpolatedAssetPropertyValues":{ "name":"GetInterpolatedAssetPropertyValues", "http":{ @@ -1128,6 +1660,46 @@ "documentation":"

    Get interpolated values for an asset property for a specified time interval, during a period of time. If your time series is missing data points during the specified time interval, you can use interpolation to estimate the missing data.

    For example, you can use this operation to return the interpolated temperature values for a wind turbine every 24 hours over a duration of 7 days.

    To identify an asset property, you must specify one of the following:

    • The assetId and propertyId of an asset property.

    • A propertyAlias, which is a data stream alias (for example, /company/windfarm/3/turbine/7/temperature). To define an asset property's alias, see UpdateAssetProperty.

    ", "endpoint":{"hostPrefix":"data."} }, + "GetQueryResults":{ + "name":"GetQueryResults", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/queries/{queryId}/results", + "responseCode":200 + }, + "input":{"shape":"GetQueryResultsRequest"}, + "output":{"shape":"GetQueryResultsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the paginated results of a query. Returns empty rows if the query is not yet complete.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, + "GetSearchResults":{ + "name":"GetSearchResults", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/searches/{searchId}/results", + "responseCode":200 + }, + "input":{"shape":"GetSearchResultsRequest"}, + "output":{"shape":"GetSearchResultsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the ranked results of a search, ordered by descending relevance score. Results are available only after the search has reached the SUCCEEDED status. Calling this on a search that exists but has not yet completed returns InvalidRequestException, while calling it on a search that does not exist returns ResourceNotFoundException. The response is paginated: when nextToken is present, pass it on a subsequent call to retrieve the next page.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "InvokeAssistant":{ "name":"InvokeAssistant", "http":{ @@ -1183,6 +1755,26 @@ "documentation":"

    Retrieves a paginated list of actions for a specific target resource.

    ", "endpoint":{"hostPrefix":"api."} }, + "ListApplications":{ + "name":"ListApplications", + "http":{ + "method":"GET", + "requestUri":"/applications", + "responseCode":200 + }, + "input":{"shape":"ListApplicationsRequest"}, + "output":{"shape":"ListApplicationsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves a paginated list of existing applications

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "ListAssetModelCompositeModels":{ "name":"ListAssetModelCompositeModels", "http":{ @@ -1227,6 +1819,7 @@ "output":{"shape":"ListAssetModelsResponse"}, "errors":[ {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], @@ -1401,6 +1994,62 @@ "documentation":"

    Retrieves a paginated list of dashboards for an IoT SiteWise Monitor project.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "ListDatasetDataSegmentRelationships":{ + "name":"ListDatasetDataSegmentRelationships", + "http":{ + "method":"GET", + "requestUri":"/datasets/{datasetId}/data-segment-relationships" + }, + "input":{"shape":"ListDatasetDataSegmentRelationshipsRequest"}, + "output":{"shape":"ListDatasetDataSegmentRelationshipsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves a paginated list of data segment relationships for a session dataset. Use this operation to find the curated datasets that reference data segments of the specified session dataset. Use the nextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, + "ListDatasetDataSegments":{ + "name":"ListDatasetDataSegments", + "http":{ + "method":"GET", + "requestUri":"/datasets/{datasetId}/data-segments" + }, + "input":{"shape":"ListDatasetDataSegmentsRequest"}, + "output":{"shape":"ListDatasetDataSegmentsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves a paginated list of data segments associated with a dataset. Use the nextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, + "ListDatasetExportJobs":{ + "name":"ListDatasetExportJobs", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/dataset-export-jobs", + "responseCode":200 + }, + "input":{"shape":"ListDatasetExportJobsRequest"}, + "output":{"shape":"ListDatasetExportJobsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves a paginated list of dataset export jobs for a workspace.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "ListDatasets":{ "name":"ListDatasets", "http":{ @@ -1411,12 +2060,35 @@ "output":{"shape":"ListDatasetsResponse"}, "errors":[ {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Retrieves a paginated list of datasets for a specific target resource.

    ", "endpoint":{"hostPrefix":"api."} }, + "ListEnrichmentJobs":{ + "name":"ListEnrichmentJobs", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/enrichment-jobs", + "responseCode":200 + }, + "input":{"shape":"ListEnrichmentJobsRequest"}, + "output":{"shape":"ListEnrichmentJobsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Lists enrichment jobs within a workspace with optional filtering and pagination. Results are ordered by createdAt timestamp descending (newest first).

    Filtering

    Combine filters to narrow results:

    • datasetId: Filter by dataset
    • propertyAlias OR timeSeriesId: Filter by time series (specify one, not both)
    • status: Filter by job status (e.g., RUNNING to find active jobs)
    • jobType: Filter by enrichment type (currently only EVENT_DETECTION)
    • startDate and endDate: Filter by job creation time range

    Important Constraints

    • You must specify either propertyAlias OR timeSeriesId, but not both
    • Attempting to specify both results in an InvalidRequestException
    • Date filters use ISO 8601 format
    • startDate is exclusive, endDate is inclusive

    Pagination

    The operation returns up to maxResults jobs per page (default 50). If more results exist, the response includes a nextToken. Submit this token in a subsequent request to retrieve the next page.

    Common Use Cases

    • Find all running jobs: Filter by status=RUNNING
    • List recent jobs for a dataset: Filter by datasetId with optional date range
    • Monitor jobs for a specific sensor: Filter by propertyAlias or timeSeriesId
    • Track all event detection jobs: Filter by jobType=EVENT_DETECTION

    Performance

    Performance is optimal when filtering by supported fields (datasetId, propertyAlias, timeSeriesId, status, jobType).

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "ListExecutions":{ "name":"ListExecutions", "http":{ @@ -1467,6 +2139,46 @@ "documentation":"

    Retrieves a paginated list of asset models that have a specific interface asset model applied to them.

    ", "endpoint":{"hostPrefix":"api."} }, + "ListPipelineExecutions":{ + "name":"ListPipelineExecutions", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}/executions", + "responseCode":200 + }, + "input":{"shape":"ListPipelineExecutionsRequest"}, + "output":{"shape":"ListPipelineExecutionsResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists pipeline executions for a specific pipeline in a workspace. Supports filtering by state and time range. State can be combined with either startTime or endTime filters. Time range filters are grouped: use startTime filters (startTimeAfter, startTimeBefore) or endTime filters (endTimeAfter, endTimeBefore), but not both. Combining startTime and endTime filters returns an InvalidRequestException. Note: endTime filters only return executions in terminal states, as in-progress executions have no endTime.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, + "ListPipelines":{ + "name":"ListPipelines", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/pipelines", + "responseCode":200 + }, + "input":{"shape":"ListPipelinesRequest"}, + "output":{"shape":"ListPipelinesResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists pipelines in a workspace. To get complete details about a pipeline, use DescribePipeline.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "ListPortals":{ "name":"ListPortals", "http":{ @@ -1518,6 +2230,46 @@ "documentation":"

    Retrieves a paginated list of projects for an IoT SiteWise Monitor portal.

    ", "endpoint":{"hostPrefix":"monitor."} }, + "ListQueries":{ + "name":"ListQueries", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/queries", + "responseCode":200 + }, + "input":{"shape":"ListQueriesRequest"}, + "output":{"shape":"ListQueriesResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves a paginated list of queries for a workspace.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, + "ListSearches":{ + "name":"ListSearches", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/searches/list", + "responseCode":200 + }, + "input":{"shape":"ListSearchesRequest"}, + "output":{"shape":"ListSearchesResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the searches in a workspace, most recently started first. Results can be narrowed with optional filters (status, search type, group, and started-at time range) and are paginated: when nextToken is present, pass it on a subsequent call to retrieve the next page.

    ", + "endpoint":{"hostPrefix":"data."}, + "readonly":true + }, "ListTagsForResource":{ "name":"ListTagsForResource", "http":{ @@ -1538,6 +2290,26 @@ "documentation":"

    Retrieves the list of tags for an IoT SiteWise resource.

    ", "endpoint":{"hostPrefix":"api."} }, + "ListTasks":{ + "name":"ListTasks", + "http":{ + "method":"GET", + "requestUri":"/workspaces/{workspaceName}/tasks", + "responseCode":200 + }, + "input":{"shape":"ListTasksRequest"}, + "output":{"shape":"ListTasksResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists tasks in a workspace. To get complete details about a task, use DescribeTask.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "ListTimeSeries":{ "name":"ListTimeSeries", "http":{ @@ -1555,6 +2327,24 @@ "documentation":"

    Retrieves a paginated list of time series (data streams).

    ", "endpoint":{"hostPrefix":"api."} }, + "ListWorkspaces":{ + "name":"ListWorkspaces", + "http":{ + "method":"GET", + "requestUri":"/workspaces" + }, + "input":{"shape":"ListWorkspacesRequest"}, + "output":{"shape":"ListWorkspacesResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Retrieves a paginated list of workspaces. Use the nextToken parameter to retrieve additional results.

    ", + "endpoint":{"hostPrefix":"api."}, + "readonly":true + }, "PutAssetModelInterfaceRelationship":{ "name":"PutAssetModelInterfaceRelationship", "http":{ @@ -1585,6 +2375,7 @@ "output":{"shape":"PutDefaultEncryptionConfigurationResponse"}, "errors":[ {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"}, {"shape":"LimitExceededException"}, @@ -1631,25 +2422,90 @@ "documentation":"

    Configures storage settings for IoT SiteWise.

    ", "endpoint":{"hostPrefix":"api."} }, - "TagResource":{ - "name":"TagResource", + "StartPipelineExecution":{ + "name":"StartPipelineExecution", "http":{ "method":"POST", - "requestUri":"/tags" + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}/executions", + "responseCode":202 }, - "input":{"shape":"TagResourceRequest"}, - "output":{"shape":"TagResourceResponse"}, + "input":{"shape":"StartPipelineExecutionRequest"}, + "output":{"shape":"StartPipelineExecutionResponse"}, "errors":[ - {"shape":"InvalidRequestException"}, {"shape":"InternalFailureException"}, - {"shape":"ThrottlingException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictingOperationException"}, + {"shape":"AccessDeniedException"}, {"shape":"LimitExceededException"}, - {"shape":"UnauthorizedException"}, - {"shape":"TooManyTagsException"} - ], - "documentation":"

    Adds tags to an IoT SiteWise resource. If a tag already exists for the resource, this operation updates the tag's value.

    ", + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Starts execution of a pipeline in the specified workspace. Each compute node runs according to the DAG dependency order defined in the pipeline. Nodes without dependencies start immediately, while dependent nodes wait for all upstream nodes to complete successfully.

    You can provide runtime environment variable overrides that take the highest priority in the environment variable hierarchy, without modifying the pipeline definition.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, + "StartQuery":{ + "name":"StartQuery", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/queries", + "responseCode":202 + }, + "input":{"shape":"StartQueryRequest"}, + "output":{"shape":"StartQueryResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Starts an asynchronous SQL query against workspace telemetry, annotations, data segment, and dataset data.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, + "StartSearch":{ + "name":"StartSearch", + "http":{ + "method":"POST", + "requestUri":"/workspaces/{workspaceName}/searches", + "responseCode":202 + }, + "input":{"shape":"StartSearchRequest"}, + "output":{"shape":"StartSearchResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"LimitExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Starts an asynchronous search over the data in a workspace. The search runs in the background; the response returns immediately with a searchId and an initial status of QUEUED. Use DescribeSearch to poll for completion and GetSearchResults to retrieve the results once the search reaches SUCCEEDED. The request is idempotent on clientToken: repeating a call with the same token returns the original search instead of starting a new one.

    ", + "endpoint":{"hostPrefix":"data."}, + "idempotent":true + }, + "TagResource":{ + "name":"TagResource", + "http":{ + "method":"POST", + "requestUri":"/tags" + }, + "input":{"shape":"TagResourceRequest"}, + "output":{"shape":"TagResourceResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictingOperationException"}, + {"shape":"LimitExceededException"}, + {"shape":"UnauthorizedException"}, + {"shape":"TooManyTagsException"} + ], + "documentation":"

    Adds tags to an IoT SiteWise resource. If a tag already exists for the resource, this operation updates the tag's value.

    ", "endpoint":{"hostPrefix":"api."} }, "UntagResource":{ @@ -1687,7 +2543,7 @@ {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Updates an existing access policy that specifies an identity's access to an IoT SiteWise Monitor portal or project resource.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Updates an existing access policy that specifies an identity's access to an IoT SiteWise Monitor portal or project resource.

    ", "endpoint":{"hostPrefix":"monitor."} }, "UpdateAsset":{ @@ -1807,7 +2663,7 @@ {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Updates an IoT SiteWise Monitor dashboard.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Updates an IoT SiteWise Monitor dashboard.

    ", "endpoint":{"hostPrefix":"monitor."} }, "UpdateDataset":{ @@ -1821,6 +2677,7 @@ "output":{"shape":"UpdateDatasetResponse"}, "errors":[ {"shape":"InvalidRequestException"}, + {"shape":"ResourceAlreadyExistsException"}, {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"}, {"shape":"LimitExceededException"}, @@ -1867,6 +2724,28 @@ "documentation":"

    Updates a gateway capability configuration or defines a new capability configuration. Each gateway capability defines data sources for a gateway.

    Important workflow notes:

    Each gateway capability defines data sources for a gateway. This is the namespace of the gateway capability.

    . The namespace follows the format service:capability:version, where:

    • service - The service providing the capability, or iotsitewise.

    • capability - The specific capability type. Options include: opcuacollector for the OPC UA data source collector, or publisher for data publisher capability.

    • version - The version number of the capability. Option include 2 for Classic streams, V2 gateways, and 3 for MQTT-enabled, V3 gateways.

    After updating a capability configuration, the sync status becomes OUT_OF_SYNC until the gateway processes the configuration.Use DescribeGatewayCapabilityConfiguration to check the sync status and verify the configuration was applied.

    A gateway can have multiple capability configurations with different namespaces.

    ", "endpoint":{"hostPrefix":"api."} }, + "UpdatePipeline":{ + "name":"UpdatePipeline", + "http":{ + "method":"PUT", + "requestUri":"/workspaces/{workspaceName}/pipelines/{pipelineName}", + "responseCode":200 + }, + "input":{"shape":"UpdatePipelineRequest"}, + "output":{"shape":"UpdatePipelineResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Updates an existing pipeline in the specified workspace. Only the fields provided in the request are updated; fields not included in the request are preserved unchanged. You can update the pipeline description, environment variables, and the list of compute nodes independently.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, "UpdatePortal":{ "name":"UpdatePortal", "http":{ @@ -1883,7 +2762,7 @@ {"shape":"ThrottlingException"}, {"shape":"ConflictingOperationException"} ], - "documentation":"

    Updates an IoT SiteWise Monitor portal.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Updates an IoT SiteWise Monitor portal.

    ", "endpoint":{"hostPrefix":"monitor."} }, "UpdateProject":{ @@ -1901,8 +2780,49 @@ {"shape":"InternalFailureException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Updates an IoT SiteWise Monitor project.

    ", + "documentation":"

    The IoT SiteWise Monitor feature will no longer be open to new customers starting November 7, 2025. If you would like to use the IoT SiteWise Monitor feature, sign up prior to that date. Existing customers can continue to use the service as normal. For more information, see IoT SiteWise Monitor availability change.

    Updates an IoT SiteWise Monitor project.

    ", "endpoint":{"hostPrefix":"monitor."} + }, + "UpdateTask":{ + "name":"UpdateTask", + "http":{ + "method":"PUT", + "requestUri":"/workspaces/{workspaceName}/tasks/{taskName}", + "responseCode":200 + }, + "input":{"shape":"UpdateTaskRequest"}, + "output":{"shape":"UpdateTaskResponse"}, + "errors":[ + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"ConflictingOperationException"} + ], + "documentation":"

    Updates an existing task in the specified workspace. Only the fields provided in the request are updated; fields not included in the request are preserved unchanged.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true + }, + "UpdateWorkspace":{ + "name":"UpdateWorkspace", + "http":{ + "method":"PUT", + "requestUri":"/workspaces/{workspaceName}" + }, + "input":{"shape":"UpdateWorkspaceRequest"}, + "output":{"shape":"UpdateWorkspaceResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidRequestException"}, + {"shape":"ConflictingOperationException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Updates a workspace. You can update only workspaces in the ACTIVE or FAILED state. Fields that you omit from the request are left unchanged. To recover a workspace in the FAILED state, call this operation and supply its encryption configuration again.

    ", + "endpoint":{"hostPrefix":"api."}, + "idempotent":true } }, "shapes":{ @@ -2123,6 +3043,84 @@ "max":1011, "min":1 }, + "Annotation":{ + "type":"structure", + "members":{}, + "documentation":"

    The annotation format configuration for bulk import files.

    " + }, + "ApplicationDescription":{ + "type":"string", + "documentation":"

    Description of the application

    ", + "max":2048, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, + "ApplicationId":{ + "type":"string", + "documentation":"

    Unique identifier for the application

    ", + "max":36, + "min":36, + "pattern":"[a-z0-9-]{36}" + }, + "ApplicationList":{ + "type":"list", + "member":{"shape":"ApplicationSummary"}, + "documentation":"

    List of applications

    " + }, + "ApplicationName":{ + "type":"string", + "documentation":"

    Name of the application

    ", + "max":256, + "min":1, + "pattern":"[A-Za-z0-9](?:[A-Za-z0-9 ._()\\-]*[A-Za-z0-9._()\\-])?" + }, + "ApplicationStatus":{ + "type":"string", + "documentation":"

    Current status of the application

    ", + "enum":[ + "CREATING", + "ACTIVE", + "DELETING" + ] + }, + "ApplicationSummary":{ + "type":"structure", + "required":[ + "arn", + "id", + "name", + "status", + "createdAt", + "workspaceName" + ], + "members":{ + "arn":{ + "shape":"ARN", + "documentation":"

    ARN of the application

    " + }, + "id":{ + "shape":"ApplicationId", + "documentation":"

    Unique identifier of the application

    " + }, + "name":{ + "shape":"ApplicationName", + "documentation":"

    Name of the application

    " + }, + "status":{ + "shape":"ApplicationStatus", + "documentation":"

    Current status of the application

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the application was created

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    Name of the workspace this application belongs to

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

    Summary of an application for list operations

    " + }, "AssetBindingValueFilter":{ "type":"structure", "required":["assetId"], @@ -2531,7 +3529,7 @@ }, "dataType":{ "shape":"PropertyDataType", - "documentation":"

    The data type of the asset model property.

    If you specify STRUCT, you must also specify dataTypeSpec to identify the type of the structure for this property.

    " + "documentation":"

    The data type of the asset model property.

    The VIDEO, ANNOTATION, and JSON data types aren't supported for asset model properties. These types are used only by time series that store data for datasets in a workspace.

    If you specify STRUCT, you must also specify dataTypeSpec to identify the type of the structure for this property.

    " }, "dataTypeSpec":{ "shape":"Name", @@ -2610,7 +3608,7 @@ }, "dataType":{ "shape":"PropertyDataType", - "documentation":"

    The data type of the property definition.

    If you specify STRUCT, you must also specify dataTypeSpec to identify the type of the structure for this property.

    " + "documentation":"

    The data type of the property definition.

    The VIDEO, ANNOTATION, and JSON data types aren't supported for asset model properties. These types are used only by time series that store data for datasets in a workspace.

    If you specify STRUCT, you must also specify dataTypeSpec to identify the type of the structure for this property.

    " }, "dataTypeSpec":{ "shape":"Name", @@ -3119,6 +4117,38 @@ } } }, + "AssociateDataSegmentEntries":{ + "type":"list", + "member":{"shape":"AssociateDataSegmentEntry"} + }, + "AssociateDataSegmentEntry":{ + "type":"structure", + "required":[ + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp" + ], + "members":{ + "sourceDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the source dataset that contains the data segment.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment to associate.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment to associate.

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

    Contains information about a data segment entry to associate with a dataset.

    " + }, "AssociateTimeSeriesToAssetPropertyRequest":{ "type":"structure", "required":[ @@ -3229,6 +4259,57 @@ "SSO" ] }, + "BatchAssociateDataSegmentsToDatasetRequest":{ + "type":"structure", + "required":[ + "datasetId", + "workspaceName", + "associateDataSegmentEntries" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the curated dataset to associate data segments with.

    ", + "location":"uri", + "locationName":"datasetId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    " + }, + "associateDataSegmentEntries":{ + "shape":"AssociateDataSegmentEntries", + "documentation":"

    The list of data segment entries to associate with the dataset.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true + } + } + }, + "BatchAssociateDataSegmentsToDatasetResponse":{ + "type":"structure", + "required":[ + "datasetId", + "datasetVersion", + "failedAssociations" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the dataset.

    " + }, + "datasetVersion":{ + "shape":"Version", + "documentation":"

    The version of the dataset after association.

    " + }, + "failedAssociations":{ + "shape":"FailedDataSegmentAssociations", + "documentation":"

    A list of data segment associations that failed.

    " + } + } + }, "BatchAssociateProjectAssetsErrors":{ "type":"list", "member":{"shape":"AssetErrorDetails"} @@ -3266,6 +4347,108 @@ } } }, + "BatchDeleteDatasetDataSegmentsRequest":{ + "type":"structure", + "required":[ + "datasetId", + "workspaceName", + "deleteDataSegmentEntries" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the session dataset from which to delete data segments.

    ", + "location":"uri", + "locationName":"datasetId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    " + }, + "deleteDataSegmentEntries":{ + "shape":"DeleteDataSegmentEntries", + "documentation":"

    The list of data segment entries to delete.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true + } + } + }, + "BatchDeleteDatasetDataSegmentsResponse":{ + "type":"structure", + "required":[ + "datasetId", + "datasetVersion", + "errors" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the dataset.

    " + }, + "datasetVersion":{ + "shape":"Version", + "documentation":"

    The version of the dataset after deletion.

    " + }, + "errors":{ + "shape":"FailedDataSegmentDeletions", + "documentation":"

    A list of data segment deletions that failed.

    " + } + } + }, + "BatchDisassociateDataSegmentsFromDatasetRequest":{ + "type":"structure", + "required":[ + "datasetId", + "workspaceName", + "disassociateDataSegmentEntries" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the curated dataset to disassociate data segments from.

    ", + "location":"uri", + "locationName":"datasetId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    " + }, + "disassociateDataSegmentEntries":{ + "shape":"DisassociateDataSegmentEntries", + "documentation":"

    The list of data segment entries to disassociate from the dataset.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true + } + } + }, + "BatchDisassociateDataSegmentsFromDatasetResponse":{ + "type":"structure", + "required":[ + "datasetId", + "datasetVersion", + "failedDisassociations" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the dataset.

    " + }, + "datasetVersion":{ + "shape":"Version", + "documentation":"

    The version of the dataset after disassociation.

    " + }, + "failedDisassociations":{ + "shape":"FailedDataSegmentDisassociations", + "documentation":"

    A list of data segment disassociations that failed.

    " + } + } + }, "BatchDisassociateProjectAssetsErrors":{ "type":"list", "member":{"shape":"AssetErrorDetails"} @@ -3967,6 +5150,138 @@ "max":63, "min":3 }, + "BulkImportJobName":{ + "type":"string", + "max":256, + "min":1, + "pattern":"^[\\p{L}\\p{N}\\p{Zs}._:/-]+$" + }, + "CancelEnrichmentJobRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "jobId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace containing the enrichment job to cancel.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "jobId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the enrichment job to cancel. This is the jobId returned by CreateEnrichmentJob.

    ", + "location":"uri", + "locationName":"jobId" + } + } + }, + "CancelEnrichmentJobResponse":{ + "type":"structure", + "required":[ + "jobId", + "status" + ], + "members":{ + "jobId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the cancelled enrichment job.

    " + }, + "status":{ + "shape":"EnrichmentJobStatus", + "documentation":"

    The status of the enrichment job after cancellation. This will be CANCELLED, indicating the job was successfully cancelled or was already in CANCELLED state (idempotent behavior).

    " + } + } + }, + "CancelPipelineExecutionRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName", + "pipelineExecutionId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "pipelineExecutionId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the pipeline execution.

    ", + "location":"uri", + "locationName":"pipelineExecutionId" + }, + "reason":{ + "shape":"CancelPipelineExecutionRequestReasonString", + "documentation":"

    A message describing why the pipeline execution is being cancelled.

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

    Request structure for CancelPipelineExecution operation.

    " + }, + "CancelPipelineExecutionRequestReasonString":{ + "type":"string", + "max":1024, + "min":1 + }, + "CancelPipelineExecutionResponse":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"PipelineExecutionState", + "documentation":"

    The current execution state of the pipeline. Can only be CANCELLING or CANCELLED.

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

    Response structure for CancelPipelineExecution operation.

    " + }, + "CancelQueryRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "queryId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace associated with the query.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution to cancel.

    ", + "location":"uri", + "locationName":"queryId" + } + } + }, + "CancelQueryResponse":{ + "type":"structure", + "required":[ + "queryId", + "status" + ], + "members":{ + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the cancelled query.

    " + }, + "status":{ + "shape":"QueryStatus", + "documentation":"

    The current query status.

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

    Contains the response for the CancelQuery operation.

    " + }, "CapabilityConfiguration":{ "type":"string", "max":10000000, @@ -3988,6 +5303,10 @@ "NOT_APPLICABLE" ] }, + "CaptureBlob":{ + "type":"blob", + "documentation":"

    A binary blob containing video data.

    " + }, "Citation":{ "type":"structure", "members":{ @@ -4012,6 +5331,12 @@ "min":36, "pattern":"\\S{36,64}" }, + "ColumnDataType":{ + "type":"string", + "documentation":"

    The data type of a column. Valid values are STRING, DOUBLE, BOOLEAN, INTEGER, TIMESTAMP, and VARIANT.

    ", + "max":64, + "min":1 + }, "ColumnInfo":{ "type":"structure", "members":{ @@ -4026,6 +5351,35 @@ }, "documentation":"

    A description of the column in the query results.

    " }, + "ColumnInformation":{ + "type":"structure", + "required":[ + "name", + "type" + ], + "members":{ + "name":{ + "shape":"ColumnLabel", + "documentation":"

    The name of the column.

    " + }, + "type":{ + "shape":"ColumnDataType", + "documentation":"

    The data type of the column. Valid values are STRING, DOUBLE, BOOLEAN, INTEGER, TIMESTAMP, and VARIANT.

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

    Contains metadata about a column in the query results.

    " + }, + "ColumnInformationList":{ + "type":"list", + "member":{"shape":"ColumnInformation"}, + "documentation":"

    A list of column metadata entries for the query results.

    " + }, + "ColumnLabel":{ + "type":"string", + "documentation":"

    The name of a column in the query results.

    ", + "max":256, + "min":1 + }, "ColumnName":{ "type":"string", "enum":[ @@ -4053,10 +5407,22 @@ }, "documentation":"

    The data type of the column.

    " }, + "ColumnValue":{ + "type":"string", + "documentation":"

    A string-encoded column value.

    ", + "max":1048576, + "min":0 + }, "ColumnsList":{ "type":"list", "member":{"shape":"ColumnInfo"} }, + "CommandList":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    A list of command strings to execute in the container.

    ", + "sensitive":true + }, "CompositeModelProperty":{ "type":"structure", "required":[ @@ -4336,6 +5702,191 @@ "CLOUD" ] }, + "ComputeNode":{ + "type":"structure", + "required":[ + "computeNodeName", + "taskName" + ], + "members":{ + "computeNodeName":{ + "shape":"ResourceName", + "documentation":"

    The unique name for this compute node within the pipeline.

    " + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task to execute for this compute node.

    " + }, + "environmentVariables":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Environment variables specific to this compute node. These override pipeline-level environment variables with the same key.

    " + }, + "dependsOn":{ + "shape":"ComputeNodeNameList", + "documentation":"

    A list of compute node names that must complete successfully before this node can start.

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

    A single compute node in a pipeline DAG. Each compute node references a task and can declare dependencies on other nodes.

    " + }, + "ComputeNodeEnvironmentVariablesMap":{ + "type":"map", + "key":{ + "shape":"ResourceName", + "documentation":"

    The compute node name from the pipeline definition.

    " + }, + "value":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Environment variable overrides specific to this compute node.

    " + }, + "documentation":"

    A map of compute node names to their environment variable overrides.

    ", + "max":50, + "min":0 + }, + "ComputeNodeErrorCode":{ + "type":"string", + "documentation":"

    Classification of a compute node execution failure.

    ", + "enum":[ + "VALIDATION_ERROR", + "INTERNAL_FAILURE", + "EXECUTION_ERROR", + "TIMED_OUT" + ] + }, + "ComputeNodeExecutionDetails":{ + "type":"structure", + "required":[ + "computeNodeName", + "taskName", + "taskArn", + "taskVersion", + "dependsOn", + "status" + ], + "members":{ + "computeNodeName":{ + "shape":"ResourceName", + "documentation":"

    The name of the compute node.

    " + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task executed for this compute node.

    " + }, + "taskArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the task.

    " + }, + "taskVersion":{ + "shape":"Version", + "documentation":"

    The task version that executed for this compute node.

    " + }, + "dependsOn":{ + "shape":"ComputeNodeNameList", + "documentation":"

    A list of compute node names that this node depends on.

    " + }, + "status":{ + "shape":"ComputeNodeExecutionStatus", + "documentation":"

    The current execution status of the compute node.

    " + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    The time the compute node execution started, in Unix epoch time.

    " + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    The time the compute node execution completed, in Unix epoch time.

    " + }, + "executionEnvironmentVariables":{ + "shape":"ExecutionEnvironmentVariablesMap", + "documentation":"

    The fully resolved environment variables used for this compute node execution.

    " + }, + "executionMounts":{ + "shape":"MountList", + "documentation":"

    The fully resolved mounts used for this compute node execution, after merging task-defined mounts with any execution-level mount overrides. Each mount attaches an external data source to the container filesystem at a relative path under the service-owned mount root.

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

    Contains detailed execution information for a compute node within a pipeline execution.

    " + }, + "ComputeNodeExecutionDetailsList":{ + "type":"list", + "member":{"shape":"ComputeNodeExecutionDetails"}, + "documentation":"

    A list of compute node execution details.

    " + }, + "ComputeNodeExecutionState":{ + "type":"string", + "documentation":"

    The state of an individual compute node execution.

    ", + "enum":[ + "NOT_STARTED", + "QUEUED", + "RUNNING", + "SUCCEEDED", + "FAILED" + ] + }, + "ComputeNodeExecutionStateDetails":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"ComputeNodeErrorCode", + "documentation":"

    Classification of the failure.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    Human-readable description of why the compute node failed.

    " + }, + "details":{ + "shape":"DetailedErrorList", + "documentation":"

    Detailed error entries to help diagnose the failure.

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

    Additional information about a compute node that has failed.

    " + }, + "ComputeNodeExecutionStatus":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"ComputeNodeExecutionState", + "documentation":"

    Current state of the compute node execution.

    " + }, + "stateDetails":{ + "shape":"ComputeNodeExecutionStateDetails", + "documentation":"

    Additional information about the compute node's failure. Populated when the compute node has failed.

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

    Current execution status of a compute node within a pipeline execution.

    " + }, + "ComputeNodeList":{ + "type":"list", + "member":{"shape":"ComputeNode"}, + "documentation":"

    A list of compute nodes forming a pipeline DAG.

    ", + "max":50, + "min":0 + }, + "ComputeNodeMountsMap":{ + "type":"map", + "key":{ + "shape":"ResourceName", + "documentation":"

    The compute node name from the pipeline definition.

    " + }, + "value":{ + "shape":"MountList", + "documentation":"

    The mount overrides applied to this compute node for this execution. Each entry is merged into the compute node's task-defined mounts by mount name: a matching name replaces the task-defined mount, a new name adds a mount, and task-defined mounts not referenced remain unchanged.

    " + }, + "documentation":"

    A map of compute node names to their mount overrides. Applies to a single pipeline execution.

    ", + "max":50, + "min":0 + }, + "ComputeNodeNameList":{ + "type":"list", + "member":{"shape":"ResourceName"}, + "documentation":"

    A list of compute node names for declaring dependencies.

    ", + "max":10, + "min":0 + }, "ConfigurationErrorDetails":{ "type":"structure", "required":[ @@ -4399,6 +5950,54 @@ "error":{"httpStatusCode":409}, "exception":true }, + "ContainerTaskConfiguration":{ + "type":"structure", + "required":[ + "ecrUri", + "taskExecutionRole", + "processingType", + "processingUnit" + ], + "members":{ + "ecrUri":{ + "shape":"EcrUri", + "documentation":"

    The Amazon ECR image URI for the task container.

    " + }, + "taskExecutionRole":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of the IAM role that grants the containerized workload permissions to access AWS resources.

    " + }, + "processingType":{ + "shape":"ProcessingType", + "documentation":"

    The processing type for compute resources.

    " + }, + "processingUnit":{ + "shape":"ProcessingUnit", + "documentation":"

    The processing unit allocation that determines the vCPU, memory, and GPU resources.

    " + }, + "ephemeralStorageConfiguration":{ + "shape":"EphemeralStorageConfiguration", + "documentation":"

    Ephemeral storage configuration for the container task.

    " + }, + "command":{ + "shape":"CommandList", + "documentation":"

    The command to execute in the container.

    " + }, + "timeoutSeconds":{ + "shape":"TimeoutSeconds", + "documentation":"

    The timeout in seconds for task execution. Default: 3600 (1 hour).

    " + }, + "environmentVariables":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Environment variables passed to the container at runtime.

    " + }, + "mounts":{ + "shape":"MountList", + "documentation":"

    Mounts attached to the container filesystem. Each mount exposes an external data source as a local directory inside the container. The service assigns each mount a container path based on the mount name. The container reads files through that path as if the data were on the local filesystem.

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

    Configuration for a container task, including the container image, IAM role, and compute settings.

    " + }, "Content":{ "type":"structure", "members":{ @@ -4477,6 +6076,73 @@ } } }, + "CreateApplicationRequest":{ + "type":"structure", + "required":[ + "idcInstanceArn", + "workspaceName", + "name" + ], + "members":{ + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Unique client token for idempotent request handling

    ", + "idempotencyToken":true + }, + "idcInstanceArn":{ + "shape":"ARN", + "documentation":"

    Identity Center Instance ARN to create the application in

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    Name of the workspace to associate with the underlying Application

    " + }, + "name":{ + "shape":"ApplicationName", + "documentation":"

    Name of the application

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    Description of the application

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    A list of key-value pairs that contain metadata for the application.

    " + } + } + }, + "CreateApplicationResponse":{ + "type":"structure", + "required":[ + "arn", + "id", + "dnsSubdomain", + "name", + "status" + ], + "members":{ + "arn":{ + "shape":"ARN", + "documentation":"

    ARN of the application

    " + }, + "id":{ + "shape":"ApplicationId", + "documentation":"

    Unique identifier of the application

    " + }, + "dnsSubdomain":{ + "shape":"DnsSubdomain", + "documentation":"

    DNS subdomain for the application

    " + }, + "name":{ + "shape":"ApplicationName", + "documentation":"

    Name of the application

    " + }, + "status":{ + "shape":"ApplicationStatus", + "documentation":"

    Current status of the application

    " + } + } + }, "CreateAssetModelCompositeModelRequest":{ "type":"structure", "required":[ @@ -4564,7 +6230,11 @@ "shape":"AssetModelCompositeModelPath", "documentation":"

    The path to the composite model listing the parent composite models.

    " }, - "assetModelStatus":{"shape":"AssetModelStatus"} + "assetModelStatus":{"shape":"AssetModelStatus"}, + "assetModelId":{ + "shape":"ID", + "documentation":"

    The ID of the asset model.

    " + } } }, "CreateAssetModelRequest":{ @@ -4702,12 +6372,11 @@ "jobName", "jobRoleArn", "files", - "errorReportLocation", - "jobConfiguration" + "errorReportLocation" ], "members":{ "jobName":{ - "shape":"Name", + "shape":"BulkImportJobName", "documentation":"

    The unique name that helps identify the job request.

    " }, "jobRoleArn":{ @@ -4716,7 +6385,7 @@ }, "files":{ "shape":"Files", - "documentation":"

    The files in the specified Amazon S3 bucket that contain your data.

    " + "documentation":"

    The files in the specified Amazon S3 bucket that contain your data. You can specify up to 100 files for each bulk import job. Each file supports the following size limits:

    • Parquet files – Up to 256 MiB.

    • Other file formats – Up to 5 GiB.

    " }, "errorReportLocation":{ "shape":"ErrorReportLocation", @@ -4733,6 +6402,14 @@ "deleteFilesAfterImport":{ "shape":"DeleteFilesAfterImport", "documentation":"

    If set to true, your data files is deleted from S3, after ingestion into IoT SiteWise storage.

    " + }, + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the session dataset to ingest data into. Specify this field, together with workspaceName, to ingest data into a session dataset in a workspace.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the session dataset. Specify this field together with datasetId.

    " } } }, @@ -4749,7 +6426,7 @@ "documentation":"

    The ID of the job.

    " }, "jobName":{ - "shape":"Name", + "shape":"BulkImportJobName", "documentation":"

    The unique name that helps identify the job request.

    " }, "jobStatus":{ @@ -4867,6 +6544,59 @@ } } }, + "CreateDatasetExportJobRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "destinationS3Uri", + "input", + "errorReportLocation" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace in which to create the dataset export job.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. The AWS SDKs and CLI populate this automatically.

    ", + "idempotencyToken":true + }, + "destinationS3Uri":{ + "shape":"S3Uri", + "documentation":"

    The S3 URI where output clips will be written.

    " + }, + "input":{ + "shape":"ProcessingInput", + "documentation":"

    The processing input source.

    " + }, + "errorReportLocation":{ + "shape":"ExportErrorReportLocation", + "documentation":"

    The location where the error report will be written on failure.

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

    Request to create a dataset export job.

    " + }, + "CreateDatasetExportJobResponse":{ + "type":"structure", + "required":[ + "jobId", + "workspaceName" + ], + "members":{ + "jobId":{ + "shape":"DatasetExportJobId", + "documentation":"

    The unique identifier for the dataset export job.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace in which the dataset export job was created.

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

    Response for create dataset export job request.

    " + }, "CreateDatasetRequest":{ "type":"structure", "required":[ @@ -4883,9 +6613,25 @@ "documentation":"

    The name of the dataset.

    " }, "datasetDescription":{ - "shape":"RestrictedDescription", + "shape":"Description", "documentation":"

    A description about the dataset, and its functionality.

    " }, + "datasetType":{ + "shape":"DatasetTypeEnum", + "documentation":"

    The type of dataset: a session dataset, a curated dataset, or a connection to an external datasource.

    " + }, + "datasetConfig":{ + "shape":"DatasetConfig", + "documentation":"

    The configuration for the dataset.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset. Required for session and curated datasets. Omit this field for datasets that connect to an external datasource.

    " + }, + "metadata":{ + "shape":"Metadata", + "documentation":"

    The metadata for the dataset, provided as key-value pairs.

    " + }, "datasetSource":{ "shape":"DatasetSource", "documentation":"

    The data source for the dataset.

    " @@ -4923,6 +6669,52 @@ } } }, + "CreateEnrichmentJobRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "jobConfiguration" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace containing the video data to analyze.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "jobConfiguration":{ + "shape":"EnrichmentJobConfiguration", + "documentation":"

    Configuration defining the type of enrichment analysis to perform and which video data to analyze. Currently supports eventDetection for generating embeddings from video data for semantic search.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    Optional unique token that makes the operation idempotent. If you submit the same request with the same token within the idempotency window, the service returns the original job without creating a duplicate. Use a UUID or timestamp-based token for each unique request.

    ", + "idempotencyToken":true + } + } + }, + "CreateEnrichmentJobResponse":{ + "type":"structure", + "required":[ + "jobId", + "status", + "createdAt" + ], + "members":{ + "jobId":{ + "shape":"ID", + "documentation":"

    Unique identifier for the enrichment job. Use this ID with DescribeEnrichmentJob to monitor progress or with CancelEnrichmentJob to cancel the job.

    " + }, + "status":{ + "shape":"EnrichmentJobStatus", + "documentation":"

    Initial status of the enrichment job, typically PENDING. The job will transition to RUNNING when processing begins, then to a terminal state (COMPLETED, FAILED, TIMED_OUT, or CANCELLED). Use DescribeEnrichmentJob to track status changes.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the enrichment job was created in ISO 8601 format.

    " + } + } + }, "CreateGatewayRequest":{ "type":"structure", "required":[ @@ -4966,6 +6758,76 @@ } }, "CreateMissingProperty":{"type":"boolean"}, + "CreatePipelineRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName", + "computations" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline to create. Must be unique within the workspace.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A description of the pipeline.

    " + }, + "environmentVariables":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Environment variables shared across all compute nodes in the pipeline. Individual compute nodes can override these values with their own environment variables.

    " + }, + "computations":{ + "shape":"ComputeNodeList", + "documentation":"

    The list of compute nodes that form the pipeline DAG. Each compute node references a task and can declare dependencies on other nodes.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    A list of key-value pairs that contain metadata for the pipeline. For more information, see Tagging your AWS IoT SiteWise resources in the AWS IoT SiteWise User Guide.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If you retry a request that completed successfully using the same client token, the server returns the cached result from the original successful request without performing the operation again.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    Request structure for CreatePipeline operation.

    " + }, + "CreatePipelineResponse":{ + "type":"structure", + "required":[ + "pipelineName", + "pipelineArn", + "version", + "status" + ], + "members":{ + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the created pipeline.

    " + }, + "pipelineArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the created pipeline.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the newly created pipeline.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the pipeline.

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

    Response structure for CreatePipeline operation.

    " + }, "CreatePortalRequest":{ "type":"structure", "required":[ @@ -5104,6 +6966,124 @@ } } }, + "CreateTaskRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "taskName", + "taskConfiguration" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task to create. Must be unique within the workspace.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    A description of the task.

    " + }, + "taskConfiguration":{ + "shape":"TaskConfiguration", + "documentation":"

    The task execution configuration. Specify a containerTaskConfiguration for custom container workloads.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    A list of key-value pairs that contain metadata for the task. For more information, see Tagging your AWS IoT SiteWise resources in the AWS IoT SiteWise User Guide.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If you retry a request that completed successfully using the same client token, the server returns the cached result from the original successful request without performing the operation again.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    Request structure for CreateTask operation.

    " + }, + "CreateTaskResponse":{ + "type":"structure", + "required":[ + "taskName", + "taskArn", + "version", + "status" + ], + "members":{ + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the created task.

    " + }, + "taskArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the created task.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the newly created task.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the task.

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

    Response structure for CreateTask operation.

    " + }, + "CreateWorkspaceRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "encryptionConfiguration" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to create.

    " + }, + "workspaceDescription":{ + "shape":"Description", + "documentation":"

    A description for the workspace.

    " + }, + "encryptionConfiguration":{ + "shape":"WorkspaceEncryptionConfiguration", + "documentation":"

    The encryption configuration for the workspace.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    A list of key-value pairs that contain metadata for the workspace. For more information, see Tagging your IoT SiteWise resources in the IoT SiteWise User Guide.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true + } + } + }, + "CreateWorkspaceResponse":{ + "type":"structure", + "required":[ + "workspaceName", + "workspaceArn", + "workspaceStatus" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "workspaceArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the workspace.

    " + }, + "workspaceStatus":{ + "shape":"WorkspaceStatus", + "documentation":"

    The status of the workspace, which is CREATING when the operation returns.

    " + } + } + }, "Csv":{ "type":"structure", "required":["columnNames"], @@ -5212,94 +7192,319 @@ }, "documentation":"

    A filter used to match specific data binding values based on criteria. This filter allows searching for data bindings by asset, asset model, asset property, or asset model property.

    " }, - "DataSetReference":{ - "type":"structure", - "members":{ - "datasetArn":{ - "shape":"String", - "documentation":"

    The ARN of the dataset. The format is arn:${Partition}:iotsitewise:${Region}:${Account}:dataset/${DatasetId}.

    " - }, - "source":{ - "shape":"Source", - "documentation":"

    The data source for the dataset.

    " - } - }, - "documentation":"

    Contains information about the dataset use and it's source.

    " - }, - "DatasetSource":{ + "DataSegmentEnrichment":{ "type":"structure", - "required":[ - "sourceType", - "sourceFormat" - ], + "required":["status"], "members":{ - "sourceType":{ - "shape":"DatasetSourceType", - "documentation":"

    The type of data source for the dataset.

    " - }, - "sourceFormat":{ - "shape":"DatasetSourceFormat", - "documentation":"

    The format of the dataset source associated with the dataset.

    " + "status":{ + "shape":"EnrichmentStatus", + "documentation":"

    The enrichment status of the data segment.

    " }, - "sourceDetail":{ - "shape":"SourceDetail", - "documentation":"

    The details of the dataset source associated with the dataset.

    " + "lastEnrichedAt":{ + "shape":"Timestamp", + "documentation":"

    The date the data segment was last enriched, in Unix epoch time.

    " } }, - "documentation":"

    The data source for the dataset.

    " + "documentation":"

    Contains enrichment status information for a data segment.

    " }, - "DatasetSourceFormat":{ + "DataSegmentErrorCode":{ "type":"string", - "enum":["KNOWLEDGE_BASE"] + "enum":[ + "INTERNAL_FAILURE", + "VALIDATION_ERROR", + "RESOURCE_NOT_FOUND", + "LIMIT_EXCEEDED", + "CONFLICTING_OPERATION" + ] }, - "DatasetSourceType":{ + "DataSegmentErrorMessage":{ "type":"string", - "enum":["KENDRA"] + "max":2048, + "min":1 }, - "DatasetState":{ - "type":"string", - "enum":[ - "CREATING", - "ACTIVE", - "UPDATING", - "DELETING", - "FAILED" - ] + "DataSegmentRelationshipSummaries":{ + "type":"list", + "member":{"shape":"DataSegmentRelationshipSummary"} }, - "DatasetStatus":{ + "DataSegmentRelationshipSummary":{ "type":"structure", - "required":["state"], + "required":[ + "targetDatasetId", + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp" + ], "members":{ - "state":{ - "shape":"DatasetState", - "documentation":"

    The current status of the dataset.

    " + "targetDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the curated dataset that references the data segment.

    " }, - "error":{"shape":"ErrorDetails"} + "sourceDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the source session dataset that contains the data segment.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment.

    " + } }, - "documentation":"

    The status of the dataset. This contains the state and any error messages. The state is ACTIVE when ready to use.

    " + "documentation":"

    Contains summary information about a data segment relationship between a source session dataset that contains the data and a curated dataset that references it, including the time series and timestamp range.

    " }, - "DatasetSummaries":{ + "DataSegmentSummaries":{ "type":"list", - "member":{"shape":"DatasetSummary"} + "member":{"shape":"DataSegmentSummary"} }, - "DatasetSummary":{ + "DataSegmentSummary":{ "type":"structure", "required":[ - "id", - "arn", - "name", - "description", - "creationDate", - "lastUpdateDate", - "status" + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp", + "alias", + "dataType" ], "members":{ - "id":{ + "sourceDatasetId":{ "shape":"ID", - "documentation":"

    The ID of the dataset.

    " + "documentation":"

    The ID of the source dataset that contains the data segment.

    " }, - "arn":{ - "shape":"ARN", + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment.

    " + }, + "alias":{ + "shape":"PropertyAlias", + "documentation":"

    The alias of the time series.

    " + }, + "dataType":{ + "shape":"PropertyDataType", + "documentation":"

    The data type of the time series.

    " + }, + "enrichment":{ + "shape":"DataSegmentEnrichment", + "documentation":"

    The enrichment information for the data segment.

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

    Contains summary information about a data segment, including its source dataset, time series, timestamp range, and enrichment status.

    " + }, + "DataSetIdList":{ + "type":"list", + "member":{"shape":"DatasetId"}, + "documentation":"

    A list of dataset identifiers to restrict a search to.

    ", + "max":100, + "min":1 + }, + "DataSetReference":{ + "type":"structure", + "members":{ + "datasetArn":{ + "shape":"String", + "documentation":"

    The ARN of the dataset. The format is arn:${Partition}:iotsitewise:${Region}:${Account}:dataset/${DatasetId}.

    " + }, + "source":{ + "shape":"Source", + "documentation":"

    The data source for the dataset.

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

    Contains information about the dataset use and it's source.

    " + }, + "DatasetConfig":{ + "type":"structure", + "members":{ + "session":{ + "shape":"SessionConfig", + "documentation":"

    The session configuration for a session-type dataset.

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

    Contains the configuration for a dataset.

    " + }, + "DatasetEnrichment":{ + "type":"structure", + "members":{ + "video":{ + "shape":"DatasetEnrichmentEntry", + "documentation":"

    The enrichment status for video data in the dataset.

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

    Contains the enrichment status information for a dataset across data types.

    " + }, + "DatasetEnrichmentEntry":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"DatasetEnrichmentStatus", + "documentation":"

    The enrichment status of the data type in the dataset.

    " + }, + "lastEnrichedAt":{ + "shape":"Timestamp", + "documentation":"

    The date the data was last enriched, in Unix epoch time.

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

    Contains enrichment status information for a specific data type in a dataset.

    " + }, + "DatasetEnrichmentStatus":{ + "type":"string", + "enum":[ + "FULLY_ENRICHED", + "PARTIALLY_ENRICHED", + "NOT_ENRICHED" + ] + }, + "DatasetExportJobFilter":{ + "type":"string", + "documentation":"<p>Filter for ListDatasetExportJobs. ALL returns jobs in any status; otherwise returns jobs in the specified status.</p>", + "enum":[ + "ALL", + "SUBMITTED", + "RUNNING", + "COMPLETED", + "COMPLETED_WITH_ERRORS", + "FAILED" + ] + }, + "DatasetExportJobId":{ + "type":"string", + "documentation":"<p>The unique identifier for a dataset export job.</p>", + "max":36, + "min":36, + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "DatasetExportJobStatus":{ + "type":"string", + "documentation":"<p>The status of a dataset export job.</p>", + "enum":[ + "SUBMITTED", + "RUNNING", + "COMPLETED", + "COMPLETED_WITH_ERRORS", + "FAILED" + ] + }, + "DatasetId":{ + "type":"string", + "documentation":"Unique identifier for a dataset (UUID format)", + "max":36, + "min":36, + "pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" + }, + "DatasetItem":{ + "type":"structure", + "required":["datasetId"], + "members":{ + "datasetId":{ + "shape":"DatasetId", + "documentation":"<p>The unique identifier for the dataset.</p>" + }, + "trimSettings":{ + "shape":"TrimSettings", + "documentation":"<p>The trim settings applied to all items in the dataset. When omitted, the full dataset time range is used.</p>" + }, + "exportDataTypes":{ + "shape":"ExportDataTypeList", + "documentation":"<p>The optional subset of data types to export. If omitted, all data types are exported.</p>" + } + }, + "documentation":"<p>A dataset to process.</p>" + }, + "DatasetSource":{ + "type":"structure", + "required":[ + "sourceType", + "sourceFormat" + ], + "members":{ + "sourceType":{ + "shape":"DatasetSourceType", + "documentation":"

    The type of data source for the dataset.

    " + }, + "sourceFormat":{ + "shape":"DatasetSourceFormat", + "documentation":"

    The format of the dataset source associated with the dataset.

    " + }, + "sourceDetail":{ + "shape":"SourceDetail", + "documentation":"

    The details of the dataset source associated with the dataset.

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

    The data source for the dataset.

    " + }, + "DatasetSourceFormat":{ + "type":"string", + "enum":[ + "KNOWLEDGE_BASE", + "TIMESERIES" + ] + }, + "DatasetSourceType":{ + "type":"string", + "enum":[ + "KENDRA", + "SITEWISE" + ] + }, + "DatasetState":{ + "type":"string", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "FAILED" + ] + }, + "DatasetStatus":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"DatasetState", + "documentation":"

    The current status of the dataset.

    " + }, + "error":{"shape":"ErrorDetails"} + }, + "documentation":"

    The status of the dataset. This contains the state and any error messages. The state is ACTIVE when ready to use.

    " + }, + "DatasetSummaries":{ + "type":"list", + "member":{"shape":"DatasetSummary"} + }, + "DatasetSummary":{ + "type":"structure", + "required":[ + "id", + "arn", + "name", + "description", + "creationDate", + "lastUpdateDate", + "status" + ], + "members":{ + "id":{ + "shape":"ID", + "documentation":"

    The ID of the dataset.

    " + }, + "arn":{ + "shape":"ARN", "documentation":"

    The ARN of the dataset. The format is arn:${Partition}:iotsitewise:${Region}:${Account}:dataset/${DatasetId}.

    " }, "name":{ @@ -5307,9 +7512,17 @@ "documentation":"

    The name of the dataset.

    " }, "description":{ - "shape":"RestrictedDescription", + "shape":"Description", "documentation":"

    A description about the dataset, and its functionality.

    " }, + "sourceType":{ + "shape":"DatasetSourceType", + "documentation":"

    The data source type of the dataset.

    " + }, + "datasetType":{ + "shape":"DatasetTypeEnum", + "documentation":"

    The type of dataset: a session dataset, a curated dataset, or a connection to an external datasource.

    " + }, "creationDate":{ "shape":"Timestamp", "documentation":"

    The dataset creation date, in Unix epoch time.

    " @@ -5321,10 +7534,22 @@ "status":{ "shape":"DatasetStatus", "documentation":"

    The status of the dataset. This contains the state and any error messages. The state is ACTIVE when ready to use.

    " + }, + "enrichmentStatus":{ + "shape":"DatasetEnrichment", + "documentation":"

    The enrichment status of the dataset.

    " } }, "documentation":"

    The summary details for the dataset.

    " }, + "DatasetTypeEnum":{ + "type":"string", + "enum":[ + "SESSION", + "CURATED", + "EXTERNAL" + ] + }, "Datum":{ "type":"structure", "members":{ @@ -5378,6 +7603,31 @@ "type":"structure", "members":{} }, + "DeleteApplicationRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "id" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    Name of the workspace to associate with the underlying Application

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "id":{ + "shape":"ApplicationId", + "documentation":"

    ID of the Application to delete

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "DeleteApplicationResponse":{ + "type":"structure", + "members":{} + }, "DeleteAssetModelCompositeModelRequest":{ "type":"structure", "required":[ @@ -5428,7 +7678,11 @@ "type":"structure", "required":["assetModelStatus"], "members":{ - "assetModelStatus":{"shape":"AssetModelStatus"} + "assetModelStatus":{"shape":"AssetModelStatus"}, + "assetModelId":{ + "shape":"ID", + "documentation":"

    The ID of the asset model.

    " + } } }, "DeleteAssetModelInterfaceRelationshipRequest":{ @@ -5524,6 +7778,10 @@ "type":"structure", "required":["assetModelStatus"], "members":{ + "assetModelId":{ + "shape":"ID", + "documentation":"

    The ID of the asset model.

    " + }, "assetModelStatus":{ "shape":"AssetModelStatus", "documentation":"

    The status of the asset model, which contains a state (DELETING after successfully calling this operation) and any error message.

    " @@ -5553,6 +7811,10 @@ "type":"structure", "required":["assetStatus"], "members":{ + "assetId":{ + "shape":"ID", + "documentation":"

    The ID of the asset.

    " + }, "assetStatus":{ "shape":"AssetStatus", "documentation":"

    The status of the asset, which contains a state (DELETING after successfully calling this operation) and any error message.

    " @@ -5611,6 +7873,35 @@ "type":"structure", "members":{} }, + "DeleteDataSegmentEntries":{ + "type":"list", + "member":{"shape":"DeleteDataSegmentEntry"}, + "max":10, + "min":1 + }, + "DeleteDataSegmentEntry":{ + "type":"structure", + "required":[ + "timeSeriesId", + "startTimestamp", + "endTimestamp" + ], + "members":{ + "timeSeriesId":{ + "shape":"ID", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment to delete.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment to delete.

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

    Contains information about a data segment entry to delete.

    " + }, "DeleteDatasetRequest":{ "type":"structure", "required":["datasetId"], @@ -5621,6 +7912,12 @@ "location":"uri", "locationName":"datasetId" }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    ", + "location":"querystring", + "locationName":"workspaceName" + }, "clientToken":{ "shape":"ClientToken", "documentation":"

    A unique case-sensitive identifier that you can provide to ensure the idempotency of the request. Don't reuse this client token if a new idempotent request is required.

    ", @@ -5653,6 +7950,39 @@ } } }, + "DeletePipelineRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline to delete.

    ", + "location":"uri", + "locationName":"pipelineName" + } + }, + "documentation":"

    Request structure for DeletePipeline operation.

    " + }, + "DeletePipelineResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the pipeline.

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

    Response structure for DeletePipeline operation.

    " + }, "DeletePortalRequest":{ "type":"structure", "required":["portalId"], @@ -5705,6 +8035,39 @@ "type":"structure", "members":{} }, + "DeleteTaskRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "taskName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task to delete.

    ", + "location":"uri", + "locationName":"taskName" + } + }, + "documentation":"

    Request structure for DeleteTask operation.

    " + }, + "DeleteTaskResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the task.

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

    Response structure for DeleteTask operation.

    " + }, "DeleteTimeSeriesRequest":{ "type":"structure", "members":{ @@ -5730,6 +8093,41 @@ "shape":"ClientToken", "documentation":"

    A unique case-sensitive identifier that you can provide to ensure the idempotency of the request. Don't reuse this client token if a new idempotent request is required.

    ", "idempotencyToken":true + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" + } + } + }, + "DeleteWorkspaceRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to delete.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true, + "location":"querystring", + "locationName":"clientToken" + } + } + }, + "DeleteWorkspaceResponse":{ + "type":"structure", + "required":["workspaceStatus"], + "members":{ + "workspaceStatus":{ + "shape":"WorkspaceStatus", + "documentation":"

    The status of the workspace after the deletion request, which is DELETING when the operation returns.

    " } } }, @@ -5835,6 +8233,83 @@ } } }, + "DescribeApplicationRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "id" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    Name of the workspace to associate with the underlying Application

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "id":{ + "shape":"ApplicationId", + "documentation":"

    ID of the Application

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "DescribeApplicationResponse":{ + "type":"structure", + "required":[ + "arn", + "createdAt", + "dnsSubdomain", + "id", + "idcApplicationArn", + "name", + "status", + "updatedAt", + "workspaceName" + ], + "members":{ + "arn":{ + "shape":"ARN", + "documentation":"

    ARN of the application

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the application was created

    " + }, + "dnsSubdomain":{ + "shape":"DnsSubdomain", + "documentation":"

    DNS subdomain for the application

    " + }, + "description":{ + "shape":"ApplicationDescription", + "documentation":"

    Description of the application

    " + }, + "id":{ + "shape":"ApplicationId", + "documentation":"

    Unique identifier of the application

    " + }, + "idcApplicationArn":{ + "shape":"ARN", + "documentation":"

    Identity Center Application ARN associated with this application

    " + }, + "name":{ + "shape":"ApplicationName", + "documentation":"

    Name of the application

    " + }, + "status":{ + "shape":"ApplicationStatus", + "documentation":"

    Current status of the application

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the application was last updated

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    Name of the workspace this application belongs to

    " + } + } + }, "DescribeAssetCompositeModelRequest":{ "type":"structure", "required":[ @@ -6301,6 +8776,12 @@ "documentation":"

    The ID of the job.

    ", "location":"uri", "locationName":"jobId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" } } }, @@ -6313,7 +8794,6 @@ "jobRoleArn", "files", "errorReportLocation", - "jobConfiguration", "jobCreationDate", "jobLastUpdateDate" ], @@ -6336,7 +8816,7 @@ }, "files":{ "shape":"Files", - "documentation":"

    The files in the specified Amazon S3 bucket that contain your data.

    " + "documentation":"

    The files in the specified Amazon S3 bucket that contain your data. You can specify up to 100 files for each bulk import job. Each file supports the following size limits:

    • Parquet files – Up to 256 MiB.

    • Other file formats – Up to 5 GiB.

    " }, "errorReportLocation":{ "shape":"ErrorReportLocation", @@ -6361,6 +8841,14 @@ "deleteFilesAfterImport":{ "shape":"DeleteFilesAfterImport", "documentation":"

    If set to true, your data files is deleted from S3, after ingestion into IoT SiteWise storage.

    " + }, + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the dataset.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " } } }, @@ -6546,6 +9034,75 @@ } } }, + "DescribeDatasetExportJobRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "jobId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset export job.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "jobId":{ + "shape":"DatasetExportJobId", + "documentation":"

    The unique identifier for the dataset export job.

    ", + "location":"uri", + "locationName":"jobId" + } + }, + "documentation":"

    Request to describe a dataset export job.

    " + }, + "DescribeDatasetExportJobResponse":{ + "type":"structure", + "required":[ + "jobId", + "workspaceName", + "status", + "startedAt", + "destinationS3Uri", + "errorReportLocation", + "input" + ], + "members":{ + "jobId":{ + "shape":"DatasetExportJobId", + "documentation":"

    The unique identifier for the dataset export job.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset export job.

    " + }, + "status":{ + "shape":"DatasetExportJobStatus", + "documentation":"

    The current status of the dataset export job.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the job started processing.

    " + }, + "completedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the job completed, or null if the job is still running.

    " + }, + "destinationS3Uri":{ + "shape":"S3Uri", + "documentation":"

    The S3 URI where output clips are written.

    " + }, + "errorReportLocation":{ + "shape":"ExportErrorReportLocation", + "documentation":"

    The location where the error report will be written on failure.

    " + }, + "input":{ + "shape":"ProcessingInput", + "documentation":"

    The processing input that was provided in the CreateDatasetExportJob request.

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

    Response for describe dataset export job request.

    " + }, "DescribeDatasetRequest":{ "type":"structure", "required":["datasetId"], @@ -6555,6 +9112,18 @@ "documentation":"

    The ID of the dataset.

    ", "location":"uri", "locationName":"datasetId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    ", + "location":"querystring", + "locationName":"workspaceName" + }, + "datasetVersion":{ + "shape":"Version", + "documentation":"

    The version of the dataset.

    ", + "location":"querystring", + "locationName":"datasetVersion" } } }, @@ -6584,9 +9153,25 @@ "documentation":"

    The name of the dataset.

    " }, "datasetDescription":{ - "shape":"RestrictedDescription", + "shape":"Description", "documentation":"

    A description about the dataset, and its functionality.

    " }, + "datasetType":{ + "shape":"DatasetTypeEnum", + "documentation":"

    The type of dataset: a session dataset, a curated dataset, or a connection to an external datasource.

    " + }, + "datasetConfig":{ + "shape":"DatasetConfig", + "documentation":"

    The configuration for the dataset.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    " + }, + "metadata":{ + "shape":"Metadata", + "documentation":"

    The metadata for the dataset.

    " + }, "datasetSource":{ "shape":"DatasetSource", "documentation":"

    The data source for the dataset.

    " @@ -6606,6 +9191,10 @@ "datasetVersion":{ "shape":"Version", "documentation":"

    The version of the dataset.

    " + }, + "enrichmentStatus":{ + "shape":"DatasetEnrichment", + "documentation":"

    The enrichment status of the dataset.

    " } } }, @@ -6634,6 +9223,80 @@ } } }, + "DescribeEnrichmentJobRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "jobId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace containing the enrichment job.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "jobId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the enrichment job to retrieve. This is the jobId returned by CreateEnrichmentJob.

    ", + "location":"uri", + "locationName":"jobId" + } + } + }, + "DescribeEnrichmentJobResponse":{ + "type":"structure", + "required":[ + "jobId", + "status", + "workspaceName", + "jobType", + "jobConfiguration", + "createdAt" + ], + "members":{ + "jobId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the enrichment job.

    " + }, + "status":{ + "shape":"EnrichmentJobStatus", + "documentation":"

    Current status of the enrichment job. Possible values:

    • PENDING: Job is waiting to start processing
    • RUNNING: Job is actively processing video data
    • COMPLETED: Job finished successfully; embeddings available in IoT SiteWise
    • FAILED: Job encountered an error; see failureMessage for details
    • TIMED_OUT: Job exceeded maximum processing time limit
    • CANCELLED: Job was cancelled by user request
    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace containing the job.

    " + }, + "jobType":{ + "shape":"JobType", + "documentation":"

    The type of enrichment job, derived from the job configuration. Currently EVENT_DETECTION is the only supported type.

    " + }, + "jobConfiguration":{ + "shape":"EnrichmentJobConfiguration", + "documentation":"

    The complete job configuration as originally submitted, including the analysis type and parameters. For event detection jobs, this includes the dataset ID, time series identifier, and trim settings defining the analysis time range.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the enrichment job was created in ISO 8601 format.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the job status was last updated in ISO 8601 format. Useful for tracking recent activity.

    " + }, + "completedAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the job completed successfully in ISO 8601 format. Only present if status is COMPLETED.

    " + }, + "cancelledAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the job was cancelled in ISO 8601 format. Only present if status is CANCELLED.

    " + }, + "failureMessage":{ + "shape":"String", + "documentation":"

    Human-readable error message explaining why the job failed. Only present if status is FAILED. Use this information to diagnose configuration issues, permission problems, or data processing errors.

    " + } + } + }, "DescribeExecutionRequest":{ "type":"structure", "required":["executionId"], @@ -6806,7 +9469,14 @@ }, "DescribeLoggingOptionsRequest":{ "type":"structure", - "members":{} + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" + } + } }, "DescribeLoggingOptionsResponse":{ "type":"structure", @@ -6818,6 +9488,200 @@ } } }, + "DescribePipelineExecutionRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName", + "pipelineExecutionId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "pipelineExecutionId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the pipeline execution.

    ", + "location":"uri", + "locationName":"pipelineExecutionId" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"DescribePipelineExecutionRequestMaxResultsInteger", + "documentation":"

    The maximum number of compute nodes to return per request. This is an upper bound; the actual number of results may be less. Default: 50.

    ", + "location":"querystring", + "locationName":"maxResults" + } + }, + "documentation":"

    Request structure for DescribePipelineExecution operation.

    " + }, + "DescribePipelineExecutionRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":250, + "min":1 + }, + "DescribePipelineExecutionResponse":{ + "type":"structure", + "required":[ + "pipelineExecutionId", + "pipelineName", + "workspaceName", + "pipelineVersion", + "status", + "requestEnvironmentVariables", + "computeNodeExecutionDetails" + ], + "members":{ + "pipelineExecutionId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the pipeline execution.

    " + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "pipelineVersion":{ + "shape":"Version", + "documentation":"

    The pipeline version this execution ran against.

    " + }, + "status":{ + "shape":"PipelineExecutionStatus", + "documentation":"

    The current execution status of the pipeline.

    " + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline execution started, in Unix epoch time.

    " + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline execution completed, in Unix epoch time.

    " + }, + "requestEnvironmentVariables":{ + "shape":"ExecutionEnvironmentVariables", + "documentation":"

    The environment variables provided as input for the pipeline execution.

    " + }, + "requestMountOverrides":{ + "shape":"MountOverrides", + "documentation":"

    The mount overrides provided as input for the pipeline execution. Present when mount overrides were supplied at execution time.

    " + }, + "executionPriority":{ + "shape":"ExecutionPriority", + "documentation":"

    Scheduling priority for the execution. When not specified, defaults to lowest priority.

    " + }, + "computeNodeExecutionDetails":{ + "shape":"ComputeNodeExecutionDetailsList", + "documentation":"

    A list of compute node execution details within this pipeline execution.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

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

    Response structure for DescribePipelineExecution operation.

    " + }, + "DescribePipelineRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "pipelineVersion":{ + "shape":"Version", + "documentation":"

    The version number of the pipeline to retrieve. If not specified, returns the latest version.

    ", + "location":"querystring", + "locationName":"version" + } + }, + "documentation":"

    Request structure for DescribePipeline operation.

    " + }, + "DescribePipelineResponse":{ + "type":"structure", + "required":[ + "pipelineName", + "workspaceName", + "pipelineArn", + "version", + "computations", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    A unique name of the pipeline within the workspace.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the pipeline.

    " + }, + "pipelineArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the pipeline.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the pipeline.

    " + }, + "environmentVariables":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    The environment variables shared across all compute nodes in the pipeline.

    " + }, + "computations":{ + "shape":"ComputeNodeList", + "documentation":"

    The list of compute nodes that form the pipeline DAG.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the pipeline.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline was last updated, in Unix epoch time.

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

    Response structure for DescribePipeline operation.

    " + }, "DescribePortalRequest":{ "type":"structure", "required":["portalId"], @@ -6967,14 +9831,137 @@ } } }, - "DescribeStorageConfigurationRequest":{ - "type":"structure", - "members":{} - }, - "DescribeStorageConfigurationResponse":{ + "DescribeQueryRequest":{ "type":"structure", "required":[ - "storageType", + "workspaceName", + "queryId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace associated with the query.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution.

    ", + "location":"uri", + "locationName":"queryId" + } + } + }, + "DescribeQueryResponse":{ + "type":"structure", + "required":[ + "queryId", + "status", + "submittedAt" + ], + "members":{ + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution.

    " + }, + "status":{ + "shape":"QueryStatus", + "documentation":"

    The current query status.

    " + }, + "submittedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the query was submitted, in Unix epoch time.

    " + }, + "completedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the query reached a terminal state, in Unix epoch time. This field is present when the query status is COMPLETED, FAILED, or CANCELED.

    " + }, + "statistics":{ + "shape":"QueryStatistics", + "documentation":"

    The query execution statistics. This field is present when the query status is COMPLETED.

    " + }, + "errorMessage":{ + "shape":"QueryErrorMessage", + "documentation":"

    A human-readable error description. This field is present when the query status is FAILED.

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

    Contains the response for the DescribeQuery operation.

    " + }, + "DescribeSearchRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "searchId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search belongs to.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "searchId":{ + "shape":"SearchId", + "documentation":"

    The identifier of the search to describe.

    ", + "location":"uri", + "locationName":"searchId" + } + }, + "documentation":"

    Input for the DescribeSearch operation.

    " + }, + "DescribeSearchResponse":{ + "type":"structure", + "required":[ + "searchId", + "workspaceName", + "status", + "queryStatement", + "searchType" + ], + "members":{ + "searchId":{ + "shape":"SearchId", + "documentation":"

    The unique identifier of the search.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search runs against.

    " + }, + "status":{ + "shape":"SearchStatus", + "documentation":"

    The current status of the search.

    " + }, + "queryStatement":{ + "shape":"SearchQueryStatement", + "documentation":"

    The natural-language query that was submitted for the search.

    " + }, + "searchType":{ + "shape":"SearchType", + "documentation":"

    The search strategy used for the search.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable explanation of the current status. Populated when the search has FAILED.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The time at which the search was started.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    The group identifier associated with the search, if one was supplied on the request.

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

    Output of the DescribeSearch operation.

    " + }, + "DescribeStorageConfigurationRequest":{ + "type":"structure", + "members":{} + }, + "DescribeStorageConfigurationResponse":{ + "type":"structure", + "required":[ + "storageType", "configurationStatus" ], "members":{ @@ -7013,6 +10000,86 @@ } } }, + "DescribeTaskRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "taskName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task.

    ", + "location":"uri", + "locationName":"taskName" + }, + "taskVersion":{ + "shape":"Version", + "documentation":"

    The version number of the task to retrieve. If not specified, returns the latest version.

    ", + "location":"querystring", + "locationName":"version" + } + }, + "documentation":"

    Request structure for DescribeTask operation.

    " + }, + "DescribeTaskResponse":{ + "type":"structure", + "required":[ + "workspaceName", + "taskName", + "taskArn", + "version", + "taskConfiguration", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the task.

    " + }, + "taskArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the task.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the task.

    " + }, + "taskConfiguration":{ + "shape":"TaskConfiguration", + "documentation":"

    The task execution configuration. Contains a containerTaskConfiguration for custom container workloads.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the task.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The time the task was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The time the task was last updated, in Unix epoch time.

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

    Response structure for DescribeTask operation.

    " + }, "DescribeTimeSeriesRequest":{ "type":"structure", "members":{ @@ -7033,6 +10100,12 @@ "documentation":"

    The ID of the asset property. This can be either the actual ID in UUID format, or else externalId: followed by the external ID, if it has one. For more information, see Referencing objects with external IDs in the IoT SiteWise User Guide.

    ", "location":"querystring", "locationName":"propertyId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" } } }, @@ -7081,6 +10154,62 @@ "timeSeriesArn":{ "shape":"ARN", "documentation":"

    The ARN of the time series, which has the following format.

    arn:${Partition}:iotsitewise:${Region}:${Account}:time-series/${TimeSeriesId}

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + } + } + }, + "DescribeWorkspaceRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + } + } + }, + "DescribeWorkspaceResponse":{ + "type":"structure", + "required":[ + "workspaceArn", + "workspaceName", + "workspaceStatus", + "createdAt", + "updatedAt" + ], + "members":{ + "workspaceArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the workspace.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "workspaceDescription":{ + "shape":"Description", + "documentation":"

    The description of the workspace.

    " + }, + "workspaceStatus":{ + "shape":"WorkspaceStatus", + "documentation":"

    The status of the workspace, which contains the state and any error message.

    " + }, + "encryptionConfiguration":{ + "shape":"WorkspaceEncryptionConfigurationInfo", + "documentation":"

    The encryption configuration information for the workspace.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The date the workspace was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date the workspace was last updated, in Unix epoch time.

    " } } }, @@ -7115,11 +10244,44 @@ "INCOMPATIBLE_FORWARDING_CONFIGURATION" ] }, + "DetailedErrorList":{ + "type":"list", + "member":{"shape":"DetailedPipelineError"}, + "documentation":"

    A list of detailed pipeline error entries.

    " + }, "DetailedErrorMessage":{"type":"string"}, "DetailedErrors":{ "type":"list", "member":{"shape":"DetailedError"} }, + "DetailedPipelineError":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"DetailedPipelineErrorCode", + "documentation":"

    The error code.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    The associated error message.

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

    Contains a detailed error entry for granular troubleshooting of pipeline failures.

    " + }, + "DetailedPipelineErrorCode":{ + "type":"string", + "documentation":"

    The error code for a detailed pipeline error entry.

    ", + "enum":[ + "VALIDATION_ERROR", + "INTERNAL_FAILURE", + "EXECUTION_ERROR", + "TIMED_OUT" + ] + }, "DisallowIngestNullNaN":{"type":"boolean"}, "DisassociateAssetsRequest":{ "type":"structure", @@ -7150,6 +10312,38 @@ } } }, + "DisassociateDataSegmentEntries":{ + "type":"list", + "member":{"shape":"DisassociateDataSegmentEntry"} + }, + "DisassociateDataSegmentEntry":{ + "type":"structure", + "required":[ + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp" + ], + "members":{ + "sourceDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the source dataset that contains the data segment.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment to disassociate.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment to disassociate.

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

    Contains information about a data segment entry to disassociate from a dataset.

    " + }, "DisassociateTimeSeriesFromAssetPropertyRequest":{ "type":"structure", "required":[ @@ -7190,10 +10384,25 @@ "DISABLED" ] }, + "DnsSubdomain":{ + "type":"string", + "documentation":"

    DNS-compliant subdomain label

    ", + "max":63, + "min":1, + "pattern":"[a-z0-9]([a-z0-9-]*[a-z0-9])?" + }, "ETag":{ "type":"string", "pattern":"^[\\w-]{43}$" }, + "EcrUri":{ + "type":"string", + "documentation":"

    The Amazon ECR image URI for the container.

    Supported formats:

    • Private: {account-id}.dkr.ecr.{region}.amazonaws.com/{repository}:{tag}
    • Public: public.ecr.aws/{registry-alias}/{repository}:{tag}

    Tags and digests (@sha256:...) are optional. If omitted, latest is used. The image must be accessible from the task execution role.

    ", + "max":1024, + "min":1, + "pattern":"((\\d{12}\\.dkr\\.ecr\\.[a-z0-9-]+\\.[a-z.]+)|public\\.ecr\\.aws/[a-z][a-z0-9]+([._-][a-z0-9]+)*)/[a-z0-9]+((\\.||__|_|-+)[a-z0-9]+)*(/[a-z0-9]+((\\.||__|_|-+)[a-z0-9]+)*)*(:[a-zA-Z0-9._-]+|@sha256:[a-f0-9]{64})?", + "sensitive":true + }, "Email":{ "type":"string", "max":255, @@ -7208,72 +10417,246 @@ "KMS_BASED_ENCRYPTION" ] }, - "EntryId":{ - "type":"string", - "max":64, - "min":1, - "pattern":"^[a-zA-Z0-9_-]+$" + "EnrichmentJobConfiguration":{ + "type":"structure", + "members":{ + "eventDetection":{ + "shape":"EventDetection", + "documentation":"

    Event detection configuration that generates embeddings from video time-series data enabling natural language similarity search on events. The service processes video data and creates embeddings stored in IoT SiteWise for semantic querying.

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

    Configuration for the enrichment job defining which analysis type to perform on video time-series data. Currently supports event detection enrichment. Exactly one member must be specified.

    ", + "union":true }, - "ErrorCode":{ + "EnrichmentJobStatus":{ "type":"string", + "documentation":"<p>Status of an enrichment job throughout its lifecycle.</p> <p>Status progression: PENDING → RUNNING → {COMPLETED, FAILED, TIMED_OUT, CANCELLED}</p> <ul> <li>PENDING: Job has been accepted and is waiting to start processing</li> <li>RUNNING: Job is actively processing video data to generate embeddings</li> <li>COMPLETED: Job finished successfully; embeddings are available in IoT SiteWise</li> <li>FAILED: Job encountered an error during processing</li> <li>TIMED_OUT: Job exceeded the maximum processing time limit</li> <li>CANCELLED: Job was cancelled via CancelEnrichmentJob</li> </ul> <p>Terminal states (job will not change status): COMPLETED, FAILED, TIMED_OUT, CANCELLED</p>", "enum":[ - "VALIDATION_ERROR", - "INTERNAL_FAILURE" + "PENDING", + "RUNNING", + "COMPLETED", + "FAILED", + "TIMED_OUT", + "CANCELLED" ] }, - "ErrorDetails":{ + "EnrichmentJobSummaries":{ + "type":"list", + "member":{"shape":"EnrichmentJobSummary"} + }, + "EnrichmentJobSummary":{ "type":"structure", "required":[ - "code", - "message" + "jobId", + "status", + "workspaceName", + "jobType", + "datasetId", + "createdAt" ], "members":{ - "code":{ - "shape":"ErrorCode", - "documentation":"

    The error code.

    " + "jobId":{ + "shape":"ID", + "documentation":"

    Unique identifier for the enrichment job.

    " }, - "message":{ - "shape":"ErrorMessage", - "documentation":"

    The error message.

    " + "status":{ + "shape":"EnrichmentJobStatus", + "documentation":"

    Current status of the job: PENDING, RUNNING, COMPLETED, FAILED, TIMED_OUT, or CANCELLED. Use this to quickly identify active jobs or jobs requiring attention.

    " }, - "details":{ - "shape":"DetailedErrors", - "documentation":"

    A list of detailed errors.

    " + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace containing this job.

    " + }, + "jobType":{ + "shape":"JobType", + "documentation":"

    The type of enrichment job. Currently EVENT_DETECTION is the only supported type.

    " + }, + "datasetId":{ + "shape":"ID", + "documentation":"

    The dataset being enriched. Useful for filtering and identifying jobs without fetching the full configuration. This allows you to quickly find all jobs related to a specific dataset.

    " + }, + "propertyAlias":{ + "shape":"AssetPropertyAlias", + "documentation":"

    The property alias (human-readable sensor name) of the time series being enriched. Present when the job was created using a propertyAlias. Use this to identify which sensor the job analyzes.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The system identifier of the time series being enriched. Present when the job was created using a timeSeriesId. Use this to identify which time series the job analyzes.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp when the job was created in ISO 8601 format.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    Timestamp of the last job status change in ISO 8601 format. Use this to track recent activity and identify stale jobs. For active jobs, this shows the last time the job transitioned to a new status.

    " } }, - "documentation":"

    Contains the details of an IoT SiteWise error.

    " + "documentation":"

    Summary information for an enrichment job returned by ListEnrichmentJobs. This lightweight representation includes identifiers, status, and key metadata without the full job configuration.

    Use DescribeEnrichmentJob to retrieve:

    • Complete job configuration (trim settings, full parameters)
    • Detailed timestamps (completedAt, cancelledAt)
    • Failure messages for failed jobs

    The summary is optimized for display in lists and dashboards, providing enough information to identify and filter jobs without the overhead of full configuration details.

    " }, - "ErrorMessage":{"type":"string"}, - "ErrorReportLocation":{ + "EnrichmentStatus":{ + "type":"string", + "enum":[ + "ENRICHED", + "NOT_ENRICHED" + ] + }, + "EnrichmentTrimSettings":{ "type":"structure", "required":[ - "bucket", - "prefix" + "startTime", + "endTime" ], "members":{ - "bucket":{ - "shape":"Bucket", - "documentation":"

    The name of the Amazon S3 bucket to which errors associated with the bulk import job are sent.

    " + "startTime":{ + "shape":"TimeInNanos", + "documentation":"<p>Start time for the video analysis time range in nanoseconds since Unix epoch (TimeInNanos format). Data segments at or after this time are included in the enrichment. Must be within the dataset's time bounds.</p> <p>Example (JavaScript): Date.parse('2024-01-01T00:00:00Z') * 1000000 Example (Python): int(datetime.timestamp() * 1e9)</p>" }, - "prefix":{ - "shape":"String", - "documentation":"

    Amazon S3 uses the prefix as a folder name to organize data in the bucket. Each Amazon S3 object has a key that is its unique identifier in the bucket. Each object in a bucket has exactly one key. The prefix must end with a forward slash (/). For more information, see Organizing objects using prefixes in the Amazon Simple Storage Service User Guide.

    " + "endTime":{ + "shape":"TimeInNanos", + "documentation":"<p>End time for the video analysis time range in nanoseconds since Unix epoch (TimeInNanos format). Data segments at or before this time are included in the enrichment. Must be greater than startTime and within the dataset's time bounds.</p>" } }, - "documentation":"

    The Amazon S3 destination where errors associated with the job creation request are saved.

    " + "documentation":"<p>Time range settings for extracting a specific window of video time-series data to process.</p> <p>Trim settings define the time bounds for enrichment and must satisfy:</p> <ul> <li>Start and end times must be within the dataset's time bounds</li> <li>Trim settings retrieve fully contained data segments within the specified time range</li> <li>endTime must be greater than startTime</li> <li>Both times should represent valid data ranges in the dataset</li> </ul> <p>Trim settings are required to:</p> <ul> <li>Prevent accidentally analyzing unbounded datasets</li> <li>Ensure predictable processing time and costs</li> <li>Allow focused analysis on specific time periods of interest</li> </ul>" }, - "ExceptionMessage":{"type":"string"}, - "ExcludeProperties":{"type":"boolean"}, - "ExecuteActionRequest":{ - "type":"structure", - "required":[ - "targetResource", - "actionDefinitionId", - "actionPayload" - ], - "members":{ - "targetResource":{ - "shape":"TargetResource", + "EntryId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"^[a-zA-Z0-9_-]+$" + }, + "EnvironmentVariableName":{ + "type":"string", + "documentation":"

    Environment variable name following POSIX naming rules Must not start with AWS_ prefix (case-insensitive)

    ", + "max":255, + "min":1, + "pattern":"(?!(?i)AWS_)[a-zA-Z_][a-zA-Z0-9_]*" + }, + "EnvironmentVariableValue":{ + "type":"string", + "documentation":"

    Environment variable value

    ", + "max":1024, + "min":0 + }, + "EnvironmentVariablesMap":{ + "type":"map", + "key":{"shape":"EnvironmentVariableName"}, + "value":{"shape":"EnvironmentVariableValue"}, + "documentation":"

    Map of environment variables for container configuration

    ", + "max":20, + "min":0, + "sensitive":true + }, + "EphemeralStorageConfiguration":{ + "type":"structure", + "required":[ + "storageClass", + "storageSizeInGiB" + ], + "members":{ + "storageClass":{ + "shape":"StorageClass", + "documentation":"

    Storage type that determines I/O performance family and level.

    " + }, + "storageSizeInGiB":{ + "shape":"EphemeralStorageConfigurationStorageSizeInGiBInteger", + "documentation":"

    Storage volume size in GiB.

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

    Configuration for ephemeral storage attached to the container task.

    " + }, + "EphemeralStorageConfigurationStorageSizeInGiBInteger":{ + "type":"integer", + "box":true, + "max":16384, + "min":1 + }, + "ErrorCode":{ + "type":"string", + "enum":[ + "VALIDATION_ERROR", + "INTERNAL_FAILURE" + ] + }, + "ErrorDetails":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"ErrorCode", + "documentation":"

    The error code.

    " + }, + "message":{ + "shape":"ErrorMessage", + "documentation":"

    The error message.

    " + }, + "details":{ + "shape":"DetailedErrors", + "documentation":"

    A list of detailed errors.

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

    Contains the details of an IoT SiteWise error.

    " + }, + "ErrorMessage":{"type":"string"}, + "ErrorReportLocation":{ + "type":"structure", + "required":[ + "bucket", + "prefix" + ], + "members":{ + "bucket":{ + "shape":"Bucket", + "documentation":"

    The name of the Amazon S3 bucket to which errors associated with the bulk import job are sent.

    " + }, + "prefix":{ + "shape":"String", + "documentation":"

    Amazon S3 uses the prefix as a folder name to organize data in the bucket. Each Amazon S3 object has a key that is its unique identifier in the bucket. Each object in a bucket has exactly one key. The prefix must end with a forward slash (/). For more information, see Organizing objects using prefixes in the Amazon Simple Storage Service User Guide.

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

    The Amazon S3 destination where errors associated with the job creation request are saved.

    " + }, + "EventDetection":{ + "type":"structure", + "required":[ + "datasetId", + "trimSettings" + ], + "members":{ + "datasetId":{ + "shape":"ID", + "documentation":"<p>The IoT SiteWise dataset ID containing the video time-series data to analyze. Query IoT SiteWise to discover available datasets in your workspace.</p>" + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"<p>Unique system identifier for the video time series to analyze. Specify either timeSeriesId or propertyAlias, but not both. Use this when you have the system-generated time series identifier from IoT SiteWise.</p>" + }, + "propertyAlias":{ + "shape":"AssetPropertyAlias", + "documentation":"<p>Human-readable alias for the video time series to analyze (e.g., /camera/warehouse/zone-a). Specify either propertyAlias or timeSeriesId, but not both. Use this when you have configured friendly aliases in IoT SiteWise for better readability.</p>" + }, + "trimSettings":{ + "shape":"EnrichmentTrimSettings", + "documentation":"<p>Time range settings defining which portion of the video time-series data to process. Required to ensure predictable processing time and prevent analyzing unbounded datasets. Start and end times must be within the dataset's time bounds.</p>" + } + }, + "documentation":"<p>Configuration for event detection enrichment on video time-series data.</p> <p>Event detection generates embeddings from video data enabling natural language similarity search on events. This allows customers to:</p> <ul> <li>Query video events using semantic search after enrichment completes</li> <li>Find relevant video segments through natural language queries</li> <li>Search across video time-series data stored in IoT SiteWise</li> </ul> <p>You must specify the dataset, exactly one time-series identifier (timeSeriesId OR propertyAlias), and trim settings defining the video time window to process.</p>" + }, + "ExceptionMessage":{"type":"string"}, + "ExcludeProperties":{"type":"boolean"}, + "ExecuteActionRequest":{ + "type":"structure", + "required":[ + "targetResource", + "actionDefinitionId", + "actionPayload" + ], + "members":{ + "targetResource":{ + "shape":"TargetResource", "documentation":"

    The resource the action will be taken on.

    " }, "actionDefinitionId":{ @@ -7366,6 +10749,53 @@ "type":"string", "pattern":"^[a-zA-Z0-9 _\\-#$*!@]+$" }, + "ExecutionEnvironmentVariables":{ + "type":"structure", + "members":{ + "global":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Global environment variables that apply to all compute nodes in the pipeline execution.

    " + }, + "computeNodes":{ + "shape":"ComputeNodeEnvironmentVariablesMap", + "documentation":"

    Per-compute-node environment variable overrides. Each entry maps a compute node name to its environment variable overrides.

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

    Environment variables provided as input for a pipeline execution.

    ", + "sensitive":true + }, + "ExecutionEnvironmentVariablesMap":{ + "type":"map", + "key":{ + "shape":"ExecutionEnvironmentVariablesMapKeyString", + "documentation":"

    The environment variable name.

    " + }, + "value":{ + "shape":"ExecutionEnvironmentVariablesMapValueString", + "documentation":"

    The environment variable value.

    " + }, + "documentation":"

    A map of fully resolved environment variable key-value pairs for a compute node execution.

    ", + "max":200, + "min":0, + "sensitive":true + }, + "ExecutionEnvironmentVariablesMapKeyString":{ + "type":"string", + "max":255, + "min":1 + }, + "ExecutionEnvironmentVariablesMapValueString":{ + "type":"string", + "max":1024, + "min":0 + }, + "ExecutionPriority":{ + "type":"integer", + "documentation":"

    Scheduling priority for pipeline execution. Lower values indicate higher priority. When not specified, defaults to lowest priority.

    ", + "box":true, + "max":2, + "min":0 + }, "ExecutionResult":{ "type":"map", "key":{"shape":"ExecutionResultKey"}, @@ -7448,6 +10878,70 @@ }, "documentation":"

    Contains the execution summary of the computation model.

    " }, + "ExportDataType":{ + "type":"string", + "documentation":"<p>Data types that can be exported from a dataset.</p>", + "enum":[ + "VIDEO", + "TELEMETRY", + "ANNOTATION" + ] + }, + "ExportDataTypeList":{ + "type":"list", + "member":{"shape":"ExportDataType"}, + "documentation":"<p>A subset of ExportDataType values to export.</p>", + "max":3, + "min":1 + }, + "ExportErrorReportLocation":{ + "type":"structure", + "required":["s3Uri"], + "members":{ + "s3Uri":{ + "shape":"S3Uri", + "documentation":"<p>The S3 URI prefix for the error report.</p>" + } + }, + "documentation":"<p>Contains the location where error reports will be written on failure.</p>" + }, + "ExportJobSummary":{ + "type":"structure", + "required":[ + "jobId", + "status", + "startedAt", + "destinationS3Uri" + ], + "members":{ + "jobId":{ + "shape":"DatasetExportJobId", + "documentation":"<p>The unique identifier for the dataset export job.</p>" + }, + "status":{ + "shape":"DatasetExportJobStatus", + "documentation":"<p>The current status of the dataset export job.</p>" + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"<p>The timestamp when the job started processing.</p>" + }, + "completedAt":{ + "shape":"Timestamp", + "documentation":"<p>The timestamp when the job completed, or null if the job is still running.</p>" + }, + "destinationS3Uri":{ + "shape":"S3Uri", + "documentation":"<p>The S3 URI where output clips are written.</p>" + } + }, + "documentation":"<p>Contains summary information about a dataset export job.</p>" + }, + "ExportJobSummaryList":{ + "type":"list", + "member":{"shape":"ExportJobSummary"}, + "documentation":"<p>A list of dataset export job summaries.</p>" + }, "Expression":{ "type":"string", "max":1024, @@ -7481,6 +10975,127 @@ "min":2, "pattern":"[a-zA-Z0-9_][a-zA-Z_\\-0-9.:]*[a-zA-Z0-9_]+" }, + "FailedDataSegmentAssociation":{ + "type":"structure", + "required":[ + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp", + "errorCode", + "errorMessage" + ], + "members":{ + "sourceDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the source dataset.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment.

    " + }, + "errorCode":{ + "shape":"DataSegmentErrorCode", + "documentation":"

    The error code for the failed association.

    " + }, + "errorMessage":{ + "shape":"DataSegmentErrorMessage", + "documentation":"

    The error message for the failed association.

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

    Contains error information for a data segment association that failed.

    " + }, + "FailedDataSegmentAssociations":{ + "type":"list", + "member":{"shape":"FailedDataSegmentAssociation"} + }, + "FailedDataSegmentDeletion":{ + "type":"structure", + "required":[ + "timeSeriesId", + "startTimestamp", + "endTimestamp", + "errorCode", + "errorMessage" + ], + "members":{ + "timeSeriesId":{ + "shape":"ID", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment.

    " + }, + "errorCode":{ + "shape":"DataSegmentErrorCode", + "documentation":"

    The error code for the failed deletion.

    " + }, + "errorMessage":{ + "shape":"DataSegmentErrorMessage", + "documentation":"

    The error message for the failed deletion.

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

    Contains error information for a data segment deletion that failed.

    " + }, + "FailedDataSegmentDeletions":{ + "type":"list", + "member":{"shape":"FailedDataSegmentDeletion"} + }, + "FailedDataSegmentDisassociation":{ + "type":"structure", + "required":[ + "sourceDatasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp", + "errorCode", + "errorMessage" + ], + "members":{ + "sourceDatasetId":{ + "shape":"ID", + "documentation":"

    The ID of the source dataset.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The ID of the time series.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the data segment.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the data segment.

    " + }, + "errorCode":{ + "shape":"DataSegmentErrorCode", + "documentation":"

    The error code for the failed disassociation.

    " + }, + "errorMessage":{ + "shape":"DataSegmentErrorMessage", + "documentation":"

    The error message for the failed disassociation.

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

    Contains error information for a data segment disassociation that failed.

    " + }, + "FailedDataSegmentDisassociations":{ + "type":"list", + "member":{"shape":"FailedDataSegmentDisassociation"} + }, "File":{ "type":"structure", "required":[ @@ -7499,6 +11114,18 @@ "versionId":{ "shape":"String", "documentation":"

    The version ID to identify a specific version of the Amazon S3 object that contains your data.

    " + }, + "alias":{ + "shape":"AssetPropertyAlias", + "documentation":"

    The alias associated with the file's time series.

    " + }, + "startTime":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time for the file data.

    " + }, + "fileFormat":{ + "shape":"FileFormat", + "documentation":"

    The file format of the data in S3.

    " } }, "documentation":"

    The file in Amazon S3 where your data is saved.

    " @@ -7513,6 +11140,14 @@ "parquet":{ "shape":"Parquet", "documentation":"

    The file is in parquet format.

    " + }, + "mp4":{ + "shape":"Mp4", + "documentation":"

    The MP4 format configuration.

    " + }, + "annotation":{ + "shape":"Annotation", + "documentation":"

    The annotation format configuration.

    " } }, "documentation":"

    The file format of the data in S3.

    " @@ -7521,6 +11156,28 @@ "type":"list", "member":{"shape":"File"} }, + "Float":{ + "type":"float", + "box":true + }, + "FormatSettings":{ + "type":"structure", + "members":{ + "framesPerSecond":{ + "shape":"PositiveInteger", + "documentation":"<p>The target frame rate for the output.</p>" + }, + "widthInPixels":{ + "shape":"PositiveInteger", + "documentation":"<p>The target width of the output, in pixels.</p>" + }, + "heightInPixels":{ + "shape":"PositiveInteger", + "documentation":"<p>The target height of the output, in pixels.</p>" + } + }, + "documentation":"<p>Contains the output format configuration for video processing.</p>" + }, "ForwardingConfig":{ "type":"structure", "required":["state"], @@ -7837,9 +11494,88 @@ } } }, - "GetInterpolatedAssetPropertyValuesRequest":{ - "type":"structure", - "required":[ + "GetCaptureDataNextToken":{ + "type":"string", + "documentation":"

    Pagination token for retrieving the next chunk of video data.

    ", + "max":4096, + "min":1 + }, + "GetCaptureDataRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "startTime", + "endTime" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the capture source.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "startTime":{ + "shape":"TimeInNanos", + "documentation":"

    The start time for the video data range.

    " + }, + "endTime":{ + "shape":"TimeInNanos", + "documentation":"

    The end time for the video data range. Must be greater than startTime.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The time series ID that identifies the capture source. Mutually exclusive with propertyAlias.

    " + }, + "propertyAlias":{ + "shape":"AssetPropertyAlias", + "documentation":"

    The property alias that identifies the capture source. Mutually exclusive with timeSeriesId.

    " + }, + "formatSettings":{ + "shape":"FormatSettings", + "documentation":"

    The optional format settings for the output.

    " + }, + "nextToken":{ + "shape":"GetCaptureDataNextToken", + "documentation":"

    The token from a previous response used to continue retrieving data.

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

    Request to retrieve video data for a specific time range. Exactly one of timeSeriesId or propertyAlias must be provided.

    " + }, + "GetCaptureDataResponse":{ + "type":"structure", + "required":[ + "data", + "startTime", + "endTime", + "dataType" + ], + "members":{ + "data":{ + "shape":"CaptureBlob", + "documentation":"

    The binary video data.

    " + }, + "startTime":{ + "shape":"TimeInNanos", + "documentation":"

    The actual start time of the returned data.

    " + }, + "endTime":{ + "shape":"TimeInNanos", + "documentation":"

    The actual end time of the returned data.

    " + }, + "dataType":{ + "shape":"VideoDataType", + "documentation":"

    The type of the returned data.

    " + }, + "nextToken":{ + "shape":"GetCaptureDataNextToken", + "documentation":"

    The token used to retrieve the next chunk. Absent if no more data is available.

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

    Response containing the video data.

    " + }, + "GetInterpolatedAssetPropertyValuesRequest":{ + "type":"structure", + "required":[ "startTimeInSeconds", "endTimeInSeconds", "quality", @@ -7941,6 +11677,112 @@ } } }, + "GetQueryResultsRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "queryId" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace associated with the query.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution.

    ", + "location":"uri", + "locationName":"queryId" + }, + "maxResults":{ + "shape":"QueryMaxResults", + "documentation":"

    The maximum number of results to return for each paginated request.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"QueryNextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "GetQueryResultsResponse":{ + "type":"structure", + "members":{ + "columnInfo":{ + "shape":"ColumnInformationList", + "documentation":"

    A list of column metadata for the query results. Each entry contains the column name and data type. Present when the query status is COMPLETED.

    " + }, + "rows":{ + "shape":"RowList", + "documentation":"

    The result rows. Each row is a list of string column values, positional to match the columnInfo order. Present when the query status is COMPLETED.

    " + }, + "nextToken":{ + "shape":"QueryNextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

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

    Contains the response for the GetQueryResults operation.

    " + }, + "GetSearchResultsRequest":{ + "type":"structure", + "required":[ + "searchId", + "workspaceName" + ], + "members":{ + "searchId":{ + "shape":"SearchId", + "documentation":"

    The identifier of the search whose results are retrieved.

    ", + "location":"uri", + "locationName":"searchId" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search belongs to.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "maxResults":{ + "shape":"GetSearchResultsRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return in a single page. Valid range is 1 to 10,000; if omitted, a service-defined default is used.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token returned by a previous GetSearchResults call. Provide it to retrieve the next page of results; omit it to retrieve the first page.

    ", + "location":"querystring", + "locationName":"nextToken" + } + }, + "documentation":"

    Input for the GetSearchResults operation.

    " + }, + "GetSearchResultsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":10000, + "min":1 + }, + "GetSearchResultsResponse":{ + "type":"structure", + "required":["searchResults"], + "members":{ + "searchResults":{ + "shape":"SearchResultList", + "documentation":"

    A page of search results, ordered by descending relevance score.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token to use in a subsequent GetSearchResults call to retrieve the next page. Absent when there are no more results.

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

    Output of the GetSearchResults operation.

    " + }, "Greengrass":{ "type":"structure", "required":["groupArn"], @@ -7967,6 +11809,20 @@ }, "documentation":"

    Contains details for a gateway that runs on IoT Greengrass V2. To create a gateway that runs on IoT Greengrass V2, you must deploy the IoT SiteWise Edge component to your gateway device. Your Greengrass device role must use the AWSIoTSiteWiseEdgeAccess policy. For more information, see Using IoT SiteWise at the edge in the IoT SiteWise User Guide.

    " }, + "GroupId":{ + "type":"string", + "documentation":"

    A caller-supplied identifier used to group related searches together.

    ", + "max":36, + "min":2, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9-]*" + }, + "GroupIdFilterList":{ + "type":"list", + "member":{"shape":"GroupId"}, + "documentation":"

    A filter on group identifier. Matches searches whose groupId is any of the listed values.

    ", + "max":100, + "min":1 + }, "GroupIdentity":{ "type":"structure", "required":["id"], @@ -8040,6 +11896,14 @@ "min":1, "pattern":"^arn:aws(-cn|-us-gov)?:[a-zA-Z0-9-:\\/_\\.\\+=,@]+$" }, + "IamRoleArn":{ + "type":"string", + "documentation":"

    IAM Role ARN with strict validation requiring a 12-digit account ID. https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateRole.html

    ", + "max":2048, + "min":20, + "pattern":"arn:aws(-cn|-us-gov)?:iam::\\d{12}:role/[\\w+=,.@/-]+", + "sensitive":true + }, "Identity":{ "type":"structure", "members":{ @@ -8305,7 +12169,6 @@ }, "JobConfiguration":{ "type":"structure", - "required":["fileFormat"], "members":{ "fileFormat":{ "shape":"FileFormat", @@ -8352,6 +12215,11 @@ }, "documentation":"

    Contains the job summary information.

    " }, + "JobType":{ + "type":"string", + "documentation":"<p>The type of enrichment job, derived from the job configuration union member</p>", + "enum":["EVENT_DETECTION"] + }, "KendraSourceDetail":{ "type":"structure", "required":[ @@ -8508,6 +12376,37 @@ } } }, + "ListApplicationsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    Maximum number of results to return

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Next Page Token

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListApplicationsResponse":{ + "type":"structure", + "required":["applications"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Next Page Token

    " + }, + "applications":{ + "shape":"ApplicationList", + "documentation":"

    List of applications

    " + } + } + }, "ListAssetModelCompositeModelsRequest":{ "type":"structure", "required":["assetModelId"], @@ -8886,6 +12785,12 @@ "documentation":"

    You can use a filter to select the bulk import jobs that you want to retrieve.

    ", "location":"querystring", "locationName":"filter" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" } } }, @@ -9086,37 +12991,46 @@ } } }, - "ListDatasetsRequest":{ + "ListDatasetDataSegmentRelationshipsRequest":{ "type":"structure", - "required":["sourceType"], + "required":[ + "datasetId", + "workspaceName" + ], "members":{ - "sourceType":{ - "shape":"DatasetSourceType", - "documentation":"

    The type of data source for the dataset.

    ", - "location":"querystring", - "locationName":"sourceType" + "datasetId":{ + "shape":"ID", + "documentation":"

    The ID of the session dataset to list data segment relationships for.

    ", + "location":"uri", + "locationName":"datasetId" }, - "nextToken":{ - "shape":"NextToken", - "documentation":"

    The token for the next set of results, or null if there are no additional results.

    ", + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    ", "location":"querystring", - "locationName":"nextToken" + "locationName":"workspaceName" }, "maxResults":{ "shape":"MaxResults", - "documentation":"

    The maximum number of results to return for each paginated request.

    ", + "documentation":"

    The maximum number of results to return for each paginated request. Default: 50.

    ", "location":"querystring", "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" } } }, - "ListDatasetsResponse":{ + "ListDatasetDataSegmentRelationshipsResponse":{ "type":"structure", - "required":["datasetSummaries"], + "required":["dataSegmentRelationshipSummaries"], "members":{ - "datasetSummaries":{ - "shape":"DatasetSummaries", - "documentation":"

    A list that summarizes the dataset response.

    " + "dataSegmentRelationshipSummaries":{ + "shape":"DataSegmentRelationshipSummaries", + "documentation":"

    A list that summarizes each data segment relationship.

    " }, "nextToken":{ "shape":"NextToken", @@ -9124,64 +13038,52 @@ } } }, - "ListExecutionsRequest":{ + "ListDatasetDataSegmentsRequest":{ "type":"structure", "required":[ - "targetResourceType", - "targetResourceId" + "datasetId", + "workspaceName" ], "members":{ - "targetResourceType":{ - "shape":"TargetResourceType", - "documentation":"

    The type of the target resource.

    ", - "location":"querystring", - "locationName":"targetResourceType" - }, - "targetResourceId":{ + "datasetId":{ "shape":"ID", - "documentation":"

    The ID of the target resource.

    ", - "location":"querystring", - "locationName":"targetResourceId" - }, - "resolveToResourceType":{ - "shape":"ResolveToResourceType", - "documentation":"

    The type of the resolved resource.

    ", - "location":"querystring", - "locationName":"resolveToResourceType" + "documentation":"

    The ID of the dataset.

    ", + "location":"uri", + "locationName":"datasetId" }, - "resolveToResourceId":{ - "shape":"ID", - "documentation":"

    The ID of the resolved resource.

    ", + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    ", "location":"querystring", - "locationName":"resolveToResourceId" + "locationName":"workspaceName" }, - "nextToken":{ - "shape":"NextToken", - "documentation":"

    The token used for the next set of paginated results.

    ", + "datasetVersion":{ + "shape":"Version", + "documentation":"

    The version of the dataset to list data segments for.

    ", "location":"querystring", - "locationName":"nextToken" + "locationName":"datasetVersion" }, "maxResults":{ "shape":"MaxResults", - "documentation":"

    The maximum number of results returned for each paginated request.

    ", + "documentation":"

    The maximum number of results to return for each paginated request. Default: 50.

    ", "location":"querystring", "locationName":"maxResults" }, - "actionType":{ - "shape":"Name", - "documentation":"

    The type of action exectued.

    ", + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", "location":"querystring", - "locationName":"actionType" + "locationName":"nextToken" } } }, - "ListExecutionsResponse":{ + "ListDatasetDataSegmentsResponse":{ "type":"structure", - "required":["executionSummaries"], + "required":["dataSegments"], "members":{ - "executionSummaries":{ - "shape":"ExecutionSummaries", - "documentation":"

    Contains the list of execution summaries of the computation models.

    " + "dataSegments":{ + "shape":"DataSegmentSummaries", + "documentation":"

    A list that summarizes each data segment.

    " }, "nextToken":{ "shape":"NextToken", @@ -9189,43 +13091,301 @@ } } }, - "ListGatewaysRequest":{ + "ListDatasetExportJobsRequest":{ "type":"structure", + "required":["workspaceName"], "members":{ - "nextToken":{ - "shape":"NextToken", - "documentation":"

    The token to be used for the next set of paginated results.

    ", + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace whose dataset export jobs should be listed.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "filter":{ + "shape":"DatasetExportJobFilter", + "documentation":"

    The optional filter that returns only jobs matching the given filter value. Defaults to ALL.

    ", "location":"querystring", - "locationName":"nextToken" + "locationName":"filter" }, "maxResults":{ - "shape":"MaxResults", - "documentation":"

    The maximum number of results to return for each paginated request.

    Default: 50

    ", + "shape":"ListExportJobsMaxResults", + "documentation":"

    The maximum number of results to return for each paginated request.

    ", "location":"querystring", "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListExportJobsNextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" } - } + }, + "documentation":"

    Request to list dataset export jobs for a workspace.

    " }, - "ListGatewaysResponse":{ + "ListDatasetExportJobsResponse":{ "type":"structure", - "required":["gatewaySummaries"], + "required":["jobs"], "members":{ - "gatewaySummaries":{ - "shape":"GatewaySummaries", - "documentation":"

    A list that summarizes each gateway.

    " + "jobs":{ + "shape":"ExportJobSummaryList", + "documentation":"

    A list of dataset export job summaries.

    " }, "nextToken":{ - "shape":"NextToken", + "shape":"ListExportJobsNextToken", "documentation":"

    The token for the next set of results, or null if there are no additional results.

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

    Response for list dataset export jobs request.

    " }, - "ListInterfaceRelationshipsRequest":{ + "ListDatasetsRequest":{ "type":"structure", - "required":["interfaceAssetModelId"], + "required":["sourceType"], "members":{ - "interfaceAssetModelId":{ - "shape":"CustomID", + "sourceType":{ + "shape":"DatasetSourceType", + "documentation":"

    The type of data source for the dataset.

    ", + "location":"querystring", + "locationName":"sourceType" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to filter datasets by.

    ", + "location":"querystring", + "locationName":"workspaceName" + }, + "datasetType":{ + "shape":"DatasetTypeEnum", + "documentation":"

    The type of dataset to filter by: a session dataset, a curated dataset, or a connection to an external datasource.

    ", + "location":"querystring", + "locationName":"datasetType" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return for each paginated request.

    ", + "location":"querystring", + "locationName":"maxResults" + } + } + }, + "ListDatasetsResponse":{ + "type":"structure", + "required":["datasetSummaries"], + "members":{ + "datasetSummaries":{ + "shape":"DatasetSummaries", + "documentation":"

    A list that summarizes the dataset response.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + } + } + }, + "ListEnrichmentJobsRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the IoT SiteWise workspace to list enrichment jobs from.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "datasetId":{ + "shape":"ID", + "documentation":"

    Filter jobs by dataset ID. Returns only jobs analyzing data from the specified dataset.

    ", + "location":"querystring", + "locationName":"datasetId" + }, + "propertyAlias":{ + "shape":"AssetPropertyAlias", + "documentation":"

    Filter by property alias (human-readable sensor name). Specify either propertyAlias or timeSeriesId, but not both. Returns only jobs analyzing the specified property alias.

    ", + "location":"querystring", + "locationName":"propertyAlias" + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    Filter by time series ID (system identifier). Specify either timeSeriesId or propertyAlias, but not both. Returns only jobs analyzing the specified time series.

    ", + "location":"querystring", + "locationName":"timeSeriesId" + }, + "status":{ + "shape":"EnrichmentJobStatus", + "documentation":"

    Filter by job status. Returns only jobs in the specified status. Use RUNNING to find active jobs, or FAILED to identify jobs requiring attention.

    ", + "location":"querystring", + "locationName":"status" + }, + "jobType":{ + "shape":"JobType", + "documentation":"

    Filter by enrichment job type. Currently only EVENT_DETECTION is supported. Use this filter to future-proof queries when additional job types are added.

    ", + "location":"querystring", + "locationName":"jobType" + }, + "startDate":{ + "shape":"Timestamp", + "documentation":"

    The exclusive start of the date range for filtering jobs by creation time. Jobs created after this timestamp are included. Use ISO 8601 format (e.g., 2024-01-01T00:00:00Z).

    ", + "location":"querystring", + "locationName":"startDate" + }, + "endDate":{ + "shape":"Timestamp", + "documentation":"

    The inclusive end of the date range for filtering jobs by creation time. Jobs created on or before this timestamp are included. Use ISO 8601 format (e.g., 2024-01-31T23:59:59Z).

    ", + "location":"querystring", + "locationName":"endDate" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    Maximum number of jobs to return per page. Defaults to 50 if not specified. Use smaller values for faster responses, larger values to reduce API calls.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Pagination token from a previous ListEnrichmentJobs response. Include this token to retrieve the next page of results. Omit for the first request.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListEnrichmentJobsResponse":{ + "type":"structure", + "required":["jobs"], + "members":{ + "jobs":{ + "shape":"EnrichmentJobSummaries", + "documentation":"

    Array of job summaries matching the filter criteria, ordered by creation time descending (newest first). Each summary includes key identifiers (jobId, datasetId, propertyAlias/timeSeriesId) and status information without the full job configuration. Use DescribeEnrichmentJob to retrieve complete details.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Pagination token to retrieve the next page of results. If present, more jobs exist that match the filter criteria. Include this token in a subsequent ListEnrichmentJobs request to retrieve the next page. If absent, you have retrieved all matching jobs.

    " + } + } + }, + "ListExecutionsRequest":{ + "type":"structure", + "required":[ + "targetResourceType", + "targetResourceId" + ], + "members":{ + "targetResourceType":{ + "shape":"TargetResourceType", + "documentation":"

    The type of the target resource.

    ", + "location":"querystring", + "locationName":"targetResourceType" + }, + "targetResourceId":{ + "shape":"ID", + "documentation":"

    The ID of the target resource.

    ", + "location":"querystring", + "locationName":"targetResourceId" + }, + "resolveToResourceType":{ + "shape":"ResolveToResourceType", + "documentation":"

    The type of the resolved resource.

    ", + "location":"querystring", + "locationName":"resolveToResourceType" + }, + "resolveToResourceId":{ + "shape":"ID", + "documentation":"

    The ID of the resolved resource.

    ", + "location":"querystring", + "locationName":"resolveToResourceId" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results returned for each paginated request.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "actionType":{ + "shape":"Name", + "documentation":"

    The type of action exectued.

    ", + "location":"querystring", + "locationName":"actionType" + } + } + }, + "ListExecutionsResponse":{ + "type":"structure", + "required":["executionSummaries"], + "members":{ + "executionSummaries":{ + "shape":"ExecutionSummaries", + "documentation":"

    Contains the list of execution summaries of the computation models.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

    " + } + } + }, + "ListExportJobsMaxResults":{ + "type":"integer", + "documentation":"<p>The maximum number of results to return for each paginated request.</p>", + "box":true, + "max":250, + "min":1 + }, + "ListExportJobsNextToken":{ + "type":"string", + "documentation":"<p>The token to be used for the next set of paginated results.</p>", + "max":4096, + "min":1 + }, + "ListGatewaysRequest":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return for each paginated request.

    Default: 50

    ", + "location":"querystring", + "locationName":"maxResults" + } + } + }, + "ListGatewaysResponse":{ + "type":"structure", + "required":["gatewaySummaries"], + "members":{ + "gatewaySummaries":{ + "shape":"GatewaySummaries", + "documentation":"

    A list that summarizes each gateway.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

    " + } + } + }, + "ListInterfaceRelationshipsRequest":{ + "type":"structure", + "required":["interfaceAssetModelId"], + "members":{ + "interfaceAssetModelId":{ + "shape":"CustomID", "documentation":"

    The ID of the interface asset model. This can be either the actual ID in UUID format, or else externalId: followed by the external ID.

    ", "location":"uri", "locationName":"interfaceAssetModelId" @@ -9258,6 +13418,137 @@ } } }, + "ListPipelineExecutionsRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"ListPipelineExecutionsRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return per request. This is an upper bound; the actual number of results may be less. Default: 50.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "state":{ + "shape":"PipelineExecutionState", + "documentation":"

    Filter by execution state. If not specified, executions in all states are returned.

    ", + "location":"querystring", + "locationName":"state" + }, + "startTimeAfter":{ + "shape":"Timestamp", + "documentation":"

    Inclusive lower bound on execution start time (ISO-8601). Only executions with startTime >= startTimeAfter are returned. Cannot be combined with endTimeAfter or endTimeBefore.

    ", + "location":"querystring", + "locationName":"startTimeAfter" + }, + "startTimeBefore":{ + "shape":"Timestamp", + "documentation":"

    Exclusive upper bound on execution start time (ISO-8601). Only executions with startTime < startTimeBefore are returned. Cannot be combined with endTimeAfter or endTimeBefore.

    ", + "location":"querystring", + "locationName":"startTimeBefore" + }, + "endTimeAfter":{ + "shape":"Timestamp", + "documentation":"

    Inclusive lower bound on execution end time (ISO-8601). Only executions with endTime >= endTimeAfter are returned. Cannot be combined with startTimeAfter or startTimeBefore. Only matches executions in terminal states.

    ", + "location":"querystring", + "locationName":"endTimeAfter" + }, + "endTimeBefore":{ + "shape":"Timestamp", + "documentation":"

    Exclusive upper bound on execution end time (ISO-8601). Only executions with endTime < endTimeBefore are returned. Cannot be combined with startTimeAfter or startTimeBefore. Only matches executions in terminal states.

    ", + "location":"querystring", + "locationName":"endTimeBefore" + } + }, + "documentation":"

    Request structure for ListPipelineExecutions operation.

    " + }, + "ListPipelineExecutionsRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":250, + "min":1 + }, + "ListPipelineExecutionsResponse":{ + "type":"structure", + "required":["pipelineExecutionSummaries"], + "members":{ + "pipelineExecutionSummaries":{ + "shape":"PipelineExecutionSummaryList", + "documentation":"

    A list that summarizes each pipeline execution.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

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

    Response structure for ListPipelineExecutions operation.

    " + }, + "ListPipelinesRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"ListPipelinesRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return for each paginated request. Default: 50.

    ", + "location":"querystring", + "locationName":"maxResults" + } + }, + "documentation":"

    Request structure for ListPipelines operation.

    " + }, + "ListPipelinesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":250, + "min":1 + }, + "ListPipelinesResponse":{ + "type":"structure", + "required":["pipelineSummaries"], + "members":{ + "pipelineSummaries":{ + "shape":"PipelineSummaries", + "documentation":"

    A list that summarizes each pipeline in the workspace.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

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

    Response structure for ListPipelines operation.

    " + }, "ListPortalsRequest":{ "type":"structure", "members":{ @@ -9364,6 +13655,123 @@ } } }, + "ListQueriesRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to list queries for.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "filter":{ + "shape":"QueryFilter", + "documentation":"

    An optional filter to return only queries with the specified status. The value must be one of the supported query statuses: SUBMITTED, RUNNING, COMPLETED, FAILED, CANCELED, or CANCELING.

    ", + "location":"querystring", + "locationName":"filter" + }, + "maxResults":{ + "shape":"QueryMaxResults", + "documentation":"

    The maximum number of results to return for each paginated request.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"QueryListNextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListQueriesResponse":{ + "type":"structure", + "required":["queries"], + "members":{ + "queries":{ + "shape":"QuerySummaryList", + "documentation":"

    A list of query summaries for the workspace.

    " + }, + "nextToken":{ + "shape":"QueryListNextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

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

    Contains the response for the ListQueries operation.

    " + }, + "ListSearchesFilters":{ + "type":"structure", + "members":{ + "statusFilter":{ + "shape":"SearchStatusFilterList", + "documentation":"

    Returns only searches whose status is one of the listed values.

    " + }, + "startedAfter":{ + "shape":"Timestamp", + "documentation":"

    Returns only searches started at or after this time.

    " + }, + "startedBefore":{ + "shape":"Timestamp", + "documentation":"

    Returns only searches started at or before this time.

    " + }, + "groupIdFilter":{ + "shape":"GroupIdFilterList", + "documentation":"

    Returns only searches whose groupId is one of the listed values.

    " + }, + "searchTypeFilter":{ + "shape":"SearchTypeFilterList", + "documentation":"

    Returns only searches whose searchType is one of the listed values.

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

    Optional filters for ListSearches. When multiple filters are set, a search must match all of them.

    " + }, + "ListSearchesRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace whose searches are listed.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "maxResults":{ + "shape":"ListSearchesRequestMaxResultsInteger", + "documentation":"

    The maximum number of searches to return in a single page. Valid range is 1 to 1,000; if omitted, a service-defined default is used.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token returned by a previous ListSearches call. Provide it to retrieve the next page; omit it to retrieve the first page.

    " + }, + "listSearchesFilters":{ + "shape":"ListSearchesFilters", + "documentation":"

    Optional filters that restrict which searches are returned.

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

    Input for the ListSearches operation.

    " + }, + "ListSearchesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "ListSearchesResponse":{ + "type":"structure", + "required":["searchSummaries"], + "members":{ + "searchSummaries":{ + "shape":"SearchSummaries", + "documentation":"

    A page of search summaries, most recently started first.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token to use in a subsequent ListSearches call to retrieve the next page. Absent when there are no more searches.

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

    Output of the ListSearches operation.

    " + }, "ListTagsForResourceRequest":{ "type":"structure", "required":["resourceArn"], @@ -9374,16 +13782,62 @@ "location":"querystring", "locationName":"resourceArn" } - } + } + }, + "ListTagsForResourceResponse":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"TagMap", + "documentation":"

    The list of key-value pairs that contain metadata for the resource. For more information, see Tagging your IoT SiteWise resources in the IoT SiteWise User Guide.

    " + } + } + }, + "ListTasksRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"ListTasksRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return for each paginated request. Default: 50.

    ", + "location":"querystring", + "locationName":"maxResults" + } + }, + "documentation":"

    Request structure for ListTasks operation.

    " }, - "ListTagsForResourceResponse":{ + "ListTasksRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":250, + "min":1 + }, + "ListTasksResponse":{ "type":"structure", + "required":["taskSummaries"], "members":{ - "tags":{ - "shape":"TagMap", - "documentation":"

    The list of key-value pairs that contain metadata for the resource. For more information, see Tagging your IoT SiteWise resources in the IoT SiteWise User Guide.

    " + "taskSummaries":{ + "shape":"TaskSummaries", + "documentation":"

    A list that summarizes each task in the workspace.

    " + }, + "nextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token to be used for the next set of paginated results.

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

    Response structure for ListTasks operation.

    " }, "ListTimeSeriesRequest":{ "type":"structure", @@ -9417,6 +13871,12 @@ "documentation":"

    The type of the time series. The time series type can be one of the following values:

    • ASSOCIATED – The time series is associated with an asset property.

    • DISASSOCIATED – The time series isn't associated with any asset property.

    ", "location":"querystring", "locationName":"timeSeriesType" + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"querystring", + "locationName":"workspaceName" } } }, @@ -9431,6 +13891,10 @@ "nextToken":{ "shape":"NextToken", "documentation":"

    The token for the next set of results, or null if there are no additional results.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " } } }, @@ -9441,6 +13905,37 @@ "DISASSOCIATED" ] }, + "ListWorkspacesRequest":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token to be used for the next set of paginated results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return for each paginated request. Default: 50.

    ", + "location":"querystring", + "locationName":"maxResults" + } + } + }, + "ListWorkspacesResponse":{ + "type":"structure", + "required":["workspaceSummaries"], + "members":{ + "workspaceSummaries":{ + "shape":"WorkspaceSummaries", + "documentation":"

    A list that summarizes each workspace.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no additional results.

    " + } + } + }, "Location":{ "type":"structure", "members":{ @@ -9470,6 +13965,10 @@ }, "documentation":"

    Contains logging options.

    " }, + "Long":{ + "type":"long", + "box":true + }, "Macro":{ "type":"string", "max":256, @@ -9524,6 +14023,21 @@ "min":1, "sensitive":true }, + "Metadata":{ + "type":"map", + "key":{"shape":"MetadataKey"}, + "value":{"shape":"MetadataValue"} + }, + "MetadataKey":{ + "type":"string", + "max":128, + "min":1 + }, + "MetadataValue":{ + "type":"string", + "max":2048, + "min":0 + }, "Metric":{ "type":"structure", "required":["window"], @@ -9591,6 +14105,93 @@ "documentation":"

    Contains IoT SiteWise Monitor error details.

    " }, "MonitorErrorMessage":{"type":"string"}, + "Mount":{ + "type":"structure", + "required":[ + "name", + "relativePath", + "source", + "storageType" + ], + "members":{ + "name":{ + "shape":"ResourceName", + "documentation":"

    A unique name for the mount within the task.

    " + }, + "relativePath":{ + "shape":"MountRelativePath", + "documentation":"

    The relative path under the service-owned mount root where this mount is attached inside the container.

    " + }, + "source":{ + "shape":"MountSource", + "documentation":"

    The data source for the mount.

    " + }, + "storageType":{ + "shape":"MountStorageType", + "documentation":"

    The type of storage used for the mount.

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

    Attaches a data source to the container filesystem for a task at a customer-supplied relative path under the service-owned mount root.

    " + }, + "MountList":{ + "type":"list", + "member":{"shape":"Mount"}, + "documentation":"

    A list of mounts for a task. Each mount attaches an external data source to the container filesystem at a customer-supplied relative path under the service-owned mount root.

    ", + "max":5, + "min":0 + }, + "MountOverrides":{ + "type":"structure", + "required":["computeNodes"], + "members":{ + "computeNodes":{ + "shape":"ComputeNodeMountsMap", + "documentation":"

    The mount overrides for each compute node, keyed by compute node name.

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

    Runtime mount overrides applied to a single pipeline execution. Overrides are transient — they do not modify the stored task configuration.

    " + }, + "MountRelativePath":{ + "type":"string", + "documentation":"

    A relative path under the service-owned mount root where this mount is attached inside the container.

    ", + "max":1024, + "min":1, + "pattern":"((?!.*(^|/)\\.\\.?(/|$))(?!.*//)[a-zA-Z0-9._-][a-zA-Z0-9._/-]*[a-zA-Z0-9._-]|[a-zA-Z0-9_-])" + }, + "MountS3AccessPointArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon S3 access point. The mount reads objects from the bucket associated with this access point. Access is governed by the access point policy and the task execution role's IAM permissions.

    ", + "max":128, + "min":4, + "pattern":"arn:aws(-cn|-us-gov)?:s3:[a-z0-9-]*:\\d{12}:accesspoint[/:][a-zA-Z0-9._-]+" + }, + "MountS3KeyPrefix":{ + "type":"string", + "documentation":"

    An object key name prefix. If specified, the mount includes only objects whose keys begin with this prefix. The maximum prefix length is 1,024 characters. To include all objects at the access point, omit this field.

    ", + "max":1024, + "min":1 + }, + "MountSource":{ + "type":"structure", + "members":{ + "s3AccessPoint":{ + "shape":"S3AccessPointSource", + "documentation":"

    Configuration for a mount that reads from an Amazon S3 access point.

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

    The data source configuration for a mount. Specify exactly one of the following.

    ", + "union":true + }, + "MountStorageType":{ + "type":"string", + "documentation":"

    The type of storage used for a mount inside the container.

    ", + "enum":["SHARED_STORAGE"] + }, + "Mp4":{ + "type":"structure", + "members":{}, + "documentation":"

    The MP4 video format configuration for bulk import files.

    " + }, "MultiLayerStorage":{ "type":"structure", "required":["customerManagedS3Storage"], @@ -9629,6 +14230,12 @@ "max":999999999, "min":0 }, + "PaginationToken":{ + "type":"string", + "documentation":"

    An opaque pagination token. Pass the value returned by a previous request to retrieve the next page of results.

    ", + "max":4096, + "min":1 + }, "Parquet":{ "type":"structure", "members":{}, @@ -9641,6 +14248,149 @@ "VIEWER" ] }, + "PipelineErrorCode":{ + "type":"string", + "documentation":"

    Classification of a pipeline execution failure.

    ", + "enum":[ + "VALIDATION_ERROR", + "INTERNAL_FAILURE", + "EXECUTION_ERROR", + "TIMED_OUT" + ] + }, + "PipelineExecutionState":{ + "type":"string", + "documentation":"

    The state of a pipeline execution.

    ", + "enum":[ + "NOT_STARTED", + "RUNNING", + "SUCCEEDED", + "FAILED", + "CANCELLING", + "CANCELLED" + ] + }, + "PipelineExecutionStateDetails":{ + "type":"structure", + "required":["message"], + "members":{ + "code":{ + "shape":"PipelineErrorCode", + "documentation":"

    Classification of the failure. Present when the execution failed.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    Human-readable description of the outcome. For a failed execution, this describes why it failed; for a cancelled execution, this is the reason you supplied when calling CancelPipelineExecution.

    " + }, + "details":{ + "shape":"DetailedErrorList", + "documentation":"

    Per-step error entries to help diagnose a failed execution. Present when the execution failed.

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

    Additional information about the current execution status. Populated when the execution has terminated.

    " + }, + "PipelineExecutionStatus":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"PipelineExecutionState", + "documentation":"

    Current state of the pipeline execution.

    " + }, + "stateDetails":{ + "shape":"PipelineExecutionStateDetails", + "documentation":"

    Additional information about the execution outcome. Populated when the execution has terminated (failed or cancelled).

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

    Current execution status of a pipeline.

    " + }, + "PipelineExecutionSummary":{ + "type":"structure", + "required":[ + "pipelineExecutionId", + "pipelineVersion", + "status" + ], + "members":{ + "pipelineExecutionId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the pipeline execution.

    " + }, + "pipelineVersion":{ + "shape":"Version", + "documentation":"

    The pipeline version this execution ran against.

    " + }, + "status":{ + "shape":"PipelineExecutionStatus", + "documentation":"

    The current execution status of the pipeline.

    " + }, + "executionPriority":{ + "shape":"ExecutionPriority", + "documentation":"

    Scheduling priority for the execution. When not specified, defaults to lowest priority.

    " + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline execution started, in Unix epoch time.

    " + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline execution completed, in Unix epoch time.

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

    Contains summary information about a pipeline execution.

    " + }, + "PipelineExecutionSummaryList":{ + "type":"list", + "member":{"shape":"PipelineExecutionSummary"}, + "documentation":"

    A list of pipeline execution summaries.

    " + }, + "PipelineSummaries":{ + "type":"list", + "member":{"shape":"PipelineSummary"}, + "documentation":"

    A list of pipeline summaries.

    " + }, + "PipelineSummary":{ + "type":"structure", + "required":[ + "pipelineName", + "pipelineArn", + "version", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the pipeline.

    " + }, + "pipelineArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the pipeline.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the pipeline.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the pipeline.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The time the pipeline was last updated, in Unix epoch time.

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

    Contains summary information about a pipeline.

    " + }, "PortalClientId":{ "type":"string", "max":256, @@ -9764,6 +14514,12 @@ "max":128, "min":1 }, + "PositiveInteger":{ + "type":"integer", + "documentation":"<p>A positive integer used for frames per second and video dimensions.</p>", + "box":true, + "min":1 + }, "PreconditionFailedException":{ "type":"structure", "required":[ @@ -9787,6 +14543,49 @@ "exception":true }, "PrimitiveBoolean":{"type":"boolean"}, + "ProcessingInput":{ + "type":"structure", + "members":{ + "timeseries":{ + "shape":"TimeseriesList", + "documentation":"<p>List of individual timeseries items to process.</p>" + }, + "dataset":{ + "shape":"DatasetItem", + "documentation":"<p>A dataset containing multiple items to process.</p>" + } + }, + "documentation":"<p>Input source for processing. Specify exactly one option.</p>", + "union":true + }, + "ProcessingType":{ + "type":"string", + "documentation":"

    The processing type for compute resources. Determines whether the task runs on standard CPU or GPU-accelerated hardware.

    ", + "enum":[ + "GENERIC_COMPUTE_PROCESSING", + "HARDWARE_ACCELERATED_PROCESSING" + ] + }, + "ProcessingUnit":{ + "type":"string", + "documentation":"

    The processing unit allocation that determines the vCPU, memory, and GPU resources assigned to a task. Available units depend on the processing type.

    ", + "enum":[ + "UNITS_2", + "UNITS_4", + "UNITS_8", + "UNITS_12", + "UNITS_16", + "UNITS_24", + "UNITS_32", + "UNITS_36", + "UNITS_48", + "UNITS_60", + "UNITS_64", + "UNITS_72", + "UNITS_84", + "UNITS_96" + ] + }, "ProjectResource":{ "type":"structure", "required":["id"], @@ -9891,7 +14690,10 @@ "INTEGER", "DOUBLE", "BOOLEAN", - "STRUCT" + "STRUCT", + "VIDEO", + "ANNOTATION", + "JSON" ] }, "PropertyMapping":{ @@ -10134,6 +14936,10 @@ "loggingOptions":{ "shape":"LoggingOptions", "documentation":"

    The logging options to set.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " } } }, @@ -10197,34 +15003,148 @@ "shape":"WarmTierState", "documentation":"

    A service managed storage tier optimized for analytical queries. It stores periodically uploaded, buffered and historical data ingested with the CreaeBulkImportJob API.

    " }, - "warmTierRetentionPeriod":{ - "shape":"WarmTierRetentionPeriod", - "documentation":"

    Set this period to specify how long your data is stored in the warm tier before it is deleted. You can set this only if cold tier is enabled.

    " + "warmTierRetentionPeriod":{ + "shape":"WarmTierRetentionPeriod", + "documentation":"

    Set this period to specify how long your data is stored in the warm tier before it is deleted. You can set this only if cold tier is enabled.

    " + }, + "disallowIngestNullNaN":{ + "shape":"DisallowIngestNullNaN", + "documentation":"

    Describes the configuration for ingesting NULL and NaN data. By default the feature is allowed. The feature is disallowed if the value is true.

    " + } + } + }, + "Qualities":{ + "type":"list", + "member":{"shape":"Quality"}, + "max":1, + "min":1 + }, + "Quality":{ + "type":"string", + "enum":[ + "GOOD", + "BAD", + "UNCERTAIN" + ] + }, + "QueryErrorMessage":{ + "type":"string", + "documentation":"

    A human-readable error description for a failed query.

    ", + "max":1024, + "min":0 + }, + "QueryFilter":{ + "type":"string", + "documentation":"

    Filter for ListQueries. Returns only queries with the specified status.

    ", + "max":64, + "min":1 + }, + "QueryId":{ + "type":"string", + "documentation":"

    The unique identifier for a query execution.

    ", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9-]+" + }, + "QueryListNextToken":{ + "type":"string", + "documentation":"

    Pagination token for the query list.

    ", + "max":4096, + "min":1 + }, + "QueryMaxResults":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for each paginated request.

    ", + "box":true, + "max":10000, + "min":1 + }, + "QueryNextToken":{ + "type":"string", + "documentation":"

    Pagination token for query results.

    ", + "max":4096, + "min":1 + }, + "QueryStatement":{ + "type":"string", + "max":10000, + "min":1, + "pattern":"^[\\s\\S]+$", + "sensitive":true + }, + "QueryStatistics":{ + "type":"structure", + "required":[ + "rowCount", + "bytesScanned", + "executionTimeInMillis" + ], + "members":{ + "rowCount":{ + "shape":"Long", + "documentation":"

    The total number of rows returned by the query.

    " + }, + "bytesScanned":{ + "shape":"Long", + "documentation":"

    The total number of bytes scanned during query execution.

    " }, - "disallowIngestNullNaN":{ - "shape":"DisallowIngestNullNaN", - "documentation":"

    Describes the configuration for ingesting NULL and NaN data. By default the feature is allowed. The feature is disallowed if the value is true.

    " + "executionTimeInMillis":{ + "shape":"Long", + "documentation":"

    The total query execution time, in milliseconds.

    " } - } - }, - "Qualities":{ - "type":"list", - "member":{"shape":"Quality"}, - "max":1, - "min":1 + }, + "documentation":"

    Contains statistics about a completed query execution.

    " }, - "Quality":{ + "QueryStatus":{ "type":"string", + "documentation":"

    The status of a query execution.

    ", "enum":[ - "GOOD", - "BAD", - "UNCERTAIN" + "SUBMITTED", + "RUNNING", + "COMPLETED", + "FAILED", + "CANCELED", + "CANCELING" ] }, - "QueryStatement":{ + "QueryString":{ "type":"string", + "documentation":"

    The SQL query statement.

    ", + "max":10240, "min":1, - "pattern":"^[\\s\\S]+$" + "sensitive":true + }, + "QuerySummary":{ + "type":"structure", + "required":[ + "queryId", + "status", + "submittedAt" + ], + "members":{ + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution.

    " + }, + "status":{ + "shape":"QueryStatus", + "documentation":"

    The current query status.

    " + }, + "submittedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the query was submitted, in Unix epoch time.

    " + }, + "completedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the query reached a terminal state, in Unix epoch time.

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

    Contains summary information about a query.

    " + }, + "QuerySummaryList":{ + "type":"list", + "member":{"shape":"QuerySummary"}, + "documentation":"

    A list of query summaries.

    " }, "QueryTimeoutException":{ "type":"structure", @@ -10313,7 +15233,36 @@ "exception":true }, "ResourceArn":{"type":"string"}, + "ResourceError":{ + "type":"structure", + "members":{ + "code":{ + "shape":"ResourceErrorCode", + "documentation":"

    The error code.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    The error message.

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

    Contains the details of a resource error.

    " + }, + "ResourceErrorCode":{ + "type":"string", + "documentation":"

    The error code.

    ", + "enum":[ + "VALIDATION_ERROR", + "INTERNAL_FAILURE" + ] + }, "ResourceId":{"type":"string"}, + "ResourceName":{ + "type":"string", + "documentation":"

    Reusable resource name with alphanumeric, hyphen, and underscore characters.

    ", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9_-]+" + }, "ResourceNotFoundException":{ "type":"structure", "required":["message"], @@ -10324,6 +15273,31 @@ "error":{"httpStatusCode":404}, "exception":true }, + "ResourceState":{ + "type":"string", + "documentation":"

    The lifecycle state of a resource.

    ", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "FAILED" + ] + }, + "ResourceStatus":{ + "type":"structure", + "members":{ + "error":{ + "shape":"ResourceError", + "documentation":"

    Contains associated error information, if any.

    " + }, + "state":{ + "shape":"ResourceState", + "documentation":"

    The current status of the resource.

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

    Contains information about the current status of a resource.

    " + }, "ResourceType":{ "type":"string", "enum":[ @@ -10363,7 +15337,13 @@ "type":"string", "max":256, "min":1, - "pattern":"^[a-zA-Z0-9 _\\-#$*!@]+$" + "pattern":"^[a-zA-Z0-9 _\\-#$*!@.]+$" + }, + "Result":{ + "type":"list", + "member":{"shape":"ColumnValue"}, + "documentation":"

    A single row of query results containing column values. Each element is a string-encoded column value, positional to match the columnInfo order.

    ", + "sparse":true }, "ResultProperty":{ "type":"string", @@ -10396,10 +15376,37 @@ }, "documentation":"

    Represents a single row in the query results.

    " }, + "RowList":{ + "type":"list", + "member":{"shape":"Result"}, + "documentation":"

    A list of result rows returned by the query. Each element is a row containing column values.

    " + }, "Rows":{ "type":"list", "member":{"shape":"Row"} }, + "S3AccessPointSource":{ + "type":"structure", + "required":["accessPointArn"], + "members":{ + "accessPointArn":{ + "shape":"MountS3AccessPointArn", + "documentation":"

    The Amazon Resource Name (ARN) of the S3 access point.

    " + }, + "prefix":{ + "shape":"MountS3KeyPrefix", + "documentation":"

    An optional key prefix to scope the mount to a subset of objects at the access point.

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

    Configures a mount that reads from an Amazon S3 access point.

    " + }, + "S3Uri":{ + "type":"string", + "documentation":"<p>An S3 URI identifying an object location, in the form s3://bucket/key.</p>", + "max":1024, + "min":1, + "pattern":"s3://[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]/.+" + }, "SSOApplicationId":{ "type":"string", "max":64, @@ -10417,6 +15424,173 @@ ] }, "ScalarValue":{"type":"string"}, + "SearchFilters":{ + "type":"structure", + "members":{ + "timeSeriesIds":{ + "shape":"TimeSeriesIdList", + "documentation":"

    Restricts the search to these time series.

    " + }, + "datasetIds":{ + "shape":"DataSetIdList", + "documentation":"

    Restricts the search to these datasets.

    " + }, + "timeIntervals":{ + "shape":"TimeIntervalList", + "documentation":"

    Restricts the search to these time intervals.

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

    Optional filters that restrict a search to a subset of the workspace's data.

    " + }, + "SearchId":{ + "type":"string", + "documentation":"

    The unique identifier of a search, assigned by the service when the search is started.

    ", + "max":36, + "min":23, + "pattern":"[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*" + }, + "SearchQueryStatement":{ + "type":"string", + "documentation":"

    A natural-language query describing the data to search for. Treated as sensitive and not logged.

    ", + "max":5000, + "min":1, + "sensitive":true + }, + "SearchResult":{ + "type":"structure", + "required":[ + "searchId", + "workspaceName", + "datasetId", + "timeSeriesId", + "startTimestamp", + "endTimestamp", + "topTimestamp", + "score" + ], + "members":{ + "searchId":{ + "shape":"SearchId", + "documentation":"

    The identifier of the search that produced this result.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search ran against.

    " + }, + "datasetId":{ + "shape":"DatasetId", + "documentation":"

    The identifier of the dataset that contains the matching data.

    " + }, + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"

    The identifier of the time series that contains the matching data.

    " + }, + "startTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The start of the matching time-series segment, in nanoseconds since the Unix epoch.

    " + }, + "endTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The end of the matching time-series segment, in nanoseconds since the Unix epoch.

    " + }, + "topTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The timestamp of the most relevant point within the matching segment, in nanoseconds since the Unix epoch.

    " + }, + "score":{ + "shape":"Float", + "documentation":"

    The relevance score of this result. Higher scores indicate a stronger match.

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

    A single matching segment of time-series data returned by a search.

    " + }, + "SearchResultList":{ + "type":"list", + "member":{"shape":"SearchResult"}, + "documentation":"

    A list of search results, ordered by descending relevance score.

    " + }, + "SearchStatus":{ + "type":"string", + "documentation":"

    The lifecycle status of a search.

    ", + "enum":[ + "QUEUED", + "RUNNING", + "SUCCEEDED", + "FAILED" + ] + }, + "SearchStatusFilterList":{ + "type":"list", + "member":{"shape":"SearchStatus"}, + "documentation":"

    A filter on search status. Matches searches whose status is any of the listed values.

    ", + "max":4, + "min":1 + }, + "SearchSummaries":{ + "type":"list", + "member":{"shape":"SearchSummary"}, + "documentation":"

    A list of search summaries returned by ListSearches.

    " + }, + "SearchSummary":{ + "type":"structure", + "required":[ + "searchId", + "workspaceName", + "status", + "queryStatement", + "searchType" + ], + "members":{ + "searchId":{ + "shape":"SearchId", + "documentation":"

    The unique identifier of the search.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search runs against.

    " + }, + "status":{ + "shape":"SearchStatus", + "documentation":"

    The current status of the search.

    " + }, + "queryStatement":{ + "shape":"SearchQueryStatement", + "documentation":"

    The natural-language query that was submitted for the search.

    " + }, + "searchType":{ + "shape":"SearchType", + "documentation":"

    The search strategy used for the search.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable explanation of the current status. Populated when the search has FAILED.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The time at which the search was started.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    The group identifier associated with the search, if one was supplied on the request.

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

    A summary of a single search as returned by ListSearches.

    " + }, + "SearchType":{ + "type":"string", + "documentation":"

    The search strategy, which trades off latency against recall. DEEP runs the full semantic and structured search for the highest-quality matches; QUICK returns faster, lower-recall results. When searchType is omitted on a request, the search defaults to QUICK.

    ", + "enum":[ + "DEEP", + "QUICK" + ] + }, + "SearchTypeFilterList":{ + "type":"list", + "member":{"shape":"SearchType"}, + "documentation":"

    A filter on search type. Matches searches whose searchType is any of the listed values.

    ", + "max":2, + "min":1 + }, "SelectAll":{ "type":"string", "pattern":"\\*" @@ -10432,6 +15606,24 @@ "exception":true, "fault":true }, + "SessionConfig":{ + "type":"structure", + "required":[ + "sessionStartTimestamp", + "sessionEndTimestamp" + ], + "members":{ + "sessionStartTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision start time of the session.

    " + }, + "sessionEndTimestamp":{ + "shape":"TimeInNanos", + "documentation":"

    The nanosecond-precision end time of the session.

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

    Contains the session configuration for a session-type dataset.

    " + }, "SiemensIE":{ "type":"structure", "required":["iotCoreThingName"], @@ -10465,7 +15657,173 @@ "documentation":"

    Contains details about the Kendra dataset source.

    " } }, - "documentation":"

    The details of the dataset source associated with the dataset.

    " + "documentation":"

    The details of the dataset source associated with the dataset.

    " + }, + "StartPipelineExecutionRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace containing the pipeline.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline to execute.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "executionEnvironmentVariableOverrides":{ + "shape":"ExecutionEnvironmentVariables", + "documentation":"

    Runtime environment variable overrides for the execution. Includes global variables that apply to all compute nodes and computeNodes for per-node overrides. These take the highest priority in the environment variable hierarchy.

    " + }, + "executionMountOverrides":{ + "shape":"MountOverrides", + "documentation":"

    Runtime mount overrides for the execution. Overrides are merged by mount name into each listed compute node's task-defined mounts: a matching name replaces the task-defined mount, a new name adds a mount, and task-defined mounts not referenced remain unchanged. Compute nodes not listed use their task-defined mounts as-is.

    " + }, + "executionPriority":{ + "shape":"ExecutionPriority", + "documentation":"

    Scheduling priority for the execution. Lower values indicate higher priority. Defaults to 2 when not specified.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. If you retry a request that completed successfully using the same client token, the server returns the cached result from the original successful request without performing the operation again.

    ", + "idempotencyToken":true + } + }, + "documentation":"

    Request structure for StartPipelineExecution operation.

    " + }, + "StartPipelineExecutionResponse":{ + "type":"structure", + "required":["pipelineExecutionId"], + "members":{ + "pipelineExecutionId":{ + "shape":"ID", + "documentation":"

    The unique identifier of the created pipeline execution.

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

    Response structure for StartPipelineExecution operation.

    " + }, + "StartQueryRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "queryStatement" + ], + "members":{ + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique case-sensitive identifier that you can provide to ensure the idempotency of the request. Don't reuse this client token if a new idempotent request is required.

    ", + "idempotencyToken":true + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to query.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "queryStatement":{ + "shape":"QueryString", + "documentation":"

    The SQL query to execute against the workspace telemetry, annotations, data segment, and dataset data.

    " + } + } + }, + "StartQueryResponse":{ + "type":"structure", + "required":[ + "queryId", + "status" + ], + "members":{ + "queryId":{ + "shape":"QueryId", + "documentation":"

    The unique identifier for the query execution.

    " + }, + "status":{ + "shape":"QueryStatus", + "documentation":"

    The initial query status. The value is always SUBMITTED upon creation.

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

    Contains the response for the StartQuery operation.

    " + }, + "StartSearchRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "queryStatement" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace whose data is searched.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "queryStatement":{ + "shape":"SearchQueryStatement", + "documentation":"

    The natural-language query describing the data to search for.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier you provide to ensure the request is idempotent. Repeating a StartSearch call with the same clientToken returns the original search rather than starting a new one. If omitted, the SDK autogenerates one.

    ", + "idempotencyToken":true + }, + "searchType":{ + "shape":"SearchType", + "documentation":"

    The search strategy to use. Defaults to QUICK when omitted.

    " + }, + "searchFilters":{ + "shape":"SearchFilters", + "documentation":"

    Optional filters that restrict the search to a subset of the workspace's data.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    An optional caller-supplied identifier used to group related searches together.

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

    Input for the StartSearch operation.

    " + }, + "StartSearchResponse":{ + "type":"structure", + "required":[ + "searchId", + "workspaceName", + "status" + ], + "members":{ + "searchId":{ + "shape":"SearchId", + "documentation":"

    The unique identifier assigned to the newly started search.

    " + }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace the search runs against.

    " + }, + "status":{ + "shape":"SearchStatus", + "documentation":"

    The initial status of the search. A newly started search is QUEUED.

    " + }, + "groupId":{ + "shape":"GroupId", + "documentation":"

    The group identifier associated with the search, if one was supplied on the request.

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

    Output of the StartSearch operation.

    " + }, + "StorageClass":{ + "type":"string", + "documentation":"

    The storage type that determines I/O performance characteristics. Family name indicates workload pattern, level number indicates performance within that family.

    ", + "enum":[ + "STANDARD_1", + "STANDARD_2", + "THROUGHPUT_1", + "THROUGHPUT_2" + ] }, "StorageType":{ "type":"string", @@ -10542,6 +15900,64 @@ "COMPUTATION_MODEL" ] }, + "TaskConfiguration":{ + "type":"structure", + "members":{ + "containerTaskConfiguration":{ + "shape":"ContainerTaskConfiguration", + "documentation":"

    Configuration for running a custom container image on managed compute.

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

    The task execution configuration. Specify a containerTaskConfiguration for a custom container workload.

    ", + "union":true + }, + "TaskSummaries":{ + "type":"list", + "member":{"shape":"TaskSummary"}, + "documentation":"

    A list of task summaries.

    " + }, + "TaskSummary":{ + "type":"structure", + "required":[ + "taskName", + "taskArn", + "version", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task.

    " + }, + "description":{ + "shape":"Description", + "documentation":"

    The description of the task.

    " + }, + "taskArn":{ + "shape":"ARN", + "documentation":"

    The ARN of the task.

    " + }, + "version":{ + "shape":"Version", + "documentation":"

    The version of the task.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the task.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The time the task was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The time the task was last updated, in Unix epoch time.

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

    Contains summary information about a task.

    " + }, "ThrottlingException":{ "type":"structure", "required":["message"], @@ -10572,6 +15988,31 @@ "max":9223372036854774, "min":1 }, + "TimeInterval":{ + "type":"structure", + "required":[ + "startTime", + "endTime" + ], + "members":{ + "startTime":{ + "shape":"TimeInNanos", + "documentation":"

    The start of the time interval.

    " + }, + "endTime":{ + "shape":"TimeInNanos", + "documentation":"

    The end of the time interval.

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

    Contains a time interval with a start time and an end time. Use a time interval to restrict an operation, such as a search, to a specific time range.

    " + }, + "TimeIntervalList":{ + "type":"list", + "member":{"shape":"TimeInterval"}, + "documentation":"

    A list of time intervals to restrict a search to.

    ", + "max":100, + "min":1 + }, "TimeOrdering":{ "type":"string", "enum":[ @@ -10584,6 +16025,13 @@ "max":73, "min":36 }, + "TimeSeriesIdList":{ + "type":"list", + "member":{"shape":"TimeSeriesId"}, + "documentation":"

    A list of time-series identifiers to restrict a search to.

    ", + "max":100, + "min":1 + }, "TimeSeriesSummaries":{ "type":"list", "member":{"shape":"TimeSeriesSummary"} @@ -10637,6 +16085,42 @@ }, "documentation":"

    Contains a summary of a time series (data stream).

    " }, + "TimeoutSeconds":{ + "type":"long", + "documentation":"

    The timeout in seconds for task execution. Default: 3600 (1 hour).

    ", + "box":true, + "max":86400, + "min":60 + }, + "TimeseriesItem":{ + "type":"structure", + "members":{ + "timeSeriesId":{ + "shape":"TimeSeriesId", + "documentation":"<p>The unique identifier for the timeseries. Mutually exclusive with propertyAlias.</p>" + }, + "propertyAlias":{ + "shape":"AssetPropertyAlias", + "documentation":"<p>The customer-friendly alias for the timeseries. Mutually exclusive with timeSeriesId.</p>" + }, + "trimSettings":{ + "shape":"TrimSettings", + "documentation":"<p>The trim settings for the time range to export. Required for VIDEO and TELEMETRY data types; optional for ANNOTATION data types.</p>" + }, + "formatSettings":{ + "shape":"FormatSettings", + "documentation":"<p>The optional format settings for the output.</p>" + } + }, + "documentation":"<p>A single timeseries item to process. Exactly one of timeSeriesId or propertyAlias must be provided.</p>" + }, + "TimeseriesList":{ + "type":"list", + "member":{"shape":"TimeseriesItem"}, + "documentation":"<p>A list of timeseries items to process.</p>", + "max":100, + "min":1 + }, "Timestamp":{"type":"timestamp"}, "Timestamps":{ "type":"list", @@ -10711,6 +16195,24 @@ "type":"string", "enum":["PATH_TO_ROOT"] }, + "TrimSettings":{ + "type":"structure", + "required":[ + "startTime", + "endTime" + ], + "members":{ + "startTime":{ + "shape":"TimeInNanos", + "documentation":"<p>The start time for the trim range.</p>" + }, + "endTime":{ + "shape":"TimeInNanos", + "documentation":"<p>The end time for the trim range. Must be greater than startTime.</p>" + } + }, + "documentation":"<p>Contains settings for trimming content to a specific time range.</p>" + }, "TumblingWindow":{ "type":"structure", "required":["interval"], @@ -10872,7 +16374,11 @@ "shape":"AssetModelCompositeModelPath", "documentation":"

    The path to the composite model listing the parent composite models.

    " }, - "assetModelStatus":{"shape":"AssetModelStatus"} + "assetModelStatus":{"shape":"AssetModelStatus"}, + "assetModelId":{ + "shape":"ID", + "documentation":"

    The ID of the asset model.

    " + } } }, "UpdateAssetModelRequest":{ @@ -10941,6 +16447,10 @@ "type":"structure", "required":["assetModelStatus"], "members":{ + "assetModelId":{ + "shape":"ID", + "documentation":"

    The ID of the asset model.

    " + }, "assetModelStatus":{ "shape":"AssetModelStatus", "documentation":"

    The status of the asset model, which contains a state (UPDATING after successfully calling this operation) and any error message.

    " @@ -11021,6 +16531,10 @@ "type":"structure", "required":["assetStatus"], "members":{ + "assetId":{ + "shape":"ID", + "documentation":"

    The ID of the asset.

    " + }, "assetStatus":{ "shape":"AssetStatus", "documentation":"

    The status of the asset, which contains a state (UPDATING after successfully calling this operation) and any error message.

    " @@ -11126,14 +16640,26 @@ "location":"uri", "locationName":"datasetId" }, + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace that contains the dataset.

    " + }, "datasetName":{ "shape":"RestrictedName", "documentation":"

    The name of the dataset.

    " }, "datasetDescription":{ - "shape":"RestrictedDescription", + "shape":"Description", "documentation":"

    A description about the dataset, and its functionality.

    " }, + "datasetConfig":{ + "shape":"DatasetConfig", + "documentation":"

    The updated configuration for the dataset.

    " + }, + "metadata":{ + "shape":"Metadata", + "documentation":"

    The updated metadata for the dataset.

    " + }, "datasetSource":{ "shape":"DatasetSource", "documentation":"

    The data source for the dataset.

    " @@ -11222,6 +16748,58 @@ } } }, + "UpdatePipelineRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "pipelineName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "pipelineName":{ + "shape":"ResourceName", + "documentation":"

    The name of the pipeline to update.

    ", + "location":"uri", + "locationName":"pipelineName" + }, + "description":{ + "shape":"Description", + "documentation":"

    A new description for the pipeline.

    " + }, + "environmentVariables":{ + "shape":"EnvironmentVariablesMap", + "documentation":"

    Updated environment variables shared across all compute nodes.

    " + }, + "computations":{ + "shape":"ComputeNodeList", + "documentation":"

    Updated list of compute nodes forming the pipeline DAG.

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

    Request structure for UpdatePipeline operation.

    " + }, + "UpdatePipelineResponse":{ + "type":"structure", + "required":[ + "version", + "status" + ], + "members":{ + "version":{ + "shape":"Version", + "documentation":"

    The new version of the pipeline created by this update.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the pipeline.

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

    Response structure for UpdatePipeline operation.

    " + }, "UpdatePortalRequest":{ "type":"structure", "required":[ @@ -11319,6 +16897,89 @@ "type":"structure", "members":{} }, + "UpdateTaskRequest":{ + "type":"structure", + "required":[ + "workspaceName", + "taskName" + ], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "taskName":{ + "shape":"ResourceName", + "documentation":"

    The name of the task to update.

    ", + "location":"uri", + "locationName":"taskName" + }, + "description":{ + "shape":"Description", + "documentation":"

    A new description for the task.

    " + }, + "taskConfiguration":{ + "shape":"TaskConfiguration", + "documentation":"

    The updated task execution configuration.

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

    Request structure for UpdateTask operation.

    " + }, + "UpdateTaskResponse":{ + "type":"structure", + "required":[ + "version", + "status" + ], + "members":{ + "version":{ + "shape":"Version", + "documentation":"

    The new version of the task created by this update.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current lifecycle status of the task.

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

    Response structure for UpdateTask operation.

    " + }, + "UpdateWorkspaceRequest":{ + "type":"structure", + "required":["workspaceName"], + "members":{ + "workspaceName":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace to update.

    ", + "location":"uri", + "locationName":"workspaceName" + }, + "workspaceDescription":{ + "shape":"Description", + "documentation":"

    A new description for the workspace.

    " + }, + "encryptionConfiguration":{ + "shape":"WorkspaceEncryptionConfiguration", + "documentation":"

    The encryption configuration for the workspace. Omit this field to leave encryption unchanged. After a customer managed key configuration becomes active, the key can't be changed; supplying the same key is accepted.

    " + }, + "clientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is idempotent. If you retry a request that completed successfully using the same client token, the retry succeeds without performing any further actions.

    ", + "idempotencyToken":true + } + } + }, + "UpdateWorkspaceResponse":{ + "type":"structure", + "required":["workspaceStatus"], + "members":{ + "workspaceStatus":{ + "shape":"WorkspaceStatus", + "documentation":"

    The status of the workspace after the update, which is UPDATING when the operation returns.

    " + } + } + }, "Url":{ "type":"string", "max":256, @@ -11401,6 +17062,11 @@ "min":1, "pattern":"^(0|([1-9]{1}\\d*))$" }, + "VideoDataType":{ + "type":"string", + "documentation":"

    The allowed video data types.

    ", + "enum":["VIDEO-MP4"] + }, "WarmTierRetentionPeriod":{ "type":"structure", "members":{ @@ -11421,6 +17087,123 @@ "ENABLED", "DISABLED" ] + }, + "WorkspaceEncryptionConfiguration":{ + "type":"structure", + "required":["encryptionType"], + "members":{ + "encryptionType":{ + "shape":"EncryptionType", + "documentation":"

    The encryption scheme for the workspace. SITEWISE_DEFAULT_ENCRYPTION encrypts data with the IoT SiteWise default key. KMS_BASED_ENCRYPTION encrypts data with the customer managed KMS key identified by kmsKeyId.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The customer managed KMS key used when encryptionType is KMS_BASED_ENCRYPTION. Accepts a key ID, key ARN, or key alias. Required for KMS_BASED_ENCRYPTION; must be omitted for SITEWISE_DEFAULT_ENCRYPTION. After a workspace's customer managed key configuration becomes active, the key can't be changed.

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

    Contains the encryption configuration for a workspace.

    " + }, + "WorkspaceEncryptionConfigurationInfo":{ + "type":"structure", + "required":["encryptionType"], + "members":{ + "encryptionType":{ + "shape":"EncryptionType", + "documentation":"

    The type of encryption used for the workspace.

    " + }, + "kmsKeyArn":{ + "shape":"ARN", + "documentation":"

    The key ARN of the KMS key used for KMS encryption if encryptionType is KMS_BASED_ENCRYPTION.

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

    Contains the encryption configuration information for a workspace.

    " + }, + "WorkspaceErrorDetails":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"ErrorCode", + "documentation":"

    The error code.

    " + }, + "message":{ + "shape":"Description", + "documentation":"

    The error message.

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

    Contains the details of an error associated with a workspace.

    " + }, + "WorkspaceName":{ + "type":"string", + "max":64, + "min":1, + "pattern":"^[a-zA-Z0-9_-]+$" + }, + "WorkspaceState":{ + "type":"string", + "documentation":"

    The current state of a workspace. The state changes as the workspace is created, updated, or deleted.

    ", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "FAILED" + ] + }, + "WorkspaceStatus":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"WorkspaceState", + "documentation":"

    The current state of the workspace.

    " + }, + "error":{ + "shape":"WorkspaceErrorDetails", + "documentation":"

    Contains associated error information, if any.

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

    Contains information about the current status of a workspace.

    " + }, + "WorkspaceSummaries":{ + "type":"list", + "member":{"shape":"WorkspaceSummary"} + }, + "WorkspaceSummary":{ + "type":"structure", + "required":[ + "name", + "arn", + "status", + "createdAt", + "updatedAt" + ], + "members":{ + "name":{ + "shape":"WorkspaceName", + "documentation":"

    The name of the workspace.

    " + }, + "arn":{ + "shape":"ARN", + "documentation":"

    The ARN of the workspace.

    " + }, + "status":{ + "shape":"WorkspaceStatus", + "documentation":"

    The status of the workspace.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The date the workspace was created, in Unix epoch time.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date the workspace was last updated, in Unix epoch time.

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

    Contains summary information about a workspace, including its name, ARN, status, and creation and update timestamps.

    " } }, "documentation":"

    Welcome to the IoT SiteWise API Reference. IoT SiteWise is an Amazon Web Services service that connects Industrial Internet of Things (IIoT) devices to the power of the Amazon Web Services Cloud. For more information, see the IoT SiteWise User Guide. For information about IoT SiteWise quotas, see Quotas in the IoT SiteWise User Guide.

    " diff --git a/services/iotthingsgraph/pom.xml b/services/iotthingsgraph/pom.xml index 0f313f7483e7..2072884964af 100644 --- a/services/iotthingsgraph/pom.xml +++ b/services/iotthingsgraph/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotthingsgraph AWS Java SDK :: Services :: IoTThingsGraph diff --git a/services/iotthingsgraph/src/main/resources/codegen-resources/customization.config b/services/iotthingsgraph/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/iotthingsgraph/src/main/resources/codegen-resources/customization.config +++ b/services/iotthingsgraph/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..52b6a2d1de1c --- /dev/null +++ b/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotthingsgraph-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotthingsgraph-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotthingsgraph.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotthingsgraph.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iotthingsgraph.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABwX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAsAAAAKAAAABgX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 686fa6f4a61d..000000000000 --- a/services/iotthingsgraph/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotthingsgraph-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotthingsgraph-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iotthingsgraph.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://iotthingsgraph.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iotthingsgraph.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iottwinmaker/pom.xml b/services/iottwinmaker/pom.xml index b94bccd425fa..e6a04de0c9de 100644 --- a/services/iottwinmaker/pom.xml +++ b/services/iottwinmaker/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iottwinmaker AWS Java SDK :: Services :: Io T Twin Maker diff --git a/services/iottwinmaker/src/main/resources/codegen-resources/customization.config b/services/iottwinmaker/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/iottwinmaker/src/main/resources/codegen-resources/customization.config +++ b/services/iottwinmaker/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..841eea06c1ee --- /dev/null +++ b/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iottwinmaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iottwinmaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iottwinmaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://iottwinmaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 41069b876c4d..000000000000 --- a/services/iottwinmaker/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iottwinmaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iottwinmaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://iottwinmaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://iottwinmaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotwireless/pom.xml b/services/iotwireless/pom.xml index f922fd5e6889..013befa5797b 100644 --- a/services/iotwireless/pom.xml +++ b/services/iotwireless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT iotwireless AWS Java SDK :: Services :: IoT Wireless diff --git a/services/iotwireless/src/main/resources/codegen-resources/customization.config b/services/iotwireless/src/main/resources/codegen-resources/customization.config index 8c7263446a5a..21b15d9542cb 100644 --- a/services/iotwireless/src/main/resources/codegen-resources/customization.config +++ b/services/iotwireless/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "underscoresInNameBehavior": "ALLOW", - "enableGenerateCompiledEndpointRules": true + "underscoresInNameBehavior": "ALLOW" } diff --git a/services/iotwireless/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/iotwireless/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..02089b934f6c --- /dev/null +++ b/services/iotwireless/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotwireless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotwireless-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotwireless.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.iotwireless.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/iotwireless/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/iotwireless/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0be201dd99c5..000000000000 --- a/services/iotwireless/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotwireless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotwireless-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.iotwireless.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.iotwireless.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/iotwireless/src/main/resources/codegen-resources/service-2.json b/services/iotwireless/src/main/resources/codegen-resources/service-2.json index 6df068e8f5d0..886179f1b95c 100644 --- a/services/iotwireless/src/main/resources/codegen-resources/service-2.json +++ b/services/iotwireless/src/main/resources/codegen-resources/service-2.json @@ -2092,10 +2092,10 @@ "members":{ "WiFiCellular":{ "shape":"WiFiCellular", - "documentation":"Configuration for WiFi and cellular-based payloads for location estimates." + "documentation":"

    Configuration for WiFi and cellular-based location estimate payloads resolved by HERE's solvers.

    " } }, - "documentation":"Optional configuration to customize location estimates." + "documentation":"

    Optional configuration for customizing position estimates, including parameters that affect the accuracy and uncertainty of WiFi and cellular-based location estimates.

    " }, "AggregationPeriod":{ "type":"string", @@ -4425,7 +4425,11 @@ }, "Gnss":{ "shape":"Gnss", - "documentation":"

    Retrieves an estimated device position by resolving the global navigation satellite system (GNSS) scan data. The position is resolved using the GNSS solver powered by LoRa Cloud.

    " + "documentation":"

    Retrieves an estimated device position by resolving the global navigation satellite system (GNSS) scan data. The position is resolved using the GNSS solver powered by LoRa Cloud. This field is mutually exclusive with the GnssMultiFrame field.

    " + }, + "GnssMultiFrame":{ + "shape":"GnssMultiFrame", + "documentation":"

    Retrieves an estimated device position by resolving multiple global navigation satellite system (GNSS) scan captures. The position is resolved using the multi-frame GNSS solver powered by LoRa Cloud. This field is mutually exclusive with the Gnss field.

    " }, "Timestamp":{ "shape":"CreationDate", @@ -4433,7 +4437,7 @@ }, "AdvancedConfiguration":{ "shape":"AdvancedConfiguration", - "documentation":"Optional configuration to customize position estimates. If not provided, defaults are applied." + "documentation":"

    Optional configuration for customizing position measurement data.

    " } } }, @@ -5087,6 +5091,54 @@ }, "documentation":"

    Global navigation satellite system (GNSS) object used for positioning.

    " }, + "GnssCapture":{ + "type":"structure", + "required":["Payload"], + "members":{ + "Payload":{ + "shape":"GnssNav", + "documentation":"

    Payload that contains the GNSS scan result, or NAV message, in hexadecimal notation.

    " + }, + "CaptureTime":{ + "shape":"GPST", + "documentation":"

    Optional parameter that gives an estimate of the time when the GNSS scan information is taken, in seconds GPS time (GPST). If capture time is not specified, the local server time is used.

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

    A single GNSS scan capture containing the scan payload and optional capture time.

    " + }, + "GnssCaptures":{ + "type":"list", + "member":{"shape":"GnssCapture"}, + "max":32, + "min":2 + }, + "GnssMultiFrame":{ + "type":"structure", + "required":["Captures"], + "members":{ + "Captures":{ + "shape":"GnssCaptures", + "documentation":"

    List of GNSS scan captures. Each capture contains a payload from a single GNSS scan. The number of captures must be 2, 4, 8, 16, or 32.

    " + }, + "CaptureTimeAccuracy":{ + "shape":"CaptureTimeAccuracy", + "documentation":"

    Optional value that gives the capture time estimate accuracy, in seconds. If capture time accuracy is not specified, default value of 300 is used.

    " + }, + "AssistPosition":{ + "shape":"AssistPosition", + "documentation":"

    Optional assistance position information, specified using latitude and longitude values in degrees. The coordinates are inside the WGS84 reference frame.

    " + }, + "AssistAltitude":{ + "shape":"Coordinate", + "documentation":"

    Optional assistance altitude, which is the altitude of the device at capture time, specified in meters above the WGS84 reference ellipsoid. This parameter is required when Use2DSolver is enabled.

    " + }, + "Use2DSolver":{ + "shape":"Use2DSolver", + "documentation":"

    Optional parameter that forces 2D solve, which modifies the positioning algorithm to a 2D solution problem. When this parameter is specified, the assistance altitude should have an accuracy of at least 10 meters.

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

    Global navigation satellite system (GNSS) multi-frame object used for positioning. Contains multiple GNSS scan captures that are combined by the solver.

    " + }, "GnssNav":{ "type":"string", "max":2048 @@ -9272,10 +9324,10 @@ "members":{ "ConfidencePercent":{ "shape":"ConfidencePercent", - "documentation":"Confidence level for WiFi and cellular position estimates, expressed as a percentage. Valid range: 50–99 inclusive. Defaults to 68 if not specified." + "documentation":"

    The confidence level for WiFi and cellular position estimates, expressed as a percentage. This value determines the size of the confidence area or uncertainty radius for the estimated position. A higher confidence level produces a larger uncertainty radius, while a lower confidence level produces a smaller, more precise radius.

    Valid range: 50 to 99 inclusive. If not specified, the default value of 68 is used, which corresponds to approximately one standard deviation of the normal distribution.

    " } }, - "documentation":"Configuration for WiFi and cellular location payloads." + "documentation":"

    Configuration for WiFi and cellular location payloads. Contains the confidence level that determines the size of the uncertainty radius in the position estimate.

    " }, "WirelessDeviceArn":{"type":"string"}, "WirelessDeviceEvent":{ diff --git a/services/ivs/pom.xml b/services/ivs/pom.xml index 8bf315c49b08..14e42f1ff098 100644 --- a/services/ivs/pom.xml +++ b/services/ivs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ivs AWS Java SDK :: Services :: Ivs diff --git a/services/ivs/src/main/resources/codegen-resources/customization.config b/services/ivs/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ivs/src/main/resources/codegen-resources/customization.config +++ b/services/ivs/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ivs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ivs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1b4ab278dda9 --- /dev/null +++ b/services/ivs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ivs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ivs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8f27bf04b97c..000000000000 --- a/services/ivs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ivs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ivschat/pom.xml b/services/ivschat/pom.xml index 570de502536e..49ef955cf570 100644 --- a/services/ivschat/pom.xml +++ b/services/ivschat/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ivschat AWS Java SDK :: Services :: Ivschat diff --git a/services/ivschat/src/main/resources/codegen-resources/customization.config b/services/ivschat/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ivschat/src/main/resources/codegen-resources/customization.config +++ b/services/ivschat/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ivschat/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ivschat/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cd186cffb4ab --- /dev/null +++ b/services/ivschat/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivschat-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivschat-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivschat.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivschat.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ivschat/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ivschat/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6f8559278681..000000000000 --- a/services/ivschat/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivschat-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivschat-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivschat.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ivschat.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ivsrealtime/pom.xml b/services/ivsrealtime/pom.xml index 7a7eea1fbe3e..fd925a4d75a0 100644 --- a/services/ivsrealtime/pom.xml +++ b/services/ivsrealtime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ivsrealtime AWS Java SDK :: Services :: IVS Real Time diff --git a/services/ivsrealtime/src/main/resources/codegen-resources/customization.config b/services/ivsrealtime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ivsrealtime/src/main/resources/codegen-resources/customization.config +++ b/services/ivsrealtime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9ae958b1e59d --- /dev/null +++ b/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivsrealtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivsrealtime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivsrealtime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ivsrealtime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fbbf03152210..000000000000 --- a/services/ivsrealtime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivsrealtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivsrealtime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivsrealtime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ivsrealtime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/ivsrealtime/src/main/resources/codegen-resources/service-2.json b/services/ivsrealtime/src/main/resources/codegen-resources/service-2.json index 6676e6f30d81..e7fe55ad37b5 100644 --- a/services/ivsrealtime/src/main/resources/codegen-resources/service-2.json +++ b/services/ivsrealtime/src/main/resources/codegen-resources/service-2.json @@ -232,7 +232,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Get information about the specified Composition resource.

    " + "documentation":"

    Get information about the specified Composition resource.

    ", + "readonly":true }, "GetEncoderConfiguration":{ "name":"GetEncoderConfiguration", @@ -251,7 +252,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets information about the specified EncoderConfiguration resource.

    " + "documentation":"

    Gets information about the specified EncoderConfiguration resource.

    ", + "readonly":true }, "GetIngestConfiguration":{ "name":"GetIngestConfiguration", @@ -267,7 +269,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets information about the specified IngestConfiguration.

    " + "documentation":"

    Gets information about the specified IngestConfiguration.

    ", + "readonly":true }, "GetParticipant":{ "name":"GetParticipant", @@ -283,7 +286,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets information about the specified participant token.

    " + "documentation":"

    Gets information about the specified participant token.

    ", + "readonly":true }, "GetPublicKey":{ "name":"GetPublicKey", @@ -299,7 +303,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets information for the specified public key.

    " + "documentation":"

    Gets information for the specified public key.

    ", + "readonly":true }, "GetStage":{ "name":"GetStage", @@ -315,7 +320,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets information for the specified stage.

    " + "documentation":"

    Gets information for the specified stage.

    ", + "readonly":true }, "GetStageSession":{ "name":"GetStageSession", @@ -331,7 +337,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets information for the specified stage session.

    " + "documentation":"

    Gets information for the specified stage session.

    ", + "readonly":true }, "GetStorageConfiguration":{ "name":"GetStorageConfiguration", @@ -350,7 +357,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets the storage configuration for the specified ARN.

    " + "documentation":"

    Gets the storage configuration for the specified ARN.

    ", + "readonly":true }, "ImportPublicKey":{ "name":"ImportPublicKey", @@ -386,7 +394,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets summary information about all Compositions in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Gets summary information about all Compositions in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListEncoderConfigurations":{ "name":"ListEncoderConfigurations", @@ -404,7 +413,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets summary information about all EncoderConfigurations in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Gets summary information about all EncoderConfigurations in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListIngestConfigurations":{ "name":"ListIngestConfigurations", @@ -419,7 +429,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Lists all IngestConfigurations in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Lists all IngestConfigurations in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListParticipantEvents":{ "name":"ListParticipantEvents", @@ -434,7 +445,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Lists events for a specified participant that occurred during a specified stage session.

    " + "documentation":"

    Lists events for a specified participant that occurred during a specified stage session.

    ", + "readonly":true }, "ListParticipantReplicas":{ "name":"ListParticipantReplicas", @@ -449,7 +461,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Lists all the replicas for a participant from a source stage.

    " + "documentation":"

    Lists all the replicas for a participant from a source stage.

    ", + "readonly":true }, "ListParticipants":{ "name":"ListParticipants", @@ -464,7 +477,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Lists all participants in a specified stage session.

    " + "documentation":"

    Lists all participants in a specified stage session.

    ", + "readonly":true }, "ListPublicKeys":{ "name":"ListPublicKeys", @@ -479,7 +493,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets summary information about all public keys in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Gets summary information about all public keys in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListStageSessions":{ "name":"ListStageSessions", @@ -494,7 +509,8 @@ {"shape":"ValidationException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Gets all sessions for a specified stage.

    " + "documentation":"

    Gets all sessions for a specified stage.

    ", + "readonly":true }, "ListStages":{ "name":"ListStages", @@ -510,7 +526,8 @@ {"shape":"AccessDeniedException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets summary information about all stages in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Gets summary information about all stages in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListStorageConfigurations":{ "name":"ListStorageConfigurations", @@ -528,7 +545,8 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ConflictException"} ], - "documentation":"

    Gets summary information about all storage configurations in your account, in the AWS region where the API request is processed.

    " + "documentation":"

    Gets summary information about all storage configurations in your account, in the AWS region where the API request is processed.

    ", + "readonly":true }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -544,7 +562,8 @@ {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Gets information about AWS tags for the specified ARN.

    " + "documentation":"

    Gets information about AWS tags for the specified ARN.

    ", + "readonly":true }, "StartComposition":{ "name":"StartComposition", @@ -581,8 +600,8 @@ {"shape":"AccessDeniedException"}, {"shape":"InternalServerException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"ConflictException"}, - {"shape":"PendingVerification"} + {"shape":"PendingVerification"}, + {"shape":"ConflictException"} ], "documentation":"

    Starts replicating a publishing participant from a source stage to a destination stage.

    " }, @@ -750,7 +769,7 @@ "documentation":"

    User does not have sufficient access to perform this action.

    " } }, - "documentation":"

    ", + "documentation":"

    User does not have sufficient access to perform this action.

    ", "error":{ "httpStatusCode":403, "senderFault":true @@ -1031,7 +1050,7 @@ "documentation":"

    Updating or deleting a resource can cause an inconsistent state.

    " } }, - "documentation":"

    ", + "documentation":"

    Updating or deleting a resource can cause an inconsistent state.

    ", "error":{ "httpStatusCode":409, "senderFault":true @@ -1094,7 +1113,7 @@ }, "redundantIngest":{ "shape":"RedundantIngest", - "documentation":"

    Indicates whether redundant ingest is enabled for the ingest configuration. Default: false.

    " + "documentation":"

    Indicates whether redundant ingest is enabled for the ingest configuration. Default: false.

    " }, "tags":{ "shape":"Tags", @@ -1105,6 +1124,48 @@ "CreateIngestConfigurationResponse":{ "type":"structure", "members":{ + "accessControlAllowOrigin":{ + "shape":"String", + "documentation":"

    See Access-Control-Allow-Origin in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Access-Control-Allow-Origin" + }, + "accessControlExposeHeaders":{ + "shape":"String", + "documentation":"

    See Access-Control-Expose-Headers in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Access-Control-Expose-Headers" + }, + "cacheControl":{ + "shape":"String", + "documentation":"

    See Cache-Control in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Cache-Control" + }, + "contentSecurityPolicy":{ + "shape":"String", + "documentation":"

    See Content-Security-Policy in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Content-Security-Policy" + }, + "strictTransportSecurity":{ + "shape":"String", + "documentation":"

    See Strict-Transport-Security in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Strict-Transport-Security" + }, + "xContentTypeOptions":{ + "shape":"String", + "documentation":"

    See X-Content-Type-Options in the MDN Web Docs.

    ", + "location":"header", + "locationName":"X-Content-Type-Options" + }, + "xFrameOptions":{ + "shape":"String", + "documentation":"

    See X-Frame-Options in the MDN Web Docs.

    ", + "location":"header", + "locationName":"X-Frame-Options" + }, "ingestConfiguration":{ "shape":"IngestConfiguration", "documentation":"

    The IngestConfiguration that was created.

    " @@ -1219,8 +1280,7 @@ }, "DeleteEncoderConfigurationResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "DeleteIngestConfigurationRequest":{ "type":"structure", @@ -1238,8 +1298,7 @@ }, "DeleteIngestConfigurationResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "DeletePublicKeyRequest":{ "type":"structure", @@ -1253,8 +1312,7 @@ }, "DeletePublicKeyResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "DeleteStageRequest":{ "type":"structure", @@ -1268,8 +1326,7 @@ }, "DeleteStageResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "DeleteStorageConfigurationRequest":{ "type":"structure", @@ -1283,8 +1340,7 @@ }, "DeleteStorageConfigurationResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "Destination":{ "type":"structure", @@ -1438,8 +1494,7 @@ }, "DisconnectParticipantResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "EncoderConfiguration":{ "type":"structure", @@ -2057,7 +2112,7 @@ "documentation":"

    Unexpected error during processing of request.

    " } }, - "documentation":"

    ", + "documentation":"

    Unexpected error during processing of request.

    ", "error":{"httpStatusCode":500}, "exception":true, "fault":true @@ -2622,7 +2677,7 @@ "type":"string", "max":64, "min":0, - "pattern":"[a-zA-Z0-9-]*" + "pattern":"[a-zA-Z0-9-_]*" }, "ParticipantList":{ "type":"list", @@ -2991,7 +3046,7 @@ "documentation":"

    Your account is pending verification.

    " } }, - "documentation":"

    ", + "documentation":"

    Your account is pending verification.

    ", "error":{ "httpStatusCode":403, "senderFault":true @@ -3266,7 +3321,7 @@ "documentation":"

    Request references a resource which does not exist.

    " } }, - "documentation":"

    ", + "documentation":"

    Request references a resource which does not exist.

    ", "error":{ "httpStatusCode":404, "senderFault":true @@ -3383,7 +3438,7 @@ "documentation":"

    Request would cause a service quota to be exceeded.

    " } }, - "documentation":"

    ", + "documentation":"

    Request would cause a service quota to be exceeded.

    ", "error":{ "httpStatusCode":402, "senderFault":true @@ -3661,8 +3716,7 @@ }, "StopCompositionResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "StopParticipantReplicationRequest":{ "type":"structure", @@ -3833,8 +3887,7 @@ }, "TagResourceResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "TagValue":{ "type":"string", @@ -3901,8 +3954,7 @@ }, "UntagResourceResponse":{ "type":"structure", - "members":{ - } + "members":{} }, "UpdateIngestConfigurationRequest":{ "type":"structure", @@ -3918,13 +3970,55 @@ }, "redundantIngest":{ "shape":"RedundantIngest", - "documentation":"

    Indicates whether redundant ingest is enabled for the ingest configuration. Default: false.

    " + "documentation":"

    Indicates whether redundant ingest is enabled for the ingest configuration. Default: false.

    " } } }, "UpdateIngestConfigurationResponse":{ "type":"structure", "members":{ + "accessControlAllowOrigin":{ + "shape":"String", + "documentation":"

    See Access-Control-Allow-Origin in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Access-Control-Allow-Origin" + }, + "accessControlExposeHeaders":{ + "shape":"String", + "documentation":"

    See Access-Control-Expose-Headers in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Access-Control-Expose-Headers" + }, + "cacheControl":{ + "shape":"String", + "documentation":"

    See Cache-Control in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Cache-Control" + }, + "contentSecurityPolicy":{ + "shape":"String", + "documentation":"

    See Content-Security-Policy in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Content-Security-Policy" + }, + "strictTransportSecurity":{ + "shape":"String", + "documentation":"

    See Strict-Transport-Security in the MDN Web Docs.

    ", + "location":"header", + "locationName":"Strict-Transport-Security" + }, + "xContentTypeOptions":{ + "shape":"String", + "documentation":"

    See X-Content-Type-Options in the MDN Web Docs.

    ", + "location":"header", + "locationName":"X-Content-Type-Options" + }, + "xFrameOptions":{ + "shape":"String", + "documentation":"

    See X-Frame-Options in the MDN Web Docs.

    ", + "location":"header", + "locationName":"X-Frame-Options" + }, "ingestConfiguration":{ "shape":"IngestConfiguration", "documentation":"

    The updated IngestConfiguration.

    " @@ -4019,7 +4113,7 @@ "documentation":"

    The input fails to satisfy the constraints specified by an Amazon Web Services service.

    " } }, - "documentation":"

    ", + "documentation":"

    The input fails to satisfy the constraints specified by an Amazon Web Services service.

    ", "error":{ "httpStatusCode":400, "senderFault":true diff --git a/services/kafka/pom.xml b/services/kafka/pom.xml index bae31d4be088..513496d9e917 100644 --- a/services/kafka/pom.xml +++ b/services/kafka/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kafka AWS Java SDK :: Services :: Kafka diff --git a/services/kafka/src/main/resources/codegen-resources/customization.config b/services/kafka/src/main/resources/codegen-resources/customization.config index 9ebe291adc93..ee26fa7f9350 100644 --- a/services/kafka/src/main/resources/codegen-resources/customization.config +++ b/services/kafka/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listClusters" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kafka/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kafka/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b84cdcf6dfac --- /dev/null +++ b/services/kafka/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,266 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafka.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 20, + "nodes": "/////wAAAAH/////AAAAAAAAABMAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAwAAAAGAAAABAAAAAcF9eEGAAAABQX14QQAAAAIAAAABgX14QQAAAAJAAAABwX14QQAAAAKAAAACAX14QQAAAALAAAACQX14QsF9eEMAAAABAAAAA8AAAANAAAACAX14QYAAAAOAAAACgX14QkF9eEKAAAABQX14QUAAAAQAAAACAX14QQAAAARAAAACQAAABIF9eEIAAAACgX14QcF9eEIAAAAAwX14QEAAAAUAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kafka/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kafka/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8a427af6cca0..000000000000 --- a/services/kafka/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,645 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://kafka.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafka-api.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafka-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafka-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafka.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kafka.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/kafka/src/main/resources/codegen-resources/service-2.json b/services/kafka/src/main/resources/codegen-resources/service-2.json index 8bfccc86c2cd..b6e0ccd0abaa 100644 --- a/services/kafka/src/main/resources/codegen-resources/service-2.json +++ b/services/kafka/src/main/resources/codegen-resources/service-2.json @@ -61,6 +61,57 @@ ], "documentation": "\n

    Associates one or more Scram Secrets with an Amazon MSK cluster.

    \n " }, + "CreateChannel": { + "name": "CreateChannel", + "http": { + "method": "POST", + "requestUri": "/v1/clusters/{clusterArn}/channels", + "responseCode": 200 + }, + "input": { + "shape": "CreateChannelRequest" + }, + "output": { + "shape": "CreateChannelResponse", + "documentation": "\n

    200 response

    \n " + }, + "errors": [ + { + "shape": "BadRequestException", + "documentation": "\n

    The request isn't valid because the input is incorrect. Correct your input and then submit it again.

    \n " + }, + { + "shape": "UnauthorizedException", + "documentation": "\n

    The request is not authorized. The provided credentials couldn't be validated.

    \n " + }, + { + "shape": "InternalServerErrorException", + "documentation": "\n

    There was an unexpected internal server error. Retrying your request might resolve the issue.

    \n " + }, + { + "shape": "ForbiddenException", + "documentation": "\n

    Access forbidden. Check your credentials and then retry your request.

    \n " + }, + { + "shape": "NotFoundException", + "documentation": "\n

    The resource could not be found due to incorrect input. Correct the input, then retry the request.

    \n " + }, + { + "shape": "ServiceUnavailableException", + "documentation": "\n

    503 response

    \n " + }, + { + "shape": "TooManyRequestsException", + "documentation": "\n

    429 response

    \n " + }, + { + "shape": "ConflictException", + "documentation": "\n

    This cluster name already exists. Retry your request using another name.

    \n " + } + ], + "documentation": "

    Creates a Channel that streams records from an Amazon MSK Express cluster topic to Amazon S3 or Apache Iceberg.

    ", + "idempotent": true + }, "CreateCluster": { "name": "CreateCluster", "http": { @@ -405,6 +456,53 @@ ], "documentation": "\n

    Deletes the MSK cluster specified by the Amazon Resource Name (ARN) in the request.

    \n " }, + "DeleteChannel": { + "name": "DeleteChannel", + "http": { + "method": "DELETE", + "requestUri": "/v1/clusters/{clusterArn}/channels/{channelArn}", + "responseCode": 200 + }, + "input": { + "shape": "DeleteChannelRequest" + }, + "output": { + "shape": "DeleteChannelResponse", + "documentation": "\n

    Successful response.

    \n " + }, + "errors": [ + { + "shape": "BadRequestException", + "documentation": "\n

    The request isn't valid because the input is incorrect. Correct your input and then submit it again.

    \n " + }, + { + "shape": "UnauthorizedException", + "documentation": "\n

    The request is not authorized. The provided credentials couldn't be validated.

    \n " + }, + { + "shape": "InternalServerErrorException", + "documentation": "\n

    There was an unexpected internal server error. Retrying your request might resolve the issue.

    \n " + }, + { + "shape": "ForbiddenException", + "documentation": "\n

    Access forbidden. Check your credentials and then retry your request.

    \n " + }, + { + "shape": "NotFoundException", + "documentation": "\n

    The resource could not be found due to incorrect input. Correct the input, then retry the request.

    \n " + }, + { + "shape": "ServiceUnavailableException", + "documentation": "\n

    503 response

    \n " + }, + { + "shape": "TooManyRequestsException", + "documentation": "\n

    429 response

    \n " + } + ], + "documentation": "

    Deletes the channel specified by channelArn from the cluster specified by clusterArn. The channel transitions through DELETING and is removed when the asynchronous delete completes.

    ", + "idempotent": true + }, "DeleteClusterPolicy": { "name": "DeleteClusterPolicy", "http": { @@ -695,6 +793,53 @@ ], "documentation": "\n

    Returns a description of the MSK cluster whose Amazon Resource Name (ARN) is specified in the request.

    \n " }, + "DescribeChannel": { + "name": "DescribeChannel", + "http": { + "method": "GET", + "requestUri": "/v1/clusters/{clusterArn}/channels/{channelArn}", + "responseCode": 200 + }, + "input": { + "shape": "DescribeChannelRequest" + }, + "output": { + "shape": "DescribeChannelResponse", + "documentation": "\n

    Successful response.

    \n " + }, + "errors": [ + { + "shape": "BadRequestException", + "documentation": "\n

    The request isn't valid because the input is incorrect. Correct your input and then submit it again.

    \n " + }, + { + "shape": "UnauthorizedException", + "documentation": "\n

    The request is not authorized. The provided credentials couldn't be validated.

    \n " + }, + { + "shape": "InternalServerErrorException", + "documentation": "\n

    There was an unexpected internal server error. Retrying your request might resolve the issue.

    \n " + }, + { + "shape": "ForbiddenException", + "documentation": "\n

    Access forbidden. Check your credentials and then retry your request.

    \n " + }, + { + "shape": "NotFoundException", + "documentation": "\n

    The resource could not be found due to incorrect input. Correct the input, then retry the request.

    \n " + }, + { + "shape": "ServiceUnavailableException", + "documentation": "\n

    503 response

    \n " + }, + { + "shape": "TooManyRequestsException", + "documentation": "\n

    429 response

    \n " + } + ], + "documentation": "

    Returns the current configuration and state of a channel.

    ", + "readonly": true + }, "DescribeClusterOperation": { "name": "DescribeClusterOperation", "http": { @@ -1339,6 +1484,53 @@ ], "documentation": "\n

    Returns a list of all the MSK clusters in the current Region.

    \n " }, + "ListChannels": { + "name": "ListChannels", + "http": { + "method": "GET", + "requestUri": "/v1/clusters/{clusterArn}/channels", + "responseCode": 200 + }, + "input": { + "shape": "ListChannelsRequest" + }, + "output": { + "shape": "ListChannelsResponse", + "documentation": "\n

    Successful response.

    \n " + }, + "errors": [ + { + "shape": "BadRequestException", + "documentation": "\n

    The request isn't valid because the input is incorrect. Correct your input and then submit it again.

    \n " + }, + { + "shape": "UnauthorizedException", + "documentation": "\n

    The request is not authorized. The provided credentials couldn't be validated.

    \n " + }, + { + "shape": "InternalServerErrorException", + "documentation": "\n

    There was an unexpected internal server error. Retrying your request might resolve the issue.

    \n " + }, + { + "shape": "ForbiddenException", + "documentation": "\n

    Access forbidden. Check your credentials and then retry your request.

    \n " + }, + { + "shape": "NotFoundException", + "documentation": "\n

    The resource could not be found due to incorrect input. Correct the input, then retry the request.

    \n " + }, + { + "shape": "ServiceUnavailableException", + "documentation": "\n

    503 response

    \n " + }, + { + "shape": "TooManyRequestsException", + "documentation": "\n

    429 response

    \n " + } + ], + "documentation": "

    Returns the list of channels in a cluster.

    ", + "readonly": true + }, "ListConfigurationRevisions": { "name": "ListConfigurationRevisions", "http": { @@ -2094,6 +2286,45 @@ ], "documentation": "\n

    Updates the cluster's connectivity configuration.

    \n " }, + "UpdateChannel": { + "name": "UpdateChannel", + "http": { + "method": "PUT", + "requestUri": "/v1/clusters/{clusterArn}/channels/{channelArn}", + "responseCode": 200 + }, + "input": { + "shape": "UpdateChannelRequest" + }, + "output": { + "shape": "UpdateChannelResponse" + }, + "errors": [ + { + "shape": "BadRequestException" + }, + { + "shape": "UnauthorizedException" + }, + { + "shape": "InternalServerErrorException" + }, + { + "shape": "ForbiddenException" + }, + { + "shape": "NotFoundException" + }, + { + "shape": "ServiceUnavailableException" + }, + { + "shape": "TooManyRequestsException" + } + ], + "documentation": "

    Updates the destination configuration of an existing channel. Exactly one of icebergDestinationUpdate or s3DestinationUpdate must be supplied.

    ", + "idempotent": true + }, "UpdateClusterConfiguration": { "name": "UpdateClusterConfiguration", "http": { @@ -2513,6 +2744,27 @@ "BootstrapBrokerString" ] }, + "AuthorizerLogs": { + "type": "structure", + "members": { + "CloudWatchLogs": { + "shape": "CloudWatchLogs", + "locationName": "cloudWatchLogs", + "documentation": "

    Details of the CloudWatch Logs destination for authorizer logs.

    " + }, + "Firehose": { + "shape": "Firehose", + "locationName": "firehose", + "documentation": "

    Details of the Kinesis Data Firehose delivery stream that is the destination for authorizer logs.

    " + }, + "S3": { + "shape": "S3", + "locationName": "s3", + "documentation": "

    Details of the Amazon S3 destination for authorizer logs.

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

    The authorizer logs configuration for this MSK cluster.

    " + }, "BatchAssociateScramSecretRequest": { "type": "structure", "members": { @@ -2754,50 +3006,146 @@ }, "documentation": "\n

    Information about the current software installed on the cluster.

    \n " }, - "ClientAuthentication": { + "Catalog": { "type": "structure", "members": { - "Sasl": { - "shape": "Sasl", - "locationName": "sasl", - "documentation": "\n

    Details for ClientAuthentication using SASL.

    \n " - }, - "Tls": { - "shape": "Tls", - "locationName": "tls", - "documentation": "\n

    Details for ClientAuthentication using TLS.

    \n " + "CatalogArn": { + "shape": "__string", + "locationName": "catalogArn", + "documentation": "

    The Amazon Resource Name (ARN) of the federated AWS Glue Data Catalog that projects the S3 Tables bucket. If omitted, MSK derives the catalog ARN from warehouseLocation.

    " }, - "Unauthenticated": { - "shape": "Unauthenticated", - "locationName": "unauthenticated", - "documentation": "\n

    Contains information about unauthenticated traffic to the cluster.

    \n " + "WarehouseLocation": { + "shape": "__string", + "locationName": "warehouseLocation", + "documentation": "

    The Amazon Resource Name (ARN) of the S3 Tables bucket that backs the Apache Iceberg warehouse.

    " } }, - "documentation": "\n

    Includes all client authentication information.

    \n " + "documentation": "

    Configuration of the AWS Glue Data Catalog and S3 Tables warehouse used by the Apache Iceberg destination.

    " }, - "VpcConnectivityClientAuthentication": { + "ChannelInfo": { "type": "structure", "members": { - "Sasl": { - "shape": "VpcConnectivitySasl", - "locationName": "sasl", - "documentation": "\n

    SASL authentication type details for VPC connectivity.

    \n " + "ChannelArn": { + "shape": "__string", + "locationName": "channelArn", + "documentation": "\n

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

    \n " }, - "Tls": { - "shape": "VpcConnectivityTls", - "locationName": "tls", - "documentation": "\n

    TLS authentication type details for VPC connectivity.

    \n " + "ChannelName": { + "shape": "__string", + "locationName": "channelName", + "documentation": "

    The name of the channel.

    " + }, + "Status": { + "shape": "ChannelStatus", + "locationName": "status", + "documentation": "

    The current lifecycle state of the channel.

    " + }, + "CreationTime": { + "shape": "__timestampIso8601", + "locationName": "creationTime", + "documentation": "\n

    The time when the channel was created.

    \n " + }, + "DestinationType": { + "shape": "ChannelDestinationType", + "locationName": "destinationType", + "documentation": "

    The type of destination configured for the channel.

    " + }, + "ClusterOperationArn": { + "shape": "__string", + "locationName": "clusterOperationArn", + "documentation": "

    The Amazon Resource Name (ARN) of the in-flight cluster operation. Returned only while the channel is in CREATING, UPDATING, or DELETING.

    " } }, - "documentation": "\n

    Includes all client authentication information for VPC connectivity.

    \n " + "documentation": "

    Summary information about a channel returned by ListChannels.

    ", + "required": [ + "ChannelArn", + "ChannelName", + "Status", + "CreationTime", + "DestinationType" + ] }, - "ServerlessClientAuthentication": { - "type": "structure", - "members": { - "Sasl": { - "shape": "ServerlessSasl", - "locationName": "sasl", - "documentation": "\n

    Details for ClientAuthentication using SASL.

    \n " + "ChannelStatus": { + "type": "string", + "documentation": "

    The lifecycle state of a channel.

    ", + "enum": [ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "FAILED", + "SUSPENDING", + "SUSPENDED" + ] + }, + "ChannelDestinationType": { + "type": "string", + "documentation": "

    The type of destination configured for the channel.

    ", + "enum": [ + "ICEBERG", + "S3" + ] + }, + "ChannelStateInfo": { + "type": "structure", + "members": { + "Code": { + "shape": "__string", + "locationName": "code", + "documentation": "

    A short, machine-readable code identifying the failure cause.

    " + }, + "Message": { + "shape": "__string", + "locationName": "message", + "documentation": "

    A human-readable message describing the failure.

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

    Additional context for the current channel state, populated when the channel is in FAILED.

    " + }, + "ClientAuthentication": { + "type": "structure", + "members": { + "Sasl": { + "shape": "Sasl", + "locationName": "sasl", + "documentation": "\n

    Details for ClientAuthentication using SASL.

    \n " + }, + "Tls": { + "shape": "Tls", + "locationName": "tls", + "documentation": "\n

    Details for ClientAuthentication using TLS.

    \n " + }, + "Unauthenticated": { + "shape": "Unauthenticated", + "locationName": "unauthenticated", + "documentation": "\n

    Contains information about unauthenticated traffic to the cluster.

    \n " + } + }, + "documentation": "\n

    Includes all client authentication information.

    \n " + }, + "VpcConnectivityClientAuthentication": { + "type": "structure", + "members": { + "Sasl": { + "shape": "VpcConnectivitySasl", + "locationName": "sasl", + "documentation": "\n

    SASL authentication type details for VPC connectivity.

    \n " + }, + "Tls": { + "shape": "VpcConnectivityTls", + "locationName": "tls", + "documentation": "\n

    TLS authentication type details for VPC connectivity.

    \n " + } + }, + "documentation": "\n

    Includes all client authentication information for VPC connectivity.

    \n " + }, + "ServerlessClientAuthentication": { + "type": "structure", + "members": { + "Sasl": { + "shape": "ServerlessSasl", + "locationName": "sasl", + "documentation": "\n

    Details for ClientAuthentication using SASL.

    \n " } }, "documentation": "\n

    Includes all client authentication information.

    \n " @@ -3663,6 +4011,58 @@ "ClusterName" ] }, + "CreateChannelRequest": { + "type": "structure", + "members": { + "ChannelName": { + "shape": "__string", + "locationName": "channelName", + "documentation": "

    The name of the channel. Must be unique within the cluster.

    " + }, + "ClusterArn": { + "shape": "__string", + "location": "uri", + "locationName": "clusterArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the cluster.

    \n " + }, + "EncryptionConfiguration": { + "shape": "EncryptionConfiguration", + "locationName": "encryptionConfiguration", + "documentation": "

    The encryption configuration applied to the channel.

    " + }, + "IcebergDestinationConfiguration": { + "shape": "IcebergDestinationConfiguration", + "locationName": "icebergDestinationConfiguration", + "documentation": "

    The Apache Iceberg destination for the channel. Mutually exclusive with s3DestinationConfiguration.

    " + }, + "S3DestinationConfiguration": { + "shape": "S3DestinationConfiguration", + "locationName": "s3DestinationConfiguration", + "documentation": "

    The Amazon S3 destination for the channel. Mutually exclusive with icebergDestinationConfiguration.

    " + }, + "Tags": { + "shape": "__mapOf__string", + "locationName": "tags", + "documentation": "

    The tags attached to the channel.

    " + }, + "TopicConfigurationList": { + "shape": "__listOfTopicConfiguration", + "locationName": "topicConfigurationList", + "documentation": "

    The list of topic configurations for the channel. Currently exactly one topic must be specified.

    " + }, + "LoggingInfo": { + "shape": "ChannelLoggingInfo", + "locationName": "loggingInfo", + "documentation": "

    The destinations to which the channel publishes operational logs.

    " + } + }, + "documentation": "

    Creates a Channel that streams records from an Amazon MSK Express cluster topic to Amazon S3 or Apache Iceberg.

    ", + "required": [ + "ClusterArn", + "ChannelName", + "TopicConfigurationList" + ] + }, "CreateClusterRequest": { "type": "structure", "members": { @@ -3738,6 +4138,25 @@ "ClusterName" ] }, + "CreateChannelResponse": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "locationName": "channelArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    \n " + }, + "ClusterOperationArn": { + "shape": "__string", + "locationName": "clusterOperationArn", + "documentation": "\n

    The Amazon Resource Name (ARN) of the cluster operation.

    \n " + } + }, + "required": [ + "ChannelArn" + ], + "documentation": "

    Returns the channel ARN and the cluster-operation ARN that tracks the asynchronous create.

    " + }, "CreateClusterResponse": { "type": "structure", "members": { @@ -4344,6 +4763,51 @@ } } }, + "DeadLetterQueueS3": { + "type": "structure", + "members": { + "BucketArn": { + "shape": "__string", + "locationName": "bucketArn", + "documentation": "

    The Amazon Resource Name (ARN) of the dead-letter Amazon S3 bucket.

    " + }, + "ErrorOutputPrefix": { + "shape": "__string", + "locationName": "errorOutputPrefix", + "documentation": "

    An optional prefix prepended to every dead-letter Amazon S3 object key.

    " + }, + "ExpectedBucketOwner": { + "shape": "__string", + "locationName": "expectedBucketOwner", + "documentation": "

    Optional 12-digit AWS account ID expected to own the dead-letter Amazon S3 bucket.

    " + } + }, + "documentation": "

    Configuration of the Amazon S3 bucket where records that fail to deliver are stored.

    ", + "required": [ + "BucketArn" + ] + }, + "DeleteChannelRequest": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "location": "uri", + "locationName": "channelArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    \n " + }, + "ClusterArn": { + "shape": "__string", + "location": "uri", + "locationName": "clusterArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the cluster.

    \n " + } + }, + "required": [ + "ClusterArn", + "ChannelArn" + ] + }, "DeleteClusterPolicyRequest": { "type": "structure", "members": { @@ -4362,6 +4826,25 @@ "type": "structure", "members": {} }, + "DeleteChannelResponse": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "locationName": "channelArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    \n " + }, + "ClusterOperationArn": { + "shape": "__string", + "locationName": "clusterOperationArn", + "documentation": "\n

    The Amazon Resource Name (ARN) of the cluster operation.

    \n " + } + }, + "required": [ + "ChannelArn" + ], + "documentation": "

    Returns the channel ARN and the cluster-operation ARN that tracks the asynchronous delete.

    " + }, "DeleteConfigurationRequest": { "type": "structure", "members": { @@ -4455,6 +4938,27 @@ } } }, + "DescribeChannelRequest": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "location": "uri", + "locationName": "channelArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    \n " + }, + "ClusterArn": { + "shape": "__string", + "location": "uri", + "locationName": "clusterArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the cluster.

    \n " + } + }, + "required": [ + "ClusterArn", + "ChannelArn" + ] + }, "DescribeClusterOperationRequest": { "type": "structure", "members": { @@ -4483,6 +4987,85 @@ "ClusterOperationArn" ] }, + "DescribeChannelResponse": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "locationName": "channelArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    \n " + }, + "ChannelName": { + "shape": "__string", + "locationName": "channelName", + "documentation": "

    The name of the channel.

    " + }, + "EncryptionConfiguration": { + "shape": "EncryptionConfiguration", + "locationName": "encryptionConfiguration", + "documentation": "

    The encryption configuration applied to the channel.

    " + }, + "IcebergDestinationConfiguration": { + "shape": "IcebergDestinationConfiguration", + "locationName": "icebergDestinationConfiguration", + "documentation": "

    The Apache Iceberg destination for the channel, if configured.

    " + }, + "S3DestinationConfiguration": { + "shape": "S3DestinationConfiguration", + "locationName": "s3DestinationConfiguration", + "documentation": "

    The Amazon S3 destination for the channel, if configured.

    " + }, + "Status": { + "shape": "ChannelStatus", + "locationName": "status", + "documentation": "

    The current lifecycle state of the channel.

    " + }, + "DestinationType": { + "shape": "ChannelDestinationType", + "locationName": "destinationType", + "documentation": "

    The type of destination configured for the channel.

    " + }, + "CreationTime": { + "shape": "__timestampIso8601", + "locationName": "creationTime", + "documentation": "\n

    The time when the channel was created.

    \n " + }, + "TopicConfigurationList": { + "shape": "__listOfTopicConfiguration", + "locationName": "topicConfigurationList", + "documentation": "

    The list of topic configurations for the channel.

    " + }, + "LoggingInfo": { + "shape": "ChannelLoggingInfo", + "locationName": "loggingInfo", + "documentation": "

    The destinations to which the channel publishes operational logs.

    " + }, + "StateInfo": { + "shape": "ChannelStateInfo", + "locationName": "stateInfo", + "documentation": "

    Additional context for the current channel state, populated when the channel is in FAILED.

    " + }, + "ClusterOperationArn": { + "shape": "__string", + "locationName": "clusterOperationArn", + "documentation": "

    The Amazon Resource Name (ARN) of the in-flight cluster operation. Returned only while the channel is in CREATING, UPDATING, or DELETING.

    " + }, + "Tags": { + "shape": "__mapOf__string", + "locationName": "tags", + "documentation": "

    The tags attached to the channel.

    " + } + }, + "required": [ + "ChannelArn", + "ChannelName", + "TopicConfigurationList", + "Status", + "DestinationType", + "CreationTime" + ], + "documentation": "

    Contains the current configuration and state of a channel.

    " + }, "DescribeClusterOperationResponse": { "type": "structure", "members": { @@ -4975,6 +5558,27 @@ } } }, + "DestinationTable": { + "type": "structure", + "members": { + "DestinationDatabaseName": { + "shape": "__string", + "locationName": "destinationDatabaseName", + "documentation": "

    The name of the destination namespace (database) in the AWS Glue Data Catalog.

    " + }, + "DestinationTableName": { + "shape": "__string", + "locationName": "destinationTableName", + "documentation": "

    The name of the destination Apache Iceberg table.

    " + }, + "PartitionSpec": { + "shape": "PartitionSpec", + "locationName": "partitionSpec", + "documentation": "

    The partition specification for the destination table.

    " + } + }, + "documentation": "

    Configuration of an Apache Iceberg destination table.

    " + }, "EBSStorageInfo": { "type": "structure", "members": { @@ -4991,6 +5595,20 @@ }, "documentation": "\n

    Contains information about the EBS storage volumes attached to Apache Kafka broker nodes.

    \n " }, + "EncryptionConfiguration": { + "type": "structure", + "members": { + "KmsKeyArn": { + "shape": "__string", + "locationName": "kmsKeyArn", + "documentation": "

    The Amazon Resource Name (ARN) of the AWS KMS key used to encrypt the data.

    " + } + }, + "documentation": "

    The AWS KMS encryption configuration applied to data at rest.

    ", + "required": [ + "KmsKeyArn" + ] + }, "EncryptionAtRest": { "type": "structure", "members": { @@ -5434,6 +6052,73 @@ } } }, + "IcebergDestinationConfiguration": { + "type": "structure", + "members": { + "AppendOnly": { + "shape": "__boolean", + "locationName": "appendOnly", + "documentation": "

    Whether the destination is append-only. Must be true; updates and deletes are not supported.

    " + }, + "Catalog": { + "shape": "Catalog", + "locationName": "catalog", + "documentation": "

    The AWS Glue Data Catalog and S3 Tables warehouse used by the destination.

    " + }, + "DataFreshnessInSeconds": { + "shape": "__integer", + "locationName": "dataFreshnessInSeconds", + "documentation": "

    The maximum time, in seconds, that records buffer in MSK before being flushed to the destination. Allowed range: 300 to 900. Default: 600.

    " + }, + "DeadLetterQueueS3": { + "shape": "DeadLetterQueueS3", + "locationName": "deadLetterQueueS3", + "documentation": "

    The Amazon S3 bucket and prefix where MSK writes records that fail to deliver.

    " + }, + "DestinationTableList": { + "shape": "__listOfDestinationTable", + "locationName": "destinationTableList", + "documentation": "

    The destination Iceberg tables. Currently exactly one table must be specified.

    " + }, + "SchemaEvolution": { + "shape": "SchemaEvolution", + "locationName": "schemaEvolution", + "documentation": "

    Configuration controlling whether the destination table's schema is evolved to match incoming records.

    " + }, + "ServiceExecutionRoleArn": { + "shape": "__string", + "locationName": "serviceExecutionRoleArn", + "documentation": "

    The Amazon Resource Name (ARN) of the IAM role that MSK assumes to access the destination table, the AWS Glue Data Catalog, and the dead-letter Amazon S3 bucket.

    " + }, + "TableCreation": { + "shape": "TableCreation", + "locationName": "tableCreation", + "documentation": "

    Configuration controlling whether MSK creates the destination table if it does not already exist.

    " + }, + "CompressionType": { + "shape": "IcebergCompressionType", + "locationName": "compressionType", + "documentation": "

    The compression codec for Iceberg table data files. Defaults to ZSTD.

    " + } + }, + "documentation": "

    Configuration of an Apache Iceberg destination for a channel.

    ", + "required": [ + "DeadLetterQueueS3", + "DestinationTableList", + "ServiceExecutionRoleArn", + "SchemaEvolution", + "TableCreation", + "AppendOnly" + ] + }, + "IcebergCompressionType": { + "type": "string", + "enum": [ + "ZSTD", + "SNAPPY" + ], + "documentation": "

    Compression codec for Iceberg table data files. Defaults to ZSTD.

    " + }, "InternalServerErrorException": { "type": "structure", "members": { @@ -5516,19 +6201,133 @@ "shape": "KafkaClusterMTLSAuthentication", "locationName": "mTLS", "documentation": "

    Details for mTLS client authentication.

    " + }, + "SaslOAuthBearer": { + "shape": "KafkaClusterSaslOAuthBearerAuthentication", + "locationName": "saslOAuthBearer", + "documentation": "

    Details for SASL/OAUTHBEARER client authentication.

    " } }, "documentation": "

    Details of the client authentication used by the Apache Kafka cluster.

    " }, - "KafkaClusterSaslScramAuthentication": { + "KafkaClusterSaslOAuthBearerAuthentication": { "type": "structure", "members": { - "Mechanism": { - "shape": "KafkaClusterSaslScramMechanism", - "locationName": "mechanism", - "documentation": "

    The SASL/SCRAM authentication mechanism.

    " + "TokenEndpointUrl": { + "shape": "__string", + "locationName": "tokenEndpointUrl", + "documentation": "

    The HTTPS URL of the OAuth token endpoint that vends OAuth Bearer tokens per RFC 6749.

    " }, - "SecretArn": { + "ClientCredentials": { + "shape": "KafkaClusterOAuthClientCredentials", + "locationName": "clientCredentials", + "documentation": "

    Details for SASL/OAUTHBEARER using standard client_credentials grant.

    " + }, + "IamJwtBearer": { + "shape": "KafkaClusterOAuthIamJwtBearer", + "locationName": "iamJwtBearer", + "documentation": "

    Details for SASL/OAUTHBEARER using JWT Bearer assertion grant (RFC 7523).

    " + }, + "ClientCredentialsAssertion": { + "shape": "KafkaClusterOAuthClientCredentialsAssertion", + "locationName": "clientCredentialsAssertion", + "documentation": "

    Details for SASL/OAUTHBEARER using client credentials grant with JWT client assertion.

    " + }, + "TokenEndpointAuthenticationMethod": { + "shape": "TokenEndpointAuthenticationMethod", + "locationName": "tokenEndpointAuthenticationMethod", + "documentation": "

    How client credentials are sent to the identity provider. Valid values are POST, BASIC, or NONE.

    " + }, + "Scope": { + "shape": "__string", + "locationName": "scope", + "documentation": "

    OAuth scope to request.

    " + }, + "TokenEndpointTlsCertificateArn": { + "shape": "__string", + "locationName": "tokenEndpointTlsCertificateArn", + "documentation": "

    Secrets Manager ARN containing a custom CA certificate for the identity provider.

    " + } + }, + "documentation": "

    Details for SASL/OAUTHBEARER client authentication.

    ", + "required": [ + "TokenEndpointUrl", + "TokenEndpointAuthenticationMethod" + ] + }, + "KafkaClusterOAuthClientCredentials": { + "type": "structure", + "members": { + "TokenRequestSecretArn": { + "shape": "__string", + "locationName": "tokenRequestSecretArn", + "documentation": "

    The Amazon Resource Name (ARN) of the Secrets Manager secret containing the OAuth client credentials.

    " + } + }, + "documentation": "

    Details for SASL/OAUTHBEARER using standard client_credentials grant.

    ", + "required": [ + "TokenRequestSecretArn" + ] + }, + "KafkaClusterOAuthIamJwtBearer": { + "type": "structure", + "members": { + "Audience": { + "shape": "__string", + "locationName": "audience", + "documentation": "

    The audience for the JWT Bearer assertion.

    " + }, + "SigningAlgorithm": { + "shape": "JwtSigningAlgorithm", + "locationName": "signingAlgorithm", + "documentation": "

    The signing algorithm for the JWT Bearer assertion.

    " + }, + "TokenRequestSecretArn": { + "shape": "__string", + "locationName": "tokenRequestSecretArn", + "documentation": "

    The Amazon Resource Name (ARN) of the Secrets Manager secret containing the signing key.

    " + } + }, + "documentation": "

    Details for SASL/OAUTHBEARER using JWT Bearer assertion grant.

    ", + "required": [ + "Audience", + "SigningAlgorithm" + ] + }, + "KafkaClusterOAuthClientCredentialsAssertion": { + "type": "structure", + "members": { + "Audience": { + "shape": "__string", + "locationName": "audience", + "documentation": "

    The audience for the JWT client assertion.

    " + }, + "SigningAlgorithm": { + "shape": "JwtSigningAlgorithm", + "locationName": "signingAlgorithm", + "documentation": "

    The signing algorithm for the JWT client assertion.

    " + }, + "TokenRequestSecretArn": { + "shape": "__string", + "locationName": "tokenRequestSecretArn", + "documentation": "

    The Amazon Resource Name (ARN) of the Secrets Manager secret containing the signing key.

    " + } + }, + "documentation": "

    Details for SASL/OAUTHBEARER using client credentials grant with JWT client assertion.

    ", + "required": [ + "Audience", + "SigningAlgorithm" + ] + }, + "KafkaClusterSaslScramAuthentication": { + "type": "structure", + "members": { + "Mechanism": { + "shape": "KafkaClusterSaslScramMechanism", + "locationName": "mechanism", + "documentation": "

    The SASL/SCRAM authentication mechanism.

    " + }, + "SecretArn": { "shape": "__string", "locationName": "secretArn", "documentation": "

    The Amazon Resource Name (ARN) of the Secrets Manager secret.

    " @@ -5554,6 +6353,23 @@ "SecretArn" ] }, + "TokenEndpointAuthenticationMethod": { + "type": "string", + "documentation": "

    How client credentials are sent to the identity provider's token endpoint.

    ", + "enum": [ + "POST", + "BASIC", + "NONE" + ] + }, + "JwtSigningAlgorithm": { + "type": "string", + "documentation": "

    The algorithm used to sign the STS JWT assertion.

    ", + "enum": [ + "RS256", + "ES384" + ] + }, "KafkaClusterSaslScramMechanism": { "type": "string", "documentation": "

    The SASL/SCRAM authentication mechanism.

    ", @@ -5747,6 +6563,54 @@ } } }, + "ListChannelsRequest": { + "type": "structure", + "members": { + "ClusterArn": { + "shape": "__string", + "location": "uri", + "locationName": "clusterArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the cluster.

    \n " + }, + "MaxResults": { + "shape": "MaxResults", + "location": "querystring", + "locationName": "maxResults", + "documentation": "\n

    Maximum number of channels to return in a single response.

    \n " + }, + "NextToken": { + "shape": "__string", + "location": "querystring", + "locationName": "nextToken", + "documentation": "\n

    If the response of ListChannels is truncated, it returns a nextToken in the response. This nextToken should be sent in the subsequent request to ListChannels.

    \n " + }, + "TopicNameFilter": { + "shape": "__string", + "location": "querystring", + "locationName": "topicNameFilter", + "documentation": "\n

    Filters results to channels whose topic name matches the specified value.

    \n " + } + }, + "required": [ + "ClusterArn" + ] + }, + "ListChannelsResponse": { + "type": "structure", + "members": { + "Channels": { + "shape": "__listOfChannelInfo", + "locationName": "channels", + "documentation": "

    The list of channels in the cluster.

    " + }, + "NextToken": { + "shape": "__string", + "locationName": "nextToken", + "documentation": "

    If the response from ListChannels is truncated, this token is included. Send it as the nextToken parameter on a subsequent ListChannels call to retrieve the next page.

    " + } + }, + "documentation": "

    Returns the list of channels in the cluster.

    " + }, "ListClustersRequest": { "type": "structure", "members": { @@ -6228,6 +7092,11 @@ "LoggingInfo": { "type": "structure", "members": { + "AuthorizerLogs": { + "shape": "AuthorizerLogs", + "locationName": "authorizerLogs", + "documentation": "

    You can configure your MSK cluster to send authorizer logs to different destination types.

    " + }, "BrokerLogs": { "shape": "BrokerLogs", "locationName": "brokerLogs" @@ -6331,6 +7200,27 @@ "Enabled" ] }, + "ChannelLoggingInfo": { + "type": "structure", + "members": { + "CloudWatchLogs": { + "shape": "CloudWatchLogs", + "locationName": "cloudWatchLogs", + "documentation": "

    Details of the CloudWatch Logs destination for Channel logs.

    " + }, + "Firehose": { + "shape": "Firehose", + "locationName": "firehose", + "documentation": "

    Details of the Kinesis Data Firehose delivery stream that is the destination for Channel logs.

    " + }, + "S3": { + "shape": "S3", + "locationName": "s3", + "documentation": "

    Details of the Amazon S3 destination for Channel logs.

    " + } + }, + "documentation": "

    Configuration for the destinations to which the channel publishes operational logs.

    " + }, "MutableClusterInfo": { "type": "structure", "members": { @@ -6496,6 +7386,43 @@ "Prometheus" ] }, + "PartitionSource": { + "type": "structure", + "members": { + "SourceName": { + "shape": "__string", + "locationName": "sourceName", + "documentation": "\n

    Source name.

    \n " + } + }, + "documentation": "

    A source column used by an Apache Iceberg destination table's partition specification.

    " + }, + "PartitionSpec": { + "type": "structure", + "members": { + "PartitionStrategy": { + "shape": "PartitionStrategy", + "locationName": "partitionStrategy", + "documentation": "

    The partitioning strategy applied to records written to the table.

    " + }, + "SourceList": { + "shape": "__listOfPartitionSource", + "locationName": "sourceList", + "documentation": "

    The source columns used by the partitioning strategy. For TIME_HOUR, must contain exactly one source column whose value is a timestamp.

    " + } + }, + "documentation": "

    Partition specification for an Apache Iceberg destination table.

    ", + "required": [ + "PartitionStrategy" + ] + }, + "PartitionStrategy": { + "type": "string", + "documentation": "

    The partitioning strategy used to partition records in the destination Apache Iceberg table.

    ", + "enum": [ + "TIME_HOUR" + ] + }, "Prometheus": { "type": "structure", "members": { @@ -6555,6 +7482,34 @@ }, "documentation": "Public access control for brokers." }, + "RecordConverter": { + "type": "structure", + "members": { + "ValueConverter": { + "shape": "ValueConverter", + "locationName": "valueConverter", + "documentation": "

    The deserialization format applied to Apache Kafka record values.

    " + } + }, + "documentation": "

    Configuration that controls how Apache Kafka record values are deserialized for the destination.

    ", + "required": [ + "ValueConverter" + ] + }, + "RecordSchema": { + "type": "structure", + "members": { + "GsrArn": { + "shape": "__string", + "locationName": "gsrArn", + "documentation": "

    The Amazon Resource Name (ARN) of the AWS Glue Schema Registry schema (not registry) used to validate records for the destination Apache Iceberg table.

    " + } + }, + "documentation": "

    Schema configuration that controls how Apache Kafka record values are validated.

    ", + "required": [ + "GsrArn" + ] + }, "PutClusterPolicyRequest": { "type": "structure", "members": { @@ -6657,6 +7612,17 @@ }, "documentation": "\n

    Details for client authentication using SASL.

    \n " }, + "SchemaEvolution": { + "type": "structure", + "members": { + "EnableSchemaEvolution": { + "shape": "__boolean", + "locationName": "enableSchemaEvolution", + "documentation": "

    Whether to allow MSK to evolve the destination table's schema. Must be false for the current release.

    " + } + }, + "documentation": "

    Configuration controlling whether the Apache Iceberg destination table's schema is evolved as incoming records change.

    " + }, "Sasl": { "type": "structure", "members": { @@ -7081,6 +8047,17 @@ "TIERED" ] }, + "TableCreation": { + "type": "structure", + "members": { + "EnableTableCreation": { + "shape": "__boolean", + "locationName": "enableTableCreation", + "documentation": "

    Whether MSK creates the destination table on the customer's behalf. Must be true for the current release.

    " + } + }, + "documentation": "

    Configuration controlling whether MSK creates the destination Apache Iceberg table if it does not already exist.

    " + }, "TagResourceRequest": { "type": "structure", "members": { @@ -7128,6 +8105,31 @@ }, "documentation": "\n

    Details for client authentication using TLS.

    \n " }, + "TopicConfiguration": { + "type": "structure", + "members": { + "RecordConverter": { + "shape": "RecordConverter", + "locationName": "recordConverter", + "documentation": "

    Configuration that controls how Apache Kafka record values are deserialized for the destination.

    " + }, + "RecordSchema": { + "shape": "RecordSchema", + "locationName": "recordSchema", + "documentation": "

    The schema used to validate records when the value converter requires one (for example, JSON_SCHEMA_GSR).

    " + }, + "TopicArn": { + "shape": "__string", + "locationName": "topicArn", + "documentation": "\n

    The Amazon Resource Name (ARN) that uniquely identifies the topic.

    \n " + } + }, + "documentation": "

    Configuration of an Apache Kafka topic that feeds a channel.

    ", + "required": [ + "RecordConverter", + "TopicArn" + ] + }, "TopicInfo": { "type": "structure", "members": { @@ -7467,6 +8469,175 @@ } } }, + "S3CompressionType": { + "type": "string", + "enum": [ + "NONE", + "GZIP", + "ZSTD" + ], + "documentation": "

    The compression codec applied to delivered Amazon S3 objects.

    " + }, + "S3DestinationConfiguration": { + "type": "structure", + "members": { + "DataFreshnessInSeconds": { + "shape": "__integer", + "locationName": "dataFreshnessInSeconds", + "documentation": "

    The maximum time, in seconds, that records buffer in MSK before being flushed to the destination. Allowed range: 300 to 900. Default: 600.

    " + }, + "DeadLetterQueueS3": { + "shape": "DeadLetterQueueS3", + "locationName": "deadLetterQueueS3", + "documentation": "

    The Amazon S3 bucket and prefix where MSK writes records that fail to deliver.

    " + }, + "ServiceExecutionRoleArn": { + "shape": "__string", + "locationName": "serviceExecutionRoleArn", + "documentation": "

    The Amazon Resource Name (ARN) of the IAM role that MSK assumes to write to the destination Amazon S3 bucket and the dead-letter bucket.

    " + }, + "Storage": { + "shape": "S3Storage", + "locationName": "storage", + "documentation": "

    The Amazon S3 bucket, prefix, and storage class for delivered records.

    " + } + }, + "required": [ + "Storage", + "ServiceExecutionRoleArn", + "DeadLetterQueueS3" + ], + "documentation": "

    Configuration of an Amazon S3 destination for a channel.

    " + }, + "IcebergDestinationUpdate": { + "type": "structure", + "members": { + "DataFreshnessInSeconds": { + "shape": "__integer", + "locationName": "dataFreshnessInSeconds", + "documentation": "

    The maximum time, in seconds, that records buffer in MSK before being flushed to the destination. Allowed range: 300 to 900.

    " + } + }, + "required": [ + "DataFreshnessInSeconds" + ], + "documentation": "

    Update payload for an Apache Iceberg destination.

    " + }, + "S3DestinationUpdate": { + "type": "structure", + "members": { + "DataFreshnessInSeconds": { + "shape": "__integer", + "locationName": "dataFreshnessInSeconds", + "documentation": "

    The maximum time, in seconds, that records buffer in MSK before being flushed to the destination. Allowed range: 300 to 900.

    " + } + }, + "required": [ + "DataFreshnessInSeconds" + ], + "documentation": "

    Update payload for an Amazon S3 destination.

    " + }, + "S3Storage": { + "type": "structure", + "members": { + "BucketArn": { + "shape": "__string", + "locationName": "bucketArn", + "documentation": "

    The Amazon Resource Name (ARN) of the destination Amazon S3 bucket.

    " + }, + "CompressionType": { + "shape": "S3CompressionType", + "locationName": "compressionType", + "documentation": "

    The compression codec applied to delivered Amazon S3 objects.

    " + }, + "OutputPrefix": { + "shape": "__string", + "locationName": "outputPrefix", + "documentation": "

    An optional prefix prepended to every Amazon S3 object key written by the channel.

    " + }, + "OutputKeyTemplate": { + "shape": "__string", + "locationName": "outputKeyTemplate", + "documentation": "

    An optional template that controls the Amazon S3 object key for each delivered record. Supports the placeholders !{partition-id}, !{sequence-number}, and !{kafka-offset}.

    " + }, + "StorageClass": { + "shape": "S3StorageClass", + "locationName": "storageClass", + "documentation": "

    The Amazon S3 storage class for delivered objects.

    " + }, + "ExpectedBucketOwner": { + "shape": "__string", + "locationName": "expectedBucketOwner", + "documentation": "

    Optional 12-digit AWS account ID expected to own the Amazon S3 bucket.

    " + } + }, + "required": [ + "BucketArn", + "StorageClass", + "CompressionType" + ], + "documentation": "

    Storage configuration for an Amazon S3 destination bucket.

    " + }, + "S3StorageClass": { + "type": "string", + "enum": [ + "STANDARD", + "INTELLIGENT_TIERING", + "GLACIER_IR" + ], + "documentation": "

    The Amazon S3 storage class applied to delivered objects.

    " + }, + "UpdateChannelRequest": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "location": "uri", + "locationName": "channelArn", + "documentation": "

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    " + }, + "ClusterArn": { + "shape": "__string", + "location": "uri", + "locationName": "clusterArn", + "documentation": "

    The Amazon Resource Name (ARN) that uniquely identifies the cluster.

    " + }, + "IcebergDestinationUpdate": { + "shape": "IcebergDestinationUpdate", + "locationName": "icebergDestinationUpdate", + "documentation": "

    Updates fields on an Apache Iceberg destination. Use only when the channel was created with an Iceberg destination.

    " + }, + "S3DestinationUpdate": { + "shape": "S3DestinationUpdate", + "locationName": "s3DestinationUpdate", + "documentation": "

    Updates fields on an Amazon S3 destination. Use only when the channel was created with an Amazon S3 destination.

    " + } + }, + "required": [ + "ClusterArn", + "ChannelArn" + ], + "documentation": "

    Updates an existing channel's destination configuration. You must update the same destination type the channel was created with; the destination type cannot be changed.

    " + }, + "UpdateChannelResponse": { + "type": "structure", + "members": { + "ChannelArn": { + "shape": "__string", + "locationName": "channelArn", + "documentation": "

    The Amazon Resource Name (ARN) that uniquely identifies the channel.

    " + }, + "ClusterOperationArn": { + "shape": "__string", + "locationName": "clusterOperationArn", + "documentation": "\n

    The Amazon Resource Name (ARN) of the cluster operation.

    \n " + } + }, + "required": [ + "ChannelArn" + ], + "documentation": "

    Returns the channel ARN and the cluster-operation ARN that tracks the asynchronous update.

    " + }, "UpdateClusterConfigurationRequest": { "type": "structure", "members": { @@ -7922,6 +9093,16 @@ "AWSSERVICE" ] }, + "ValueConverter": { + "type": "string", + "documentation": "

    The deserialization format applied to Apache Kafka record values.

    ", + "enum": [ + "BYTE_ARRAY", + "JSON", + "JSON_SCHEMA_GSR", + "STRING" + ] + }, "VpcConnectionInfo": { "type": "structure", "members": { @@ -8096,6 +9277,12 @@ "shape": "ClusterOperationV2Summary" } }, + "__listOfChannelInfo": { + "type": "list", + "member": { + "shape": "ChannelInfo" + } + }, "__listOfClusterOperationStep": { "type": "list", "member": { @@ -8108,6 +9295,18 @@ "shape": "CompatibleKafkaVersion" } }, + "__listOfDestinationTable": { + "type": "list", + "member": { + "shape": "DestinationTable" + } + }, + "__listOfTopicConfiguration": { + "type": "list", + "member": { + "shape": "TopicConfiguration" + } + }, "__listOfVpcConfig": { "type": "list", "member": { @@ -8156,6 +9355,12 @@ "shape": "NodeInfo" } }, + "__listOfPartitionSource": { + "type": "list", + "member": { + "shape": "PartitionSource" + } + }, "__listOfClientVpcConnection": { "type": "list", "member": { diff --git a/services/kafkaconnect/pom.xml b/services/kafkaconnect/pom.xml index 6ffce7a14f1c..ee7c56704963 100644 --- a/services/kafkaconnect/pom.xml +++ b/services/kafkaconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kafkaconnect AWS Java SDK :: Services :: Kafka Connect diff --git a/services/kafkaconnect/src/main/resources/codegen-resources/customization.config b/services/kafkaconnect/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/kafkaconnect/src/main/resources/codegen-resources/customization.config +++ b/services/kafkaconnect/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..60489e170550 --- /dev/null +++ b/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,203 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafkaconnect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafkaconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafkaconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kafkaconnect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEEAAAABwX14QUF9eEKAAAABAAAAAsAAAAJAAAABQX14QQAAAAKAAAABgX14QgF9eEJAAAABQX14QUAAAAMAAAABgAAAA0F9eEHAAAABwX14QYF9eEHAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9a6bf3aa37c2..000000000000 --- a/services/kafkaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,430 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://kafkaconnect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://kafkaconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafkaconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafkaconnect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kafkaconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kafkaconnect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/kafkaconnect/src/main/resources/codegen-resources/service-2.json b/services/kafkaconnect/src/main/resources/codegen-resources/service-2.json index 056d7f3a50d4..f14ae502139f 100644 --- a/services/kafkaconnect/src/main/resources/codegen-resources/service-2.json +++ b/services/kafkaconnect/src/main/resources/codegen-resources/service-2.json @@ -329,6 +329,26 @@ "documentation":"

    Returns a list of all of the worker configurations in this account and Region.

    ", "readonly":true }, + "RestartConnector":{ + "name":"RestartConnector", + "http":{ + "method":"POST", + "requestUri":"/v1/connectors/{connectorArn}/restart", + "responseCode":200 + }, + "input":{"shape":"RestartConnectorRequest"}, + "output":{"shape":"RestartConnectorResponse"}, + "errors":[ + {"shape":"NotFoundException"}, + {"shape":"BadRequestException"}, + {"shape":"ForbiddenException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"UnauthorizedException"}, + {"shape":"InternalServerErrorException"} + ], + "documentation":"

    Restarts the specified connector. By default, this operation restarts the connector and all of its tasks. This operation is asynchronous and returns a connector operation ARN that you can pass to DescribeConnectorOperation to track the state of the restart.

    " + }, "TagResource":{ "name":"TagResource", "http":{ @@ -645,7 +665,10 @@ "UPDATE_FAILED", "ROLLBACK_IN_PROGRESS", "ROLLBACK_FAILED", - "ROLLBACK_COMPLETE" + "ROLLBACK_COMPLETE", + "RESTART_IN_PROGRESS", + "RESTART_COMPLETE", + "RESTART_FAILED" ] }, "ConnectorOperationStep":{ @@ -714,7 +737,8 @@ "UPDATE_WORKER_SETTING", "UPDATE_CONNECTOR_CONFIGURATION", "ISOLATE_CONNECTOR", - "RESTORE_CONNECTOR" + "RESTORE_CONNECTOR", + "RESTART_CONNECTOR" ] }, "ConnectorState":{ @@ -724,7 +748,8 @@ "CREATING", "UPDATING", "DELETING", - "FAILED" + "FAILED", + "RESTARTING" ] }, "ConnectorSummary":{ @@ -1862,6 +1887,37 @@ }, "documentation":"

    An update to a connector's fixed capacity.

    " }, + "RestartConnectorRequest":{ + "type":"structure", + "required":["connectorArn"], + "members":{ + "connectorArn":{ + "shape":"__string", + "documentation":"

    The Amazon Resource Name (ARN) of the connector that you want to restart.

    ", + "location":"uri", + "locationName":"connectorArn" + }, + "onlyFailedTasks":{ + "shape":"__boolean", + "documentation":"

    Specifies whether to restart only the connector's failed tasks. If true, the operation restarts only the tasks that are currently in a failed state, and healthy tasks continue running. If false or not specified, the operation restarts the connector and all of its tasks.

    ", + "location":"querystring", + "locationName":"onlyFailedTasks" + } + } + }, + "RestartConnectorResponse":{ + "type":"structure", + "members":{ + "connectorArn":{ + "shape":"__string", + "documentation":"

    The Amazon Resource Name (ARN) of the connector.

    " + }, + "connectorOperationArn":{ + "shape":"__string", + "documentation":"

    The Amazon Resource Name (ARN) of the connector operation created to perform the restart.

    " + } + } + }, "S3Location":{ "type":"structure", "required":[ diff --git a/services/kendra/pom.xml b/services/kendra/pom.xml index 9ffd72942f51..6d4248fb0b21 100644 --- a/services/kendra/pom.xml +++ b/services/kendra/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kendra AWS Java SDK :: Services :: Kendra diff --git a/services/kendra/src/main/resources/codegen-resources/customization.config b/services/kendra/src/main/resources/codegen-resources/customization.config index d5dea02b2d47..8a5b385a97e4 100644 --- a/services/kendra/src/main/resources/codegen-resources/customization.config +++ b/services/kendra/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "DocumentAttributeValue": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/kendra/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kendra/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..72d0f22dea43 --- /dev/null +++ b/services/kendra/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kendra/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kendra/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fc36a7a14bed..000000000000 --- a/services/kendra/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kendra-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kendra-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kendra.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kendra.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kendraranking/pom.xml b/services/kendraranking/pom.xml index 9140b21227ec..60724f6827eb 100644 --- a/services/kendraranking/pom.xml +++ b/services/kendraranking/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kendraranking AWS Java SDK :: Services :: Kendra Ranking @@ -61,5 +61,10 @@ http-auth-aws ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + diff --git a/services/kendraranking/src/main/resources/codegen-resources/customization.config b/services/kendraranking/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/kendraranking/src/main/resources/codegen-resources/customization.config +++ b/services/kendraranking/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/kendraranking/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kendraranking/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..212110efbacd --- /dev/null +++ b/services/kendraranking/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,157 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-ranking-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-ranking.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-ranking-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kendra-ranking.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAAAAAkAAAADAAAAAQAAAAQF9eEIAAAAAgAAAAUF9eEIAAAAAwAAAAcAAAAGAAAABQX14QUF9eEHAAAABAAAAAgF9eEEAAAABQX14QMF9eEGAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/kendraranking/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kendraranking/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0f89b8b2b54b..000000000000 --- a/services/kendraranking/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kendra-ranking-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kendra-ranking.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kendra-ranking-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kendra-ranking.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kendraranking/src/main/resources/codegen-resources/service-2.json b/services/kendraranking/src/main/resources/codegen-resources/service-2.json index b719aaa64f03..c7d324f09d21 100644 --- a/services/kendraranking/src/main/resources/codegen-resources/service-2.json +++ b/services/kendraranking/src/main/resources/codegen-resources/service-2.json @@ -4,8 +4,11 @@ "apiVersion":"2022-10-19", "endpointPrefix":"kendra-ranking", "jsonVersion":"1.0", - "protocol":"json", - "protocols":["json"], + "protocol":"smithy-rpc-v2-cbor", + "protocols":[ + "smithy-rpc-v2-cbor", + "json" + ], "serviceAbbreviation":"Kendra Ranking", "serviceFullName":"Amazon Kendra Intelligent Ranking", "serviceId":"Kendra Ranking", @@ -179,6 +182,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    You don’t have sufficient access to perform this action. Please ensure you have the required permission policies and user accounts and try again.

    ", + "error":{"httpStatusCode":403}, "exception":true }, "AmazonResourceName":{ @@ -214,6 +218,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    A conflict occurred with the request. Please fix any inconsistencies with your resources and try again.

    ", + "error":{"httpStatusCode":409}, "exception":true }, "CreateRescoreExecutionPlanRequest":{ @@ -408,6 +413,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    An issue occurred with the internal server used for your Amazon Kendra Intelligent Ranking service. Please wait a few minutes and try again, or contact Support for help.

    ", + "error":{"httpStatusCode":500}, "exception":true, "fault":true }, @@ -597,6 +603,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The resource you want to use doesn't exist. Please check you have provided the correct resource and try again.

    ", + "error":{"httpStatusCode":404}, "exception":true }, "ResourceUnavailableException":{ @@ -605,6 +612,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The resource you want to use is unavailable. Please check you have provided the correct resource information and try again.

    ", + "error":{"httpStatusCode":404}, "exception":true }, "SearchQuery":{ @@ -618,6 +626,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    You have exceeded the set limits for your Amazon Kendra Intelligent Ranking service. Please see Quotas for more information, or contact Support to inquire about an increase of limits.

    ", + "error":{"httpStatusCode":402}, "exception":true }, "Tag":{ @@ -689,6 +698,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The request was denied due to request throttling. Please reduce the number of requests and try again.

    ", + "error":{"httpStatusCode":429}, "exception":true }, "Timestamp":{"type":"timestamp"}, @@ -753,6 +763,7 @@ "Message":{"shape":"ErrorMessage"} }, "documentation":"

    The input fails to satisfy the constraints set by the Amazon Kendra Intelligent Ranking service. Please provide the correct input and try again.

    ", + "error":{"httpStatusCode":400}, "exception":true } }, diff --git a/services/keyspaces/pom.xml b/services/keyspaces/pom.xml index ad9e3ec726da..ac5186f157dd 100644 --- a/services/keyspaces/pom.xml +++ b/services/keyspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT keyspaces AWS Java SDK :: Services :: Keyspaces diff --git a/services/keyspaces/src/main/resources/codegen-resources/customization.config b/services/keyspaces/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/keyspaces/src/main/resources/codegen-resources/customization.config +++ b/services/keyspaces/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/keyspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/keyspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3c2f5f662f5c --- /dev/null +++ b/services/keyspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/keyspaces/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/keyspaces/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c403821cce34..000000000000 --- a/services/keyspaces/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cassandra-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://cassandra.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cassandra-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://cassandra.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cassandra.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/keyspacesstreams/pom.xml b/services/keyspacesstreams/pom.xml index 59e0f305e8e9..2f1c847d6379 100644 --- a/services/keyspacesstreams/pom.xml +++ b/services/keyspacesstreams/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT keyspacesstreams AWS Java SDK :: Services :: Keyspaces Streams diff --git a/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4f70c4c56ad7 --- /dev/null +++ b/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra-streams-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cassandra-streams.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0a45c4671f00..000000000000 --- a/services/keyspacesstreams/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://cassandra-streams-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://cassandra-streams.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/kinesis/pom.xml b/services/kinesis/pom.xml index ad6303d2927c..69dc80ec3236 100644 --- a/services/kinesis/pom.xml +++ b/services/kinesis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesis AWS Java SDK :: Services :: Amazon Kinesis diff --git a/services/kinesis/src/main/resources/codegen-resources/customization.config b/services/kinesis/src/main/resources/codegen-resources/customization.config index df57fdb8aefb..dfdcec2369ad 100644 --- a/services/kinesis/src/main/resources/codegen-resources/customization.config +++ b/services/kinesis/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "verifiedSimpleMethods": [ "describeLimits", "listStreams" diff --git a/services/kinesis/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesis/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c8f685de0b1a --- /dev/null +++ b/services/kinesis/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,1502 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "OperationType": { + "required": false, + "documentation": "Internal parameter to distinguish between Control/Data plane API and accordingly generate control/data plane endpoint", + "type": "string" + }, + "StreamId": { + "required": false, + "documentation": "The unique identifier of the Kinesis stream", + "type": "string" + }, + "StreamARN": { + "required": false, + "documentation": "The ARN of the Kinesis stream", + "type": "string" + }, + "ConsumerARN": { + "required": false, + "documentation": "The ARN of the Kinesis consumer", + "type": "string" + }, + "ResourceARN": { + "required": false, + "documentation": "The ARN of the Kinesis resource", + "type": "string" + }, + "ChannelARN": { + "required": false, + "documentation": "The ARN of the Kinesis data channel", + "type": "string" + }, + "AccountId": { + "builtIn": "AWS::Auth::AccountId", + "required": false, + "documentation": "The AWS AccountId used for the request.", + "type": "string" + }, + "AccountIdEndpointMode": { + "builtIn": "AWS::Auth::AccountIdEndpointMode", + "required": false, + "documentation": "The AccountId Endpoint Mode.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "StreamId" + } + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "StreamId" + }, + 21, + 24, + false + ], + "assign": "StreamIdSuffixValue" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "StreamId" + }, + 0, + 20, + false + ], + "assign": "StreamIdPrefixValue" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "StreamId" + }, + 20, + 21, + false + ] + }, + "" + ] + }, + "-" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "StreamId" + }, + 3, + 4, + true + ] + }, + "" + ] + }, + "-" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "StreamARN" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ConsumerARN" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "ConsumerARN" + } + ], + "assign": "arn_ssa_2" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 15, + 20, + false + ], + "assign": "HttpsCustomEndpointSuffixValue" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 15, + 16, + false + ] + }, + "" + ] + }, + "-" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 20, + 21, + false + ] + }, + "" + ] + }, + "." + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 7, + 12, + false + ], + "assign": "PlainCustomEndpointSuffixValue" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_2" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_2" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_2" + }, + "service" + ] + }, + "kinesis" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_2" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_2" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_2" + }, + "" + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "StreamARN" + } + ], + "assign": "arn_ssa_4" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_4" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_2" + }, + "stream" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_4" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_2" + }, + "partition" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_4" + }, + "service" + ] + }, + "kinesis" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_4" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_1" + }, + "" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ResourceARN" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ChannelARN" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountIdEndpointMode" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountId" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "ChannelARN" + } + ], + "assign": "arn_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountIdEndpointMode" + }, + "disabled" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "AccountId" + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "service" + ] + }, + "kinesis" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_4" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_4" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_4" + }, + "channel" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "partition" + ] + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "ResourceARN" + } + ], + "assign": "arn_ssa_3" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "region" + ] + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "service" + ] + }, + "kinesis" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_3" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_3" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_3" + }, + "stream" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_3" + }, + "channel" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "partition" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_1" + }, + "stream" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_4" + }, + "partition" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountIdEndpointMode" + }, + "required" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "OperationType" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_3" + }, + "resourceId[1]" + ], + "assign": "resourceId_ssa_1" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "resourceId_ssa_1" + }, + false + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "arn_ssa_1" + }, + "resourceId[1]" + ], + "assign": "resourceId_ssa_2" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "resourceId_ssa_2" + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "OperationType" + }, + "data" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 7, + 8, + false + ] + }, + "" + ] + }, + "-" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Endpoint" + }, + 12, + 13, + false + ] + }, + "" + ] + }, + "." + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled, but this partition does not support DualStack.", + "type": "error" + }, + { + "conditions": [], + "error": "FIPS is enabled, but this partition does not support FIPS.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Operation Type is not set. Please contact service team for resolution.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_4#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_4#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_4#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_4#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Partition: {arn_ssa_4#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Kinesis ARNs don't support `{arnType_ssa_1}` arn types.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: No ARN type specified", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn_ssa_4#service}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Invalid region.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Invalid account id.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Failed to parse ARN.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_2#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_2#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_2#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_2#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Partition: {arn_ssa_2#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Kinesis ARNs don't support `{arnType_ssa_2}` arn types.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn_ssa_2#service}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Unsupported resource type `{arnType_ssa_3}`. Expected: stream or channel", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_3#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_3#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_3#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{arn_ssa_3#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_1}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_1}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_1}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_1}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: Invalid channel id.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Missing channel id.", + "type": "error" + }, + { + "conditions": [], + "error": "Partition: {arn_ssa_3#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn_ssa_3#service}.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_2}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_2}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_2}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{resourceId_ssa_2}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "ChannelARN does not support the `data` operation type.", + "type": "error" + }, + { + "conditions": [], + "error": "Partition: {arn_ssa_1#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: ChannelARN only supports `channel` arn types, found: `{arnType_ssa_4}`.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn_ssa_1#service}.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "metricValues": [ + "O" + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid account id.", + "type": "error" + }, + { + "conditions": [], + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesis.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 155, + "nodes": "/////wAAAAH/////AAAAAAAAAAMAAAAEAAAAAQAAAAUAAAAEAAAACQAAAJoF9eFJAAAAAgAAAI8AAAAGAAAAAwAAAI8AAAAHAAAABAAAAAgAAAAMAAAABQAAAAkAAAAMAAAABgAAAAoAAAAMAAAABwAAAAsAAAAMAAAACAAAAG0AAAAMAAAACQAAAJoAAAANAAAACgAAAF0AAAAOAAAACwAAAE0AAAAPAAAAHgAAADEAAAAQAAAAHwAAAB4AAAARAAAAIAAAABIAAACSAAAAIQAAABMAAAAdAAAAIwAAAB0AAAAUAAAAJAAAABUF9eE9AAAAOAAAABYF9eERAAAAPwAAABkAAAAXAAAAQAAAABgF9eE8AAAAQgX14TsF9eEHAAAAQAAAABsAAAAaAAAAQQX14ToF9eEFAAAAQQAAABwF9eEDAAAAQgX14TkF9eECAAAANwX14T4AAACSAAAAIgAAAB8F9eEcAAAAJQAAACAF9eEbAAAAJgAAACEF9eEaAAAAJwAAACIF9eE4AAAAKAAAACMF9eEYAAAAKQX14RgAAAAkAAAAKgAAACUF9eE3AAAAKwAAACYF9eE2AAAAOAAAACcF9eERAAAAOwAAACgF9eEuAAAAPAAAACkF9eEtAAAAPQX14TUAAAAqAAAAPwAAAC0AAAArAAAAQAAAACwF9eE0AAAAQgX14TMF9eEHAAAAQAAAAC8AAAAuAAAAQQX14TIF9eEFAAAAQQAAADAF9eEDAAAAQgX14TEF9eECAAAALAAAADIF9eEcAAAALQAAADMF9eEbAAAALgAAADQF9eEaAAAALwAAADUF9eEwAAAAMAAAADYF9eEYAAAAMQX14RgAAAA3AAAAMgAAAEQAAAA4AAAAMwAAADkF9eEkAAAANAAAADoF9eEvAAAAOAAAADsF9eERAAAAOQAAADwF9eEuAAAAOgAAAD0F9eEtAAAAPwAAAEAAAAA+AAAAQAAAAD8F9eEsAAAAQgX14SsF9eEHAAAAQAAAAEIAAABBAAAAQQX14SoF9eEFAAAAQQAAAEMF9eEDAAAAQgX14SkF9eECAAAANAAAAEUF9eEvAAAAOAAAAEYF9eERAAAAPwAAAEkAAABHAAAAQAAAAEgF9eEoAAAAQgX14ScF9eEHAAAAQAAAAEsAAABKAAAAQQX14SYF9eEFAAAAQQAAAEwF9eEDAAAAQgX14SUF9eECAAAADAAAAE4F9eEcAAAAEQAAAE8F9eEbAAAAEgAAAFAF9eEaAAAAEwAAAFEF9eEjAAAAFAAAAFIF9eEYAAAAFQX14RgAAABTAAAAGAAAAFQF9eEiAAAAGgAAAFUF9eEhAAAAOAAAAFYF9eERAAAAPwAAAFkAAABXAAAAQAAAAFgF9eEgAAAAQgX14R8F9eEHAAAAQAAAAFsAAABaAAAAQQX14R4F9eEFAAAAQQAAAFwF9eEDAAAAQgX14R0F9eECAAAAFgAAAF4F9eEcAAAAFwAAAF8F9eEbAAAAGQAAAGAF9eEaAAAAGwAAAGEF9eEZAAAAHAAAAGIF9eEYAAAAHQX14RgAAABjAAAANQAAAGQF9eEXAAAANgAAAGUF9eEWAAAAOAAAAGYF9eERAAAAPwAAAGkAAABnAAAAQAAAAGgF9eEVAAAAQgX14RQF9eEHAAAAQAAAAGsAAABqAAAAQQX14RMF9eEFAAAAQQAAAGwF9eEDAAAAQgX14RIF9eECAAAACQAAAG4AAAByAAAADQAAAG8AAABxAAAADgAAAHAAAABxAAAADwAAAIcAAABxAAAAEAAAAHMAAAByAAAAOAAAAHUF9eERAAAAOAAAAHQF9eERAAAAPgAAAHwAAAB1AAAAPwAAAHgAAAB2AAAAQAAAAHcF9eEQAAAAQgX14Q8F9eEHAAAAQAAAAHoAAAB5AAAAQQX14Q4F9eEFAAAAQQAAAHsF9eEDAAAAQgX14Q0F9eECAAAAPwAAAIEAAAB9AAAAQAAAAH8AAAB+AAAARAX14QwF9eEQAAAAQgAAAIAF9eEHAAAARAX14QsF9eEPAAAAQAAAAIQAAACCAAAAQQAAAIMF9eEFAAAARAX14QoF9eEOAAAAQQAAAIUF9eEDAAAAQgAAAIYF9eECAAAARAX14QkF9eENAAAAOAAAAIgF9eERAAAAPwAAAIsAAACJAAAAQAAAAIoF9eEIAAAAQgX14QYF9eEHAAAAQAAAAI0AAACMAAAAQQX14QQF9eEFAAAAQQAAAI4F9eEDAAAAQgX14QEF9eECAAAACQAAAJoAAACQAAAAIAAAAJEAAACSAAAANwX14T8AAACSAAAAPwAAAJUAAACTAAAAQAAAAJQF9eFIAAAAQgX14UcF9eEHAAAAQAAAAJgAAACWAAAAQQAAAJcF9eEFAAAAQwX14UUF9eFGAAAAQQAAAJkF9eFEAAAAQgX14UMF9eFEAAAAPwX14UAAAACbAAAAQAX14UEF9eFC" +} \ No newline at end of file diff --git a/services/kinesis/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesis/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8bd3a0316c13..000000000000 --- a/services/kinesis/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,2739 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "StreamId": { - "required": false, - "documentation": "The unique identifier of the Kinesis stream", - "type": "string" - }, - "StreamARN": { - "required": false, - "documentation": "The ARN of the Kinesis stream", - "type": "string" - }, - "OperationType": { - "required": false, - "documentation": "Internal parameter to distinguish between Control/Data plane API and accordingly generate control/data plane endpoint", - "type": "string" - }, - "ConsumerARN": { - "required": false, - "documentation": "The ARN of the Kinesis consumer", - "type": "string" - }, - "ResourceARN": { - "required": false, - "documentation": "The ARN of the Kinesis resource", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "StreamId" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "StreamId" - }, - 20, - 21, - false - ], - "assign": "StreamIdDelimiterValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "StreamIdDelimiterValue" - }, - "-" - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "StreamId" - }, - 3, - 4, - true - ], - "assign": "StreamIdDelimiterReversedValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "StreamIdDelimiterReversedValue" - }, - "-" - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "StreamId" - }, - 0, - 20, - false - ], - "assign": "StreamIdPrefixValue" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "StreamId" - }, - 21, - 24, - false - ], - "assign": "StreamIdSuffixValue" - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "OperationType" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 15, - 16, - false - ], - "assign": "HttpsCustomEndpointDelimiterValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "HttpsCustomEndpointDelimiterValue" - }, - "-" - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 20, - 21, - false - ], - "assign": "HttpsEndpointDelimiterValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "HttpsEndpointDelimiterValue" - }, - "." - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 15, - 20, - false - ], - "assign": "HttpsCustomEndpointSuffixValue" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{HttpsCustomEndpointSuffixValue}.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 7, - 8, - false - ], - "assign": "PlainCustomEndpointDelimiterValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "PlainCustomEndpointDelimiterValue" - }, - "-" - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 12, - 13, - false - ], - "assign": "PlainEndpointDelimiterValue" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "PlainEndpointDelimiterValue" - }, - "." - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Endpoint" - }, - 7, - 12, - false - ], - "assign": "PlainCustomEndpointSuffixValue" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis{PlainCustomEndpointSuffixValue}.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{StreamIdPrefixValue}.{StreamIdSuffixValue}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Operation Type is not set. Please contact service team for resolution.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "StreamARN" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "StreamARN" - } - ], - "assign": "arn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "region" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "service" - ] - }, - "kinesis" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "stream" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "{arn#partition}" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "OperationType" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Operation Type is not set. Please contact service team for resolution.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Partition: {arn#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Kinesis ARNs don't support `{arnType}` arn types.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn#service}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid region.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid account id.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Failed to parse ARN.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "ConsumerARN" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "ConsumerARN" - } - ], - "assign": "arn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "region" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "service" - ] - }, - "kinesis" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "stream" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "{arn#partition}" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "OperationType" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Operation Type is not set. Please contact service team for resolution.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Partition: {arn#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Kinesis ARNs don't support `{arnType}` arn types.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn#service}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid region.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid account id.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Failed to parse ARN.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "ResourceARN" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "ResourceARN" - } - ], - "assign": "arn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "region" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "service" - ] - }, - "kinesis" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "stream" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "{arn#partition}" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "OperationType" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled, but this partition does not support DualStack.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled, but this partition does not support FIPS.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{arn#accountId}.{OperationType}-kinesis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Operation Type is not set. Please contact service team for resolution.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Partition: {arn#partition} from ARN doesn't match with partition name: {PartitionResult#name}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Kinesis ARNs don't support `{arnType}` arn types.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN was not for the Kinesis service, found: {arn#service}.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid region.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Invalid account id.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Failed to parse ARN.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://kinesis.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesis/src/main/resources/codegen-resources/endpoint-tests.json b/services/kinesis/src/main/resources/codegen-resources/endpoint-tests.json index 0a5d8b6447a1..cf29cc5da235 100644 --- a/services/kinesis/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/kinesis/src/main/resources/codegen-resources/endpoint-tests.json @@ -1487,7 +1487,7 @@ { "documentation": "ResourceARN as StreamARN test: Invalid ARN: Kinesis ARNs only support stream arn types", "expect": { - "error": "Invalid ARN: Kinesis ARNs don't support `accesspoint` arn types." + "error": "Invalid ARN: Unsupported resource type `accesspoint`. Expected: stream or channel" }, "params": { "Region": "us-east-1", @@ -1838,7 +1838,7 @@ { "documentation": "ResourceARN as ConsumerARN test: Invalid ARN: Kinesis ARNs only support stream arn/consumer arn types", "expect": { - "error": "Invalid ARN: Kinesis ARNs don't support `accesspoint` arn types." + "error": "Invalid ARN: Unsupported resource type `accesspoint`. Expected: stream or channel" }, "params": { "Region": "us-east-1", @@ -2100,6 +2100,234 @@ "ResourceARN": "arn:aws-iso-b:kinesis:us-isob-east-1:123:stream/test-stream/consumer/test-consumer:1525898737" } }, + { + "documentation": "ResourceARN as ChannelARN test: Invalid ARN: unsupported resource type", + "expect": { + "error": "Invalid ARN: Unsupported resource type `accesspoint`. Expected: stream or channel" + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:accesspoint/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Invalid ARN: Not Kinesis", + "expect": { + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: s3." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:s3:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Invalid ARN: partitions mismatch", + "expect": { + "error": "Partition: aws from ARN doesn't match with partition name: aws-us-gov." + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-west-2:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: OperationType not set", + "expect": { + "error": "Operation Type is not set. Please contact service team for resolution." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Missing channel id", + "expect": { + "error": "Invalid ARN: Missing channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Invalid channel id (subdomains not allowed)", + "expect": { + "error": "Invalid ARN: Invalid channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8.ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Custom Endpoint is specified", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe", + "Endpoint": "https://example.com" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: endpoint targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: endpoint with fips targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: endpoint with Dual Stack enabled", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: endpoint with Dual Stack and FIPS enabled", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: RegionMismatch: client region should be used for endpoint region", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-west-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Account endpoint with FIPS enabled for cn regions", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.cn-northwest-1.amazonaws.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws-cn:kinesis:cn-northwest-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Account endpoint with FIPS and DualStack enabled for cn regions", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "ResourceARN": "arn:aws-cn:kinesis:cn-northwest-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Account endpoint targeting control operation type in ADC regions", + "expect": { + "endpoint": { + "url": "https://kinesis.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws-iso:kinesis:us-iso-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ResourceARN as ChannelARN test: Account endpoint with fips targeting control operation type in ADC regions", + "expect": { + "endpoint": { + "url": "https://kinesis-fips.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws-iso:kinesis:us-iso-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, { "documentation": "StreamId test: OperationType not set with StreamId", "expect": { @@ -2679,6 +2907,1671 @@ "StreamId": "af4lwng4k01746835071-yz", "ResourceARN": "arn:aws:kinesis:us-east-1:123:stream/test-stream" } + }, + { + "documentation": "ChannelARN: endpoint targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1" + }, + "operationName": "DescribeChannel", + "operationParams": { + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ChannelARN: endpoint with FIPS targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true + }, + "operationName": "DeleteChannel", + "operationParams": { + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ChannelARN: endpoint with DualStack targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseDualStack": true + }, + "operationName": "UpdateChannel", + "operationParams": { + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "ChannelARN: endpoint with FIPS and DualStack targeting control operation type", + "expect": { + "endpoint": { + "url": "https://apu0zt8ge6utbndxe.control-kinesis-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "DescribeChannel", + "operationParams": { + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: ChannelARN only supports channel arn types", + "expect": { + "error": "Invalid ARN: ChannelARN only supports `channel` arn types, found: `stream`." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:stream/test-stream" + } + }, + { + "documentation": "Invalid ChannelARN: ARN was not for the Kinesis service", + "expect": { + "error": "Invalid ARN: The ARN was not for the Kinesis service, found: s3." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "ChannelARN": "arn:aws:s3:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: OperationType not set", + "expect": { + "error": "Operation Type is not set. Please contact service team for resolution." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: partitions mismatch", + "expect": { + "error": "Partition: aws from ARN doesn't match with partition name: aws-us-gov." + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "ChannelARN": "arn:aws:kinesis:us-west-2:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: missing channel id", + "expect": { + "error": "Invalid ARN: Missing channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel" + } + }, + { + "documentation": "Invalid ChannelARN: channel id contains a period (subdomains not allowed)", + "expect": { + "error": "Invalid ARN: Invalid channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8.ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: channel id exceeds 63 character host label limit", + "expect": { + "error": "Invalid ARN: Invalid channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + } + }, + { + "documentation": "Invalid ChannelARN: channel id starts with a hyphen", + "expect": { + "error": "Invalid ARN: Invalid channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/-pu0zt8ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: channel id contains an invalid character", + "expect": { + "error": "Invalid ARN: Invalid channel id." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8_ge6utbndxe" + } + }, + { + "documentation": "Invalid ChannelARN: data operation type is not supported for channel", + "expect": { + "error": "ChannelARN does not support the `data` operation type." + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "ChannelARN": "arn:aws:kinesis:us-east-1:298091445058:channel/apu0zt8ge6utbndxe" + } + }, + { + "documentation": "AccountId test: Account Id present", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://012345678901.data-kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "012345678901", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "GetShardIterator", + "operationParams": { + "ShardId": "shardId-000000000001", + "ShardIteratorType": "LATEST", + "StreamName": "test-stream" + } + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "data", + "AccountId": "012345678901", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "AccountId test: Account Id present with fips", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123.control-kinesis-fips.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123", + "AWS::Auth::AccountIdEndpointMode": "required", + "AWS::UseFIPS": true + }, + "operationName": "ListShards", + "operationParams": { + "StreamName": "testStream" + } + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "AccountId test: Account Id present with dual stack", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123.control-kinesis.us-west-2.api.aws" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "AccountId test: Account Id present with fips and dual stack", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123.control-kinesis-fips.us-west-2.api.aws" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present with streamId", + "expect": { + "endpoint": { + "url": "https://af4lwng4k01746835071.xyz.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamId": "af4lwng4k01746835071-xyz", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present with stream ARN", + "expect": { + "endpoint": { + "url": "https://123.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamARN": "arn:aws:kinesis:us-east-1:123:stream/test-stream", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present with consumer ARN", + "expect": { + "endpoint": { + "url": "https://123.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ConsumerARN": "arn:aws:kinesis:us-west-2:123:stream/testStream/consumer/test-consumer:1525898737", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present with resource ARN", + "expect": { + "endpoint": { + "url": "https://123.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-west-2:123:stream/testStream/consumer/test-consumer:1525898737", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present and stream ARN with different accountId", + "expect": { + "endpoint": { + "url": "https://456.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-west-2:456:stream/testStream", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id present and consumer ARN with different accountId", + "expect": { + "endpoint": { + "url": "https://456.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "ResourceARN": "arn:aws:kinesis:us-west-2:456:stream/testStream/consumer/test-consumer:1525898737", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id, streamId and resource ARN with different accountId", + "expect": { + "endpoint": { + "url": "https://af4lwng4k01746835071.xyz.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamId": "af4lwng4k01746835071-xyz", + "ResourceARN": "arn:aws:kinesis:us-west-2:456:stream/testStream/consumer/test-consumer:1525898737", + "AccountId": "123", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id with account id endpoint mode disabled", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "ListShards", + "operationParams": { + "StreamName": "testStream" + } + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "Account Id and StreamArn with account id endpoint mode disabled", + "expect": { + "endpoint": { + "url": "https://456.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamARN": "arn:aws:kinesis:us-west-2:456:stream/testStream", + "AccountId": "123", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode required", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountIdEndpointMode": "required" + }, + "operationName": "ListShards", + "operationParams": { + "StreamName": "testStream" + } + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode required, fips and dual stack enabled", + "expect": { + "error": "AccountIdEndpointMode is required but no AccountID was provided or able to be loaded" + }, + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode required in ADC region", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id present with account id endpoint mode required in ADC region", + "expect": { + "error": "Invalid Configuration: AccountIdEndpointMode is required but account endpoints are not supported in this partition" + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id present with account id endpoint mode preferred in ADC region", + "expect": { + "endpoint": { + "url": "https://kinesis.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode required and endpoint override", + "expect": { + "endpoint": { + "url": "https://kinesis-pod1.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "Endpoint": "https://kinesis-pod1.us-west-2.amazonaws.com", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id missing with StreamArn and account id endpoint mode required", + "expect": { + "endpoint": { + "url": "https://456.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamARN": "arn:aws:kinesis:us-west-2:456:stream/testStream", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id missing with StreamId and account id endpoint mode required", + "expect": { + "endpoint": { + "url": "https://af4lwng4k01746835071.xyz.control-kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "StreamId": "af4lwng4k01746835071-xyz", + "AccountIdEndpointMode": "required" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode preferred", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "Account Id missing with account id endpoint mode disabled", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateStream: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateStream: control operation type with FIPS and AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "ListStreams: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "ListStreams" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "ListStreams: control operation type with FIPS and DualStack", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-west-2.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "ListStreams" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "DescribeLimits: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "DescribeLimits" + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "DescribeLimits: control operation type with FIPS", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true + }, + "operationName": "DescribeLimits" + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "DescribeAccountSettings: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "DescribeAccountSettings" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "DescribeAccountSettings: control operation type with FIPS and DualStack", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-west-2.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "DescribeAccountSettings" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "UpdateAccountSettings: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "UpdateAccountSettings", + "operationParams": { + "MinimumThroughputBillingCommitment": { + "Status": "ENABLED" + } + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "UpdateAccountSettings: control operation type with FIPS", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true + }, + "operationName": "UpdateAccountSettings", + "operationParams": { + "MinimumThroughputBillingCommitment": { + "Status": "ENABLED" + } + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateStream: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "ListStreams: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "ListStreams" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "DescribeLimits: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "DescribeLimits" + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "DescribeAccountSettings: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "DescribeAccountSettings" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "UpdateAccountSettings: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "UpdateAccountSettings", + "operationParams": { + "MinimumThroughputBillingCommitment": { + "Status": "ENABLED" + } + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateStream: account id endpoint mode disabled with FIPS falls back to regional FIPS endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseFIPS": true + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateStream: account id endpoint mode disabled with DualStack falls back to regional DualStack endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseDualStack": true + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateStream: account id endpoint mode disabled with FIPS and DualStack falls back to regional FIPS DualStack endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "CreateStream", + "operationParams": { + "StreamName": "test-stream", + "ShardCount": 1 + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateChannel: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateChannel: control operation type with FIPS and AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateChannel: control operation type with DualStack and AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseDualStack": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateChannel: control operation type with FIPS and DualStack and AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "CreateChannel: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateChannel: account id endpoint mode disabled with FIPS falls back to regional FIPS endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis-fips.us-east-1.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseFIPS": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateChannel: account id endpoint mode disabled with DualStack falls back to regional DualStack endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseDualStack": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "CreateChannel: account id endpoint mode disabled with FIPS and DualStack falls back to regional FIPS DualStack endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis-fips.us-east-1.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-east-1", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "CreateChannel", + "operationParams": { + "ChannelName": "test-channel", + "ServiceExecutionRoleARN": "arn:aws:iam::123456789012:role/test-role", + "StreamConfigurationList": [ + { + "StreamARN": "arn:aws:kinesis:us-east-1:123456789012:stream/test-stream", + "RecordConfiguration": { + "RecordFormatType": "JSON" + } + } + ] + } + } + ], + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } + }, + { + "documentation": "ListChannels: control operation type with AccountId", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred" + }, + "operationName": "ListChannels" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "ListChannels: control operation type with FIPS and DualStack", + "expect": { + "endpoint": { + "properties": { + "metricValues": [ + "O" + ] + }, + "url": "https://123456789012.control-kinesis-fips.us-west-2.api.aws" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "preferred", + "AWS::UseFIPS": true, + "AWS::UseDualStack": true + }, + "operationName": "ListChannels" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": true, + "UseDualStack": true, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "preferred" + } + }, + { + "documentation": "ListChannels: account id endpoint mode disabled falls back to regional endpoint", + "expect": { + "endpoint": { + "url": "https://kinesis.us-west-2.amazonaws.com" + } + }, + "operationInputs": [ + { + "builtInParams": { + "AWS::Region": "us-west-2", + "AWS::Auth::AccountId": "123456789012", + "AWS::Auth::AccountIdEndpointMode": "disabled" + }, + "operationName": "ListChannels" + } + ], + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false, + "OperationType": "control", + "AccountId": "123456789012", + "AccountIdEndpointMode": "disabled" + } } ], "version": "1.0" diff --git a/services/kinesis/src/main/resources/codegen-resources/paginators-1.json b/services/kinesis/src/main/resources/codegen-resources/paginators-1.json index 690d5fe919d1..ee488f5d553e 100644 --- a/services/kinesis/src/main/resources/codegen-resources/paginators-1.json +++ b/services/kinesis/src/main/resources/codegen-resources/paginators-1.json @@ -7,6 +7,12 @@ "output_token": "StreamDescription.Shards[-1].ShardId", "result_key": "StreamDescription.Shards" }, + "ListChannels": { + "input_token": "NextToken", + "limit_key": "MaxResults", + "output_token": "NextToken", + "result_key": "ChannelSummaries" + }, "ListStreamConsumers": { "input_token": "NextToken", "limit_key": "MaxResults", diff --git a/services/kinesis/src/main/resources/codegen-resources/service-2.json b/services/kinesis/src/main/resources/codegen-resources/service-2.json index 0e4cfbd0b6df..9334d74db047 100644 --- a/services/kinesis/src/main/resources/codegen-resources/service-2.json +++ b/services/kinesis/src/main/resources/codegen-resources/service-2.json @@ -35,6 +35,33 @@ "OperationType":{"value":"control"} } }, + "CreateChannel":{ + "name":"CreateChannel", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateChannelInput"}, + "output":{"shape":"CreateChannelOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceInUseException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"KMSDisabledException"}, + {"shape":"KMSInvalidStateException"}, + {"shape":"KMSAccessDeniedException"}, + {"shape":"KMSNotFoundException"}, + {"shape":"KMSOptInRequired"}, + {"shape":"KMSThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Creates a channel that delivers records from a Kinesis data stream to a destination. A channel reads records from the specified stream and writes them to streaming tables on Apache Iceberg (Amazon S3 Tables) or to a general purpose Amazon S3 bucket.

    You must specify either S3DestinationConfiguration or S3TablesDestinationConfiguration, but not both.

    To use this operation, you must have permission to pass the specified service execution IAM role to Amazon Kinesis Data Streams (the iam:PassRole permission on that role).

    Creating a channel is an asynchronous operation. Upon receiving the request, Amazon Kinesis Data Streams returns immediately with the channel in the CREATING state. After provisioning is complete, Amazon Kinesis Data Streams sets the state to ACTIVE. You can use DescribeChannel to check the current state.

    This operation is only supported for data streams with the on-demand capacity mode.

    This operation has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. Exceeding 5 TPS results in a LimitExceededException.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, "CreateStream":{ "name":"CreateStream", "http":{ @@ -48,7 +75,10 @@ {"shape":"InvalidArgumentException"}, {"shape":"ValidationException"} ], - "documentation":"

    Creates a Kinesis data stream. A stream captures and transports data records that are continuously emitted from different data sources or producers. Scale-out within a stream is explicitly supported by means of shards, which are uniquely identified groups of data records in a stream.

    You can create your data stream using either on-demand or provisioned capacity mode. Data streams with an on-demand mode require no capacity planning and automatically scale to handle gigabytes of write and read throughput per minute. With the on-demand mode, Kinesis Data Streams automatically manages the shards in order to provide the necessary throughput.

    If you'd still like to proactively scale your on-demand data stream’s capacity, you can unlock the warm throughput feature for on-demand data streams by enabling MinimumThroughputBillingCommitment for your account. Once your account has MinimumThroughputBillingCommitment enabled, you can specify the warm throughput in MiB per second that your stream can support in writes.

    For the data streams with a provisioned mode, you must specify the number of shards for the data stream. Each shard can support reads up to five transactions per second, up to a maximum data read total of 2 MiB per second. Each shard can support writes up to 1,000 records per second, up to a maximum data write total of 1 MiB per second. If the amount of data input increases or decreases, you can add or remove shards.

    The stream name identifies the stream. The name is scoped to the Amazon Web Services account used by the application. It is also scoped by Amazon Web Services Region. That is, two streams in two different accounts can have the same name, and two streams in the same account, but in two different Regions, can have the same name.

    CreateStream is an asynchronous operation. Upon receiving a CreateStream request, Kinesis Data Streams immediately returns and sets the stream status to CREATING. After the stream is created, Kinesis Data Streams sets the stream status to ACTIVE. You should perform read and write operations only on an ACTIVE stream.

    You receive a LimitExceededException when making a CreateStream request when you try to do one of the following:

    • Have more than five streams in the CREATING state at any point in time.

    • Create more shards than are authorized for your account.

    For the default shard or on-demand throughput limits for an Amazon Web Services account, see Amazon Kinesis Data Streams Limits in the Amazon Kinesis Data Streams Developer Guide. To increase this limit, contact Amazon Web Services Support.

    You can use DescribeStreamSummary to check the stream status, which is returned in StreamStatus.

    CreateStream has a limit of five transactions per second per account.

    You can add tags to the stream when making a CreateStream request by setting the Tags parameter. If you pass the Tags parameter, in addition to having the kinesis:CreateStream permission, you must also have the kinesis:AddTagsToStream permission for the stream that will be created. The kinesis:TagResource permission won’t work to tag streams on creation. Tags will take effect from the CREATING status of the stream, but you can't make any updates to the tags until the stream is in ACTIVE state.

    " + "documentation":"

    Creates a Kinesis data stream. A stream captures and transports data records that are continuously emitted from different data sources or producers. Scale-out within a stream is explicitly supported by means of shards, which are uniquely identified groups of data records in a stream.

    You can create your data stream using either on-demand or provisioned capacity mode. Data streams with an on-demand mode require no capacity planning and automatically scale to handle gigabytes of write and read throughput per minute. With the on-demand mode, Kinesis Data Streams automatically manages the shards in order to provide the necessary throughput.

    If you'd still like to proactively scale your on-demand data stream’s capacity, you can unlock the warm throughput feature for on-demand data streams by enabling MinimumThroughputBillingCommitment for your account. Once your account has MinimumThroughputBillingCommitment enabled, you can specify the warm throughput in MiB per second that your stream can support in writes.

    For the data streams with a provisioned mode, you must specify the number of shards for the data stream. Each shard can support reads up to five transactions per second, up to a maximum data read total of 2 MiB per second. Each shard can support writes up to 1,000 records per second, up to a maximum data write total of 1 MiB per second. If the amount of data input increases or decreases, you can add or remove shards.

    The stream name identifies the stream. The name is scoped to the Amazon Web Services account used by the application. It is also scoped by Amazon Web Services Region. That is, two streams in two different accounts can have the same name, and two streams in the same account, but in two different Regions, can have the same name.

    CreateStream is an asynchronous operation. Upon receiving a CreateStream request, Kinesis Data Streams immediately returns and sets the stream status to CREATING. After the stream is created, Kinesis Data Streams sets the stream status to ACTIVE. You should perform read and write operations only on an ACTIVE stream.

    You receive a LimitExceededException when making a CreateStream request when you try to do one of the following:

    • Have more than five streams in the CREATING state at any point in time.

    • Create more shards than are authorized for your account.

    For the default shard or on-demand throughput limits for an Amazon Web Services account, see Amazon Kinesis Data Streams Limits in the Amazon Kinesis Data Streams Developer Guide. To increase this limit, contact Amazon Web Services Support.

    You can use DescribeStreamSummary to check the stream status, which is returned in StreamStatus.

    CreateStream has a limit of five transactions per second per account.

    You can add tags to the stream when making a CreateStream request by setting the Tags parameter. If you pass the Tags parameter, in addition to having the kinesis:CreateStream permission, you must also have the kinesis:AddTagsToStream permission for the stream that will be created. The kinesis:TagResource permission won’t work to tag streams on creation. Tags will take effect from the CREATING status of the stream, but you can't make any updates to the tags until the stream is in ACTIVE state.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } }, "DecreaseStreamRetentionPeriod":{ "name":"DecreaseStreamRetentionPeriod", @@ -69,6 +99,25 @@ "OperationType":{"value":"control"} } }, + "DeleteChannel":{ + "name":"DeleteChannel", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteChannelInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes the specified channel. Deleting a channel stops delivery from the source stream to the destination. Data already delivered to the destination is not deleted.

    A stream cannot be deleted while it has active channels. Use ListChannels with a stream filter to find the channels attached to a stream before deleting it.

    This operation has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. Exceeding 5 TPS results in a LimitExceededException.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, "DeleteResourcePolicy":{ "name":"DeleteResourcePolicy", "http":{ @@ -135,7 +184,31 @@ "errors":[ {"shape":"LimitExceededException"} ], - "documentation":"

    Describes the account-level settings for Amazon Kinesis Data Streams. This operation returns information about the minimum throughput billing commitments and other account-level configurations.

    This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    " + "documentation":"

    Describes the account-level settings for Amazon Kinesis Data Streams. This operation returns information about the minimum throughput billing commitments and other account-level configurations.

    This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, + "DescribeChannel":{ + "name":"DescribeChannel", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeChannelInput"}, + "output":{"shape":"DescribeChannelOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes the specified channel, including its configuration and current status.

    Use this operation to verify that a channel reached the ACTIVE state after creation, or to diagnose a channel in the FAILED state by reading the ChannelStatusReason.

    This operation has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. Exceeding 5 TPS results in a LimitExceededException.

    ", + "readonly":true, + "staticContextParams":{ + "OperationType":{"value":"control"} + } }, "DescribeLimits":{ "name":"DescribeLimits", @@ -148,7 +221,10 @@ "errors":[ {"shape":"LimitExceededException"} ], - "documentation":"

    Describes the shard limits and usage for the account.

    If you update your account limits, the old limits might be returned for a few minutes.

    This operation has a limit of one transaction per second per account.

    " + "documentation":"

    Describes the shard limits and usage for the account.

    If you update your account limits, the old limits might be returned for a few minutes.

    This operation has a limit of one transaction per second per account.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } }, "DescribeStream":{ "name":"DescribeStream", @@ -266,9 +342,10 @@ {"shape":"KMSOptInRequired"}, {"shape":"KMSThrottlingException"}, {"shape":"AccessDeniedException"}, - {"shape":"InternalFailureException"} + {"shape":"InternalFailureException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Gets data records from a Kinesis data stream's shard.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    Specify a shard iterator using the ShardIterator parameter. The shard iterator specifies the position in the shard from which you want to start reading data records sequentially. If there are no records available in the portion of the shard that the iterator points to, GetRecords returns an empty list. It might take multiple calls to get to a portion of the shard that contains records.

    You can scale by provisioning multiple shards per stream while considering service limits (for more information, see Amazon Kinesis Data Streams Limits in the Amazon Kinesis Data Streams Developer Guide). Your application should have one thread per shard, each reading continuously from its stream. To read from a stream continually, call GetRecords in a loop. Use GetShardIterator to get the shard iterator to specify in the first GetRecords call. GetRecords returns a new shard iterator in NextShardIterator. Specify the shard iterator returned in NextShardIterator in subsequent calls to GetRecords. If the shard has been closed, the shard iterator can't return more data and GetRecords returns null in NextShardIterator. You can terminate the loop when the shard is closed, or when the shard iterator reaches the record with the sequence number or other attribute that marks it as the last record to process.

    Each data record can be up to 1 MiB in size, and each shard can read up to 2 MiB per second. You can ensure that your calls don't exceed the maximum supported size or throughput by using the Limit parameter to specify the maximum number of records that GetRecords can return. Consider your average record size when determining this limit. The maximum number of records that can be returned per call is 10,000.

    The size of the data returned by GetRecords varies depending on the utilization of the shard. It is recommended that consumer applications retrieve records via the GetRecords command using the 5 TPS limit to remain caught up. Retrieving records less frequently can lead to consumer applications falling behind. The maximum size of data that GetRecords can return is 10 MiB. If a call returns this amount of data, subsequent calls made within the next 5 seconds throw ProvisionedThroughputExceededException. If there is insufficient provisioned throughput on the stream, subsequent calls made within the next 1 second throw ProvisionedThroughputExceededException. GetRecords doesn't return any data when it throws an exception. For this reason, we recommend that you wait 1 second between calls to GetRecords. However, it's possible that the application will get exceptions for longer than 1 second.

    To detect whether the application is falling behind in processing, you can use the MillisBehindLatest response attribute. You can also monitor the stream using CloudWatch metrics and other mechanisms (see Monitoring in the Amazon Kinesis Data Streams Developer Guide).

    Each Amazon Kinesis record includes a value, ApproximateArrivalTimestamp, that is set when a stream successfully receives and stores a record. This is commonly referred to as a server-side time stamp, whereas a client-side time stamp is set when a data producer creates or sends the record to a stream (a data producer is any data source putting data records into a stream, for example with PutRecords). The time stamp has millisecond precision. There are no guarantees about the time stamp accuracy, or that the time stamp is always increasing. For example, records in a shard or across a stream might have time stamps that are out of order.

    This operation has a limit of five transactions per second per shard.

    ", + "documentation":"

    Gets data records from a Kinesis data stream's shard.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    Specify a shard iterator using the ShardIterator parameter. The shard iterator specifies the position in the shard from which you want to start reading data records sequentially. If there are no records available in the portion of the shard that the iterator points to, GetRecords returns an empty list. It might take multiple calls to get to a portion of the shard that contains records.

    You can scale by provisioning multiple shards per stream while considering service limits (for more information, see Amazon Kinesis Data Streams Limits in the Amazon Kinesis Data Streams Developer Guide). Your application should have one thread per shard, each reading continuously from its stream. To read from a stream continually, call GetRecords in a loop. Use GetShardIterator to get the shard iterator to specify in the first GetRecords call. GetRecords returns a new shard iterator in NextShardIterator. Specify the shard iterator returned in NextShardIterator in subsequent calls to GetRecords. If the shard has been closed, the shard iterator can't return more data and GetRecords returns null in NextShardIterator. You can terminate the loop when the shard is closed, or when the shard iterator reaches the record with the sequence number or other attribute that marks it as the last record to process.

    Each data record can be up to 1 MiB in size by default. Amazon Kinesis Data Streams supports large records up to 10 MiB in size, but the average throughput for your stream cannot exceed 1 MiB per second. For more information about how large records are handled, see Large records. Each shard can read up to 2 MiB per second. You can ensure that your calls don't exceed the maximum supported size or throughput by using the Limit parameter to specify the maximum number of records that GetRecords can return. Consider your average record size when determining this limit. The maximum number of records that can be returned per call is 10,000.

    The size of the data returned by GetRecords varies depending on the utilization of the shard. It is recommended that consumer applications retrieve records via the GetRecords command using the 5 TPS limit to remain caught up. Retrieving records less frequently can lead to consumer applications falling behind. The maximum size of data that GetRecords can return is 10 MiB. If a call returns this amount of data, subsequent calls made within the next 5 seconds throw ProvisionedThroughputExceededException. If there is insufficient provisioned throughput on the stream, subsequent calls made within the next 1 second throw ProvisionedThroughputExceededException. GetRecords doesn't return any data when it throws an exception. For this reason, we recommend that you wait 1 second between calls to GetRecords. However, it's possible that the application will get exceptions for longer than 1 second.

    To detect whether the application is falling behind in processing, you can use the MillisBehindLatest response attribute. You can also monitor the stream using CloudWatch metrics and other mechanisms (see Monitoring in the Amazon Kinesis Data Streams Developer Guide).

    Each Amazon Kinesis record includes a value, ApproximateArrivalTimestamp, that is set when a stream successfully receives and stores a record. This is commonly referred to as a server-side time stamp, whereas a client-side time stamp is set when a data producer creates or sends the record to a stream (a data producer is any data source putting data records into a stream, for example with PutRecords). The time stamp has millisecond precision. There are no guarantees about the time stamp accuracy, or that the time stamp is always increasing. For example, records in a shard or across a stream might have time stamps that are out of order.

    This operation has a limit of five transactions per second per shard.

    ", "staticContextParams":{ "OperationType":{"value":"data"} } @@ -306,7 +383,8 @@ {"shape":"InvalidArgumentException"}, {"shape":"ProvisionedThroughputExceededException"}, {"shape":"AccessDeniedException"}, - {"shape":"InternalFailureException"} + {"shape":"InternalFailureException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Gets an Amazon Kinesis shard iterator. A shard iterator expires 5 minutes after it is returned to the requester.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    A shard iterator specifies the shard position from which to start reading data records sequentially. The position is specified using the sequence number of a data record in a shard. A sequence number is the identifier associated with every record ingested in the stream, and is assigned when a record is put into the stream. Each stream has one or more shards.

    You must specify the shard iterator type. For example, you can set the ShardIteratorType parameter to read exactly from the position denoted by a specific sequence number by using the AT_SEQUENCE_NUMBER shard iterator type. Alternatively, the parameter can read right after the sequence number by using the AFTER_SEQUENCE_NUMBER shard iterator type, using sequence numbers returned by earlier calls to PutRecord, PutRecords, GetRecords, or DescribeStream. In the request, you can specify the shard iterator type AT_TIMESTAMP to read records from an arbitrary point in time, TRIM_HORIZON to cause ShardIterator to point to the last untrimmed record in the shard in the system (the oldest data record in the shard), or LATEST so that you always read the most recent data in the shard.

    When you read repeatedly from a stream, use a GetShardIterator request to get the first shard iterator for use in your first GetRecords request and for subsequent reads use the shard iterator returned by the GetRecords request in NextShardIterator. A new shard iterator is returned by every GetRecords request in NextShardIterator, which you use in the ShardIterator parameter of the next GetRecords request.

    If a GetShardIterator request is made too often, you receive a ProvisionedThroughputExceededException. For more information about throughput limits, see GetRecords, and Streams Limits in the Amazon Kinesis Data Streams Developer Guide.

    If the shard is closed, GetShardIterator returns a valid iterator for the last sequence number of the shard. A shard can be closed as a result of using SplitShard or MergeShards.

    GetShardIterator has a limit of five transactions per second per account per open shard.

    ", "staticContextParams":{ @@ -332,6 +410,27 @@ "OperationType":{"value":"control"} } }, + "ListChannels":{ + "name":"ListChannels", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListChannelsInput"}, + "output":{"shape":"ListChannelsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ExpiredNextTokenException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the channels in your account. You can filter the results by source stream. The results are paginated. Use the NextToken value returned in the response to retrieve additional results.

    Use this operation to find channels before deleting a stream, or to audit the channels configured in an Amazon Web Services Region.

    This operation has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. Exceeding 5 TPS results in a LimitExceededException.

    ", + "readonly":true, + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, "ListShards":{ "name":"ListShards", "http":{ @@ -386,7 +485,10 @@ {"shape":"ExpiredNextTokenException"}, {"shape":"InvalidArgumentException"} ], - "documentation":"

    Lists your Kinesis data streams.

    The number of streams may be too large to return from a single call to ListStreams. You can limit the number of returned streams using the Limit parameter. If you do not specify a value for the Limit parameter, Kinesis Data Streams uses the default limit, which is currently 100.

    You can detect if there are more streams available to list by using the HasMoreStreams flag from the returned output. If there are more streams available, you can request more streams by using the name of the last stream returned by the ListStreams request in the ExclusiveStartStreamName parameter in a subsequent request to ListStreams. The group of stream names returned by the subsequent request is then added to the list. You can continue this process until all the stream names have been collected in the list.

    ListStreams has a limit of five transactions per second per account.

    " + "documentation":"

    Lists your Kinesis data streams.

    The number of streams may be too large to return from a single call to ListStreams. You can limit the number of returned streams using the Limit parameter. If you do not specify a value for the Limit parameter, Kinesis Data Streams uses the default limit, which is currently 100.

    You can detect if there are more streams available to list by using the HasMoreStreams flag from the returned output. If there are more streams available, you can request more streams by using the name of the last stream returned by the ListStreams request in the ExclusiveStartStreamName parameter in a subsequent request to ListStreams. The group of stream names returned by the subsequent request is then added to the list. You can continue this process until all the stream names have been collected in the list.

    ListStreams has a limit of five transactions per second per account.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -466,7 +568,8 @@ {"shape":"KMSOptInRequired"}, {"shape":"KMSThrottlingException"}, {"shape":"AccessDeniedException"}, - {"shape":"InternalFailureException"} + {"shape":"InternalFailureException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Writes a single data record into an Amazon Kinesis data stream. Call PutRecord to send data into the stream for real-time ingestion and subsequent processing, one record at a time. Each shard can support writes up to 1,000 records per second, up to a maximum data write total of 10 MiB per second.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    You must specify the name of the stream that captures, stores, and transports the data; a partition key; and the data blob itself.

    The data blob can be any type of data; for example, a segment from a log file, geographic/location data, website clickstream data, and so on.

    The partition key is used by Kinesis Data Streams to distribute data across shards. Kinesis Data Streams segregates the data records that belong to a stream into multiple shards, using the partition key associated with each data record to determine the shard to which a given data record belongs.

    Partition keys are Unicode strings, with a maximum length limit of 256 characters for each key. An MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards using the hash key ranges of the shards. You can override hashing the partition key to determine the shard by explicitly specifying a hash value using the ExplicitHashKey parameter. For more information, see Adding Data to a Stream in the Amazon Kinesis Data Streams Developer Guide.

    PutRecord returns the shard ID of where the data record was placed and the sequence number that was assigned to the data record.

    Sequence numbers increase over time and are specific to a shard within a stream, not across all shards within a stream. To guarantee strictly increasing ordering, write serially to a shard and use the SequenceNumberForOrdering parameter. For more information, see Adding Data to a Stream in the Amazon Kinesis Data Streams Developer Guide.

    After you write a record to a stream, you cannot modify that record or its order within the stream.

    If a PutRecord request cannot be processed because of insufficient provisioned throughput on the shard involved in the request, PutRecord throws ProvisionedThroughputExceededException.

    By default, data records are accessible for 24 hours from the time that they are added to a stream. You can use IncreaseStreamRetentionPeriod or DecreaseStreamRetentionPeriod to modify this retention period.

    ", "staticContextParams":{ @@ -492,7 +595,8 @@ {"shape":"KMSOptInRequired"}, {"shape":"KMSThrottlingException"}, {"shape":"AccessDeniedException"}, - {"shape":"InternalFailureException"} + {"shape":"InternalFailureException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    Writes multiple data records into a Kinesis data stream in a single call (also referred to as a PutRecords request). Use this operation to send data into the stream for data ingestion and processing.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    Each PutRecords request can support up to 500 records. Each record in the request can be as large as 10 MiB, up to a limit of 10 MiB for the entire request, including partition keys. Each shard can support writes up to 1,000 records per second, up to a maximum data write total of 1 MB per second.

    You must specify the name of the stream that captures, stores, and transports the data; and an array of request Records, with each record in the array requiring a partition key and data blob. The record size limit applies to the total size of the partition key and data blob.

    The data blob can be any type of data; for example, a segment from a log file, geographic/location data, website clickstream data, and so on.

    The partition key is used by Kinesis Data Streams as input to a hash function that maps the partition key and associated data to a specific shard. An MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream. For more information, see Adding Data to a Stream in the Amazon Kinesis Data Streams Developer Guide.

    Each record in the Records array may include an optional parameter, ExplicitHashKey, which overrides the partition key to shard mapping. This parameter allows a data producer to determine explicitly the shard where the record is stored. For more information, see Adding Multiple Records with PutRecords in the Amazon Kinesis Data Streams Developer Guide.

    The PutRecords response includes an array of response Records. Each record in the response array directly correlates with a record in the request array using natural ordering, from the top to the bottom of the request and response. The response Records array always includes the same number of records as the request array.

    The response Records array includes both successfully and unsuccessfully processed records. Kinesis Data Streams attempts to process all records in each PutRecords request. A single record failure does not stop the processing of subsequent records. As a result, PutRecords doesn't guarantee the ordering of records. If you need to read records in the same order they are written to the stream, use PutRecord instead of PutRecords, and write to the same shard.

    A successfully processed record includes ShardId and SequenceNumber values. The ShardId parameter identifies the shard in the stream where the record is stored. The SequenceNumber parameter is an identifier assigned to the put record, unique to all records in the stream.

    An unsuccessfully processed record includes ErrorCode and ErrorMessage values. ErrorCode reflects the type of error and can be one of the following values: ProvisionedThroughputExceededException or InternalFailure. ErrorMessage provides more detailed information about the ProvisionedThroughputExceededException exception including the account ID, stream name, and shard ID of the record that was throttled. For more information about partially successful responses, see Adding Multiple Records with PutRecords in the Amazon Kinesis Data Streams Developer Guide.

    After you write a record to a stream, you cannot modify that record or its order within the stream.

    By default, data records are accessible for 24 hours from the time that they are added to a stream. You can use IncreaseStreamRetentionPeriod or DecreaseStreamRetentionPeriod to modify this retention period.

    ", "staticContextParams":{ @@ -633,7 +737,8 @@ {"shape":"InvalidArgumentException"}, {"shape":"ResourceInUseException"}, {"shape":"LimitExceededException"}, - {"shape":"AccessDeniedException"} + {"shape":"AccessDeniedException"}, + {"shape":"DryRunOperationException"} ], "documentation":"

    This operation establishes an HTTP/2 connection between the consumer you specify in the ConsumerARN parameter and the shard you specify in the ShardId parameter. After the connection is successfully established, Kinesis Data Streams pushes records from the shard to the consumer over this connection. Before you call this operation, call RegisterStreamConsumer to register the consumer with Kinesis Data Streams.

    When the SubscribeToShard call succeeds, your consumer starts receiving events of type SubscribeToShardEvent over the HTTP/2 connection for up to 5 minutes, after which time you need to call SubscribeToShard again to renew the subscription if you want to continue to receive records.

    You can make one call to SubscribeToShard per second per registered consumer per shard. For example, if you have a 4000 shard stream and two registered stream consumers, you can make one SubscribeToShard request per second for each combination of shard and registered consumer, allowing you to subscribe both consumers to all 4000 shards in one second.

    If you call SubscribeToShard again with the same ConsumerARN and ShardId within 5 seconds of a successful call, you'll get a ResourceInUseException. If you call SubscribeToShard 5 seconds or more after a successful call, the second call takes over the subscription and the previous connection expires or fails with a ResourceInUseException.

    For an example of how to use this operation, see Enhanced Fan-Out Using the Kinesis Data Streams API.

    ", "staticContextParams":{ @@ -691,7 +796,31 @@ {"shape":"ValidationException"}, {"shape":"LimitExceededException"} ], - "documentation":"

    Updates the account-level settings for Amazon Kinesis Data Streams.

    Updating account settings is a synchronous operation. Upon receiving the request, Kinesis Data Streams will return immediately with your account’s updated settings.

    API limits

    • Certain account configurations have minimum commitment windows. Attempting to update your settings prior to the end of the minimum commitment window might have certain restrictions.

    • This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    " + "documentation":"

    Updates the account-level settings for Amazon Kinesis Data Streams.

    Updating account settings is a synchronous operation. Upon receiving the request, Kinesis Data Streams will return immediately with your account’s updated settings.

    API limits

    • Certain account configurations have minimum commitment windows. Attempting to update your settings prior to the end of the minimum commitment window might have certain restrictions.

    • This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, + "UpdateChannel":{ + "name":"UpdateChannel", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateChannelInput"}, + "output":{"shape":"UpdateChannelOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceInUseException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Updates the data freshness interval or the Amazon CloudWatch Logs configuration of an existing channel. You cannot change the destination, source stream, record format, schema, encryption configuration, or service execution role of an existing channel. To change any other setting, delete the channel and create a new one.

    Updating a channel is an asynchronous operation. Upon receiving the request, Amazon Kinesis Data Streams sets the channel to the UPDATING state and returns immediately. After the change is applied, Amazon Kinesis Data Streams sets the channel back to the ACTIVE state.

    This operation has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. Exceeding 5 TPS results in a LimitExceededException.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } }, "UpdateMaxRecordSize":{ "name":"UpdateMaxRecordSize", @@ -753,6 +882,26 @@ "OperationType":{"value":"control"} } }, + "UpdateStreamRecordDistributionStrategy":{ + "name":"UpdateStreamRecordDistributionStrategy", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateStreamRecordDistributionStrategyInput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidArgumentException"}, + {"shape":"ResourceInUseException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"} + ], + "documentation":"

    Updates the record distribution strategy for the specified Amazon Kinesis Data Streams on-demand data stream. The record distribution strategy determines how Amazon Kinesis Data Streams distributes records across the shards in a stream.

    You must specify the stream using the StreamARN parameter.

    The record distribution strategy is a stream-level setting. You can switch between the following strategies at any time, and the change takes effect immediately without downtime, data loss, or disruption to producer or consumer applications:

    • AUTO – Amazon Kinesis Data Streams distributes records evenly across shards using service-managed algorithms, and ignores any partition key and ExplicitHashKey that a producer provides. Use this strategy for stateless workloads that do not require partition-key ordering.

    • USER_PARTITION_KEY – Producers must provide a partition key, and Amazon Kinesis Data Streams uses the partition key to determine shard placement. Records that share a partition key are sent to the same shard. This is the default strategy.

    This operation is only supported for data streams that use the on-demand capacity mode. Provisioned capacity mode streams do not support the record distribution strategy setting. Attempting to set AUTO on a provisioned stream results in an InvalidArgumentException.

    New records that arrive after the change are distributed according to the new strategy. Records already in the stream keep their original shard assignments and are not redistributed.

    ", + "staticContextParams":{ + "OperationType":{"value":"control"} + } + }, "UpdateStreamWarmThroughput":{ "name":"UpdateStreamWarmThroughput", "http":{ @@ -769,7 +918,7 @@ {"shape":"ResourceInUseException"}, {"shape":"ValidationException"} ], - "documentation":"

    Updates the warm throughput configuration for the specified Amazon Kinesis Data Streams on-demand data stream. This operation allows you to proactively scale your on-demand data stream to a specified throughput level, enabling better performance for sudden traffic spikes.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    Updating the warm throughput is an asynchronous operation. Upon receiving the request, Kinesis Data Streams returns immediately and sets the status of the stream to UPDATING. After the update is complete, Kinesis Data Streams sets the status of the stream back to ACTIVE. Depending on the size of the stream, the scaling action could take a few minutes to complete. You can continue to read and write data to your stream while its status is UPDATING.

    This operation is only supported for data streams with the on-demand capacity mode in accounts that have MinimumThroughputBillingCommitment enabled. Provisioned capacity mode streams do not support warm throughput configuration.

    This operation has the following default limits. By default, you cannot do the following:

    • Scale to more than 10 GiBps for an on-demand stream.

    • This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    For the default limits for an Amazon Web Services account, see Streams Limits in the Amazon Kinesis Data Streams Developer Guide. To request an increase in the call rate limit, the shard limit for this API, or your overall shard limit, use the limits form.

    ", + "documentation":"

    Updates the warm throughput configuration for the specified Amazon Kinesis Data Streams on-demand data stream. Updates the warm throughput configuration for the specified on-demand data stream. Use this operation to scale your stream to a specified throughput level before anticipated traffic spikes, or to release excess capacity after traffic has decreased.

    When invoking this API, you must use either the StreamARN or the StreamName parameter, or both. It is recommended that you use the StreamARN input parameter when you invoke this API.

    Updating the warm throughput is an asynchronous operation. Upon receiving the request, Kinesis Data Streams returns immediately and sets the status of the stream to UPDATING. After the update is complete, Kinesis Data Streams sets the status of the stream back to ACTIVE. Depending on the size of the stream, the scaling action could take a few minutes to complete. You can continue to read and write data to your stream while its status is UPDATING.

    This operation is only supported for data streams with the on-demand capacity mode in accounts that have MinimumThroughputBillingCommitment enabled. Provisioned capacity mode streams do not support warm throughput configuration.

    To release excess capacity, call the API again and set the warm throughput to the same or a lower value.

    This operation has the following default limits. By default, you cannot do the following:

    • Scale to more than 10 GiBps for an on-demand stream.

    • This API has a call limit of 5 transactions per second (TPS) for each Amazon Web Services account. TPS over 5 will initiate the LimitExceededException.

    For the default limits for an Amazon Web Services account, see Streams Limits in the Amazon Kinesis Data Streams Developer Guide. To request an increase in the call rate limit, the shard limit for this API, or your overall shard limit, use the limits form.

    ", "staticContextParams":{ "OperationType":{"value":"control"} } @@ -810,6 +959,292 @@ "documentation":"

    Represents the input for AddTagsToStream.

    " }, "BooleanObject":{"type":"boolean"}, + "BucketARN":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws[-a-z0-9]*:s3:::[a-z0-9._-]{3,63}" + }, + "ChannelARN":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws.*:kinesis:.*:\\d{12}:channel/\\S+" + }, + "ChannelCountObject":{ + "type":"integer", + "max":1000000, + "min":0 + }, + "ChannelDescription":{ + "type":"structure", + "required":[ + "ChannelName", + "ChannelARN", + "ChannelId", + "ChannelStatus", + "ChannelCreationTimestamp", + "ServiceExecutionRoleARN", + "StreamConfigurationList", + "LoggingConfiguration" + ], + "members":{ + "ChannelName":{ + "shape":"ChannelName", + "documentation":"

    The name of the channel.

    " + }, + "ChannelARN":{ + "shape":"ChannelARN", + "documentation":"

    The Amazon Resource Name (ARN) of the channel.

    " + }, + "ChannelId":{ + "shape":"ChannelId", + "documentation":"

    The unique identifier of the channel.

    " + }, + "ChannelStatus":{ + "shape":"ChannelStatus", + "documentation":"

    The current status of the channel. Valid values:

    • CREATING - The channel is being created.

    • ACTIVE - The channel is ready to deliver records.

    • UPDATING - The channel configuration is being updated.

    • DELETING - The channel is being deleted.

    • FAILED - See ChannelStatusReason for the failure cause.

    " + }, + "ChannelStatusReason":{ + "shape":"ChannelStatusReason", + "documentation":"

    A message describing the reason for a FAILED status.

    " + }, + "ChannelCreationTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The time at which the channel was created.

    " + }, + "ServiceExecutionRoleARN":{ + "shape":"RoleARN", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon Kinesis Data Streams assumes to write records to the destination.

    " + }, + "StreamConfigurationList":{ + "shape":"ChannelStreamDescriptionList", + "documentation":"

    The source stream configuration for the channel.

    " + }, + "S3DestinationConfiguration":{ + "shape":"S3DestinationDescription", + "documentation":"

    The configuration for delivery to a general purpose Amazon S3 bucket. Present only when the channel destination is a general purpose Amazon S3 bucket.

    " + }, + "S3TablesDestinationConfiguration":{ + "shape":"S3TablesDestinationDescription", + "documentation":"

    The configuration for delivery to streaming tables on Apache Iceberg in Amazon S3 Tables. Present only when the channel destination is a streaming table.

    " + }, + "EncryptionConfiguration":{ + "shape":"ChannelEncryptionConfiguration", + "documentation":"

    The Amazon Web Services KMS key configuration that Amazon Kinesis Data Streams uses to encrypt data delivered to the channel's destination.

    " + }, + "LoggingConfiguration":{ + "shape":"ChannelLoggingConfiguration", + "documentation":"

    The Amazon CloudWatch Logs configuration for the channel.

    " + } + }, + "documentation":"

    Describes the configuration and current status of a channel.

    " + }, + "ChannelDestinationType":{ + "type":"string", + "enum":[ + "S3", + "S3_TABLES" + ] + }, + "ChannelEncryptionConfiguration":{ + "type":"structure", + "required":[ + "EncryptionType", + "KeyId" + ], + "members":{ + "EncryptionType":{ + "shape":"ChannelEncryptionType", + "documentation":"

    The encryption type. The only valid value is KMS.

    " + }, + "KeyId":{ + "shape":"KeyId", + "documentation":"

    The identifier of the customer managed Amazon Web Services KMS key. You cannot use the Amazon Kinesis Data Streams service key (aws/kinesis).

    " + } + }, + "documentation":"

    Specifies the Amazon Web Services KMS key that Amazon Kinesis Data Streams uses to encrypt data delivered to the channel's destination.

    " + }, + "ChannelEncryptionType":{ + "type":"string", + "enum":["KMS"] + }, + "ChannelId":{ + "type":"string", + "max":64, + "min":1 + }, + "ChannelLoggingConfiguration":{ + "type":"structure", + "required":["CloudWatchLogs"], + "members":{ + "CloudWatchLogs":{ + "shape":"CloudWatchLogs", + "documentation":"

    The Amazon CloudWatch Logs settings for the channel.

    " + } + }, + "documentation":"

    The Amazon CloudWatch Logs configuration for a channel.

    " + }, + "ChannelLoggingUpdateInput":{ + "type":"structure", + "required":["CloudWatchLogs"], + "members":{ + "CloudWatchLogs":{ + "shape":"CloudWatchLogsUpdateInput", + "documentation":"

    The updated Amazon CloudWatch Logs settings, including whether logging is enabled and the target log group and log stream.

    " + } + }, + "documentation":"

    The updated Amazon CloudWatch Logs configuration for a channel. Used in UpdateChannel.

    " + }, + "ChannelName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9_.-]+" + }, + "ChannelStatus":{ + "type":"string", + "enum":[ + "CREATING", + "ACTIVE", + "UPDATING", + "DELETING", + "FAILED" + ] + }, + "ChannelStatusReason":{ + "type":"string", + "max":2048, + "min":1 + }, + "ChannelStreamConfiguration":{ + "type":"structure", + "required":[ + "StreamARN", + "RecordConfiguration" + ], + "members":{ + "StreamARN":{ + "shape":"StreamARN", + "documentation":"

    The Amazon Resource Name (ARN) of the source Kinesis data stream.

    " + }, + "RecordConfiguration":{ + "shape":"RecordConfiguration", + "documentation":"

    The record format configuration for the source stream.

    " + } + }, + "documentation":"

    Specifies the source stream and record configuration when creating a channel.

    " + }, + "ChannelStreamConfigurationList":{ + "type":"list", + "member":{"shape":"ChannelStreamConfiguration"}, + "max":10000, + "min":1 + }, + "ChannelStreamDescription":{ + "type":"structure", + "required":[ + "StreamARN", + "StreamCreationTimestamp", + "RecordConfiguration" + ], + "members":{ + "StreamARN":{ + "shape":"StreamARN", + "documentation":"

    The Amazon Resource Name (ARN) of the source Kinesis data stream.

    " + }, + "StreamCreationTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The time at which the source stream was created.

    " + }, + "RecordConfiguration":{ + "shape":"RecordConfiguration", + "documentation":"

    The record format configuration for the source stream.

    " + } + }, + "documentation":"

    Describes the source stream of a channel.

    " + }, + "ChannelStreamDescriptionList":{ + "type":"list", + "member":{"shape":"ChannelStreamDescription"}, + "max":10000, + "min":1 + }, + "ChannelStreamIdentifier":{ + "type":"structure", + "required":[ + "StreamARN", + "StreamCreationTimestamp" + ], + "members":{ + "StreamARN":{ + "shape":"StreamARN", + "documentation":"

    The Amazon Resource Name (ARN) of the source Kinesis data stream.

    " + }, + "StreamCreationTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The time at which the source stream was created.

    " + } + }, + "documentation":"

    Identifies a source stream associated with a channel.

    " + }, + "ChannelStreamIdentifierList":{ + "type":"list", + "member":{"shape":"ChannelStreamIdentifier"}, + "max":10000, + "min":1 + }, + "ChannelSummary":{ + "type":"structure", + "required":[ + "ChannelName", + "ChannelARN", + "ChannelId", + "ChannelStatus", + "ChannelCreationTimestamp", + "ChannelDestinationType", + "Streams" + ], + "members":{ + "ChannelName":{ + "shape":"ChannelName", + "documentation":"

    The name of the channel.

    " + }, + "ChannelARN":{ + "shape":"ChannelARN", + "documentation":"

    The Amazon Resource Name (ARN) of the channel.

    " + }, + "ChannelId":{ + "shape":"ChannelId", + "documentation":"

    The unique identifier of the channel.

    " + }, + "ChannelStatus":{ + "shape":"ChannelStatus", + "documentation":"

    The current status of the channel. Valid values:

    • CREATING - The channel is being created.

    • ACTIVE - The channel is ready to deliver records.

    • UPDATING - The channel configuration is being updated.

    • DELETING - The channel is being deleted.

    • FAILED - See ChannelStatusReason for the failure cause.

    " + }, + "ChannelStatusReason":{ + "shape":"ChannelStatusReason", + "documentation":"

    A message describing the reason for a FAILED status.

    " + }, + "ChannelCreationTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The time at which the channel was created.

    " + }, + "ChannelDestinationType":{ + "shape":"ChannelDestinationType", + "documentation":"

    The destination type of the channel. Valid values:

    • S3 - Delivery to a general purpose Amazon S3 bucket.

    • S3_TABLES - Delivery to streaming tables on Apache Iceberg.

    " + }, + "Streams":{ + "shape":"ChannelStreamIdentifierList", + "documentation":"

    The source streams associated with the channel.

    " + } + }, + "documentation":"

    A summary of a channel, returned by ListChannels.

    " + }, + "ChannelSummaryList":{ + "type":"list", + "member":{"shape":"ChannelSummary"} + }, "ChildShard":{ "type":"structure", "required":[ @@ -834,6 +1269,56 @@ "type":"list", "member":{"shape":"ChildShard"} }, + "CloudWatchLogGroupName":{ + "type":"string", + "max":512, + "min":1, + "pattern":"[\\.\\-_/#A-Za-z0-9]+" + }, + "CloudWatchLogStreamName":{ + "type":"string", + "max":512, + "min":1, + "pattern":"[^:*]*" + }, + "CloudWatchLogs":{ + "type":"structure", + "required":["Enabled"], + "members":{ + "Enabled":{ + "shape":"BooleanObject", + "documentation":"

    Specifies whether logging to Amazon CloudWatch Logs is enabled.

    " + }, + "LogGroupName":{ + "shape":"CloudWatchLogGroupName", + "documentation":"

    The name of the Amazon CloudWatch Logs log group. Defaults to /aws/kinesis/{channelName}/{channelId}.

    " + }, + "LogStreamName":{ + "shape":"CloudWatchLogStreamName", + "documentation":"

    The name of the Amazon CloudWatch Logs log stream. Defaults to DestinationDelivery.

    " + } + }, + "documentation":"

    The Amazon CloudWatch Logs settings for channel logging.

    " + }, + "CloudWatchLogsUpdateInput":{ + "type":"structure", + "required":["Enabled"], + "members":{ + "Enabled":{ + "shape":"BooleanObject", + "documentation":"

    Specifies whether logging to Amazon CloudWatch Logs is enabled.

    " + }, + "LogGroupName":{ + "shape":"CloudWatchLogGroupName", + "documentation":"

    The name of the Amazon CloudWatch Logs log group.

    " + }, + "LogStreamName":{ + "shape":"CloudWatchLogStreamName", + "documentation":"

    The name of the Amazon CloudWatch Logs log stream.

    " + } + }, + "documentation":"

    The updated Amazon CloudWatch Logs settings for a channel.

    " + }, "Consumer":{ "type":"structure", "required":[ @@ -924,6 +1409,58 @@ "ACTIVE" ] }, + "CreateChannelInput":{ + "type":"structure", + "required":[ + "ChannelName", + "ServiceExecutionRoleARN", + "StreamConfigurationList" + ], + "members":{ + "ChannelName":{ + "shape":"ChannelName", + "documentation":"

    The name of the channel. The name is unique within your Amazon Web Services account and Amazon Web Services Region.

    " + }, + "ServiceExecutionRoleARN":{ + "shape":"RoleARN", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon Kinesis Data Streams assumes to write records to the destination.

    " + }, + "StreamConfigurationList":{ + "shape":"ChannelStreamConfigurationList", + "documentation":"

    The source stream configuration for the channel. Currently, one stream is supported per channel.

    " + }, + "S3DestinationConfiguration":{ + "shape":"S3DestinationConfiguration", + "documentation":"

    The configuration for delivery to a general purpose Amazon S3 bucket. Specify this parameter when S3TablesDestinationConfiguration is not specified.

    " + }, + "S3TablesDestinationConfiguration":{ + "shape":"S3TablesDestinationConfiguration", + "documentation":"

    The configuration for delivery to streaming tables on Apache Iceberg in Amazon S3 Tables. Specify this parameter when S3DestinationConfiguration is not specified.

    " + }, + "EncryptionConfiguration":{ + "shape":"ChannelEncryptionConfiguration", + "documentation":"

    The server-side encryption configuration that uses an Amazon Web Services KMS key to encrypt data delivered to the destination.

    " + }, + "Tags":{ + "shape":"TagMap", + "documentation":"

    A set of key-value pairs to assign to the channel. A tag consists of a required key and an optional value.

    " + }, + "LoggingConfiguration":{ + "shape":"ChannelLoggingConfiguration", + "documentation":"

    The Amazon CloudWatch Logs configuration for the channel.

    " + } + } + }, + "CreateChannelOutput":{ + "type":"structure", + "required":["ChannelDescription"], + "members":{ + "ChannelDescription":{ + "shape":"ChannelDescription", + "documentation":"

    The configuration and current status of the channel, including its ARN, destination configuration, and lifecycle state. Immediately after creation, the state is CREATING.

    " + } + } + }, "CreateStreamInput":{ "type":"structure", "required":["StreamName"], @@ -951,14 +1488,41 @@ "MaxRecordSizeInKiB":{ "shape":"MaxRecordSizeInKiB", "documentation":"

    The maximum record size of a single record in kibibyte (KiB) that you can write to, and read from a stream.

    " + }, + "RecordDistributionStrategy":{ + "shape":"RecordDistributionStrategy", + "documentation":"

    The record distribution strategy for the stream, which determines how Amazon Kinesis Data Streams distributes records across shards. Specify one of the following values:

    • AUTO – Amazon Kinesis Data Streams distributes records evenly across shards and ignores any partition key and ExplicitHashKey that producers supply. Use this value for stateless workloads that do not require partition-key ordering.

    • USER_PARTITION_KEY – Producers must supply a partition key, which Amazon Kinesis Data Streams uses to determine shard placement. This is the default.

    The record distribution strategy is only supported for streams that use the on-demand capacity mode. If you do not specify this parameter, the stream uses USER_PARTITION_KEY.

    " + } + }, + "documentation":"

    Represents the input for CreateStream.

    " + }, + "Data":{ + "type":"blob", + "max":10485760, + "min":0 + }, + "DataFreshnessInSeconds":{"type":"integer"}, + "DeadLetterQueueS3Configuration":{ + "type":"structure", + "required":[ + "BucketARN", + "ExpectedBucketOwner" + ], + "members":{ + "BucketARN":{ + "shape":"BucketARN", + "documentation":"

    The Amazon Resource Name (ARN) of the dead-letter queue Amazon S3 bucket.

    " + }, + "ExpectedBucketOwner":{ + "shape":"ExpectedBucketOwner", + "documentation":"

    The Amazon Web Services account ID of the expected owner of the dead-letter queue bucket.

    " + }, + "ErrorOutputPrefix":{ + "shape":"S3ErrorOutputPrefix", + "documentation":"

    The Amazon S3 key prefix for error records.

    " } }, - "documentation":"

    Represents the input for CreateStream.

    " - }, - "Data":{ - "type":"blob", - "max":10485760, - "min":0 + "documentation":"

    The Amazon S3 dead-letter queue configuration for records that cannot be delivered.

    " }, "DecreaseStreamRetentionPeriodInput":{ "type":"structure", @@ -985,6 +1549,17 @@ }, "documentation":"

    Represents the input for DecreaseStreamRetentionPeriod.

    " }, + "DeleteChannelInput":{ + "type":"structure", + "required":["ChannelARN"], + "members":{ + "ChannelARN":{ + "shape":"ChannelARN", + "documentation":"

    The Amazon Resource Name (ARN) of the channel to delete.

    ", + "contextParam":{"name":"ChannelARN"} + } + } + }, "DeleteResourcePolicyInput":{ "type":"structure", "required":["ResourceARN"], @@ -1062,6 +1637,27 @@ } } }, + "DescribeChannelInput":{ + "type":"structure", + "required":["ChannelARN"], + "members":{ + "ChannelARN":{ + "shape":"ChannelARN", + "documentation":"

    The Amazon Resource Name (ARN) of the channel to describe.

    ", + "contextParam":{"name":"ChannelARN"} + } + } + }, + "DescribeChannelOutput":{ + "type":"structure", + "required":["ChannelDescription"], + "members":{ + "ChannelDescription":{ + "shape":"ChannelDescription", + "documentation":"

    The configuration and current status of the channel, including its ARN, source stream, destination configuration, and lifecycle state.

    " + } + } + }, "DescribeLimitsInput":{ "type":"structure", "members":{} @@ -1090,6 +1686,14 @@ "OnDemandStreamCountLimit":{ "shape":"OnDemandStreamCountLimitObject", "documentation":"

    The maximum number of data streams with the on-demand capacity mode.

    " + }, + "ChannelCount":{ + "shape":"ChannelCountObject", + "documentation":"

    The number of channels in the account.

    " + }, + "ChannelCountLimit":{ + "shape":"ChannelCountObject", + "documentation":"

    The maximum number of channels allowed in the account.

    " } } }, @@ -1225,6 +1829,14 @@ }, "documentation":"

    Represents the input for DisableEnhancedMonitoring.

    " }, + "DryRunOperationException":{ + "type":"structure", + "members":{ + "message":{"shape":"ErrorMessage"} + }, + "documentation":"

    The request was rejected because the DryRun parameter was specified.

    ", + "exception":true + }, "EnableEnhancedMonitoringInput":{ "type":"structure", "required":["ShardLevelMetrics"], @@ -1295,6 +1907,12 @@ }, "ErrorCode":{"type":"string"}, "ErrorMessage":{"type":"string"}, + "ExpectedBucketOwner":{ + "type":"string", + "max":12, + "min":12, + "pattern":"\\d{12}" + }, "ExpiredIteratorException":{ "type":"structure", "members":{ @@ -1314,6 +1932,12 @@ "documentation":"

    The pagination token passed to the operation is expired.

    ", "exception":true }, + "GSRSchemaARN":{ + "type":"string", + "max":512, + "min":1, + "pattern":"arn:aws[-a-z0-9]*:glue:[-a-z0-9]+:\\d{12}:schema/[-a-zA-Z0-9_$#.]+/[-a-zA-Z0-9_$#.]+" + }, "GetRecordsInput":{ "type":"structure", "required":["ShardIterator"], @@ -1335,6 +1959,10 @@ "shape":"StreamId", "documentation":"

    Not Implemented. Reserved for future use.

    ", "contextParam":{"name":"StreamId"} + }, + "DryRun":{ + "shape":"BooleanObject", + "documentation":"

    Checks if your request will succeed. DryRun is an optional parameter.

    " } }, "documentation":"

    Represents the input for GetRecords.

    " @@ -1429,6 +2057,10 @@ "shape":"StreamId", "documentation":"

    Not Implemented. Reserved for future use.

    ", "contextParam":{"name":"StreamId"} + }, + "DryRun":{ + "shape":"BooleanObject", + "documentation":"

    Checks if your request will succeed. DryRun is an optional parameter.

    " } }, "documentation":"

    Represents the input for GetShardIterator.

    " @@ -1445,7 +2077,7 @@ }, "HashKey":{ "type":"string", - "pattern":"0|([1-9]\\d{0,38})" + "pattern":"^(0|([1-9]\\d{0,38}))$" }, "HashKeyRange":{ "type":"structure", @@ -1592,6 +2224,42 @@ "documentation":"

    The requested resource exceeds the maximum number allowed, or the number of concurrent stream requests exceeds the maximum number allowed.

    ", "exception":true }, + "ListChannelsInput":{ + "type":"structure", + "members":{ + "StreamFilter":{ + "shape":"StreamFilterList", + "documentation":"

    Filters the results to channels associated with the specified streams.

    " + }, + "MaxResults":{ + "shape":"ListChannelsInputLimit", + "documentation":"

    The maximum number of channels to return in a single call. The default value is 100. If you specify a value greater than 100, at most 100 results are returned.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token returned by a previous call. Specify this token to retrieve the next page of results.

    " + } + } + }, + "ListChannelsInputLimit":{ + "type":"integer", + "max":10000, + "min":1 + }, + "ListChannelsOutput":{ + "type":"structure", + "required":["ChannelSummaries"], + "members":{ + "ChannelSummaries":{ + "shape":"ChannelSummaryList", + "documentation":"

    A list of channel summaries.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token to use in a subsequent call to retrieve the next page of results. This value is null when there are no more results to return.

    " + } + } + }, "ListShardsInput":{ "type":"structure", "members":{ @@ -1948,11 +2616,56 @@ "max":1000000, "min":0 }, + "PartitionField":{ + "type":"structure", + "required":[ + "Transform", + "SourceName" + ], + "members":{ + "Transform":{ + "shape":"PartitionTransform", + "documentation":"

    The partition transform to apply. The only valid value is TIME_HOUR.

    " + }, + "SourceName":{ + "shape":"PartitionSourceName", + "documentation":"

    The name of the source column used for partitioning. This column must be of the timestamptz type.

    " + } + }, + "documentation":"

    Specifies a single partition field.

    " + }, + "PartitionFieldList":{ + "type":"list", + "member":{"shape":"PartitionField"}, + "max":10, + "min":1 + }, "PartitionKey":{ "type":"string", "max":256, "min":1 }, + "PartitionSourceName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[a-zA-Z0-9\\.\\_]+" + }, + "PartitionSpec":{ + "type":"structure", + "required":["PartitionFields"], + "members":{ + "PartitionFields":{ + "shape":"PartitionFieldList", + "documentation":"

    The list of partition fields.

    " + } + }, + "documentation":"

    Specifies how the destination table is partitioned.

    " + }, + "PartitionTransform":{ + "type":"string", + "enum":["TIME_HOUR"] + }, "Policy":{"type":"string"}, "PositiveIntegerObject":{ "type":"integer", @@ -1971,10 +2684,7 @@ }, "PutRecordInput":{ "type":"structure", - "required":[ - "Data", - "PartitionKey" - ], + "required":["Data"], "members":{ "StreamName":{ "shape":"StreamName", @@ -1986,7 +2696,7 @@ }, "PartitionKey":{ "shape":"PartitionKey", - "documentation":"

    Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.

    " + "documentation":"

    Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.

    If the stream uses the USER_PARTITION_KEY record distribution strategy (the default), a partition key is required. If the stream uses the AUTO record distribution strategy, the partition key is optional and any value you provide is ignored, along with any ExplicitHashKey you provide. In that case, Amazon Kinesis Data Streams distributes the record across shards using service-managed algorithms. For more information, see UpdateStreamRecordDistributionStrategy.

    " }, "ExplicitHashKey":{ "shape":"HashKey", @@ -2005,6 +2715,10 @@ "shape":"StreamId", "documentation":"

    Not Implemented. Reserved for future use.

    ", "contextParam":{"name":"StreamId"} + }, + "DryRun":{ + "shape":"BooleanObject", + "documentation":"

    Checks if your request will succeed. DryRun is an optional parameter.

    " } }, "documentation":"

    Represents the input for PutRecord.

    " @@ -2052,6 +2766,10 @@ "shape":"StreamId", "documentation":"

    Not Implemented. Reserved for future use.

    ", "contextParam":{"name":"StreamId"} + }, + "DryRun":{ + "shape":"BooleanObject", + "documentation":"

    Checks if your request will succeed. DryRun is an optional parameter.

    " } }, "documentation":"

    A PutRecords request.

    " @@ -2077,10 +2795,7 @@ }, "PutRecordsRequestEntry":{ "type":"structure", - "required":[ - "Data", - "PartitionKey" - ], + "required":["Data"], "members":{ "Data":{ "shape":"Data", @@ -2092,7 +2807,7 @@ }, "PartitionKey":{ "shape":"PartitionKey", - "documentation":"

    Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.

    " + "documentation":"

    Determines which shard in the stream the data record is assigned to. Partition keys are Unicode strings with a maximum length limit of 256 characters for each key. Amazon Kinesis Data Streams uses the partition key as input to a hash function that maps the partition key and associated data to a specific shard. Specifically, an MD5 hash function is used to map partition keys to 128-bit integer values and to map associated data records to shards. As a result of this hashing mechanism, all data records with the same partition key map to the same shard within the stream.

    If the stream uses the USER_PARTITION_KEY record distribution strategy (the default), a partition key is required for each record. If the stream uses the AUTO record distribution strategy, the partition key is optional and any value you provide is ignored, along with any ExplicitHashKey you provide. In that case, Amazon Kinesis Data Streams distributes records across shards using service-managed algorithms. For more information, see UpdateStreamRecordDistributionStrategy.

    " } }, "documentation":"

    Represents the output for PutRecords.

    " @@ -2158,8 +2873,7 @@ "type":"structure", "required":[ "SequenceNumber", - "Data", - "PartitionKey" + "Data" ], "members":{ "SequenceNumber":{ @@ -2172,11 +2886,11 @@ }, "Data":{ "shape":"Data", - "documentation":"

    The data blob. The data in the blob is both opaque and immutable to Kinesis Data Streams, which does not inspect, interpret, or change the data in the blob in any way. When the data blob (the payload before base64-encoding) is added to the partition key size, the total size must not exceed the maximum record size (1 MiB).

    " + "documentation":"

    The data blob. The data in the blob is both opaque and immutable to Kinesis Data Streams, which does not inspect, interpret, or change the data in the blob in any way. When the data blob (the payload before base64-encoding) is added to the partition key size, the total size must not exceed the maximum record size (10 MiB).

    " }, "PartitionKey":{ "shape":"PartitionKey", - "documentation":"

    Identifies which shard in the stream the data record is assigned to.

    " + "documentation":"

    Identifies which shard in the stream the data record is assigned to.

    For a stream that uses the AUTO record distribution strategy, this value is not returned if the producer did not provide a partition key when writing the record. If the producer provided a partition key, the original value is returned even though it was not used to determine shard placement.

    " }, "EncryptionType":{ "shape":"EncryptionType", @@ -2185,6 +2899,37 @@ }, "documentation":"

    The unit of data of the Kinesis data stream, which is composed of a sequence number, a partition key, and a data blob.

    " }, + "RecordConfiguration":{ + "type":"structure", + "required":["RecordFormatType"], + "members":{ + "RecordFormatType":{ + "shape":"RecordFormatType", + "documentation":"

    The format of records on the source stream. Valid values:

    • GSR_JSON - Supported only for streaming table (Amazon S3 Tables) destinations.

    • JSON - Supported for both general purpose Amazon S3 and streaming table destinations.

    • STRING - Supported only for general purpose Amazon S3 destinations.

    • BYTE_ARRAY - Supported only for general purpose Amazon S3 destinations.

    " + }, + "GSRSchemaARN":{ + "shape":"GSRSchemaARN", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Web Services Glue Schema Registry schema used to validate records. Required when the channel destination is a streaming table.

    " + } + }, + "documentation":"

    Specifies the format of records read from the source stream.

    " + }, + "RecordDistributionStrategy":{ + "type":"string", + "enum":[ + "AUTO", + "USER_PARTITION_KEY" + ] + }, + "RecordFormatType":{ + "type":"string", + "enum":[ + "GSR_JSON", + "JSON", + "STRING", + "BYTE_ARRAY" + ] + }, "RecordList":{ "type":"list", "member":{"shape":"Record"} @@ -2255,7 +3000,7 @@ "type":"string", "max":2048, "min":1, - "pattern":"arn:aws.*:kinesis:.*:\\d{12}:.*stream/\\S+" + "pattern":"arn:aws.*:kinesis:.*:\\d{12}:.*(stream|channel)/\\S+" }, "ResourceInUseException":{ "type":"structure", @@ -2280,13 +3025,245 @@ "exception":true }, "RetentionPeriodHours":{"type":"integer"}, + "RoleARN":{ + "type":"string", + "max":512, + "min":1, + "pattern":"arn:aws[-a-z0-9]*:iam::\\d{12}:role/[a-zA-Z_0-9+=,.@\\-_/]+" + }, + "S3CompressionType":{ + "type":"string", + "enum":[ + "NONE", + "GZIP", + "ZSTD" + ] + }, + "S3DestinationConfiguration":{ + "type":"structure", + "required":["StorageConfiguration"], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data before the channel delivers it to the destination. The default value is 300 seconds.

    " + }, + "DeadLetterQueueS3Configuration":{ + "shape":"DeadLetterQueueS3Configuration", + "documentation":"

    The dead-letter queue configuration for records that cannot be delivered. Optional for general purpose Amazon S3 destinations. If not specified, it defaults to the destination bucket with an error prefix.

    " + }, + "StorageConfiguration":{ + "shape":"S3StorageConfiguration", + "documentation":"

    The Amazon S3 storage configuration for the channel.

    " + } + }, + "documentation":"

    The configuration for delivery to a general purpose Amazon S3 bucket. Used in CreateChannel.

    " + }, + "S3DestinationDescription":{ + "type":"structure", + "required":[ + "DataFreshnessInSeconds", + "DeadLetterQueueS3Configuration", + "StorageConfiguration" + ], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data.

    " + }, + "DeadLetterQueueS3Configuration":{ + "shape":"DeadLetterQueueS3Configuration", + "documentation":"

    The dead-letter queue configuration for records that cannot be delivered.

    " + }, + "StorageConfiguration":{ + "shape":"S3StorageConfiguration", + "documentation":"

    The Amazon S3 storage configuration for the channel.

    " + } + }, + "documentation":"

    The configuration for delivery to a general purpose Amazon S3 bucket. Returned in ChannelDescription.

    " + }, + "S3DestinationUpdateInput":{ + "type":"structure", + "required":["DataFreshnessInSeconds"], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data before the channel delivers it to the destination.

    " + } + }, + "documentation":"

    The updated configuration for a general purpose Amazon S3 destination. Used in UpdateChannel. Only DataFreshnessInSeconds can be updated.

    " + }, + "S3ErrorOutputPrefix":{ + "type":"string", + "max":512, + "min":1, + "pattern":"[0-9A-Za-z!\\-_'.*()\\/]+" + }, + "S3OutputKeyTemplate":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"[0-9A-Za-z!\\-_'.*()\\/=:{}]+" + }, + "S3StorageClass":{ + "type":"string", + "enum":[ + "STANDARD", + "INTELLIGENT_TIERING", + "GLACIER_IR" + ] + }, + "S3StorageConfiguration":{ + "type":"structure", + "required":[ + "BucketARN", + "ExpectedBucketOwner", + "CompressionType" + ], + "members":{ + "BucketARN":{ + "shape":"BucketARN", + "documentation":"

    The Amazon Resource Name (ARN) of the destination Amazon S3 bucket.

    " + }, + "ExpectedBucketOwner":{ + "shape":"ExpectedBucketOwner", + "documentation":"

    The Amazon Web Services account ID of the expected owner of the destination bucket. This value helps prevent delivery to an unintended bucket if ownership changes.

    " + }, + "OutputKeyTemplate":{ + "shape":"S3OutputKeyTemplate", + "documentation":"

    The template used to construct the Amazon S3 object key for delivered objects. If not specified, a default template is used.

    " + }, + "StorageClass":{ + "shape":"S3StorageClass", + "documentation":"

    The Amazon S3 storage class for delivered objects. Valid values:

    • STANDARD - The default storage class, for frequently accessed data.

    • INTELLIGENT_TIERING - Automatically moves objects to the most cost-effective access tier based on usage patterns.

    • GLACIER_IR - Low-cost storage for rarely accessed data that requires millisecond retrieval.

    " + }, + "CompressionType":{ + "shape":"S3CompressionType", + "documentation":"

    The compression applied to delivered objects. Valid values:

    • NONE - No compression.

    • GZIP - gzip compression.

    • ZSTD - Zstandard compression.

    " + } + }, + "documentation":"

    The Amazon S3 storage settings for a general purpose Amazon S3 destination.

    " + }, + "S3TablesCompressionType":{ + "type":"string", + "enum":[ + "NONE", + "ZSTD", + "SNAPPY" + ] + }, + "S3TablesConfiguration":{ + "type":"structure", + "required":[ + "TableBucketARN", + "Namespace", + "TableName", + "CompressionType" + ], + "members":{ + "TableBucketARN":{ + "shape":"TableBucketARN", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon S3 table bucket.

    " + }, + "Namespace":{ + "shape":"S3TablesNamespace", + "documentation":"

    The namespace (database) of the destination table.

    " + }, + "TableName":{ + "shape":"S3TablesTableName", + "documentation":"

    The name of the destination table. Amazon Kinesis Data Streams creates this table in the specified table bucket.

    " + }, + "CompressionType":{ + "shape":"S3TablesCompressionType", + "documentation":"

    The compression applied to Parquet data files. Valid values:

    • NONE - No compression.

    • ZSTD - Zstandard compression.

    • SNAPPY - Snappy compression.

    " + }, + "PartitionSpec":{ + "shape":"PartitionSpec", + "documentation":"

    The partitioning specification for the destination table.

    " + } + }, + "documentation":"

    Specifies a destination streaming table on Apache Iceberg.

    " + }, + "S3TablesConfigurationList":{ + "type":"list", + "member":{"shape":"S3TablesConfiguration"}, + "max":10000, + "min":1 + }, + "S3TablesDestinationConfiguration":{ + "type":"structure", + "required":[ + "DeadLetterQueueS3Configuration", + "S3TablesConfigurationList" + ], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data before the channel delivers it to the destination. The default value is 300 seconds.

    " + }, + "DeadLetterQueueS3Configuration":{ + "shape":"DeadLetterQueueS3Configuration", + "documentation":"

    The dead-letter queue configuration for records that cannot be delivered. Required for streaming table destinations.

    " + }, + "S3TablesConfigurationList":{ + "shape":"S3TablesConfigurationList", + "documentation":"

    The list of streaming table configurations. Currently, one table is supported per channel.

    " + } + }, + "documentation":"

    The configuration for delivery to streaming tables on Apache Iceberg. Used in CreateChannel.

    " + }, + "S3TablesDestinationDescription":{ + "type":"structure", + "required":[ + "DataFreshnessInSeconds", + "DeadLetterQueueS3Configuration", + "S3TablesConfigurationList" + ], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data.

    " + }, + "DeadLetterQueueS3Configuration":{ + "shape":"DeadLetterQueueS3Configuration", + "documentation":"

    The dead-letter queue configuration for records that cannot be delivered.

    " + }, + "S3TablesConfigurationList":{ + "shape":"S3TablesConfigurationList", + "documentation":"

    The list of streaming table configurations.

    " + } + }, + "documentation":"

    The configuration for delivery to streaming tables on Apache Iceberg. Returned in ChannelDescription.

    " + }, + "S3TablesDestinationUpdateInput":{ + "type":"structure", + "required":["DataFreshnessInSeconds"], + "members":{ + "DataFreshnessInSeconds":{ + "shape":"DataFreshnessInSeconds", + "documentation":"

    The maximum age, in seconds, of undelivered data before the channel delivers it to the destination.

    " + } + }, + "documentation":"

    The updated configuration for a streaming table destination. Used in UpdateChannel. Only DataFreshnessInSeconds can be updated.

    " + }, + "S3TablesNamespace":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[0-9a-z_]+" + }, + "S3TablesTableName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[0-9a-z_]+" + }, "ScalingType":{ "type":"string", "enum":["UNIFORM_SCALING"] }, "SequenceNumber":{ "type":"string", - "pattern":"0|([1-9]\\d{0,128})" + "pattern":"^(0|([1-9]\\d{0,128}))$" }, "SequenceNumberRange":{ "type":"structure", @@ -2644,10 +3621,39 @@ "MaxRecordSizeInKiB":{ "shape":"MaxRecordSizeInKiB", "documentation":"

    The maximum record size of a single record in kibibyte (KiB) that you can write to, and read from a stream.

    " + }, + "ChannelCount":{ + "shape":"ChannelCountObject", + "documentation":"

    The number of channels associated with the stream.

    " + }, + "RecordDistributionStrategy":{ + "shape":"RecordDistributionStrategy", + "documentation":"

    The record distribution strategy that the stream currently uses. A value of AUTO indicates that Amazon Kinesis Data Streams distributes records across shards using service-managed algorithms. A value of USER_PARTITION_KEY indicates that shard placement is determined by the partition key that producers supply. This field is only present for streams that use the on-demand capacity mode.

    " } }, "documentation":"

    Represents the output for DescribeStreamSummary

    " }, + "StreamFilter":{ + "type":"structure", + "required":["StreamARN"], + "members":{ + "StreamARN":{ + "shape":"StreamARN", + "documentation":"

    The Amazon Resource Name (ARN) of the source stream to filter by.

    " + }, + "StreamCreationTimestamp":{ + "shape":"Timestamp", + "documentation":"

    The creation timestamp of the source stream.

    " + } + }, + "documentation":"

    Filters ListChannels results by source stream.

    " + }, + "StreamFilterList":{ + "type":"list", + "member":{"shape":"StreamFilter"}, + "max":10000, + "min":1 + }, "StreamId":{ "type":"string", "max":24, @@ -2800,6 +3806,10 @@ "StartingPosition":{ "shape":"StartingPosition", "documentation":"

    The starting position in the data stream from which to start streaming.

    " + }, + "DryRun":{ + "shape":"BooleanObject", + "documentation":"

    Checks if your request will succeed. DryRun is an optional parameter.

    " } } }, @@ -2813,6 +3823,12 @@ } } }, + "TableBucketARN":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws[-a-z0-9]*:s3tables:[-a-z0-9]+:\\d{12}:bucket/[a-z0-9_-]{3,63}" + }, "Tag":{ "type":"structure", "required":["Key"], @@ -2923,6 +3939,39 @@ } } }, + "UpdateChannelInput":{ + "type":"structure", + "required":["ChannelARN"], + "members":{ + "ChannelARN":{ + "shape":"ChannelARN", + "documentation":"

    The Amazon Resource Name (ARN) of the channel to update.

    ", + "contextParam":{"name":"ChannelARN"} + }, + "S3DestinationConfiguration":{ + "shape":"S3DestinationUpdateInput", + "documentation":"

    The updated configuration for a general purpose Amazon S3 destination. Specify this parameter when the channel delivers to a general purpose Amazon S3 bucket. Only DataFreshnessInSeconds can be updated.

    " + }, + "S3TablesDestinationConfiguration":{ + "shape":"S3TablesDestinationUpdateInput", + "documentation":"

    The updated configuration for a streaming table destination. Specify this parameter when the channel delivers to streaming tables on Apache Iceberg in Amazon S3 Tables. Only DataFreshnessInSeconds can be updated.

    " + }, + "LoggingConfiguration":{ + "shape":"ChannelLoggingUpdateInput", + "documentation":"

    The updated Amazon CloudWatch Logs configuration for the channel.

    " + } + } + }, + "UpdateChannelOutput":{ + "type":"structure", + "required":["ChannelDescription"], + "members":{ + "ChannelDescription":{ + "shape":"ChannelDescription", + "documentation":"

    The configuration and current status of the channel after the update, including its ARN, destination configuration, and lifecycle state. Immediately after the request, the state is UPDATING.

    " + } + } + }, "UpdateMaxRecordSizeInput":{ "type":"structure", "required":["MaxRecordSizeInKiB"], @@ -3022,6 +4071,29 @@ } } }, + "UpdateStreamRecordDistributionStrategyInput":{ + "type":"structure", + "required":[ + "StreamARN", + "RecordDistributionStrategy" + ], + "members":{ + "StreamARN":{ + "shape":"StreamARN", + "documentation":"

    The Amazon Resource Name (ARN) of the stream to update.

    ", + "contextParam":{"name":"StreamARN"} + }, + "StreamId":{ + "shape":"StreamId", + "documentation":"

    Not Implemented. Reserved for future use.

    ", + "contextParam":{"name":"StreamId"} + }, + "RecordDistributionStrategy":{ + "shape":"RecordDistributionStrategy", + "documentation":"

    The record distribution strategy to apply to the stream. Specify one of the following values:

    • AUTO – Amazon Kinesis Data Streams distributes records evenly across shards and ignores any partition key and ExplicitHashKey that producers supply.

    • USER_PARTITION_KEY – Producers must supply a partition key, which Amazon Kinesis Data Streams uses to determine shard placement. This is the default.

    " + } + } + }, "UpdateStreamWarmThroughputInput":{ "type":"structure", "required":["WarmThroughputMiBps"], diff --git a/services/kinesis/src/main/resources/codegen-resources/waiters-2.json b/services/kinesis/src/main/resources/codegen-resources/waiters-2.json index d61efe435de5..8d42f578c2d3 100644 --- a/services/kinesis/src/main/resources/codegen-resources/waiters-2.json +++ b/services/kinesis/src/main/resources/codegen-resources/waiters-2.json @@ -25,6 +25,43 @@ "state": "success" } ] + }, + "ChannelActive": { + "delay": 10, + "operation": "DescribeChannel", + "maxAttempts": 18, + "acceptors": [ + { + "expected": "ACTIVE", + "matcher": "path", + "state": "success", + "argument": "ChannelDescription.ChannelStatus" + }, + { + "expected": "CREATING", + "matcher": "path", + "state": "retry", + "argument": "ChannelDescription.ChannelStatus" + }, + { + "expected": "UPDATING", + "matcher": "path", + "state": "retry", + "argument": "ChannelDescription.ChannelStatus" + }, + { + "expected": "DELETING", + "matcher": "path", + "state": "failure", + "argument": "ChannelDescription.ChannelStatus" + }, + { + "expected": "FAILED", + "matcher": "path", + "state": "failure", + "argument": "ChannelDescription.ChannelStatus" + } + ] } } } diff --git a/services/kinesisanalytics/pom.xml b/services/kinesisanalytics/pom.xml index 8e60f1bbfe28..d52c627ce6d3 100644 --- a/services/kinesisanalytics/pom.xml +++ b/services/kinesisanalytics/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisanalytics AWS Java SDK :: Services :: Amazon Kinesis Analytics diff --git a/services/kinesisanalytics/src/main/resources/codegen-resources/customization.config b/services/kinesisanalytics/src/main/resources/codegen-resources/customization.config index 2faadebcd541..00cf44abda98 100644 --- a/services/kinesisanalytics/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisanalytics/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "discoverInputSchema" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0e5ac9ca0377 --- /dev/null +++ b/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a913ed9e5a40..000000000000 --- a/services/kinesisanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisanalyticsv2/pom.xml b/services/kinesisanalyticsv2/pom.xml index 3b5dadd7f3b5..6510319a721e 100644 --- a/services/kinesisanalyticsv2/pom.xml +++ b/services/kinesisanalyticsv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisanalyticsv2 AWS Java SDK :: Services :: Kinesis Analytics V2 diff --git a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/customization.config b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/customization.config index e5f468b10579..81981a072d5e 100644 --- a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listApplications" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0e5ac9ca0377 --- /dev/null +++ b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisanalytics.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a913ed9e5a40..000000000000 --- a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisanalytics.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/service-2.json b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/service-2.json index 67a1990c32d7..b25b4c4434ce 100644 --- a/services/kinesisanalyticsv2/src/main/resources/codegen-resources/service-2.json +++ b/services/kinesisanalyticsv2/src/main/resources/codegen-resources/service-2.json @@ -1524,10 +1524,10 @@ }, "MinPauseBetweenCheckpoints":{ "shape":"MinPauseBetweenCheckpoints", - "documentation":"

    Describes the minimum time in milliseconds after a checkpoint operation completes that a new checkpoint operation can start. If a checkpoint operation takes longer than the CheckpointInterval, the application otherwise performs continual checkpoint operations. For more information, see Tuning Checkpointing in the Apache Flink Documentation.

    If CheckpointConfiguration.ConfigurationType is DEFAULT, the application will use a MinPauseBetweenCheckpoints value of 5000, even if this value is set using this API or in application code.

    " + "documentation":"

    Describes the minimum time in milliseconds after a checkpoint operation completes that a new checkpoint operation can start. If a checkpoint operation takes longer than the CheckpointInterval, the application otherwise performs continual checkpoint operations. For more information, see Tuning Checkpointing in the Apache Flink Documentation.

    If CheckpointConfiguration.ConfigurationType is DEFAULT, the application will use a MinPauseBetweenCheckpoints value of 5000, even if this value is set using this API or in application code.

    " } }, - "documentation":"

    Describes an application's checkpointing configuration. Checkpointing is the process of persisting application state for fault tolerance. For more information, see Checkpoints for Fault Tolerance in the Apache Flink Documentation.

    " + "documentation":"

    Describes an application's checkpointing configuration. Checkpointing is the process of persisting application state for fault tolerance. For more information, see Checkpoints for Fault Tolerance in the Apache Flink Documentation.

    " }, "CheckpointConfigurationDescription":{ "type":"structure", @@ -2367,7 +2367,7 @@ "members":{ "CheckpointConfiguration":{ "shape":"CheckpointConfiguration", - "documentation":"

    Describes an application's checkpointing configuration. Checkpointing is the process of persisting application state for fault tolerance. For more information, see Checkpoints for Fault Tolerance in the Apache Flink Documentation.

    " + "documentation":"

    Describes an application's checkpointing configuration. Checkpointing is the process of persisting application state for fault tolerance. For more information, see Checkpoints for Fault Tolerance in the Apache Flink Documentation.

    " }, "MonitoringConfiguration":{ "shape":"MonitoringConfiguration", @@ -2397,7 +2397,7 @@ }, "JobPlanDescription":{ "shape":"JobPlanDescription", - "documentation":"

    The job plan for an application. For more information about the job plan, see Jobs and Scheduling in the Apache Flink Documentation. To retrieve the job plan for the application, use the DescribeApplicationRequest$IncludeAdditionalDetails parameter of the DescribeApplication operation.

    " + "documentation":"

    The job plan for an application. For more information about the job plan, see Jobs and Scheduling in the Apache Flink Documentation. To retrieve the job plan for the application, use the DescribeApplicationRequest$IncludeAdditionalDetails parameter of the DescribeApplication operation.

    " } }, "documentation":"

    Describes configuration parameters for a Managed Service for Apache Flink application.

    " @@ -2425,7 +2425,7 @@ "members":{ "AllowNonRestoredState":{ "shape":"BooleanObject", - "documentation":"

    When restoring from a snapshot, specifies whether the runtime is allowed to skip a state that cannot be mapped to the new program. This will happen if the program is updated between snapshots to remove stateful parameters, and state data in the snapshot no longer corresponds to valid application data. For more information, see Allowing Non-Restored State in the Apache Flink documentation.

    This value defaults to false. If you update your application without specifying this parameter, AllowNonRestoredState will be set to false, even if it was previously set to true.

    " + "documentation":"

    When restoring from a snapshot, specifies whether the runtime is allowed to skip a state that cannot be mapped to the new program. This will happen if the program is updated between snapshots to remove stateful parameters, and state data in the snapshot no longer corresponds to valid application data. For more information, see Allowing Non-Restored State in the Apache Flink documentation.

    This value defaults to false. If you update your application without specifying this parameter, AllowNonRestoredState will be set to false, even if it was previously set to true.

    " } }, "documentation":"

    Describes the starting parameters for a Managed Service for Apache Flink application.

    " @@ -3444,7 +3444,7 @@ "documentation":"

    Describes whether the Managed Service for Apache Flink service can increase the parallelism of the application in response to increased throughput.

    " } }, - "documentation":"

    Describes parameters for how a Managed Service for Apache Flink application executes multiple tasks simultaneously. For more information about parallelism, see Parallel Execution in the Apache Flink Documentation.

    " + "documentation":"

    Describes parameters for how a Managed Service for Apache Flink application executes multiple tasks simultaneously. For more information about parallelism, see Parallel Execution in the Apache Flink Documentation.

    " }, "ParallelismConfigurationDescription":{ "type":"structure", @@ -3851,7 +3851,8 @@ "FLINK-1_18", "FLINK-1_19", "FLINK-1_20", - "FLINK-2_2" + "FLINK-2_2", + "FLINK-2_3" ] }, "S3ApplicationCodeLocationDescription":{ diff --git a/services/kinesisvideo/pom.xml b/services/kinesisvideo/pom.xml index 487fe0ffd8c0..3078c13c8b9d 100644 --- a/services/kinesisvideo/pom.xml +++ b/services/kinesisvideo/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 kinesisvideo diff --git a/services/kinesisvideo/src/main/resources/codegen-resources/customization.config b/services/kinesisvideo/src/main/resources/codegen-resources/customization.config index c501ccd5d7ac..31d46c600f43 100644 --- a/services/kinesisvideo/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisvideo/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "excludedSimpleMethods": [ "listTagsForStream", "describeStream" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b6b573bc0e87 --- /dev/null +++ b/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1643b51374b9..000000000000 --- a/services/kinesisvideo/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisvideoarchivedmedia/pom.xml b/services/kinesisvideoarchivedmedia/pom.xml index ab196318a26c..562dce7288ba 100644 --- a/services/kinesisvideoarchivedmedia/pom.xml +++ b/services/kinesisvideoarchivedmedia/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisvideoarchivedmedia AWS Java SDK :: Services :: Kinesis Video Archived Media diff --git a/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/customization.config b/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/customization.config index 9a222fcf67a0..2f8167885e99 100644 --- a/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "getHLSStreamingSessionURL" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b6b573bc0e87 --- /dev/null +++ b/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1643b51374b9..000000000000 --- a/services/kinesisvideoarchivedmedia/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisvideomedia/pom.xml b/services/kinesisvideomedia/pom.xml index 89139796a283..a16c871d5ea1 100644 --- a/services/kinesisvideomedia/pom.xml +++ b/services/kinesisvideomedia/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisvideomedia AWS Java SDK :: Services :: Kinesis Video Media diff --git a/services/kinesisvideomedia/src/main/resources/codegen-resources/customization.config b/services/kinesisvideomedia/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/kinesisvideomedia/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisvideomedia/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b6b573bc0e87 --- /dev/null +++ b/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1643b51374b9..000000000000 --- a/services/kinesisvideomedia/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisvideosignaling/pom.xml b/services/kinesisvideosignaling/pom.xml index 835a0930d627..909e92e83bcc 100644 --- a/services/kinesisvideosignaling/pom.xml +++ b/services/kinesisvideosignaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisvideosignaling AWS Java SDK :: Services :: Kinesis Video Signaling diff --git a/services/kinesisvideosignaling/src/main/resources/codegen-resources/customization.config b/services/kinesisvideosignaling/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/kinesisvideosignaling/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisvideosignaling/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b6b573bc0e87 --- /dev/null +++ b/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1643b51374b9..000000000000 --- a/services/kinesisvideosignaling/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/kinesisvideowebrtcstorage/pom.xml b/services/kinesisvideowebrtcstorage/pom.xml index 7c3087c0e013..c7b13db02909 100644 --- a/services/kinesisvideowebrtcstorage/pom.xml +++ b/services/kinesisvideowebrtcstorage/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kinesisvideowebrtcstorage AWS Java SDK :: Services :: Kinesis Video Web RTC Storage diff --git a/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/customization.config b/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/customization.config +++ b/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b6b573bc0e87 --- /dev/null +++ b/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fa29ee515998..000000000000 --- a/services/kinesisvideowebrtcstorage/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kinesisvideo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/kms/pom.xml b/services/kms/pom.xml index d79261a765d1..74fd66b99f12 100644 --- a/services/kms/pom.xml +++ b/services/kms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT kms AWS Java SDK :: Services :: AWS KMS diff --git a/services/kms/src/main/resources/codegen-resources/customization.config b/services/kms/src/main/resources/codegen-resources/customization.config index 5ad7080232ca..f319c25d9faa 100644 --- a/services/kms/src/main/resources/codegen-resources/customization.config +++ b/services/kms/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ "describeCustomKeyStores", "listAliases", "listKeys" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/kms/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/kms/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f143747dc7cb --- /dev/null +++ b/services/kms/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kms-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kms.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://kms.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/kms/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/kms/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 42a8b6e5a3cb..000000000000 --- a/services/kms/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kms-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kms-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://kms.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://kms.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lakeformation/pom.xml b/services/lakeformation/pom.xml index fa57be906a47..643ae2c07f52 100644 --- a/services/lakeformation/pom.xml +++ b/services/lakeformation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lakeformation AWS Java SDK :: Services :: LakeFormation diff --git a/services/lakeformation/src/main/resources/codegen-resources/customization.config b/services/lakeformation/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/lakeformation/src/main/resources/codegen-resources/customization.config +++ b/services/lakeformation/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/lakeformation/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lakeformation/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2119da6adf83 --- /dev/null +++ b/services/lakeformation/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lakeformation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lakeformation-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lakeformation.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lakeformation.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lakeformation/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lakeformation/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 837d3257e484..000000000000 --- a/services/lakeformation/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lakeformation-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lakeformation-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lakeformation.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://lakeformation.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lambda/pom.xml b/services/lambda/pom.xml index eac53849a1d9..8fa824afb341 100644 --- a/services/lambda/pom.xml +++ b/services/lambda/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lambda AWS Java SDK :: Services :: AWS Lambda diff --git a/services/lambda/src/main/resources/codegen-resources/customization.config b/services/lambda/src/main/resources/codegen-resources/customization.config index 952021ded000..1eb09419bc58 100644 --- a/services/lambda/src/main/resources/codegen-resources/customization.config +++ b/services/lambda/src/main/resources/codegen-resources/customization.config @@ -7,6 +7,5 @@ ], "deprecatedOperations": [ "InvokeAsync" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/lambda/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lambda/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2c05a12f0e07 --- /dev/null +++ b/services/lambda/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lambda/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lambda/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 96339d6fb782..000000000000 --- a/services/lambda/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lambda/src/main/resources/codegen-resources/service-2.json b/services/lambda/src/main/resources/codegen-resources/service-2.json index 5ac72a26c462..10005f47c003 100644 --- a/services/lambda/src/main/resources/codegen-resources/service-2.json +++ b/services/lambda/src/main/resources/codegen-resources/service-2.json @@ -387,6 +387,25 @@ "documentation":"

    Deletes the provisioned concurrency configuration for a function.

    ", "idempotent":true }, + "DeleteResourcePolicy":{ + "name":"DeleteResourcePolicy", + "http":{ + "method":"DELETE", + "requestUri":"/2026-07-09/resource-policy/{ResourceArn}", + "responseCode":204 + }, + "input":{"shape":"DeleteResourcePolicyRequest"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ResourceConflictException"}, + {"shape":"ServiceException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"PreconditionFailedException"} + ], + "documentation":"

    Deletes a resource-based policy from a Lambda resource.

    ", + "idempotent":true + }, "GetAccountSettings":{ "name":"GetAccountSettings", "http":{ @@ -775,6 +794,24 @@ "documentation":"

    Retrieves the provisioned concurrency configuration for a function's alias or version.

    ", "readonly":true }, + "GetResourcePolicy":{ + "name":"GetResourcePolicy", + "http":{ + "method":"GET", + "requestUri":"/2026-07-09/resource-policy/{ResourceArn}", + "responseCode":200 + }, + "input":{"shape":"GetResourcePolicyRequest"}, + "output":{"shape":"GetResourcePolicyResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ServiceException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Retrieves the resource-based policy attached to a Lambda resource.

    ", + "readonly":true + }, "GetRuntimeManagementConfig":{ "name":"GetRuntimeManagementConfig", "http":{ @@ -1355,6 +1392,28 @@ "documentation":"

    Adds a provisioned concurrency configuration to a function's alias or version.

    ", "idempotent":true }, + "PutResourcePolicy":{ + "name":"PutResourcePolicy", + "http":{ + "method":"PUT", + "requestUri":"/2026-07-09/resource-policy/{ResourceArn}", + "responseCode":200 + }, + "input":{"shape":"PutResourcePolicyRequest"}, + "output":{"shape":"PutResourcePolicyResponse"}, + "errors":[ + {"shape":"InvalidParameterValueException"}, + {"shape":"ResourceConflictException"}, + {"shape":"PublicPolicyException"}, + {"shape":"ServiceException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"PolicyLengthExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"PreconditionFailedException"} + ], + "documentation":"

    Adds a resource-based policy to a Lambda resource. Resource-based policies grant access to other Amazon Web Services accounts, organizations, or services. Resource-based policies apply to a single Lambda resource (for example, a function, function version, or function alias).

    This operation replaces any existing policy on the Lambda resource. If you previously added permissions using the AddPermission operation, the new policy overwrites those permissions.

    ", + "idempotent":true + }, "PutRuntimeManagementConfig":{ "name":"PutRuntimeManagementConfig", "http":{ @@ -2196,7 +2255,11 @@ "shape":"Timestamp", "documentation":"

    The date and time when the capacity provider was last modified.

    " }, - "PropagateTags":{"shape":"PropagateTags"} + "PropagateTags":{"shape":"PropagateTags"}, + "TelemetryConfig":{ + "shape":"CapacityProviderTelemetryConfig", + "documentation":"

    The telemetry configuration for the capacity provider, including logging settings.

    " + } }, "documentation":"

    A capacity provider manages compute resources for Lambda functions.

    " }, @@ -2233,6 +2296,20 @@ }, "exception":true }, + "CapacityProviderLoggingConfig":{ + "type":"structure", + "members":{ + "SystemLogLevel":{ + "shape":"SystemLogLevel", + "documentation":"

    Set this property to filter the system logs for your capacity provider that Lambda sends to CloudWatch. Lambda only sends system logs at the selected level of detail and lower, where DEBUG is the highest level and WARN is the lowest.

    " + }, + "LogGroup":{ + "shape":"LogGroup", + "documentation":"

    The name of the Amazon CloudWatch log group the capacity provider sends logs to. By default, Lambda capacity providers send logs to a default log group named /aws/lambda/capacity-provider/<capacity provider name>. To use a different log group, enter an existing log group or enter a new log group name.

    " + } + }, + "documentation":"

    The capacity provider's Amazon CloudWatch Logs configuration settings.

    " + }, "CapacityProviderMaxVCpuCount":{ "type":"integer", "box":true, @@ -2312,6 +2389,16 @@ "max":16, "min":1 }, + "CapacityProviderTelemetryConfig":{ + "type":"structure", + "members":{ + "LoggingConfig":{ + "shape":"CapacityProviderLoggingConfig", + "documentation":"

    The capacity provider's Amazon CloudWatch Logs configuration settings.

    " + } + }, + "documentation":"

    Configuration that specifies the telemetry collection for the capacity provider.

    " + }, "CapacityProviderVpcConfig":{ "type":"structure", "required":[ @@ -2855,6 +2942,10 @@ "PropagateTags":{ "shape":"PropagateTags", "documentation":"

    The tag propagation configuration for the capacity provider. Specifies tags to apply to managed resources at launch.

    " + }, + "TelemetryConfig":{ + "shape":"CapacityProviderTelemetryConfig", + "documentation":"

    The telemetry configuration for the capacity provider. Specifies logging settings for managed resources.

    " } } }, @@ -3052,7 +3143,7 @@ }, "Timeout":{ "shape":"Timeout", - "documentation":"

    The amount of time (in seconds) that Lambda allows a function to run before stopping it. The default is 3 seconds. The maximum allowed value is 900 seconds. For more information, see Lambda execution environment.

    " + "documentation":"

    The amount of time (in seconds) that Lambda allows a function to run before stopping it. The default is 3 seconds, and the maximum allowed value is 900 seconds. For functions using Lambda Managed Instances, asynchronous invocations and event source mapping invocations (except Amazon MQ and Amazon DocumentDB) support a maximum allowed value of 5,400 seconds (90 minutes). For more information, see Lambda execution environment.

    " }, "MemorySize":{ "shape":"MemorySize", @@ -3426,6 +3517,24 @@ } } }, + "DeleteResourcePolicyRequest":{ + "type":"structure", + "required":["ResourceArn"], + "members":{ + "ResourceArn":{ + "shape":"PolicyResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Lambda resource you want to delete the policy from. You can use a qualified or an unqualified ARN. The value must be a complete ARN, and the operation does not accept wildcard characters.

    ", + "location":"uri", + "locationName":"ResourceArn" + }, + "RevisionId":{ + "shape":"RevisionId", + "documentation":"

    The revision ID that the existing policy must match for the deletion to proceed. If the revision ID doesn't match, the operation fails with a PreconditionFailedException error. To retrieve the current revision ID, use the GetResourcePolicy operation.

    ", + "location":"querystring", + "locationName":"RevisionId" + } + } + }, "Description":{ "type":"string", "max":256, @@ -3451,6 +3560,14 @@ }, "documentation":"

    A configuration object that specifies the destination of an event after Lambda processes it. For more information, see Adding a destination.

    " }, + "DirectS3Read":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED", + "AUTO" + ] + }, "DocumentDBEventSourceConfig":{ "type":"structure", "members":{ @@ -3732,7 +3849,7 @@ "EphemeralStorageSize":{ "type":"integer", "box":true, - "max":10240, + "max":32768, "min":512 }, "ErrorData":{ @@ -4330,9 +4447,13 @@ "LocalMountPath":{ "shape":"LocalMountPath", "documentation":"

    The path where the function can access the file system, starting with /mnt/.

    " + }, + "S3FilesConfig":{ + "shape":"S3FilesConfig", + "documentation":"

    The configuration for how your function accesses data on an Amazon S3 file system. Valid only when the file system access point ARN is an Amazon S3 Files access point. If you specify a different access point type (for example, Amazon Elastic File System), the operation returns an InvalidParameterException.

    " } }, - "documentation":"

    Details about the connection between a Lambda function and an Amazon EFS file system or an Amazon S3 Files file system.

    " + "documentation":"

    Details about the connection between a Lambda function and an Amazon EFS file system or an Amazon S3 file system.

    " }, "FileSystemConfigList":{ "type":"list", @@ -4428,7 +4549,7 @@ }, "S3ObjectStorageMode":{ "shape":"S3ObjectStorageMode", - "documentation":"

    Specifies how the deployment package is stored. Use COPY (default) to upload a copy of your deployment package to Lambda. Use REFERENCE to have Lambda reference the deployment package from the specified Amazon S3 bucket.

    " + "documentation":"

    Specifies how the deployment package is stored. Valid values:

    • COPY (default) – Uploads a copy of your deployment package to Lambda.

    • REFERENCE – Lambda references the deployment package from the specified Amazon S3 bucket.

    " }, "ImageUri":{ "shape":"String", @@ -4480,14 +4601,14 @@ "members":{ "ErrorCode":{ "shape":"String", - "documentation":"

    The error code for the failed retrieval.

    " + "documentation":"

    The error code that identifies why Lambda failed to retrieve the deployment package.

    " }, "Message":{ "shape":"SensitiveString", - "documentation":"

    A description of the error.

    " + "documentation":"

    The human-readable message that describes why Lambda failed to retrieve the deployment package.

    " } }, - "documentation":"

    Details about an error related to retrieving a function's deployment package.

    " + "documentation":"

    Contains details about an error that occurred when Lambda attempted to retrieve a function's deployment package.

    " }, "FunctionConfiguration":{ "type":"structure", @@ -4598,7 +4719,7 @@ }, "FileSystemConfigs":{ "shape":"FileSystemConfigList", - "documentation":"

    Connection settings for an Amazon EFS file system or an Amazon S3 Files file system.

    " + "documentation":"

    Connection settings for an Amazon EFS file system or an Amazon S3 file system.

    " }, "SigningProfileVersionArn":{ "shape":"Arn", @@ -5552,6 +5673,31 @@ } } }, + "GetResourcePolicyRequest":{ + "type":"structure", + "required":["ResourceArn"], + "members":{ + "ResourceArn":{ + "shape":"PolicyResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Lambda resource you want to retrieve the policy for. You can use a qualified or an unqualified ARN. The value must be a complete ARN, and the operation does not accept wildcard characters.

    ", + "location":"uri", + "locationName":"ResourceArn" + } + } + }, + "GetResourcePolicyResponse":{ + "type":"structure", + "members":{ + "Policy":{ + "shape":"ResourcePolicy", + "documentation":"

    The resource-based policy attached to the Lambda resource you specified.

    " + }, + "RevisionId":{ + "shape":"RevisionId", + "documentation":"

    The revision ID of the policy. Pass this value as the RevisionId in a PutResourcePolicy or DeleteResourcePolicy request. Doing so ensures the operation acts on the expected version of the policy.

    " + } + } + }, "GetRuntimeManagementConfigRequest":{ "type":"structure", "required":["FunctionName"], @@ -5996,12 +6142,6 @@ "location":"uri", "locationName":"FunctionName" }, - "InvocationType":{ - "shape":"ResponseStreamingInvocationType", - "documentation":"

    Use one of the following options:

    • RequestResponse (default) – Invoke the function synchronously. Keep the connection open until the function returns a response or times out. The API operation response includes the function response and additional data.

    • DryRun – Validate parameter values and verify that the IAM user or role has permission to invoke the function.

    ", - "location":"header", - "locationName":"X-Amz-Invocation-Type" - }, "LogType":{ "shape":"LogType", "documentation":"

    Set to Tail to include the execution log in the response. Applies to synchronously invoked functions only.

    ", @@ -6029,6 +6169,12 @@ "documentation":"

    The identifier of the tenant in a multi-tenant Lambda function.

    ", "location":"header", "locationName":"X-Amz-Tenant-Id" + }, + "InvocationType":{ + "shape":"ResponseStreamingInvocationType", + "documentation":"

    Use one of the following options:

    • RequestResponse (default) – Invoke the function synchronously. Keep the connection open until the function returns a response or times out. The API operation response includes the function response and additional data.

    • DryRun – Validate parameter values and verify that the IAM user or role has permission to invoke the function.

    ", + "location":"header", + "locationName":"X-Amz-Invocation-Type" } }, "payload":"Payload" @@ -6274,7 +6420,8 @@ "FunctionError.PermissionDenied", "FunctionError.TooManyExtensions", "FunctionError.InitResourceExhausted", - "DisallowedByVpcEncryptionControl" + "DisallowedByVpcEncryptionControl", + "DependencyError" ] }, "Layer":{ @@ -6348,7 +6495,10 @@ "shape":"S3ObjectVersion", "documentation":"

    For versioned objects, the version of the layer archive object to use.

    " }, - "S3ObjectStorageMode":{"shape":"S3ObjectStorageMode"}, + "S3ObjectStorageMode":{ + "shape":"S3ObjectStorageMode", + "documentation":"

    Specifies how the layer archive is stored. Valid values:

    • COPY (default) – Uploads a copy of your layer archive to Lambda.

    • REFERENCE – Lambda references the layer archive from the specified Amazon S3 bucket.

    " + }, "ZipFile":{ "shape":"Blob", "documentation":"

    The base64-encoded contents of the layer archive. Amazon Web Services SDK and Amazon Web Services CLI clients handle the encoding for you.

    " @@ -6379,7 +6529,10 @@ "shape":"Arn", "documentation":"

    The Amazon Resource Name (ARN) of a signing job.

    " }, - "ResolvedS3Object":{"shape":"ResolvedS3Object"} + "ResolvedS3Object":{ + "shape":"ResolvedS3Object", + "documentation":"

    The resolved Amazon S3 object that contains the layer archive.

    " + } }, "documentation":"

    Details about a version of an Lambda layer.

    " }, @@ -7558,6 +7711,12 @@ }, "exception":true }, + "PolicyResourceArn":{ + "type":"string", + "max":256, + "min":0, + "pattern":"arn:(aws[a-zA-Z-]*)?:lambda:(eusc-)?[a-z]{2}((-gov)|(-iso([a-z]?)))?-[a-z]+-\\d{1}:\\d{12}:function:[a-zA-Z0-9-_]+(:(\\$LATEST(\\.PUBLISHED)?|[a-zA-Z0-9-_])+)?" + }, "PositiveInteger":{ "type":"integer", "box":true, @@ -7690,7 +7849,7 @@ }, "MaximumPollers":{ "shape":"MaximumNumberOfPollers", - "documentation":"

    The maximum number of event pollers this event source can scale up to. For Amazon SQS events source mappings, default is 200, and minimum value allowed is 2. For Amazon MSK and self-managed Apache Kafka event source mappings, default is 200, and minimum value allowed is 1.

    " + "documentation":"

    The maximum number of event pollers this event source can scale up to. For Amazon SQS event source mappings, the accepted range is between 2 and 10,000, with a default of 200. For Amazon MSK and self-managed Apache Kafka event source mappings, the accepted range is between 1 and 2,000, with a default of 200.

    " }, "PollerGroupName":{ "shape":"ProvisionedPollerGroupName", @@ -7717,7 +7876,7 @@ "documentation":"

    The exception message.

    " } }, - "documentation":"

    The resource-based policy you tried to add to the Lambda function would grant public access to it, and your account's BlockPublicAccess setting prevents public access. For more information about blocking public access to Lambda functions, see Block public access to Lambda resources.

    ", + "documentation":"

    The resource-based policy you tried to add to the Lambda resource would grant public access to it, which isn't allowed.

    ", "error":{ "httpStatusCode":400, "senderFault":true @@ -8036,6 +8195,42 @@ } } }, + "PutResourcePolicyRequest":{ + "type":"structure", + "required":[ + "ResourceArn", + "Policy" + ], + "members":{ + "ResourceArn":{ + "shape":"PolicyResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Lambda resource you want to add the policy to. You can use a qualified or an unqualified ARN. The value must be a complete ARN, and the operation does not accept wildcard characters.

    ", + "location":"uri", + "locationName":"ResourceArn" + }, + "Policy":{ + "shape":"ResourcePolicy", + "documentation":"

    The policy document you want to add to your Lambda resource. This is formatted as a JSON string.

    For more information, see Working with resource-based policies in Lambda in the Lambda Developer Guide.

    " + }, + "RevisionId":{ + "shape":"RevisionId", + "documentation":"

    The revision ID that the existing policy must match for the replacement to proceed. If the revision ID doesn't match, the operation fails with a PreconditionFailedException error. To retrieve the current revision ID, use the GetResourcePolicy operation.

    " + } + } + }, + "PutResourcePolicyResponse":{ + "type":"structure", + "members":{ + "Policy":{ + "shape":"ResourcePolicy", + "documentation":"

    The resource-based policy that Lambda adds to the resource.

    " + }, + "RevisionId":{ + "shape":"RevisionId", + "documentation":"

    The revision ID of the policy that Lambda adds to your Lambda resource.

    " + } + } + }, "PutRuntimeManagementConfigRequest":{ "type":"structure", "required":[ @@ -8305,6 +8500,12 @@ "exception":true, "fault":true }, + "ResourcePolicy":{ + "type":"string", + "max":20480, + "min":1, + "pattern":"[\\s\\S]+" + }, "ResponseStreamingInvocationType":{ "type":"string", "enum":[ @@ -8336,6 +8537,12 @@ "type":"boolean", "box":true }, + "RevisionId":{ + "type":"string", + "max":36, + "min":36, + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, "RoleArn":{ "type":"string", "max":10000, @@ -8390,7 +8597,12 @@ "ruby4.0", "provided", "provided.al2", - "provided.al2023" + "provided.al2023", + "nodejs26.x", + "python3.15", + "java8.al2023", + "java11.al2023", + "java17.al2023" ] }, "RuntimeVersionArn":{ @@ -8433,6 +8645,16 @@ "min":3, "pattern":"[0-9A-Za-z\\.\\-_]*(?Specifies if a function reads from the file system for the lowest latency, or through Amazon S3 Files feature \"direct Amazon S3 bucket reads\" for the highest throughput. Valid values:

    • AUTO (default) – Direct reads are active for functions you configure with 512 MB or more of memory.

    • ENABLED – Enforces all reads are directly from the Amazon S3 bucket, regardless of available memory (less than 512 MB).

    • DISABLED – Routes all reads through the file system, regardless of memory configuration.

    To use direct reads, you must grant the execution role the s3:GetObject and s3:GetObjectVersion permissions. If a direct read fails, Lambda automatically falls back to reading through the file system.

    " + } + }, + "documentation":"

    Setting controls how your function accesses data from an Amazon S3 file system.

    " + }, "S3FilesMountConnectivityException":{ "type":"structure", "members":{ @@ -8498,7 +8720,7 @@ }, "S3ObjectStorageMode":{ "type":"string", - "documentation":"

    The storage mode for a function's deployment package.

    ", + "documentation":"

    The method Lambda uses to store a function's deployment package — either by copying the package into Lambda-managed storage (COPY) or by referencing it directly from the source Amazon S3 bucket (REFERENCE).

    ", "enum":[ "COPY", "REFERENCE" @@ -8886,7 +9108,8 @@ "FunctionError.TooManyExtensions", "FunctionError.InitResourceExhausted", "DisallowedByVpcEncryptionControl", - "DrainingDurableExecutions" + "DrainingDurableExecutions", + "DependencyError" ] }, "StatementId":{ @@ -9363,7 +9586,11 @@ "shape":"CapacityProviderScalingConfig", "documentation":"

    The updated scaling configuration for the capacity provider.

    " }, - "PropagateTags":{"shape":"PropagateTags"} + "PropagateTags":{"shape":"PropagateTags"}, + "TelemetryConfig":{ + "shape":"CapacityProviderTelemetryConfig", + "documentation":"

    The updated telemetry configuration for the capacity provider.

    " + } } }, "UpdateCapacityProviderResponse":{ @@ -9525,7 +9752,7 @@ }, "S3ObjectStorageMode":{ "shape":"S3ObjectStorageMode", - "documentation":"

    Specifies how the deployment package is stored. Use COPY (default) to upload a copy of your deployment package to Lambda. Use REFERENCE to have Lambda reference the deployment package from the specified Amazon S3 bucket.

    " + "documentation":"

    Specifies how the deployment package is stored. Valid values:

    • COPY (default) – Uploads a copy of your deployment package to Lambda.

    • REFERENCE – Lambda references the deployment package from the specified Amazon S3 bucket.

    " }, "ImageUri":{ "shape":"String", @@ -9581,7 +9808,7 @@ }, "Timeout":{ "shape":"Timeout", - "documentation":"

    The amount of time (in seconds) that Lambda allows a function to run before stopping it. The default is 3 seconds. The maximum allowed value is 900 seconds. For more information, see Lambda execution environment.

    " + "documentation":"

    The amount of time (in seconds) that Lambda allows a function to run before stopping it. The default is 3 seconds, and the maximum allowed value is 900 seconds. For functions using Lambda Managed Instances, asynchronous invocations and event source mapping invocations (except Amazon MQ and Amazon DocumentDB) support a maximum allowed value of 5,400 seconds (90 minutes). For more information, see Lambda execution environment.

    " }, "MemorySize":{ "shape":"MemorySize", diff --git a/services/lambdacore/pom.xml b/services/lambdacore/pom.xml index 90fd1789d153..0987b6ecb95c 100644 --- a/services/lambdacore/pom.xml +++ b/services/lambdacore/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lambdacore AWS Java SDK :: Services :: Lambda Core diff --git a/services/lambdacore/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lambdacore/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2c05a12f0e07 --- /dev/null +++ b/services/lambdacore/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lambdacore/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lambdacore/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 45723baf9152..000000000000 --- a/services/lambdacore/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/lambdamicrovms/pom.xml b/services/lambdamicrovms/pom.xml index 4c1600a85f88..a64843648381 100644 --- a/services/lambdamicrovms/pom.xml +++ b/services/lambdamicrovms/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lambdamicrovms AWS Java SDK :: Services :: Lambda Microvms diff --git a/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2c05a12f0e07 --- /dev/null +++ b/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 45723baf9152..000000000000 --- a/services/lambdamicrovms/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lambda.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/lambdamicrovms/src/main/resources/codegen-resources/service-2.json b/services/lambdamicrovms/src/main/resources/codegen-resources/service-2.json index 6a4cf43a3919..2070c148d6b3 100644 --- a/services/lambdamicrovms/src/main/resources/codegen-resources/service-2.json +++ b/services/lambdamicrovms/src/main/resources/codegen-resources/service-2.json @@ -27,6 +27,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"ValidationException"} ], "documentation":"

    Creates an authentication token for accessing a running MicroVM. The token grants access to the specified ports on the MicroVM endpoint.

    " @@ -65,6 +66,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"ValidationException"} ], "documentation":"

    Creates a shell authentication token for interactive shell access to a running MicroVM. The MicroVM must have been run with the SHELL_INGRESS network connector attached.

    " @@ -308,8 +310,12 @@ "output":{"shape":"ListTagsResponse"}, "errors":[ {"shape":"TooManyRequestsException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceException"}, + {"shape":"ValidationException"}, {"shape":"InvalidParameterValueException"} ], "documentation":"

    Lists the tags associated with a Lambda MicroVM resource.

    ", @@ -347,6 +353,7 @@ "errors":[ {"shape":"InternalServerException"}, {"shape":"AccessDeniedException"}, + {"shape":"InsufficientCapacityException"}, {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"}, {"shape":"ConflictException"}, @@ -385,8 +392,12 @@ "input":{"shape":"TagResourceRequest"}, "errors":[ {"shape":"TooManyRequestsException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceException"}, + {"shape":"ValidationException"}, {"shape":"InvalidParameterValueException"}, {"shape":"ResourceConflictException"} ], @@ -423,8 +434,12 @@ "input":{"shape":"UntagResourceRequest"}, "errors":[ {"shape":"TooManyRequestsException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, {"shape":"ServiceException"}, + {"shape":"ValidationException"}, {"shape":"InvalidParameterValueException"}, {"shape":"ResourceConflictException"} ], @@ -559,7 +574,7 @@ "members":{ "uri":{ "shape":"NonBlankString", - "documentation":"

    The URI of the code artifact, such as an Amazon S3 path or Amazon ECR image URI.

    " + "documentation":"

    The URI of the code artifact in Amazon S3.

    " } }, "documentation":"

    Contains the location of the code artifact for a MicroVM image.

    ", @@ -934,7 +949,8 @@ "EnvironmentVariableValue":{ "type":"string", "max":4096, - "min":0 + "min":0, + "sensitive":true }, "GetMicrovmImageBuildInput":{ "type":"structure", @@ -1348,6 +1364,17 @@ "min":1, "pattern":"[a-zA-Z0-9-_]+" }, + "InsufficientCapacityException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    There is insufficient capacity to fulfill the request. Retry the request later.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, "Integer":{ "type":"integer", "box":true @@ -1766,6 +1793,10 @@ "shape":"NonBlankString", "documentation":"

    The version of the managed MicroVM image.

    " }, + "status":{ + "shape":"ManagedMicrovmImageVersionStatus", + "documentation":"

    The lifecycle status of the managed MicroVM image version. Valid values: AVAILABLE (the version is available for use) or DEPRECATED (the version is deprecated; do not use it for new MicroVM images).

    " + }, "createdAt":{ "shape":"Timestamp", "documentation":"

    The timestamp when the version was created.

    " @@ -1781,6 +1812,14 @@ "type":"list", "member":{"shape":"ManagedMicrovmImageVersion"} }, + "ManagedMicrovmImageVersionStatus":{ + "type":"string", + "documentation":"

    The lifecycle status of a managed MicroVM image version.

    ", + "enum":[ + "AVAILABLE", + "DEPRECATED" + ] + }, "MicrovmHooks":{ "type":"structure", "members":{ @@ -1853,7 +1892,8 @@ "type":"string", "documentation":"

    MicroVm Image Arn

    ", "max":2048, - "min":20 + "min":20, + "pattern":"arn:[a-z0-9-]+:lambda:[a-z0-9-]*:[a-z0-9]*:microvm-image:.+" }, "MicrovmImageBuildSummaries":{ "type":"list", @@ -2323,6 +2363,12 @@ "min":20, "pattern":"arn:aws[a-z\\-]*:iam::[0-9]{12}:role/?[a-zA-Z_0-9+=,.@\\-_/]+" }, + "RunHookPayload":{ + "type":"string", + "max":4096, + "min":0, + "sensitive":true + }, "RunMicrovmRequest":{ "type":"structure", "required":["imageIdentifier"], @@ -2356,7 +2402,7 @@ "documentation":"

    The logging configuration for this MicroVM instance. Specify {\"cloudWatch\": {\"logGroup\": \"...\"}} to stream application logs to a custom CloudWatch log group, or {\"disabled\": {}} to turn off logging.

    " }, "runHookPayload":{ - "shape":"RunMicrovmRequestRunHookPayloadString", + "shape":"RunHookPayload", "documentation":"

    Per-MicroVM initialization data delivered as the request body of the /run lifecycle hook. Use to pass tenant-specific configuration such as session IDs or secret references. Maximum: 16,384 bytes.

    " }, "maximumDurationInSeconds":{ @@ -2381,11 +2427,6 @@ "max":28800, "min":1 }, - "RunMicrovmRequestRunHookPayloadString":{ - "type":"string", - "max":4096, - "min":0 - }, "RunMicrovmResponse":{ "type":"structure", "required":[ diff --git a/services/launchwizard/pom.xml b/services/launchwizard/pom.xml index a4eb1e8469e7..5d11ffbbe971 100644 --- a/services/launchwizard/pom.xml +++ b/services/launchwizard/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT launchwizard AWS Java SDK :: Services :: Launch Wizard diff --git a/services/launchwizard/src/main/resources/codegen-resources/customization.config b/services/launchwizard/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/launchwizard/src/main/resources/codegen-resources/customization.config +++ b/services/launchwizard/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/launchwizard/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/launchwizard/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2614a5994c86 --- /dev/null +++ b/services/launchwizard/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://launchwizard-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://launchwizard-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://launchwizard.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://launchwizard.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/launchwizard/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/launchwizard/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 941cdb43c22b..000000000000 --- a/services/launchwizard/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://launchwizard-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://launchwizard-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://launchwizard.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://launchwizard.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/launchwizard/src/main/resources/codegen-resources/service-2.json b/services/launchwizard/src/main/resources/codegen-resources/service-2.json index 1f9d98f23eb4..dea3bc6b4535 100644 --- a/services/launchwizard/src/main/resources/codegen-resources/service-2.json +++ b/services/launchwizard/src/main/resources/codegen-resources/service-2.json @@ -268,6 +268,21 @@ } }, "shapes":{ + "AccountConstraint":{ + "type":"structure", + "members":{ + "managementAccount":{"shape":"ManagementAccountConstraint"}, + "delegatedAdmin":{"shape":"DelegatedAdminConstraint"} + }, + "documentation":"

    A constraint on which AWS account a deployment can be initiated from. Specify one of the supported constraint types.

    ", + "union":true + }, + "AccountConstraintsList":{ + "type":"list", + "member":{"shape":"AccountConstraint"}, + "max":10, + "min":0 + }, "AllowedValues":{ "type":"list", "member":{"shape":"ValueString"} @@ -320,6 +335,17 @@ } } }, + "DelegatedAdminConstraint":{ + "type":"structure", + "required":["servicePrincipal"], + "members":{ + "servicePrincipal":{ + "shape":"ServicePrincipalType", + "documentation":"

    The service principal for which the account must be a delegated administrator. For example, stacksets.cloudformation.amazonaws.com.

    " + } + }, + "documentation":"

    The deployment must be initiated from a delegated administrator account for the specified service principal.

    " + }, "DeleteDeploymentInput":{ "type":"structure", "required":["deploymentId"], @@ -475,7 +501,8 @@ "timestamp":{ "shape":"Timestamp", "documentation":"

    The timestamp of the deployment event.

    " - } + }, + "metadata":{"shape":"DeploymentEventMetadata"} }, "documentation":"

    A summary of the deployment event data.

    " }, @@ -483,6 +510,25 @@ "type":"list", "member":{"shape":"DeploymentEventDataSummary"} }, + "DeploymentEventMetadata":{ + "type":"map", + "key":{"shape":"DeploymentEventMetadataKey"}, + "value":{"shape":"DeploymentEventMetadataValue"}, + "documentation":"

    A map of metadata key-value pairs associated with a deployment event. For error detection events, contains workload context and log excerpts used for troubleshooting.

    ", + "max":25, + "min":0 + }, + "DeploymentEventMetadataKey":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9_.-]+" + }, + "DeploymentEventMetadataValue":{ + "type":"string", + "max":4096, + "min":0 + }, "DeploymentFilter":{ "type":"structure", "members":{ @@ -973,6 +1019,11 @@ } } }, + "ManagementAccountConstraint":{ + "type":"structure", + "members":{}, + "documentation":"

    The deployment must be initiated from the AWS Organizations management account.

    " + }, "MaxDeploymentEventResults":{ "type":"integer", "box":true, @@ -1026,6 +1077,12 @@ }, "exception":true }, + "ServicePrincipalType":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-z0-9.-]+\\.amazonaws\\.com(\\.cn)?" + }, "SpecificationsConditionalData":{ "type":"list", "member":{"shape":"DeploymentConditionalField"}, @@ -1037,7 +1094,7 @@ "type":"string", "max":128, "min":1, - "pattern":"(?!aws:)[a-zA-Z+-=._:/]+" + "pattern":"[a-zA-Z0-9 _.:/=+@-]+" }, "TagKeyList":{ "type":"list", @@ -1072,7 +1129,7 @@ "type":"string", "max":256, "min":0, - "pattern":"[a-zA-Z+-=._:/]*" + "pattern":"[a-zA-Z0-9 _.:/=+@-]*" }, "Tags":{ "type":"map", @@ -1181,6 +1238,10 @@ "shape":"WorkloadStatus", "documentation":"

    The status of a workload.

    You can list deployments in the DISABLED status.

    " }, + "accountConstraints":{ + "shape":"AccountConstraintsList", + "documentation":"

    Optional list of constraints describing what kind of AWS account is allowed to deploy this workload or deployment pattern. Within a single list the semantics are OR: an account satisfies the list if it satisfies any entry. Workload-level and pattern-level lists combine with AND at deployment time. An absent or empty list at this level means no constraint at this level.

    " + }, "description":{ "shape":"String", "documentation":"

    The description of a workload.

    " @@ -1214,6 +1275,10 @@ "status":{ "shape":"WorkloadStatus", "documentation":"

    The status of the workload.

    " + }, + "accountConstraints":{ + "shape":"AccountConstraintsList", + "documentation":"

    Optional list of constraints describing what kind of AWS account is allowed to deploy this workload or deployment pattern. Within a single list the semantics are OR: an account satisfies the list if it satisfies any entry. Workload-level and pattern-level lists combine with AND at deployment time. An absent or empty list at this level means no constraint at this level.

    " } }, "documentation":"

    Describes workload data.

    " @@ -1257,6 +1322,10 @@ "shape":"String", "documentation":"

    The status message of the deployment pattern.

    " }, + "accountConstraints":{ + "shape":"AccountConstraintsList", + "documentation":"

    Optional list of constraints describing what kind of AWS account is allowed to deploy this workload or deployment pattern. Within a single list the semantics are OR: an account satisfies the list if it satisfies any entry. Workload-level and pattern-level lists combine with AND at deployment time. An absent or empty list at this level means no constraint at this level.

    " + }, "specifications":{ "shape":"DeploymentSpecificationsData", "documentation":"

    The settings specified for the deployment. These settings define how to deploy and configure your resources created by the deployment. For more information about the specifications required for creating a deployment for a SAP workload, see SAP deployment specifications. To retrieve the specifications required to create a deployment for other workloads, use the GetWorkloadDeploymentPattern operation.

    " @@ -1298,6 +1367,10 @@ "statusMessage":{ "shape":"String", "documentation":"

    A message about a workload deployment pattern's status.

    " + }, + "accountConstraints":{ + "shape":"AccountConstraintsList", + "documentation":"

    Optional list of constraints describing what kind of AWS account is allowed to deploy this workload or deployment pattern. Within a single list the semantics are OR: an account satisfies the list if it satisfies any entry. Workload-level and pattern-level lists combine with AND at deployment time. An absent or empty list at this level means no constraint at this level.

    " } }, "documentation":"

    Describes a workload deployment pattern.

    " diff --git a/services/lexmodelbuilding/pom.xml b/services/lexmodelbuilding/pom.xml index 972635fce1f8..fc210e4a00bc 100644 --- a/services/lexmodelbuilding/pom.xml +++ b/services/lexmodelbuilding/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lexmodelbuilding AWS Java SDK :: Services :: Amazon Lex Model Building diff --git a/services/lexmodelbuilding/src/main/resources/codegen-resources/customization.config b/services/lexmodelbuilding/src/main/resources/codegen-resources/customization.config index dd5c901b0edb..b809e235553a 100644 --- a/services/lexmodelbuilding/src/main/resources/codegen-resources/customization.config +++ b/services/lexmodelbuilding/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "getBuiltinSlotTypes", "getIntents", "getSlotTypes" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..35d83c1763c4 --- /dev/null +++ b/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models.lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models-fips.lex.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models.lex-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models.lex.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models.lex.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models.lex.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAABwX14QsAAAAIAAAACAX14QsF9eEMAAAABQX14QkF9eEKAAAABAAAAA4AAAALAAAABgAAAAwF9eEIAAAABwX14QYAAAANAAAACAX14QYF9eEHAAAABQAAAA8F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 069fe163e144..000000000000 --- a/services/lexmodelbuilding/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,414 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://models.lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://models-fips.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://models-fips.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://models.lex-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://models.lex.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://models.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://models.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://models.lex.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lexmodelsv2/pom.xml b/services/lexmodelsv2/pom.xml index bf4fd1ff0c4e..b825aea7598a 100644 --- a/services/lexmodelsv2/pom.xml +++ b/services/lexmodelsv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lexmodelsv2 AWS Java SDK :: Services :: Lex Models V2 diff --git a/services/lexmodelsv2/src/main/resources/codegen-resources/customization.config b/services/lexmodelsv2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/lexmodelsv2/src/main/resources/codegen-resources/customization.config +++ b/services/lexmodelsv2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..22fa48a2056c --- /dev/null +++ b/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models-v2-lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models-v2-lex-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models-v2-lex.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://models-v2-lex.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9becf5783aa1..000000000000 --- a/services/lexmodelsv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://models-v2-lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://models-v2-lex-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://models-v2-lex.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://models-v2-lex.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lexmodelsv2/src/main/resources/codegen-resources/service-2.json b/services/lexmodelsv2/src/main/resources/codegen-resources/service-2.json index a6e834fe70bb..0e60467988b6 100644 --- a/services/lexmodelsv2/src/main/resources/codegen-resources/service-2.json +++ b/services/lexmodelsv2/src/main/resources/codegen-resources/service-2.json @@ -4015,6 +4015,10 @@ "audioFillerSettings":{ "shape":"AudioFillerSettings", "documentation":"

    Audio filler settings to apply when importing the bot locale configuration. Audio filler requires unifiedSpeechSettings (speech-to-speech) to be enabled when enabled is true.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The speaker diarization settings to apply when importing the bot locale configuration.

    " } }, "documentation":"

    Provides the bot locale parameters required for importing a bot locale.

    " @@ -5160,6 +5164,10 @@ "speechDetectionSensitivity":{ "shape":"SpeechDetectionSensitivity", "documentation":"

    The sensitivity level for voice activity detection (VAD) in the bot locale. This setting helps optimize speech recognition accuracy by adjusting how the system responds to background noise during voice interactions.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The speaker diarization settings to configure for the new bot locale. When enabled, Amazon Lex restricts speech detection to the primary (loudest) speaker during streaming audio conversations.

    " } } }, @@ -5218,6 +5226,10 @@ "speechDetectionSensitivity":{ "shape":"SpeechDetectionSensitivity", "documentation":"

    The sensitivity level for voice activity detection (VAD) that was specified for the bot locale.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The speaker diarization settings configured for the created bot locale.

    " } } }, @@ -7074,6 +7086,10 @@ "speechDetectionSensitivity":{ "shape":"SpeechDetectionSensitivity", "documentation":"

    The sensitivity level for voice activity detection (VAD) configured for the bot locale.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The speaker diarization settings configured for the bot locale.

    " } } }, @@ -12938,6 +12954,17 @@ "Descending" ] }, + "SpeakerDiarizationSettings":{ + "type":"structure", + "required":["enabled"], + "members":{ + "enabled":{ + "shape":"Enabled", + "documentation":"

    Specifies whether speaker diarization is enabled for the bot locale. Set to true to have Amazon Lex treat speech from speakers other than the primary speaker as non-speech. Set to false to disable speaker diarization and rely on voice activity detection alone.

    " + } + }, + "documentation":"

    Specifies configuration that restricts speech detection to the primary (loudest) speaker during streaming audio conversations, so that speech from background speakers does not start a turn, interrupt the bot, or reach speech recognition.

    " + }, "Specifications":{ "type":"structure", "required":[ @@ -12995,7 +13022,8 @@ "enum":[ "Standard", "Neural", - "Deepgram" + "Deepgram", + "Advanced" ] }, "SpeechRecognitionSettings":{ @@ -14524,6 +14552,10 @@ "speechDetectionSensitivity":{ "shape":"SpeechDetectionSensitivity", "documentation":"

    The new sensitivity level for voice activity detection (VAD) in the bot locale. This setting helps optimize speech recognition accuracy by adjusting how the system responds to background noise during voice interactions.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The updated speaker diarization settings to apply to the bot locale. If you omit this field, Amazon Lex keeps the setting currently stored on the bot locale. To turn speaker diarization off, set enabled to false explicitly.

    " } } }, @@ -14597,6 +14629,10 @@ "speechDetectionSensitivity":{ "shape":"SpeechDetectionSensitivity", "documentation":"

    The updated sensitivity level for voice activity detection (VAD) in the bot locale.

    " + }, + "speakerDiarizationSettings":{ + "shape":"SpeakerDiarizationSettings", + "documentation":"

    The updated speaker diarization settings for the bot locale.

    " } } }, @@ -15814,5 +15850,5 @@ "min":0 } }, - "documentation":"

    Amazon Lex Model Building Service provides APIs for creating, managing, and deploying conversational bots and their components.

    " + "documentation":"

    This document provides detailed information about the Amazon Lex V2 API actions and their parameters.

    For information about the IAM access control permissions you need to use this API, see Identity-based policies for Amazon Lex V2.

    Amazon Lex V2 Model Building V2 operations let you build and manage bots.

    If you use a custom HTTP client to call Amazon Lex Model Building V2 operations, you must set the \"Content-Type\" HTTP header to \"application/x-amz-json-1.1\". Otherwise, you receive an HTTP 404 - UnknownOperationException in the response.

    Amazon Lex Model Building V2 operations return the responses with the \"application/x-amz-json-1.1\" content type.

    You can use Amazon Web Services SDKs to access Amazon Lex V2 APIs using your favorite programming language. The SDKs automatically perform useful tasks for you, such as:

    • Cryptographically sign your service requests

    • Retry requests

    • Handle error responses

    The following resources provide additional information about the Amazon Lex V2 Model Building API.

    " } diff --git a/services/lexruntime/pom.xml b/services/lexruntime/pom.xml index 06cd5962a942..5e2b6b091e1c 100644 --- a/services/lexruntime/pom.xml +++ b/services/lexruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lexruntime AWS Java SDK :: Services :: Amazon Lex Runtime diff --git a/services/lexruntime/src/main/resources/codegen-resources/customization.config b/services/lexruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/lexruntime/src/main/resources/codegen-resources/customization.config +++ b/services/lexruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/lexruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lexruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ca7ff318fbe2 --- /dev/null +++ b/services/lexruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-fips.lex.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.lex-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.lex.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.lex.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.lex.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAABwX14QsAAAAIAAAACAX14QsF9eEMAAAABQX14QkF9eEKAAAABAAAAA4AAAALAAAABgAAAAwF9eEIAAAABwX14QYAAAANAAAACAX14QYF9eEHAAAABQAAAA8F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAARAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lexruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lexruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ff45540ddeb3..000000000000 --- a/services/lexruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,414 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime.lex-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.lex.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://runtime.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://runtime.lex.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime.lex.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lexruntimev2/pom.xml b/services/lexruntimev2/pom.xml index 48c447719922..c7f974b4667e 100644 --- a/services/lexruntimev2/pom.xml +++ b/services/lexruntimev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lexruntimev2 AWS Java SDK :: Services :: Lex Runtime V2 diff --git a/services/lexruntimev2/src/main/resources/codegen-resources/customization.config b/services/lexruntimev2/src/main/resources/codegen-resources/customization.config index a10b6cbcf23a..903b59d94b56 100644 --- a/services/lexruntimev2/src/main/resources/codegen-resources/customization.config +++ b/services/lexruntimev2/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "customServiceMetadata": { "contentType": "application/json" }, - "enableGenerateCompiledEndpointRules": true, "usePriorKnowledgeForH2": true } diff --git a/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..33b4d2868dca --- /dev/null +++ b/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-v2-lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-v2-lex-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-v2-lex.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-v2-lex.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f855f7f1f318..000000000000 --- a/services/lexruntimev2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime-v2-lex-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime-v2-lex-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime-v2-lex.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime-v2-lex.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/licensemanager/pom.xml b/services/licensemanager/pom.xml index ccb6af62428b..4f1daf3e3733 100644 --- a/services/licensemanager/pom.xml +++ b/services/licensemanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT licensemanager AWS Java SDK :: Services :: License Manager diff --git a/services/licensemanager/src/main/resources/codegen-resources/customization.config b/services/licensemanager/src/main/resources/codegen-resources/customization.config index d8c559db863a..16be78f108b4 100644 --- a/services/licensemanager/src/main/resources/codegen-resources/customization.config +++ b/services/licensemanager/src/main/resources/codegen-resources/customization.config @@ -7,6 +7,5 @@ "getServiceSettings", "listLicenseConfigurations", "listResourceInventory" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/licensemanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/licensemanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1e4ca41a6c5f --- /dev/null +++ b/services/licensemanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/licensemanager/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/licensemanager/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2387d248b684..000000000000 --- a/services/licensemanager/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://license-manager.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/licensemanager/src/main/resources/codegen-resources/service-2.json b/services/licensemanager/src/main/resources/codegen-resources/service-2.json index b2160657d4a4..fd6942b5aa48 100644 --- a/services/licensemanager/src/main/resources/codegen-resources/service-2.json +++ b/services/licensemanager/src/main/resources/codegen-resources/service-2.json @@ -2030,6 +2030,10 @@ "SourceVersion":{ "shape":"String", "documentation":"

    Current version of the license.

    " + }, + "ResetUsage":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to reset the license usage for the new license version. If you don't specify a value, the license usage is not reset.

    " } } }, diff --git a/services/licensemanagerlinuxsubscriptions/pom.xml b/services/licensemanagerlinuxsubscriptions/pom.xml index 892fd96f78b1..3e3dfa556031 100644 --- a/services/licensemanagerlinuxsubscriptions/pom.xml +++ b/services/licensemanagerlinuxsubscriptions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT licensemanagerlinuxsubscriptions AWS Java SDK :: Services :: License Manager Linux Subscriptions diff --git a/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/customization.config b/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/customization.config +++ b/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c169f855d195 --- /dev/null +++ b/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-linux-subscriptions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-linux-subscriptions-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-linux-subscriptions.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-linux-subscriptions.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4b9b16b1bc04..000000000000 --- a/services/licensemanagerlinuxsubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-linux-subscriptions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-linux-subscriptions-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-linux-subscriptions.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-linux-subscriptions.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/licensemanagerusersubscriptions/pom.xml b/services/licensemanagerusersubscriptions/pom.xml index e01e3d956cbe..80e9a05024c3 100644 --- a/services/licensemanagerusersubscriptions/pom.xml +++ b/services/licensemanagerusersubscriptions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT licensemanagerusersubscriptions AWS Java SDK :: Services :: License Manager User Subscriptions diff --git a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/customization.config b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/customization.config +++ b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..19cd701976b4 --- /dev/null +++ b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-user-subscriptions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-user-subscriptions-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-user-subscriptions.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://license-manager-user-subscriptions.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f72081b8f1df..000000000000 --- a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-user-subscriptions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-user-subscriptions-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-user-subscriptions.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://license-manager-user-subscriptions.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/service-2.json b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/service-2.json index af5be9481bb4..172cdf8011ee 100644 --- a/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/service-2.json +++ b/services/licensemanagerusersubscriptions/src/main/resources/codegen-resources/service-2.json @@ -211,7 +211,8 @@ {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Returns the list of tags for the specified resource.

    " + "documentation":"

    Returns the list of tags for the specified resource.

    ", + "readonly":true }, "ListUserAssociations":{ "name":"ListUserAssociations", @@ -563,7 +564,7 @@ }, "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "IdentityProviderArn":{ "shape":"Arn", @@ -1039,7 +1040,7 @@ "members":{ "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "IdentityProvider":{ "shape":"IdentityProvider", @@ -1179,6 +1180,10 @@ "SubscriptionEndDate":{ "shape":"String", "documentation":"

    The end date of a subscription.

    " + }, + "LicenseExpirationDate":{ + "shape":"String", + "documentation":"

    The expiration date of the license associated with this subscription, in ISO 8601 UTC format (for example, 2025-03-15T00:00:00Z).

    This field applies only to subscriptions that use license server endpoints, such as Remote Desktop Services (RDS) Subscriber Access License (SAL). It returns null for products that don't use license-based subscriptions.

    " } }, "documentation":"

    A summary of the user-based subscription products for a specific user.

    " @@ -1211,7 +1216,7 @@ }, "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "Settings":{ "shape":"Settings", @@ -1343,7 +1348,7 @@ }, "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "Domain":{ "shape":"String", @@ -1378,7 +1383,7 @@ }, "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "ProductUserArn":{ "shape":"Arn", @@ -1492,7 +1497,7 @@ "IdentityProvider":{"shape":"IdentityProvider"}, "Product":{ "shape":"String", - "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | REMOTE_DESKTOP_SERVICES

    " + "documentation":"

    The name of the user-based subscription product.

    Valid values: VISUAL_STUDIO_ENTERPRISE | VISUAL_STUDIO_PROFESSIONAL | OFFICE_PROFESSIONAL_PLUS | OFFICE_STANDARD | REMOTE_DESKTOP_SERVICES

    " }, "IdentityProviderArn":{ "shape":"Arn", diff --git a/services/lightsail/pom.xml b/services/lightsail/pom.xml index a5285b61d287..ac31329d338b 100644 --- a/services/lightsail/pom.xml +++ b/services/lightsail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lightsail AWS Java SDK :: Services :: Amazon Lightsail diff --git a/services/lightsail/src/main/resources/codegen-resources/customization.config b/services/lightsail/src/main/resources/codegen-resources/customization.config index 229655a6c433..1ad24a1daaea 100644 --- a/services/lightsail/src/main/resources/codegen-resources/customization.config +++ b/services/lightsail/src/main/resources/codegen-resources/customization.config @@ -23,6 +23,5 @@ "getRelationalDatabaseSnapshots", "getRelationalDatabases", "getStaticIps" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/lightsail/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lightsail/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cfcdbebe1227 --- /dev/null +++ b/services/lightsail/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lightsail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lightsail-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lightsail.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lightsail.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lightsail/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lightsail/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5c8ff92e8e1f..000000000000 --- a/services/lightsail/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lightsail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lightsail-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lightsail.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://lightsail.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lightsail/src/main/resources/codegen-resources/service-2.json b/services/lightsail/src/main/resources/codegen-resources/service-2.json index 2f2458a7f3de..f677b3b360f1 100644 --- a/services/lightsail/src/main/resources/codegen-resources/service-2.json +++ b/services/lightsail/src/main/resources/codegen-resources/service-2.json @@ -2133,6 +2133,23 @@ ], "documentation":"

    Gets operations for a specific resource (an instance or a static IP).

    " }, + "GetProfile":{ + "name":"GetProfile", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetProfileRequest"}, + "output":{"shape":"GetProfileResult"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"AccountSetupInProgressException"}, + {"shape":"InvalidInputException"}, + {"shape":"ServiceException"}, + {"shape":"UnauthenticatedException"} + ], + "documentation":"

    Returns information about the profile of the Amazon Lightsail account that makes the request. The response includes the profile type and, for accounts enrolled in the Lightsail partner program, the partner membership details.

    " + }, "GetRegions":{ "name":"GetRegions", "http":{ @@ -5401,6 +5418,18 @@ "viewerMinimumTlsProtocolVersion":{ "shape":"ViewerMinimumTlsProtocolVersionEnum", "documentation":"

    The minimum TLS protocol version for the SSL/TLS certificate.

    " + }, + "enablePrivateOriginAccess":{ + "shape":"boolean", + "documentation":"

    Specifies whether to enable private origin access for the distribution. With private origin access, the distribution can serve objects that aren't publicly accessible from a Lightsail bucket.

    Lightsail grants the distribution permission to read the bucket's objects. Enabling private origin access doesn't change the bucket's access settings, and you can still retrieve publicly accessible objects directly from the bucket's endpoint.

    You can enable private origin access only when the distribution's origin is a Lightsail bucket. If the origin is another resource type, the request fails.

    " + }, + "defaultRootObject":{ + "shape":"string", + "documentation":"

    The object (for example, index.html) that the distribution returns when a viewer requests the root URL of the distribution (/) instead of a specific object. The object that you specify must be available from the origin.

    " + }, + "customErrorResponses":{ + "shape":"DistributionCustomErrorResponseList", + "documentation":"

    An array of objects that describe the custom error responses for the distribution. With a custom error response, you can specify the page to return when the origin responds with a given HTTP error code. You can also specify the HTTP status code to send to the viewer.

    " } } }, @@ -6772,6 +6801,32 @@ "type":"list", "member":{"shape":"DistributionBundle"} }, + "DistributionCustomErrorResponse":{ + "type":"structure", + "members":{ + "errorCode":{ + "shape":"integer", + "documentation":"

    The HTTP error code from the origin that triggers the custom error response (for example, 403 or 404).

    " + }, + "responseCode":{ + "shape":"string", + "documentation":"

    The HTTP status code that the distribution returns to the viewer for the custom error response.

    " + }, + "responsePagePath":{ + "shape":"string", + "documentation":"

    The path to the custom error page that the distribution returns to the viewer (for example, /404.html). The path must begin with a forward slash (/) and reference an object that is available from the origin.

    " + }, + "errorCachingMinTTL":{ + "shape":"long", + "documentation":"

    The minimum time, in seconds, that the distribution caches the custom error response before requesting the object again from the origin. If you don't specify a value, the default is 10 seconds.

    " + } + }, + "documentation":"

    Describes a custom error response for a Lightsail distribution. A custom error response specifies the page that the distribution returns to the viewer. It also specifies the HTTP status code that the distribution sends when the origin responds with a given HTTP error code.

    " + }, + "DistributionCustomErrorResponseList":{ + "type":"list", + "member":{"shape":"DistributionCustomErrorResponse"} + }, "DistributionList":{ "type":"list", "member":{"shape":"LightsailDistribution"} @@ -8411,6 +8466,24 @@ } } }, + "GetProfileRequest":{ + "type":"structure", + "members":{} + }, + "GetProfileResult":{ + "type":"structure", + "required":["profileType"], + "members":{ + "profileType":{ + "shape":"ProfileType", + "documentation":"

    The type of the profile.

    The following profile types are possible:

    • Lightsailor – The account is not enrolled in the Lightsail partner program.

    • LightsailPartner – The account is enrolled in the Lightsail partner program.

    " + }, + "partner":{ + "shape":"PartnerInfo", + "documentation":"

    An object that describes the partner membership of the account, such as the tier of the membership, its status, and when the account was enrolled.

    This parameter is returned only for accounts that have a profileType of LightsailPartner.

    " + } + } + }, "GetRegionsRequest":{ "type":"structure", "members":{ @@ -9705,6 +9778,14 @@ "viewerMinimumTlsProtocolVersion":{ "shape":"string", "documentation":"

    The minimum TLS protocol version that the distribution can use to communicate with viewers.

    " + }, + "defaultRootObject":{ + "shape":"string", + "documentation":"

    The object (for example, index.html) that the distribution returns when a viewer requests the root URL of the distribution (/) instead of a specific object.

    " + }, + "customErrorResponses":{ + "shape":"DistributionCustomErrorResponseList", + "documentation":"

    An array of objects that describe the custom error responses configured for the distribution.

    " } }, "documentation":"

    Describes an Amazon Lightsail content delivery network (CDN) distribution.

    " @@ -10227,6 +10308,8 @@ "FreeStorageSpace", "NetworkReceiveThroughput", "NetworkTransmitThroughput", + "FreeableMemory", + "SwapUsage", "BurstCapacityTime", "BurstCapacityPercentage" ] @@ -10552,7 +10635,8 @@ "UpdateInstanceMetadataOptions", "StartGUISession", "StopGUISession", - "SetupInstanceHttps" + "SetupInstanceHttps", + "GetProfile" ] }, "Origin":{ @@ -10581,6 +10665,10 @@ "ipAddressType":{ "shape":"OriginIpAddressTypeEnum", "documentation":"

    The IP address type that the distribution uses when connecting to the origin.

    The possible values are ipv4 for IPv4 only, ipv6 for IPv6 only, and dualstack for IPv4 and IPv6.

    " + }, + "isPrivateOriginAccessEnabled":{ + "shape":"boolean", + "documentation":"

    Specifies whether private origin access is enabled for the distribution's origin. With private origin access, the distribution can serve objects that aren't publicly accessible from a Lightsail bucket.

    This applies when you set the bucket's getObject access rule to private. It also applies when you set getObject to public but set individual objects to private.

    " } }, "documentation":"

    Describes the origin resource of an Amazon Lightsail content delivery network (CDN) distribution.

    An origin can be a Lightsail instance, bucket, or load balancer. A distribution pulls content from an origin, caches it, and serves it to viewers via a worldwide network of edge servers.

    " @@ -10605,6 +10693,35 @@ "member":{"shape":"NonEmptyString"}, "max":10 }, + "PartnerInfo":{ + "type":"structure", + "required":[ + "enrolledAt", + "status" + ], + "members":{ + "enrolledAt":{ + "shape":"IsoDate", + "documentation":"

    The timestamp when the account was enrolled in the Lightsail partner program.

    " + }, + "tierName":{ + "shape":"TierName", + "documentation":"

    The tier of the partner membership.

    " + }, + "status":{ + "shape":"PartnerStatus", + "documentation":"

    The status of the partner membership.

    The following statuses are possible:

    • Active – The membership is active, and the benefits of the current tier are available to the account.

    • Suspended – The membership is suspended, and the benefits of the tier are not available to the account.

    " + } + }, + "documentation":"

    An object that contains information about the Lightsail partner program membership of an Amazon Lightsail account.

    " + }, + "PartnerStatus":{ + "type":"string", + "enum":[ + "Active", + "Suspended" + ] + }, "PasswordData":{ "type":"structure", "members":{ @@ -10773,6 +10890,13 @@ }, "documentation":"

    Describes a request to configure an Amazon Lightsail container service to access private container image repositories, such as Amazon Elastic Container Registry (Amazon ECR) private repositories.

    For more information, see Configuring access to an Amazon ECR private repository for an Amazon Lightsail container service in the Amazon Lightsail Developer Guide.

    " }, + "ProfileType":{ + "type":"string", + "enum":[ + "Lightsailor", + "LightsailPartner" + ] + }, "PutAlarmRequest":{ "type":"structure", "required":[ @@ -11337,7 +11461,9 @@ "DiskQueueDepth", "FreeStorageSpace", "NetworkReceiveThroughput", - "NetworkTransmitThroughput" + "NetworkTransmitThroughput", + "FreeableMemory", + "SwapUsage" ] }, "RelationalDatabaseParameter":{ @@ -12252,6 +12378,15 @@ } } }, + "TierName":{ + "type":"string", + "enum":[ + "Essential", + "Growth", + "Accelerate", + "Premier" + ] + }, "TimeOfDay":{ "type":"string", "pattern":"^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$" @@ -12502,6 +12637,18 @@ "useDefaultCertificate":{ "shape":"boolean", "documentation":"

    Indicates whether the default SSL/TLS certificate is attached to the distribution. The default value is true. When true, the distribution uses the default domain name such as d111111abcdef8.cloudfront.net.

    Set this value to false to attach a new certificate to the distribution.

    " + }, + "enablePrivateOriginAccess":{ + "shape":"boolean", + "documentation":"

    Specifies whether to enable private origin access for the distribution. With private origin access, the distribution can serve objects that aren't publicly accessible from a Lightsail bucket.

    Lightsail grants the distribution permission to read the bucket's objects. Enabling private origin access doesn't change the bucket's access settings, and you can still retrieve publicly accessible objects directly from the bucket's endpoint.

    When you include this parameter, you must also include the origin parameter with the resource name, even if the origin is not changing.

    You can enable private origin access only when the distribution's origin is a Lightsail bucket. If the origin is another resource type, the request fails.

    " + }, + "defaultRootObject":{ + "shape":"string", + "documentation":"

    The object (for example, index.html) that the distribution returns when a viewer requests the root URL of the distribution (/) instead of a specific object. The object that you specify must be available from the origin.

    " + }, + "customErrorResponses":{ + "shape":"DistributionCustomErrorResponseList", + "documentation":"

    An array of objects that describe the custom error responses for the distribution. With a custom error response, you can specify the page to return when the origin responds with a given HTTP error code. You can also specify the HTTP status code to send to the viewer.

    " } } }, diff --git a/services/location/pom.xml b/services/location/pom.xml index 1ebc71dab194..01d50b503a80 100644 --- a/services/location/pom.xml +++ b/services/location/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT location AWS Java SDK :: Services :: Location diff --git a/services/location/src/main/resources/codegen-resources/customization.config b/services/location/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/location/src/main/resources/codegen-resources/customization.config +++ b/services/location/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/location/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/location/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f74597449106 --- /dev/null +++ b/services/location/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://geo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/location/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/location/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2cd25b7ab460..000000000000 --- a/services/location/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://geo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://geo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/lookoutequipment/pom.xml b/services/lookoutequipment/pom.xml index 5a72582ece0f..8fbaaba7a6b3 100644 --- a/services/lookoutequipment/pom.xml +++ b/services/lookoutequipment/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT lookoutequipment AWS Java SDK :: Services :: Lookout Equipment diff --git a/services/lookoutequipment/src/main/resources/codegen-resources/customization.config b/services/lookoutequipment/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/lookoutequipment/src/main/resources/codegen-resources/customization.config +++ b/services/lookoutequipment/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..da2d8c828152 --- /dev/null +++ b/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lookoutequipment-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lookoutequipment-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lookoutequipment.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://lookoutequipment.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5549a83b17c8..000000000000 --- a/services/lookoutequipment/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lookoutequipment-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lookoutequipment-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://lookoutequipment.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://lookoutequipment.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/m2/pom.xml b/services/m2/pom.xml index 405b279c2a3f..316a6590addb 100644 --- a/services/m2/pom.xml +++ b/services/m2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT m2 AWS Java SDK :: Services :: M2 diff --git a/services/m2/src/main/resources/codegen-resources/customization.config b/services/m2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/m2/src/main/resources/codegen-resources/customization.config +++ b/services/m2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/m2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/m2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bf5c0a23cb87 --- /dev/null +++ b/services/m2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://m2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://m2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://m2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://m2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/m2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/m2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 885d0c333b70..000000000000 --- a/services/m2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://m2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://m2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://m2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://m2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/machinelearning/pom.xml b/services/machinelearning/pom.xml index eaf9cc95ceb0..c1da5cfcb7fd 100644 --- a/services/machinelearning/pom.xml +++ b/services/machinelearning/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT machinelearning AWS Java SDK :: Services :: Amazon Machine Learning diff --git a/services/machinelearning/src/main/resources/codegen-resources/customization.config b/services/machinelearning/src/main/resources/codegen-resources/customization.config index 4798c2627d0c..e3c6e5f92019 100644 --- a/services/machinelearning/src/main/resources/codegen-resources/customization.config +++ b/services/machinelearning/src/main/resources/codegen-resources/customization.config @@ -8,6 +8,5 @@ "interceptors": [ "software.amazon.awssdk.services.machinelearning.internal.PredictEndpointInterceptor", "software.amazon.awssdk.services.machinelearning.internal.RandomIdInterceptor" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/machinelearning/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/machinelearning/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d56d1badc30d --- /dev/null +++ b/services/machinelearning/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://machinelearning-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://machinelearning-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://machinelearning.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://machinelearning.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/machinelearning/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/machinelearning/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9d5e59c4099f..000000000000 --- a/services/machinelearning/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://machinelearning-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://machinelearning-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://machinelearning.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://machinelearning.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/macie2/pom.xml b/services/macie2/pom.xml index 33c1f9cfb27e..9c3ee5167e7e 100644 --- a/services/macie2/pom.xml +++ b/services/macie2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT macie2 AWS Java SDK :: Services :: Macie2 diff --git a/services/macie2/src/main/resources/codegen-resources/customization.config b/services/macie2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/macie2/src/main/resources/codegen-resources/customization.config +++ b/services/macie2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/macie2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/macie2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7c6b3ad8699e --- /dev/null +++ b/services/macie2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://macie2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://macie2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://macie2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://macie2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/macie2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/macie2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fc24ee900b9d..000000000000 --- a/services/macie2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://macie2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://macie2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://macie2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://macie2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mailmanager/pom.xml b/services/mailmanager/pom.xml index ceeb2af6e0c5..567a11411cab 100644 --- a/services/mailmanager/pom.xml +++ b/services/mailmanager/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mailmanager AWS Java SDK :: Services :: Mail Manager diff --git a/services/mailmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mailmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c473a1a638b1 --- /dev/null +++ b/services/mailmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mail-manager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mail-manager-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mail-manager.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mail-manager.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mailmanager/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mailmanager/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5452c97f9491..000000000000 --- a/services/mailmanager/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mail-manager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mail-manager-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mail-manager.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mail-manager.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/managedblockchain/pom.xml b/services/managedblockchain/pom.xml index e9e393e55e60..36f5db8177cb 100644 --- a/services/managedblockchain/pom.xml +++ b/services/managedblockchain/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT managedblockchain AWS Java SDK :: Services :: ManagedBlockchain diff --git a/services/managedblockchain/src/main/resources/codegen-resources/customization.config b/services/managedblockchain/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/managedblockchain/src/main/resources/codegen-resources/customization.config +++ b/services/managedblockchain/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/managedblockchain/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/managedblockchain/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e05ddbaf352a --- /dev/null +++ b/services/managedblockchain/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/managedblockchain/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/managedblockchain/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index be123cb13d70..000000000000 --- a/services/managedblockchain/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/managedblockchainquery/pom.xml b/services/managedblockchainquery/pom.xml index 5c4c6796f1eb..82cd3aad844a 100644 --- a/services/managedblockchainquery/pom.xml +++ b/services/managedblockchainquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT managedblockchainquery AWS Java SDK :: Services :: Managed Blockchain Query diff --git a/services/managedblockchainquery/src/main/resources/codegen-resources/customization.config b/services/managedblockchainquery/src/main/resources/codegen-resources/customization.config index c2457f7c37ab..0db3279e44b0 100644 --- a/services/managedblockchainquery/src/main/resources/codegen-resources/customization.config +++ b/services/managedblockchainquery/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true - } diff --git a/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6212eab713ff --- /dev/null +++ b/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-query-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-query-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-query.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://managedblockchain-query.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 70448e92f795..000000000000 --- a/services/managedblockchainquery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-query-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-query-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-query.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://managedblockchain-query.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplaceagreement/pom.xml b/services/marketplaceagreement/pom.xml index 1506e6d3c1a2..4d1cc5173896 100644 --- a/services/marketplaceagreement/pom.xml +++ b/services/marketplaceagreement/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplaceagreement AWS Java SDK :: Services :: Marketplace Agreement diff --git a/services/marketplaceagreement/src/main/resources/codegen-resources/customization.config b/services/marketplaceagreement/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/marketplaceagreement/src/main/resources/codegen-resources/customization.config +++ b/services/marketplaceagreement/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0b8080209adb --- /dev/null +++ b/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agreement-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agreement-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agreement-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://agreement-marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9380a0e87e9e..000000000000 --- a/services/marketplaceagreement/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://agreement-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://agreement-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://agreement-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://agreement-marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplaceagreement/src/main/resources/codegen-resources/service-2.json b/services/marketplaceagreement/src/main/resources/codegen-resources/service-2.json index b537a9f77ad4..a2fcd2a49aa3 100644 --- a/services/marketplaceagreement/src/main/resources/codegen-resources/service-2.json +++ b/services/marketplaceagreement/src/main/resources/codegen-resources/service-2.json @@ -395,7 +395,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Searches across all agreements that a proposer or an acceptor has in AWS Marketplace. The search returns a list of agreements with basic agreement information.

    The following filter combinations are supported when the PartyType is Proposer:

    • AgreementType

    • AgreementType + EndTime

    • AgreementType + ResourceType

    • AgreementType + ResourceType + EndTime

    • AgreementType + ResourceType + Status

    • AgreementType + ResourceType + Status + EndTime

    • AgreementType + ResourceIdentifier

    • AgreementType + ResourceIdentifier + EndTime

    • AgreementType + ResourceIdentifier + Status

    • AgreementType + ResourceIdentifier + Status + EndTime

    • AgreementType + AcceptorAccountId

    • AgreementType + AcceptorAccountId + EndTime

    • AgreementType + AcceptorAccountId + Status

    • AgreementType + AcceptorAccountId + Status + EndTime

    • AgreementType + AcceptorAccountId + OfferId

    • AgreementType + AcceptorAccountId + OfferId + Status

    • AgreementType + AcceptorAccountId + OfferId + EndTime

    • AgreementType + AcceptorAccountId + OfferId + Status + EndTime

    • AgreementType + AcceptorAccountId + ResourceIdentifier

    • AgreementType + AcceptorAccountId + ResourceIdentifier + Status

    • AgreementType + AcceptorAccountId + ResourceIdentifier + EndTime

    • AgreementType + AcceptorAccountId + ResourceIdentifier + Status + EndTime

    • AgreementType + AcceptorAccountId + ResourceType

    • AgreementType + AcceptorAccountId + ResourceType + EndTime

    • AgreementType + AcceptorAccountId + ResourceType + Status

    • AgreementType + AcceptorAccountId + ResourceType + Status + EndTime

    • AgreementType + Status

    • AgreementType + Status + EndTime

    • AgreementType + OfferId

    • AgreementType + OfferId + EndTime

    • AgreementType + OfferId + Status

    • AgreementType + OfferId + Status + EndTime

    • AgreementType + OfferSetId

    • AgreementType + OfferSetId + EndTime

    • AgreementType + OfferSetId + Status

    • AgreementType + OfferSetId + Status + EndTime

    To filter by EndTime, you can use BeforeEndTime and/or AfterEndTime. Only EndTime is supported for sorting.

    The following filter combinations are supported when the PartyType is Acceptor:

    • AgreementType

    • AgreementType + Status

    • AgreementType + EndTime

    • AgreementType + Status + EndTime

    • AgreementType + ResourceIdentifier

    • AgreementType + ResourceIdentifier + EndTime

    • AgreementType + ResourceIdentifier + Status

    • AgreementType + ResourceIdentifier + Status + EndTime

    • AgreementType + ResourceType

    • AgreementType + ResourceType + EndTime

    • AgreementType + OfferId

    • AgreementType + OfferId + EndTime

    • AgreementType + OfferId + Status

    • AgreementType + OfferId + Status + EndTime

    • AgreementType + OfferSetId

    • AgreementType + OfferSetId + EndTime

    • AgreementType + OfferSetId + Status

    • AgreementType + OfferSetId + Status + EndTime

    " + "documentation":"

    Searches across all agreements that a proposer or an acceptor has in AWS Marketplace. The search returns a list of agreements with basic agreement information.

    " }, "SendAgreementCancellationRequest":{ "name":"SendAgreementCancellationRequest", @@ -607,7 +607,7 @@ }, "renewalTerm":{ "shape":"RenewalTerm", - "documentation":"

    Defines that on graceful expiration of the agreement (when the agreement ends on its pre-defined end date), a new agreement will be created using the accepted terms on the existing agreement. In other words, the agreement will be renewed. Presence of RenewalTerm in the offer document means that auto-renewal is allowed. Buyers will have the option to accept or decline auto-renewal at the offer acceptance/agreement creation. Buyers can also change this flag from True to False or False to True at anytime during the agreement's lifecycle.

    " + "documentation":"

    Defines that on graceful expiration of the agreement (when the agreement ends on its pre-defined end date), a new agreement will be created using the accepted terms on the existing agreement. In other words, the agreement will be renewed. Presence of RenewalTerm in the offer document means that auto-renewal is allowed. The acceptor will have the option to accept or decline auto-renewal at the offer acceptance/agreement creation. The acceptor can also change this flag from True to False or False to True, within the limits set by LockoutPeriod and MaxRenewals. Setting the flag to True doesn't by itself guarantee that the agreement renews, because the proposer can also opt out.

    " }, "usageBasedPricingTerm":{ "shape":"UsageBasedPricingTerm", @@ -644,6 +644,10 @@ "variablePaymentTerm":{ "shape":"VariablePaymentTerm", "documentation":"

    Defines a payment model where sellers can submit variable payment requests up to a maximum charge amount, with configurable approval strategies and expiration timelines.

    " + }, + "netPaymentTerm":{ + "shape":"NetPaymentTerm", + "documentation":"

    Defines the net payment due period for the agreement, specifying when payment is due after an invoice is issued.

    " } }, "documentation":"

    A subset of terms proposed by the proposer, which have been accepted by the acceptor as part of agreement creation.

    ", @@ -945,6 +949,10 @@ "shape":"Timestamp", "documentation":"

    The date and time when the agreement ends. The field is null for pay-as-you-go agreements, which don’t have end dates.

    " }, + "lastUpdateTime":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the agreement was last updated. An agreement is updated when any of its attributes or accepted terms change. Amendments, renewals, and a party changing whether the agreement renews are all examples.

    Use the BeforeLastUpdateTime and AfterLastUpdateTime filters to search on this value, and LastUpdateTime as the SortBy value to sort by it. Sorting by LastUpdateTime is supported only when PartyType is Proposer.

    " + }, "agreementType":{ "shape":"AgreementType", "documentation":"

    The type of agreement.

    " @@ -968,6 +976,18 @@ "entitlements":{ "shape":"EntitlementList", "documentation":"

    A list of entitlements associated with the agreement.

    " + }, + "initialAgreementId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the very first agreement in a chain of related agreements, such as renewals or replacements. It stays the same across all agreements in that chain, which lets you trace an agreement back to the original. You can also use it as the InitialAgreementId filter value to return every agreement in the same chain.

    " + }, + "endTimeBehaviorType":{ + "shape":"EndTimeBehaviorType", + "documentation":"

    The behavior of the agreement when it reaches its end date. The field is null for agreements that have no end date, because those agreements never reach an end time.

    Types include:

    • RENEW – A new agreement is created from the accepted terms of this agreement.

    • REPLACE – A new agreement is created from a different offer than the one this agreement was created from. This happens, for example, when a private offer reaches its end date and the acceptor transitions to the public offer for the product.

    • EXPIRE – The agreement ends and isn't renewed or replaced.

    " + }, + "endTimeBehaviorReasonCode":{ + "shape":"EndTimeBehaviorReasonCode", + "documentation":"

    The reason why the agreement doesn't renew at its end date. The field is null when the agreement renews.

    More than one reason can apply to the same agreement. When that happens, the operation returns only one reason code, and PROPOSER_RENEW_OPTED_OUT takes precedence over all others.

    The EnableAutoRenew field reflects only the acceptor's preference, and doesn't reflect the other reasons an agreement might not renew.

    Reason codes include:

    • PROPOSER_RENEW_OPTED_OUT – The proposer opted out of renewing the agreement.

    • ACCEPTOR_RENEW_OPTED_OUT – The acceptor opted out of renewing the agreement.

    • NO_RENEWAL_TERM – The accepted terms of the agreement don't include a renewal term, which is required for an agreement to renew.

    • RENEWAL_LIMIT_EXHAUSTED – The agreement reached the maximum number of renewals allowed by its renewal term.

    " } }, "documentation":"

    A summary of the agreement, including top-level attributes (for example, the agreement ID, proposer, and acceptor).

    " @@ -1417,6 +1437,12 @@ "min":1, "pattern":"ch-[a-zA-Z0-9]+" }, + "ChargePercentage":{ + "type":"string", + "max":6, + "min":1, + "pattern":"(100(\\.0{1,2})?|[1-9]\\d?(\\.\\d{1,2})?|0\\.(0[1-9]|[1-9]\\d?))" + }, "ChargeRevision":{ "type":"long", "box":true, @@ -1622,6 +1648,12 @@ "min":3, "pattern":"[A-Z]+" }, + "DayDuration":{ + "type":"string", + "max":9, + "min":3, + "pattern":"P([1-9]\\d{0,6}D)" + }, "DescribeAgreementInput":{ "type":"structure", "required":["agreementId"], @@ -1673,7 +1705,15 @@ }, "status":{ "shape":"AgreementStatus", - "documentation":"

    The current status of the agreement.

    Statuses include:

    • ACTIVE – The terms of the agreement are active.

    • ARCHIVED – The agreement ended without a specified reason.

    • CANCELLED – The acceptor ended the agreement before the defined end date.

    • EXPIRED – The agreement ended on the defined end date.

    • RENEWED – The agreement was renewed into a new agreement (for example, an auto-renewal).

    • REPLACED – The agreement was replaced using an agreement replacement offer.

    • TERMINATED – The agreement ended before the defined end date because of an AWS termination (for example, a payment failure).

    " + "documentation":"

    The current status of the agreement.

    Statuses include:

    • ACTIVE – The terms of the agreement are active.

    • CANCELLED – The acceptor ended the agreement before the defined end date.

    • EXPIRED – The agreement ended on the defined end date.

    • RENEWED – The agreement was renewed into a new agreement (for example, an auto-renewal).

    • REPLACED – The agreement was replaced using an agreement replacement offer.

    • TERMINATED – The agreement ended before the defined end date because of an AWS termination (for example, a payment failure).

    " + }, + "initialAgreementId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the very first agreement in a chain of related agreements, such as renewals or replacements. It stays the same across all agreements in that chain, which lets you trace an agreement back to the original. When an agreement isn't derived from another agreement, its InitialAgreementId is its own AgreementId.

    " + }, + "endTimeBehavior":{ + "shape":"EndTimeBehavior", + "documentation":"

    The behavior of the agreement when it reaches its end date. For example, whether the agreement renews, and if it doesn't, the reason why.

    This field is present for every active agreement that has an end date. It is not present for an agreement that has no end date, because such an agreement never reaches an end time. Pay-as-you-go agreements are the most common example. It is also not present for an agreement that is no longer active.

    " } } }, @@ -1722,6 +1762,42 @@ "type":"list", "member":{"shape":"DocumentItem"} }, + "EndTimeBehavior":{ + "type":"structure", + "required":["type"], + "members":{ + "type":{ + "shape":"EndTimeBehaviorType", + "documentation":"

    The behavior of the agreement when it reaches its end date.

    Types include:

    • RENEW – A new agreement is created from the accepted terms of this agreement.

    • REPLACE – A new agreement is created from a different offer than the one this agreement was created from. This happens, for example, when a private offer reaches its end date and the acceptor transitions to the public offer for the product.

    • EXPIRE – The agreement ends and isn't renewed or replaced.

    " + }, + "reasonCode":{ + "shape":"EndTimeBehaviorReasonCode", + "documentation":"

    The reason why the agreement doesn't renew at its end date. The field is null when the agreement renews.

    More than one reason can apply to the same agreement. When that happens, the operation returns only one reason code, and PROPOSER_RENEW_OPTED_OUT takes precedence over all others.

    The EnableAutoRenew field reflects only the acceptor's preference, and doesn't reflect the other reasons an agreement might not renew.

    Reason codes include:

    • PROPOSER_RENEW_OPTED_OUT – The proposer opted out of renewing the agreement.

    • ACCEPTOR_RENEW_OPTED_OUT – The acceptor opted out of renewing the agreement.

    • NO_RENEWAL_TERM – The accepted terms of the agreement don't include a renewal term, which is required for an agreement to renew.

    • RENEWAL_LIMIT_EXHAUSTED – The agreement reached the maximum number of renewals allowed by its renewal term.

    " + }, + "renewalSummary":{ + "shape":"RenewalSummary", + "documentation":"

    The details of the renewal that applies at the end date of the agreement. This field is present when Type is RENEW. It is also present when ReasonCode is PROPOSER_RENEW_OPTED_OUT or ACCEPTOR_RENEW_OPTED_OUT. In those cases, it identifies the offer that the agreement would otherwise have renewed from. The field is null in all other cases.

    " + } + }, + "documentation":"

    The behavior of an agreement when it reaches its end date. For example, whether the agreement renews, and if it doesn't, the reason why.

    " + }, + "EndTimeBehaviorReasonCode":{ + "type":"string", + "enum":[ + "PROPOSER_RENEW_OPTED_OUT", + "ACCEPTOR_RENEW_OPTED_OUT", + "NO_RENEWAL_TERM", + "RENEWAL_LIMIT_EXHAUSTED" + ] + }, + "EndTimeBehaviorType":{ + "type":"string", + "enum":[ + "RENEW", + "REPLACE", + "EXPIRE" + ] + }, "Entitlement":{ "type":"structure", "members":{ @@ -1837,9 +1913,9 @@ }, "FilterValue":{ "type":"string", - "max":64, + "max":256, "min":1, - "pattern":"[A-Za-z0-9+:_-]+" + "pattern":"[A-Za-z0-9.,+:/_-]+" }, "FilterValueList":{ "type":"list", @@ -1847,6 +1923,16 @@ "max":1, "min":1 }, + "FixedPercentage":{ + "type":"structure", + "members":{ + "value":{ + "shape":"PriceIncreasePercentage", + "documentation":"

    The percentage by which the price increases at each renewal, from 0.00 to 100.00 with up to two decimal places. A value of 0.00 means that the agreement renews at the same price.

    " + } + }, + "documentation":"

    A fixed price increase that is applied each time the agreement renews.

    " + }, "FixedUpfrontPricingTerm":{ "type":"structure", "members":{ @@ -2564,6 +2650,24 @@ "max":50, "min":1 }, + "NetPaymentTerm":{ + "type":"structure", + "members":{ + "type":{ + "shape":"UnversionedTermType", + "documentation":"

    Type of the term being updated.

    " + }, + "id":{ + "shape":"TermId", + "documentation":"

    The unique identifier for the term.

    " + }, + "paymentDuePeriod":{ + "shape":"BoundedString", + "documentation":"

    The duration after an invoice is issued within which the payment is due. The duration is represented in the ISO 8601 format (for example, P30D for 30 days or P60D for 60 days).

    " + } + }, + "documentation":"

    Defines the net payment due period for the agreement, specifying when payment is due after an invoice is issued.

    " + }, "NextToken":{ "type":"string", "max":8192, @@ -2580,6 +2684,12 @@ "type":"string", "pattern":"\\S{1,50}" }, + "OffsetDuration":{ + "type":"string", + "max":6, + "min":3, + "pattern":"P(\\d{1,4}M|\\d{1,4}D)" + }, "PartyType":{ "type":"string", "max":32, @@ -2674,6 +2784,30 @@ "type":"list", "member":{"shape":"PaymentRequestSummary"} }, + "PaymentScheduleEntry":{ + "type":"structure", + "members":{ + "chargeDateOffset":{ + "shape":"OffsetDuration", + "documentation":"

    The time between the start date of the renewed agreement and the date this installment is charged. The duration is represented in the ISO 8601 format in either whole months or whole days (for example, P1M for 1 month or P30D for 30 days). All installments in a schedule use the same unit.

    " + }, + "chargePercentage":{ + "shape":"ChargePercentage", + "documentation":"

    The percentage of the total contract value of the renewed agreement that is charged in this installment. Valid values range from 0.01 to 100.00, with up to two decimal places.

    " + }, + "dayOfMonth":{ + "shape":"PaymentScheduleEntryDayOfMonthInteger", + "documentation":"

    The day of the month on which this installment is charged, from 1 to 31. Use this field to anchor the charge to a specific calendar day within the month identified by ChargeDateOffset. This field is supported only when ChargeDateOffset is expressed in months.

    " + } + }, + "documentation":"

    A single installment in a payment schedule template. Because the start date of the renewed agreement isn't known when the offer is created, the charge date of each installment is expressed as an offset from that start date rather than as an absolute date.

    " + }, + "PaymentScheduleEntryDayOfMonthInteger":{ + "type":"integer", + "box":true, + "max":31, + "min":1 + }, "PaymentScheduleTerm":{ "type":"structure", "members":{ @@ -2696,6 +2830,40 @@ }, "documentation":"

    Defines an installment-based pricing model where customers are charged a fixed price on different dates during the agreement validity period. This is used most commonly for flexible payment schedule pricing.

    " }, + "PaymentScheduleTermTemplate":{ + "type":"structure", + "members":{ + "schedule":{ + "shape":"PaymentScheduleTermTemplateScheduleList", + "documentation":"

    The installments that make up the payment schedule of the renewed agreement. The ChargePercentage values of all installments add up to 100.

    " + } + }, + "documentation":"

    Defines the payment schedule that is applied to the renewed agreement.

    " + }, + "PaymentScheduleTermTemplateScheduleList":{ + "type":"list", + "member":{"shape":"PaymentScheduleEntry"}, + "max":200, + "min":1 + }, + "PercentageRange":{ + "type":"structure", + "members":{ + "minValue":{ + "shape":"PriceIncreasePercentage", + "documentation":"

    The lowest percentage that the proposer can choose, from 0.00 to 100.00 with up to two decimal places.

    " + }, + "maxValue":{ + "shape":"PriceIncreasePercentage", + "documentation":"

    The highest percentage that the proposer can choose, from 0.00 to 100.00 with up to two decimal places.

    " + }, + "defaultValue":{ + "shape":"PriceIncreasePercentage", + "documentation":"

    The percentage that is applied if the proposer doesn't choose a value before the adjustment deadline. Valid values range from 0.00 to 100.00, with up to two decimal places.

    " + } + }, + "documentation":"

    A range of price increase percentages that the proposer can choose from before the adjustment deadline of the agreement.

    MinValue will be less than MaxValue, and DefaultValue will fall within the range. When the proposer authorizes a single percentage instead of a range, PriceIncrease is a FixedPercentage rather than a PercentageRange.

    " + }, "PositiveAmountUpto8Decimals":{ "type":"string", "pattern":"[0-9]*(\\.[0-9]{0,8})?" @@ -2705,6 +2873,27 @@ "box":true, "min":1 }, + "PriceIncrease":{ + "type":"structure", + "members":{ + "fixedPercentage":{ + "shape":"FixedPercentage", + "documentation":"

    A fixed price increase percentage that is applied at each renewal.

    " + }, + "percentageRange":{ + "shape":"PercentageRange", + "documentation":"

    A range of price increase percentages that the proposer can choose from before the adjustment deadline of the agreement.

    " + } + }, + "documentation":"

    The price increase that is applied each time the agreement renews. Exactly one of the following fields is set.

    ", + "union":true + }, + "PriceIncreasePercentage":{ + "type":"string", + "max":6, + "min":1, + "pattern":"(100(\\.0{1,2})?|[1-9]\\d?(\\.\\d{1,2})?|0(\\.\\d{1,2})?)" + }, "PricingCurrencyAmount":{ "type":"structure", "members":{ @@ -2959,6 +3148,16 @@ } } }, + "RenewalSummary":{ + "type":"structure", + "members":{ + "offerId":{ + "shape":"OfferId", + "documentation":"

    The unique identifier of the offer that provides the terms for the next renewal cycle. For most renewals, this is the same offer that the agreement was created from.

    " + } + }, + "documentation":"

    The details of the renewal that applies at the end date of an agreement.

    " + }, "RenewalTerm":{ "type":"structure", "members":{ @@ -2973,9 +3172,29 @@ "configuration":{ "shape":"RenewalTermConfiguration", "documentation":"

    Additional parameters specified by the acceptor while accepting the term.

    " + }, + "lockoutPeriod":{ + "shape":"DayDuration", + "documentation":"

    The renewal decision deadline, measured back from the end date of the agreement. This is the last day either party can opt in to or opt out of the renewal. The duration is represented in the ISO 8601 format in whole days (for example, P30D for 30 days or P60D for 60 days).

    The field is null when no renewal decision deadline is set. In that case, either party can change the auto-renewal decision up to the end date of the agreement.

    " + }, + "maxRenewals":{ + "shape":"RenewalTermMaxRenewalsInteger", + "documentation":"

    The maximum number of times the agreement can be renewed. The field is null when the number of renewals is unlimited.

    After the agreement reaches this limit, it expires on its end date instead of renewing.

    " + }, + "adjustmentDeadline":{ + "shape":"DayDuration", + "documentation":"

    The date by which the proposer must finalize the price increase for the next renewal, measured back from the end date of the agreement. The duration is represented in the ISO 8601 format in whole days (for example, P30D for 30 days or P60D for 60 days).

    This field applies only when PriceIncrease is a PercentageRange. The field is null when PriceIncrease is a FixedPercentage, because the price increase is already fixed and there is nothing for the proposer to finalize. If the proposer doesn't finalize a value by the adjustment deadline, the DefaultValue of the range applies.

    AdjustmentDeadline must be greater than LockoutPeriod.

    " + }, + "priceIncrease":{ + "shape":"PriceIncrease", + "documentation":"

    The price increase that is applied each time the agreement renews. The field is null when the price doesn't change at renewal.

    " + }, + "termTemplates":{ + "shape":"RenewalTermTermTemplatesList", + "documentation":"

    Defines how specific terms change each time the agreement renews. The field is null when no terms change at renewal.

    " } }, - "documentation":"

    Defines that on graceful expiration of the agreement (when the agreement ends on its pre-defined end date), a new agreement will be created using the accepted terms on the existing agreement. In other words, the agreement will be renewed. The presence of RenewalTerm in the offer document means that auto-renewal is allowed. Buyers will have the option to accept or decline auto-renewal at the offer acceptance/agreement creation. Buyers can also change this flag from True to False or False to True at anytime during the agreement's lifecycle.

    " + "documentation":"

    Defines that on graceful expiration of the agreement (when the agreement ends on its pre-defined end date), a new agreement will be created using the accepted terms on the existing agreement. In other words, the agreement will be renewed. Presence of RenewalTerm in the offer document means that auto-renewal is allowed. The acceptor will have the option to accept or decline auto-renewal at the offer acceptance/agreement creation. The acceptor can also change this flag from True to False or False to True, within the limits set by LockoutPeriod and MaxRenewals. Setting the flag to True doesn't by itself guarantee that the agreement renews, because the proposer can also opt out.

    " }, "RenewalTermConfiguration":{ "type":"structure", @@ -2983,11 +3202,22 @@ "members":{ "enableAutoRenew":{ "shape":"Boolean", - "documentation":"

    Defines whether the acceptor has chosen to auto-renew the agreement at the end of its lifecycle. Can be set to True or False.

    " + "documentation":"

    Defines whether the acceptor has chosen to auto-renew the agreement when it reaches its end date. Can be set to True or False. The acceptor can change this value within the limits set by LockoutPeriod and MaxRenewals.

    " } }, "documentation":"

    Additional parameters specified by the acceptor while accepting the term.

    " }, + "RenewalTermMaxRenewalsInteger":{ + "type":"integer", + "box":true, + "min":1 + }, + "RenewalTermTermTemplatesList":{ + "type":"list", + "member":{"shape":"TermTemplate"}, + "max":10, + "min":1 + }, "RequestId":{ "type":"string", "max":128, @@ -3112,11 +3342,11 @@ }, "filters":{ "shape":"FilterList", - "documentation":"

    The filter name and value pair used to return a specific list of results.

    The following filters are supported:

    • ResourceIdentifier – The unique identifier of the resource.

    • ResourceType – Type of the resource, which is the product (AmiProduct, ContainerProduct, SaaSProduct, ProfessionalServicesProduct, or MachineLearningProduct).

    • PartyType – The party type of the caller. Use Proposer or Acceptor.

    • AcceptorAccountId – The AWS account ID of the party accepting the agreement terms.

    • OfferId – The unique identifier of the offer in which the terms are registered in the agreement token.

    • Status – The current status of the agreement. Values include ACTIVE, ARCHIVED, CANCELLED, EXPIRED, RENEWED, REPLACED, and TERMINATED.

    • BeforeEndTime – A date used to filter agreements with a date before the endTime of an agreement.

    • AfterEndTime – A date used to filter agreements with a date after the endTime of an agreement.

    • AgreementType – The type of agreement. Supported value includes PurchaseAgreement.

    • OfferSetId – A unique identifier for the offer set containing this offer. All agreements created from offers in this set include this identifier as context.

    " + "documentation":"

    The filter name and value pair used to return a specific list of results.

    The following filters are supported:

    • ResourceIdentifier – The unique identifier of the resource.

    • ResourceType – Type of the resource, which is the product (AmiProduct, ContainerProduct, SaaSProduct, ProfessionalServicesProduct, or MachineLearningProduct).

    • PartyType – The party type of the caller. Use Proposer or Acceptor.

    • AcceptorAccountId – The AWS account ID of the party accepting the agreement terms.

    • OfferId – The unique identifier of the offer in which the terms are registered in the agreement token.

    • Status – The current status of the agreement. Values include ACTIVE, CANCELLED, EXPIRED, RENEWED, REPLACED, and TERMINATED.

    • BeforeEndTime – A date used to filter agreements with a date before the endTime of an agreement.

    • AfterEndTime – A date used to filter agreements with a date after the endTime of an agreement.

    • BeforeStartTime – A date used to filter agreements with a date before the startTime of an agreement.

    • AfterStartTime – A date used to filter agreements with a date after the startTime of an agreement.

    • BeforeLastUpdateTime – A date used to filter agreements with a date before the lastUpdateTime of an agreement.

    • AfterLastUpdateTime – A date used to filter agreements with a date after the lastUpdateTime of an agreement.

    • AgreementType – The type of agreement. Supported value includes PurchaseAgreement.

    • OfferSetId – A unique identifier for the offer set containing this offer. All agreements created from offers in this set include this identifier as context.

    • EndTimeBehaviorType – What happens to the agreement when it reaches its end date. Values include RENEW, REPLACE, and EXPIRE.

    • EndTimeBehaviorReasonCode – The reason why the agreement doesn't renew at its end date. Values include PROPOSER_RENEW_OPTED_OUT, ACCEPTOR_RENEW_OPTED_OUT, NO_RENEWAL_TERM, and RENEWAL_LIMIT_EXHAUSTED.

    • InitialAgreementId – The unique identifier of the very first agreement in a chain of related agreements. Use this filter to return every agreement in the same chain.

    • LicenseArn – The Amazon Resource Name (ARN) of the AWS License Manager license associated with an entitlement granted by the agreement.

    A proposer can use any combination of the preceding filters along with AgreementType, which is required.

    The following filter combinations are supported when the PartyType is Acceptor:

    • AgreementType

    • AgreementType + Status

    • AgreementType + EndTime

    • AgreementType + Status + EndTime

    • AgreementType + ResourceIdentifier

    • AgreementType + ResourceIdentifier + EndTime

    • AgreementType + ResourceIdentifier + Status

    • AgreementType + ResourceIdentifier + Status + EndTime

    • AgreementType + ResourceType

    • AgreementType + ResourceType + EndTime

    • AgreementType + OfferId

    • AgreementType + OfferId + EndTime

    • AgreementType + OfferId + Status

    • AgreementType + OfferId + Status + EndTime

    • AgreementType + OfferSetId

    • AgreementType + OfferSetId + EndTime

    • AgreementType + OfferSetId + Status

    • AgreementType + OfferSetId + Status + EndTime

    To filter by EndTime, you can use BeforeEndTime, AfterEndTime, or both.

    " }, "sort":{ "shape":"Sort", - "documentation":"

    An object that contains the SortBy and SortOrder attributes. Only EndTime is supported for SearchAgreements. The default sort is EndTime descending.

    " + "documentation":"

    An object that contains the SortBy and SortOrder attributes. For SearchAgreements, SortBy supports EndTime for both party types, and StartTime and LastUpdateTime only when PartyType is Proposer. The default SortBy value is EndTime.

    " }, "maxResults":{ "shape":"MaxResults", @@ -3323,11 +3553,11 @@ "members":{ "sortBy":{ "shape":"SortBy", - "documentation":"

    The attribute on which the data is grouped, which can be by StartTime and EndTime. The default value is EndTime.

    " + "documentation":"

    The attribute on which the data is grouped, which can be EndTime, StartTime, or LastUpdateTime. StartTime and LastUpdateTime are supported only when PartyType is Proposer. The default value is EndTime.

    " }, "sortOrder":{ "shape":"SortOrder", - "documentation":"

    The sorting order, which can be ASCENDING or DESCENDING. The default value is DESCENDING.

    " + "documentation":"

    The sorting order, which can be ASCENDING or DESCENDING. The default value is ASCENDING.

    " } }, "documentation":"

    An object that contains the SortBy and SortOrder attributes.

    " @@ -3409,6 +3639,17 @@ "min":1, "pattern":"[A-Za-z0-9+=;,.@\\-_]+" }, + "TermTemplate":{ + "type":"structure", + "members":{ + "paymentScheduleTermTemplate":{ + "shape":"PaymentScheduleTermTemplate", + "documentation":"

    Defines the payment schedule that is applied to the renewed agreement.

    " + } + }, + "documentation":"

    Defines how a specific type of term changes each time the agreement renews. Exactly one of the following fields is set.

    ", + "union":true + }, "ThrottlingException":{ "type":"structure", "members":{ diff --git a/services/marketplacecatalog/pom.xml b/services/marketplacecatalog/pom.xml index 1c62f97e0db8..7a836d03719c 100644 --- a/services/marketplacecatalog/pom.xml +++ b/services/marketplacecatalog/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacecatalog AWS Java SDK :: Services :: Marketplace Catalog diff --git a/services/marketplacecatalog/src/main/resources/codegen-resources/customization.config b/services/marketplacecatalog/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/marketplacecatalog/src/main/resources/codegen-resources/customization.config +++ b/services/marketplacecatalog/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..de89eaa8c150 --- /dev/null +++ b/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,206 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://catalog-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://catalog.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://catalog.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://catalog.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://catalog.marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABQAAAAcF9eELAAAABgX14QQAAAAIAAAABwX14QkF9eEKAAAABAAAAAsAAAAKAAAABQX14QYF9eEIAAAABQAAAAwF9eEHAAAABwX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 35e04c05784d..000000000000 --- a/services/marketplacecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,381 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://catalog-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://catalog.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://catalog.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://catalog.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://catalog.marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplacecatalog/src/main/resources/codegen-resources/paginators-1.json b/services/marketplacecatalog/src/main/resources/codegen-resources/paginators-1.json index 8bbef9687db7..b2a73c06dcd4 100644 --- a/services/marketplacecatalog/src/main/resources/codegen-resources/paginators-1.json +++ b/services/marketplacecatalog/src/main/resources/codegen-resources/paginators-1.json @@ -1,5 +1,17 @@ { "pagination": { + "DescribeAssessment": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "ControlAssessments" + }, + "ListAssessments": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "AssessmentSummaryList" + }, "ListChangeSets": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/marketplacecatalog/src/main/resources/codegen-resources/service-2.json b/services/marketplacecatalog/src/main/resources/codegen-resources/service-2.json index 882ce3af88ac..96eb5347bddc 100644 --- a/services/marketplacecatalog/src/main/resources/codegen-resources/service-2.json +++ b/services/marketplacecatalog/src/main/resources/codegen-resources/service-2.json @@ -66,6 +66,23 @@ ], "documentation":"

    Deletes a resource-based policy on an entity that is identified by its resource ARN.

    " }, + "DescribeAssessment":{ + "name":"DescribeAssessment", + "http":{ + "method":"POST", + "requestUri":"/DescribeAssessment" + }, + "input":{"shape":"DescribeAssessmentRequest"}, + "output":{"shape":"DescribeAssessmentResponse"}, + "errors":[ + {"shape":"InternalServiceException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns the metadata and detailed results of a single assessment, including the framework that was evaluated, the overall assessment result, and a paginated list of individual control evaluation results.

    To list available assessments before describing one, use the ListAssessments action.

    " + }, "DescribeChangeSet":{ "name":"DescribeChangeSet", "http":{ @@ -118,6 +135,22 @@ ], "documentation":"

    Gets a resource-based policy of an entity that is identified by its resource ARN.

    " }, + "ListAssessments":{ + "name":"ListAssessments", + "http":{ + "method":"POST", + "requestUri":"/ListAssessments" + }, + "input":{"shape":"ListAssessmentsRequest"}, + "output":{"shape":"ListAssessmentsResponse"}, + "errors":[ + {"shape":"InternalServiceException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns a paginated list of assessments associated with an entity or change set in AWS Marketplace. An assessment is the result of evaluating a product or change set against a framework, such as AMI Security or Container Security.

    Use the AssessmentTargetFilter to scope results to a specific entity or change set, and use FrameworkFilters to scope results to a single framework. To retrieve detailed control-level results for an individual assessment, use the DescribeAssessment action.

    Results are sorted by assessment creation time in descending order.

    " + }, "ListChangeSets":{ "name":"ListChangeSets", "http":{ @@ -240,6 +273,26 @@ } }, "shapes":{ + "AMISecurityFilters":{ + "type":"structure", + "members":{ + "DeliveryOptionId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the delivery option whose AMI Security assessments you want to list.

    " + } + }, + "documentation":"

    Filters that apply to assessments performed against the AMI Security framework.

    " + }, + "AMISecuritySummary":{ + "type":"structure", + "members":{ + "DeliveryOptionId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the delivery option that was evaluated.

    " + } + }, + "documentation":"

    The details of the resource assessed under the AMI Security framework.

    " + }, "ARN":{ "type":"string", "max":2048, @@ -412,6 +465,89 @@ "Draft" ] }, + "AssessmentIdentifier":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"^(assessment-[a-zA-Z0-9]+|arn:[a-zA-Z0-9-]+:[a-zA-Z0-9-]+:[a-zA-Z0-9-]*:[0-9]*:[a-zA-Z0-9-]+/Assessment/assessment-[a-zA-Z0-9]+)$" + }, + "AssessmentResult":{ + "type":"string", + "enum":[ + "PASS", + "FAIL" + ] + }, + "AssessmentSummary":{ + "type":"structure", + "members":{ + "AssessmentArn":{ + "shape":"ARN", + "documentation":"

    The ARN associated with the assessment.

    " + }, + "AssessmentId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the assessment.

    " + }, + "FrameworkId":{ + "shape":"VersionedFrameworkId", + "documentation":"

    The identifier of the framework that was evaluated by this assessment, in the format frameworkId@version (for example, AMISecurity@1.0).

    " + }, + "AssessmentTargetSummary":{ + "shape":"AssessmentTargetSummary", + "documentation":"

    Identifies the entity or change set that was assessed.

    " + }, + "FrameworkSummary":{ + "shape":"FrameworkSummary", + "documentation":"

    The framework-specific details of the assessed resource. The set member corresponds to the framework identified by FrameworkId.

    " + }, + "AssessmentResult":{ + "shape":"AssessmentResult", + "documentation":"

    The overall result of the assessment.

    " + }, + "CreatedAt":{ + "shape":"DateTimeISO8601", + "documentation":"

    The date and time the assessment was created, in ISO 8601 format (2018-02-27T13:45:22Z).

    " + }, + "ExpiresAt":{ + "shape":"DateTimeISO8601", + "documentation":"

    The date and time the assessment expires, in ISO 8601 format (2018-02-27T13:45:22Z).

    " + } + }, + "documentation":"

    Summarized information about an assessment.

    " + }, + "AssessmentSummaryList":{ + "type":"list", + "member":{"shape":"AssessmentSummary"} + }, + "AssessmentTargetFilter":{ + "type":"structure", + "members":{ + "EntityId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the entity whose assessments you want to list.

    " + }, + "ChangeSetId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the change set that triggered the assessments you want to list.

    " + } + }, + "documentation":"

    Filters assessment list results by the resource that was assessed. Provide an entity identifier, a change set identifier, or both.

    " + }, + "AssessmentTargetSummary":{ + "type":"structure", + "members":{ + "EntityId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the entity that was assessed.

    " + }, + "ChangeSetId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the change set that was assessed.

    " + } + }, + "documentation":"

    Identifies the entity or change set that was assessed.

    " + }, "BatchDescribeEntitiesRequest":{ "type":"structure", "required":["EntityRequestList"], @@ -802,6 +938,79 @@ "Draft" ] }, + "ContainerSecurityFilters":{ + "type":"structure", + "members":{ + "DeliveryOptionId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the delivery option whose Container Security assessments you want to list.

    " + } + }, + "documentation":"

    Filters that apply to assessments performed against the Container Security framework.

    " + }, + "ContainerSecuritySummary":{ + "type":"structure", + "members":{ + "DeliveryOptionId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the delivery option that was evaluated.

    " + } + }, + "documentation":"

    The details of the resource assessed under the Container Security framework.

    " + }, + "ControlAssessment":{ + "type":"structure", + "members":{ + "ControlId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the control that was evaluated.

    " + }, + "ControlAssessmentResult":{ + "shape":"ControlAssessmentResult", + "documentation":"

    The result of the control evaluation.

    " + }, + "Errors":{ + "shape":"ControlErrorList", + "documentation":"

    An array of ControlError objects associated with the control evaluation.

    " + } + }, + "documentation":"

    The result of evaluating a single control as part of an assessment.

    " + }, + "ControlAssessmentList":{ + "type":"list", + "member":{"shape":"ControlAssessment"} + }, + "ControlAssessmentResult":{ + "type":"string", + "enum":[ + "PASS", + "FAIL", + "NOT_EXECUTED", + "EXEMPTION_PASS" + ] + }, + "ControlError":{ + "type":"structure", + "members":{ + "Code":{ + "shape":"ErrorCode", + "documentation":"

    The error code that identifies the type of error.

    " + }, + "Message":{ + "shape":"ErrorMessage", + "documentation":"

    The message for the error.

    " + }, + "Scope":{ + "shape":"ErrorScopeList", + "documentation":"

    The list of name-value pairs that identify the resource or attribute that the error applies to.

    " + } + }, + "documentation":"

    An error reported during the evaluation of a single control.

    " + }, + "ControlErrorList":{ + "type":"list", + "member":{"shape":"ControlError"} + }, "DataProductEntityIdFilter":{ "type":"structure", "members":{ @@ -981,6 +1190,82 @@ "type":"structure", "members":{} }, + "DescribeAssessmentMaxResultInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "DescribeAssessmentRequest":{ + "type":"structure", + "required":[ + "Catalog", + "AssessmentIdentifier" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog related to the request. Fixed value: AWSMarketplace

    " + }, + "AssessmentIdentifier":{ + "shape":"AssessmentIdentifier", + "documentation":"

    The unique identifier of the assessment to describe. You can provide either the assessment ID (for example, assessment-12345) or the full assessment ARN (for example, arn:aws:aws-marketplace:us-east-1::AWSMarketplace/Assessment/assessment-12345).

    " + }, + "MaxResults":{ + "shape":"DescribeAssessmentMaxResultInteger", + "documentation":"

    Specifies the upper limit of ControlAssessment elements returned on a single page. If a value isn't provided, the default value is 50. Valid values range from 1 to 100.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The value of the next token, if it exists. null if there are no more results.

    " + } + } + }, + "DescribeAssessmentResponse":{ + "type":"structure", + "members":{ + "AssessmentArn":{ + "shape":"ARN", + "documentation":"

    The ARN associated with the assessment.

    " + }, + "AssessmentId":{ + "shape":"ResourceId", + "documentation":"

    The unique ID of the assessment.

    " + }, + "FrameworkId":{ + "shape":"VersionedFrameworkId", + "documentation":"

    The identifier of the framework that was evaluated by this assessment, in the format frameworkId@version (for example, AMISecurity@1.0).

    " + }, + "AssessmentTargetSummary":{ + "shape":"AssessmentTargetSummary", + "documentation":"

    Identifies the entity or change set that was assessed.

    " + }, + "FrameworkSummary":{ + "shape":"FrameworkSummary", + "documentation":"

    The framework-specific details of the assessed resource. The set member corresponds to the framework identified by FrameworkId.

    " + }, + "AssessmentResult":{ + "shape":"AssessmentResult", + "documentation":"

    The overall result of the assessment.

    " + }, + "CreatedAt":{ + "shape":"DateTimeISO8601", + "documentation":"

    The date and time the assessment was created, in ISO 8601 format (2018-02-27T13:45:22Z).

    " + }, + "ExpiresAt":{ + "shape":"DateTimeISO8601", + "documentation":"

    The date and time the assessment expires, in ISO 8601 format (2018-02-27T13:45:22Z).

    " + }, + "ControlAssessments":{ + "shape":"ControlAssessmentList", + "documentation":"

    An array of ControlAssessment objects, each containing the result of an individual control evaluated as part of the assessment.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The value of the next token, if it exists. null if there are no more results.

    " + } + } + }, "DescribeChangeSetRequest":{ "type":"structure", "required":[ @@ -1320,6 +1605,12 @@ "documentation":"

    Object containing all the sort fields per entity type.

    ", "union":true }, + "ErrorCode":{ + "type":"string", + "max":256, + "min":1, + "pattern":"^[A-Z_]+$" + }, "ErrorCodeString":{ "type":"string", "max":72, @@ -1344,6 +1635,29 @@ "type":"list", "member":{"shape":"ErrorDetail"} }, + "ErrorMessage":{ + "type":"string", + "max":2048, + "min":1 + }, + "ErrorScope":{ + "type":"structure", + "members":{ + "Name":{ + "shape":"ScopeName", + "documentation":"

    The name of the resource field the error applies to (for example, AMI_ID, FILE_PATH, or PACKAGE_NAME).

    " + }, + "Value":{ + "shape":"ScopeValue", + "documentation":"

    The value of the resource field the error applies to.

    " + } + }, + "documentation":"

    A name-value pair that identifies the resource or attribute that a ControlError applies to.

    " + }, + "ErrorScopeList":{ + "type":"list", + "member":{"shape":"ErrorScope"} + }, "Errors":{ "type":"map", "key":{"shape":"EntityId"}, @@ -1362,6 +1676,12 @@ "SERVER_FAULT" ] }, + "FieldName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"^[a-zA-Z0-9\\-_\\.\\/]+$" + }, "Filter":{ "type":"structure", "members":{ @@ -1394,6 +1714,42 @@ "min":1, "pattern":"^(.)+$" }, + "FrameworkFilters":{ + "type":"structure", + "members":{ + "AMISecurityFilters":{ + "shape":"AMISecurityFilters", + "documentation":"

    Filters that apply to assessments performed against the AMI Security framework.

    " + }, + "ContainerSecurityFilters":{ + "shape":"ContainerSecurityFilters", + "documentation":"

    Filters that apply to assessments performed against the Container Security framework.

    " + } + }, + "documentation":"

    Framework-specific filters used to scope ListAssessments results. Set exactly one member, corresponding to the framework you want to filter by.

    ", + "union":true + }, + "FrameworkId":{ + "type":"string", + "max":255, + "min":1, + "pattern":"^[\\w\\-@]+$" + }, + "FrameworkSummary":{ + "type":"structure", + "members":{ + "AMISecuritySummary":{ + "shape":"AMISecuritySummary", + "documentation":"

    The details of the resource assessed under the AMI Security framework.

    " + }, + "ContainerSecuritySummary":{ + "shape":"ContainerSecuritySummary", + "documentation":"

    The details of the resource assessed under the Container Security framework.

    " + } + }, + "documentation":"

    The framework-specific details of the assessed resource. Exactly one member is set, corresponding to the framework that was assessed.

    ", + "union":true + }, "GetResourcePolicyRequest":{ "type":"structure", "required":["ResourceArn"], @@ -1449,6 +1805,55 @@ "members":{}, "document":true }, + "ListAssessmentsMaxResultInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListAssessmentsRequest":{ + "type":"structure", + "required":["Catalog"], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog related to the request. Fixed value: AWSMarketplace

    " + }, + "FrameworkId":{ + "shape":"FrameworkId", + "documentation":"

    The unique identifier of a framework. When specified, only assessments performed against this framework are returned. For example, AMISecurity.

    " + }, + "AssessmentTargetFilter":{ + "shape":"AssessmentTargetFilter", + "documentation":"

    Filters the list of assessments to those performed against a specific entity or change set.

    " + }, + "FrameworkFilters":{ + "shape":"FrameworkFilters", + "documentation":"

    Framework-specific filters. Set exactly one member to filter results to assessments performed against that framework.

    " + }, + "MaxResults":{ + "shape":"ListAssessmentsMaxResultInteger", + "documentation":"

    Specifies the upper limit of the elements on a single page. If a value isn't provided, the default value is 20. Valid values range from 1 to 100.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The value of the next token, if it exists. null if there are no more results.

    " + } + } + }, + "ListAssessmentsResponse":{ + "type":"structure", + "members":{ + "AssessmentSummaryList":{ + "shape":"AssessmentSummaryList", + "documentation":"

    An array of AssessmentSummary objects.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The value of the next token, if it exists. null if there are no more results.

    " + } + } + }, "ListChangeSetsMaxResultInteger":{ "type":"integer", "box":true, @@ -1746,9 +2151,9 @@ }, "NextToken":{ "type":"string", - "max":2048, + "max":4096, "min":1, - "pattern":"^[\\w+=.:@\\-\\/]$" + "pattern":"^[\\w+=.:@\\-\\/]+$" }, "OfferAvailabilityEndDateFilter":{ "type":"structure", @@ -1802,6 +2207,29 @@ "min":12, "pattern":"^\\d{12}$" }, + "OfferCreatedBySourceFilter":{ + "type":"structure", + "members":{ + "ValueList":{ + "shape":"OfferCreatedBySourceFilterValueList", + "documentation":"

    Allows filtering on the CreatedBySource of an offer with list input.

    " + } + }, + "documentation":"

    Allows filtering on the CreatedBySource of an offer.

    " + }, + "OfferCreatedBySourceFilterValueList":{ + "type":"list", + "member":{"shape":"OfferCreatedBySourceString"}, + "max":2, + "min":1 + }, + "OfferCreatedBySourceString":{ + "type":"string", + "enum":[ + "Seller", + "AwsMarketplace" + ] + }, "OfferEntityIdFilter":{ "type":"structure", "members":{ @@ -1870,6 +2298,18 @@ "OfferSetId":{ "shape":"OfferSetIdFilter", "documentation":"

    Allows filtering on the OfferSetId of an offer.

    " + }, + "TargetAgreementId":{ + "shape":"OfferTargetAgreementIdFilter", + "documentation":"

    Allows filtering on the TargetAgreementId of an offer.

    " + }, + "TargetAgreementIntent":{ + "shape":"OfferTargetAgreementIntentFilter", + "documentation":"

    Allows filtering on the TargetAgreementIntent of an offer.

    " + }, + "CreatedBySource":{ + "shape":"OfferCreatedBySourceFilter", + "documentation":"

    Allows filtering on the CreatedBySource of an offer.

    " } }, "documentation":"

    Object containing all the filter fields for offers entity. Client can add only one wildcard filter and a maximum of 8 filters in a single ListEntities request.

    " @@ -2291,7 +2731,10 @@ "State", "Targeting", "LastModifiedDate", - "OfferSetId" + "OfferSetId", + "TargetAgreementId", + "TargetAgreementIntent", + "CreatedBySource" ] }, "OfferStateFilter":{ @@ -2355,10 +2798,64 @@ "OfferSetId":{ "shape":"OfferSetIdString", "documentation":"

    The offer set ID of the offer.

    " + }, + "TargetAgreementId":{ + "shape":"OfferTargetAgreementIdString", + "documentation":"

    The target agreement ID of the offer.

    " + }, + "TargetAgreementIntent":{ + "shape":"OfferTargetAgreementIntentString", + "documentation":"

    The target agreement intent of the offer.

    " + }, + "CreatedBySource":{ + "shape":"OfferCreatedBySourceString", + "documentation":"

    The creation source of the offer.

    " } }, "documentation":"

    Summarized information about an offer.

    " }, + "OfferTargetAgreementIdFilter":{ + "type":"structure", + "members":{ + "ValueList":{ + "shape":"OfferTargetAgreementIdFilterValueList", + "documentation":"

    Allows filtering on the TargetAgreementId of an offer with list input.

    " + } + }, + "documentation":"

    Allows filtering on the TargetAgreementId of an offer.

    " + }, + "OfferTargetAgreementIdFilterValueList":{ + "type":"list", + "member":{"shape":"OfferTargetAgreementIdString"}, + "max":10, + "min":1 + }, + "OfferTargetAgreementIdString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"^(.)+$" + }, + "OfferTargetAgreementIntentFilter":{ + "type":"structure", + "members":{ + "ValueList":{ + "shape":"OfferTargetAgreementIntentFilterValueList", + "documentation":"

    Allows filtering on the TargetAgreementIntent of an offer with list input.

    " + } + }, + "documentation":"

    Allows filtering on the TargetAgreementIntent of an offer.

    " + }, + "OfferTargetAgreementIntentFilterValueList":{ + "type":"list", + "member":{"shape":"OfferTargetAgreementIntentString"}, + "max":2, + "min":1 + }, + "OfferTargetAgreementIntentString":{ + "type":"string", + "enum":["Renew"] + }, "OfferTargetingFilter":{ "type":"structure", "members":{ @@ -2572,10 +3069,40 @@ "ResellerRole":{ "shape":"ResaleAuthorizationResellerRoleFilter", "documentation":"

    Allows filtering on the ResellerRole of a ResaleAuthorization.

    " + }, + "SourceAuthorization":{ + "shape":"ResaleAuthorizationSourceAuthorizationFilter", + "documentation":"

    Allows filtering on the SourceAuthorization of a ResaleAuthorization.

    " + }, + "IssuerAccountId":{ + "shape":"ResaleAuthorizationIssuerAccountIdFilter", + "documentation":"

    Allows filtering on the IssuerAccountId of a ResaleAuthorization.

    " } }, "documentation":"

    Object containing all the filter fields for resale authorization entity. Client can add only one wildcard filter and a maximum of 8 filters in a single ListEntities request.

    " }, + "ResaleAuthorizationIssuerAccountIdFilter":{ + "type":"structure", + "members":{ + "ValueList":{ + "shape":"ResaleAuthorizationIssuerAccountIdFilterValueList", + "documentation":"

    Allows filtering on the IssuerAccountId of a ResaleAuthorization with list input.

    " + } + }, + "documentation":"

    Allows filtering on the IssuerAccountId of a ResaleAuthorization.

    " + }, + "ResaleAuthorizationIssuerAccountIdFilterValueList":{ + "type":"list", + "member":{"shape":"ResaleAuthorizationIssuerAccountIdString"}, + "max":10, + "min":1 + }, + "ResaleAuthorizationIssuerAccountIdString":{ + "type":"string", + "max":12, + "min":12, + "pattern":"^\\d{12}$" + }, "ResaleAuthorizationLastModifiedDateFilter":{ "type":"structure", "members":{ @@ -2898,9 +3425,34 @@ "OfferExtendedStatus", "CreatedDate", "AvailabilityEndDate", - "LastModifiedDate" + "LastModifiedDate", + "ResellerRole", + "SourceAuthorization", + "IssuerAccountId" ] }, + "ResaleAuthorizationSourceAuthorizationFilter":{ + "type":"structure", + "members":{ + "ValueList":{ + "shape":"ResaleAuthorizationSourceAuthorizationFilterValueList", + "documentation":"

    Allows filtering on the SourceAuthorization of a ResaleAuthorization with list input.

    " + } + }, + "documentation":"

    Allows filtering on the SourceAuthorization of a ResaleAuthorization.

    " + }, + "ResaleAuthorizationSourceAuthorizationFilterValueList":{ + "type":"list", + "member":{"shape":"ResaleAuthorizationSourceAuthorizationString"}, + "max":10, + "min":1 + }, + "ResaleAuthorizationSourceAuthorizationString":{ + "type":"string", + "max":255, + "min":1, + "pattern":"^(.)+$" + }, "ResaleAuthorizationStatusFilter":{ "type":"structure", "members":{ @@ -2975,6 +3527,14 @@ "ResellerRole":{ "shape":"ResaleAuthorizationResellerRoleString", "documentation":"

    The reseller role of the ResaleAuthorization.

    " + }, + "SourceAuthorization":{ + "shape":"ResaleAuthorizationSourceAuthorizationString", + "documentation":"

    The source authorization of the ResaleAuthorization.

    " + }, + "IssuerAccountId":{ + "shape":"ResaleAuthorizationIssuerAccountIdString", + "documentation":"

    The issuer account ID of the ResaleAuthorization.

    " } }, "documentation":"

    Summarized information about a Resale Authorization.

    " @@ -3188,6 +3748,16 @@ "Draft" ] }, + "ScopeName":{ + "type":"string", + "max":50, + "min":1 + }, + "ScopeValue":{ + "type":"string", + "max":1024, + "min":1 + }, "ServiceQuotaExceededException":{ "type":"structure", "members":{ @@ -3369,19 +3939,72 @@ "ValidationException":{ "type":"structure", "members":{ - "Message":{"shape":"ExceptionMessageContent"} + "Message":{"shape":"ExceptionMessageContent"}, + "ValidationExceptionFieldList":{ + "shape":"ValidationExceptionFieldList", + "documentation":"

    A list of detailed entries describing the request fields that failed validation. Present when the failure can be attributed to one or more specific fields.

    " + } }, "documentation":"

    An error occurred during validation.

    HTTP status code: 422

    ", "error":{"httpStatusCode":422}, "exception":true, "synthetic":true }, + "ValidationExceptionField":{ + "type":"structure", + "members":{ + "Reason":{ + "shape":"ValidationExceptionReason", + "documentation":"

    The reason the field failed validation.

    " + }, + "EntityType":{ + "shape":"EntityType", + "documentation":"

    The entity type the failing field applies to, if the field is on a specific entity. For example, AmiProduct@1.0.

    " + }, + "EntityId":{ + "shape":"EntityId", + "documentation":"

    The entity identifier the failing field applies to, if the field is on a specific entity.

    " + }, + "ChangeType":{ + "shape":"ChangeType", + "documentation":"

    The change type the failing field applies to, if the field is part of a change request. For example, AddDeliveryOptions.

    " + }, + "Field":{ + "shape":"FieldName", + "documentation":"

    The name of the request field that failed validation, expressed as a JSON path (for example, Details.DeliveryOptions[0].Type).

    " + }, + "Message":{ + "shape":"ExceptionMessageContent", + "documentation":"

    A human-readable message describing why the field failed validation.

    " + } + }, + "documentation":"

    Detailed information about a single request field that failed validation, including the field's location, the reason it failed, and a human-readable message.

    " + }, + "ValidationExceptionFieldList":{ + "type":"list", + "member":{"shape":"ValidationExceptionField"} + }, + "ValidationExceptionReason":{ + "type":"string", + "enum":[ + "UnknownOperation", + "CannotParse", + "FieldValidationFailed", + "Other" + ] + }, "ValueList":{ "type":"list", "member":{"shape":"FilterValueContent"}, "max":10, "min":1 }, + "VersionedFrameworkId":{ + "type":"string", + "max":255, + "min":1, + "pattern":"^[\\w\\-@.]+$" + }, "VisibilityValue":{ "type":"string", "max":64, diff --git a/services/marketplacecommerceanalytics/pom.xml b/services/marketplacecommerceanalytics/pom.xml index d48332239802..f85d7da15da3 100644 --- a/services/marketplacecommerceanalytics/pom.xml +++ b/services/marketplacecommerceanalytics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacecommerceanalytics AWS Java SDK :: Services :: AWS Marketplace Commerce Analytics diff --git a/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/customization.config b/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/customization.config index af7a1033611e..de632ba92f3e 100644 --- a/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/customization.config +++ b/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "renameShapes": { "MarketplaceCommerceAnalyticsException": "MarketplaceCommerceAnalyticsServiceException" - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..410f5d277efb --- /dev/null +++ b/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://marketplacecommerceanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://marketplacecommerceanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://marketplacecommerceanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://marketplacecommerceanalytics.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4c6e157ff940..000000000000 --- a/services/marketplacecommerceanalytics/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://marketplacecommerceanalytics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://marketplacecommerceanalytics-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://marketplacecommerceanalytics.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://marketplacecommerceanalytics.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/marketplacedeployment/pom.xml b/services/marketplacedeployment/pom.xml index 846e7864680c..73544d65a59c 100644 --- a/services/marketplacedeployment/pom.xml +++ b/services/marketplacedeployment/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacedeployment AWS Java SDK :: Services :: Marketplace Deployment diff --git a/services/marketplacedeployment/src/main/resources/codegen-resources/customization.config b/services/marketplacedeployment/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/marketplacedeployment/src/main/resources/codegen-resources/customization.config +++ b/services/marketplacedeployment/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5b58361ad5dd --- /dev/null +++ b/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deployment-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deployment-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deployment-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://deployment-marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e40dabee3c8f..000000000000 --- a/services/marketplacedeployment/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deployment-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deployment-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deployment-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://deployment-marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplacediscovery/pom.xml b/services/marketplacediscovery/pom.xml index 84523af83d5a..d4ee3f66fd11 100644 --- a/services/marketplacediscovery/pom.xml +++ b/services/marketplacediscovery/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacediscovery AWS Java SDK :: Services :: Marketplace Discovery diff --git a/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..61e454d1fa0a --- /dev/null +++ b/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://discovery-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6192c1588e9f..000000000000 --- a/services/marketplacediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://discovery-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://discovery-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplacediscovery/src/main/resources/codegen-resources/service-2.json b/services/marketplacediscovery/src/main/resources/codegen-resources/service-2.json index 75f4efee94ec..7cff2717b5c6 100644 --- a/services/marketplacediscovery/src/main/resources/codegen-resources/service-2.json +++ b/services/marketplacediscovery/src/main/resources/codegen-resources/service-2.json @@ -842,6 +842,17 @@ "max":30, "min":0 }, + "FixedPercentage":{ + "type":"structure", + "required":["percentageValue"], + "members":{ + "percentageValue":{ + "shape":"BoundedString", + "documentation":"

    The percentage value applied at each renewal cycle.

    " + } + }, + "documentation":"

    A single fixed price increase percentage applied at each renewal cycle.

    " + }, "FixedUpfrontPricingTerm":{ "type":"structure", "required":[ @@ -1142,11 +1153,11 @@ "required":[ "offerId", "catalog", - "agreementProposalId", "sellerOfRecord", + "associatedEntities", + "agreementProposalId", "pricingModel", - "badges", - "associatedEntities" + "badges" ], "members":{ "offerId":{ @@ -1161,10 +1172,6 @@ "shape":"NullableString", "documentation":"

    The display name of the offer. This is free-form text provided by the seller.

    " }, - "agreementProposalId":{ - "shape":"AgreementResourceId", - "documentation":"

    An encoded string to be passed by the acceptor of the terms when creating an agreement.

    " - }, "expirationTime":{ "shape":"Timestamp", "documentation":"

    The date and time until when the offer can be procured. This value is null for offers that never expire.

    " @@ -1177,6 +1184,14 @@ "shape":"SellerInformation", "documentation":"

    The entity responsible for selling the product under this offer.

    " }, + "associatedEntities":{ + "shape":"OfferAssociatedEntityList", + "documentation":"

    The products and offer sets associated with this offer.

    " + }, + "agreementProposalId":{ + "shape":"AgreementResourceId", + "documentation":"

    An encoded string to be passed by the acceptor of the terms when creating an agreement.

    " + }, "replacementAgreementId":{ "shape":"AgreementResourceId", "documentation":"

    The identifier of the existing agreement that this offer would replace. Enables agreement-based offer functionality.

    " @@ -1188,10 +1203,6 @@ "badges":{ "shape":"PurchaseOptionBadgeList", "documentation":"

    Badges indicating special attributes of the offer, such as private pricing, future dated, or replacement offer.

    " - }, - "associatedEntities":{ - "shape":"OfferAssociatedEntityList", - "documentation":"

    The products and offer sets associated with this offer.

    " } } }, @@ -1307,10 +1318,10 @@ "productId", "catalog", "productName", + "manufacturer", "deployedOnAws", "shortDescription", "longDescription", - "manufacturer", "logoThumbnailUrl", "fulfillmentOptionSummaries", "categories", @@ -1332,6 +1343,10 @@ "shape":"NonEmptyString", "documentation":"

    The human-readable display name of the product.

    " }, + "manufacturer":{ + "shape":"SellerInformation", + "documentation":"

    The entity who manufactured the product.

    " + }, "deployedOnAws":{ "shape":"DeployedOnAwsStatus", "documentation":"

    Indicates whether the product is deployed on AWS infrastructure.

    " @@ -1344,10 +1359,6 @@ "shape":"GetProductOutputLongDescriptionString", "documentation":"

    A detailed description of what the product does, in paragraph format.

    " }, - "manufacturer":{ - "shape":"SellerInformation", - "documentation":"

    The entity who manufactured the product.

    " - }, "logoThumbnailUrl":{ "shape":"URL", "documentation":"

    The URL of the logo thumbnail image for the product.

    " @@ -1719,11 +1730,11 @@ "listingId", "listingName", "publisher", + "fulfillmentOptionSummaries", "catalog", "shortDescription", "logoThumbnailUrl", "categories", - "fulfillmentOptionSummaries", "badges", "reviewSummary", "pricingModels", @@ -1743,6 +1754,10 @@ "shape":"SellerInformation", "documentation":"

    The entity who created and published the listing.

    " }, + "fulfillmentOptionSummaries":{ + "shape":"FulfillmentOptionSummaryList", + "documentation":"

    A summary of fulfillment options available for the listing.

    " + }, "catalog":{ "shape":"Catalog", "documentation":"

    The name of the catalog that the listing belongs to.

    " @@ -1759,10 +1774,6 @@ "shape":"CategoryList", "documentation":"

    The categories used to classify this listing into logical groups.

    " }, - "fulfillmentOptionSummaries":{ - "shape":"FulfillmentOptionSummaryList", - "documentation":"

    A summary of fulfillment options available for the listing.

    " - }, "badges":{ "shape":"ListingBadgeList", "documentation":"

    Badges indicating special attributes of the listing.

    " @@ -1812,6 +1823,29 @@ "max":100, "min":1 }, + "NetPaymentTerm":{ + "type":"structure", + "required":[ + "id", + "type", + "paymentDuePeriod" + ], + "members":{ + "id":{ + "shape":"TermId", + "documentation":"

    The unique identifier of the term.

    " + }, + "type":{ + "shape":"TermType", + "documentation":"

    The category of the term.

    " + }, + "paymentDuePeriod":{ + "shape":"BoundedString", + "documentation":"

    The duration after invoice date by which payment is due.

    " + } + }, + "documentation":"

    Defines a net payment term that sets how many days after the invoice date the payment is due.

    " + }, "NextToken":{ "type":"string", "max":8192, @@ -1945,7 +1979,11 @@ "supportTerm":{"shape":"SupportTerm"}, "usageBasedPricingTerm":{"shape":"UsageBasedPricingTerm"}, "validityTerm":{"shape":"ValidityTerm"}, - "variablePaymentTerm":{"shape":"VariablePaymentTerm"} + "variablePaymentTerm":{"shape":"VariablePaymentTerm"}, + "netPaymentTerm":{ + "shape":"NetPaymentTerm", + "documentation":"

    A net payment term.

    " + } }, "documentation":"

    A term attached to an offer. Each element contains exactly one term type, such as a pricing term, legal term, or payment schedule term.

    ", "union":true @@ -1954,6 +1992,40 @@ "type":"list", "member":{"shape":"OfferTerm"} }, + "PaymentScheduleEntry":{ + "type":"structure", + "required":[ + "chargeDateOffset", + "chargePercentage" + ], + "members":{ + "chargeDateOffset":{ + "shape":"BoundedString", + "documentation":"

    The relative offset from the renewal agreement start date when this installment is due, in ISO 8601 duration format. The offset uses months only or days only (for example, P1M or P30D); mixed units are not supported, and every offset in a schedule uses the same unit.

    " + }, + "chargePercentage":{ + "shape":"BoundedString", + "documentation":"

    The percentage of the increased TCV to charge in this installment. All entries in a schedule sum to 100.00.

    " + }, + "dayOfMonth":{ + "shape":"PaymentScheduleEntryDayOfMonthInteger", + "documentation":"

    The optional calendar day of month on which the charge occurs. When absent, the charge day is derived from chargeDateOffset, and this field does not apply when chargeDateOffset is expressed in days. For months with fewer days than the specified day, the charge occurs on the last day of the month. For example, if dayOfMonth is 31, the charge in April occurs on April 30.

    " + } + }, + "documentation":"

    A single installment entry in the renewal payment schedule.

    " + }, + "PaymentScheduleEntryDayOfMonthInteger":{ + "type":"integer", + "box":true, + "max":31, + "min":1 + }, + "PaymentScheduleEntryList":{ + "type":"list", + "member":{"shape":"PaymentScheduleEntry"}, + "max":200, + "min":1 + }, "PaymentScheduleTerm":{ "type":"structure", "required":[ @@ -1982,6 +2054,55 @@ }, "documentation":"

    Defines a payment schedule term with installment payments at specified dates.

    " }, + "PaymentScheduleTermTemplate":{ + "type":"structure", + "required":["schedule"], + "members":{ + "schedule":{ + "shape":"PaymentScheduleEntryList", + "documentation":"

    An ordered list of installment entries for the renewal payment schedule.

    " + } + }, + "documentation":"

    A template for the payment schedule term on the renewal offer.

    " + }, + "PercentageRange":{ + "type":"structure", + "required":[ + "minimumValue", + "maximumValue", + "defaultValue" + ], + "members":{ + "minimumValue":{ + "shape":"BoundedString", + "documentation":"

    The minimum percentage by which the price can increase at each renewal cycle.

    " + }, + "maximumValue":{ + "shape":"BoundedString", + "documentation":"

    The maximum percentage by which the price can increase at each renewal cycle.

    " + }, + "defaultValue":{ + "shape":"BoundedString", + "documentation":"

    The percentage increase applied by default when no other value is finalized before the adjustment deadline. Falls between minimumValue and maximumValue.

    " + } + }, + "documentation":"

    A price increase percentage range with minimum, maximum, and default values.

    " + }, + "PriceIncrease":{ + "type":"structure", + "members":{ + "fixedPercentage":{ + "shape":"FixedPercentage", + "documentation":"

    A single fixed percentage applied uniformly at every renewal cycle.

    " + }, + "percentageRange":{ + "shape":"PercentageRange", + "documentation":"

    A percentage band with minimum, maximum, and default values that bound the price increase at each renewal cycle.

    " + } + }, + "documentation":"

    The pricing adjustment that applies at each renewal cycle, expressed as either a fixed percentage or a percentage range. Exactly one variant is present.

    ", + "union":true + }, "PricingModel":{ "type":"structure", "required":[ @@ -2229,7 +2350,8 @@ "enum":[ "PRIVATE_PRICING", "FUTURE_DATED", - "REPLACEMENT_OFFER" + "REPLACEMENT_OFFER", + "AUTO_RENEW" ] }, "PurchaseOptionFilter":{ @@ -2434,10 +2556,35 @@ "type":{ "shape":"TermType", "documentation":"

    The category of the term.

    " + }, + "maxRenewals":{ + "shape":"RenewalTermMaxRenewalsInteger", + "documentation":"

    The maximum number of renewals allowed on this offer. Absent means unlimited renewals.

    " + }, + "lockoutPeriod":{ + "shape":"BoundedString", + "documentation":"

    The duration before the agreement end date when the lockout window begins, in ISO 8601 format (for example, P30D). Absent means no lockout.

    " + }, + "adjustmentDeadline":{ + "shape":"BoundedString", + "documentation":"

    The duration before the agreement end date by which the renewal price is finalized, represented in ISO 8601 format (for example, P30D). Only applicable with PercentageRange.

    " + }, + "priceIncrease":{ + "shape":"PriceIncrease", + "documentation":"

    The price increase applied at each renewal cycle. Absent means identical pricing on renewal.

    " + }, + "termTemplates":{ + "shape":"TermTemplateList", + "documentation":"

    Structural templates defining how specific terms are reshaped on each renewal cycle. Absent for upfront-only offers.

    " } }, "documentation":"

    Defines a renewal term that enables automatic agreement renewal.

    " }, + "RenewalTermMaxRenewalsInteger":{ + "type":"integer", + "box":true, + "min":1 + }, "Resource":{ "type":"structure", "required":[ @@ -3011,6 +3158,23 @@ "min":1, "pattern":"[A-Za-z0-9+=;,.@\\-_]+" }, + "TermTemplate":{ + "type":"structure", + "members":{ + "paymentScheduleTermTemplate":{ + "shape":"PaymentScheduleTermTemplate", + "documentation":"

    The installment schedule used to structure payments on the renewal offer.

    " + } + }, + "documentation":"

    A structural template defining how a specific term type is reshaped on each renewal cycle. Exactly one variant is present.

    ", + "union":true + }, + "TermTemplateList":{ + "type":"list", + "member":{"shape":"TermTemplate"}, + "max":10, + "min":0 + }, "TermType":{ "type":"string", "enum":[ @@ -3025,7 +3189,8 @@ "RenewalTerm", "SupportTerm", "ValidityTerm", - "VariablePaymentTerm" + "VariablePaymentTerm", + "NetPaymentTerm" ] }, "ThrottlingException":{ diff --git a/services/marketplaceentitlement/pom.xml b/services/marketplaceentitlement/pom.xml index 64b2c88d3993..dfeec23b0437 100644 --- a/services/marketplaceentitlement/pom.xml +++ b/services/marketplaceentitlement/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplaceentitlement AWS Java SDK :: Services :: AWS Marketplace Entitlement diff --git a/services/marketplaceentitlement/src/main/resources/codegen-resources/customization.config b/services/marketplaceentitlement/src/main/resources/codegen-resources/customization.config index 6d810faea5bc..30af78fe47a3 100644 --- a/services/marketplaceentitlement/src/main/resources/codegen-resources/customization.config +++ b/services/marketplaceentitlement/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "EntitlementValue": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9b3d51201b1b --- /dev/null +++ b/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,260 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement-marketplace.{Region}.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement-marketplace.{Region}.amazonaws.eu", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://entitlement.marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAwAAAAGAAAABQAAAAsAAAAHAAAABgAAAAkAAAAIAAAACQX14QYF9eENAAAABwX14QQAAAAKAAAACAX14QsF9eEMAAAABgX14QQF9eEFAAAABAAAAA4AAAANAAAABgX14QgF9eEKAAAABgAAAA8F9eEJAAAACAX14QcF9eEIAAAAAwX14QEAAAARAAAABgX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 68a92f7d9039..000000000000 --- a/services/marketplaceentitlement/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,516 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://entitlement-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://entitlement-marketplace.{Region}.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://entitlement-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://entitlement-marketplace.{Region}.amazonaws.eu", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entitlement.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entitlement.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://entitlement.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://entitlement.marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplacemetering/pom.xml b/services/marketplacemetering/pom.xml index f646882e19a6..0c8646de6d97 100644 --- a/services/marketplacemetering/pom.xml +++ b/services/marketplacemetering/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacemetering AWS Java SDK :: Services :: AWS Marketplace Metering Service diff --git a/services/marketplacemetering/src/main/resources/codegen-resources/customization.config b/services/marketplacemetering/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/marketplacemetering/src/main/resources/codegen-resources/customization.config +++ b/services/marketplacemetering/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..64cb3e98394c --- /dev/null +++ b/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,266 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering-marketplace.{Region}.amazonaws.eu", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metering.marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAwAAAAGAAAABQAAAAgAAAAHAAAABgX14QUF9eEMAAAABwX14QQAAAAJAAAACAX14QQAAAAKAAAACQX14QQAAAALAAAACgX14QoF9eELAAAABAAAAA4AAAANAAAABQX14QcF9eEJAAAABQAAAA8F9eEIAAAACgX14QYF9eEHAAAAAwX14QEAAAARAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 134f7e51aab9..000000000000 --- a/services/marketplacemetering/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,516 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://metering-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://metering-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://metering-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://metering-marketplace.{Region}.amazonaws.eu", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://metering.marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://metering.marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://metering.marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://metering.marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/marketplacemetering/src/main/resources/codegen-resources/service-2.json b/services/marketplacemetering/src/main/resources/codegen-resources/service-2.json index 21fe0dbdcf48..54c0285ce78d 100644 --- a/services/marketplacemetering/src/main/resources/codegen-resources/service-2.json +++ b/services/marketplacemetering/src/main/resources/codegen-resources/service-2.json @@ -35,7 +35,7 @@ {"shape":"DisabledApiException"}, {"shape":"InvalidLicenseException"} ], - "documentation":"

    Amazon Web Services Marketplace is introducing Concurrent Agreements, enabling buyers to make multiple purchases per Amazon Web Services account. Starting June 1, 2026, new SaaS products must use CustomerAWSAccountId (instead of CustomerIdentifier), LicenseArn (instead of ProductCode) to support this feature. Existing integrations will continue to work. Review the new integration for Concurrent Agreements here.

    To post metering records for customers, SaaS applications call BatchMeterUsage, which is used for metering SaaS flexible consumption pricing (FCP). Identical requests are idempotent and can be retried with the same records or a subset of records. Each BatchMeterUsage request is for only one product. If you want to meter usage for multiple products, you must make multiple BatchMeterUsage calls.

    Usage records should be submitted in quick succession following a recorded event. Usage records aren't accepted 24 hours or more after an event.

    At the end of each billing cycle, a 6-hour grace period applies. We accept usage records for the previous billing month until 06:00 UTC on the first day of the next month. For example, you must submit March usage records before 06:00 UTC on April 1. After this grace period, we return a TimestampOutOfBoundsException error.

    BatchMeterUsage can process up to 25 UsageRecords at a time, and each request must be less than 1 MB in size. Optionally, you can have multiple usage allocations for usage data that's split into buckets according to predefined tags.

    BatchMeterUsage returns a list of UsageRecordResult objects, which have each UsageRecord. It also returns a list of UnprocessedRecords, which indicate errors on the service side that should be retried.

    For Amazon Web Services Regions that support BatchMeterUsage, see BatchMeterUsage Region support.

    For an example of BatchMeterUsage, see BatchMeterUsage code example in the Amazon Web Services Marketplace Seller Guide.

    " + "documentation":"

    Amazon Web Services Marketplace is introducing Concurrent Agreements, enabling buyers to make multiple purchases per Amazon Web Services account. Starting June 1, 2026, new SaaS products must use CustomerAWSAccountId (instead of CustomerIdentifier), LicenseArn (instead of ProductCode) to support this feature. BatchMeterUsage does not support CustomerIdentifier for new integrations. Existing integrations continue to work. Review the new integration for Concurrent Agreements here. For additional implementation details, see BatchMeterUsage code example with LicenseArn in the Amazon Web Services Marketplace Seller Guide.

    To post metering records for customers, SaaS applications call BatchMeterUsage, which is used for metering SaaS flexible consumption pricing (FCP). Identical requests are idempotent and can be retried with the same records or a subset of records. Each BatchMeterUsage request is for only one product. If you want to meter usage for multiple products, you must make multiple BatchMeterUsage calls.

    Usage records should be submitted in quick succession following a recorded event. Usage records aren't accepted 24 hours or more after an event. At the end of each billing cycle, a 6-hour grace period applies. We accept usage records for the previous billing month until 06:00 UTC on the first day of the next month. For example, you must submit March usage records before 06:00 UTC on April 1. On April 1 at 05:00 UTC, you can still submit records for March 31 (within the 6-hour grace period). After 06:00 UTC on April 1, March records are rejected regardless of the normal 24-hour submission window. After this grace period, we return a TimestampOutOfBoundsException error.

    BatchMeterUsage can process up to 25 UsageRecords at a time, and each request must be less than 1 MB in size. Optionally, you can have multiple usage allocations for usage data that's split into buckets according to predefined tags.

    BatchMeterUsage returns a list of UsageRecordResult objects, which have each UsageRecord. It also returns a list of UnprocessedRecords, which indicate errors on the service side that should be retried.

    For Amazon Web Services Regions that support BatchMeterUsage, see BatchMeterUsage Region support.

    For an example of BatchMeterUsage, see BatchMeterUsage code example in the Amazon Web Services Marketplace Seller Guide.

    " }, "MeterUsage":{ "name":"MeterUsage", @@ -95,7 +95,7 @@ {"shape":"InternalServiceErrorException"}, {"shape":"DisabledApiException"} ], - "documentation":"

    ResolveCustomer is called by a SaaS application during the registration process. When a buyer visits your website during the registration process, the buyer submits a registration token through their browser. The registration token is resolved through this API to obtain a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    To successfully resolve the token, the API must be called from the account that was used to publish the SaaS application. For an example of using ResolveCustomer, see ResolveCustomer code example in the Amazon Web Services Marketplace Seller Guide.

    Permission is required for this operation. Your IAM role or user performing this operation requires a policy to allow the aws-marketplace:ResolveCustomer action. For more information, see Actions, resources, and condition keys for Amazon Web Services Marketplace Metering Service in the Service Authorization Reference.

    For Amazon Web Services Regions that support ResolveCustomer, see ResolveCustomer Region support.

    " + "documentation":"

    ResolveCustomer is called by a SaaS application during the registration process. When a buyer visits your website during the registration process, the buyer submits a registration token through their browser. The registration token is resolved through this API to obtain a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    For new SaaS product integrations, the CustomerIdentifier field is not populated in the ResolveCustomer API response. New integrations must use CustomerAWSAccountId and LicenseArn to identify customers. Existing integrations continue to work unchanged.

    To successfully resolve the token, the API must be called from the account that was used to publish the SaaS application. For an example of using ResolveCustomer, see ResolveCustomer code example in the Amazon Web Services Marketplace Seller Guide.

    Permission is required for this operation. Your IAM role or user performing this operation requires a policy to allow the aws-marketplace:ResolveCustomer action. For more information, see Actions, resources, and condition keys for Amazon Web Services Marketplace Metering Service in the Service Authorization Reference.

    For Amazon Web Services Regions that support ResolveCustomer, see ResolveCustomer Region support.

    " } }, "shapes":{ @@ -114,7 +114,7 @@ }, "ProductCode":{ "shape":"ProductCode", - "documentation":"

    Product code is used to uniquely identify a product in Amazon Web Services Marketplace. The product code should be the same as the one used during the publishing of a new product.

    " + "documentation":"

    Product code is used to uniquely identify a product in Amazon Web Services Marketplace. The product code should be the same as the one used during the publishing of a new product.

    ProductCode is required only for legacy integrations that use CustomerIdentifier. For new integrations using LicenseArn (Concurrent Agreements), do NOT include ProductCode at the request level. The LicenseArn in each UsageRecord identifies both the product and the specific agreement.

    Sending metering records with both ProductCode and LicenseArn for the same customer within the same hour will result in duplicate billing. If you are migrating from product-based metering to license-based metering, stop sending ProductCode before you start sending LicenseArn.

    " } }, "documentation":"

    A BatchMeterUsageRequest contains UsageRecords, which indicate quantities of usage within your application.

    " @@ -395,7 +395,7 @@ "members":{ "RegistrationToken":{ "shape":"NonEmptyString", - "documentation":"

    When a buyer visits your website during the registration process, the buyer submits a registration token through the browser. The registration token is resolved to obtain a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    " + "documentation":"

    When a buyer visits your website during the registration process, the buyer submits a registration token through the browser. The registration token is resolved to obtain a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    For new SaaS product integrations, the CustomerIdentifier field is not populated. Use CustomerAWSAccountId and LicenseArn for customer identification.

    " } }, "documentation":"

    Contains input to the ResolveCustomer operation.

    " @@ -405,7 +405,7 @@ "members":{ "CustomerIdentifier":{ "shape":"CustomerIdentifier", - "documentation":"

    The CustomerIdentifier is used to identify an individual customer in your application.

    " + "documentation":"

    The CustomerIdentifier is used to identify an individual customer in your application.

    For new SaaS product integrations, this field is not populated. Use CustomerAWSAccountId and LicenseArn to identify customers instead.

    " }, "ProductCode":{ "shape":"ProductCode", @@ -521,7 +521,7 @@ }, "CustomerIdentifier":{ "shape":"CustomerIdentifier", - "documentation":"

    The CustomerIdentifier is obtained through the ResolveCustomer operation and represents an individual buyer in your application.

    " + "documentation":"

    The CustomerIdentifier is obtained through the ResolveCustomer operation and represents an individual buyer in your application.

    CustomerIdentifier is not supported for new SaaS product integrations. Use CustomerAWSAccountId to identify the buyer.

    " }, "Dimension":{ "shape":"UsageDimension", @@ -537,7 +537,7 @@ }, "CustomerAWSAccountId":{ "shape":"CustomerAWSAccountId", - "documentation":"

    The CustomerAWSAccountId parameter specifies the AWS account ID of the buyer.

    For existing integrations, to access your CustomerIdentifier to CustomerAWSAccountId mapping, see Account Feeds.

    " + "documentation":"

    The CustomerAWSAccountId parameter specifies the AWS account ID of the buyer.

    If you have an existing integration and need the CustomerAWSAccountId that corresponds to a CustomerIdentifier, contact AWS Marketplace Seller Operations to obtain the mapping. Do not request the CustomerAWSAccountId directly from buyers. We cannot verify that a buyer-provided account ID is authentic, which can result in incorrect metering or billing.

    " }, "LicenseArn":{ "shape":"LicenseArn", @@ -588,5 +588,5 @@ }, "errorMessage":{"type":"string"} }, - "documentation":"Amazon Web Services Marketplace Metering Service

    This reference provides descriptions of the low-level Marketplace Metering Service API.

    Amazon Web Services Marketplace sellers can use this API to submit usage data for custom usage dimensions.

    For information about the permissions that you need to use this API, see Amazon Web Services Marketplace metering and entitlement API permissions in the Amazon Web Services Marketplace Seller Guide.

    Submitting metering records

    MeterUsage

    • Submits the metering record for an Amazon Web Services Marketplace product.

    • Called from: Amazon Elastic Compute Cloud (Amazon EC2) instance or a container running on either Amazon Elastic Kubernetes Service (Amazon EKS) or Amazon Elastic Container Service (Amazon ECS)

    • Supported product types: Amazon Machine Images (AMIs) and containers

    • Vendor-metered tagging: Supported allocation tagging

    BatchMeterUsage

    • Submits the metering record for a set of customers. BatchMeterUsage API calls are captured by CloudTrail. You can use CloudTrail to verify that the software as a subscription (SaaS) metering records that you sent are accurate by searching for records with the eventName of BatchMeterUsage. You can also use CloudTrail to audit records over time. For more information, see the CloudTrail User Guide.

    • Called from: SaaS applications

    • Supported product type: SaaS

    • Vendor-metered tagging: Supports allocation tagging

    Accepting new customers

    ResolveCustomer

    • Resolves the registration token that the buyer submits through the browser during the registration process. Obtains a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    • Called from: SaaS application during the registration process

    • Supported product type: SaaS

    • Vendor-metered tagging: Not applicable

    Entitlement and metering for paid container products

    RegisteredUsage

    • Provides software entitlement and metering. Paid container software products sold through Amazon Web Services Marketplace must integrate with the Marketplace Metering Service and call the RegisterUsage operation. Free and Bring Your Own License model (BYOL) products for Amazon ECS or Amazon EKS aren't required to call RegisterUsage. However, you can do so if you want to receive usage data in your seller reports. For more information about using the RegisterUsage operation, see Container-based products.

    • Called from: Paid container software products

    • Supported product type: Containers

    • Vendor-metered tagging: Not applicable

    Entitlement custom metering for container products

    • MeterUsage API is available in GovCloud Regions but only supports AMI FCP products in GovCloud Regions. Flexible Consumption Pricing (FCP) Container products aren’t supported in GovCloud Regions: us-gov-west-1 and us-gov-east-1. For more information, see Container-based products.

    • Custom metering for container products are called using the MeterUsage API. The API is used for FCP AMI and FCP Container product metering.

    Custom metering for Amazon EKS is available in 17 Amazon Web Services Regions

    • The metering service supports Amazon ECS and EKS for Flexible Consumption Pricing (FCP) products using MeterUsage API. Amazon ECS is supported in all Amazon Web Services Regions that MeterUsage API is available except for GovCloud.

    • Amazon EKS is supported in the following: us-east-1, us-east-2, us-west-1, us-west-2, eu-west-1, eu-central-1, eu-west-2, eu-west-3, eu-north-1, ap-east-1, ap-southeast-1, ap-northeast-1, ap-southeast-2, ap-northeast-2, ap-south-1, ca-central-1, sa-east-1.

      For questions about adding Amazon Web Services Regions for metering, contact Amazon Web Services Marketplace Seller Operations.

    " + "documentation":"Amazon Web Services Marketplace Metering Service

    This reference provides descriptions of the low-level Marketplace Metering Service API.

    Amazon Web Services Marketplace sellers can use this API to submit usage data for custom usage dimensions.

    For information about the permissions that you need to use this API, see Amazon Web Services Marketplace metering and entitlement API permissions in the Amazon Web Services Marketplace Seller Guide.

    Submitting metering records

    MeterUsage

    • Submits the metering record for an Amazon Web Services Marketplace product.

    • Called from: Amazon Elastic Compute Cloud (Amazon EC2) instance or a container running on either Amazon Elastic Kubernetes Service (Amazon EKS) or Amazon Elastic Container Service (Amazon ECS)

    • Supported product types: Amazon Machine Images (AMIs) and containers

    • Vendor-metered tagging: Supported allocation tagging

    BatchMeterUsage

    • Submits the metering record for a set of customers. BatchMeterUsage API calls are captured by CloudTrail. You can use CloudTrail to verify that the software as a service (SaaS) metering records that you sent are accurate by searching for records with the eventName of BatchMeterUsage. You can also use CloudTrail to audit records over time. For more information, see the CloudTrail User Guide.

    • Called from: SaaS applications

    • Supported product type: SaaS

    • Vendor-metered tagging: Supports allocation tagging

    Accepting new customers

    ResolveCustomer

    • Resolves the registration token that the buyer submits through the browser during the registration process. Obtains a CustomerIdentifier along with the CustomerAWSAccountId, ProductCode, and LicenseArn.

    • Called from: SaaS application during the registration process

    • Supported product type: SaaS

    • Vendor-metered tagging: Not applicable

    Entitlement and metering for paid container products

    RegisterUsage

    • Provides software entitlement and metering. Paid container software products sold through Amazon Web Services Marketplace must integrate with the Marketplace Metering Service and call the RegisterUsage operation. Free and Bring Your Own License model (BYOL) products for Amazon ECS or Amazon EKS aren't required to call RegisterUsage. However, you can do so if you want to receive usage data in your seller reports. For more information about using the RegisterUsage operation, see Container-based products.

    • Called from: Paid container software products

    • Supported product type: Containers

    • Vendor-metered tagging: Not applicable

    Entitlement custom metering for container products

    • MeterUsage API is available in GovCloud Regions but only supports AMI FCP products in GovCloud Regions. Flexible Consumption Pricing (FCP) Container products aren’t supported in GovCloud Regions: us-gov-west-1 and us-gov-east-1. For more information, see Container-based products.

    • Custom metering for container products are called using the MeterUsage API. The API is used for FCP AMI and FCP Container product metering.

    Custom metering for Amazon EKS is available in 17 Amazon Web Services Regions

    • The metering service supports Amazon ECS and EKS for Flexible Consumption Pricing (FCP) products using MeterUsage API. Amazon ECS is supported in all Amazon Web Services Regions that MeterUsage API is available except for GovCloud.

    • Amazon EKS is supported in the following: us-east-1, us-east-2, us-west-1, us-west-2, eu-west-1, eu-central-1, eu-west-2, eu-west-3, eu-north-1, ap-east-1, ap-southeast-1, ap-northeast-1, ap-southeast-2, ap-northeast-2, ap-south-1, ca-central-1, sa-east-1.

      For questions about adding Amazon Web Services Regions for metering, contact Amazon Web Services Marketplace Seller Operations.

    " } diff --git a/services/marketplacereporting/pom.xml b/services/marketplacereporting/pom.xml index 756fd678ee73..52fef4a67f80 100644 --- a/services/marketplacereporting/pom.xml +++ b/services/marketplacereporting/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT marketplacereporting AWS Java SDK :: Services :: Marketplace Reporting diff --git a/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5b2666c98753 --- /dev/null +++ b/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://reporting-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://reporting-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://reporting-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://reporting-marketplace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4cc4028690a2..000000000000 --- a/services/marketplacereporting/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://reporting-marketplace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://reporting-marketplace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://reporting-marketplace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://reporting-marketplace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/mediaconnect/pom.xml b/services/mediaconnect/pom.xml index 3f680fa35c21..94ddcbdc5829 100644 --- a/services/mediaconnect/pom.xml +++ b/services/mediaconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mediaconnect AWS Java SDK :: Services :: MediaConnect diff --git a/services/mediaconnect/src/main/resources/codegen-resources/customization.config b/services/mediaconnect/src/main/resources/codegen-resources/customization.config index cf0eeb89dc03..b0fa95744f2e 100644 --- a/services/mediaconnect/src/main/resources/codegen-resources/customization.config +++ b/services/mediaconnect/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "listEntitlements", "listFlows" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mediaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7aeb44fc5ed4 --- /dev/null +++ b/services/mediaconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconnect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconnect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a6552e2bd208..000000000000 --- a/services/mediaconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediaconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediaconnect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediaconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediaconnect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediaconnect/src/main/resources/codegen-resources/service-2.json b/services/mediaconnect/src/main/resources/codegen-resources/service-2.json index 461ad832b92f..2dc831954eef 100644 --- a/services/mediaconnect/src/main/resources/codegen-resources/service-2.json +++ b/services/mediaconnect/src/main/resources/codegen-resources/service-2.json @@ -3272,6 +3272,11 @@ "documentation":"

    Key-value pairs that can be used to tag this router output.

    ", "locationName":"tags" }, + "FabricConfiguration":{ + "shape":"FabricConfiguration", + "documentation":"

    The fabric configuration settings for the router output.

    ", + "locationName":"fabricConfiguration" + }, "ClientToken":{ "shape":"ClientToken", "documentation":"

    A unique identifier for the request to ensure idempotency.

    ", @@ -4036,6 +4041,25 @@ "DISABLED" ] }, + "FabricConfiguration":{ + "type":"structure", + "required":["RecoveryLatencyMode"], + "members":{ + "RecoveryLatencyMode":{ + "shape":"FabricLatencyMode", + "documentation":"

    The recovery latency mode for the router fabric connection. Valid values include the following:

    • BALANCED (default) – Optimizes for stream quality.

    • LOW_LATENCY – Reduces latency at the potential cost of stream quality under adverse network conditions.

    ", + "locationName":"recoveryLatencyMode" + } + }, + "documentation":"

    The fabric configuration settings for the router output.

    " + }, + "FabricLatencyMode":{ + "type":"string", + "enum":[ + "BALANCED", + "LOW_LATENCY" + ] + }, "FailoverConfig":{ "type":"structure", "members":{ @@ -8233,7 +8257,8 @@ "Tags", "StreamDetails", "MaintenanceType", - "MaintenanceConfiguration" + "MaintenanceConfiguration", + "FabricConfiguration" ], "members":{ "Name":{ @@ -8348,6 +8373,11 @@ "shape":"MaintenanceSchedule", "documentation":"

    The current maintenance schedule details for this router output.

    ", "locationName":"maintenanceSchedule" + }, + "FabricConfiguration":{ + "shape":"FabricConfiguration", + "documentation":"

    The fabric configuration settings for the router output.

    ", + "locationName":"fabricConfiguration" } }, "documentation":"

    A router output in AWS Elemental MediaConnect. A router output is a destination for media content that can receive input from one or more router inputs.

    " @@ -10966,6 +10996,11 @@ "shape":"MaintenanceConfiguration", "documentation":"

    The updated maintenance configuration settings for the router output, including any changes to preferred maintenance windows and schedules.

    ", "locationName":"maintenanceConfiguration" + }, + "FabricConfiguration":{ + "shape":"FabricConfiguration", + "documentation":"

    The updated fabric configuration settings for the router output. You cannot update the fabric configuration while the output has an active route. You must unroute the output before updating the fabric configuration.

    ", + "locationName":"fabricConfiguration" } } }, diff --git a/services/mediaconvert/pom.xml b/services/mediaconvert/pom.xml index 7cd98726684a..9227e41816cf 100644 --- a/services/mediaconvert/pom.xml +++ b/services/mediaconvert/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 mediaconvert diff --git a/services/mediaconvert/src/main/resources/codegen-resources/customization.config b/services/mediaconvert/src/main/resources/codegen-resources/customization.config index da22aaad9103..9a6245c00e53 100644 --- a/services/mediaconvert/src/main/resources/codegen-resources/customization.config +++ b/services/mediaconvert/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "*" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mediaconvert/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediaconvert/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..91571c0a9595 --- /dev/null +++ b/services/mediaconvert/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,230 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "cn-northwest-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconvert-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconvert.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconvert-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconvert.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://subscribe.mediaconvert.cn-northwest-1.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediaconvert.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAACAX14QsF9eEMAAAABQX14QkF9eEKAAAABAAAAAwAAAAKAAAABgAAAAsF9eEIAAAABwX14QYF9eEHAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediaconvert/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediaconvert/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f82a7f2d6daf..000000000000 --- a/services/mediaconvert/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediaconvert-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://mediaconvert.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediaconvert-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediaconvert.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "cn-northwest-1" - ] - } - ], - "endpoint": { - "url": "https://subscribe.mediaconvert.cn-northwest-1.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediaconvert.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediaconvert/src/main/resources/codegen-resources/service-2.json b/services/mediaconvert/src/main/resources/codegen-resources/service-2.json index d5188790eb30..63f0f2a7cff2 100644 --- a/services/mediaconvert/src/main/resources/codegen-resources/service-2.json +++ b/services/mediaconvert/src/main/resources/codegen-resources/service-2.json @@ -1157,6 +1157,10 @@ "shape": "ProbeResponse" }, "errors": [ + { + "shape": "UnprocessableEntityException", + "documentation": "The input file was recognized but appears to be malformed or corrupt." + }, { "shape": "BadRequestException", "documentation": "The service can't process your request because of a problem in the request. Please check your request form and syntax." @@ -1186,7 +1190,7 @@ "documentation": "The service couldn't complete your request because there is a conflict with the current state of the resource." } ], - "documentation": "Use Probe to obtain detailed information about your input media files. Probe returns a JSON that includes container, codec, frame rate, resolution, track count, audio layout, captions, and more. You can use this information to learn more about your media files, or to help make decisions while automating your transcoding workflow." + "documentation": "Use Probe to obtain detailed information about your input media files. Probe returns a JSON that includes container, codec, frame rate, resolution, track count, audio layout, captions, and more. You can use this information to learn more about your media files, or to help make decisions while automating your transcoding workflow. Probe supports the following input container formats: MP4, QuickTime (MOV), 3GP, 3G2, Matroska (MKV), WebM, MXF, MPEG-TS, MPEG-PS, AVI, WAV, MP3, FLAC, Ogg, and ASF (Windows Media / WMA). The fields that Probe returns vary by container and codec. A field isn't returned when the source doesn't contain it, or when it isn't available for that container and codec." }, "PutPolicy": { "name": "PutPolicy", @@ -1588,6 +1592,14 @@ "ANCHOR" ] }, + "AacPassthroughControl": { + "type": "string", + "documentation": "When set to WHEN_POSSIBLE, input AAC audio will be passed through if it is present on the input. This detection is dynamic over the life of the transcode. Inputs that alternate between AAC and non-AAC content will have a consistent AAC output as the system alternates between passthrough and encoding.", + "enum": [ + "WHEN_POSSIBLE", + "NO_PASSTHROUGH" + ] + }, "AacRateControlMode": { "type": "string", "documentation": "Specify the AAC rate control mode. For a constant bitrate: Choose CBR. Your AAC output bitrate will be equal to the value that you choose for Bitrate. For a variable bitrate: Choose VBR. Your AAC output bitrate will vary according to your audio content and the value that you choose for Bitrate quality.", @@ -1632,6 +1644,11 @@ "locationName": "loudnessMeasurementMode", "documentation": "Choose the loudness measurement mode for your audio content. For music or advertisements: We recommend that you keep the default value, Program. For speech or other content: We recommend that you choose Anchor. When you do, MediaConvert optimizes the loudness of your output for clarify by applying speech gates." }, + "PassthroughControl": { + "shape": "AacPassthroughControl", + "locationName": "passthroughControl", + "documentation": "When set to WHEN_POSSIBLE, input AAC audio will be passed through if it is present on the input. This detection is dynamic over the life of the transcode. Inputs that alternate between AAC and non-AAC content will have a consistent AAC output as the system alternates between passthrough and encoding." + }, "RapInterval": { "shape": "__integerMin2000Max30000", "locationName": "rapInterval", @@ -2105,6 +2122,22 @@ "ENABLED" ] }, + "AspectRatio": { + "type": "structure", + "members": { + "Denominator": { + "shape": "__integer", + "locationName": "denominator", + "documentation": "The denominator, or bottom number, in the fractional aspect ratio. For example, for a display aspect ratio of 16 / 9, the denominator would be 9." + }, + "Numerator": { + "shape": "__integer", + "locationName": "numerator", + "documentation": "The numerator, or top number, in the fractional aspect ratio. For example, for a display aspect ratio of 16 / 9, the numerator would be 16." + } + }, + "documentation": "An aspect ratio expressed as a fraction with numerator and denominator values, reduced to lowest terms. Used for the sample (pixel) aspect ratio and the display aspect ratio of a video track. For example, a 720x576 anamorphic track has a sample aspect ratio of 64 / 45 and a display aspect ratio of 16 / 9. A video track can declare an aspect ratio in two independent places, and MediaConvert reports each one where it was found rather than choosing between them. The ratio declared by the container appears on the video track itself, and the ratio declared by the video essence appears under codecMetadata. When a file declares an aspect ratio in only one of the two places, the other is null; when it declares both and they disagree, you can compare them and decide which to use." + }, "AssociateCertificateRequest": { "type": "structure", "members": { @@ -2174,7 +2207,7 @@ }, "AudioCodec": { "type": "string", - "documentation": "Choose the audio codec for this output. Note that the option Dolby Digital passthrough applies only to Dolby Digital and Dolby Digital Plus audio inputs. Make sure that you choose a codec that's supported with your output container: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#reference-codecs-containers-output-audio For audio-only outputs, make sure that both your input audio codec and your output audio codec are supported for audio-only workflows. For more information, see: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers-input.html#reference-codecs-containers-input-audio-only and https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#audio-only-output", + "documentation": "Choose the audio codec for this output. Note that the option passthrough applies only to Dolby Digital, Dolby Digital Plus, AAC LC, AAC HEV1, and AAC HEV2 audio inputs. Make sure that you choose a codec that's supported with your output container: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#reference-codecs-containers-output-audio For audio-only outputs, make sure that both your input audio codec and your output audio codec are supported for audio-only workflows. For more information, see: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers-input.html#reference-codecs-containers-input-audio-only and https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#audio-only-output", "enum": [ "AAC", "MP2", @@ -2217,7 +2250,7 @@ "Codec": { "shape": "AudioCodec", "locationName": "codec", - "documentation": "Choose the audio codec for this output. Note that the option Dolby Digital passthrough applies only to Dolby Digital and Dolby Digital Plus audio inputs. Make sure that you choose a codec that's supported with your output container: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#reference-codecs-containers-output-audio For audio-only outputs, make sure that both your input audio codec and your output audio codec are supported for audio-only workflows. For more information, see: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers-input.html#reference-codecs-containers-input-audio-only and https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#audio-only-output" + "documentation": "Choose the audio codec for this output. Note that the option passthrough applies only to Dolby Digital, Dolby Digital Plus, AAC LC, AAC HEV1, and AAC HEV2 audio inputs. Make sure that you choose a codec that's supported with your output container: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#reference-codecs-containers-output-audio For audio-only outputs, make sure that both your input audio codec and your output audio codec are supported for audio-only workflows. For more information, see: https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers-input.html#reference-codecs-containers-input-audio-only and https://docs.aws.amazon.com/mediaconvert/latest/ug/reference-codecs-containers.html#audio-only-output" }, "Eac3AtmosSettings": { "shape": "Eac3AtmosSettings", @@ -2447,13 +2480,18 @@ "BitDepth": { "shape": "__integer", "locationName": "bitDepth", - "documentation": "The bit depth of the audio track." + "documentation": "The bit depth of the audio track. This value is exact for PCM and FLAC audio. For lossy codecs, such as AAC, AC-3, and E-AC-3, it is a nominal value and should be treated as approximate." }, "BitRate": { "shape": "__long", "locationName": "bitRate", "documentation": "The bit rate of the audio track, in bits per second." }, + "ChannelLayout": { + "shape": "__string", + "locationName": "channelLayout", + "documentation": "The audio channel layout of the track, such as \"mono\", \"stereo\", \"5.1\", or \"7.1\". Object-based or immersive audio is reported as \"5.1.4\" or \"7.1.4\". The layout is exact for AC-3 and E-AC-3 audio. For other codecs, it is inferred from the channel count and should be treated as approximate." + }, "Channels": { "shape": "__integer", "locationName": "channels", @@ -2540,6 +2578,11 @@ "locationName": "selectorType", "documentation": "Specify how MediaConvert selects audio content within your input. The default is Track. PID: Select audio by specifying the Packet Identifier (PID) values for MPEG Transport Stream inputs. Use this when you know the exact PID values of your audio streams. Track: Default. Select audio by track number. This is the most common option and works with most input container formats. If more types of audio data get recognized in the future, these numberings may shift, but the numberings used for Stream mode will not. Language code: Select audio by language using an ISO 639-2 or ISO 639-3 three-letter code in all capital letters. Use this when your source has embedded language metadata and you want to select tracks based on their language. HLS rendition group: Select audio from an HLS rendition group. Use this when your input is an HLS package with multiple audio renditions and you want to select specific rendition groups. All PCM: Select all uncompressed PCM audio tracks from your input automatically. This is useful when you want to include all PCM audio tracks without specifying individual track numbers. Stream: Select audio by stream number. Stream numbers include all tracks in the source file, regardless of type, and correspond to either the order of tracks in the file, or if applicable, the stream number metadata of the track. Although all tracks count toward these stream numbers, in this audio selector context, only the stream number of a track containing audio data may be used. If your source file contains a track which is not recognized by the service, then the corresponding stream number will still be reserved for future use. If more types of audio data get recognized in the future, these numberings will not shift." }, + "Smpte337Passthrough": { + "shape": "AudioSmpte337Passthrough", + "locationName": "smpte337Passthrough", + "documentation": "Specify whether to pass SMPTE 337M-wrapped audio (such as Dolby E) through without unwrapping. Choose Enabled to pass the SMPTE 337M container through unchanged, treating the track as raw PCM. Choose Disabled (default) to automatically detect and unwrap SMPTE 337M data, extracting the underlying Dolby E programs as separate audio tracks for encoding. When this field is absent, the service defaults to Disabled (auto-unwrap)." + }, "Streams": { "shape": "__listOf__integerMin1Max2147483647", "locationName": "streams", @@ -2576,6 +2619,14 @@ "STREAM" ] }, + "AudioSmpte337Passthrough": { + "type": "string", + "documentation": "Specify whether to pass SMPTE 337M-wrapped audio (such as Dolby E) through without unwrapping. Choose Enabled to pass the SMPTE 337M container through unchanged, treating the track as raw PCM. Choose Disabled (default) to automatically detect and unwrap SMPTE 337M data, extracting the underlying Dolby E programs as separate audio tracks for encoding. When this field is absent, the service defaults to Disabled (auto-unwrap).", + "enum": [ + "ENABLED", + "DISABLED" + ] + }, "AudioTypeControl": { "type": "string", "documentation": "When set to FOLLOW_INPUT, if the input contains an ISO 639 audio_type, then that value is passed through to the output. If the input contains no ISO 639 audio_type, the value in Audio Type is included in the output. Otherwise the value in Audio Type is included in the output. Note that this field and audioType are both ignored if audioDescriptionBroadcasterMix is set to BROADCASTER_MIXED_AD.", @@ -4094,10 +4145,11 @@ }, "CmfcScte35Source": { "type": "string", - "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output.", + "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest.", "enum": [ "PASSTHROUGH", - "NONE" + "NONE", + "MANIFEST_CUES" ] }, "CmfcSettings": { @@ -4161,7 +4213,7 @@ "Scte35Source": { "shape": "CmfcScte35Source", "locationName": "scte35Source", - "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output." + "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest." }, "SigningKmsKey": { "shape": "__stringMin1PatternArnAwsUsGovCnKmsAZ26EastWestCentralNorthSouthEastWest1912D12KeyAFAF098AFAF094AFAF094AFAF094AFAF0912MrkAFAF0932", @@ -4213,6 +4265,7 @@ "UNKNOWN", "AAC", "AC3", + "AMR", "EAC3", "FLAC", "MP2", @@ -4220,8 +4273,13 @@ "OPUS", "PCM", "VORBIS", + "WMA", + "WMA2", + "WMAPRO", "AV1", "AVC", + "DV", + "H263", "HEVC", "JPEG2000", "MJPEG", @@ -4232,6 +4290,8 @@ "QTRLE", "THEORA", "UNCOMPRESSED", + "VC1", + "VC3", "VFW", "VP8", "VP9", @@ -4268,6 +4328,26 @@ "locationName": "contentLightLevel", "documentation": "Content light level information (CTA-861.3). Describes the light level characteristics of the content." }, + "DisplayAspectRatio": { + "shape": "AspectRatio", + "locationName": "displayAspectRatio", + "documentation": "An aspect ratio expressed as a fraction with numerator and denominator values, reduced to lowest terms. Used for the sample (pixel) aspect ratio and the display aspect ratio of a video track. For example, a 720x576 anamorphic track has a sample aspect ratio of 64 / 45 and a display aspect ratio of 16 / 9. A video track can declare an aspect ratio in two independent places, and MediaConvert reports each one where it was found rather than choosing between them. The ratio declared by the container appears on the video track itself, and the ratio declared by the video essence appears under codecMetadata. When a file declares an aspect ratio in only one of the two places, the other is null; when it declares both and they disagree, you can compare them and decide which to use." + }, + "DolbyVision": { + "shape": "DolbyVisionMetadata", + "locationName": "dolbyVision", + "documentation": "Dolby Vision characteristics of the video track: the profile and level, and whether the RPU (dynamic metadata), base layer, and enhancement layer are present. Use this to distinguish Dolby Vision content from standard HEVC and to choose your encoding or passthrough settings. Omitted when the content is not Dolby Vision." + }, + "FieldOrder": { + "shape": "__string", + "locationName": "fieldOrder", + "documentation": "The field order of interlaced video, which indicates whether the top or bottom field is displayed first. Use this to select the correct deinterlacing behavior. One of \"TopFieldFirst\" or \"BottomFieldFirst\". This field is present only for interlaced video; it is omitted for progressive video and when the field order is not indicated by the source." + }, + "Hdr10PlusPresence": { + "shape": "Hdr10PlusPresence", + "locationName": "hdr10PlusPresence", + "documentation": "Indicates that HDR10+ (SMPTE ST 2094-40) dynamic metadata was detected in the HEVC bitstream. Present only when detected." + }, "Height": { "shape": "__integer", "locationName": "height", @@ -4293,6 +4373,11 @@ "locationName": "rotation", "documentation": "The clockwise rotation angle of the video, in degrees, as specified in the codec bitstream via a Display Orientation SEI message (payload type 47 for both H.264 and H.265). This field is null when the video essence does not contain a Display Orientation SEI message or when the rotation is 0 degrees." }, + "SampleAspectRatio": { + "shape": "AspectRatio", + "locationName": "sampleAspectRatio", + "documentation": "An aspect ratio expressed as a fraction with numerator and denominator values, reduced to lowest terms. Used for the sample (pixel) aspect ratio and the display aspect ratio of a video track. For example, a 720x576 anamorphic track has a sample aspect ratio of 64 / 45 and a display aspect ratio of 16 / 9. A video track can declare an aspect ratio in two independent places, and MediaConvert reports each one where it was found rather than choosing between them. The ratio declared by the container appears on the video track itself, and the ratio declared by the video essence appears under codecMetadata. When a file declares an aspect ratio in only one of the two places, the other is null; when it declares both and they disagree, you can compare them and decide which to use." + }, "ScanType": { "shape": "__string", "locationName": "scanType", @@ -4309,7 +4394,7 @@ "documentation": "The width in pixels as coded by the codec. This represents the actual encoded video width as specified in the video stream headers." } }, - "documentation": "Codec-specific parameters parsed from the video essence headers. This information provides detailed technical specifications about how the video was encoded, including profile settings, resolution details, and color space information that can help you understand the source video characteristics and make informed encoding decisions." + "documentation": "Codec-specific parameters parsed from the video essence headers. This information provides detailed technical specifications about how the video was encoded, including profile settings, resolution details, and color space information that can help you understand the source video characteristics and make informed encoding decisions. These fields are returned for H.264 (AVC), H.265 (HEVC), and MPEG-2 video, and might not be returned for other codecs. For MPEG-TS and MPEG-PS inputs, color information (color primaries, transfer characteristics, and matrix coefficients) appears in these fields rather than in the top-level videoProperties." }, "ColorConversion3DLUTSetting": { "type": "structure", @@ -4493,6 +4578,11 @@ "Container": { "type": "structure", "members": { + "BitRate": { + "shape": "__long", + "locationName": "bitRate", + "documentation": "The overall bit rate of your media file, in bits per second. This is derived from the file size and duration as (file size in bytes * 8) / duration in seconds." + }, "Duration": { "shape": "__double", "locationName": "duration", @@ -4501,7 +4591,7 @@ "Format": { "shape": "Format", "locationName": "format", - "documentation": "The format of your media file. For example: MP4, QuickTime (MOV), Matroska (MKV), WebM, MXF, Wave, AVI, MPEG-TS, MPEG-PS, or MP3. Note that this will be blank if your media file has a format that the MediaConvert Probe operation does not recognize." + "documentation": "The format of your media file. For example: MP4, QuickTime (MOV), Matroska (MKV), WebM, MXF, Wave, AVI, MPEG-TS, MPEG-PS, MP3, FLAC, ASF (Windows Media / WMA), OGG, 3GP, 3G2, AAC (raw ADTS), AC-3, or Enhanced AC-3 (E-AC-3). Note that this will be blank if your media file has a format that the MediaConvert Probe operation does not recognize." }, "StartTimecode": { "shape": "__string", @@ -4917,7 +5007,7 @@ "PlaybackDeviceCompatibility": { "shape": "DashIsoPlaybackDeviceCompatibility", "locationName": "playbackDeviceCompatibility", - "documentation": "This setting can improve the compatibility of your output with video players on obsolete devices. It applies only to DASH H.264 outputs with DRM encryption. Choose Unencrypted SEI only to correct problems with playback on older devices. Otherwise, keep the default setting CENC v1. If you choose Unencrypted SEI, for that output, the service will exclude the access unit delimiter and will leave the SEI NAL units unencrypted." + "documentation": "This setting can improve the compatibility of your output with video players on obsolete devices. It applies only to DASH outputs with DRM encryption. Choose Unencrypted SEI only to correct problems with playback on older H.264 devices. Choose CENC v1 unencrypted headers to leave NAL unit headers and slice headers unencrypted for H.265 outputs, improving compatibility with strict HEVC decoders. Otherwise, keep the default setting CENC v1." }, "SpekeKeyProvider": { "shape": "SpekeKeyProvider", @@ -5174,10 +5264,11 @@ }, "DashIsoPlaybackDeviceCompatibility": { "type": "string", - "documentation": "This setting can improve the compatibility of your output with video players on obsolete devices. It applies only to DASH H.264 outputs with DRM encryption. Choose Unencrypted SEI only to correct problems with playback on older devices. Otherwise, keep the default setting CENC v1. If you choose Unencrypted SEI, for that output, the service will exclude the access unit delimiter and will leave the SEI NAL units unencrypted.", + "documentation": "This setting can improve the compatibility of your output with video players on obsolete devices. It applies only to DASH outputs with DRM encryption. Choose Unencrypted SEI only to correct problems with playback on older H.264 devices. Choose CENC v1 unencrypted headers to leave NAL unit headers and slice headers unencrypted for H.265 outputs, improving compatibility with strict HEVC decoders. Otherwise, keep the default setting CENC v1.", "enum": [ "CENC_V1", - "UNENCRYPTED_SEI" + "UNENCRYPTED_SEI", + "CENC_V1_UNENCRYPTED_HEADERS" ] }, "DashIsoPtsOffsetHandlingForBFrames": { @@ -5512,6 +5603,45 @@ "HDR10_1000" ] }, + "DolbyVisionMetadata": { + "type": "structure", + "members": { + "BaseLayer": { + "shape": "DolbyVisionPresence", + "locationName": "baseLayer", + "documentation": "Whether a Dolby Vision component is present in the track." + }, + "EnhancementLayer": { + "shape": "DolbyVisionPresence", + "locationName": "enhancementLayer", + "documentation": "Whether a Dolby Vision component is present in the track." + }, + "Level": { + "shape": "__integer", + "locationName": "level", + "documentation": "The Dolby Vision level, which indicates the maximum resolution and frame rate." + }, + "Profile": { + "shape": "__integer", + "locationName": "profile", + "documentation": "The Dolby Vision profile, for example 5, 7, or 8. The profile determines the layer structure and playback compatibility of the content." + }, + "Rpu": { + "shape": "DolbyVisionPresence", + "locationName": "rpu", + "documentation": "Whether a Dolby Vision component is present in the track." + } + }, + "documentation": "Dolby Vision characteristics of the video track: the profile and level, and whether the RPU (dynamic metadata), base layer, and enhancement layer are present. Use this to distinguish Dolby Vision content from standard HEVC and to choose your encoding or passthrough settings. Omitted when the content is not Dolby Vision." + }, + "DolbyVisionPresence": { + "type": "string", + "documentation": "Whether a Dolby Vision component is present in the track.", + "enum": [ + "PRESENT", + "ABSENT" + ] + }, "DolbyVisionProfile": { "type": "string", "documentation": "Required when you enable Dolby Vision. Use Profile 5 to include frame-interleaved Dolby Vision metadata in your output. Your input must include Dolby Vision metadata or an HDR10 YUV color space. Use Profile 8.1 to include frame-interleaved Dolby Vision metadata and HDR10 metadata in your output. Your input must include Dolby Vision metadata.", @@ -6733,7 +6863,15 @@ "avi", "mpegts", "mpegps", - "mp3" + "mp3", + "flac", + "asf", + "ogg", + "three_gp", + "three_g2", + "aac", + "ac3", + "eac3" ] }, "FrameCaptureSettings": { @@ -8160,6 +8298,13 @@ }, "documentation": "Setting for HDR10+ metadata insertion" }, + "Hdr10PlusPresence": { + "type": "string", + "documentation": "Indicates that HDR10+ (SMPTE ST 2094-40) dynamic metadata was detected in the HEVC bitstream. Present only when detected.", + "enum": [ + "PRESENT" + ] + }, "HdrMetadata": { "type": "structure", "members": { @@ -9651,7 +9796,7 @@ "FollowSource": { "shape": "__integerMin1Max150", "locationName": "followSource", - "documentation": "Specify the input that MediaConvert references for your default output settings. MediaConvert uses this input's Resolution, Frame rate, and Pixel aspect ratio for all outputs that you don't manually specify different output settings for. Enabling this setting will disable \"Follow source\" for all other inputs. If MediaConvert cannot follow your source, for example if you specify an audio-only input, MediaConvert uses the first followable input instead. In your JSON job specification, enter an integer from 1 to 150 corresponding to the order of your inputs." + "documentation": "Specify the input that MediaConvert references for your default output settings. MediaConvert uses this input's Resolution, Frame rate, and Pixel aspect ratio for all outputs that you don't manually specify different output settings for. Enabling this setting will disable \"Follow source\" for all other inputs. If MediaConvert cannot follow your source, for example if you specify an audio-only input, MediaConvert uses the first followable input instead. In your JSON job specification, enter an integer from 1 to 150 corresponding to the order of your inputs." }, "Inputs": { "shape": "__listOfInput", @@ -9668,6 +9813,11 @@ "locationName": "motionImageInserter", "documentation": "Overlay motion graphics on top of your video. The motion graphics that you specify here appear on all outputs in all output groups. For more information, see https://docs.aws.amazon.com/mediaconvert/latest/ug/motion-graphic-overlay.html." }, + "MotionImageInserters": { + "shape": "__listOfMotionImageInserter", + "locationName": "motionImageInserters", + "documentation": "Array of motion image inserters for overlaying multiple independent motion graphics. Compositing order follows array index. Mutually exclusive with motionImageInserter." + }, "NielsenConfiguration": { "shape": "NielsenConfiguration", "locationName": "nielsenConfiguration", @@ -9822,7 +9972,7 @@ "FollowSource": { "shape": "__integerMin1Max150", "locationName": "followSource", - "documentation": "Specify the input that MediaConvert references for your default output settings. MediaConvert uses this input's Resolution, Frame rate, and Pixel aspect ratio for all outputs that you don't manually specify different output settings for. Enabling this setting will disable \"Follow source\" for all other inputs. If MediaConvert cannot follow your source, for example if you specify an audio-only input, MediaConvert uses the first followable input instead. In your JSON job specification, enter an integer from 1 to 150 corresponding to the order of your inputs." + "documentation": "Specify the input that MediaConvert references for your default output settings. MediaConvert uses this input's Resolution, Frame rate, and Pixel aspect ratio for all outputs that you don't manually specify different output settings for. Enabling this setting will disable \"Follow source\" for all other inputs. If MediaConvert cannot follow your source, for example if you specify an audio-only input, MediaConvert uses the first followable input instead. In your JSON job specification, enter an integer from 1 to 150 corresponding to the order of your inputs." }, "Inputs": { "shape": "__listOfInputTemplate", @@ -9839,6 +9989,11 @@ "locationName": "motionImageInserter", "documentation": "Overlay motion graphics on top of your video. The motion graphics that you specify here appear on all outputs in all output groups. For more information, see https://docs.aws.amazon.com/mediaconvert/latest/ug/motion-graphic-overlay.html." }, + "MotionImageInserters": { + "shape": "__listOfMotionImageInserter", + "locationName": "motionImageInserters", + "documentation": "Array of motion image inserters for overlaying multiple independent motion graphics. Compositing order follows array index. Mutually exclusive with motionImageInserter." + }, "NielsenConfiguration": { "shape": "NielsenConfiguration", "locationName": "nielsenConfiguration", @@ -9873,7 +10028,7 @@ "Key": { "shape": "JobsQueryFilterKey", "locationName": "key", - "documentation": "Specify job details to filter for while performing a jobs query. You specify these filters as part of a key-value pair within the JobsQueryFilter array. The following list describes which keys are available and their possible values: * queue - Your Queue's name or ARN. * status - Your job's status. (SUBMITTED | PROGRESSING | COMPLETE | CANCELED | ERROR) * fileInput - Your input file URL, or partial input file name. * jobEngineVersionRequested - The Job engine version that you requested for your job. Valid versions are in a YYYY-MM-DD format. * jobEngineVersionUsed - The Job engine version that your job used. This may differ from the version that you requested. Valid versions are in a YYYY-MM-DD format. * audioCodec - Your output's audio codec. (AAC | MP2 | MP3 | WAV | AIFF | AC3| EAC3 | EAC3_ATMOS | VORBIS | OPUS | PASSTHROUGH | FLAC) * videoCodec - Your output's video codec. (AV1 | AVC_INTRA | FRAME_CAPTURE | H_264 | H_265 | MPEG2 | PASSTHROUGH | PRORES | UNCOMPRESSED | VC3 | VP8 | VP9 | XAVC)" + "documentation": "Specify job details to filter for while performing a jobs query. You specify these filters as part of a key-value pair within the JobsQueryFilter array. The following list describes which keys are available and their possible values: * queue - Your Queue's name or ARN. * status - Your job's status. (SUBMITTED | PROGRESSING | COMPLETE | CANCELED | ERROR) * fileInput - Your input file URL, or partial input file name. * jobEngineVersionRequested - The Job engine version that you requested for your job. Valid versions are in a YYYY-MM-DD format. * jobEngineVersionUsed - The Job engine version that your job used. This may differ from the version that you requested. Valid versions are in a YYYY-MM-DD format. * audioCodec - Your output's audio codec. (AAC | MP2 | MP3 | WAV | AIFF | AC3| EAC3 | EAC3_ATMOS | VORBIS | OPUS | PASSTHROUGH | FLAC) * videoCodec - Your output's video codec. (AV1 | AVC_INTRA | FRAME_CAPTURE | H_264 | H_265 | MPEG2 | PASSTHROUGH | PRORES | UNCOMPRESSED | VC3 | VP8 | VP9 | XAVC) * errorCode - The error code that your job failed with. For example, 1010. For more information, see https://docs.aws.amazon.com/mediaconvert/latest/ug/mediaconvert_error_codes.html" }, "Values": { "shape": "__listOf__stringMax100", @@ -9885,7 +10040,7 @@ }, "JobsQueryFilterKey": { "type": "string", - "documentation": "Specify job details to filter for while performing a jobs query. You specify these filters as part of a key-value pair within the JobsQueryFilter array. The following list describes which keys are available and their possible values: * queue - Your Queue's name or ARN. * status - Your job's status. (SUBMITTED | PROGRESSING | COMPLETE | CANCELED | ERROR) * fileInput - Your input file URL, or partial input file name. * jobEngineVersionRequested - The Job engine version that you requested for your job. Valid versions are in a YYYY-MM-DD format. * jobEngineVersionUsed - The Job engine version that your job used. This may differ from the version that you requested. Valid versions are in a YYYY-MM-DD format. * audioCodec - Your output's audio codec. (AAC | MP2 | MP3 | WAV | AIFF | AC3| EAC3 | EAC3_ATMOS | VORBIS | OPUS | PASSTHROUGH | FLAC) * videoCodec - Your output's video codec. (AV1 | AVC_INTRA | FRAME_CAPTURE | H_264 | H_265 | MPEG2 | PASSTHROUGH | PRORES | UNCOMPRESSED | VC3 | VP8 | VP9 | XAVC)", + "documentation": "Specify job details to filter for while performing a jobs query. You specify these filters as part of a key-value pair within the JobsQueryFilter array. The following list describes which keys are available and their possible values: * queue - Your Queue's name or ARN. * status - Your job's status. (SUBMITTED | PROGRESSING | COMPLETE | CANCELED | ERROR) * fileInput - Your input file URL, or partial input file name. * jobEngineVersionRequested - The Job engine version that you requested for your job. Valid versions are in a YYYY-MM-DD format. * jobEngineVersionUsed - The Job engine version that your job used. This may differ from the version that you requested. Valid versions are in a YYYY-MM-DD format. * audioCodec - Your output's audio codec. (AAC | MP2 | MP3 | WAV | AIFF | AC3| EAC3 | EAC3_ATMOS | VORBIS | OPUS | PASSTHROUGH | FLAC) * videoCodec - Your output's video codec. (AV1 | AVC_INTRA | FRAME_CAPTURE | H_264 | H_265 | MPEG2 | PASSTHROUGH | PRORES | UNCOMPRESSED | VC3 | VP8 | VP9 | XAVC) * errorCode - The error code that your job failed with. For example, 1010. For more information, see https://docs.aws.amazon.com/mediaconvert/latest/ug/mediaconvert_error_codes.html", "enum": [ "queue", "status", @@ -9893,7 +10048,8 @@ "jobEngineVersionRequested", "jobEngineVersionUsed", "audioCodec", - "videoCodec" + "videoCodec", + "errorCode" ] }, "JobsQueryStatus": { @@ -9935,7 +10091,7 @@ "documentation": "Provide your Kantar license ID number. You should get this number from Kantar." }, "KantarServerUrl": { - "shape": "__stringPatternHttpsKantarmedia", + "shape": "__stringPatternHttpsKantarmedia55Prod", "locationName": "kantarServerUrl", "documentation": "Provide the HTTPS endpoint to the Kantar server. You should get this endpoint from Kantar." }, @@ -10552,10 +10708,11 @@ }, "M2tsScte35Source": { "type": "string", - "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None. Also provide the ESAM XML as a string in the setting Signal processing notification XML. Also enable ESAM SCTE-35 (include the property scte35Esam).", + "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest. For SCTE-35 markers from an ESAM XML document-- Choose None. Also provide the ESAM XML as a string in the setting Signal processing notification XML. Also enable ESAM SCTE-35 (include the property scte35Esam).", "enum": [ "PASSTHROUGH", - "NONE" + "NONE", + "MANIFEST_CUES" ] }, "M2tsSegmentationMarkers": { @@ -10764,7 +10921,7 @@ "Scte35Source": { "shape": "M2tsScte35Source", "locationName": "scte35Source", - "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None. Also provide the ESAM XML as a string in the setting Signal processing notification XML. Also enable ESAM SCTE-35 (include the property scte35Esam)." + "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest. For SCTE-35 markers from an ESAM XML document-- Choose None. Also provide the ESAM XML as a string in the setting Signal processing notification XML. Also enable ESAM SCTE-35 (include the property scte35Esam)." }, "SegmentationMarkers": { "shape": "M2tsSegmentationMarkers", @@ -10833,10 +10990,11 @@ }, "M3u8Scte35Source": { "type": "string", - "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None if you don't want manifest conditioning. Choose Passthrough and choose Ad markers if you do want manifest conditioning. In both cases, also provide the ESAM XML as a string in the setting Signal processing notification XML.", + "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None if you don't want manifest conditioning. Choose Passthrough and choose Ad markers if you do want manifest conditioning. In both cases, also provide the ESAM XML as a string in the setting Signal processing notification XML. For SCTE-35 markers from your input HLS manifest-- Choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest.", "enum": [ "PASSTHROUGH", - "NONE" + "NONE", + "MANIFEST_CUES" ] }, "M3u8Settings": { @@ -10930,7 +11088,7 @@ "Scte35Source": { "shape": "M3u8Scte35Source", "locationName": "scte35Source", - "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None if you don't want manifest conditioning. Choose Passthrough and choose Ad markers if you do want manifest conditioning. In both cases, also provide the ESAM XML as a string in the setting Signal processing notification XML." + "documentation": "For SCTE-35 markers from your input-- Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want SCTE-35 markers in this output. For SCTE-35 markers from an ESAM XML document-- Choose None if you don't want manifest conditioning. Choose Passthrough and choose Ad markers if you do want manifest conditioning. In both cases, also provide the ESAM XML as a string in the setting Signal processing notification XML. For SCTE-35 markers from your input HLS manifest-- Choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest." }, "TimedMetadata": { "shape": "TimedMetadata", @@ -11220,6 +11378,11 @@ "MovSettings": { "type": "structure", "members": { + "AudioDuration": { + "shape": "CmfcAudioDuration", + "locationName": "audioDuration", + "documentation": "Specify this setting only when your output will be consumed by a downstream repackaging workflow that is sensitive to very small duration differences between video and audio. For this situation, choose Match video duration. In all other cases, keep the default value, Default codec duration. When you choose Match video duration, MediaConvert pads the output audio streams with silence or trims them to ensure that the total duration of each audio stream is at least as long as the total duration of the video stream. After padding or trimming, the audio stream duration is no more than one frame longer than the video stream. MediaConvert applies audio padding or trimming only to the end of the last segment of the output. For unsegmented outputs, MediaConvert adds padding only to the end of the file. When you keep the default value, any minor discrepancies between audio and video duration will depend on your output audio codec." + }, "ClapAtom": { "shape": "MovClapAtom", "locationName": "clapAtom", @@ -11462,10 +11625,11 @@ }, "MpdScte35Source": { "type": "string", - "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output.", + "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest.", "enum": [ "PASSTHROUGH", - "NONE" + "NONE", + "MANIFEST_CUES" ] }, "MpdSettings": { @@ -11514,7 +11678,7 @@ "Scte35Source": { "shape": "MpdScte35Source", "locationName": "scte35Source", - "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output." + "documentation": "Ignore this setting unless you have SCTE-35 markers in your input video file. Choose Passthrough if you want SCTE-35 markers that appear in your input to also appear in this output. Choose None if you don't want those SCTE-35 markers in this output. When your input is an HLS manifest, choose Manifest cues to pass through CUE markers in your HLS manifest as segment boundaries and SCTE-35 markers in this output at each EXT-X-CUE-OUT splice point in the input manifest." }, "SigningKmsKey": { "shape": "__stringMin1PatternArnAwsUsGovCnKmsAZ26EastWestCentralNorthSouthEastWest1912D12KeyAFAF098AFAF094AFAF094AFAF094AFAF0912MrkAFAF0932", @@ -12602,6 +12766,15 @@ }, "documentation": "If you work with a third party video watermarking partner, use the group of settings that correspond with your watermarking partner to include watermarks in your output." }, + "PassthroughSegmentationMode": { + "type": "string", + "documentation": "Choose how MediaConvert determines segment boundaries when you passthrough video to a segmented ABR output (HLS, DASH, or CMAF). This setting applies only to ABR outputs. Keep the default value, Auto, to let MediaConvert choose based on your input: when your input is a segmented HLS or DASH source, MediaConvert reproduces your input's own segment boundaries, with one output segment per input segment; for all other inputs, MediaConvert places boundaries by duration, cutting at the first eligible IDR-frame at or after each configured Segment length or Fragment length target. Choose Duration based to always place boundaries by duration, at the first eligible IDR-frame at or after each configured Segment length or Fragment length target, regardless of your input. When your input GOP duration does not evenly divide your target segment length, output segment durations will vary. Choose GOP count to place a fixed number of input GOPs in every segment, and specify GOPs per segment. Every segment contains the same number of input GOPs, which produces consistent segment durations when your input GOP cadence is constant. In this mode MediaConvert ignores your configured Segment length and Fragment length for video boundary placement. Ad avails and input discontinuities are still honored as segment boundaries.", + "enum": [ + "AUTO", + "DURATION_BASED", + "GOP_COUNT" + ] + }, "PassthroughSettings": { "type": "structure", "members": { @@ -12610,6 +12783,16 @@ "locationName": "frameControl", "documentation": "Choose how MediaConvert handles start and end times for input clipping with video passthrough. Your input video codec must be H.264 or H.265 to use IFRAME. To clip at the nearest IDR-frame: Choose Nearest IDR. If an IDR-frame is not found at the frame that you specify, MediaConvert uses the next compatible IDR-frame. Note that your output may be shorter than your input clip duration. To clip at the nearest I-frame: Choose Nearest I-frame. If an I-frame is not found at the frame that you specify, MediaConvert uses the next compatible I-frame. Note that your output may be shorter than your input clip duration. We only recommend this setting for special workflows, and when you choose this setting your output may not be compatible with most players." }, + "GopsPerSegment": { + "shape": "__integerMin1Max100", + "locationName": "gopsPerSegment", + "documentation": "Specify how many input GOPs MediaConvert places in each output segment when you set Passthrough segmentation mode to GOP count. For example, if your input has a closed GOP every 1.92 seconds and you specify 2, each output segment is 3.84 seconds. In this mode, output segment duration is determined by your input GOP structure rather than by your configured Segment length or Fragment length, so segment durations are consistent only when your input GOP cadence is constant. Segments at input discontinuities or ad avails may contain fewer GOPs." + }, + "SegmentationMode": { + "shape": "PassthroughSegmentationMode", + "locationName": "segmentationMode", + "documentation": "Choose how MediaConvert determines segment boundaries when you passthrough video to a segmented ABR output (HLS, DASH, or CMAF). This setting applies only to ABR outputs. Keep the default value, Auto, to let MediaConvert choose based on your input: when your input is a segmented HLS or DASH source, MediaConvert reproduces your input's own segment boundaries, with one output segment per input segment; for all other inputs, MediaConvert places boundaries by duration, cutting at the first eligible IDR-frame at or after each configured Segment length or Fragment length target. Choose Duration based to always place boundaries by duration, at the first eligible IDR-frame at or after each configured Segment length or Fragment length target, regardless of your input. When your input GOP duration does not evenly divide your target segment length, output segment durations will vary. Choose GOP count to place a fixed number of input GOPs in every segment, and specify GOPs per segment. Every segment contains the same number of input GOPs, which produces consistent segment durations when your input GOP cadence is constant. In this mode MediaConvert ignores your configured Segment length and Fragment length for video boundary placement. Ad avails and input discontinuities are still honored as segment boundaries." + }, "VideoSelectorMode": { "shape": "VideoSelectorMode", "locationName": "videoSelectorMode", @@ -13374,7 +13557,8 @@ "ONEZONE_IA", "INTELLIGENT_TIERING", "GLACIER", - "DEEP_ARCHIVE" + "DEEP_ARCHIVE", + "GLACIER_IR" ] }, "SampleRangeConversion": { @@ -14031,17 +14215,96 @@ "MILLISECONDS" ] }, + "TtmlBackgroundColor": { + "type": "string", + "documentation": "Specify the background color for TTML captions output.", + "enum": [ + "NONE", + "BLACK", + "WHITE", + "AUTO" + ] + }, "TtmlDestinationSettings": { "type": "structure", "members": { + "BackgroundColor": { + "shape": "TtmlBackgroundColor", + "locationName": "backgroundColor", + "documentation": "Specify the color of the rectangle behind the captions. If Style passthrough is set to enabled, leave blank or set to Auto to pass through the background color from your input captions. If Style passthrough is set to disabled, leave blank or set to Auto to use the default black." + }, + "BackgroundOpacity": { + "shape": "__integerMin0Max255", + "locationName": "backgroundOpacity", + "documentation": "Specify the opacity of the background rectangle. Enter a value from 0 to 255, where 0 is transparent and 255 is opaque. If Style passthrough is set to enabled, leave blank to pass through the background style information in your input captions to your output captions. If Style passthrough is set to disabled and backgroundColor is set, leave blank to use a value of 255 (opaque)." + }, + "FontColor": { + "shape": "TtmlFontColor", + "locationName": "fontColor", + "documentation": "Specify the color of the captions text. If Style passthrough is set to enabled, leave blank or set to Auto to pass through the font color from your input captions. If Style passthrough is set to disabled, leave blank or set to Auto to use the default white." + }, + "FontOpacity": { + "shape": "__integerMin0Max255", + "locationName": "fontOpacity", + "documentation": "Specify the opacity of the captions. Enter a value from 0 to 255, where 0 is transparent and 255 is opaque. If Style passthrough is set to enabled, leave blank to pass through the font opacity information in your input captions to your output captions. If Style passthrough is set to disabled and fontColor is set, leave blank to use a value of 255 (opaque)." + }, + "FontSize": { + "shape": "__integerMin0Max96", + "locationName": "fontSize", + "documentation": "Specify the Font size in pixels. Must be a positive integer. Set to 0, or leave blank, for automatic font size." + }, + "FontStyle": { + "shape": "TtmlFontStyle", + "locationName": "fontStyle", + "documentation": "Specify the font style of the caption text. If Style passthrough is set to enabled, leave blank to pass through the font style from your input captions. If Style passthrough is set to disabled, leave blank to use the default normal style." + }, + "FontWeight": { + "shape": "TtmlFontWeight", + "locationName": "fontWeight", + "documentation": "Specify the font weight of the caption text. If Style passthrough is set to enabled, leave blank to pass through the font weight from your input captions. If Style passthrough is set to disabled, leave blank to use the default normal weight." + }, "StylePassthrough": { "shape": "TtmlStylePassthrough", "locationName": "stylePassthrough", "documentation": "Pass through style and position information from a TTML-like input source (TTML, IMSC, SMPTE-TT) to the TTML output." + }, + "TextDecoration": { + "shape": "TtmlTextDecoration", + "locationName": "textDecoration", + "documentation": "Specify the text decoration of the caption text. If Style passthrough is set to enabled, leave blank to pass through the text decoration from your input captions. If Style passthrough is set to disabled, leave blank to use the default of none." } }, "documentation": "Settings related to TTML captions. TTML is a sidecar format that holds captions in a file that is separate from the video container. Set up sidecar captions in the same output group, but different output from your video. For more information, see https://docs.aws.amazon.com/mediaconvert/latest/ug/ttml-and-webvtt-output-captions.html." }, + "TtmlFontColor": { + "type": "string", + "documentation": "Specify the font color for TTML captions output.", + "enum": [ + "WHITE", + "BLACK", + "YELLOW", + "RED", + "GREEN", + "BLUE", + "AUTO" + ] + }, + "TtmlFontStyle": { + "type": "string", + "documentation": "Specify the font style for TTML captions output.", + "enum": [ + "NORMAL", + "ITALIC" + ] + }, + "TtmlFontWeight": { + "type": "string", + "documentation": "Specify the font weight for TTML captions output.", + "enum": [ + "NORMAL", + "BOLD" + ] + }, "TtmlStylePassthrough": { "type": "string", "documentation": "Pass through style and position information from a TTML-like input source (TTML, IMSC, SMPTE-TT) to the TTML output.", @@ -14050,6 +14313,14 @@ "DISABLED" ] }, + "TtmlTextDecoration": { + "type": "string", + "documentation": "Specify the text decoration for TTML captions output.", + "enum": [ + "NONE", + "UNDERLINE" + ] + }, "Type": { "type": "string", "enum": [ @@ -14167,6 +14438,20 @@ "HARD" ] }, + "UnprocessableEntityException": { + "type": "structure", + "members": { + "Message": { + "shape": "__string", + "locationName": "message" + } + }, + "exception": true, + "error": { + "httpStatusCode": 422 + }, + "documentation": "The input file was recognized but appears to be malformed or corrupt." + }, "UntagResourceRequest": { "type": "structure", "members": { @@ -14927,13 +15212,18 @@ "CodecMetadata": { "shape": "CodecMetadata", "locationName": "codecMetadata", - "documentation": "Codec-specific parameters parsed from the video essence headers. This information provides detailed technical specifications about how the video was encoded, including profile settings, resolution details, and color space information that can help you understand the source video characteristics and make informed encoding decisions." + "documentation": "Codec-specific parameters parsed from the video essence headers. This information provides detailed technical specifications about how the video was encoded, including profile settings, resolution details, and color space information that can help you understand the source video characteristics and make informed encoding decisions. These fields are returned for H.264 (AVC), H.265 (HEVC), and MPEG-2 video, and might not be returned for other codecs. For MPEG-TS and MPEG-PS inputs, color information (color primaries, transfer characteristics, and matrix coefficients) appears in these fields rather than in the top-level videoProperties." }, "ColorPrimaries": { "shape": "ColorPrimaries", "locationName": "colorPrimaries", "documentation": "The color space primaries of the video track, defining the red, green, and blue color coordinates used for the video. This information helps ensure accurate color reproduction during playback and transcoding." }, + "DisplayAspectRatio": { + "shape": "AspectRatio", + "locationName": "displayAspectRatio", + "documentation": "An aspect ratio expressed as a fraction with numerator and denominator values, reduced to lowest terms. Used for the sample (pixel) aspect ratio and the display aspect ratio of a video track. For example, a 720x576 anamorphic track has a sample aspect ratio of 64 / 45 and a display aspect ratio of 16 / 9. A video track can declare an aspect ratio in two independent places, and MediaConvert reports each one where it was found rather than choosing between them. The ratio declared by the container appears on the video track itself, and the ratio declared by the video essence appears under codecMetadata. When a file declares an aspect ratio in only one of the two places, the other is null; when it declares both and they disagree, you can compare them and decide which to use." + }, "FrameRate": { "shape": "FrameRate", "locationName": "frameRate", @@ -14959,6 +15249,11 @@ "locationName": "rotation", "documentation": "The clockwise rotation angle of the video track, in degrees, as derived from container-level metadata (e.g. the MP4 tkhd transformation matrix or the Matroska ProjectionPoseRoll element). Common values are 90, 180, and 270. This field is null when no rotation metadata is present or when the rotation is 0 degrees. For MP4, non-standard transformation matrices also yield null." }, + "SampleAspectRatio": { + "shape": "AspectRatio", + "locationName": "sampleAspectRatio", + "documentation": "An aspect ratio expressed as a fraction with numerator and denominator values, reduced to lowest terms. Used for the sample (pixel) aspect ratio and the display aspect ratio of a video track. For example, a 720x576 anamorphic track has a sample aspect ratio of 64 / 45 and a display aspect ratio of 16 / 9. A video track can declare an aspect ratio in two independent places, and MediaConvert reports each one where it was found rather than choosing between them. The ratio declared by the container appears on the video track itself, and the ratio declared by the video essence appears under codecMetadata. When a file declares an aspect ratio in only one of the two places, the other is null; when it declares both and they disagree, you can compare them and decide which to use." + }, "TransferCharacteristics": { "shape": "TransferCharacteristics", "locationName": "transferCharacteristics", @@ -15613,6 +15908,11 @@ "XavcHdIntraCbgProfileSettings": { "type": "structure", "members": { + "InterlaceMode": { + "shape": "XavcInterlaceMode", + "locationName": "interlaceMode", + "documentation": "Choose the scan line type for the output. Keep the default value, Progressive, to create a progressive output, regardless of the scan type of your input. To create an interlaced output, choose Top field first or Follow, default top. Outputs that you create with this profile are always top field first when they are interlaced. When you create an interlaced output, set your output frame rate to 25 or 29.97." + }, "XavcClass": { "shape": "XavcHdIntraCbgProfileClass", "locationName": "xavcClass", @@ -15711,7 +16011,7 @@ }, "XavcProfile": { "type": "string", - "documentation": "Specify the XAVC profile for this output. For more information, see the Sony documentation at https://www.xavc-info.org/. Note that MediaConvert doesn't support the interlaced video XAVC operating points for XAVC_HD_INTRA_CBG. To create an interlaced XAVC output, choose the profile XAVC_HD.", + "documentation": "Specify the XAVC profile for this output. For more information, see the Sony documentation at https://www.xavc-info.org/. Note that when you choose XAVC_HD_INTRA_CBG, MediaConvert supports interlaced outputs only when they are top field first and your output frame rate is 25 or 29.97 fps.", "enum": [ "XAVC_HD_INTRA_CBG", "XAVC_4K_INTRA_CBG", @@ -15761,7 +16061,7 @@ "Profile": { "shape": "XavcProfile", "locationName": "profile", - "documentation": "Specify the XAVC profile for this output. For more information, see the Sony documentation at https://www.xavc-info.org/. Note that MediaConvert doesn't support the interlaced video XAVC operating points for XAVC_HD_INTRA_CBG. To create an interlaced XAVC output, choose the profile XAVC_HD." + "documentation": "Specify the XAVC profile for this output. For more information, see the Sony documentation at https://www.xavc-info.org/. Note that when you choose XAVC_HD_INTRA_CBG, MediaConvert supports interlaced outputs only when they are top field first and your output frame rate is 25 or 29.97 fps." }, "SlowPal": { "shape": "XavcSlowPal", @@ -16609,6 +16909,12 @@ "shape": "JobsQueryFilter" } }, + "__listOfMotionImageInserter": { + "type": "list", + "member": { + "shape": "MotionImageInserter" + } + }, "__listOfMsSmoothAdditionalManifest": { "type": "list", "member": { @@ -17068,9 +17374,9 @@ "type": "string", "pattern": "^https:\\/\\/[^:@\\/]*(:\\d*)?(\\/.*)?$" }, - "__stringPatternHttpsKantarmedia": { + "__stringPatternHttpsKantarmedia55Prod": { "type": "string", - "pattern": "^https:\\/\\/.*.kantarmedia.*$" + "pattern": "^https:\\/\\/.*.(kantarmedia|55-prod).*$" }, "__stringPatternIdentityAZaZ26AZaZ09163": { "type": "string", diff --git a/services/medialive/pom.xml b/services/medialive/pom.xml index d6fb2fc1d0c4..86d915c2add7 100644 --- a/services/medialive/pom.xml +++ b/services/medialive/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 medialive diff --git a/services/medialive/src/main/resources/codegen-resources/customization.config b/services/medialive/src/main/resources/codegen-resources/customization.config index 34826c5c0209..93e2131d4ce1 100644 --- a/services/medialive/src/main/resources/codegen-resources/customization.config +++ b/services/medialive/src/main/resources/codegen-resources/customization.config @@ -10,6 +10,5 @@ "createChannel", "createInput", "createInputSecurityGroup" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/medialive/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/medialive/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2e73960b4648 --- /dev/null +++ b/services/medialive/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medialive-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medialive-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medialive.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medialive.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/medialive/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/medialive/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c9caa9e3c9f9..000000000000 --- a/services/medialive/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medialive-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medialive-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medialive.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://medialive.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/medialive/src/main/resources/codegen-resources/service-2.json b/services/medialive/src/main/resources/codegen-resources/service-2.json index 7ed7aff11423..b86fb6c6a692 100644 --- a/services/medialive/src/main/resources/codegen-resources/service-2.json +++ b/services/medialive/src/main/resources/codegen-resources/service-2.json @@ -10489,7 +10489,18 @@ }, "EmbeddedDestinationSettings": { "type": "structure", - "members": {}, + "members": { + "Position": { + "shape": "EmbeddedCaptionPositionSettings", + "locationName": "position", + "documentation": "Specifies the position of the output captions. Applies only when styleControl is set to manual." + }, + "StyleControl": { + "shape": "EmbeddedDestinationStyleControl", + "locationName": "styleControl", + "documentation": "Controls the source of position and style information for the output captions.\n\n- \"passthrough\": Carry the caption position and style from the source captions. When the source captions are embedded, SCTE-20, or ancillary, the position and style are preserved exactly. When the source captions are another format, the position and any supported style are carried over.\n- \"manual\": Applies the specified styling and positioning. All other styling and positioning is given default values." + } + }, "documentation": "Embedded Destination Settings" }, "EmbeddedPlusScte20DestinationSettings": { @@ -14752,7 +14763,8 @@ "documentation": "M2ts Scte35 Control", "enum": [ "NONE", - "PASSTHROUGH" + "PASSTHROUGH", + "SCTE_35_WITHOUT_IDR" ] }, "M2tsSegmentationMarkers": { @@ -14971,7 +14983,7 @@ "Scte35Control": { "shape": "M2tsScte35Control", "locationName": "scte35Control", - "documentation": "Optionally pass SCTE-35 signals from the input source to this output." + "documentation": "SCTE-35 control. Option \"none\" indicates that a SCTE-35 marker will not be inserted, nor will an IDR be inserted at the SCTE-35 cue point, nor will the segment be segmented. Option \"scte35WithoutIdr\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, but MediaLive will not insert an IDR on that frame nor will it introduce a new segment boundary there if it wasn't already going to be one (this option is required for use with downstream multiview bitstream stitching workflows). Option \"passthrough\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, and an IDR will be inserted on that frame, and MediaLive itself will introduce a new segment boundary there." }, "Scte35Pid": { "shape": "__string", @@ -16345,6 +16357,11 @@ "shape": "NielsenNaesIiNw", "locationName": "nielsenNaesIiNwSettings", "documentation": "Complete these fields only if you want to insert watermarks of type Nielsen NAES II (N2) and Nielsen NAES VI (NW)." + }, + "NielsenNwOnlySettings": { + "shape": "NielsenNwOnly", + "locationName": "nielsenNwOnlySettings", + "documentation": "Complete these fields only if you want to insert watermarks of type Nielsen NAES VI (NW) only,\nwithout inserting NAES II (N2) watermarks." } }, "documentation": "Nielsen Watermarks Settings" @@ -16535,6 +16552,11 @@ "shape": "__string", "locationName": "username", "documentation": "username for destination" + }, + "VirtualSourceAddress": { + "shape": "__string", + "locationName": "virtualSourceAddress", + "documentation": "Specifies the source IP address for outbound multicast packets." } }, "documentation": "Placeholder documentation for OutputDestinationSettings" @@ -19069,7 +19091,12 @@ "StyleControl": { "shape": "TtmlDestinationStyleControl", "locationName": "styleControl", - "documentation": "This field is not currently supported and will not affect the output styling. Leave the default value." + "documentation": "Controls the source of style and position information for the output captions. PASSTHROUGH - Preserve the style and position from the source captions. USE_CONFIGURED - Don't pass through the style. The output captions will use the default styling. MANUAL - Applies the specified styling and positioning. All other styling and positioning is given default values." + }, + "Position": { + "shape": "TextCaptionPositionSettings", + "locationName": "position", + "documentation": "Specifies the position of the output captions. Applies only when styleControl is set to manual." } }, "documentation": "Ttml Destination Settings" @@ -19079,7 +19106,8 @@ "documentation": "Ttml Destination Style Control", "enum": [ "PASSTHROUGH", - "USE_CONFIGURED" + "USE_CONFIGURED", + "MANUAL" ] }, "UdpContainerSettings": { @@ -20104,6 +20132,21 @@ "shape": "__integer", "locationName": "width", "documentation": "Output video width, in pixels. Must be an even number. For most codecs, you can leave this field and height blank in order to use the height and width (resolution) from the source. Note, however, that leaving blank is not recommended. For the Frame Capture codec, height and width are required." + }, + "CropRectangle": { + "shape": "VideoPositionRectangle", + "locationName": "cropRectangle", + "documentation": "Region of the input video to crop before scaling. If not specified, the entire input\nframe is used.\n\nNote: Unlike {@link outputPositionRectangle}, the bounds of cropRectangle are validated\nat ingest time by the encoder/scaler rather than at the API level, because the input\nresolution is not known until the source is probed. Field-level constraints on (x, y,\nwidth, height) defined on {@link VideoPositionRectangle} still apply." + }, + "OutputPositionRectangle": { + "shape": "VideoPositionRectangle", + "locationName": "outputPositionRectangle", + "documentation": "Position of the encoded video within the output frame. The area outside the rectangle\nis filled with black. If not specified, the video fills the entire output frame.\nWhen used, both {@link width} and {@link height} of the VideoDescription must be\nexplicitly specified so that the rectangle can be validated against the output frame." + }, + "Border": { + "shape": "__integerMin0Max100", + "locationName": "border", + "documentation": "Specifies the number of pixels of black border that will be inserted around the edge\nof the encoded picture. Must be an even integer from 0 (no border, the default) up\nto 100. The width and height of the VideoDescription must each be greater than twice\nthis value. Cannot be used together with {@link outputPositionRectangle} -- both\ngovern the position of the encoded content within the output frame." } }, "documentation": "Video settings for this stream.", @@ -20307,7 +20350,12 @@ "StyleControl": { "shape": "WebvttDestinationStyleControl", "locationName": "styleControl", - "documentation": "Controls whether the color and position of the source captions is passed through to the WebVTT output captions. PASSTHROUGH - Valid only if the source captions are EMBEDDED or TELETEXT. NO_STYLE_DATA - Don't pass through the style. The output captions will not contain any font styling information." + "documentation": "Controls whether the color and position of the source captions is passed through to the WebVTT output captions. PASSTHROUGH - Valid only if the source captions are EMBEDDED, TELETEXT, or SMART SUBTITLES. NO_STYLE_DATA - Don't pass through the style. The output captions will not contain any font styling information. MANUAL - Applies the specified styling and positioning. All other styling and positioning is given default values." + }, + "Position": { + "shape": "TextCaptionPositionSettings", + "locationName": "position", + "documentation": "Specifies the position of the output captions. Applies only when styleControl is set to manual." } }, "documentation": "Webvtt Destination Settings" @@ -20317,7 +20365,8 @@ "documentation": "Webvtt Destination Style Control", "enum": [ "NO_STYLE_DATA", - "PASSTHROUGH" + "PASSTHROUGH", + "MANUAL" ] }, "__boolean": { @@ -21354,7 +21403,7 @@ "Scte35Type": { "shape": "Scte35Type", "locationName": "scte35Type", - "documentation": "Type of scte35 track to add. none or scte35WithoutSegmentation" + "documentation": "SCTE-35 insertion type. Option \"none\" indicates that a SCTE-35 marker will not be inserted, nor will an IDR be inserted at the SCTE-35 cue point, nor will the segment be segmented. Option \"scte35WithoutIdr\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, but MediaLive will not insert an IDR on that frame nor will it introduce a new segment boundary there if it wasn't already going to be one (this option is required for use with downstream multiview bitstream stitching workflows). Option \"scte35WithoutSegmentation\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, and an IDR will be inserted on that frame so that a downstream re-packager might split the segment there, but MediaLive itself will not introduce a new segment boundary there." }, "SegmentLength": { "shape": "__integerMin1", @@ -21425,6 +21474,11 @@ "shape": "__listOfAdditionalDestinations", "locationName": "additionalDestinations", "documentation": "Optional an array of additional destinational HTTP destinations for the OutputGroup outputs" + }, + "WatermarkingSettings": { + "shape": "CmafIngestWatermarkingSettings", + "locationName": "watermarkingSettings", + "documentation": "Specifies the type of watermarking technology to use." } }, "documentation": "Cmaf Ingest Group Settings", @@ -21525,7 +21579,8 @@ "documentation": "Scte35 Type", "enum": [ "NONE", - "SCTE_35_WITHOUT_SEGMENTATION" + "SCTE_35_WITHOUT_SEGMENTATION", + "SCTE_35_WITHOUT_IDR" ] }, "BadRequestExceptionResponseContent": { @@ -29035,7 +29090,7 @@ "Scte35Control": { "shape": "M2tsScte35Control", "locationName": "scte35Control", - "documentation": "Optionally pass SCTE-35 signals from the input source to this output." + "documentation": "SCTE-35 control. Option \"none\" indicates that a SCTE-35 marker will not be inserted, nor will an IDR be inserted at the SCTE-35 cue point, nor will the segment be segmented. Option \"scte35WithoutIdr\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, but MediaLive will not insert an IDR on that frame nor will it introduce a new segment boundary there if it wasn't already going to be one (this option is required for use with downstream multiview bitstream stitching workflows). Option \"passthrough\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, and an IDR will be inserted on that frame, and MediaLive itself will introduce a new segment boundary there." }, "Scte35PrerollPullupMilliseconds": { "shape": "__doubleMin0Max5000", @@ -29711,6 +29766,11 @@ "shape": "HlsDefault", "locationName": "hlsDefault", "documentation": "Specifies whether MediaPackage should set this output as the default rendition in the HLS manifest. YES means this must be the default. NO means this should never be the default. OMIT means MediaPackage decides what to set on this rendition.\nWhen you consider all the renditions, follow these guidelines. You can set zero or one renditions to YES. You can set zero or more renditions to NO, but you can't set all renditions to NO. You can set zero, some, or all to OMIT." + }, + "OutputUsage": { + "shape": "__listOfOutputUsage", + "locationName": "outputUsage", + "documentation": "List of usage tags declaring how this MediaPackage V2 output is used. Currently these are all multiview-related (multiviewPrimaryView, multiviewSecondaryView, multiviewEqualSizeView) and enable multiview validations and augmentations to help ensure proper multiview configuration and compatibility with MediaPackage. Leave empty (the default) if this output has no multiview role. If any video-carrying MediaPackage V2 output in an output group specifies a multiview value, every video-carrying MediaPackage V2 output in the group must also specify a multiview value; place standalone video outputs in a separate output group." } }, "documentation": "Media Package V2 Destination Settings" @@ -29741,7 +29801,7 @@ "Scte35Type": { "shape": "Scte35Type", "locationName": "scte35Type", - "documentation": "Type of scte35 track to add. none or scte35WithoutSegmentation" + "documentation": "SCTE-35 insertion type. Option \"none\" indicates that a SCTE-35 marker will not be inserted, nor will an IDR be inserted at the SCTE-35 cue point, nor will the segment be segmented. Option \"scte35WithoutIdr\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, but MediaLive will not insert an IDR on that frame nor will it introduce a new segment boundary there if it wasn't already going to be one (this option is required for use with downstream multiview bitstream stitching workflows). Option \"scte35WithoutSegmentation\" indicates that a SCTE-35 marker will be inserted to indicate the cue point, and an IDR will be inserted on that frame so that a downstream re-packager might split the segment there, but MediaLive itself will not introduce a new segment boundary there." }, "SegmentLength": { "shape": "__integerMin1", @@ -29772,6 +29832,11 @@ "shape": "__listOfMediaPackageAdditionalDestinations", "locationName": "additionalDestinations", "documentation": "Optional an array of additional destinational HTTP destinations for the OutputGroup outputs" + }, + "WatermarkingSettings": { + "shape": "MediaPackageV2WatermarkingSettings", + "locationName": "watermarkingSettings", + "documentation": "Specifies the type of watermarking technology to use." } }, "documentation": "Media Package V2 Group Settings" @@ -30555,6 +30620,11 @@ "shape": "__listOfAudioFeedInput", "locationName": "audioFeedInputs", "documentation": "A list of audio feed inputs that map audio selectors in the channel to feed inputs on the associated Elemental Inference feed." + }, + "EnrichmentMethods": { + "shape": "__listOfEnrichmentMethod", + "locationName": "enrichmentMethods", + "documentation": "The set of Contextual Metadata Enrichment methods enabled for this channel. Each method represents a specific way the channel uses the inference feed to augment its output with contextual metadata." } }, "documentation": "Configures Elemental Inference features in a channel." @@ -30571,6 +30641,11 @@ "shape": "__listOfAudioFeedInput", "locationName": "audioFeedInputs", "documentation": "A list of audio feed inputs that map audio selectors in the channel to feed inputs on the associated Elemental Inference feed." + }, + "EnrichmentMethods": { + "shape": "__listOfEnrichmentMethod", + "locationName": "enrichmentMethods", + "documentation": "The set of Contextual Metadata Enrichment methods enabled for this channel. Each method represents a specific way the channel will use the inference feed to augment its output with contextual metadata. An empty array (or omitting the field) disables enrichment. Order is not significant; duplicate values are not permitted." } }, "documentation": "Configures Elemental Inference features in a channel." @@ -30818,6 +30893,311 @@ "shape": "AudioPid" }, "documentation": "Placeholder documentation for __listOfAudioPid" + }, + "NielsenNwOnly": { + "type": "structure", + "members": { + "CheckDigitString": { + "shape": "__stringMin2Max2", + "locationName": "checkDigitString", + "documentation": "Enter the check digit string for the watermark" + }, + "Sid": { + "shape": "__doubleMin1Max65535", + "locationName": "sid", + "documentation": "Enter the Nielsen Source ID (SID) to include in the watermark" + }, + "Timezone": { + "shape": "NielsenWatermarkTimezones", + "locationName": "timezone", + "documentation": "Choose the timezone for the time stamps in the watermark. If not provided,\nthe timestamps will be in Coordinated Universal Time (UTC)" + } + }, + "documentation": "Nielsen Nw Only", + "required": [ + "CheckDigitString", + "Sid" + ] + }, + "VideoPositionRectangle": { + "type": "structure", + "members": { + "Height": { + "shape": "__integerMin2Max8192", + "locationName": "height", + "documentation": "Height in pixels. Must be an even number." + }, + "Width": { + "shape": "__integerMin2Max8192", + "locationName": "width", + "documentation": "Width in pixels. Must be an even number." + }, + "X": { + "shape": "__integerMin0Max8190", + "locationName": "x", + "documentation": "Left offset in pixels. Must be an even number." + }, + "Y": { + "shape": "__integerMin0Max8190", + "locationName": "y", + "documentation": "Top offset in pixels. Must be an even number." + } + }, + "documentation": "A rectangle defined by position (x, y) and dimensions (width, height) in pixels.\nUsed for output positioning and input cropping.", + "required": [ + "X", + "Y", + "Height", + "Width" + ] + }, + "__integerMin0Max8190": { + "type": "integer", + "documentation": "Placeholder documentation for __integerMin0Max8190" + }, + "__integerMin2Max8192": { + "type": "integer", + "documentation": "Placeholder documentation for __integerMin2Max8192" + }, + "AbWatermarkerIdLength": { + "type": "string", + "documentation": "Ab Watermarker Id Length", + "enum": [ + "ID_2048", + "ID_512" + ] + }, + "AbWatermarkingCustomProfile": { + "type": "structure", + "members": { + "EmbeddingFrequency": { + "shape": "__doubleMin250Max5000", + "locationName": "embeddingFrequency", + "documentation": "The frequency with which watermarks will be embedded, in milliseconds." + }, + "SceneCut": { + "shape": "__doubleMinNegative1Max5", + "locationName": "sceneCut", + "documentation": "The number of frames after scene-cut to embed the watermark." + }, + "TargetPsnr": { + "shape": "__doubleMin32Max46", + "locationName": "targetPsnr", + "documentation": "The target PSNR of the watermarked frame" + } + }, + "documentation": "The vendor-specified custom profile options", + "required": [ + "SceneCut", + "EmbeddingFrequency", + "TargetPsnr" + ] + }, + "AbWatermarkingProfile": { + "type": "string", + "documentation": "Ab Watermarking Profile", + "enum": [ + "CAMCORDING", + "CUSTOM", + "DEFAULT", + "HQ", + "MEZZANINE", + "ROBUST" + ] + }, + "CmafIngestAbWatermarkerIrdetoSettings": { + "type": "structure", + "members": { + "AdditionalDestinationsAlternateDestinations": { + "shape": "__listOfOutputLocationRef", + "locationName": "additionalDestinationsAlternateDestinations", + "documentation": "The \"B\" pipeline renditions for the additional destinations." + }, + "AlternateDestination": { + "shape": "OutputLocationRef", + "locationName": "alternateDestination", + "documentation": "The \"B\" pipeline renditions for the main destination." + }, + "CustomProfile": { + "shape": "AbWatermarkingCustomProfile", + "locationName": "customProfile", + "documentation": "The vendor-provided custom profile values." + }, + "License": { + "shape": "__string", + "locationName": "license", + "documentation": "The name of the Secrets Manager secret containing the license file." + }, + "OperatorId": { + "shape": "__integerMin1Max511", + "locationName": "operatorId", + "documentation": "The vendor-provided Operator ID." + }, + "PolyPeriod": { + "shape": "__integerMin1Max1000", + "locationName": "polyPeriod", + "documentation": "The number of segments per watermarking bit. The total duration of the watermarking bit\nshould be the LCM (least common multiple) of all segments sizes emitted by the downstream packager." + }, + "Profile": { + "shape": "AbWatermarkingProfile", + "locationName": "profile", + "documentation": "The vendor-provided profile choice." + }, + "WatermarkIdLength": { + "shape": "AbWatermarkerIdLength", + "locationName": "watermarkIdLength", + "documentation": "The number of bits that compose the watermarking identifier to be embedded." + } + }, + "documentation": "A/B Watermarker settings for CMAF Ingest output groups.", + "required": [ + "AlternateDestination", + "OperatorId", + "Profile" + ] + }, + "CmafIngestWatermarkingSettings": { + "type": "structure", + "members": { + "CmafIngestAbWatermarkerIrdetoSettings": { + "shape": "CmafIngestAbWatermarkerIrdetoSettings", + "locationName": "cmafIngestAbWatermarkerIrdetoSettings" + } + }, + "documentation": "A/B Watermarker settings for CMAF Ingest output groups." + }, + "MediaPackageV2AbWatermarkerIrdetoSettings": { + "type": "structure", + "members": { + "AdditionalDestinationsAlternateDestinations": { + "shape": "__listOfOutputLocationRef", + "locationName": "additionalDestinationsAlternateDestinations", + "documentation": "The \"B\" pipeline renditions for the additional destinations." + }, + "AlternateDestination": { + "shape": "OutputLocationRef", + "locationName": "alternateDestination", + "documentation": "The \"B\" pipeline renditions for the main destination." + }, + "CustomProfile": { + "shape": "AbWatermarkingCustomProfile", + "locationName": "customProfile", + "documentation": "The vendor-provided custom profile values." + }, + "License": { + "shape": "__string", + "locationName": "license", + "documentation": "The name of the Secrets Manager secret containing the license file." + }, + "OperatorId": { + "shape": "__integerMin1Max511", + "locationName": "operatorId", + "documentation": "The vendor-provided Operator ID." + }, + "PolyPeriod": { + "shape": "__integerMin1Max1000", + "locationName": "polyPeriod", + "documentation": "The number of segments per watermarking bit. The total duration of the watermarking bit\nshould be the LCM (least common multiple) of all segments sizes emitted by the downstream packager." + }, + "Profile": { + "shape": "AbWatermarkingProfile", + "locationName": "profile", + "documentation": "The vendor-provided profile choice." + }, + "WatermarkIdLength": { + "shape": "AbWatermarkerIdLength", + "locationName": "watermarkIdLength", + "documentation": "The number of bits that compose the watermarking identifier to be embedded." + } + }, + "documentation": "A/B Watermarker settings for MediaPackage V2 output groups.", + "required": [ + "AlternateDestination", + "OperatorId", + "Profile" + ] + }, + "MediaPackageV2WatermarkingSettings": { + "type": "structure", + "members": { + "MediaPackageV2AbWatermarkerIrdetoSettings": { + "shape": "MediaPackageV2AbWatermarkerIrdetoSettings", + "locationName": "mediaPackageV2AbWatermarkerIrdetoSettings" + } + }, + "documentation": "A/B Watermarker settings for MediaPackage V2 output groups." + }, + "__integerMin1Max1000": { + "type": "integer", + "documentation": "Placeholder documentation for __integerMin1Max1000" + }, + "__integerMin1Max511": { + "type": "integer", + "documentation": "Placeholder documentation for __integerMin1Max511" + }, + "EnrichmentMethod": { + "type": "string", + "documentation": "A Contextual Metadata Enrichment method. Each value selects a strategy for enriching the channel's output with contextual metadata derived from the Elemental Inference feed. SCTE35_ELEMENTAL_INFERENCE_QUERY_PARAMS enriches outbound SCTE-35 messages with query parameters that downstream systems can use to call the Elemental Inference GetMetadata API.", + "enum": [ + "SCTE35_ELEMENTAL_INFERENCE_QUERY_PARAMS" + ] + }, + "__listOfEnrichmentMethod": { + "type": "list", + "member": { + "shape": "EnrichmentMethod" + }, + "documentation": "Placeholder documentation for __listOfEnrichmentMethod" + }, + "EmbeddedCaptionPositionSettings": { + "type": "structure", + "members": { + "YPositionLine": { + "shape": "__integerMin1Max15", + "locationName": "yPositionLine", + "documentation": "Specifies the vertical position of the caption as a row counted from the top of the output. Row 1 is the topmost row. Acceptable values are 1 through 15." + } + }, + "documentation": "Embedded Caption Position Settings" + }, + "EmbeddedDestinationStyleControl": { + "type": "string", + "documentation": "Controls the source of position and style information for embedded outputs.\n- \"passthrough\": Carry the caption position and style from the source captions. When the source captions are embedded, SCTE-20, or ancillary, the position and style are preserved exactly. When the source captions are another format, the position and any supported style are carried over.\n- \"manual\": Use the position specified in the destination's position field.", + "enum": [ + "MANUAL", + "PASSTHROUGH" + ] + }, + "TextCaptionPositionSettings": { + "type": "structure", + "members": { + "YPositionPercentage": { + "shape": "__integerMin0Max100", + "locationName": "yPositionPercentage", + "documentation": "Specifies the vertical position of the top edge of the caption relative to the top of the output as a percentage. A value of 0 places the caption at the top of the output and 100 at the bottom." + } + }, + "documentation": "Text Caption Position Settings" + }, + "__integerMin1Max15": { + "type": "integer", + "documentation": "Placeholder documentation for __integerMin1Max15" + }, + "OutputUsage": { + "type": "string", + "documentation": "Output Usage", + "enum": [ + "MULTIVIEW_EQUAL_SIZE_VIEW", + "MULTIVIEW_PRIMARY_VIEW", + "MULTIVIEW_SECONDARY_VIEW" + ] + }, + "__listOfOutputUsage": { + "type": "list", + "member": { + "shape": "OutputUsage" + }, + "documentation": "Placeholder documentation for __listOfOutputUsage" } }, "documentation": "API for AWS Elemental MediaLive" diff --git a/services/medialive/src/main/resources/codegen-resources/waiters-2.json b/services/medialive/src/main/resources/codegen-resources/waiters-2.json index d95e09abe9f2..2481f5a57ebb 100644 --- a/services/medialive/src/main/resources/codegen-resources/waiters-2.json +++ b/services/medialive/src/main/resources/codegen-resources/waiters-2.json @@ -58,7 +58,7 @@ ] }, "ChannelStopped": { - "description": "Wait until a channel has is stopped", + "description": "Wait until a channel is not running", "operation": "DescribeChannel", "delay": 5, "maxAttempts": 60, @@ -79,6 +79,23 @@ "state": "retry", "matcher": "status", "expected": 500 + }, + { + "state": "success", + "matcher": "path", + "argument": "State", + "expected": "DELETING" + }, + { + "state": "success", + "matcher": "path", + "argument": "State", + "expected": "DELETED" + }, + { + "state": "failure", + "matcher": "error", + "expected": "NotFoundException" } ] }, diff --git a/services/mediapackage/pom.xml b/services/mediapackage/pom.xml index b4c94b82ddef..f7f3c12d3a07 100644 --- a/services/mediapackage/pom.xml +++ b/services/mediapackage/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 mediapackage diff --git a/services/mediapackage/src/main/resources/codegen-resources/customization.config b/services/mediapackage/src/main/resources/codegen-resources/customization.config index 37a289229927..ee587bd61c35 100644 --- a/services/mediapackage/src/main/resources/codegen-resources/customization.config +++ b/services/mediapackage/src/main/resources/codegen-resources/customization.config @@ -10,6 +10,5 @@ // Do not keep adding to this list. Require the service team to name enums like they're naming their shapes. "__AdTriggersElement": "AdTriggersElement", "__PeriodTriggersElement": "PeriodTriggersElement" - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/mediapackage/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediapackage/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0f441eecd25d --- /dev/null +++ b/services/mediapackage/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediapackage/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediapackage/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 73f1ff52c7e1..000000000000 --- a/services/mediapackage/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediapackagev2/pom.xml b/services/mediapackagev2/pom.xml index 584c2058aa92..fb3ff215b7d1 100644 --- a/services/mediapackagev2/pom.xml +++ b/services/mediapackagev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mediapackagev2 AWS Java SDK :: Services :: Media Package V2 diff --git a/services/mediapackagev2/src/main/resources/codegen-resources/customization.config b/services/mediapackagev2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/mediapackagev2/src/main/resources/codegen-resources/customization.config +++ b/services/mediapackagev2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..91071b708ad6 --- /dev/null +++ b/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackagev2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackagev2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackagev2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackagev2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 07b5dea6d8a1..000000000000 --- a/services/mediapackagev2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackagev2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackagev2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackagev2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackagev2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/mediapackagev2/src/main/resources/codegen-resources/service-2.json b/services/mediapackagev2/src/main/resources/codegen-resources/service-2.json index f0bf2cffe10d..08b35219433f 100644 --- a/services/mediapackagev2/src/main/resources/codegen-resources/service-2.json +++ b/services/mediapackagev2/src/main/resources/codegen-resources/service-2.json @@ -612,6 +612,11 @@ "SCTE35_ENHANCED" ] }, + "AttachedMultiviewChannelList":{ + "type":"list", + "member":{"shape":"ResourceName"}, + "documentation":"

    A list of the names of multiview channels.

    " + }, "Boolean":{ "type":"boolean", "box":true @@ -770,7 +775,19 @@ }, "InputType":{ "shape":"InputType", - "documentation":"

    The input type will be an immutable field which will be used to define whether the channel will allow CMAF ingest or HLS ingest. If unprovided, it will default to HLS to preserve current behavior.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    " + "documentation":"

    The input type is an immutable field. It defines whether the channel allows CMAF ingest, HLS ingest, or server-side multiview output. Multiview channels receive no ingest of their own. If unprovided, the value defaults to HLS.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    • MULTIVIEW – Server-side multiview. The channel receives no ingest of its own. Instead, it composites video from the source channels in its MultiviewConfiguration into a single tiled output stream.

    " + }, + "OutputLockingMode":{ + "shape":"OutputLockingMode", + "documentation":"

    The output locking mode configured for the channel.

    The allowed values are:

    • EPOCH_LOCKED - The channel uses epoch-locked behavior with deterministic sequence numbering and fixed segment boundaries aligned to epoch time.

    • NON_EPOCH_LOCKED - The channel uses non-epoch-locked behavior with duration-based segment combining and monotonically increasing sequence numbers starting from 0.

    " + }, + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This is present only when InputType is MULTIVIEW.

    " + }, + "AttachedMultiviewChannels":{ + "shape":"AttachedMultiviewChannelList", + "documentation":"

    The multiview channels, in the same channel group, that list this channel as an available source. This is a read-only field.

    " } }, "documentation":"

    The configuration of the channel.

    " @@ -815,6 +832,24 @@ "ISM" ] }, + "ContentKeyPeriodConfiguration":{ + "type":"structure", + "members":{ + "ContentKeyPeriodTiming":{ + "shape":"ContentKeyPeriodTiming", + "documentation":"

    Specifies what timing information MediaPackage signals in the ContentKeyPeriod to your DRM key provider. If you don't specify a value, the default is INDEX_ONLY. Signaling start and end times (START_END_ONLY or INDEX_WITH_START_END) also requires key rotation to be enabled.

    The allowed values are:

    • INDEX_ONLY - Signals only the content key index. This is the default and matches the current behavior. It's supported for both SPEKE Version 2.0 and 2.1.

    • START_END_ONLY - Signals only the start and end times the key is used for. Requires SpekeVersion V2_1.

    • INDEX_WITH_START_END - Signals both the content key index and the start and end times the key is used for. Requires SpekeVersion V2_1.

    " + } + }, + "documentation":"

    The configuration that controls the content key period timing information that MediaPackage signals to your DRM key provider.

    " + }, + "ContentKeyPeriodTiming":{ + "type":"string", + "enum":[ + "INDEX_ONLY", + "START_END_ONLY", + "INDEX_WITH_START_END" + ] + }, "CreateChannelGroupRequest":{ "type":"structure", "required":["ChannelGroupName"], @@ -911,7 +946,7 @@ }, "InputType":{ "shape":"InputType", - "documentation":"

    The input type will be an immutable field which will be used to define whether the channel will allow CMAF ingest or HLS ingest. If unprovided, it will default to HLS to preserve current behavior.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    " + "documentation":"

    The input type is an immutable field. It defines whether the channel allows CMAF ingest, HLS ingest, or server-side multiview output. Multiview channels receive no ingest of their own. If unprovided, the value defaults to HLS.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    • MULTIVIEW – Server-side multiview. The channel receives no ingest of its own. Instead, it composites video from the source channels in its MultiviewConfiguration into a single tiled output stream.

    " }, "Description":{ "shape":"ResourceDescription", @@ -925,6 +960,14 @@ "shape":"OutputHeaderConfiguration", "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN. This setting is valid only when InputType is CMAF.

    " }, + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This setting is required when InputType is MULTIVIEW, and can't be set for any other input type.

    " + }, + "OutputLockingMode":{ + "shape":"OutputLockingMode", + "documentation":"

    The output locking mode for the channel. This setting is only valid when InputType is CMAF. This value is immutable after channel creation. If you don't specify a value, the default is EPOCH_LOCKED.

    The allowed values are:

    • EPOCH_LOCKED - The channel uses epoch-locked behavior with deterministic sequence numbering and fixed segment boundaries aligned to epoch time. This mode supports cross-region synchronization and failover.

    • NON_EPOCH_LOCKED - The channel uses non-epoch-locked behavior with duration-based segment combining and monotonically increasing sequence numbers starting from 0. This mode does not support cross-region synchronization or failover.

    " + }, "Tags":{ "shape":"TagMap", "documentation":"

    A comma-separated list of tag key:value pairs that you define. For example:

    \"Key1\": \"Value1\",

    \"Key2\": \"Value2\"

    ", @@ -942,6 +985,14 @@ "ModifiedAt" ], "members":{ + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This is present only when InputType is MULTIVIEW.

    " + }, + "AttachedMultiviewChannels":{ + "shape":"AttachedMultiviewChannelList", + "documentation":"

    The multiview channels, in the same channel group, that list this channel as an available source. This is a read-only field. You can't delete a channel while any multiview channel still lists it as a source. Use this field to find the multiview channels that you need to update first.

    " + }, "Arn":{ "shape":"String", "documentation":"

    The Amazon Resource Name (ARN) associated with the resource.

    " @@ -969,7 +1020,7 @@ "IngestEndpoints":{"shape":"IngestEndpointList"}, "InputType":{ "shape":"InputType", - "documentation":"

    The input type will be an immutable field which will be used to define whether the channel will allow CMAF ingest or HLS ingest. If unprovided, it will default to HLS to preserve current behavior.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    " + "documentation":"

    The input type is an immutable field. It defines whether the channel allows CMAF ingest, HLS ingest, or server-side multiview output. Multiview channels receive no ingest of their own. If unprovided, the value defaults to HLS.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    • MULTIVIEW – Server-side multiview. The channel receives no ingest of its own. Instead, it composites video from the source channels in its MultiviewConfiguration into a single tiled output stream.

    " }, "ETag":{ "shape":"EntityTag", @@ -986,6 +1037,10 @@ "OutputHeaderConfiguration":{ "shape":"OutputHeaderConfiguration", "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN. This setting is valid only when InputType is CMAF.

    " + }, + "OutputLockingMode":{ + "shape":"OutputLockingMode", + "documentation":"

    The output locking mode configured for the channel.

    The allowed values are:

    • EPOCH_LOCKED - The channel uses epoch-locked behavior with deterministic sequence numbering and fixed segment boundaries aligned to epoch time.

    • NON_EPOCH_LOCKED - The channel uses non-epoch-locked behavior with duration-based segment combining and monotonically increasing sequence numbers starting from 0.

    " } } }, @@ -1441,6 +1496,10 @@ "shape":"UriSeparator", "documentation":"

    The separator character to use in generated URIs for this origin endpoint. This setting applies to all manifest types on the endpoint. If you don't specify a value, the default is UNDERSCORE.

    " }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests. This setting is valid only when the associated channel's InputType is HLS. You can't change the stream name output mode after you create the endpoint.

    INDEX uses numeric indices for stream names (for example, 1, 2, 3). PASSTHROUGH_NAME uses the stream names from the input manifest. If you don't specify a value, the default is INDEX.

    " + }, "Tags":{ "shape":"TagMap", "documentation":"

    A comma-separated list of tag key:value pairs that you define. For example:

    \"Key1\": \"Value1\",

    \"Key2\": \"Value2\"

    " @@ -1530,6 +1589,10 @@ "shape":"UriSeparator", "documentation":"

    The separator character used in generated URIs for this origin endpoint.

    " }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests for this origin endpoint.

    " + }, "ETag":{ "shape":"EntityTag", "documentation":"

    The current Entity Tag (ETag) associated with this resource. The entity tag can be used to safely make concurrent updates to the resource.

    " @@ -2296,6 +2359,14 @@ "ModifiedAt" ], "members":{ + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This is present only when InputType is MULTIVIEW.

    " + }, + "AttachedMultiviewChannels":{ + "shape":"AttachedMultiviewChannelList", + "documentation":"

    The multiview channels, in the same channel group, that list this channel as an available source. This is a read-only field. You can't delete a channel while any multiview channel still lists it as a source. Use this field to find the multiview channels that you need to update first.

    " + }, "Arn":{ "shape":"String", "documentation":"

    The Amazon Resource Name (ARN) associated with the resource.

    " @@ -2327,7 +2398,7 @@ "IngestEndpoints":{"shape":"IngestEndpointList"}, "InputType":{ "shape":"InputType", - "documentation":"

    The input type will be an immutable field which will be used to define whether the channel will allow CMAF ingest or HLS ingest. If unprovided, it will default to HLS to preserve current behavior.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    " + "documentation":"

    The input type is an immutable field. It defines whether the channel allows CMAF ingest, HLS ingest, or server-side multiview output. Multiview channels receive no ingest of their own. If unprovided, the value defaults to HLS.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    • MULTIVIEW – Server-side multiview. The channel receives no ingest of its own. Instead, it composites video from the source channels in its MultiviewConfiguration into a single tiled output stream.

    " }, "ETag":{ "shape":"EntityTag", @@ -2344,6 +2415,10 @@ "OutputHeaderConfiguration":{ "shape":"OutputHeaderConfiguration", "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN. This setting is valid only when InputType is CMAF.

    " + }, + "OutputLockingMode":{ + "shape":"OutputLockingMode", + "documentation":"

    The output locking mode configured for the channel.

    The allowed values are:

    • EPOCH_LOCKED - The channel uses epoch-locked behavior with deterministic sequence numbering and fixed segment boundaries aligned to epoch time.

    • NON_EPOCH_LOCKED - The channel uses non-epoch-locked behavior with duration-based segment combining and monotonically increasing sequence numbers starting from 0.

    " } } }, @@ -2843,6 +2918,10 @@ "shape":"UriSeparator", "documentation":"

    The separator character used in generated URIs for this origin endpoint.

    " }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests for this origin endpoint.

    " + }, "ETag":{ "shape":"EntityTag", "documentation":"

    The current Entity Tag (ETag) associated with this resource. The entity tag can be used to safely make concurrent updates to the resource.

    " @@ -3072,7 +3151,8 @@ "type":"string", "enum":[ "HLS", - "CMAF" + "CMAF", + "MULTIVIEW" ] }, "Integer":{ @@ -3406,6 +3486,50 @@ "COMPACT" ] }, + "MultiviewConfiguration":{ + "type":"structure", + "required":[ + "AvailableSources", + "AvailableLayouts" + ], + "members":{ + "AvailableSources":{ + "shape":"MultiviewSourceList", + "documentation":"

    The channels that players can use as tiles in this multiview channel's output. Each source channel must be in the same channel group as the multiview channel, and must have an InputType of CMAF. Only the channels that you list here are available as tiles.

    " + }, + "AvailableLayouts":{ + "shape":"MultiviewLayoutList", + "documentation":"

    The tile layouts that players can request from this multiview channel's origin endpoints. Only the layouts that you list here are available. Each layout must appear at most once.

    " + } + }, + "documentation":"

    The multiview configuration for a channel. A multiview channel composites video from several source channels into a single tiled output stream. Players receive one standard HLS or DASH stream instead of several separate streams. This setting is required when InputType is MULTIVIEW, and can't be set for any other input type.

    " + }, + "MultiviewLayoutList":{ + "type":"list", + "member":{"shape":"MultiviewLayoutType"}, + "documentation":"

    A list of tile layouts that players can request from a multiview channel's origin endpoints.

    ", + "max":6, + "min":1 + }, + "MultiviewLayoutType":{ + "type":"string", + "documentation":"

    A tile layout for a multiview channel. Each layout determines how many source tiles are composited into the output and how those tiles are arranged.

    The allowed values are:

    • LAYOUT_2EH – Two tiles of equal size, arranged horizontally.

    • LAYOUT_2PL – Two tiles, with one larger primary tile.

    • LAYOUT_3EL – Three tiles of equal size, arranged in two columns.

    • LAYOUT_3PL – Three tiles, with one larger primary tile on the left and two stacked on the right.

    • LAYOUT_4E – Four tiles of equal size, arranged in a two-by-two grid.

    • LAYOUT_4PL – Four tiles, with one larger primary tile on the left and three stacked on the right.

    ", + "enum":[ + "LAYOUT_2EH", + "LAYOUT_2PL", + "LAYOUT_3EL", + "LAYOUT_3PL", + "LAYOUT_4E", + "LAYOUT_4PL" + ] + }, + "MultiviewSourceList":{ + "type":"list", + "member":{"shape":"ResourceName"}, + "documentation":"

    A list of channel names that players can use as tiles in a multiview channel's output.

    ", + "max":10, + "min":1 + }, "OriginEndpointListConfiguration":{ "type":"structure", "required":[ @@ -3471,6 +3595,10 @@ "UriSeparator":{ "shape":"UriSeparator", "documentation":"

    The separator character used in generated URIs for this origin endpoint.

    " + }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests for this origin endpoint.

    " } }, "documentation":"

    The configuration of the origin endpoint.

    " @@ -3489,6 +3617,20 @@ }, "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN.

    " }, + "OutputLockingMode":{ + "type":"string", + "enum":[ + "EPOCH_LOCKED", + "NON_EPOCH_LOCKED" + ] + }, + "OutputTimestampMode":{ + "type":"string", + "enum":[ + "PASSTHROUGH", + "REBASED_TO_CHANNEL_START" + ] + }, "PolicyText":{ "type":"string", "max":6144, @@ -3881,7 +4023,11 @@ "shape":"Scte", "documentation":"

    The SCTE configuration options in the segment settings.

    " }, - "Encryption":{"shape":"Encryption"} + "Encryption":{"shape":"Encryption"}, + "OutputTimestampMode":{ + "shape":"OutputTimestampMode", + "documentation":"

    The output timestamp mode for the origin endpoint's segments. This setting is only configurable on channels with OutputLockingMode set to NON_EPOCH_LOCKED. This value is immutable after endpoint creation. If you don't specify a value, the default is PASSTHROUGH.

    The allowed values are:

    • PASSTHROUGH - Output PTS (Presentation Timestamp) values pass through unchanged from the input.

    • REBASED_TO_CHANNEL_START - Output PTS is rebased relative to the channel start time.

    " + } }, "documentation":"

    The segment configuration, including the segment name, duration, and other configuration values.

    " }, @@ -3942,6 +4088,14 @@ "CertificateArn":{ "shape":"SpekeKeyProviderCertificateArnString", "documentation":"

    The ARN for the certificate that you imported to Amazon Web Services Certificate Manager to add content key encryption to this endpoint. For this feature to work, your DRM key provider must support content key encryption.

    " + }, + "SpekeVersion":{ + "shape":"SpekeVersion", + "documentation":"

    Specifies the SPEKE version used with your DRM key provider. If you don't specify a value, the default is V2_0.

    The allowed values are:

    • V2_0 - Follows the SPEKE Version 2.0 contract and signals only the content key index in key requests. This is the default.

    • V2_1 - Follows the SPEKE Version 2.1 contract and additionally supports signaling the start and end times a content key is used for, using ContentKeyPeriodConfiguration.

    For more information, see SPEKE Version 2.0 payload.

    " + }, + "ContentKeyPeriodConfiguration":{ + "shape":"ContentKeyPeriodConfiguration", + "documentation":"

    The configuration that controls whether MediaPackage signals the start and end times a content key is used for, in the ContentKeyPeriod sent to your DRM key provider. Signaling this timing is supported only when key rotation is enabled (KeyRotationIntervalSeconds is set to a non-zero value) and SpekeVersion is V2_1. You can update these settings on an existing origin endpoint.

    " } }, "documentation":"

    The parameters for the SPEKE key provider.

    " @@ -3974,6 +4128,13 @@ "max":1024, "min":1 }, + "SpekeVersion":{ + "type":"string", + "enum":[ + "V2_0", + "V2_1" + ] + }, "StartTag":{ "type":"structure", "required":["TimeOffset"], @@ -3989,6 +4150,13 @@ }, "documentation":"

    To insert an EXT-X-START tag in your HLS playlist, specify a StartTag configuration object with a valid TimeOffset. When you do, you can also optionally specify whether to include a PRECISE value in the EXT-X-START tag.

    " }, + "StreamNameOutputMode":{ + "type":"string", + "enum":[ + "INDEX", + "PASSTHROUGH_NAME" + ] + }, "String":{"type":"string"}, "SyntheticTimestamp_date_time":{ "type":"timestamp", @@ -4170,6 +4338,10 @@ "OutputHeaderConfiguration":{ "shape":"OutputHeaderConfiguration", "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN. This setting is valid only when InputType is CMAF.

    " + }, + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This setting is required when the channel's InputType is MULTIVIEW, and can't be set for any other input type. Because InputType is immutable, you can change a multiview channel's sources and layouts. You can't add or remove the multiview configuration itself.

    " } } }, @@ -4183,6 +4355,14 @@ "ModifiedAt" ], "members":{ + "MultiviewConfiguration":{ + "shape":"MultiviewConfiguration", + "documentation":"

    The multiview configuration for the channel. This is present only when InputType is MULTIVIEW.

    " + }, + "AttachedMultiviewChannels":{ + "shape":"AttachedMultiviewChannelList", + "documentation":"

    The multiview channels, in the same channel group, that list this channel as an available source. This is a read-only field. You can't delete a channel while any multiview channel still lists it as a source. Use this field to find the multiview channels that you need to update first.

    " + }, "Arn":{ "shape":"String", "documentation":"

    The Amazon Resource Name (ARN) associated with the resource.

    " @@ -4210,7 +4390,7 @@ "IngestEndpoints":{"shape":"IngestEndpointList"}, "InputType":{ "shape":"InputType", - "documentation":"

    The input type will be an immutable field which will be used to define whether the channel will allow CMAF ingest or HLS ingest. If unprovided, it will default to HLS to preserve current behavior.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    " + "documentation":"

    The input type is an immutable field. It defines whether the channel allows CMAF ingest, HLS ingest, or server-side multiview output. Multiview channels receive no ingest of their own. If unprovided, the value defaults to HLS.

    The allowed values are:

    • HLS - The HLS streaming specification (which defines M3U8 manifests and TS segments).

    • CMAF - The DASH-IF CMAF Ingest specification (which defines CMAF segments with optional DASH manifests).

    • MULTIVIEW – Server-side multiview. The channel receives no ingest of its own. Instead, it composites video from the source channels in its MultiviewConfiguration into a single tiled output stream.

    " }, "ETag":{ "shape":"EntityTag", @@ -4228,6 +4408,10 @@ "OutputHeaderConfiguration":{ "shape":"OutputHeaderConfiguration", "documentation":"

    The settings for what common media server data (CMSD) headers AWS Elemental MediaPackage includes in responses to the CDN. This setting is valid only when InputType is CMAF.

    " + }, + "OutputLockingMode":{ + "shape":"OutputLockingMode", + "documentation":"

    The output locking mode configured for the channel. This value is immutable after channel creation.

    The allowed values are:

    • EPOCH_LOCKED - The channel uses epoch-locked behavior with deterministic sequence numbering and fixed segment boundaries aligned to epoch time.

    • NON_EPOCH_LOCKED - The channel uses non-epoch-locked behavior with duration-based segment combining and monotonically increasing sequence numbers starting from 0.

    " } } }, @@ -4298,6 +4482,10 @@ "shape":"UriSeparator", "documentation":"

    The separator character to use in generated URIs for this origin endpoint. This setting applies to all manifest types on the endpoint. If you don't specify a value in the update request, the current value is preserved.

    " }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests. If you provide a value, it must match the current value. You can't change the stream name output mode after you create the endpoint.

    " + }, "ETag":{ "shape":"EntityTag", "documentation":"

    The expected current Entity Tag (ETag) for the resource. If the specified ETag does not match the resource's current entity tag, the update request will be rejected.

    ", @@ -4385,6 +4573,10 @@ "shape":"UriSeparator", "documentation":"

    The separator character used in generated URIs for this origin endpoint.

    " }, + "StreamNameOutputMode":{ + "shape":"StreamNameOutputMode", + "documentation":"

    The output mode for stream names in egress manifests for this origin endpoint.

    " + }, "ETag":{ "shape":"EntityTag", "documentation":"

    The current Entity Tag (ETag) associated with this resource. The entity tag can be used to safely make concurrent updates to the resource.

    " @@ -4528,7 +4720,39 @@ "MISSING_CERTIFICATE_DOMAIN_NAME", "INVALID_ARN", "SCTE_IN_MANIFESTS_INVALID_CONFIGURATION", - "CUSTOM_AD_TYPES_INVALID_CONFIGURATION" + "CUSTOM_AD_TYPES_INVALID_CONFIGURATION", + "ONLY_CMAF_INPUT_TYPE_ALLOW_OUTPUT_LOCKING_MODE", + "ONLY_NON_EPOCH_LOCKED_ALLOW_OUTPUT_TIMESTAMP_MODE", + "OUTPUT_TIMESTAMP_MODE_IMMUTABLE", + "NON_EPOCH_LOCKED_WITH_FORCE_ENDPOINT_ERROR_CONFIGURATION", + "ONLY_HLS_INPUT_TYPE_ALLOW_STREAM_NAME_OUTPUT_MODE", + "STREAM_NAME_OUTPUT_MODE_IMMUTABLE", + "MULTIVIEW_CONFIGURATION_REQUIRED", + "MULTIVIEW_CONFIGURATION_NOT_ALLOWED", + "MULTIVIEW_SOURCE_NOT_FOUND", + "MULTIVIEW_SOURCE_INVALID_INPUT_TYPE", + "MULTIVIEW_CHANNEL_POLICY_NOT_ALLOWED", + "MULTIVIEW_INPUT_TYPE_WITH_LL_HLS_MANIFEST", + "MULTIVIEW_INPUT_TYPE_WITH_MSS_MANIFEST", + "MULTIVIEW_INPUT_TYPE_WITH_ISM_CONTAINER", + "MULTIVIEW_INPUT_TYPE_WITH_FILTER_CONFIGURATION", + "MULTIVIEW_INPUT_TYPE_WITH_START_TAG", + "MULTIVIEW_INPUT_TYPE_WITH_HARVEST_JOB", + "MULTIVIEW_RESET_NOT_ALLOWED", + "MULTIVIEW_DUPLICATE_SOURCE", + "MULTIVIEW_DUPLICATE_LAYOUT", + "MULTIVIEW_INPUT_SWITCH_NOT_ALLOWED", + "MULTIVIEW_OUTPUT_HEADER_NOT_ALLOWED", + "MULTIVIEW_STARTOVER_WINDOW_NOT_ALLOWED", + "MULTIVIEW_INVALID_TIME_DELAY_SECONDS", + "MULTIVIEW_MANIFEST_WINDOW_TOO_LONG", + "MULTIVIEW_INPUT_TYPE_WITH_IFRAME_ONLY_STREAMS", + "MULTIVIEW_INPUT_TYPE_WITH_NON_EPOCH_LOCKED", + "MULTIVIEW_INPUT_TYPE_WITH_SEGMENT_DURATION", + "MULTIVIEW_SOURCE_NON_EPOCH_LOCKED", + "MULTIVIEW_SCTE_REQUIRES_AVAILS_PERIOD_TRIGGER", + "CONTENT_KEY_PERIOD_TIMING_WITHOUT_KEY_ROTATION", + "CONTENT_KEY_PERIOD_TIMING_REQUIRES_SPEKE_V2_1" ] } }, diff --git a/services/mediapackagevod/pom.xml b/services/mediapackagevod/pom.xml index f63373e273cc..85745740f2e9 100644 --- a/services/mediapackagevod/pom.xml +++ b/services/mediapackagevod/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mediapackagevod AWS Java SDK :: Services :: MediaPackage Vod diff --git a/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c6d16eff9ed4 --- /dev/null +++ b/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-vod-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-vod-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-vod.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediapackage-vod.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ff8498433197..000000000000 --- a/services/mediapackagevod/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-vod-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-vod-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-vod.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediapackage-vod.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediastore/pom.xml b/services/mediastore/pom.xml index a2327b4cd8c6..1292ffd99c06 100644 --- a/services/mediastore/pom.xml +++ b/services/mediastore/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 mediastore diff --git a/services/mediastore/src/main/resources/codegen-resources/customization.config b/services/mediastore/src/main/resources/codegen-resources/customization.config index 1d165fcb810b..228615d70078 100644 --- a/services/mediastore/src/main/resources/codegen-resources/customization.config +++ b/services/mediastore/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "describeContainer" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mediastore/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediastore/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..200d921ee034 --- /dev/null +++ b/services/mediastore/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediastore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediastore-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediastore.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediastore.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediastore/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediastore/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4da8182149d7..000000000000 --- a/services/mediastore/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediastore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediastore-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mediastore.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mediastore.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediastoredata/pom.xml b/services/mediastoredata/pom.xml index d0bbec83b96e..d7107929986e 100644 --- a/services/mediastoredata/pom.xml +++ b/services/mediastoredata/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 mediastoredata diff --git a/services/mediastoredata/src/main/resources/codegen-resources/customization.config b/services/mediastoredata/src/main/resources/codegen-resources/customization.config index 32a48c48174d..a5746334a293 100644 --- a/services/mediastoredata/src/main/resources/codegen-resources/customization.config +++ b/services/mediastoredata/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "excludedSimpleMethods" : [ "listItems" ] diff --git a/services/mediastoredata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediastoredata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..488718dfa924 --- /dev/null +++ b/services/mediastoredata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.mediastore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.mediastore-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.mediastore.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.mediastore.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediastoredata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediastoredata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9050cffc210e..000000000000 --- a/services/mediastoredata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.mediastore-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.mediastore-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.mediastore.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://data.mediastore.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mediatailor/pom.xml b/services/mediatailor/pom.xml index 047d7a2b238b..46e7c24d2505 100644 --- a/services/mediatailor/pom.xml +++ b/services/mediatailor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mediatailor AWS Java SDK :: Services :: MediaTailor diff --git a/services/mediatailor/src/main/resources/codegen-resources/customization.config b/services/mediatailor/src/main/resources/codegen-resources/customization.config index df53e3257979..fed460fcf047 100644 --- a/services/mediatailor/src/main/resources/codegen-resources/customization.config +++ b/services/mediatailor/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listPlaybackConfigurations" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mediatailor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mediatailor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3c9fd7ab07ba --- /dev/null +++ b/services/mediatailor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mediatailor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.mediatailor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.mediatailor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.mediatailor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.mediatailor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABQAAAAcF9eELAAAABgX14QQAAAAIAAAABwX14QkF9eEKAAAABAAAAAsAAAAKAAAABQX14QYF9eEIAAAABQAAAAwF9eEHAAAABwX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/mediatailor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mediatailor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e0a50933f2c9..000000000000 --- a/services/mediatailor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,387 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://mediatailor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.mediatailor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.mediatailor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.mediatailor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.mediatailor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/mediatailor/src/main/resources/codegen-resources/service-2.json b/services/mediatailor/src/main/resources/codegen-resources/service-2.json index 344d67aa7400..66e61fdac088 100644 --- a/services/mediatailor/src/main/resources/codegen-resources/service-2.json +++ b/services/mediatailor/src/main/resources/codegen-resources/service-2.json @@ -687,6 +687,10 @@ "HttpRequest":{ "shape":"HttpRequest", "documentation":"

    The HTTP request configuration parameters for the ad decision server.

    " + }, + "VastResponse":{ + "shape":"VastResponse", + "documentation":"

    The settings that control how MediaTailor processes VAST responses from the ad decision server.

    " } }, "documentation":"

    Configuration parameters for customizing HTTP requests sent to the ad decision server (ADS). This allows you to specify the HTTP method, headers, request body, and compression settings for ADS requests.

    " @@ -708,8 +712,18 @@ "SCTE35_ENHANCED" ] }, + "AdSequencingMode":{ + "type":"string", + "enum":[ + "FOLLOW_AD_SEQUENCE", + "IGNORE_AD_SEQUENCE", + "FOLLOW_AD_SEQUENCE_ONLY_LIVE", + "FOLLOW_AD_SEQUENCE_ONLY_VOD" + ] + }, "AdsInteractionExcludeEventType":{ "type":"string", + "documentation":"

    An ADS interaction log event type that MediaTailor emits by default and that you can suppress. For descriptions of each event type, see MediaTailor ADS logs description and event types in Elemental MediaTailor User Guide.

    ", "enum":[ "AD_MARKER_FOUND", "NON_AD_MARKER_FOUND", @@ -753,7 +767,11 @@ "INTERSTITIAL_VOD_SUCCESS", "INTERSTITIAL_VOD_FAILURE", "PRE_ADS_REQUEST_HOOK_ERROR", - "PRE_ADS_REQUEST_FUNCTION_ERROR" + "PRE_ADS_REQUEST_FUNCTION_ERROR", + "POST_ADS_RESPONSE_HOOK_ERROR", + "POST_ADS_RESPONSE_FUNCTION_ERROR", + "PRE_MANIFEST_INSERTION_HOOK_ERROR", + "PRE_MANIFEST_INSERTION_FUNCTION_ERROR" ] }, "AdsInteractionLog":{ @@ -761,7 +779,7 @@ "members":{ "PublishOptInEventTypes":{ "shape":"__adsInteractionPublishOptInEventTypesList", - "documentation":"

    Indicates that MediaTailor emits RAW_ADS_RESPONSE logs for playback sessions that are initialized with this configuration.

    " + "documentation":"

    Indicates that MediaTailor will emit the selected events in the logs for playback sessions that are initialized with this configuration. These events are not emitted by default and must be explicitly opted in. For descriptions of each event type, see MediaTailor ADS logs description and event types in Elemental MediaTailor User Guide.

    " }, "ExcludeEventTypes":{ "shape":"__adsInteractionExcludeEventTypesList", @@ -772,13 +790,60 @@ }, "AdsInteractionPublishOptInEventType":{ "type":"string", + "documentation":"

    An ADS interaction log event type that MediaTailor emits only when you opt in to it. For descriptions of each event type, see MediaTailor ADS logs description and event types in Elemental MediaTailor User Guide.

    ", "enum":[ "RAW_ADS_RESPONSE", "RAW_ADS_REQUEST", + "RAW_BID_REQUEST", + "RAW_BID_RESPONSE", "PRE_ADS_REQUEST_HOOK_SUMMARY", - "PRE_ADS_REQUEST_FUNCTION_COMPLETED" + "PRE_ADS_REQUEST_FUNCTION_COMPLETED", + "POST_ADS_RESPONSE_HOOK_SUMMARY", + "POST_ADS_RESPONSE_FUNCTION_COMPLETED", + "PRE_MANIFEST_INSERTION_HOOK_SUMMARY", + "PRE_MANIFEST_INSERTION_FUNCTION_COMPLETED" ] }, + "AdsPersonalizationConcurrency":{ + "type":"structure", + "members":{ + "MaxConcurrentAdsRequests":{ + "shape":"__integer", + "documentation":"

    The maximum number of simultaneous requests that MediaTailor makes to the ad decision server per manifest request. The default is 1.

    " + }, + "EnableVodVastParallelization":{ + "shape":"__boolean", + "documentation":"

    Enables parallel processing of ad decision server requests in VOD workflows when the ADS returns VAST responses. The default is false.

    " + } + }, + "documentation":"

    The concurrency settings for ad decision server interactions during ad personalization.

    " + }, + "AdsPersonalizationTimeouts":{ + "type":"structure", + "members":{ + "AdsRequestTimeoutMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum time, in milliseconds, that MediaTailor waits for a single ad decision server response during live or VOD playback. The default is 3000.

    " + }, + "LiveMaximumAdsPersonalizationTimeMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum total time, in milliseconds, that MediaTailor spends on ad decision server activity for live manifests, including making requests, waiting for responses, and following VAST wrapper redirects. The default is 10000.

    " + }, + "VodMaximumAdsPersonalizationTimeMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum total time, in milliseconds, that MediaTailor spends on ad decision server activity for VOD manifests, including making requests, waiting for responses, and following VAST wrapper redirects. The default is 10000.

    " + }, + "PrefetchAdsRequestTimeoutMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum time, in milliseconds, that MediaTailor waits for a single ad decision server response during prefetch retrieval. If not set, the value of AdsRequestTimeoutMilliseconds is used.

    " + }, + "PrefetchMaximumAdsPersonalizationTimeMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum total time, in milliseconds, that MediaTailor spends on ad decision server activity during prefetch retrieval, including making requests, waiting for responses, and following VAST wrapper redirects.

    " + } + }, + "documentation":"

    The timeout settings for ad decision server interactions during ad personalization.

    " + }, "Alert":{ "type":"structure", "required":[ @@ -855,6 +920,21 @@ }, "documentation":"

    A playlist of media (VOD and/or live) to be played instead of the default media on a particular program.

    " }, + "ApsPublisherId":{ + "type":"string", + "max":36, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "ApsRegion":{ + "type":"string", + "documentation":"

    Supported Amazon Publisher Services regions for yield optimization integration. The region selection affects latency and ad inventory availability, so choose the region closest to your primary audience.

    ", + "enum":[ + "AMERICAS", + "EUROPE", + "ASIA_PACIFIC" + ] + }, "AudienceMedia":{ "type":"structure", "members":{ @@ -909,6 +989,67 @@ }, "documentation":"

    The configuration for avail suppression, also known as ad suppression. For more information about ad suppression, see Ad Suppression.

    " }, + "AwsServiceRequestConfiguration":{ + "type":"structure", + "required":[ + "Runtime", + "MethodType", + "RequestTimeoutMilliseconds", + "Url", + "TargetService", + "TargetRegion" + ], + "members":{ + "Runtime":{ + "shape":"RuntimeType", + "documentation":"

    The expression language used to evaluate expressions in the function configuration. The only supported value is JSONata.

    " + }, + "Output":{ + "shape":"__mapOf__string", + "documentation":"

    A map of output bindings. Each key is a namespaced output path, such as player_params.device_type. Each value is an expression that MediaTailor evaluates at runtime and can reference the response object from the target service. For more information, see JSONata expression reference in the MediaTailor User Guide.

    " + }, + "MethodType":{ + "shape":"MethodType", + "documentation":"

    Specifies how the function sends the request to the target service. The value must match what the target service operation requires. Valid values:

    • GET – Retrieves data from the target service.

    • POST – Submits a request body to the target service.

    " + }, + "RequestTimeoutMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum time, in milliseconds, that MediaTailor waits for a response from the AWS service. If the call exceeds this timeout, MediaTailor sets the response status code to null and proceeds with output expression evaluation. Valid values: 100 to 2000.

    " + }, + "Url":{ + "shape":"__string", + "documentation":"

    An expression that evaluates to the endpoint URL for the target AWS service API operation. Use {%...%} delimiters for dynamic expressions. The URL must correspond to a valid endpoint for the service specified in TargetService. The maximum length after evaluation is 2,048 characters.

    " + }, + "Body":{ + "shape":"__string", + "documentation":"

    An expression that evaluates to the request body for the AWS service API call. The body must conform to the input format that the target service operation expects. Applies only when the target operation accepts a request body. The maximum size after evaluation is 64 KB.

    " + }, + "Headers":{ + "shape":"__mapOf__string", + "documentation":"

    A map of HTTP header names to expression values. MediaTailor evaluates each header value expression at runtime and includes the result in the outbound request to the AWS service. Use this to pass any headers required by the target service operation. You can include a maximum of 50 headers.

    " + }, + "TargetService":{ + "shape":"AwsTargetService", + "documentation":"

    The AWS service to call. Valid value: elemental-inference (AWS Elemental Inference).

    " + }, + "TargetRegion":{ + "shape":"AwsServiceRequestConfigurationTargetRegionString", + "documentation":"

    The AWS Region for the target service. Specify a static Region code (for example, us-east-1) or a JSONata expression that resolves to a Region code at runtime (for example, {%inference.region%}).

    " + } + }, + "documentation":"

    The configuration for an AWS_SERVICE_REQUEST function. Contains the target service, target Region, and request parameters that the function uses to call an AWS service API. For more information, see AWS_SERVICE_REQUEST in the MediaTailor User Guide.

    " + }, + "AwsServiceRequestConfigurationTargetRegionString":{ + "type":"string", + "max":256, + "min":1 + }, + "AwsTargetService":{ + "type":"string", + "max":63, + "min":1, + "pattern":"[a-z0-9-]+" + }, "BadRequestException":{ "type":"structure", "members":{ @@ -1042,6 +1183,39 @@ "GZIP" ] }, + "ConcurrentExecutorConfiguration":{ + "type":"structure", + "required":[ + "Runtime", + "Output", + "FunctionList", + "TimeoutMilliseconds", + "MaxConcurrency" + ], + "members":{ + "Runtime":{ + "shape":"RuntimeType", + "documentation":"

    The expression language used to evaluate expressions in the function configuration. Set this to JSONata.

    " + }, + "Output":{ + "shape":"__mapOf__string", + "documentation":"

    A map of output bindings that controls which bindings the executor commits to the session state after all child functions complete. Each key is a namespaced output path, and each value is an expression that MediaTailor evaluates against the combined results of the child functions.

    " + }, + "FunctionList":{ + "shape":"__listOfFunctionsRef", + "documentation":"

    The list of child functions that MediaTailor runs in parallel. Each entry specifies a child function to execute and an optional run condition expression that controls whether the function runs.

    " + }, + "TimeoutMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum time, in milliseconds, for all child functions to complete. This timeout covers every function in the list, including any HTTP calls the child functions make. If the executor exceeds this timeout, MediaTailor discards all output from the executor and proceeds with default behavior.

    " + }, + "MaxConcurrency":{ + "shape":"__integer", + "documentation":"

    The maximum number of child functions that MediaTailor runs simultaneously. When the list contains more functions than MaxConcurrency, MediaTailor starts additional functions as running ones complete, so that no more than MaxConcurrency functions run at the same time.

    " + } + }, + "documentation":"

    The configuration for a CONCURRENT_EXECUTOR function. A CONCURRENT_EXECUTOR runs a set of child functions in parallel, up to a maximum concurrency, and combines their output when all functions complete. For more information about functions, see Working with functions in the MediaTailor User Guide.

    " + }, "ConfigurationAliasesRequest":{ "type":"map", "key":{ @@ -2242,7 +2416,9 @@ "type":"string", "enum":[ "PRE_SESSION_INITIALIZATION", - "PRE_ADS_REQUEST" + "PRE_ADS_REQUEST", + "POST_ADS_RESPONSE", + "PRE_MANIFEST_INSERTION" ] }, "FillPolicy":{ @@ -2275,14 +2451,26 @@ "shape":"HttpRequestConfiguration", "documentation":"

    The configuration for an HTTP_REQUEST function.

    " }, + "AwsServiceRequestConfiguration":{ + "shape":"AwsServiceRequestConfiguration", + "documentation":"

    The configuration for an AWS_SERVICE_REQUEST function. Specifies the target service, target Region, and request parameters.

    " + }, "CustomOutputConfiguration":{ "shape":"CustomOutputConfiguration", "documentation":"

    The configuration for a CUSTOM_OUTPUT function.

    " }, + "ConcurrentExecutorConfiguration":{ + "shape":"ConcurrentExecutorConfiguration", + "documentation":"

    The configuration for a CONCURRENT_EXECUTOR function.

    " + }, "SequentialExecutorConfiguration":{ "shape":"SequentialExecutorConfiguration", "documentation":"

    The configuration for a SEQUENTIAL_EXECUTOR function.

    " }, + "VastRequestConfiguration":{ + "shape":"VastRequestConfiguration", + "documentation":"

    The configuration for a VAST_REQUEST function.

    " + }, "Tags":{ "shape":"__mapOf__string", "documentation":"

    The tags assigned to the function. Tags are key-value pairs that you can associate with Amazon resources to help with organization, access control, and cost tracking. For more information, see Tagging AWS Elemental MediaTailor Resources.

    ", @@ -2293,7 +2481,7 @@ "documentation":"

    The Amazon Resource Name (ARN) of the function.

    " } }, - "documentation":"

    -- Define Mixin --

    " + "documentation":"

    Defines reusable logic that MediaTailor executes at lifecycle hooks during ad insertion. The FunctionType determines the function's runtime behavior. For more information about functions, see Working with functions in the MediaTailor User Guide.

    " }, "FunctionMapping":{ "type":"map", @@ -2310,17 +2498,24 @@ "FunctionId":{ "shape":"__string", "documentation":"

    The identifier of the child function to execute in this step.

    " + }, + "Alias":{ + "shape":"__string", + "documentation":"

    An optional alternate name for the function within the executor. If omitted, MediaTailor uses the function identifier.

    " } }, "documentation":"

    A reference to a child function within a SEQUENTIAL_EXECUTOR function.

    " }, "FunctionType":{ "type":"string", - "documentation":"

    -- Define Enums

    ", + "documentation":"

    The type of a function, which determines what the function can do at runtime. For more information, see Function types and composition in the MediaTailor User Guide.

    ", "enum":[ "HTTP_REQUEST", + "AWS_SERVICE_REQUEST", "CUSTOM_OUTPUT", - "SEQUENTIAL_EXECUTOR" + "CONCURRENT_EXECUTOR", + "SEQUENTIAL_EXECUTOR", + "VAST_REQUEST" ] }, "GetChannelPolicyRequest":{ @@ -2429,14 +2624,26 @@ "shape":"HttpRequestConfiguration", "documentation":"

    The configuration for an HTTP_REQUEST function.

    " }, + "AwsServiceRequestConfiguration":{ + "shape":"AwsServiceRequestConfiguration", + "documentation":"

    The configuration for an AWS_SERVICE_REQUEST function. Specifies the target service, target Region, and request parameters.

    " + }, "CustomOutputConfiguration":{ "shape":"CustomOutputConfiguration", "documentation":"

    The configuration for a CUSTOM_OUTPUT function.

    " }, + "ConcurrentExecutorConfiguration":{ + "shape":"ConcurrentExecutorConfiguration", + "documentation":"

    The configuration for a CONCURRENT_EXECUTOR function.

    " + }, "SequentialExecutorConfiguration":{ "shape":"SequentialExecutorConfiguration", "documentation":"

    The configuration for a SEQUENTIAL_EXECUTOR function.

    " }, + "VastRequestConfiguration":{ + "shape":"VastRequestConfiguration", + "documentation":"

    The configuration for a VAST_REQUEST function.

    " + }, "Tags":{ "shape":"__mapOf__string", "documentation":"

    The tags assigned to the function. Tags are key-value pairs that you can associate with Amazon resources to help with organization, access control, and cost tracking. For more information, see Tagging AWS Elemental MediaTailor Resources.

    ", @@ -2561,9 +2768,21 @@ "shape":"AdDecisionServerConfiguration", "documentation":"

    The configuration for customizing HTTP requests to the ad decision server (ADS). This includes settings for request method, headers, body content, and compression options.

    " }, + "YieldOptimizationConfiguration":{ + "shape":"YieldOptimizationConfiguration", + "documentation":"

    Configuration for Yield Optimization, which fills unsold ad inventory in ad breaks with programmatic ads from Amazon Publisher Services (APS).

    " + }, "FunctionMapping":{ "shape":"FunctionMapping", - "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION and PRE_ADS_REQUEST. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION, PRE_ADS_REQUEST, POST_ADS_RESPONSE, and PRE_MANIFEST_INSERTION. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + }, + "AdsPersonalizationTimeouts":{ + "shape":"AdsPersonalizationTimeouts", + "documentation":"

    The timeout settings for ad decision server interactions. These settings control how long MediaTailor waits for ADS responses and the total time budget for ad personalization across live, VOD, and prefetch workflows.

    " + }, + "AdsPersonalizationConcurrency":{ + "shape":"AdsPersonalizationConcurrency", + "documentation":"

    The concurrency settings for ad decision server interactions. These settings control how many simultaneous ADS requests MediaTailor makes per manifest request.

    " } } }, @@ -2757,7 +2976,7 @@ "documentation":"

    A map of HTTP header names to expression values. MediaTailor evaluates each header value expression at runtime and includes the result in the outbound HTTP request. Maximum 50 headers.

    " } }, - "documentation":"

    -- Function Configuration DataStructure

    " + "documentation":"

    The configuration for an HTTP_REQUEST function. Specifies the HTTP method, URL, headers, body, timeout, and output expressions for the request. For more information, see HTTP_REQUEST in the MediaTailor User Guide.

    " }, "InsertionMode":{ "type":"string", @@ -3101,6 +3320,10 @@ "MaxDurationSeconds":{ "shape":"__integer", "documentation":"

    The maximum allowed duration for the pre-roll ad avail. AWS Elemental MediaTailor won't play pre-roll ads to exceed this duration, regardless of the total duration of ads that the ADS returns.

    " + }, + "AdDecisionServerConfiguration":{ + "shape":"PreRollAdDecisionServerConfiguration", + "documentation":"

    The configuration for the ad decision server (ADS) for live pre-roll ads. The configuration contains settings that control how MediaTailor processes VAST responses for pre-roll ad breaks.

    " } }, "documentation":"

    The configuration for pre-roll ad insertion.

    " @@ -3298,6 +3521,12 @@ "POST" ] }, + "MinimumUnfilledDurationSeconds":{ + "type":"integer", + "box":true, + "max":3600, + "min":6 + }, "Mode":{ "type":"string", "enum":[ @@ -3306,6 +3535,11 @@ "AFTER_LIVE_EDGE" ] }, + "OpenRtbTemplateString":{ + "type":"string", + "max":102400, + "min":1 + }, "Operator":{ "type":"string", "enum":["EQUALS"] @@ -3414,9 +3648,21 @@ "documentation":"

    The setting that indicates what conditioning MediaTailor will perform on ads that the ad decision server (ADS) returns, and what priority MediaTailor uses when inserting ads.

    " }, "AdDecisionServerConfiguration":{"shape":"AdDecisionServerConfiguration"}, + "YieldOptimizationConfiguration":{ + "shape":"YieldOptimizationConfiguration", + "documentation":"

    Configuration for Yield Optimization, which fills unsold ad inventory in ad breaks with programmatic ads from Amazon Publisher Services (APS).

    " + }, "FunctionMapping":{ "shape":"FunctionMapping", - "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION and PRE_ADS_REQUEST. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION, PRE_ADS_REQUEST, POST_ADS_RESPONSE, and PRE_MANIFEST_INSERTION. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + }, + "AdsPersonalizationTimeouts":{ + "shape":"AdsPersonalizationTimeouts", + "documentation":"

    The timeout settings for ad decision server interactions. These settings control how long MediaTailor waits for ADS responses and the total time budget for ad personalization across live, VOD, and prefetch workflows.

    " + }, + "AdsPersonalizationConcurrency":{ + "shape":"AdsPersonalizationConcurrency", + "documentation":"

    The concurrency settings for ad decision server interactions. These settings control how many simultaneous ADS requests MediaTailor makes per manifest request.

    " } }, "documentation":"

    A playback configuration. For information about MediaTailor configurations, see Working with configurations in AWS Elemental MediaTailor.

    " @@ -3428,6 +3674,33 @@ "LINEAR" ] }, + "PreRollAdDecisionServerConfiguration":{ + "type":"structure", + "members":{ + "VastResponse":{ + "shape":"PreRollVastResponse", + "documentation":"

    The settings that control how MediaTailor processes VAST responses for live pre-roll ad breaks.

    " + } + }, + "documentation":"

    The ad decision server configuration for live pre-roll ads. It contains settings that control how MediaTailor processes VAST responses for pre-roll ad breaks.

    " + }, + "PreRollAdSequencingMode":{ + "type":"string", + "enum":[ + "FOLLOW_AD_SEQUENCE", + "IGNORE_AD_SEQUENCE" + ] + }, + "PreRollVastResponse":{ + "type":"structure", + "members":{ + "AdSequencingMode":{ + "shape":"PreRollAdSequencingMode", + "documentation":"

    The ad sequencing mode for live pre-roll ads. FOLLOW_AD_SEQUENCE inserts sequenced ads in increasing order and uses standalone ads only as replacements when a sequenced ad fails. IGNORE_AD_SEQUENCE inserts ads in the order they appear in the VAST response, regardless of sequence attributes. The default behavior is IGNORE_AD_SEQUENCE.

    " + } + }, + "documentation":"

    The settings that control how MediaTailor processes VAST responses from the ad decision server for live pre-roll ad breaks.

    " + }, "PrefetchConsumption":{ "type":"structure", "required":["EndTime"], @@ -3571,7 +3844,7 @@ }, "FunctionType":{ "shape":"FunctionType", - "documentation":"

    The type of the function. The function type determines what the function can do at runtime. Valid values: CUSTOM_OUTPUT evaluates expressions and produces output bindings with no external calls. HTTP_REQUEST makes an HTTP call to an external service and evaluates output expressions that can reference the response. SEQUENTIAL_EXECUTOR runs a sequence of child functions in order, passing data between steps through temporary data. For more information, see Function types and composition in the MediaTailor User Guide.

    " + "documentation":"

    The type of the function, which determines what the function can do at runtime. Valid values:

    • CUSTOM_OUTPUT – Evaluates expressions and produces output bindings with no external calls.

    • HTTP_REQUEST – Makes an HTTP call to an external service and evaluates output expressions that can reference the response.

    • AWS_SERVICE_REQUEST – Makes an authenticated request to a supported AWS service API and evaluates output expressions that can reference the response.

    • VAST_REQUEST – Calls a VAST endpoint, parses the response as VAST, and makes the parsed ads available to output expressions.

    • SEQUENTIAL_EXECUTOR – Runs a sequence of child functions in order, passing data between steps through temporary data.

    • CONCURRENT_EXECUTOR – Runs a set of child functions in parallel, up to a maximum concurrency, and combines their output when all functions complete.

    For more information, see Function types and composition in the MediaTailor User Guide.

    " }, "Description":{ "shape":"__string", @@ -3581,14 +3854,26 @@ "shape":"HttpRequestConfiguration", "documentation":"

    The configuration for an HTTP_REQUEST function. Specifies the HTTP method, URL, headers, body, timeout, and output expressions. Required when FunctionType is HTTP_REQUEST.

    " }, + "AwsServiceRequestConfiguration":{ + "shape":"AwsServiceRequestConfiguration", + "documentation":"

    The configuration for an AWS_SERVICE_REQUEST function. You must specify this parameter when FunctionType is AWS_SERVICE_REQUEST.

    " + }, "CustomOutputConfiguration":{ "shape":"CustomOutputConfiguration", "documentation":"

    The configuration for a CUSTOM_OUTPUT function. Specifies the runtime and output expressions. Required when FunctionType is CUSTOM_OUTPUT.

    " }, + "ConcurrentExecutorConfiguration":{ + "shape":"ConcurrentExecutorConfiguration", + "documentation":"

    The configuration for a CONCURRENT_EXECUTOR function. Specifies the list of child functions to run in parallel, the maximum concurrency, an optional output block, and a timeout. Required when FunctionType is CONCURRENT_EXECUTOR.

    " + }, "SequentialExecutorConfiguration":{ "shape":"SequentialExecutorConfiguration", "documentation":"

    The configuration for a SEQUENTIAL_EXECUTOR function. Specifies the ordered list of child functions to execute, an optional output block, and a timeout. Required when FunctionType is SEQUENTIAL_EXECUTOR.

    " }, + "VastRequestConfiguration":{ + "shape":"VastRequestConfiguration", + "documentation":"

    The configuration for a VAST_REQUEST function. Specifies the HTTP method, URL, headers, body, timeout, and output expressions. Required when FunctionType is VAST_REQUEST.

    " + }, "Tags":{ "shape":"__mapOf__string", "documentation":"

    The tags to assign to the function. Tags are key-value pairs that you can associate with Amazon resources to help with organization, access control, and cost tracking. For more information, see Tagging AWS Elemental MediaTailor Resources.

    ", @@ -3620,14 +3905,26 @@ "shape":"HttpRequestConfiguration", "documentation":"

    The configuration for an HTTP_REQUEST function.

    " }, + "AwsServiceRequestConfiguration":{ + "shape":"AwsServiceRequestConfiguration", + "documentation":"

    The configuration for an AWS_SERVICE_REQUEST function. Specifies the target service, target Region, and request parameters.

    " + }, "CustomOutputConfiguration":{ "shape":"CustomOutputConfiguration", "documentation":"

    The configuration for a CUSTOM_OUTPUT function.

    " }, + "ConcurrentExecutorConfiguration":{ + "shape":"ConcurrentExecutorConfiguration", + "documentation":"

    The configuration for a CONCURRENT_EXECUTOR function.

    " + }, "SequentialExecutorConfiguration":{ "shape":"SequentialExecutorConfiguration", "documentation":"

    The configuration for a SEQUENTIAL_EXECUTOR function.

    " }, + "VastRequestConfiguration":{ + "shape":"VastRequestConfiguration", + "documentation":"

    The configuration for a VAST_REQUEST function.

    " + }, "Tags":{ "shape":"__mapOf__string", "documentation":"

    The tags assigned to the function. Tags are key-value pairs that you can associate with Amazon resources to help with organization, access control, and cost tracking. For more information, see Tagging AWS Elemental MediaTailor Resources.

    ", @@ -3713,9 +4010,21 @@ "shape":"AdDecisionServerConfiguration", "documentation":"

    The configuration for customizing HTTP requests to the ad decision server (ADS). This includes settings for request method, headers, body content, and compression options.

    " }, + "YieldOptimizationConfiguration":{ + "shape":"YieldOptimizationConfiguration", + "documentation":"

    Configuration for Yield Optimization, which fills unsold ad inventory in ad breaks with programmatic ads from Amazon Publisher Services (APS).

    " + }, "FunctionMapping":{ "shape":"FunctionMapping", - "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION and PRE_ADS_REQUEST. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION, PRE_ADS_REQUEST, POST_ADS_RESPONSE, and PRE_MANIFEST_INSERTION. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + }, + "AdsPersonalizationTimeouts":{ + "shape":"AdsPersonalizationTimeouts", + "documentation":"

    The timeout settings for ad decision server interactions. These settings control how long MediaTailor waits for ADS responses and the total time budget for ad personalization across live, VOD, and prefetch workflows.

    " + }, + "AdsPersonalizationConcurrency":{ + "shape":"AdsPersonalizationConcurrency", + "documentation":"

    The concurrency settings for ad decision server interactions. These settings control how many simultaneous ADS requests MediaTailor makes per manifest request.

    " } } }, @@ -3819,9 +4128,21 @@ "shape":"AdDecisionServerConfiguration", "documentation":"

    The configuration for customizing HTTP requests to the ad decision server (ADS). This includes settings for request method, headers, body content, and compression options.

    " }, + "YieldOptimizationConfiguration":{ + "shape":"YieldOptimizationConfiguration", + "documentation":"

    Configuration for Yield Optimization, which fills unsold ad inventory in ad breaks with programmatic ads from Amazon Publisher Services (APS).

    " + }, "FunctionMapping":{ "shape":"FunctionMapping", - "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION and PRE_ADS_REQUEST. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + "documentation":"

    A map of lifecycle hook event names to function identifiers. The function mapping specifies which function MediaTailor executes at each lifecycle hook during ad insertion. Valid keys are PRE_SESSION_INITIALIZATION, PRE_ADS_REQUEST, POST_ADS_RESPONSE, and PRE_MANIFEST_INSERTION. For more information, see Functions lifecycle hooks in the MediaTailor User Guide.

    " + }, + "AdsPersonalizationTimeouts":{ + "shape":"AdsPersonalizationTimeouts", + "documentation":"

    The timeout settings for ad decision server interactions. These settings control how long MediaTailor waits for ADS responses and the total time budget for ad personalization across live, VOD, and prefetch workflows.

    " + }, + "AdsPersonalizationConcurrency":{ + "shape":"AdsPersonalizationConcurrency", + "documentation":"

    The concurrency settings for ad decision server interactions. These settings control how many simultaneous ADS requests MediaTailor makes per manifest request.

    " } } }, @@ -4839,6 +5160,56 @@ } } }, + "VastRequestConfiguration":{ + "type":"structure", + "required":[ + "Runtime", + "MethodType", + "RequestTimeoutMilliseconds", + "Url" + ], + "members":{ + "Runtime":{ + "shape":"RuntimeType", + "documentation":"

    The expression language used to evaluate expressions in the function configuration. Set this to JSONata.

    " + }, + "Output":{ + "shape":"__mapOf__string", + "documentation":"

    A map of output bindings. Each key is a namespaced output path (such as temp.wrappedAds), and each value is an expression that MediaTailor evaluates at runtime. Output expressions in a VAST_REQUEST function can reference the response object, which exposes response.parsedAds — the ads parsed from the VAST response after schema validation and wrapper resolution — and response.statusCode. For more information about expression syntax, see JSONata expression reference in the MediaTailor User Guide.

    " + }, + "MethodType":{ + "shape":"MethodType", + "documentation":"

    The HTTP method for the request to the VAST endpoint. Valid values: GET and POST. Use POST to send a bid request body, such as an OpenRTB payload.

    " + }, + "RequestTimeoutMilliseconds":{ + "shape":"__integer", + "documentation":"

    The maximum time, in milliseconds, that MediaTailor waits for a response from the VAST endpoint. The timeout covers the entire response, including any wrapper redirects that MediaTailor follows. If the call exceeds this timeout, MediaTailor proceeds with an empty ad list and continues output expression evaluation. Valid values: 100 to 2000.

    " + }, + "Url":{ + "shape":"__string", + "documentation":"

    An expression that evaluates to the VAST endpoint URL. Use {%...%} delimiters for dynamic expressions. A literal value must be an https:// URL. The expression can be up to 25,000 characters, and the URL after evaluation can be up to 2,048 characters.

    " + }, + "Body":{ + "shape":"__string", + "documentation":"

    An expression that evaluates to the request body, for example to send an OpenRTB bid request. The expression can be up to 100,000 characters, and the body after evaluation can be up to 64 KB.

    " + }, + "Headers":{ + "shape":"__mapOf__string", + "documentation":"

    A map of HTTP header names to expression values. MediaTailor evaluates each header value expression at runtime and includes the result in the outbound request. Headers beginning with X-Amz- are reserved by the service, and method override headers are not allowed.

    " + } + }, + "documentation":"

    The configuration for a VAST_REQUEST function. Specifies the HTTP method, URL, headers, body, timeout, and output expressions for a request to a VAST endpoint. MediaTailor parses the response as VAST and resolves wrapper redirects, then makes the parsed ads available to the function's output expressions. For more information, see Function types and composition in the MediaTailor User Guide.

    " + }, + "VastResponse":{ + "type":"structure", + "members":{ + "AdSequencingMode":{ + "shape":"AdSequencingMode", + "documentation":"

    The ad sequencing mode that controls how MediaTailor handles sequenced and standalone ads in VAST responses. FOLLOW_AD_SEQUENCE inserts sequenced ads in increasing order for both live and VOD workflows, using standalone ads only as replacements when a sequenced ad fails. FOLLOW_AD_SEQUENCE_ONLY_LIVE enables ad sequencing for live workflows only. FOLLOW_AD_SEQUENCE_ONLY_VOD enables ad sequencing for VOD workflows only. IGNORE_AD_SEQUENCE inserts ads in the order they appear in the VAST response, regardless of sequence attributes. The default behavior is IGNORE_AD_SEQUENCE.

    " + } + }, + "documentation":"

    The settings that control how MediaTailor processes VAST responses from the ad decision server.

    " + }, "VodSource":{ "type":"structure", "required":[ @@ -4880,6 +5251,34 @@ }, "documentation":"

    VOD source configuration parameters.

    " }, + "YieldOptimizationConfiguration":{ + "type":"structure", + "required":[ + "MinimumUnfilledDuration", + "PublisherId", + "Region", + "OpenRtbTemplate" + ], + "members":{ + "MinimumUnfilledDuration":{ + "shape":"MinimumUnfilledDurationSeconds", + "documentation":"

    The minimum unfilled duration, in seconds, that must remain in an ad break before MediaTailor requests additional ads from Amazon Publisher Services (APS). For example, if set to 6 seconds, yield optimization triggers only when at least 6 seconds of unfilled time remains after the primary ad server response.

    " + }, + "PublisherId":{ + "shape":"ApsPublisherId", + "documentation":"

    Publisher ID for an existing Amazon Publisher Services configuration. This ID must be obtained by registering with APS prior to using the Yield Optimization feature. The Publisher ID identifies your account in the APS system and is required for all bid requests.

    " + }, + "Region":{ + "shape":"ApsRegion", + "documentation":"

    The Amazon Publisher Services (APS) region that MediaTailor sends bid requests to. Choose the region closest to your primary audience, because the selection affects both latency and the ad inventory available to you. This setting applies to the entire playback configuration, not to individual viewers. If you serve traffic across multiple regions, create a separate playback configuration for each APS region.

    " + }, + "OpenRtbTemplate":{ + "shape":"OpenRtbTemplateString", + "documentation":"

    The OpenRTB bid request template, in JSON, that MediaTailor sends to Amazon Publisher Services (APS). The template must include an imp array with one impression specifying bidfloor, an app object specifying bundle and storeurl, and a device object specifying ua and ip. Use double curly braces (for example, {{player_params.user_agent}}) to insert session variables and player parameters.

    " + } + }, + "documentation":"

    Configuration for Yield Optimization, which fills unsold ad inventory in ad breaks with programmatic ads from Amazon Publisher Services (APS).

    " + }, "__adsInteractionExcludeEventTypesList":{ "type":"list", "member":{"shape":"AdsInteractionExcludeEventType"} diff --git a/services/medicalimaging/pom.xml b/services/medicalimaging/pom.xml index 9efa89dea094..c27db95fc088 100644 --- a/services/medicalimaging/pom.xml +++ b/services/medicalimaging/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT medicalimaging AWS Java SDK :: Services :: Medical Imaging diff --git a/services/medicalimaging/src/main/resources/codegen-resources/customization.config b/services/medicalimaging/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/medicalimaging/src/main/resources/codegen-resources/customization.config +++ b/services/medicalimaging/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/medicalimaging/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/medicalimaging/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2b0a1d851822 --- /dev/null +++ b/services/medicalimaging/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medical-imaging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medical-imaging-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medical-imaging.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://medical-imaging.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/medicalimaging/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/medicalimaging/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 851754274abb..000000000000 --- a/services/medicalimaging/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medical-imaging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medical-imaging-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medical-imaging.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://medical-imaging.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/memorydb/pom.xml b/services/memorydb/pom.xml index ff8b940ac549..a0afee5a2b59 100644 --- a/services/memorydb/pom.xml +++ b/services/memorydb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT memorydb AWS Java SDK :: Services :: Memory DB diff --git a/services/memorydb/src/main/resources/codegen-resources/customization.config b/services/memorydb/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/memorydb/src/main/resources/codegen-resources/customization.config +++ b/services/memorydb/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/memorydb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/memorydb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ad2b440fb872 --- /dev/null +++ b/services/memorydb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,214 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "fips" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://memory-db-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://memory-db-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://memory-db.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://memory-db-fips.us-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "memorydb", + "signingRegion": "us-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://memory-db.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABwX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAsAAAAKAAAABgX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/memorydb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/memorydb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9ce3ea07f836..000000000000 --- a/services/memorydb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,341 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://memory-db-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://memory-db-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://memory-db.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "fips" - ] - } - ], - "endpoint": { - "url": "https://memory-db-fips.us-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "memorydb", - "signingRegion": "us-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://memory-db.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mgn/pom.xml b/services/mgn/pom.xml index 29b1e3e5f352..54762b47d648 100644 --- a/services/mgn/pom.xml +++ b/services/mgn/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mgn AWS Java SDK :: Services :: Mgn diff --git a/services/mgn/src/main/resources/codegen-resources/customization.config b/services/mgn/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/mgn/src/main/resources/codegen-resources/customization.config +++ b/services/mgn/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/mgn/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mgn/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ebdb129798a2 --- /dev/null +++ b/services/mgn/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgn-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgn-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgn.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgn.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mgn/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mgn/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b6044333b029..000000000000 --- a/services/mgn/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgn-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgn-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgn.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mgn.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mgn/src/main/resources/codegen-resources/service-2.json b/services/mgn/src/main/resources/codegen-resources/service-2.json index 96c9de6925f9..e74a274b4e51 100644 --- a/services/mgn/src/main/resources/codegen-resources/service-2.json +++ b/services/mgn/src/main/resources/codegen-resources/service-2.json @@ -379,7 +379,7 @@ {"shape":"UninitializedAccountException"}, {"shape":"ValidationException"} ], - "documentation":"

    Returns a list of Jobs. Use the JobsID and fromDate and toData filters to limit which jobs are returned. The response is sorted by creationDataTime - latest date first. Jobs are normally created by the StartTest, StartCutover, and TerminateTargetInstances APIs. Jobs are also created by DiagnosticLaunch and TerminateDiagnosticInstances, which are APIs available only to *Support* and only used in response to relevant support tickets.

    ", + "documentation":"

    Returns a list of Jobs. Use the jobIDs and fromDate and toDate filters to limit which jobs are returned. The response is sorted by creationDateTime - latest date first. Jobs are normally created by the StartTest, StartCutover, and TerminateTargetInstances APIs. Jobs are also created by DiagnosticLaunch and TerminateDiagnosticInstances, which are APIs available only to *Support* and only used in response to relevant support tickets.

    ", "readonly":true }, "DescribeLaunchConfigurationTemplates":{ @@ -413,7 +413,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ValidationException"} ], - "documentation":"

    Lists all ReplicationConfigurationTemplates, filtered by Source Server IDs.

    ", + "documentation":"

    Lists all ReplicationConfigurationTemplates, filtered by replication configuration template IDs.

    ", "readonly":true }, "DescribeSourceServers":{ @@ -497,7 +497,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"} ], - "documentation":"

    Disconnects specific Source Servers from Application Migration Service. Data replication is stopped immediately. All AWS resources created by Application Migration Service for enabling the replication of these source servers will be terminated / deleted within 90 minutes. Launched Test or Cutover instances will NOT be terminated. If the agent on the source server has not been prevented from communicating with the Application Migration Service service, then it will receive a command to uninstall itself (within approximately 10 minutes). The following properties of the SourceServer will be changed immediately: dataReplicationInfo.dataReplicationState will be set to DISCONNECTED; The totalStorageBytes property for each of dataReplicationInfo.replicatedDisks will be set to zero; dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be nullified.

    " + "documentation":"

    Disconnects specific Source Servers from Application Migration Service. Data replication is stopped immediately. All AWS resources created by Application Migration Service for enabling the replication of these source servers will be terminated / deleted within 90 minutes. Launched Test or Cutover instances will NOT be terminated. If the agent on the source server has not been prevented from communicating with Application Migration Service, then it will receive a command to uninstall itself (within approximately 10 minutes). The following properties of the SourceServer will be changed immediately: dataReplicationInfo.dataReplicationState will be set to DISCONNECTED; The totalStorageBytes property for each of dataReplicationInfo.replicatedDisks will be set to zero; dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be nullified.

    " }, "FinalizeCutover":{ "name":"FinalizeCutover", @@ -514,7 +514,7 @@ {"shape":"ValidationException"}, {"shape":"ConflictException"} ], - "documentation":"

    Finalizes the cutover immediately for specific Source Servers. All AWS resources created by Application Migration Service for enabling the replication of these source servers will be terminated / deleted within 90 minutes. Launched Test or Cutover instances will NOT be terminated. The AWS Replication Agent will receive a command to uninstall itself (within 10 minutes). The following properties of the SourceServer will be changed immediately: dataReplicationInfo.dataReplicationState will be changed to DISCONNECTED; The SourceServer.lifeCycle.state will be changed to CUTOVER; The totalStorageBytes property fo each of dataReplicationInfo.replicatedDisks will be set to zero; dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be nullified.

    " + "documentation":"

    Finalizes the cutover immediately for specific Source Servers. All AWS resources created by Application Migration Service for enabling the replication of these source servers will be terminated / deleted within 90 minutes. Launched Test or Cutover instances will NOT be terminated. The AWS Replication Agent will receive a command to uninstall itself (within 10 minutes). The following properties of the SourceServer will be changed immediately: dataReplicationInfo.dataReplicationState will be changed to DISCONNECTED; The SourceServer.lifeCycle.state will be changed to CUTOVER; The totalStorageBytes property for each of dataReplicationInfo.replicatedDisks will be set to zero; dataReplicationInfo.lagDuration and dataReplicationInfo.lagDuration will be nullified.

    " }, "GetLaunchConfiguration":{ "name":"GetLaunchConfiguration", @@ -1012,7 +1012,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"} ], - "documentation":"

    Archives specific Source Servers by setting the SourceServer.isArchived property to true for specified SourceServers by ID. This command only works for SourceServers with a lifecycle. state which equals DISCONNECTED or CUTOVER.

    " + "documentation":"

    Archives specific Source Servers by setting the SourceServer.isArchived property to true for specified SourceServers by ID. This command only works for SourceServers with a lifecycle state that equals DISCONNECTED or CUTOVER.

    " }, "PauseReplication":{ "name":"PauseReplication", @@ -1486,7 +1486,7 @@ {"shape":"ValidationException"}, {"shape":"ConflictException"} ], - "documentation":"

    Updates multiple LaunchConfigurations by Source Server ID.

    bootMode valid values are LEGACY_BIOS | UEFI

    ", + "documentation":"

    Updates multiple LaunchConfigurations by Source Server ID.

    bootMode valid values are LEGACY_BIOS | UEFI | USE_SOURCE

    ", "idempotent":true }, "UpdateLaunchConfigurationTemplate":{ @@ -1574,7 +1574,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ValidationException"} ], - "documentation":"

    Updates multiple ReplicationConfigurationTemplates by ID.

    " + "documentation":"

    Updates a ReplicationConfigurationTemplate by ID.

    " }, "UpdateSourceServer":{ "name":"UpdateSourceServer", @@ -1640,7 +1640,7 @@ "message":{"shape":"LargeBoundedString"}, "code":{"shape":"LargeBoundedString"} }, - "documentation":"

    Operating denied due to a file permission or access check error.

    ", + "documentation":"

    Operation denied due to a file permission or access check error.

    ", "error":{ "httpStatusCode":403, "senderFault":true @@ -1998,6 +1998,30 @@ "type":"string", "pattern":"([0-9]{1,3}\\.){3}[0-9]{1,3}/[0-9]{1,2}" }, + "CidrMapping":{ + "type":"structure", + "required":[ + "originalCidr", + "updatedCidr" + ], + "members":{ + "originalCidr":{ + "shape":"Cidr", + "documentation":"

    The original CIDR range in the source network.

    " + }, + "updatedCidr":{ + "shape":"Cidr", + "documentation":"

    The updated CIDR range to use in the target network.

    " + } + }, + "documentation":"

    Maps a source CIDR range to the corresponding target CIDR range to use in the target network.

    " + }, + "CidrMappingsList":{ + "type":"list", + "member":{"shape":"CidrMapping"}, + "max":50, + "min":0 + }, "ClientIdempotencyToken":{ "type":"string", "max":64, @@ -2333,6 +2357,14 @@ "shape":"TargetDeployment", "documentation":"

    The target deployment configuration for the migrated network.

    " }, + "vpcProvisioningStrategy":{ + "shape":"VpcProvisioningStrategy", + "documentation":"

    Specifies whether to create new target VPCs or use existing ones. Set to CREATE_NEW to provision new target VPCs as part of the migration, or USE_EXISTING to migrate into existing VPCs in the target account.

    " + }, + "cidrMappings":{ + "shape":"CidrMappingsList", + "documentation":"

    A list of CIDR mappings that map original source CIDR ranges to updated target CIDR ranges. CIDR mappings can be provided only when vpcProvisioningStrategy is set to USE_EXISTING.

    " + }, "tags":{ "shape":"TagsMap", "documentation":"

    Tags to assign to the network migration definition.

    " @@ -2947,7 +2979,7 @@ }, "accountID":{ "shape":"AccountID", - "documentation":"

    Request to filter Source Servers list by Accoun ID.

    " + "documentation":"

    Request to filter Source Servers list by Account ID.

    " } } }, @@ -2994,11 +3026,11 @@ "members":{ "items":{ "shape":"SourceServersList", - "documentation":"

    Request to filter Source Servers list by item.

    " + "documentation":"

    The list of returned Source Servers.

    " }, "nextToken":{ "shape":"PaginationToken", - "documentation":"

    Request to filter Source Servers next token.

    " + "documentation":"

    The token of the next Source Server to retrieve.

    " } } }, @@ -3774,14 +3806,14 @@ "members":{ "createdCount":{ "shape":"PositiveInteger", - "documentation":"

    Import task summery waves created count.

    " + "documentation":"

    Import task summary waves created count.

    " }, "modifiedCount":{ "shape":"PositiveInteger", - "documentation":"

    Import task summery waves modified count.

    " + "documentation":"

    Import task summary waves modified count.

    " } }, - "documentation":"

    Import task summery waves.

    " + "documentation":"

    Import task summary waves.

    " }, "InitializeServiceRequest":{ "type":"structure", @@ -3971,7 +4003,7 @@ "members":{ "ssmDocument":{ "shape":"SsmDocument", - "documentation":"

    AWS Systems Manager's Document of the of the Job Post Launch Actions.

    " + "documentation":"

    AWS Systems Manager's Document of the Job Post Launch Actions.

    " }, "ssmDocumentType":{ "shape":"SsmDocumentType", @@ -3979,7 +4011,7 @@ }, "executionID":{ "shape":"BoundedString", - "documentation":"

    AWS Systems Manager Document's execution ID of the of the Job Post Launch Actions.

    " + "documentation":"

    AWS Systems Manager Document's execution ID of the Job Post Launch Actions.

    " }, "executionStatus":{ "shape":"PostLaunchActionExecutionStatus", @@ -4248,6 +4280,14 @@ "throughput":{ "shape":"Throughput", "documentation":"

    Launch template disk throughput configuration.

    " + }, + "volumeInitializationRate":{ + "shape":"VolumeInitializationRate", + "documentation":"

    Launch template disk volume initialization rate configuration.

    " + }, + "deleteOnTermination":{ + "shape":"Boolean", + "documentation":"

    Launch template disk delete on termination configuration.

    " } }, "documentation":"

    Launch template disk configuration.

    " @@ -4293,7 +4333,7 @@ "members":{ "addedToServiceDateTime":{ "shape":"ISO8601DatetimeString", - "documentation":"

    Lifecycle added to service data and time.

    " + "documentation":"

    Lifecycle added to service date and time.

    " }, "firstByteDateTime":{ "shape":"ISO8601DatetimeString", @@ -4397,7 +4437,7 @@ "members":{ "apiCallDateTime":{ "shape":"ISO8601DatetimeString", - "documentation":"

    Lifecycle Test failed API call date and time.

    " + "documentation":"

    Lifecycle Test finalized API call date and time.

    " } }, "documentation":"

    Lifecycle last Test finalized.

    " @@ -5793,7 +5833,7 @@ }, "artifactType":{ "shape":"NetworkMigrationCodeGenerationArtifactType", - "documentation":"

    The type of the artifact, such as CLOUDFORMATION_TEMPLATE or TERRAFORM_MODULE.

    " + "documentation":"

    The type of the generated artifact.

    " }, "artifactSubType":{ "shape":"NetworkMigrationCodeGenerationArtifactSubType", @@ -5985,6 +6025,14 @@ "shape":"TargetDeployment", "documentation":"

    The target deployment configuration for the migrated network.

    " }, + "vpcProvisioningStrategy":{ + "shape":"VpcProvisioningStrategy", + "documentation":"

    Indicates whether the migration creates new target VPCs or uses existing ones. CREATE_NEW provisions new target VPCs; USE_EXISTING migrates into existing VPCs in the target account.

    " + }, + "cidrMappings":{ + "shape":"CidrMappingsList", + "documentation":"

    A list of CIDR mappings that map original source CIDR ranges to updated target CIDR ranges. CIDR mappings apply only when vpcProvisioningStrategy is set to USE_EXISTING.

    " + }, "createdAt":{ "shape":"Timestamp", "documentation":"

    The timestamp when the network migration definition was created.

    " @@ -6275,7 +6323,7 @@ }, "segmentType":{ "shape":"NetworkMigrationMapperSegmentType", - "documentation":"

    The type of the segment, such as VPC, subnet, or security group.

    " + "documentation":"

    The category of the network migration segment. A segment groups the network constructs (such as VPCs, subnets, and security groups) that are migrated together. Valid values: WORKLOAD, APPLIANCE.

    " }, "name":{ "shape":"SegmentName", @@ -6597,7 +6645,7 @@ "documentation":"

    AWS Systems Manager Documents.

    " } }, - "documentation":"

    Post Launch Actions to executed on the Test or Cutover instance.

    " + "documentation":"

    Post Launch Actions to be executed on the Test or Cutover instance.

    " }, "PostLaunchActionsDeploymentType":{ "type":"string", @@ -7281,7 +7329,7 @@ "documentation":"

    Exceeded the service quota value.

    " } }, - "documentation":"

    The request could not be completed because its exceeded the service quota.

    ", + "documentation":"

    The request could not be completed because it exceeded the service quota.

    ", "error":{ "httpStatusCode":402, "senderFault":true @@ -7752,7 +7800,7 @@ }, "tags":{ "shape":"TagsMap", - "documentation":"

    Start import request tags.

    " + "documentation":"

    Start export request tags.

    " } }, "documentation":"

    Start export request.

    " @@ -8413,7 +8461,7 @@ "Throughput":{ "type":"long", "box":true, - "max":1000, + "max":2000, "min":125 }, "Timestamp":{"type":"timestamp"}, @@ -8669,6 +8717,14 @@ "shape":"TargetDeployment", "documentation":"

    The updated target deployment configuration.

    " }, + "vpcProvisioningStrategy":{ + "shape":"VpcProvisioningStrategy", + "documentation":"

    Updates whether the migration creates new target VPCs or uses existing ones. Set to USE_EXISTING to migrate into existing VPCs in the target account, or to CREATE_NEW to provision new target VPCs.

    " + }, + "cidrMappings":{ + "shape":"CidrMappingsList", + "documentation":"

    The updated list of CIDR mappings that map original source CIDR ranges to updated target CIDR ranges. CIDR mappings can be provided only when vpcProvisioningStrategy is set to USE_EXISTING.

    " + }, "scopeTags":{ "shape":"ScopeTagsMap", "documentation":"

    The updated scope tags for the network migration definition.

    " @@ -9058,6 +9114,12 @@ "type":"list", "member":{"shape":"VcenterClient"} }, + "VolumeInitializationRate":{ + "type":"long", + "box":true, + "max":300, + "min":100 + }, "VolumeType":{ "type":"string", "enum":[ @@ -9080,6 +9142,13 @@ "max":10, "min":0 }, + "VpcProvisioningStrategy":{ + "type":"string", + "enum":[ + "CREATE_NEW", + "USE_EXISTING" + ] + }, "Wave":{ "type":"structure", "members":{ @@ -9196,5 +9265,5 @@ "member":{"shape":"SegmentID"} } }, - "documentation":"

    The Application Migration Service service.

    " + "documentation":"

    Application Migration Service.

    " } diff --git a/services/migrationhub/pom.xml b/services/migrationhub/pom.xml index 4f65d2bd6a36..01a2c394cc6a 100644 --- a/services/migrationhub/pom.xml +++ b/services/migrationhub/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 migrationhub diff --git a/services/migrationhub/src/main/resources/codegen-resources/customization.config b/services/migrationhub/src/main/resources/codegen-resources/customization.config index da22aaad9103..9a6245c00e53 100644 --- a/services/migrationhub/src/main/resources/codegen-resources/customization.config +++ b/services/migrationhub/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "*" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/migrationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/migrationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3c117ab50ddf --- /dev/null +++ b/services/migrationhub/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgh-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgh-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgh.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mgh.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/migrationhub/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/migrationhub/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index aa710015708a..000000000000 --- a/services/migrationhub/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgh-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgh-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mgh.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mgh.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/migrationhubconfig/pom.xml b/services/migrationhubconfig/pom.xml index 2c7390af5423..00bad65c9276 100644 --- a/services/migrationhubconfig/pom.xml +++ b/services/migrationhubconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT migrationhubconfig AWS Java SDK :: Services :: MigrationHub Config diff --git a/services/migrationhubconfig/src/main/resources/codegen-resources/customization.config b/services/migrationhubconfig/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/migrationhubconfig/src/main/resources/codegen-resources/customization.config +++ b/services/migrationhubconfig/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2eb1b928ec35 --- /dev/null +++ b/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-config-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-config-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-config.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-config.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 61ea75f704c5..000000000000 --- a/services/migrationhubconfig/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-config-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-config-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-config.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-config.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/migrationhuborchestrator/pom.xml b/services/migrationhuborchestrator/pom.xml index ad683872f135..3a86df51a365 100644 --- a/services/migrationhuborchestrator/pom.xml +++ b/services/migrationhuborchestrator/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT migrationhuborchestrator AWS Java SDK :: Services :: Migration Hub Orchestrator diff --git a/services/migrationhuborchestrator/src/main/resources/codegen-resources/customization.config b/services/migrationhuborchestrator/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/migrationhuborchestrator/src/main/resources/codegen-resources/customization.config +++ b/services/migrationhuborchestrator/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8cb1cba9d0b4 --- /dev/null +++ b/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-orchestrator-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-orchestrator-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-orchestrator.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-orchestrator.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6567ca528930..000000000000 --- a/services/migrationhuborchestrator/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-orchestrator-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-orchestrator-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-orchestrator.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-orchestrator.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/migrationhubrefactorspaces/pom.xml b/services/migrationhubrefactorspaces/pom.xml index 2a2cdb275958..c465c5c93f1e 100644 --- a/services/migrationhubrefactorspaces/pom.xml +++ b/services/migrationhubrefactorspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT migrationhubrefactorspaces AWS Java SDK :: Services :: Migration Hub Refactor Spaces diff --git a/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/customization.config b/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/customization.config +++ b/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ed8ecaa100e4 --- /dev/null +++ b/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://refactor-spaces-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://refactor-spaces-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://refactor-spaces.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://refactor-spaces.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f83f1c5ea344..000000000000 --- a/services/migrationhubrefactorspaces/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://refactor-spaces-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://refactor-spaces-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://refactor-spaces.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://refactor-spaces.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/migrationhubstrategy/pom.xml b/services/migrationhubstrategy/pom.xml index e7078dc2e64c..a30ee275b171 100644 --- a/services/migrationhubstrategy/pom.xml +++ b/services/migrationhubstrategy/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT migrationhubstrategy AWS Java SDK :: Services :: Migration Hub Strategy diff --git a/services/migrationhubstrategy/src/main/resources/codegen-resources/customization.config b/services/migrationhubstrategy/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/migrationhubstrategy/src/main/resources/codegen-resources/customization.config +++ b/services/migrationhubstrategy/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..025615ae4ded --- /dev/null +++ b/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-strategy-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-strategy-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-strategy.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://migrationhub-strategy.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 83199acf2c10..000000000000 --- a/services/migrationhubstrategy/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-strategy-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-strategy-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-strategy.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://migrationhub-strategy.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mpa/pom.xml b/services/mpa/pom.xml index 9a36c184b617..21ee085de26d 100644 --- a/services/mpa/pom.xml +++ b/services/mpa/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mpa AWS Java SDK :: Services :: MPA diff --git a/services/mpa/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mpa/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e008ba77a4c5 --- /dev/null +++ b/services/mpa/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mpa-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mpa.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/mpa/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mpa/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f6d9438ff056..000000000000 --- a/services/mpa/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://mpa-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mpa.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/mq/pom.xml b/services/mq/pom.xml index 7486072db882..4e414e7f253a 100644 --- a/services/mq/pom.xml +++ b/services/mq/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 mq diff --git a/services/mq/src/main/resources/codegen-resources/customization.config b/services/mq/src/main/resources/codegen-resources/customization.config index f2a240391567..2fb6426d19d5 100644 --- a/services/mq/src/main/resources/codegen-resources/customization.config +++ b/services/mq/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ "excludedSimpleMethods": [ "createBroker", "createConfiguration" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mq/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mq/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8cbf45bad692 --- /dev/null +++ b/services/mq/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mq-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mq-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mq.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mq.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mq/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mq/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b9d988700b8a..000000000000 --- a/services/mq/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mq-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mq-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mq.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mq.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mq/src/main/resources/codegen-resources/service-2.json b/services/mq/src/main/resources/codegen-resources/service-2.json index a46e9016b3cb..1c198450f76a 100644 --- a/services/mq/src/main/resources/codegen-resources/service-2.json +++ b/services/mq/src/main/resources/codegen-resources/service-2.json @@ -1374,6 +1374,11 @@ "locationName": "securityGroups", "documentation": "

    The list of rules (1 minimum, 125 maximum) that authorize connections to brokers.

    " }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " + }, "StorageType": { "shape": "BrokerStorageType", "locationName": "storageType", @@ -1499,6 +1504,11 @@ "locationName": "securityGroups", "documentation": "

    The list of rules (1 minimum, 125 maximum) that authorize connections to brokers.

    " }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " + }, "StorageType": { "shape": "BrokerStorageType", "locationName": "storageType", @@ -2218,6 +2228,11 @@ "locationName": "pendingSecurityGroups", "documentation": "

    The list of pending security groups to authorize connections to brokers.

    " }, + "PendingStorageSize": { + "shape": "__integer", + "locationName": "pendingStorageSize", + "documentation": "

    The pending storage size in GB, to be applied on the next broker restart.

    " + }, "PubliclyAccessible": { "shape": "__boolean", "locationName": "publiclyAccessible", @@ -2228,6 +2243,11 @@ "locationName": "securityGroups", "documentation": "

    The list of rules (1 minimum, 125 maximum) that authorize connections to brokers.

    " }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " + }, "StorageType": { "shape": "BrokerStorageType", "locationName": "storageType", @@ -2389,6 +2409,11 @@ "locationName": "pendingSecurityGroups", "documentation": "

    The list of pending security groups to authorize connections to brokers.

    " }, + "PendingStorageSize": { + "shape": "__integer", + "locationName": "pendingStorageSize", + "documentation": "

    The pending storage size in GB, to be applied on the next broker restart.

    " + }, "PubliclyAccessible": { "shape": "__boolean", "locationName": "publiclyAccessible", @@ -2399,6 +2424,11 @@ "locationName": "securityGroups", "documentation": "

    The list of rules (1 minimum, 125 maximum) that authorize connections to brokers.

    " }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " + }, "StorageType": { "shape": "BrokerStorageType", "locationName": "storageType", @@ -3692,6 +3722,11 @@ "shape": "__listOf__string", "locationName": "securityGroups", "documentation": "

    The list of security groups (1 minimum, 5 maximum) that authorizes connections to brokers.

    " + }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " } }, "documentation": "

    Updates the broker using the specified properties.

    " @@ -3773,6 +3808,11 @@ "shape": "__listOf__string", "locationName": "securityGroups", "documentation": "

    The list of security groups (1 minimum, 5 maximum) that authorizes connections to brokers.

    " + }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " } }, "documentation": "

    Returns information about the updated broker.

    ", @@ -3839,6 +3879,11 @@ "locationName": "securityGroups", "documentation": "

    The list of security groups (1 minimum, 5 maximum) that authorizes connections to brokers.

    " }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " + }, "DataReplicationMode": { "shape": "DataReplicationMode", "locationName": "dataReplicationMode", @@ -3927,6 +3972,11 @@ "shape": "DataReplicationMode", "locationName": "pendingDataReplicationMode", "documentation": "

    Describes whether this broker will be a part of a data replication pair after reboot.

    " + }, + "StorageSize": { + "shape": "__integer", + "locationName": "storageSize", + "documentation": "

    The broker's storage size in GB.

    " } } }, diff --git a/services/mturk/pom.xml b/services/mturk/pom.xml index 45b67912173e..3d464dc263cf 100644 --- a/services/mturk/pom.xml +++ b/services/mturk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mturk AWS Java SDK :: Services :: Amazon Mechanical Turk Requester diff --git a/services/mturk/src/main/resources/codegen-resources/customization.config b/services/mturk/src/main/resources/codegen-resources/customization.config index ce10323d7ce7..dccf427b7cae 100644 --- a/services/mturk/src/main/resources/codegen-resources/customization.config +++ b/services/mturk/src/main/resources/codegen-resources/customization.config @@ -8,6 +8,5 @@ "getAccountBalance", "listQualificationRequests", "listHITs" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/mturk/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mturk/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..701cd1e5f6f7 --- /dev/null +++ b/services/mturk/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,206 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "sandbox" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mturk-requester-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mturk-requester-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mturk-requester.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mturk-requester-sandbox.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://mturk-requester.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABwX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAsAAAAKAAAABgX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mturk/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mturk/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ad7639a2ddbf..000000000000 --- a/services/mturk/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,333 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mturk-requester-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mturk-requester-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://mturk-requester.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "sandbox" - ] - } - ], - "endpoint": { - "url": "https://mturk-requester-sandbox.us-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://mturk-requester.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mwaa/pom.xml b/services/mwaa/pom.xml index 0bdf829eb9f3..f1ae0db3785a 100644 --- a/services/mwaa/pom.xml +++ b/services/mwaa/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mwaa AWS Java SDK :: Services :: MWAA diff --git a/services/mwaa/src/main/resources/codegen-resources/customization.config b/services/mwaa/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/mwaa/src/main/resources/codegen-resources/customization.config +++ b/services/mwaa/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/mwaa/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mwaa/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..916360d36c0d --- /dev/null +++ b/services/mwaa/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/mwaa/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mwaa/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 575678017d89..000000000000 --- a/services/mwaa/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://airflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://airflow-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://airflow.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://airflow.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/mwaa/src/main/resources/codegen-resources/service-2.json b/services/mwaa/src/main/resources/codegen-resources/service-2.json index 1824f0da2646..eb2c91b02968 100644 --- a/services/mwaa/src/main/resources/codegen-resources/service-2.json +++ b/services/mwaa/src/main/resources/codegen-resources/service-2.json @@ -1108,7 +1108,7 @@ "RelativePath":{ "type":"string", "max":1024, - "min":1, + "min":0, "pattern":".*" }, "ResourceNotFoundException":{ @@ -1197,7 +1197,7 @@ "S3ObjectVersion":{ "type":"string", "max":1024, - "min":1 + "min":0 }, "Schedulers":{ "type":"integer", diff --git a/services/mwaaserverless/pom.xml b/services/mwaaserverless/pom.xml index 96751e76b841..010c3227150b 100644 --- a/services/mwaaserverless/pom.xml +++ b/services/mwaaserverless/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT mwaaserverless AWS Java SDK :: Services :: MWAA Serverless diff --git a/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e4556e7e32ed --- /dev/null +++ b/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://airflow-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d3b4a9b69513..000000000000 --- a/services/mwaaserverless/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://airflow-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://airflow-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/mwaaserverless/src/main/resources/codegen-resources/service-2.json b/services/mwaaserverless/src/main/resources/codegen-resources/service-2.json index 89d9c1063629..c85604c496f7 100644 --- a/services/mwaaserverless/src/main/resources/codegen-resources/service-2.json +++ b/services/mwaaserverless/src/main/resources/codegen-resources/service-2.json @@ -310,6 +310,17 @@ "documentation":"

    You do not have sufficient permission to perform this action.

    ", "exception":true }, + "Code":{ + "type":"structure", + "members":{ + "S3Location":{ + "shape":"S3Location", + "documentation":"

    The Amazon S3 location of the code artifacts that your workflow tasks use during execution.

    " + } + }, + "documentation":"

    Specifies the Amazon S3 location of code artifacts that workflows use during execution.

    ", + "union":true + }, "ConflictException":{ "type":"structure", "required":[ @@ -352,6 +363,10 @@ "shape":"DefinitionS3Location", "documentation":"

    The Amazon S3 location where the workflow definition file is stored. This must point to a valid YAML file that defines the workflow structure using supported Amazon Web Services operators and tasks. Amazon Managed Workflows for Apache Airflow Serverless takes a snapshot of the definition at creation time, so subsequent changes to the Amazon S3 object will not affect the workflow unless you create a new version. In your YAML definition, include task dependencies, scheduling information, and operator configurations that are compatible with the Amazon Managed Workflows for Apache Airflow Serverless execution environment.

    " }, + "Code":{ + "shape":"Code", + "documentation":"

    The location of code artifacts in Amazon S3 for the workflow. The service copies the code from this location at the time of the request.

    " + }, "RoleArn":{ "shape":"RoleARN", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon Managed Workflows for Apache Airflow Serverless assumes when executing the workflow. This role must have the necessary permissions to access the required Amazon Web Services services and resources that your workflow tasks will interact with. The role is used for task execution in the isolated, multi-tenant environment and should follow the principle of least privilege. Amazon Managed Workflows for Apache Airflow Serverless validates role access during workflow creation but runtime permission checks are performed by the target services.

    " @@ -678,6 +693,14 @@ "shape":"DefinitionS3Location", "documentation":"

    The Amazon S3 location of the workflow definition file.

    " }, + "Code":{ + "shape":"Code", + "documentation":"

    The Amazon S3 location of the code artifacts provided during workflow creation or update.

    " + }, + "CodeSnapshottedAt":{ + "shape":"TimestampValue", + "documentation":"

    The time at which the code artifacts were copied for this workflow, in ISO 8601 date-time format.

    " + }, "ScheduleConfiguration":{ "shape":"ScheduleConfiguration", "documentation":"

    The schedule configuration for the workflow, including cron expressions for automated execution. Amazon Managed Workflows for Apache Airflow Serverless uses EventBridge Scheduler for cost-effective, timezone-aware scheduling. When a workflow includes schedule information in its YAML definition, the service automatically configures the appropriate triggers for automated execution. Only one version of a workflow can have an active schedule at any given time.

    " @@ -1057,6 +1080,43 @@ "SCHEDULED" ] }, + "S3Location":{ + "type":"structure", + "required":[ + "Bucket", + "ObjectKey" + ], + "members":{ + "Bucket":{ + "shape":"S3LocationBucketString", + "documentation":"

    The name of the Amazon S3 bucket.

    " + }, + "ObjectKey":{ + "shape":"S3LocationObjectKeyString", + "documentation":"

    The key of the code artifact within the Amazon S3 bucket.

    " + }, + "VersionId":{ + "shape":"S3LocationVersionIdString", + "documentation":"

    The version ID of the object in Amazon S3. If not specified, the latest version is used.

    " + } + }, + "documentation":"

    Specifies the Amazon S3 location of code artifacts that workflows use during execution.

    " + }, + "S3LocationBucketString":{ + "type":"string", + "max":63, + "min":3 + }, + "S3LocationObjectKeyString":{ + "type":"string", + "max":1024, + "min":1 + }, + "S3LocationVersionIdString":{ + "type":"string", + "max":1024, + "min":1 + }, "ScheduleConfiguration":{ "type":"structure", "members":{ @@ -1377,6 +1437,10 @@ "shape":"DefinitionS3Location", "documentation":"

    The Amazon S3 location where the updated workflow definition file is stored.

    " }, + "Code":{ + "shape":"Code", + "documentation":"

    The location of code artifacts in Amazon S3 for the updated workflow. The service copies the code from this location at the time of the request.

    " + }, "RoleArn":{ "shape":"RoleARN", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that Amazon Managed Workflows for Apache Airflow Serverless assumes when it executes the updated workflow.

    " diff --git a/services/neptune/pom.xml b/services/neptune/pom.xml index e5eae9ef6e39..ae5d518c0df4 100644 --- a/services/neptune/pom.xml +++ b/services/neptune/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT neptune AWS Java SDK :: Services :: Neptune diff --git a/services/neptune/src/main/java/software/amazon/awssdk/services/neptune/internal/RdsPresignInterceptor.java b/services/neptune/src/main/java/software/amazon/awssdk/services/neptune/internal/RdsPresignInterceptor.java index 1ff7adf4221d..09aa57f1ec65 100644 --- a/services/neptune/src/main/java/software/amazon/awssdk/services/neptune/internal/RdsPresignInterceptor.java +++ b/services/neptune/src/main/java/software/amazon/awssdk/services/neptune/internal/RdsPresignInterceptor.java @@ -24,9 +24,7 @@ import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsExecutionAttribute; -import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.core.ClientEndpointProvider; -import software.amazon.awssdk.core.Protocol; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -35,7 +33,6 @@ 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.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; @@ -48,6 +45,7 @@ import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptune.endpoints.NeptuneEndpointProvider; import software.amazon.awssdk.services.neptune.model.NeptuneRequest; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -72,7 +70,6 @@ public abstract class RdsPresignInterceptor implements .build()) .build(); - private static final String SERVICE_NAME = "rds"; private static final String PARAM_SOURCE_REGION = "SourceRegion"; private static final String PARAM_DESTINATION_REGION = "DestinationRegion"; private static final String PARAM_PRESIGNED_URL = "PreSignedUrl"; @@ -109,7 +106,7 @@ public final SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, SelectedAuthScheme selectedAuthScheme = resolveAuthScheme(context.request(), executionAttributes); String sourceRegion = presignableRequest.getSourceRegion(); String destinationRegion = selectedAuthScheme.authSchemeOption().signerProperty(AwsV4HttpSigner.REGION_NAME); - URI endpoint = createEndpoint(sourceRegion, SERVICE_NAME, executionAttributes); + URI endpoint = createEndpoint(sourceRegion, executionAttributes); SdkHttpFullRequest.Builder marshalledRequest = presignableRequest.marshall().toBuilder().uri(endpoint); SdkHttpFullRequest requestToPresign = @@ -223,17 +220,14 @@ private SdkHttpFullRequest toSdkHttpFullRequest(SignedRequest signedRequest) { .build(); } - private URI createEndpoint(String regionName, String serviceName, ExecutionAttributes attributes) { - return AwsClientEndpointProvider.builder() - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol(Protocol.HTTPS.toString()) - .region(Region.of(regionName)) - .profileFile(attributes.getAttribute(SdkExecutionAttribute.PROFILE_FILE_SUPPLIER)) - .profileName(attributes.getAttribute(SdkExecutionAttribute.PROFILE_NAME)) - .dualstackEnabled( - attributes.getAttribute(AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) - .fipsEnabled(attributes.getAttribute(AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED)) - .build() - .clientEndpoint(); + private URI createEndpoint(String regionName, ExecutionAttributes attributes) { + return CompletableFutureUtils.joinLikeSync( + NeptuneEndpointProvider.defaultProvider() + .resolveEndpoint(p -> p.region(Region.of(regionName)) + .useDualStack(attributes.getAttribute( + AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(attributes.getAttribute( + AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED))) + ).url(); } } diff --git a/services/neptune/src/main/resources/codegen-resources/customization.config b/services/neptune/src/main/resources/codegen-resources/customization.config index c0859e026214..39e6434f9f2d 100644 --- a/services/neptune/src/main/resources/codegen-resources/customization.config +++ b/services/neptune/src/main/resources/codegen-resources/customization.config @@ -39,8 +39,6 @@ "interceptors": [ "software.amazon.awssdk.services.neptune.internal.CopyDbClusterSnapshotPresignInterceptor", "software.amazon.awssdk.services.neptune.internal.CreateDbClusterPresignInterceptor" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/neptune/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/neptune/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fd1d9901492d --- /dev/null +++ b/services/neptune/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/neptune/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/neptune/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index eaad8e6d0e8d..000000000000 --- a/services/neptune/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://rds.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/neptunedata/pom.xml b/services/neptunedata/pom.xml index d56e3e4af6b8..ef66c724525c 100644 --- a/services/neptunedata/pom.xml +++ b/services/neptunedata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT neptunedata AWS Java SDK :: Services :: Neptunedata diff --git a/services/neptunedata/src/main/resources/codegen-resources/customization.config b/services/neptunedata/src/main/resources/codegen-resources/customization.config index e16c687a7da2..1afec6c42d9f 100644 --- a/services/neptunedata/src/main/resources/codegen-resources/customization.config +++ b/services/neptunedata/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "customErrorCodeFieldName": "code", - "enableGenerateCompiledEndpointRules": true + "customErrorCodeFieldName": "code" } diff --git a/services/neptunedata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/neptunedata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9236f4829e7e --- /dev/null +++ b/services/neptunedata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-db-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-db-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-db.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-db.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/neptunedata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/neptunedata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b0fd44610821..000000000000 --- a/services/neptunedata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://neptune-db-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://neptune-db-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://neptune-db.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://neptune-db.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/neptunegraph/pom.xml b/services/neptunegraph/pom.xml index f6b021db2791..9595d3b1e478 100644 --- a/services/neptunegraph/pom.xml +++ b/services/neptunegraph/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT neptunegraph AWS Java SDK :: Services :: Neptune Graph diff --git a/services/neptunegraph/src/main/resources/codegen-resources/customization.config b/services/neptunegraph/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/neptunegraph/src/main/resources/codegen-resources/customization.config +++ b/services/neptunegraph/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/neptunegraph/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/neptunegraph/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..12d537e8f607 --- /dev/null +++ b/services/neptunegraph/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,239 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "ApiType": { + "required": true, + "documentation": "Parameter to determine whether current API is a control plane or dataplane API", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "ApiType" + }, + "ControlPlane" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "ApiType" + }, + "DataPlane" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-graph-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: fips endpoint is not supported for this API", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Unknown ApiType", + "type": "error" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-graph-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-graph.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-graph.{Region}.on.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://neptune-graph.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.neptune-graph.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 20, + "nodes": "/////wAAAAH/////AAAAAAAAABMAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAAwAAAAGAAAABAAAAAkAAAAHAAAABwX14Q0AAAAIAAAACAX14Q4F9eEGAAAABQAAAAoF9eEMAAAABwX14QoAAAALAAAACAX14QsF9eEGAAAABAAAAA8AAAANAAAABgAAAA4F9eEJAAAABwX14QgAAAASAAAABQAAABAF9eEHAAAABgAAABEF9eEHAAAABwX14QQAAAASAAAACAX14QUF9eEGAAAAAwX14QEAAAAUAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/neptunegraph/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/neptunegraph/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f1a047c5100a..000000000000 --- a/services/neptunegraph/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,447 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "ApiType": { - "required": true, - "documentation": "Parameter to determine whether current API is a control plane or dataplane API", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "ControlPlane" - ] - } - ], - "endpoint": { - "url": "https://neptune-graph-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "DataPlane" - ] - } - ], - "error": "Invalid Configuration: fips endpoint is not supported for this API", - "type": "error" - }, - { - "conditions": [], - "error": "Invalid Configuration: Unknown ApiType", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "ControlPlane" - ] - } - ], - "endpoint": { - "url": "https://neptune-graph-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "DataPlane" - ] - } - ], - "error": "Invalid Configuration: fips endpoint is not supported for this API", - "type": "error" - }, - { - "conditions": [], - "error": "Invalid Configuration: Unknown ApiType", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "ControlPlane" - ] - } - ], - "endpoint": { - "url": "https://neptune-graph.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "DataPlane" - ] - } - ], - "endpoint": { - "url": "https://neptune-graph.{Region}.on.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "error": "Invalid Configuration: Unknown ApiType", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "ControlPlane" - ] - } - ], - "endpoint": { - "url": "https://neptune-graph.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "ApiType" - }, - "DataPlane" - ] - } - ], - "endpoint": { - "url": "https://{Region}.neptune-graph.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "error": "Invalid Configuration: Unknown ApiType", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/neptunegraph/src/main/resources/codegen-resources/service-2.json b/services/neptunegraph/src/main/resources/codegen-resources/service-2.json index bf7f8d452cc9..cfffb50788be 100644 --- a/services/neptunegraph/src/main/resources/codegen-resources/service-2.json +++ b/services/neptunegraph/src/main/resources/codegen-resources/service-2.json @@ -2497,7 +2497,7 @@ "type":"string", "max":1024, "min":1, - "pattern":"arn:aws(|-cn|-us-gov):kms:[a-zA-Z0-9-]*:[0-9]{12}:key/[a-zA-Z0-9-]{36}" + "pattern":"arn:aws[^:]*:kms:[a-zA-Z0-9-]*:[0-9]{12}:key/[a-zA-Z0-9-]{36}" }, "ListExportTasksInput":{ "type":"structure", @@ -3592,7 +3592,7 @@ "type":"string", "max":128, "min":1, - "pattern":"(?!aws:)[a-zA-Z+-=._:/]+" + "pattern":"[a-zA-Z+-=._:/]+" }, "TagKeyList":{ "type":"list", diff --git a/services/networkfirewall/pom.xml b/services/networkfirewall/pom.xml index 95b04f91b072..bc2249d5a5ed 100644 --- a/services/networkfirewall/pom.xml +++ b/services/networkfirewall/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT networkfirewall AWS Java SDK :: Services :: Network Firewall diff --git a/services/networkfirewall/src/main/resources/codegen-resources/customization.config b/services/networkfirewall/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/networkfirewall/src/main/resources/codegen-resources/customization.config +++ b/services/networkfirewall/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/networkfirewall/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/networkfirewall/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..756709665b9c --- /dev/null +++ b/services/networkfirewall/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-firewall-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-firewall-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-firewall.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-firewall.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/networkfirewall/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/networkfirewall/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 080a83293070..000000000000 --- a/services/networkfirewall/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://network-firewall-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://network-firewall-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://network-firewall.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://network-firewall.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/networkfirewall/src/main/resources/codegen-resources/service-2.json b/services/networkfirewall/src/main/resources/codegen-resources/service-2.json index da0e4ca33e33..46fea6296c3d 100644 --- a/services/networkfirewall/src/main/resources/codegen-resources/service-2.json +++ b/services/networkfirewall/src/main/resources/codegen-resources/service-2.json @@ -119,7 +119,7 @@ {"shape":"InternalServerError"}, {"shape":"InsufficientCapacityException"} ], - "documentation":"

    Creates a container association for Network Firewall. A container association links container clusters (ECS or EKS) to Network Firewall, enabling dynamic IP resolution for firewall rules based on container attributes.

    To manage a container association's tags, use the standard Amazon Web Services resource tagging operations, ListTagsForResource, TagResource, and UntagResource.

    To retrieve information about container associations, use ListContainerAssociations and DescribeContainerAssociation.

    " + "documentation":"

    Creates a Network Firewall container association. The association monitors container lifecycle events in your Amazon ECS or Amazon EKS clusters and resolves running container addresses for use in firewall rules.

    " }, "CreateFirewall":{ "name":"CreateFirewall", @@ -290,7 +290,7 @@ {"shape":"ThrottlingException"}, {"shape":"InvalidOperationException"} ], - "documentation":"

    Deletes the specified container association. When you delete a container association, Network Firewall stops monitoring the associated container clusters and removes the resolved IP addresses from firewall rules.

    " + "documentation":"

    Deletes a container association. The resource transitions to a DELETING state. Deletion is asynchronous - Network Firewall returns immediately while cleanup proceeds in the background. You can't delete a container association while a rule group references it.

    " }, "DeleteFirewall":{ "name":"DeleteFirewall", @@ -492,7 +492,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the properties of a container association.

    " + "documentation":"

    Retrieves the configuration and status of a container association.

    " }, "DescribeFirewall":{ "name":"DescribeFirewall", @@ -831,7 +831,7 @@ {"shape":"InternalServerError"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Retrieves the metadata for the container associations that you have defined. You can optionally page through results.

    " + "documentation":"

    Lists the container associations in your account and Region. Use the NextToken parameter in subsequent requests to retrieve additional results.

    " }, "ListFirewallPolicies":{ "name":"ListFirewallPolicies", @@ -1149,7 +1149,7 @@ {"shape":"InternalServerError"}, {"shape":"InvalidTokenException"} ], - "documentation":"

    Updates the properties of an existing container association. Use this to modify the container monitoring configurations or description.

    " + "documentation":"

    Updates the monitoring configurations and description of a container association. You can't change the container type after creation. Provide an update token to enable optimistic concurrency control.

    " }, "UpdateFirewallAnalysisSettings":{ "name":"UpdateFirewallAnalysisSettings", @@ -1355,6 +1355,25 @@ ], "documentation":"

    Updates proxy rule priorities within a proxy rule group.

    " }, + "UpdateProxySettings":{ + "name":"UpdateProxySettings", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateProxySettingsRequest"}, + "output":{"shape":"UpdateProxySettingsResponse"}, + "errors":[ + {"shape":"InvalidRequestException"}, + {"shape":"InternalServerError"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceOwnerCheckException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidTokenException"}, + {"shape":"InvalidOperationException"} + ], + "documentation":"

    Modifies the proxy listener configuration of a proxy mode firewall. Proxy mode firewalls are created with NoSourcePreservation set to TRUE. Use this operation to change the ports and protocols on which the firewall's proxy listens for traffic.

    " + }, "UpdateRuleGroup":{ "name":"UpdateRuleGroup", "http":{ @@ -1770,6 +1789,10 @@ "StatusMessage":{ "shape":"StatusMessage", "documentation":"

    If Network Firewall fails to create or delete the firewall endpoint in the subnet, it populates this with the reason for the error or failure and how to resolve it. A FAILED status indicates a non-recoverable state, and a ERROR status indicates an issue that you can fix. Depending on the error, it can take as many as 15 minutes to populate this field. For more information about the causes for failiure or errors and solutions available for this field, see Troubleshooting firewall endpoint failures in the Network Firewall Developer Guide.

    " + }, + "DnsName":{ + "shape":"DnsName", + "documentation":"

    The DNS name that resolves to the firewall endpoint in the subnet. This is populated for proxy mode firewalls, where clients direct traffic to the firewall's proxy using this name.

    " } }, "documentation":"

    The definition and status of the firewall endpoint for a single subnet. In each configured subnet, Network Firewall instantiates a firewall endpoint to handle network traffic.

    This data type is used for any firewall endpoint type:

    • For Firewall.SubnetMappings, this Attachment is part of the FirewallStatus sync states information. You define firewall subnets using CreateFirewall and AssociateSubnets.

    • For VpcEndpointAssociation, this Attachment is part of the VpcEndpointAssociationStatus sync states information. You define these subnets using CreateVpcEndpointAssociation.

    " @@ -1898,7 +1921,8 @@ "enum":[ "ACTIVE", "CREATING", - "DELETING" + "DELETING", + "UPDATING" ] }, "ContainerAssociationSummary":{ @@ -1913,7 +1937,7 @@ "documentation":"

    The descriptive name of the container association.

    " } }, - "documentation":"

    High-level information about a container association, returned by the ListContainerAssociations operation. You can use this information to retrieve the full details of a container association using DescribeContainerAssociation.

    " + "documentation":"

    The metadata for a container association returned by ListContainerAssociations. Contains the ARN and name that you use to identify the container association in other operations.

    " }, "ContainerAssociations":{ "type":"list", @@ -1928,14 +1952,14 @@ "members":{ "Key":{ "shape":"ContainerAttributeKey", - "documentation":"

    The key of the container attribute to filter on.

    " + "documentation":"

    The attribute key to filter on.

    " }, "Value":{ "shape":"ContainerAttributeValue", - "documentation":"

    The value of the container attribute to filter on.

    " + "documentation":"

    The attribute value to match.

    " } }, - "documentation":"

    A key-value pair that defines a container attribute filter for a container monitoring configuration.

    " + "documentation":"

    A key-value filter pair used in container association monitoring configurations to narrow which containers are tracked.

    " }, "ContainerAttributeKey":{ "type":"string", @@ -1959,14 +1983,14 @@ "members":{ "ClusterArn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container cluster to monitor.

    " + "documentation":"

    The ARN of the Amazon ECS or Amazon EKS cluster to monitor. The cluster must be in the same Region and account as the container association.

    " }, "AttributeFilters":{ "shape":"ContainerAttributes", - "documentation":"

    A list of key-value pairs that filter which containers within the cluster are monitored. Only containers that match the specified attributes are included.

    " + "documentation":"

    Key-value pairs that filter which containers are tracked. For Amazon EKS, you can filter by namespace and Kubernetes labels. For Amazon ECS, you can filter by container instance attributes (EC2 launch type only).

    " } }, - "documentation":"

    Defines a container cluster to monitor, along with optional attribute filters that narrow the scope of monitored containers within the cluster.

    " + "documentation":"

    Contains the monitoring configuration for a single cluster in a container association. Specifies the cluster ARN and optional attribute filters to narrow which containers are tracked.

    " }, "ContainerMonitoringConfigurations":{ "type":"list", @@ -1998,11 +2022,11 @@ }, "Type":{ "shape":"ContainerMonitoringType", - "documentation":"

    The type of container orchestration platform for the clusters in this association. Valid values are ECS and EKS. You can't change the type after creation.

    " + "documentation":"

    The type of containers to monitor. You can't change the container type after creation. Valid values:

    • ECS - Amazon Elastic Container Service

    • EKS - Amazon Elastic Kubernetes Service

    " }, "ContainerMonitoringConfigurations":{ "shape":"ContainerMonitoringConfigurations", - "documentation":"

    The list of container monitoring configurations that define which clusters and container attributes to monitor.

    " + "documentation":"

    The monitoring configurations for the container association. Each configuration specifies an Amazon ECS or Amazon EKS cluster to monitor and optional attribute filters to narrow which containers are tracked.

    " }, "Tags":{ "shape":"TagList", @@ -2027,23 +2051,23 @@ }, "Type":{ "shape":"ContainerMonitoringType", - "documentation":"

    The type of container orchestration platform. Either ECS or EKS.

    " + "documentation":"

    The container type. Valid values:

    • ECS - Amazon Elastic Container Service

    • EKS - Amazon Elastic Kubernetes Service

    " }, "ContainerMonitoringConfigurations":{ "shape":"ContainerMonitoringConfigurations", - "documentation":"

    The container monitoring configurations for this container association.

    " + "documentation":"

    The monitoring configurations for the container association.

    " }, "Status":{ "shape":"ContainerAssociationStatus", - "documentation":"

    The current status of the container association.

    " + "documentation":"

    The current status of the container association. For a new container association, the status is CREATING.

    " }, "Tags":{ "shape":"TagList", - "documentation":"

    The key:value pairs associated with the resource.

    " + "documentation":"

    The key:value pairs to associate with the resource.

    " }, "UpdateToken":{ "shape":"UpdateToken", - "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request. To make an update to the container association, provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a new token. Reapply your changes as needed, then try the operation again using the new token.

    " + "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    To make changes to the container association, you provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a current token. Reapply your changes as needed, then try the operation again using the new token.

    " } } }, @@ -2159,6 +2183,22 @@ "AvailabilityZoneChangeProtection":{ "shape":"Boolean", "documentation":"

    Optional. A setting indicating whether the firewall is protected against changes to its Availability Zone configuration. When set to TRUE, you cannot add or remove Availability Zones without first disabling this protection using UpdateAvailabilityZoneChangeProtection.

    Default value: FALSE

    " + }, + "NatGatewayMappings":{ + "shape":"NatGatewayMappingsList", + "documentation":"

    The NAT gateways that the firewall uses to proxy traffic when NoSourcePreservation is TRUE. Network Firewall attaches the firewall to each NAT gateway that you specify, so that egress traffic is proxied through the NAT gateway.

    " + }, + "ProxySettings":{ + "shape":"ProxySettings", + "documentation":"

    The listener configuration for a proxy mode firewall, used when NoSourcePreservation is TRUE. This specifies the ports and protocols on which the firewall's proxy listens for traffic.

    " + }, + "NoSourcePreservation":{ + "shape":"Boolean", + "documentation":"

    Optional. Indicates whether the firewall operates in proxy mode, in which the source IP address of the traffic is not preserved. When set to TRUE, the firewall proxies traffic through a NAT gateway and the traffic reaching the destination uses the NAT gateway's IP address as the source.

    When you set this to TRUE, you must specify NatGatewayMappings and VpcEndpoint instead of a top-level VpcId and SubnetMappings.

    You can't change this setting after you create the firewall.

    Default value: FALSE

    " + }, + "VpcEndpoint":{ + "shape":"VpcEndpoint", + "documentation":"

    The VPC and subnets for the firewall endpoint, used when NoSourcePreservation is TRUE. Network Firewall creates the firewall endpoint in the subnets that you specify here.

    For proxy mode firewalls, provide the firewall's VPC and endpoint subnets through this parameter instead of the top-level VpcId and SubnetMappings.

    " } } }, @@ -2575,11 +2615,11 @@ "members":{ "ContainerAssociationName":{ "shape":"ResourceName", - "documentation":"

    The descriptive name of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The descriptive name of the container association.

    You must specify the ARN or the name, and you can specify both.

    " }, "ContainerAssociationArn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container association.

    You must specify the ARN or the name, and you can specify both.

    " } } }, @@ -2596,7 +2636,7 @@ }, "Status":{ "shape":"ContainerAssociationStatus", - "documentation":"

    The current status of the container association.

    " + "documentation":"

    The current status of the container association. After deletion is initiated, the status is DELETING.

    " } } }, @@ -2877,11 +2917,11 @@ "members":{ "ContainerAssociationName":{ "shape":"ResourceName", - "documentation":"

    The descriptive name of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The descriptive name of the container association.

    You must specify the ARN or the name, and you can specify both.

    " }, "ContainerAssociationArn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container association.

    You must specify the ARN or the name, and you can specify both.

    " } } }, @@ -2902,11 +2942,11 @@ }, "Type":{ "shape":"ContainerMonitoringType", - "documentation":"

    The type of container orchestration platform. Either ECS or EKS.

    " + "documentation":"

    The container type. Valid values:

    • ECS - Amazon Elastic Container Service

    • EKS - Amazon Elastic Kubernetes Service

    " }, "ContainerMonitoringConfigurations":{ "shape":"ContainerMonitoringConfigurations", - "documentation":"

    The container monitoring configurations for this container association.

    " + "documentation":"

    The monitoring configurations for the container association.

    " }, "Status":{ "shape":"ContainerAssociationStatus", @@ -2914,19 +2954,19 @@ }, "ResolvedCidrCount":{ "shape":"CIDRCount", - "documentation":"

    The number of CIDR blocks that have been resolved from the monitored containers for this container association.

    " + "documentation":"

    The number of CIDR blocks resolved from the monitored containers.

    " }, "LastUpdatedTime":{ "shape":"ContainerAssociationLastUpdatedTime", - "documentation":"

    The last time that the container association was updated or resolved new container IP addresses.

    " + "documentation":"

    The most recent time that Network Firewall updated the container association.

    " }, "Tags":{ "shape":"TagList", - "documentation":"

    The key:value pairs associated with the resource.

    " + "documentation":"

    The key:value pairs to associate with the resource.

    " }, "UpdateToken":{ "shape":"UpdateToken", - "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    " + "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    To make changes to the container association, you provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a current token. Reapply your changes as needed, then try the operation again using the new token.

    " } } }, @@ -3691,6 +3731,7 @@ } } }, + "DnsName":{"type":"string"}, "Domain":{"type":"string"}, "EnableMonitoringDashboard":{"type":"boolean"}, "EnableTLSSessionHolding":{"type":"boolean"}, @@ -3812,6 +3853,22 @@ "AvailabilityZoneChangeProtection":{ "shape":"Boolean", "documentation":"

    A setting indicating whether the firewall is protected against changes to its Availability Zone configuration. When set to TRUE, you must first disable this protection before adding or removing Availability Zones.

    " + }, + "NatGatewayMappings":{ + "shape":"NatGatewayMappingsList", + "documentation":"

    The NAT gateways that the firewall uses to proxy traffic. This is set for proxy mode firewalls, where NoSourcePreservation is TRUE.

    " + }, + "ProxySettings":{ + "shape":"ProxySettings", + "documentation":"

    The listener configuration for the firewall's proxy. This is set for proxy mode firewalls, where NoSourcePreservation is TRUE.

    " + }, + "NoSourcePreservation":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the firewall operates in proxy mode, in which the source IP address of the traffic is not preserved. When this value is TRUE, the firewall proxies traffic through a NAT gateway and uses the NAT gateway's IP address as the source for traffic reaching the destination.

    " + }, + "VpcEndpoint":{ + "shape":"VpcEndpoint", + "documentation":"

    The VPC and subnets for the firewall endpoint. This is set for proxy mode firewalls, where NoSourcePreservation is TRUE.

    " } }, "documentation":"

    A firewall defines the behavior of a firewall, the main VPC where the firewall is used, the Availability Zones where the firewall can be used, and one subnet to use for a firewall endpoint within each of the Availability Zones. The Availability Zones are defined implicitly in the subnet specifications.

    In addition to the firewall endpoints that you define in this Firewall specification, you can create firewall endpoints in VpcEndpointAssociation resources for any VPC, in any Availability Zone where the firewall is already in use.

    The status of the firewall, for example whether it's ready to filter network traffic, is provided in the corresponding FirewallStatus. You can retrieve both the firewall and firewall status by calling DescribeFirewall.

    " @@ -3867,7 +3924,7 @@ }, "StatefulDefaultActions":{ "shape":"StatefulActions", - "documentation":"

    The default actions to take on a packet that doesn't match any stateful rules. The stateful default action is optional, and is only valid when using the strict rule order.

    Valid values of the stateful default action:

    • aws:drop_strict

    • aws:drop_established

    • aws:alert_strict

    • aws:alert_established

    For more information, see Strict evaluation order in the Network Firewall Developer Guide.

    " + "documentation":"

    The default actions to take on a packet that doesn't match any stateful rules. The stateful default action is optional, and is only valid when using the strict rule order.

    Valid values of the stateful default action:

    • aws:drop_strict

    • aws:drop_established

    • aws:alert_strict

    • aws:alert_established

    • aws:drop_established_app_layer

    • aws:alert_established_app_layer

    • aws:drop_established_app_layer_to_server

    • aws:alert_established_app_layer_to_server

    For more information, see Strict evaluation order in the Network Firewall Developer Guide.

    " }, "StatefulEngineOptions":{ "shape":"StatefulEngineOptions", @@ -3996,7 +4053,8 @@ "enum":[ "PROVISIONING", "DELETING", - "READY" + "READY", + "FAILED" ] }, "Firewalls":{ @@ -4462,7 +4520,7 @@ "members":{ "ContainerAssociations":{ "shape":"ContainerAssociations", - "documentation":"

    The container association metadata objects.

    " + "documentation":"

    The container association metadata objects for the account and Region.

    " }, "NextToken":{ "shape":"PaginationToken", @@ -5012,10 +5070,65 @@ }, "documentation":"

    Criteria for Network Firewall to use to inspect an individual packet in stateless rule inspection. Each match attributes set can include one or more items such as IP address, CIDR range, port number, protocol, and TCP flags.

    " }, + "NatGatewayAttachment":{ + "type":"structure", + "required":[ + "NatGatewayId", + "Status" + ], + "members":{ + "NatGatewayId":{ + "shape":"NatGatewayId", + "documentation":"

    A unique identifier for the NAT gateway to use with proxy resources.

    " + }, + "Status":{ + "shape":"NatGatewayAttachmentStatus", + "documentation":"

    The current status of the NAT gateway attachment.

    When this value is READY, the attachment is available to proxy traffic. Otherwise, this value reflects its state, for example CREATING or DELETING.

    " + }, + "StatusMessage":{ + "shape":"StatusReason", + "documentation":"

    If Network Firewall encounters an issue with the NAT gateway attachment, it populates this with an explanation of the problem.

    " + }, + "DnsName":{ + "shape":"DnsName", + "documentation":"

    The DNS name that resolves to the firewall's proxy for traffic sent through this NAT gateway attachment.

    " + } + }, + "documentation":"

    The definition and status of the attachment between a proxy mode firewall and a NAT gateway that proxies its traffic.

    " + }, + "NatGatewayAttachmentStatus":{ + "type":"string", + "enum":[ + "CREATING", + "READY", + "UPDATING", + "FAILED", + "DELETING" + ] + }, + "NatGatewayAttachmentsList":{ + "type":"list", + "member":{"shape":"NatGatewayAttachment"} + }, "NatGatewayId":{ "type":"string", "min":1 }, + "NatGatewayMapping":{ + "type":"structure", + "required":["NatGatewayId"], + "members":{ + "NatGatewayId":{ + "shape":"NatGatewayId", + "documentation":"

    A unique identifier for the NAT gateway to use with proxy resources.

    " + } + }, + "documentation":"

    A NAT gateway that a proxy mode firewall uses to proxy traffic. This is used in CreateFirewall when NoSourcePreservation is TRUE.

    " + }, + "NatGatewayMappingsList":{ + "type":"list", + "member":{"shape":"NatGatewayMapping"} + }, "NatGatewayPort":{"type":"integer"}, "NumberOfAssociations":{"type":"integer"}, "OverrideAction":{ @@ -5546,6 +5659,17 @@ }, "documentation":"

    Evaluation points in the traffic flow where rules are applied. There are three phases in a traffic where the rule match is applied.

    " }, + "ProxySettings":{ + "type":"structure", + "required":["ListenerProperties"], + "members":{ + "ListenerProperties":{ + "shape":"ListenerProperties", + "documentation":"

    Listener properties for HTTP and HTTPS traffic.

    " + } + }, + "documentation":"

    The listener configuration for a proxy mode firewall. This specifies the ports and protocols on which the firewall's proxy listens for traffic.

    " + }, "ProxyState":{ "type":"string", "enum":[ @@ -5866,11 +5990,11 @@ "members":{ "Keyword":{ "shape":"Keyword", - "documentation":"

    The keyword for the Suricata compatible rule option. You must include a sid (signature ID), and can optionally include other keywords. For information about Suricata compatible keywords, see Rule options in the Suricata documentation.

    " + "documentation":"

    The keyword for the Suricata compatible rule option. You must include a sid (signature ID), and can optionally include other keywords. For information about Suricata compatible keywords, see Rule options in the Suricata documentation.

    " }, "Settings":{ "shape":"Settings", - "documentation":"

    The settings of the Suricata compatible rule option. Rule options have zero or more setting values, and the number of possible and required settings depends on the Keyword. For more information about the settings for specific options, see Rule options.

    " + "documentation":"

    The settings of the Suricata compatible rule option. Rule options have zero or more setting values, and the number of possible and required settings depends on the Keyword. For more information about the settings for specific options, see Rule options.

    " } }, "documentation":"

    Additional settings for a stateful rule. This is part of the StatefulRule configuration.

    " @@ -5945,7 +6069,7 @@ }, "StatefulRules":{ "shape":"StatefulRules", - "documentation":"

    An array of individual stateful rules inspection criteria to be used together in a stateful rule group. Use this option to specify simple Suricata rules with protocol, source and destination, ports, direction, and rule options. For information about the Suricata Rules format, see Rules Format.

    " + "documentation":"

    An array of individual stateful rules inspection criteria to be used together in a stateful rule group. Use this option to specify simple Suricata rules with protocol, source and destination, ports, direction, and rule options. For information about the Suricata Rules format, see Rules Format.

    " }, "StatelessRulesAndCustomActions":{ "shape":"StatelessRulesAndCustomActions", @@ -6240,7 +6364,7 @@ "documentation":"

    Configures the amount of time that can pass without any traffic sent through the firewall before the firewall determines that the connection is idle.

    " } }, - "documentation":"

    Configuration settings for the handling of the stateful rule groups in a firewall policy.

    " + "documentation":"

    Configuration settings for the handling of the stateful rule groups in a firewall policy.

    Updating any setting in StatefulEngineOptions may require a restart of the stateful engine in order to apply the changes. When this occurs, existing connections will be treated according to your stream exception policy configuration.

    " }, "StatefulRule":{ "type":"structure", @@ -6263,7 +6387,7 @@ "documentation":"

    Additional options for the rule. These are the Suricata RuleOptions settings.

    " } }, - "documentation":"

    A single Suricata rules specification, for use in a stateful rule group. Use this option to specify a simple Suricata rule with protocol, source and destination, ports, direction, and rule options. For information about the Suricata Rules format, see Rules Format.

    " + "documentation":"

    A single Suricata rules specification, for use in a stateful rule group. Use this option to specify a simple Suricata rule with protocol, source and destination, ports, direction, and rule options. For information about the Suricata Rules format, see Rules Format.

    " }, "StatefulRuleDirection":{ "type":"string", @@ -6502,6 +6626,10 @@ "Config":{ "shape":"SyncStateConfig", "documentation":"

    The configuration status of the firewall endpoint in a single VPC subnet. Network Firewall provides each endpoint with the rules that are configured in the firewall policy. Each time you add a subnet or modify the associated firewall policy, Network Firewall synchronizes the rules in the endpoint, so it can properly filter network traffic.

    " + }, + "NatGatewayAttachments":{ + "shape":"NatGatewayAttachmentsList", + "documentation":"

    The status of the NAT gateway attachments for a proxy mode firewall in the Availability Zone. This reflects the attachment of the firewall to each NAT gateway that proxies its traffic.

    " } }, "documentation":"

    The status of the firewall endpoint and firewall policy configuration for a single VPC subnet. This is part of the FirewallStatus.

    For each VPC subnet that you associate with a firewall, Network Firewall does the following:

    • Instantiates a firewall endpoint in the subnet, ready to take traffic.

    • Configures the endpoint with the current firewall policy settings, to provide the filtering behavior for the endpoint.

    When you update a firewall, for example to add a subnet association or change a rule group in the firewall policy, the affected sync states reflect out-of-sync or not ready status until the changes are complete.

    " @@ -6910,31 +7038,31 @@ "members":{ "ContainerAssociationName":{ "shape":"ResourceName", - "documentation":"

    The descriptive name of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The descriptive name of the container association.

    You must specify the ARN or the name, and you can specify both.

    " }, "ContainerAssociationArn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the container association. You must specify the ARN or the name, and you can specify both.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the container association.

    You must specify the ARN or the name, and you can specify both.

    " }, "Description":{ "shape":"Description", - "documentation":"

    A description of the container association.

    " + "documentation":"

    A description of the container association. When omitted, the existing description remains unchanged. To clear the description, pass an empty string.

    " }, "Type":{ "shape":"ContainerMonitoringType", - "documentation":"

    The type of container orchestration platform. This must match the type specified when the container association was created.

    " + "documentation":"

    The container type. This value must match the existing type and can't be changed. Valid values:

    • ECS - Amazon Elastic Container Service

    • EKS - Amazon Elastic Kubernetes Service

    " }, "ContainerMonitoringConfigurations":{ "shape":"ContainerMonitoringConfigurations", - "documentation":"

    The updated list of container monitoring configurations that define which clusters and container attributes to monitor.

    " + "documentation":"

    The updated monitoring configurations for the container association. Each configuration specifies an Amazon ECS or Amazon EKS cluster to monitor and optional attribute filters.

    " }, "Tags":{ "shape":"TagList", - "documentation":"

    The key:value pairs associated with the resource.

    " + "documentation":"

    The key:value pairs to associate with the resource.

    " }, "UpdateToken":{ "shape":"UpdateToken", - "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request. To make an update to the container association, provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a new token. Reapply your changes as needed, then try the operation again using the new token.

    " + "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    To make changes to the container association, you provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a current token. Reapply your changes as needed, then try the operation again using the new token.

    " } } }, @@ -6955,11 +7083,11 @@ }, "Type":{ "shape":"ContainerMonitoringType", - "documentation":"

    The type of container orchestration platform. Either ECS or EKS.

    " + "documentation":"

    The container type. Valid values:

    • ECS - Amazon Elastic Container Service

    • EKS - Amazon Elastic Kubernetes Service

    " }, "ContainerMonitoringConfigurations":{ "shape":"ContainerMonitoringConfigurations", - "documentation":"

    The container monitoring configurations for this container association.

    " + "documentation":"

    The monitoring configurations for the container association.

    " }, "Status":{ "shape":"ContainerAssociationStatus", @@ -6967,11 +7095,11 @@ }, "Tags":{ "shape":"TagList", - "documentation":"

    The key:value pairs associated with the resource.

    " + "documentation":"

    The key:value pairs to associate with the resource.

    " }, "UpdateToken":{ "shape":"UpdateToken", - "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    " + "documentation":"

    A token used for optimistic locking. Network Firewall returns a token to your requests that access the container association. The token marks the state of the container association resource at the time of the request.

    To make changes to the container association, you provide the token in your request. Network Firewall uses the token to ensure that the container association hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the container association again to get a current copy of it with a current token. Reapply your changes as needed, then try the operation again using the new token.

    " } } }, @@ -7513,6 +7641,48 @@ } } }, + "UpdateProxySettingsRequest":{ + "type":"structure", + "members":{ + "FirewallArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the firewall.

    You must specify the ARN or the name, and you can specify both.

    " + }, + "FirewallName":{ + "shape":"ResourceName", + "documentation":"

    The descriptive name of the firewall. You can't change the name of a firewall after you create it.

    You must specify the ARN or the name, and you can specify both.

    " + }, + "UpdateToken":{ + "shape":"UpdateToken", + "documentation":"

    An optional token that you can use for optimistic locking. Network Firewall returns a token to your requests that access the firewall. The token marks the state of the firewall resource at the time of the request.

    To make an unconditional change to the firewall, omit the token in your update request. Without the token, Network Firewall performs your updates regardless of whether the firewall has changed since you last retrieved it.

    To make a conditional change to the firewall, provide the token in your update request. Network Firewall uses the token to ensure that the firewall hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the firewall again to get a current copy of it with a new token. Reapply your changes as needed, then try the operation again using the new token.

    " + }, + "ProxySettings":{ + "shape":"ProxySettings", + "documentation":"

    The proxy listener configuration to set on the firewall. This specifies the ports and protocols on which the firewall's proxy listens for traffic.

    " + } + } + }, + "UpdateProxySettingsResponse":{ + "type":"structure", + "members":{ + "FirewallArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the firewall.

    " + }, + "FirewallName":{ + "shape":"ResourceName", + "documentation":"

    The descriptive name of the firewall. You can't change the name of a firewall after you create it.

    " + }, + "UpdateToken":{ + "shape":"UpdateToken", + "documentation":"

    An optional token that you can use for optimistic locking. Network Firewall returns a token to your requests that access the firewall. The token marks the state of the firewall resource at the time of the request.

    To make an unconditional change to the firewall, omit the token in your update request. Without the token, Network Firewall performs your updates regardless of whether the firewall has changed since you last retrieved it.

    To make a conditional change to the firewall, provide the token in your update request. Network Firewall uses the token to ensure that the firewall hasn't changed since you last retrieved it. If it has changed, the operation fails with an InvalidTokenException. If this happens, retrieve the firewall again to get a current copy of it with a new token. Reapply your changes as needed, then try the operation again using the new token.

    " + }, + "ProxySettings":{ + "shape":"ProxySettings", + "documentation":"

    The updated proxy listener configuration on the firewall.

    " + } + } + }, "UpdateRuleGroupRequest":{ "type":"structure", "required":["UpdateToken"], @@ -7694,6 +7864,24 @@ "member":{"shape":"VariableDefinition"} }, "VendorName":{"type":"string"}, + "VpcEndpoint":{ + "type":"structure", + "required":[ + "VpcId", + "SubnetMappings" + ], + "members":{ + "VpcId":{ + "shape":"VpcId", + "documentation":"

    The unique identifier of the VPC where Network Firewall creates the proxy mode firewall endpoint.

    " + }, + "SubnetMappings":{ + "shape":"SubnetMappings", + "documentation":"

    The subnets in which Network Firewall creates the firewall endpoint for a proxy mode firewall. Each subnet must belong to a different Availability Zone in the VPC.

    " + } + }, + "documentation":"

    The VPC and subnets for a proxy mode firewall endpoint. This is used in CreateFirewall when NoSourcePreservation is TRUE, to specify where Network Firewall creates the firewall endpoint.

    This differs from VpcEndpointAssociation, which defines additional secondary endpoints for a firewall in other VPCs.

    " + }, "VpcEndpointAssociation":{ "type":"structure", "required":[ @@ -7778,5 +7966,5 @@ "member":{"shape":"VpcId"} } }, - "documentation":"

    This is the API Reference for Network Firewall. This guide is for developers who need detailed information about the Network Firewall API actions, data types, and errors.

    The REST API requires you to handle connection details, such as calculating signatures, handling request retries, and error handling. For general information about using the Amazon Web Services REST APIs, see Amazon Web Services APIs.

    To view the complete list of Amazon Web Services Regions where Network Firewall is available, see Service endpoints and quotas in the Amazon Web Services General Reference.

    To access Network Firewall using the IPv4 REST API endpoint: https://network-firewall.<region>.amazonaws.com

    To access Network Firewall using the Dualstack (IPv4 and IPv6) REST API endpoint: https://network-firewall.<region>.aws.api

    Alternatively, you can use one of the Amazon Web Services SDKs to access an API that's tailored to the programming language or platform that you're using. For more information, see Amazon Web Services SDKs.

    For descriptions of Network Firewall features, including and step-by-step instructions on how to use them through the Network Firewall console, see the Network Firewall Developer Guide.

    Network Firewall is a stateful, managed, network firewall and intrusion detection and prevention service for Amazon Virtual Private Cloud (Amazon VPC). With Network Firewall, you can filter traffic at the perimeter of your VPC. This includes filtering traffic going to and coming from an internet gateway, NAT gateway, or over VPN or Direct Connect. Network Firewall uses rules that are compatible with Suricata, a free, open source network analysis and threat detection engine. Network Firewall supports Suricata version 7.0.3. For information about Suricata, see the Suricata website and the Suricata User Guide.

    You can use Network Firewall to monitor and protect your VPC traffic in a number of ways. The following are just a few examples:

    • Allow domains or IP addresses for known Amazon Web Services service endpoints, such as Amazon S3, and block all other forms of traffic.

    • Use custom lists of known bad domains to limit the types of domain names that your applications can access.

    • Perform deep packet inspection on traffic entering or leaving your VPC.

    • Use stateful protocol detection to filter protocols like HTTPS, regardless of the port used.

    To enable Network Firewall for your VPCs, you perform steps in both Amazon VPC and in Network Firewall. For information about using Amazon VPC, see Amazon VPC User Guide.

    To start using Network Firewall, do the following:

    1. (Optional) If you don't already have a VPC that you want to protect, create it in Amazon VPC.

    2. In Amazon VPC, in each Availability Zone where you want to have a firewall endpoint, create a subnet for the sole use of Network Firewall.

    3. In Network Firewall, define the firewall behavior as follows:

      1. Create stateless and stateful rule groups, to define the components of the network traffic filtering behavior that you want your firewall to have.

      2. Create a firewall policy that uses your rule groups and specifies additional default traffic filtering behavior.

    4. In Network Firewall, create a firewall and specify your new firewall policy and VPC subnets. Network Firewall creates a firewall endpoint in each subnet that you specify, with the behavior that's defined in the firewall policy.

    5. In Amazon VPC, use ingress routing enhancements to route traffic through the new firewall endpoints.

    After your firewall is established, you can add firewall endpoints for new Availability Zones by following the prior steps for the Amazon VPC setup and firewall subnet definitions. You can also add endpoints to Availability Zones that you're using in the firewall, either for the same VPC or for another VPC, by following the prior steps for the Amazon VPC setup, and defining the new VPC subnets as VPC endpoint associations.

    " + "documentation":"

    This is the API Reference for Network Firewall. This guide is for developers who need detailed information about the Network Firewall API actions, data types, and errors.

    The REST API requires you to handle connection details, such as calculating signatures, handling request retries, and error handling. For general information about using the Amazon Web Services REST APIs, see Amazon Web Services APIs.

    To view the complete list of Amazon Web Services Regions where Network Firewall is available, see Service endpoints and quotas in the Amazon Web Services General Reference.

    To access Network Firewall using the IPv4 REST API endpoint: https://network-firewall.<region>.amazonaws.com

    To access Network Firewall using the Dualstack (IPv4 and IPv6) REST API endpoint: https://network-firewall.<region>.aws.api

    Alternatively, you can use one of the Amazon Web Services SDKs to access an API that's tailored to the programming language or platform that you're using. For more information, see Amazon Web Services SDKs.

    For descriptions of Network Firewall features, including and step-by-step instructions on how to use them through the Network Firewall console, see the Network Firewall Developer Guide.

    Network Firewall is a stateful, managed, network firewall and intrusion detection and prevention service for Amazon Virtual Private Cloud (Amazon VPC). With Network Firewall, you can filter traffic at the perimeter of your VPC. This includes filtering traffic going to and coming from an internet gateway, NAT gateway, or over VPN or Direct Connect. Network Firewall uses rules that are compatible with Suricata, a free, open source network analysis and threat detection engine. Network Firewall supports Suricata version 7.0.8. For information about Suricata, see the Suricata website and the Suricata User Guide.

    You can use Network Firewall to monitor and protect your VPC traffic in a number of ways. The following are just a few examples:

    • Allow domains or IP addresses for known Amazon Web Services service endpoints, such as Amazon S3, and block all other forms of traffic.

    • Use custom lists of known bad domains to limit the types of domain names that your applications can access.

    • Perform deep packet inspection on traffic entering or leaving your VPC.

    • Use stateful protocol detection to filter protocols like HTTPS, regardless of the port used.

    To enable Network Firewall for your VPCs, you perform steps in both Amazon VPC and in Network Firewall. For information about using Amazon VPC, see Amazon VPC User Guide.

    To start using Network Firewall, do the following:

    1. (Optional) If you don't already have a VPC that you want to protect, create it in Amazon VPC.

    2. In Amazon VPC, in each Availability Zone where you want to have a firewall endpoint, create a subnet for the sole use of Network Firewall.

    3. In Network Firewall, define the firewall behavior as follows:

      1. Create stateless and stateful rule groups, to define the components of the network traffic filtering behavior that you want your firewall to have.

      2. Create a firewall policy that uses your rule groups and specifies additional default traffic filtering behavior.

    4. In Network Firewall, create a firewall and specify your new firewall policy and VPC subnets. Network Firewall creates a firewall endpoint in each subnet that you specify, with the behavior that's defined in the firewall policy.

    5. In Amazon VPC, use ingress routing enhancements to route traffic through the new firewall endpoints.

    After your firewall is established, you can add firewall endpoints for new Availability Zones by following the prior steps for the Amazon VPC setup and firewall subnet definitions. You can also add endpoints to Availability Zones that you're using in the firewall, either for the same VPC or for another VPC, by following the prior steps for the Amazon VPC setup, and defining the new VPC subnets as VPC endpoint associations.

    " } diff --git a/services/networkflowmonitor/pom.xml b/services/networkflowmonitor/pom.xml index 66390e7b306d..78351207610f 100644 --- a/services/networkflowmonitor/pom.xml +++ b/services/networkflowmonitor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT networkflowmonitor AWS Java SDK :: Services :: Network Flow Monitor diff --git a/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d013cf1d3f59 --- /dev/null +++ b/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkflowmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkflowmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 177b2a22c6f3..000000000000 --- a/services/networkflowmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://networkflowmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://networkflowmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/networkmanager/pom.xml b/services/networkmanager/pom.xml index 10e1f3229491..f7cf0dbd3314 100644 --- a/services/networkmanager/pom.xml +++ b/services/networkmanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT networkmanager AWS Java SDK :: Services :: NetworkManager diff --git a/services/networkmanager/src/main/resources/codegen-resources/customization.config b/services/networkmanager/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/networkmanager/src/main/resources/codegen-resources/customization.config +++ b/services/networkmanager/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/networkmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/networkmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ceb8b4f85da9 --- /dev/null +++ b/services/networkmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,342 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.us-west-2.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.us-west-2.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager-fips.us-west-2.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager-fips.us-west-2.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.us-gov-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.us-gov-west-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmanager.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 19, + "nodes": "/////wAAAAH/////AAAAAAAAABIAAAADAAAAAQAAAAQF9eERAAAAAgAAAAUF9eERAAAAAwAAAAoAAAAGAAAABAAAAAkAAAAHAAAABQAAAAgF9eEQAAAABwX14Q4F9eEPAAAABQX14QUF9eEEAAAABAAAABEAAAALAAAABQAAAA4AAAAMAAAABgX14QgAAAANAAAACAX14QwF9eENAAAABgX14QkAAAAPAAAABwAAABAF9eELAAAACAX14QoF9eELAAAABQX14QcF9eEGAAAAAwX14QEAAAATAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/networkmanager/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/networkmanager/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index fac4979df659..000000000000 --- a/services/networkmanager/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,672 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://networkmanager.us-west-2.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://networkmanager.us-west-2.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://networkmanager-fips.us-west-2.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://networkmanager-fips.us-west-2.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://networkmanager.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://networkmanager.us-gov-west-1.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmanager-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmanager-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmanager.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://networkmanager.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/networkmonitor/pom.xml b/services/networkmonitor/pom.xml index 2fc2160ed367..2f8561998c51 100644 --- a/services/networkmonitor/pom.xml +++ b/services/networkmonitor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT networkmonitor AWS Java SDK :: Services :: Network Monitor diff --git a/services/networkmonitor/src/main/resources/codegen-resources/customization.config b/services/networkmonitor/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/networkmonitor/src/main/resources/codegen-resources/customization.config +++ b/services/networkmonitor/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/networkmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/networkmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2e1ada68588a --- /dev/null +++ b/services/networkmonitor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmonitor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://networkmonitor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/networkmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/networkmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3c772403cef8..000000000000 --- a/services/networkmonitor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmonitor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmonitor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmonitor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://networkmonitor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/networksecuritymanager/pom.xml b/services/networksecuritymanager/pom.xml new file mode 100644 index 000000000000..b8dad021f519 --- /dev/null +++ b/services/networksecuritymanager/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + networksecuritymanager + AWS Java SDK :: Services :: Network Security Manager + The AWS Java SDK for Network Security Manager module holds the client classes that are used for + communicating with Network Security Manager. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.networksecuritymanager + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f8b73259272b --- /dev/null +++ b/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-security-manager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://network-security-manager.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-tests.json b/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..ee0ab9356177 --- /dev/null +++ b/services/networksecuritymanager/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,105 @@ +{ + "testCases": [ + { + "documentation": "For custom endpoint with region not set and fips disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": false + } + }, + { + "documentation": "For custom endpoint with fips enabled", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "params": { + "Endpoint": "https://example.com", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager-fips.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": true + } + }, + { + "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager.cn-northwest-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-northwest-1", + "UseFIPS": false + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager-fips.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": true + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://network-security-manager.us-gov-west-1.api.aws" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false + } + }, + { + "documentation": "Missing region", + "expect": { + "error": "Invalid Configuration: Missing Region" + } + } + ], + "version": "1.0" +} \ No newline at end of file diff --git a/services/networksecuritymanager/src/main/resources/codegen-resources/paginators-1.json b/services/networksecuritymanager/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..663914fba37d --- /dev/null +++ b/services/networksecuritymanager/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,88 @@ +{ + "pagination": { + "ListAdminAccounts": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "adminAccounts" + }, + "ListAggregateResourceSynchronizationStatuses": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "resourceSynchronizationStatuses" + }, + "ListDeploymentSnapshots": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "snapshots" + }, + "ListDeployments": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "deployments" + }, + "ListPolicies": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "policies" + }, + "ListPolicySnapshots": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "snapshots" + }, + "ListResourceAssociations": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "resourceAssociations" + }, + "ListResourceSynchronizationStatuses": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "resourceSynchronizationStatuses" + }, + "ListRuleSnapshots": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "snapshots" + }, + "ListRules": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "rules" + }, + "ListScopeSnapshots": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "snapshots" + }, + "ListScopes": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "scopes" + }, + "ListTemplateSnapshots": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "snapshots" + }, + "ListTemplates": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "templates" + } + } +} diff --git a/services/networksecuritymanager/src/main/resources/codegen-resources/service-2.json b/services/networksecuritymanager/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..db028077e159 --- /dev/null +++ b/services/networksecuritymanager/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,5318 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2025-10-30", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"network-security-manager", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"AWS Network Security Manager Customer API", + "serviceId":"Network Security Manager", + "signatureVersion":"v4", + "signingName":"network-security-manager", + "uid":"network-security-manager-2025-10-30" + }, + "operations":{ + "CreateDeployment":{ + "name":"CreateDeployment", + "http":{ + "method":"POST", + "requestUri":"/deployments", + "responseCode":201 + }, + "input":{"shape":"CreateDeploymentInput"}, + "output":{"shape":"CreateDeploymentOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a deployment. A deployment applies one or more policies to the accounts and resources selected by a scope. Use isPublished to create the deployment in published (ACTIVE) or draft (DRAFT) state. The response includes coverage information and any warnings about the deployment.

    ", + "idempotent":true + }, + "CreateDeploymentSnapshot":{ + "name":"CreateDeploymentSnapshot", + "http":{ + "method":"POST", + "requestUri":"/deployments/{deploymentIdentifier}/snapshots", + "responseCode":201 + }, + "input":{"shape":"CreateDeploymentSnapshotInput"}, + "output":{"shape":"CreateDeploymentSnapshotOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a snapshot of the current published version of the specified deployment.

    ", + "idempotent":true + }, + "CreatePolicy":{ + "name":"CreatePolicy", + "http":{ + "method":"POST", + "requestUri":"/policies", + "responseCode":201 + }, + "input":{"shape":"CreatePolicyInput"}, + "output":{"shape":"CreatePolicyOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a policy. A policy combines templates and rules with enforcement settings for a firewall type, such as AWS WAF or AWS Shield Advanced. Use isPublished to create the policy in published (ACTIVE) or draft (DRAFT) state.

    ", + "idempotent":true + }, + "CreatePolicySnapshot":{ + "name":"CreatePolicySnapshot", + "http":{ + "method":"POST", + "requestUri":"/policies/{policyIdentifier}/snapshots", + "responseCode":201 + }, + "input":{"shape":"CreatePolicySnapshotInput"}, + "output":{"shape":"CreatePolicySnapshotOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a snapshot of the current published version of the specified policy.

    ", + "idempotent":true + }, + "CreateRule":{ + "name":"CreateRule", + "http":{ + "method":"POST", + "requestUri":"/rules", + "responseCode":201 + }, + "input":{"shape":"CreateRuleInput"}, + "output":{"shape":"CreateRuleOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a rule. A rule defines a network security configuration to enforce, such as an AWS WAF rule group or configuration data. Use isPublished to create the rule in published (ACTIVE) or draft (DRAFT) state.

    ", + "idempotent":true + }, + "CreateRuleSnapshot":{ + "name":"CreateRuleSnapshot", + "http":{ + "method":"POST", + "requestUri":"/rules/{ruleIdentifier}/snapshots", + "responseCode":201 + }, + "input":{"shape":"CreateRuleSnapshotInput"}, + "output":{"shape":"CreateRuleSnapshotOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a snapshot of the current published version of the specified rule. A snapshot is an immutable, versioned copy that other resources can reference.

    ", + "idempotent":true + }, + "CreateScope":{ + "name":"CreateScope", + "http":{ + "method":"POST", + "requestUri":"/scopes", + "responseCode":201 + }, + "input":{"shape":"CreateScopeInput"}, + "output":{"shape":"CreateScopeOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a scope. A scope selects the accounts and resources that a deployment applies to. Use isPublished to create the scope in published (ACTIVE) or draft (DRAFT) state.

    ", + "idempotent":true + }, + "CreateScopeSnapshot":{ + "name":"CreateScopeSnapshot", + "http":{ + "method":"POST", + "requestUri":"/scopes/{scopeIdentifier}/snapshots", + "responseCode":201 + }, + "input":{"shape":"CreateScopeSnapshotInput"}, + "output":{"shape":"CreateScopeSnapshotOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a snapshot of the current published version of the specified scope.

    ", + "idempotent":true + }, + "CreateTemplate":{ + "name":"CreateTemplate", + "http":{ + "method":"POST", + "requestUri":"/templates", + "responseCode":201 + }, + "input":{"shape":"CreateTemplateInput"}, + "output":{"shape":"CreateTemplateOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a template. A template groups one or more rules to simplify reuse across policies. You can also associate rules with a policy directly, without a template. Use isPublished to create the template in published (ACTIVE) or draft (DRAFT) state.

    ", + "idempotent":true + }, + "CreateTemplateSnapshot":{ + "name":"CreateTemplateSnapshot", + "http":{ + "method":"POST", + "requestUri":"/templates/{templateIdentifier}/snapshots", + "responseCode":201 + }, + "input":{"shape":"CreateTemplateSnapshotInput"}, + "output":{"shape":"CreateTemplateSnapshotOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a snapshot of the current published version of the specified template.

    ", + "idempotent":true + }, + "DeleteAdminAccount":{ + "name":"DeleteAdminAccount", + "http":{ + "method":"DELETE", + "requestUri":"/admin-account/{accountId}", + "responseCode":204 + }, + "input":{"shape":"DeleteAdminAccountRequest"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Removes the specified AWS Network Security Manager administrator account.

    ", + "idempotent":true + }, + "DeleteDeployment":{ + "name":"DeleteDeployment", + "http":{ + "method":"DELETE", + "requestUri":"/deployments/{deploymentIdentifier}", + "responseCode":204 + }, + "input":{"shape":"DeleteDeploymentInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes the specified deployment.

    ", + "idempotent":true + }, + "DeletePolicy":{ + "name":"DeletePolicy", + "http":{ + "method":"DELETE", + "requestUri":"/policies/{policyIdentifier}", + "responseCode":204 + }, + "input":{"shape":"DeletePolicyInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes the specified policy.

    ", + "idempotent":true + }, + "DeleteRule":{ + "name":"DeleteRule", + "http":{ + "method":"DELETE", + "requestUri":"/rules/{ruleIdentifier}", + "responseCode":204 + }, + "input":{"shape":"DeleteRuleInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes the specified rule.

    ", + "idempotent":true + }, + "DeleteScope":{ + "name":"DeleteScope", + "http":{ + "method":"DELETE", + "requestUri":"/scopes/{scopeIdentifier}", + "responseCode":204 + }, + "input":{"shape":"DeleteScopeInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes the specified scope.

    ", + "idempotent":true + }, + "DeleteTemplate":{ + "name":"DeleteTemplate", + "http":{ + "method":"DELETE", + "requestUri":"/templates/{templateIdentifier}", + "responseCode":204 + }, + "input":{"shape":"DeleteTemplateInput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes the specified template.

    ", + "idempotent":true + }, + "GenerateRuleConfiguration":{ + "name":"GenerateRuleConfiguration", + "http":{ + "method":"POST", + "requestUri":"/GenerateRuleConfiguration", + "responseCode":200 + }, + "input":{"shape":"GenerateRuleConfigurationRequest"}, + "output":{"shape":"GenerateRuleConfigurationResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Generates a rule configuration from a natural-language description. Provide a prompt along with the rule's firewall type and rule type. The service returns a configuration that you can use when you create or update a rule. If you also provide an existing configuration, the service edits that configuration instead of generating a new one.

    " + }, + "GetAdminAccount":{ + "name":"GetAdminAccount", + "http":{ + "method":"GET", + "requestUri":"/admin-account/{accountId}", + "responseCode":200 + }, + "input":{"shape":"GetAdminAccountRequest"}, + "output":{"shape":"GetAdminAccountResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified AWS Network Security Manager administrator account.

    ", + "readonly":true + }, + "GetDeployment":{ + "name":"GetDeployment", + "http":{ + "method":"GET", + "requestUri":"/deployments/{deploymentIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetDeploymentInput"}, + "output":{"shape":"GetDeploymentOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified deployment, including coverage information and any warnings.

    ", + "readonly":true + }, + "GetPolicy":{ + "name":"GetPolicy", + "http":{ + "method":"GET", + "requestUri":"/policies/{policyIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetPolicyInput"}, + "output":{"shape":"GetPolicyOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified policy.

    ", + "readonly":true + }, + "GetRule":{ + "name":"GetRule", + "http":{ + "method":"GET", + "requestUri":"/rules/{ruleIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetRuleInput"}, + "output":{"shape":"GetRuleOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified rule.

    ", + "readonly":true + }, + "GetScope":{ + "name":"GetScope", + "http":{ + "method":"GET", + "requestUri":"/scopes/{scopeIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetScopeInput"}, + "output":{"shape":"GetScopeOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified scope.

    ", + "readonly":true + }, + "GetTemplate":{ + "name":"GetTemplate", + "http":{ + "method":"GET", + "requestUri":"/templates/{templateIdentifier}", + "responseCode":200 + }, + "input":{"shape":"GetTemplateInput"}, + "output":{"shape":"GetTemplateOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves the details of the specified template.

    ", + "readonly":true + }, + "ListAdminAccounts":{ + "name":"ListAdminAccounts", + "http":{ + "method":"GET", + "requestUri":"/admin-accounts", + "responseCode":200 + }, + "input":{"shape":"ListAdminAccountsRequest"}, + "output":{"shape":"ListAdminAccountsResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the AWS Network Security Manager administrator accounts in the organization.

    ", + "readonly":true + }, + "ListAggregateResourceSynchronizationStatuses":{ + "name":"ListAggregateResourceSynchronizationStatuses", + "http":{ + "method":"GET", + "requestUri":"/aggregate-sync-statuses", + "responseCode":200 + }, + "input":{"shape":"ListAggregateResourceSynchronizationStatusesInput"}, + "output":{"shape":"ListAggregateResourceSynchronizationStatusesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the aggregated synchronization statuses of resources across the deployments in your administrator account. You can filter the results by synchronization status and page through them.

    ", + "readonly":true + }, + "ListDeploymentSnapshots":{ + "name":"ListDeploymentSnapshots", + "http":{ + "method":"GET", + "requestUri":"/deployments/{deploymentIdentifier}/snapshots", + "responseCode":200 + }, + "input":{"shape":"ListDeploymentSnapshotsInput"}, + "output":{"shape":"ListDeploymentSnapshotsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the snapshots of the specified deployment.

    ", + "readonly":true + }, + "ListDeployments":{ + "name":"ListDeployments", + "http":{ + "method":"GET", + "requestUri":"/deployments", + "responseCode":200 + }, + "input":{"shape":"ListDeploymentsInput"}, + "output":{"shape":"ListDeploymentsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the deployments in the account. You can filter the results by status and page through them using maxResults and nextToken.

    ", + "readonly":true + }, + "ListPolicies":{ + "name":"ListPolicies", + "http":{ + "method":"GET", + "requestUri":"/policies", + "responseCode":200 + }, + "input":{"shape":"ListPoliciesInput"}, + "output":{"shape":"ListPoliciesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the policies in the account. You can filter the results by status and page through them using maxResults and nextToken.

    ", + "readonly":true + }, + "ListPolicySnapshots":{ + "name":"ListPolicySnapshots", + "http":{ + "method":"GET", + "requestUri":"/policies/{policyIdentifier}/snapshots", + "responseCode":200 + }, + "input":{"shape":"ListPolicySnapshotsInput"}, + "output":{"shape":"ListPolicySnapshotsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the snapshots of the specified policy.

    ", + "readonly":true + }, + "ListResourceAssociations":{ + "name":"ListResourceAssociations", + "http":{ + "method":"GET", + "requestUri":"/resource-associations", + "responseCode":200 + }, + "input":{"shape":"ListResourceAssociationsInput"}, + "output":{"shape":"ListResourceAssociationsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the resources associated with the specified resource.

    ", + "readonly":true + }, + "ListResourceSynchronizationStatuses":{ + "name":"ListResourceSynchronizationStatuses", + "http":{ + "method":"GET", + "requestUri":"/resource-sync-statuses", + "responseCode":200 + }, + "input":{"shape":"ListResourceSynchronizationStatusesInput"}, + "output":{"shape":"ListResourceSynchronizationStatusesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the synchronization statuses of the resources covered by the specified deployment. You can filter the results by synchronization status and page through them.

    ", + "readonly":true + }, + "ListRuleSnapshots":{ + "name":"ListRuleSnapshots", + "http":{ + "method":"GET", + "requestUri":"/rules/{ruleIdentifier}/snapshots", + "responseCode":200 + }, + "input":{"shape":"ListRuleSnapshotsInput"}, + "output":{"shape":"ListRuleSnapshotsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the snapshots of the specified rule.

    ", + "readonly":true + }, + "ListRules":{ + "name":"ListRules", + "http":{ + "method":"GET", + "requestUri":"/rules", + "responseCode":200 + }, + "input":{"shape":"ListRulesInput"}, + "output":{"shape":"ListRulesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the rules in the account. You can filter the results by status and page through them using maxResults and nextToken.

    ", + "readonly":true + }, + "ListScopeSnapshots":{ + "name":"ListScopeSnapshots", + "http":{ + "method":"GET", + "requestUri":"/scopes/{scopeIdentifier}/snapshots", + "responseCode":200 + }, + "input":{"shape":"ListScopeSnapshotsInput"}, + "output":{"shape":"ListScopeSnapshotsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the snapshots of the specified scope.

    ", + "readonly":true + }, + "ListScopes":{ + "name":"ListScopes", + "http":{ + "method":"GET", + "requestUri":"/scopes", + "responseCode":200 + }, + "input":{"shape":"ListScopesInput"}, + "output":{"shape":"ListScopesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the scopes in the account. You can filter the results by status and page through them using maxResults and nextToken.

    ", + "readonly":true + }, + "ListTagsForResource":{ + "name":"ListTagsForResource", + "http":{ + "method":"GET", + "requestUri":"/tags/{resourceArn}", + "responseCode":200 + }, + "input":{"shape":"ListTagsForResourceInput"}, + "output":{"shape":"ListTagsForResourceOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the tags associated with the specified resource.

    ", + "readonly":true + }, + "ListTemplateSnapshots":{ + "name":"ListTemplateSnapshots", + "http":{ + "method":"GET", + "requestUri":"/templates/{templateIdentifier}/snapshots", + "responseCode":200 + }, + "input":{"shape":"ListTemplateSnapshotsInput"}, + "output":{"shape":"ListTemplateSnapshotsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the snapshots of the specified template.

    ", + "readonly":true + }, + "ListTemplates":{ + "name":"ListTemplates", + "http":{ + "method":"GET", + "requestUri":"/templates", + "responseCode":200 + }, + "input":{"shape":"ListTemplatesInput"}, + "output":{"shape":"ListTemplatesOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the templates in the account. You can filter the results by status and page through them using maxResults and nextToken.

    ", + "readonly":true + }, + "PutAdminAccount":{ + "name":"PutAdminAccount", + "http":{ + "method":"PUT", + "requestUri":"/admin-account", + "responseCode":200 + }, + "input":{"shape":"PutAdminAccountRequest"}, + "output":{"shape":"PutAdminAccountResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceUnavailableException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Sets the AWS account that serves as an AWS Network Security Manager administrator account, and optionally configures the scope of resources that the administrator can manage.

    You can't set an administrator account again immediately after you remove it, or while the service creates its service-linked role. Retry the request after a few minutes.

    ", + "idempotent":true + }, + "TagResource":{ + "name":"TagResource", + "http":{ + "method":"POST", + "requestUri":"/tags/{resourceArn}", + "responseCode":204 + }, + "input":{"shape":"TagResourceInput"}, + "output":{"shape":"TagResourceOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Adds or overwrites the specified tags on the given resource.

    ", + "idempotent":true + }, + "UntagResource":{ + "name":"UntagResource", + "http":{ + "method":"DELETE", + "requestUri":"/tags/{resourceArn}", + "responseCode":204 + }, + "input":{"shape":"UntagResourceInput"}, + "output":{"shape":"UntagResourceOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"TagPolicyViolationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Removes the specified tags from the given resource.

    ", + "idempotent":true + }, + "UpdateDeployment":{ + "name":"UpdateDeployment", + "http":{ + "method":"PATCH", + "requestUri":"/deployments/{deploymentIdentifier}", + "responseCode":200 + }, + "input":{"shape":"UpdateDeploymentInput"}, + "output":{"shape":"UpdateDeploymentOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the specified deployment. To prevent conflicting concurrent updates, provide the current updateToken. Use isPublished to publish the update or keep the deployment as a draft.

    ", + "idempotent":true + }, + "UpdatePolicy":{ + "name":"UpdatePolicy", + "http":{ + "method":"PATCH", + "requestUri":"/policies/{policyIdentifier}", + "responseCode":200 + }, + "input":{"shape":"UpdatePolicyInput"}, + "output":{"shape":"UpdatePolicyOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the specified policy. To prevent conflicting concurrent updates, provide the current updateToken. Use isPublished to publish the update or keep the policy as a draft.

    ", + "idempotent":true + }, + "UpdateRule":{ + "name":"UpdateRule", + "http":{ + "method":"PATCH", + "requestUri":"/rules/{ruleIdentifier}", + "responseCode":200 + }, + "input":{"shape":"UpdateRuleInput"}, + "output":{"shape":"UpdateRuleOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the specified rule. To prevent conflicting concurrent updates, provide the current updateToken. Use isPublished to publish the update or keep the rule as a draft.

    ", + "idempotent":true + }, + "UpdateScope":{ + "name":"UpdateScope", + "http":{ + "method":"PATCH", + "requestUri":"/scopes/{scopeIdentifier}", + "responseCode":200 + }, + "input":{"shape":"UpdateScopeInput"}, + "output":{"shape":"UpdateScopeOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the specified scope. To prevent conflicting concurrent updates, provide the current updateToken. Use isPublished to publish the update or keep the scope as a draft.

    ", + "idempotent":true + }, + "UpdateTemplate":{ + "name":"UpdateTemplate", + "http":{ + "method":"PATCH", + "requestUri":"/templates/{templateIdentifier}", + "responseCode":200 + }, + "input":{"shape":"UpdateTemplateInput"}, + "output":{"shape":"UpdateTemplateOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the specified template. To prevent conflicting concurrent updates, provide the current updateToken. Use isPublished to publish the update or keep the template as a draft.

    ", + "idempotent":true + } + }, + "shapes":{ + "AccessDeniedException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    You do not have sufficient permissions to perform this action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "AccountFilter":{ + "type":"structure", + "members":{ + "includeAll":{ + "shape":"Unit", + "documentation":"

    Includes all accounts. No account filtering is applied.

    " + }, + "include":{ + "shape":"AccountSet", + "documentation":"

    Includes only the specified accounts and organizational units.

    " + }, + "exclude":{ + "shape":"AccountSet", + "documentation":"

    Excludes the specified accounts and organizational units. All others are in scope.

    " + } + }, + "documentation":"

    Determines which accounts are in scope. Exactly one of includeAll, include, or exclude is set.

    ", + "union":true + }, + "AccountId":{ + "type":"string", + "max":12, + "min":12, + "pattern":"(?:[0-9]{12})" + }, + "AccountIdList":{ + "type":"list", + "member":{"shape":"AccountId"}, + "max":1000, + "min":0 + }, + "AccountList":{ + "type":"list", + "member":{"shape":"AccountId"}, + "max":1000, + "min":0 + }, + "AccountReference":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID.

    " + }, + "name":{ + "shape":"SensitiveAccountName", + "documentation":"

    The display name of the account.

    " + }, + "email":{ + "shape":"SensitiveAccountEmail", + "documentation":"

    The email address associated with the account.

    " + } + }, + "documentation":"

    A reference to an AWS account, with optional display metadata.

    " + }, + "AccountReferenceList":{ + "type":"list", + "member":{"shape":"AccountReference"}, + "max":1000, + "min":0 + }, + "AccountSet":{ + "type":"structure", + "members":{ + "accountIds":{ + "shape":"AccountList", + "documentation":"

    The list of AWS account IDs.

    " + }, + "organizationalUnits":{ + "shape":"OrganizationalUnitList", + "documentation":"

    The AWS Organizations organizational units (OUs) in the selection.

    " + } + }, + "documentation":"

    A set of AWS accounts and organizational units.

    " + }, + "AdminAccountDetails":{ + "type":"structure", + "required":[ + "adminAccount", + "priority" + ], + "members":{ + "adminAccount":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID of the administrator account.

    " + }, + "priority":{ + "shape":"AdminPriority", + "documentation":"

    The priority assigned to the administrator account.

    " + }, + "adminScope":{ + "shape":"AdminScope", + "documentation":"

    The administrative scope, which defines the accounts, organizational units, and firewall types that the administrator can manage.

    " + }, + "status":{ + "shape":"AdminAccountStatus", + "documentation":"

    The status of the administrator account, either ONBOARDED or OFFBOARDED.

    " + } + }, + "documentation":"

    The details of an AWS Network Security Manager administrator account.

    " + }, + "AdminAccountStatus":{ + "type":"string", + "enum":[ + "ONBOARDED", + "OFFBOARDED" + ] + }, + "AdminAccountSummary":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID.

    " + }, + "priority":{ + "shape":"AdminPriority", + "documentation":"

    The priority assigned to the administrator account.

    " + }, + "name":{ + "shape":"SensitiveName", + "documentation":"

    The name of the administrator account.

    " + }, + "email":{ + "shape":"SensitiveEmail", + "documentation":"

    The email address associated with the account.

    " + } + }, + "documentation":"

    Summary information about an AWS Network Security Manager administrator account.

    " + }, + "AdminAccountSummaryList":{ + "type":"list", + "member":{"shape":"AdminAccountSummary"}, + "max":100, + "min":0 + }, + "AdminFirewallTypeScope":{ + "type":"structure", + "members":{ + "allFirewallTypesEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the administrator can manage all firewall types, except for third-party firewall types.

    " + }, + "firewallTypes":{ + "shape":"FirewallTypeList", + "documentation":"

    The list of firewall types that the administrator can manage.

    " + } + }, + "documentation":"

    Defines the firewall types that an administrator can create and manage.

    " + }, + "AdminPriority":{ + "type":"integer", + "box":true, + "max":10, + "min":1 + }, + "AdminScope":{ + "type":"structure", + "members":{ + "scopeFilter":{ + "shape":"AdminScopeFilter", + "documentation":"

    The filter that determines which accounts and organizational units are in the administrator's scope.

    " + }, + "firewallTypeScope":{ + "shape":"AdminFirewallTypeScope", + "documentation":"

    The firewall types that the administrator can create and manage.

    " + } + }, + "documentation":"

    Defines the accounts, organizational units, and firewall types that an administrator can manage.

    " + }, + "AdminScopeFilter":{ + "type":"structure", + "members":{ + "includeAll":{ + "shape":"Unit", + "documentation":"

    All accounts and organizational units are in scope.

    " + }, + "includeOnly":{ + "shape":"AdminScopeSelection", + "documentation":"

    Only the specified accounts and organizational units are in the administrator's scope.

    " + }, + "excludeOnly":{ + "shape":"AdminScopeSelection", + "documentation":"

    The accounts and organizational units to exclude from the administrator's scope. All others are in scope.

    " + } + }, + "documentation":"

    Determines which accounts and organizational units are in an administrator's scope. This is the reference form, which includes display metadata.

    ", + "union":true + }, + "AdminScopeFilterInput":{ + "type":"structure", + "members":{ + "includeAll":{ + "shape":"Unit", + "documentation":"

    All accounts and organizational units are in scope.

    " + }, + "includeOnly":{ + "shape":"AdminScopeSelectionInput", + "documentation":"

    Only the specified accounts and organizational units are in the administrator's scope.

    " + }, + "excludeOnly":{ + "shape":"AdminScopeSelectionInput", + "documentation":"

    The accounts and organizational units to exclude from the administrator's scope. All others are in scope.

    " + } + }, + "documentation":"

    Determines which accounts and organizational units are in an administrator's scope. This is the input form, which uses account and organizational unit IDs.

    ", + "union":true + }, + "AdminScopeInput":{ + "type":"structure", + "members":{ + "scopeFilter":{ + "shape":"AdminScopeFilterInput", + "documentation":"

    The filter that determines which accounts and organizational units are in the administrator's scope.

    " + }, + "firewallTypeScope":{ + "shape":"AdminFirewallTypeScope", + "documentation":"

    The firewall types that the administrator can create and manage.

    " + } + }, + "documentation":"

    The administrative scope configuration provided on input, using account and organizational unit IDs.

    " + }, + "AdminScopeSelection":{ + "type":"structure", + "members":{ + "accounts":{ + "shape":"AccountReferenceList", + "documentation":"

    The AWS accounts in the selection.

    " + }, + "organizationalUnits":{ + "shape":"OrganizationalUnitReferenceList", + "documentation":"

    The AWS Organizations organizational units (OUs) in the selection.

    " + } + }, + "documentation":"

    A selection of accounts and organizational units. This is the reference form, which includes display metadata.

    " + }, + "AdminScopeSelectionInput":{ + "type":"structure", + "members":{ + "accounts":{ + "shape":"AccountIdList", + "documentation":"

    The AWS accounts in the selection.

    " + }, + "organizationalUnits":{ + "shape":"OrganizationalUnitIdList", + "documentation":"

    The AWS Organizations organizational units (OUs) in the selection.

    " + } + }, + "documentation":"

    A selection of accounts and organizational units. This is the input form, which uses account and organizational unit IDs.

    " + }, + "AlbConfiguration":{ + "type":"structure", + "members":{ + "scheme":{ + "shape":"Scheme", + "documentation":"

    The scheme of the Application Load Balancer, either internet-facing or internal.

    " + }, + "ipAddressType":{ + "shape":"IpAddressType", + "documentation":"

    The IP address type of the Application Load Balancer.

    " + } + }, + "documentation":"

    Filter criteria specific to Application Load Balancers.

    " + }, + "Arn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "AssociatedPolicy":{ + "type":"structure", + "required":["policyArn"], + "members":{ + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The ARN of the associated policy, including its version qualifier when a specific published version is pinned (for example, ...:policy:abc123:3).

    " + } + }, + "documentation":"

    An association between a deployment and a policy, as returned in outputs. The corresponding request structure is PolicyReference.

    " + }, + "AssociatedPolicyList":{ + "type":"list", + "member":{"shape":"AssociatedPolicy"}, + "max":2, + "min":1 + }, + "AssociatedRule":{ + "type":"structure", + "required":["ruleArn"], + "members":{ + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The ARN of the associated rule.

    " + } + }, + "documentation":"

    An association between a template and a rule, as returned in outputs. The corresponding request structure is RuleReference.

    " + }, + "AssociatedRuleList":{ + "type":"list", + "member":{"shape":"AssociatedRule"}, + "max":50, + "min":1 + }, + "AssociatedScope":{ + "type":"structure", + "required":["scopeArn"], + "members":{ + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The ARN of the associated scope.

    " + } + }, + "documentation":"

    An association between a deployment and a scope, as returned in outputs. The corresponding request structure is ScopeReference.

    " + }, + "AssociatedScopeList":{ + "type":"list", + "member":{"shape":"AssociatedScope"}, + "max":1, + "min":1 + }, + "AssociatedTemplateAndRuleList":{ + "type":"list", + "member":{"shape":"AssociatedTemplateOrRule"}, + "max":100, + "min":0 + }, + "AssociatedTemplateOrRule":{ + "type":"structure", + "members":{ + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The ARN of the associated template.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The ARN of the associated rule.

    " + } + }, + "documentation":"

    An association between a policy and either a template or a rule, as returned in outputs. Exactly one of templateArn or ruleArn is set. The corresponding request structure is TemplateOrRuleReference.

    ", + "union":true + }, + "Boolean":{ + "type":"boolean", + "box":true + }, + "ConfigurationIssue":{ + "type":"structure", + "members":{ + "configurationName":{ + "shape":"String", + "documentation":"

    The name of the configuration setting that is in conflict.

    " + }, + "expectedValue":{ + "shape":"String", + "documentation":"

    The configuration value that AWS Network Security Manager expected.

    " + }, + "actualValue":{ + "shape":"String", + "documentation":"

    The configuration value that was found on the resource.

    " + } + }, + "documentation":"

    Describes a single configuration value that does not match the intended configuration.

    " + }, + "ConfigurationIssueList":{ + "type":"list", + "member":{"shape":"ConfigurationIssue"}, + "max":100, + "min":0 + }, + "ConflictException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The ID of the resource that is in conflict with the request.

    " + }, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource that is in conflict with the request.

    " + } + }, + "documentation":"

    The request conflicts with the current state of the resource. For example, the resource was modified concurrently, or it is in a state that does not allow the requested operation.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "CreateDeploymentInput":{ + "type":"structure", + "required":[ + "deploymentName", + "deploymentConfiguration", + "associatedPolicyList", + "associatedScopeList" + ], + "members":{ + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"PolicyReferenceList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"ScopeReferenceList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT). Default: true.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource when it is created.

    " + } + } + }, + "CreateDeploymentOutput":{ + "type":"structure", + "required":[ + "deploymentId", + "deploymentArn", + "deploymentName", + "status", + "associatedPolicyList", + "associatedScopeList", + "version" + ], + "members":{ + "deploymentId":{ + "shape":"DeploymentId", + "documentation":"

    The service-generated id of the deployment.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deployment.

    " + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"AssociatedPolicyList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"AssociatedScopeList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "deploymentCoverage":{ + "shape":"DeploymentCoverageList", + "documentation":"

    The coverage information for the deployment. For each firewall type, it shows which policies have that firewall type and which in-scope resource types the firewall type protects.

    " + }, + "warnings":{ + "shape":"DeploymentWarningList", + "documentation":"

    Warnings about potential issues, such as a policy that has no applicable resources in the deployment's scope.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "CreateDeploymentSnapshotInput":{ + "type":"structure", + "required":["deploymentIdentifier"], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"deploymentIdentifier" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the snapshot when it is created.

    " + } + } + }, + "CreateDeploymentSnapshotOutput":{ + "type":"structure", + "required":[ + "deploymentId", + "deploymentArn", + "deploymentName", + "status", + "associatedPolicyList", + "associatedScopeList", + "version" + ], + "members":{ + "deploymentId":{ + "shape":"DeploymentId", + "documentation":"

    The service-generated id of the deployment.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deployment.

    " + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"AssociatedPolicyList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"AssociatedScopeList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the snapshot was created.

    " + } + } + }, + "CreatePolicyInput":{ + "type":"structure", + "required":[ + "policyName", + "priority", + "firewallType", + "policyConfiguration" + ], + "members":{ + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"TemplateAndRuleReferenceList", + "documentation":"

    The templates and rules to associate with the policy. For AWS WAF policies, specify 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list must be empty.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT). Default: true.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource when it is created.

    " + } + } + }, + "CreatePolicyOutput":{ + "type":"structure", + "required":[ + "policyId", + "policyArn", + "policyName", + "status", + "priority", + "associatedTemplateAndRuleList", + "version", + "firewallType" + ], + "members":{ + "policyId":{ + "shape":"PolicyId", + "documentation":"

    The service-generated id of the policy.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the policy.

    " + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"AssociatedTemplateAndRuleList", + "documentation":"

    The templates and rules associated with the policy. For AWS WAF policies, this list contains 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list is empty.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "CreatePolicySnapshotInput":{ + "type":"structure", + "required":["policyIdentifier"], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"policyIdentifier" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the snapshot when it is created.

    " + } + } + }, + "CreatePolicySnapshotOutput":{ + "type":"structure", + "required":[ + "policyId", + "policyArn", + "policyName", + "status", + "priority", + "associatedTemplateAndRuleList", + "version", + "firewallType" + ], + "members":{ + "policyId":{ + "shape":"PolicyId", + "documentation":"

    The service-generated id of the policy.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the policy.

    " + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"AssociatedTemplateAndRuleList", + "documentation":"

    The templates and rules associated with the policy. For AWS WAF policies, this list contains 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list is empty.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the snapshot was created.

    " + } + } + }, + "CreateRuleInput":{ + "type":"structure", + "required":[ + "ruleName", + "firewallType", + "ruleType", + "configuration" + ], + "members":{ + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type. For an AWS WAF INSPECTION rule, provide an AWS WAF rule group. For an AWS WAF CONFIGURATION rule, provide a single web ACL setting, such as DefaultAction or VisibilityConfig; use wafConfigDataType to declare which setting the document contains. For the schema of each setting and complete examples, see Writing rule configurations in the AWS Network Security Manager Developer Guide.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT). Default: true.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource when it is created.

    " + } + } + }, + "CreateRuleOutput":{ + "type":"structure", + "required":[ + "ruleId", + "ruleArn", + "ruleName", + "firewallType", + "configuration", + "status", + "version" + ], + "members":{ + "ruleId":{ + "shape":"RuleId", + "documentation":"

    The service-generated id of the rule.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "CreateRuleSnapshotInput":{ + "type":"structure", + "required":["ruleIdentifier"], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"ruleIdentifier" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the snapshot when it is created.

    " + } + } + }, + "CreateRuleSnapshotOutput":{ + "type":"structure", + "required":[ + "ruleId", + "ruleArn", + "ruleName", + "firewallType", + "configuration", + "status", + "version" + ], + "members":{ + "ruleId":{ + "shape":"RuleId", + "documentation":"

    The service-generated id of the rule.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the snapshot was created.

    " + } + } + }, + "CreateScopeInput":{ + "type":"structure", + "required":[ + "scopeName", + "scopeConfiguration" + ], + "members":{ + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT). Default: true.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource when it is created.

    " + } + } + }, + "CreateScopeOutput":{ + "type":"structure", + "required":[ + "scopeId", + "scopeArn", + "scopeName", + "status", + "version" + ], + "members":{ + "scopeId":{ + "shape":"ScopeId", + "documentation":"

    The service-generated id of the scope.

    " + }, + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the scope.

    " + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "CreateScopeSnapshotInput":{ + "type":"structure", + "required":["scopeIdentifier"], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"scopeIdentifier" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the snapshot when it is created.

    " + } + } + }, + "CreateScopeSnapshotOutput":{ + "type":"structure", + "required":[ + "scopeId", + "scopeArn", + "scopeName", + "status", + "version" + ], + "members":{ + "scopeId":{ + "shape":"ScopeId", + "documentation":"

    The service-generated id of the scope.

    " + }, + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the scope.

    " + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the snapshot was created.

    " + } + } + }, + "CreateTemplateInput":{ + "type":"structure", + "required":[ + "templateName", + "associatedRuleList", + "firewallType" + ], + "members":{ + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "associatedRuleList":{ + "shape":"RuleReferenceList", + "documentation":"

    The rules associated with the template.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT). Default: true.

    " + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource when it is created.

    " + } + } + }, + "CreateTemplateOutput":{ + "type":"structure", + "required":[ + "templateId", + "templateArn", + "templateName", + "status", + "version", + "associatedRuleList", + "firewallType" + ], + "members":{ + "templateId":{ + "shape":"TemplateId", + "documentation":"

    The service-generated id of the template.

    " + }, + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the template.

    " + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "associatedRuleList":{ + "shape":"AssociatedRuleList", + "documentation":"

    The rules associated with the template.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "CreateTemplateSnapshotInput":{ + "type":"structure", + "required":["templateIdentifier"], + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"templateIdentifier" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the snapshot when it is created.

    " + } + } + }, + "CreateTemplateSnapshotOutput":{ + "type":"structure", + "required":[ + "templateId", + "templateArn", + "templateName", + "status", + "version", + "associatedRuleList", + "firewallType" + ], + "members":{ + "templateId":{ + "shape":"TemplateId", + "documentation":"

    The service-generated id of the template.

    " + }, + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the template.

    " + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "associatedRuleList":{ + "shape":"AssociatedRuleList", + "documentation":"

    The rules associated with the template.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the snapshot was created.

    " + } + } + }, + "DateTimestamp":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, + "DeleteAdminAccountRequest":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID of the administrator account to remove.

    ", + "location":"uri", + "locationName":"accountId" + } + } + }, + "DeleteDeploymentInput":{ + "type":"structure", + "required":["deploymentIdentifier"], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"deploymentIdentifier" + } + } + }, + "DeletePolicyInput":{ + "type":"structure", + "required":["policyIdentifier"], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"policyIdentifier" + } + } + }, + "DeleteRuleInput":{ + "type":"structure", + "required":["ruleIdentifier"], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"ruleIdentifier" + } + } + }, + "DeleteScopeInput":{ + "type":"structure", + "required":["scopeIdentifier"], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"scopeIdentifier" + } + } + }, + "DeleteTemplateInput":{ + "type":"structure", + "required":["templateIdentifier"], + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"templateIdentifier" + } + } + }, + "DeploymentArn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "DeploymentConfiguration":{ + "type":"structure", + "required":["enableCrossAccountVisibility"], + "members":{ + "enableCrossAccountVisibility":{ + "shape":"EnableCrossAccountVisibility", + "documentation":"

    Specifies whether aggregate synchronization status details for the resources covered by this deployment are visible across accounts. Default: false.

    " + } + }, + "documentation":"

    Configuration settings that control a deployment's behavior.

    " + }, + "DeploymentCoverageEntry":{ + "type":"structure", + "required":[ + "firewallType", + "policyArns", + "inScopeResourceTypes" + ], + "members":{ + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type that the policies in this entry share.

    " + }, + "policyArns":{ + "shape":"DeploymentPolicyArnList", + "documentation":"

    The Amazon Resource Names (ARNs) of the deployment's policies that have this firewall type.

    " + }, + "inScopeResourceTypes":{ + "shape":"DeploymentResourceTypeList", + "documentation":"

    The resource types in the deployment's scope that this firewall type protects. This list is empty if the scope does not select any resource types that the firewall type protects.

    " + } + }, + "documentation":"

    Coverage information for one firewall type within a deployment. It lists the deployment's policies that have this firewall type. It also lists the resource types in the deployment's scope that the firewall type protects.

    " + }, + "DeploymentCoverageList":{ + "type":"list", + "member":{"shape":"DeploymentCoverageEntry"}, + "max":10, + "min":0 + }, + "DeploymentId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9]{1,64}" + }, + "DeploymentIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "DeploymentName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _.:/=+\\-@]*" + }, + "DeploymentPolicyArnList":{ + "type":"list", + "member":{"shape":"PolicyArn"}, + "max":100, + "min":0 + }, + "DeploymentResourceTypeList":{ + "type":"list", + "member":{"shape":"ScopeResourceType"}, + "max":50, + "min":0 + }, + "DeploymentSummary":{ + "type":"structure", + "required":[ + "deploymentId", + "deploymentArn" + ], + "members":{ + "deploymentId":{ + "shape":"DeploymentId", + "documentation":"

    The service-generated id of the deployment.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deployment.

    " + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable), ACTIVE (published, in use), or DISABLED (deactivated; changes cannot be published until the resource is re-enabled).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated. For a snapshot, this is the time when the snapshot was created.

    " + } + }, + "documentation":"

    Summary information about a deployment.

    " + }, + "DeploymentSummaryList":{ + "type":"list", + "member":{"shape":"DeploymentSummary"}, + "max":100, + "min":0 + }, + "DeploymentWarningEntry":{ + "type":"structure", + "required":[ + "code", + "policyArn", + "message" + ], + "members":{ + "code":{ + "shape":"String", + "documentation":"

    A code that identifies the type of warning.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The ARN of the policy that the warning relates to.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A human-readable description of the warning.

    " + } + }, + "documentation":"

    A warning about a potential issue with a deployment.

    " + }, + "DeploymentWarningList":{ + "type":"list", + "member":{"shape":"DeploymentWarningEntry"}, + "max":100, + "min":0 + }, + "Description":{ + "type":"string", + "max":256, + "min":0, + "pattern":"[a-zA-Z0-9 _.:/=+\\-@]*" + }, + "EnableCrossAccountVisibility":{ + "type":"boolean", + "box":true + }, + "EntityStatus":{ + "type":"string", + "enum":[ + "DRAFT", + "ACTIVE", + "DISABLED" + ] + }, + "EntityStatusFilter":{ + "type":"string", + "enum":[ + "ACTIVE", + "DRAFT", + "DISABLED" + ] + }, + "EntityVersion":{ + "type":"string", + "max":10, + "min":1, + "pattern":"[1-9][0-9]*" + }, + "ExistingCustomerWebACLResolution":{ + "type":"string", + "enum":[ + "RETROFIT", + "OVERRIDE_ASSOCIATION", + "NO_REMEDIATION" + ] + }, + "FirewallSyncReason":{ + "type":"structure", + "members":{ + "missingFirewall":{ + "shape":"String", + "documentation":"

    Indicates that an expected firewall is missing. The value describes the missing firewall.

    " + }, + "invalidFirewall":{ + "shape":"InvalidFirewallReasons", + "documentation":"

    Details about a firewall whose configuration does not match the intended configuration.

    " + } + }, + "documentation":"

    Describes why a firewall is out of sync. Exactly one of missingFirewall or invalidFirewall is set.

    ", + "union":true + }, + "FirewallTypeList":{ + "type":"list", + "member":{"shape":"PolicyFirewallType"}, + "max":10, + "min":0 + }, + "GenerateRuleConfigurationRequest":{ + "type":"structure", + "required":[ + "prompt", + "ruleFirewallType", + "ruleType" + ], + "members":{ + "prompt":{ + "shape":"GenerateRuleConfigurationRequestPromptString", + "documentation":"

    A natural-language description of the configuration that you want to generate.

    " + }, + "ruleFirewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type of the rule.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "wafConfigDataType":{ + "shape":"WAFConfigDataType", + "documentation":"

    For AWS WAF configuration rules, the specific AWS WAF configuration variant to generate. This is optional; if you omit it, the service selects the variant.

    " + }, + "currentConfiguration":{ + "shape":"GenerateRuleConfigurationRequestCurrentConfigurationString", + "documentation":"

    An existing configuration to edit, as a JSON string. When you provide this value, the operation edits the configuration. When you omit it, the operation generates a new configuration.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "GenerateRuleConfigurationRequestCurrentConfigurationString":{ + "type":"string", + "max":32768, + "min":0 + }, + "GenerateRuleConfigurationRequestPromptString":{ + "type":"string", + "max":2000, + "min":1, + "pattern":"[A-Za-z0-9.,?!@&:;()'\"\\s\\-\\/\\n_=<>+*\\#\\[\\]{}]*", + "sensitive":true + }, + "GenerateRuleConfigurationResponse":{ + "type":"structure", + "required":["configuration"], + "members":{ + "configuration":{ + "shape":"GenerateRuleConfigurationResponseConfigurationString", + "documentation":"

    The generated configuration, as a JSON string. You can use this value in the configuration field of a rule.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    Reserved for a future human-readable description of the generated configuration. This field is currently not populated.

    " + } + } + }, + "GenerateRuleConfigurationResponseConfigurationString":{ + "type":"string", + "max":32768, + "min":0 + }, + "GetAdminAccountRequest":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID of the administrator account to retrieve.

    ", + "location":"uri", + "locationName":"accountId" + } + } + }, + "GetAdminAccountResponse":{ + "type":"structure", + "members":{ + "adminAccountDetails":{ + "shape":"AdminAccountDetails", + "documentation":"

    The details of the administrator account.

    " + } + } + }, + "GetDeploymentInput":{ + "type":"structure", + "required":["deploymentIdentifier"], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"deploymentIdentifier" + } + } + }, + "GetDeploymentOutput":{ + "type":"structure", + "required":[ + "deploymentId", + "deploymentArn", + "deploymentName", + "status", + "associatedPolicyList", + "associatedScopeList", + "version" + ], + "members":{ + "deploymentId":{ + "shape":"DeploymentId", + "documentation":"

    The service-generated id of the deployment.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deployment.

    " + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable), ACTIVE (published, in use), or DISABLED (deactivated; changes cannot be published until the resource is re-enabled).

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"AssociatedPolicyList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"AssociatedScopeList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + }, + "deploymentCoverage":{ + "shape":"DeploymentCoverageList", + "documentation":"

    The coverage information for the deployment. For each firewall type, it shows which policies have that firewall type and which in-scope resource types the firewall type protects.

    " + }, + "warnings":{ + "shape":"DeploymentWarningList", + "documentation":"

    Warnings about potential issues, such as a policy that has no applicable resources in the deployment's scope.

    " + } + } + }, + "GetPolicyInput":{ + "type":"structure", + "required":["policyIdentifier"], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"policyIdentifier" + } + } + }, + "GetPolicyOutput":{ + "type":"structure", + "required":[ + "policyId", + "policyArn", + "policyName", + "status", + "priority", + "associatedTemplateAndRuleList", + "version", + "firewallType" + ], + "members":{ + "policyId":{ + "shape":"PolicyId", + "documentation":"

    The service-generated id of the policy.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the policy.

    " + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"AssociatedTemplateAndRuleList", + "documentation":"

    The templates and rules associated with the policy. For AWS WAF policies, this list contains 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list is empty.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "GetRuleInput":{ + "type":"structure", + "required":["ruleIdentifier"], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"ruleIdentifier" + } + } + }, + "GetRuleOutput":{ + "type":"structure", + "required":[ + "ruleId", + "ruleArn", + "ruleName", + "firewallType", + "configuration", + "status", + "version" + ], + "members":{ + "ruleId":{ + "shape":"RuleId", + "documentation":"

    The service-generated id of the rule.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "GetScopeInput":{ + "type":"structure", + "required":["scopeIdentifier"], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"scopeIdentifier" + } + } + }, + "GetScopeOutput":{ + "type":"structure", + "required":[ + "scopeId", + "scopeArn", + "scopeName", + "status", + "version" + ], + "members":{ + "scopeId":{ + "shape":"ScopeId", + "documentation":"

    The service-generated id of the scope.

    " + }, + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the scope.

    " + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable), ACTIVE (published, in use), or DISABLED (deactivated; changes cannot be published until the resource is re-enabled).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "GetTemplateInput":{ + "type":"structure", + "required":["templateIdentifier"], + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"templateIdentifier" + } + } + }, + "GetTemplateOutput":{ + "type":"structure", + "required":[ + "templateId", + "templateArn", + "templateName", + "status", + "version", + "associatedRuleList", + "firewallType" + ], + "members":{ + "templateId":{ + "shape":"TemplateId", + "documentation":"

    The service-generated id of the template.

    " + }, + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the template.

    " + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "associatedRuleList":{ + "shape":"AssociatedRuleList", + "documentation":"

    The rules associated with the template.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "HasPublishedVersion":{ + "type":"boolean", + "box":true + }, + "IdempotencyToken":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "Integer":{ + "type":"integer", + "box":true + }, + "InternalServerException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request processing failed because of an internal error in the service. This is a retryable error.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, + "InvalidFirewallReasons":{ + "type":"structure", + "members":{ + "incorrectSingleValueConfigurations":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Single-value configuration settings whose values do not match the expected values.

    " + }, + "missingAppendableConfigurationValues":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Appendable configuration values that are expected but missing.

    " + }, + "unexpectedAppendableConfigurationValues":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Appendable configuration values that are present but not expected.

    " + }, + "incorrectAppendableConfigurationOrder":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Appendable configuration values that are present but in the wrong order.

    " + }, + "missingMergeableConfigurationValues":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Mergeable configuration values that are expected but missing.

    " + }, + "unexpectedMergeableConfigurationValues":{ + "shape":"ConfigurationIssueList", + "documentation":"

    Mergeable configuration values that are present but not expected.

    " + } + }, + "documentation":"

    Details about the ways in which a firewall's configuration differs from the intended configuration.

    " + }, + "IpAddressType":{ + "type":"string", + "enum":[ + "ipv4", + "dualstack", + "dualstack-without-public-ipv4" + ] + }, + "IsPublished":{ + "type":"boolean", + "box":true + }, + "IsSnapshot":{ + "type":"boolean", + "box":true + }, + "JsonDocument":{ + "type":"structure", + "members":{}, + "document":true + }, + "ListAdminAccountsRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAdminAccountsResponse":{ + "type":"structure", + "required":["adminAccounts"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "adminAccounts":{ + "shape":"AdminAccountSummaryList", + "documentation":"

    The list of administrator accounts.

    " + } + } + }, + "ListAggregateResourceSynchronizationStatusesInput":{ + "type":"structure", + "members":{ + "synchronizationStatus":{ + "shape":"SynchronizationStatus", + "documentation":"

    Filters the results by synchronization status, such as IN_SYNC or OUT_OF_SYNC.

    ", + "location":"querystring", + "locationName":"synchronizationStatus" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAggregateResourceSynchronizationStatusesOutput":{ + "type":"structure", + "required":["resourceSynchronizationStatuses"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "resourceSynchronizationStatuses":{ + "shape":"ResourceSynchronizationStatusSummaryList", + "documentation":"

    The list of resource synchronization statuses.

    " + } + } + }, + "ListDeploymentSnapshotsInput":{ + "type":"structure", + "required":["deploymentIdentifier"], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"deploymentIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListDeploymentSnapshotsOutput":{ + "type":"structure", + "required":["snapshots"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "snapshots":{ + "shape":"DeploymentSummaryList", + "documentation":"

    The snapshots of the deployment.

    " + } + } + }, + "ListDeploymentsInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "status":{ + "shape":"EntityStatusFilter", + "documentation":"

    Filters the results by status: ACTIVE, DRAFT, or DISABLED.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListDeploymentsOutput":{ + "type":"structure", + "required":["deployments"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "deployments":{ + "shape":"DeploymentSummaryList", + "documentation":"

    The list of deployments.

    " + } + } + }, + "ListPoliciesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "status":{ + "shape":"EntityStatusFilter", + "documentation":"

    Filters the results by status, either ACTIVE or DRAFT.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListPoliciesOutput":{ + "type":"structure", + "required":["policies"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "policies":{ + "shape":"PolicySummaryList", + "documentation":"

    The list of policies.

    " + } + } + }, + "ListPolicySnapshotsInput":{ + "type":"structure", + "required":["policyIdentifier"], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"policyIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListPolicySnapshotsOutput":{ + "type":"structure", + "required":["snapshots"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "snapshots":{ + "shape":"PolicySummaryList", + "documentation":"

    The snapshots of the policy.

    " + } + } + }, + "ListResourceAssociationsInput":{ + "type":"structure", + "required":["resourceIdentifier"], + "members":{ + "resourceIdentifier":{ + "shape":"ResourceIdentifier", + "documentation":"

    The identifier of the resource to list associations for. This is the resource's Amazon Resource Name (ARN).

    ", + "location":"querystring", + "locationName":"resourceIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListResourceAssociationsOutput":{ + "type":"structure", + "required":["resourceAssociations"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "resourceAssociations":{ + "shape":"ResourceAssociationList", + "documentation":"

    The list of resource associations.

    " + } + } + }, + "ListResourceSynchronizationStatusesInput":{ + "type":"structure", + "required":["deploymentIdentifier"], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment to list synchronization statuses for. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"querystring", + "locationName":"deploymentIdentifier" + }, + "synchronizationStatus":{ + "shape":"SynchronizationStatus", + "documentation":"

    Filters the results by synchronization status, such as IN_SYNC or OUT_OF_SYNC.

    ", + "location":"querystring", + "locationName":"synchronizationStatus" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListResourceSynchronizationStatusesOutput":{ + "type":"structure", + "required":["resourceSynchronizationStatuses"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "resourceSynchronizationStatuses":{ + "shape":"ResourceSynchronizationStatusSummaryList", + "documentation":"

    The list of resource synchronization statuses.

    " + } + } + }, + "ListRuleSnapshotsInput":{ + "type":"structure", + "required":["ruleIdentifier"], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"ruleIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListRuleSnapshotsOutput":{ + "type":"structure", + "required":["snapshots"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "snapshots":{ + "shape":"RuleSummaryList", + "documentation":"

    The snapshots of the rule.

    " + } + } + }, + "ListRulesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "status":{ + "shape":"EntityStatusFilter", + "documentation":"

    Filters the results by status, either ACTIVE or DRAFT.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListRulesOutput":{ + "type":"structure", + "required":["rules"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "rules":{ + "shape":"RuleSummaryList", + "documentation":"

    The list of rules.

    " + } + } + }, + "ListScopeSnapshotsInput":{ + "type":"structure", + "required":["scopeIdentifier"], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"scopeIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListScopeSnapshotsOutput":{ + "type":"structure", + "required":["snapshots"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "snapshots":{ + "shape":"ScopeSummaryList", + "documentation":"

    The snapshots of the scope.

    " + } + } + }, + "ListScopesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "status":{ + "shape":"EntityStatusFilter", + "documentation":"

    Filters the results by status: ACTIVE, DRAFT, or DISABLED.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListScopesOutput":{ + "type":"structure", + "required":["scopes"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "scopes":{ + "shape":"ScopeSummaryList", + "documentation":"

    The list of scopes.

    " + } + } + }, + "ListTagsForResourceInput":{ + "type":"structure", + "required":["resourceArn"], + "members":{ + "resourceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the resource to list tags for. The ARN must not include a :DRAFT qualifier.

    ", + "location":"uri", + "locationName":"resourceArn" + } + } + }, + "ListTagsForResourceOutput":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags associated with the resource. Each tag is a key-value pair.

    " + } + } + }, + "ListTemplateSnapshotsInput":{ + "type":"structure", + "required":["templateIdentifier"], + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"templateIdentifier" + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTemplateSnapshotsOutput":{ + "type":"structure", + "required":["snapshots"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "snapshots":{ + "shape":"TemplateSummaryList", + "documentation":"

    The snapshots of the template.

    " + } + } + }, + "ListTemplatesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Valid range: 1-100. To retrieve the remaining results, use the returned nextToken value in a subsequent call.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "status":{ + "shape":"EntityStatusFilter", + "documentation":"

    Filters the results by status, either ACTIVE or DRAFT.

    ", + "location":"querystring", + "locationName":"status" + } + } + }, + "ListTemplatesOutput":{ + "type":"structure", + "required":["templates"], + "members":{ + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next page of results. To retrieve the next page, call the operation again and provide this value. When there are no more results, this value is null.

    " + }, + "templates":{ + "shape":"TemplateSummaryList", + "documentation":"

    The list of templates.

    " + } + } + }, + "MaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "NextToken":{ + "type":"string", + "max":4096, + "min":1, + "pattern":"[0-9A-Za-z:/+=_-]+" + }, + "NotVisibleMarker":{ + "type":"structure", + "required":["reason"], + "members":{ + "reason":{ + "shape":"String", + "documentation":"

    The reason the details are not visible.

    " + } + }, + "documentation":"

    Indicates that details are not visible because of cross-account restrictions.

    " + }, + "OrganizationalUnit":{ + "type":"string", + "max":68, + "min":0 + }, + "OrganizationalUnitId":{ + "type":"string", + "max":68, + "min":16, + "pattern":"(ou-[0-9a-z]{4,32}-[a-z0-9]{8,32})" + }, + "OrganizationalUnitIdList":{ + "type":"list", + "member":{"shape":"OrganizationalUnitId"}, + "max":100, + "min":0 + }, + "OrganizationalUnitList":{ + "type":"list", + "member":{"shape":"OrganizationalUnit"}, + "max":1000, + "min":0 + }, + "OrganizationalUnitReference":{ + "type":"structure", + "required":["ouId"], + "members":{ + "ouId":{ + "shape":"OrganizationalUnitId", + "documentation":"

    The ID of the AWS Organizations organizational unit (OU).

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The display name of the organizational unit.

    " + } + }, + "documentation":"

    A reference to an AWS Organizations organizational unit (OU), with optional display metadata.

    " + }, + "OrganizationalUnitReferenceList":{ + "type":"list", + "member":{"shape":"OrganizationalUnitReference"}, + "max":1000, + "min":0 + }, + "OutOfSyncReasons":{ + "type":"map", + "key":{"shape":"PolicyFirewallType"}, + "value":{"shape":"FirewallSyncReason"}, + "max":10, + "min":0 + }, + "OutOfSyncReasonsView":{ + "type":"structure", + "members":{ + "reasons":{ + "shape":"OutOfSyncReasons", + "documentation":"

    The out-of-sync reasons, keyed by firewall type.

    " + }, + "notVisible":{ + "shape":"NotVisibleMarker", + "documentation":"

    Indicates that the details are not visible because of cross-account restrictions.

    " + } + }, + "documentation":"

    The out-of-sync reasons for a resource, or a marker indicating that the details are not visible. Exactly one member is set.

    ", + "union":true + }, + "PolicyArn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "PolicyConfiguration":{ + "type":"structure", + "required":[ + "remediationEnabled", + "resourcesCleanUp" + ], + "members":{ + "remediationEnabled":{ + "shape":"RemediationEnabled", + "documentation":"

    Specifies whether AWS Network Security Manager automatically remediates noncompliant resources. Default: false.

    " + }, + "resourcesCleanUp":{ + "shape":"ResourcesCleanUp", + "documentation":"

    Specifies whether AWS Network Security Manager automatically removes the resources it created when they are no longer needed. Default: false.

    " + }, + "wafConfig":{ + "shape":"WafConfig", + "documentation":"

    AWS WAF-specific policy settings. This is populated only for AWS WAF policies.

    " + } + }, + "documentation":"

    Configuration settings that control a policy's behavior.

    " + }, + "PolicyFirewallType":{ + "type":"string", + "enum":[ + "WAF", + "SHIELD_ADVANCED" + ] + }, + "PolicyId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9]{1,64}" + }, + "PolicyIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "PolicyName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _.:/=+\\-@]*" + }, + "PolicyReference":{ + "type":"structure", + "required":["policyIdentifier"], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN), optionally version-qualified to pin a specific published version.

    " + } + }, + "documentation":"

    A reference to a policy in a create or update request.

    " + }, + "PolicyReferenceList":{ + "type":"list", + "member":{"shape":"PolicyReference"}, + "max":2, + "min":1 + }, + "PolicySummary":{ + "type":"structure", + "required":[ + "policyId", + "policyArn" + ], + "members":{ + "policyId":{ + "shape":"PolicyId", + "documentation":"

    The service-generated id of the policy.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the policy.

    " + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated. For a snapshot, this is the time when the snapshot was created.

    " + } + }, + "documentation":"

    Summary information about a policy.

    " + }, + "PolicySummaryList":{ + "type":"list", + "member":{"shape":"PolicySummary"}, + "max":100, + "min":0 + }, + "Priority":{ + "type":"integer", + "box":true, + "min":1 + }, + "PutAdminAccountRequest":{ + "type":"structure", + "required":[ + "accountId", + "priority" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID to set as the AWS Network Security Manager administrator account.

    " + }, + "priority":{ + "shape":"AdminPriority", + "documentation":"

    The priority to assign to the administrator account.

    " + }, + "adminScope":{ + "shape":"AdminScopeInput", + "documentation":"

    The scope of accounts, organizational units, and firewall types that the administrator can manage.

    " + } + } + }, + "PutAdminAccountResponse":{ + "type":"structure", + "members":{ + "adminAccountDetails":{ + "shape":"AdminAccountDetails", + "documentation":"

    The details of the administrator account that was set.

    " + } + } + }, + "RemediationEnabled":{ + "type":"boolean", + "box":true + }, + "RemediationIssueDetails":{ + "type":"structure", + "members":{ + "issueType":{ + "shape":"String", + "documentation":"

    The type of remediation issue.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A human-readable description of the remediation issue.

    " + }, + "correctiveAction":{ + "shape":"String", + "documentation":"

    A recommended action for resolving the remediation issue.

    " + } + }, + "documentation":"

    Details about a remediation issue for a firewall type.

    " + }, + "RemediationIssues":{ + "type":"map", + "key":{"shape":"PolicyFirewallType"}, + "value":{"shape":"RemediationIssueDetails"}, + "max":10, + "min":0 + }, + "RemediationIssuesView":{ + "type":"structure", + "members":{ + "issues":{ + "shape":"RemediationIssues", + "documentation":"

    The remediation issues, keyed by firewall type.

    " + }, + "notVisible":{ + "shape":"NotVisibleMarker", + "documentation":"

    Indicates that the details are not visible because of cross-account restrictions.

    " + } + }, + "documentation":"

    Remediation issue details for a resource, or a marker indicating that the details are not visible. Exactly one member is set.

    ", + "union":true + }, + "ResourceArnList":{ + "type":"list", + "member":{"shape":"Arn"}, + "max":100, + "min":0 + }, + "ResourceAssociation":{ + "type":"structure", + "required":[ + "arn", + "resourceType" + ], + "members":{ + "arn":{ + "shape":"Arn", + "documentation":"

    The ARN of the associated resource.

    " + }, + "resourceType":{ + "shape":"ServiceResourceType", + "documentation":"

    The type of the associated resource, such as Policy, Template, or Deployment.

    " + } + }, + "documentation":"

    Describes an association between a resource and another entity.

    " + }, + "ResourceAssociationList":{ + "type":"list", + "member":{"shape":"ResourceAssociation"}, + "max":100, + "min":0 + }, + "ResourceCriteria":{ + "type":"structure", + "members":{ + "tags":{ + "shape":"StringMap", + "documentation":"

    Tag key-value pairs used to match resources.

    " + }, + "albConfig":{ + "shape":"AlbConfiguration", + "documentation":"

    Filter criteria specific to Application Load Balancers.

    " + } + }, + "documentation":"

    A leaf condition that matches resources by tag or by resource-type-specific configuration.

    ", + "union":true + }, + "ResourceIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "ResourceLogicalExpression":{ + "type":"structure", + "members":{ + "criteria":{ + "shape":"ResourceCriteria", + "documentation":"

    A leaf condition that matches resources by tag or by resource-type-specific configuration.

    " + }, + "and":{ + "shape":"ResourceLogicalExpressionList", + "documentation":"

    A list of subexpressions that must all match.

    " + }, + "or":{ + "shape":"ResourceLogicalExpressionList", + "documentation":"

    A list of subexpressions of which at least one must match.

    " + }, + "not":{ + "shape":"ResourceLogicalExpression", + "documentation":"

    A subexpression that must not match.

    " + } + }, + "documentation":"

    A logical expression that selects resources. Exactly one of criteria, and, or, or not is set.

    ", + "union":true + }, + "ResourceLogicalExpressionList":{ + "type":"list", + "member":{"shape":"ResourceLogicalExpression"}, + "max":20, + "min":0 + }, + "ResourceNotFoundException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The ID of the resource that could not be found.

    " + }, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource that could not be found.

    " + } + }, + "documentation":"

    The specified resource was not found. Verify that the resource identifier is correct and that the resource exists, then try your request again.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "ResourceScope":{ + "type":"structure", + "members":{ + "includeAll":{ + "shape":"Boolean", + "documentation":"

    Includes all resources of the resource type.

    " + }, + "include":{ + "shape":"ResourceSet", + "documentation":"

    Includes the resources that match the specified criteria or explicit ARNs.

    " + }, + "exclude":{ + "shape":"ResourceSet", + "documentation":"

    Excludes the resources that match the specified criteria or explicit ARNs.

    " + } + }, + "documentation":"

    Defines which resources of a given type are in scope. Exactly one of includeAll, include, or exclude is set.

    " + }, + "ResourceScopeMap":{ + "type":"map", + "key":{"shape":"ScopeResourceType"}, + "value":{"shape":"ResourceScope"}, + "max":20, + "min":0 + }, + "ResourceSet":{ + "type":"structure", + "members":{ + "explicitArns":{ + "shape":"ResourceArnList", + "documentation":"

    An explicit list of resource ARNs.

    " + }, + "expression":{ + "shape":"ResourceLogicalExpression", + "documentation":"

    A logical expression that selects resources by combining criteria with AND, OR, and NOT operators.

    " + } + }, + "documentation":"

    A set of resources defined by explicit ARNs, a logical expression, or both.

    " + }, + "ResourceSynchronizationStatusSummary":{ + "type":"structure", + "required":[ + "synchronizationStatus", + "accountId", + "resourceArn", + "updatedAt" + ], + "members":{ + "synchronizationStatus":{ + "shape":"SynchronizationStatus", + "documentation":"

    The synchronization status of the resource, such as IN_SYNC or OUT_OF_SYNC.

    " + }, + "accountId":{ + "shape":"AccountId", + "documentation":"

    The AWS account ID that owns the resource.

    " + }, + "resourceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the resource whose synchronization status is reported.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The ARN of the deployment that the synchronization status is associated with. This is absent for aggregate (cross-deployment) statuses.

    " + }, + "resourceType":{ + "shape":"ResourceType", + "documentation":"

    The type of the resource, in AWS CloudFormation format.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + }, + "outOfSyncReasons":{ + "shape":"OutOfSyncReasonsView", + "documentation":"

    The reasons the resource is out of sync, keyed by firewall type. This is null when the resource is in sync.

    " + }, + "remediationIssues":{ + "shape":"RemediationIssuesView", + "documentation":"

    Details about remediation issues, keyed by firewall type. This is null when there are no remediation issues.

    " + }, + "evaluatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the synchronization status was last evaluated.

    " + } + }, + "documentation":"

    The synchronization status of a resource covered by a deployment.

    " + }, + "ResourceSynchronizationStatusSummaryList":{ + "type":"list", + "member":{"shape":"ResourceSynchronizationStatusSummary"}, + "max":100, + "min":0 + }, + "ResourceType":{ + "type":"string", + "enum":[ + "AWS::ApiGateway::Stage", + "AWS::CloudFront::Distribution", + "AWS::EC2::EIP", + "AWS::ElasticLoadBalancingV2::LoadBalancer::application", + "AWS::ElasticLoadBalancing::LoadBalancer", + "AWS::WAFv2::WebACL", + "AWS::Shield::Protection", + "AWS::ShieldRegional::Protection" + ] + }, + "ResourcesCleanUp":{ + "type":"boolean", + "box":true + }, + "RuleArn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "RuleFirewallType":{ + "type":"string", + "enum":["WAF"] + }, + "RuleId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9]{1,64}" + }, + "RuleIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "RuleName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _.:/=+\\-@]*" + }, + "RuleReference":{ + "type":"structure", + "required":["ruleIdentifier"], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    " + } + }, + "documentation":"

    A reference to a rule in a create or update request.

    " + }, + "RuleReferenceList":{ + "type":"list", + "member":{"shape":"RuleReference"}, + "max":50, + "min":1 + }, + "RuleSummary":{ + "type":"structure", + "required":[ + "ruleId", + "ruleArn", + "ruleName" + ], + "members":{ + "ruleId":{ + "shape":"RuleId", + "documentation":"

    The service-generated id of the rule.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated. For a snapshot, this is the time when the snapshot was created.

    " + } + }, + "documentation":"

    Summary information about a rule.

    " + }, + "RuleSummaryList":{ + "type":"list", + "member":{"shape":"RuleSummary"}, + "max":100, + "min":0 + }, + "RuleType":{ + "type":"string", + "enum":[ + "CONFIGURATION", + "INSPECTION" + ] + }, + "Scheme":{ + "type":"string", + "enum":[ + "internet-facing", + "internal" + ] + }, + "ScopeArn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "ScopeConfiguration":{ + "type":"structure", + "required":["resourceScopes"], + "members":{ + "accountFilter":{ + "shape":"AccountFilter", + "documentation":"

    The account filter that determines which accounts are in scope. When set, exactly one of includeAll, include, or exclude is set.

    Organization administrators must include an account filter in every scope configuration. Single-account administrators must omit it: a scope without an account filter applies only to the administrator's own account. The presence of an account filter is fixed when the scope is created: an update can't add an account filter to a scope that was created without one, or remove the account filter from a scope that was created with one.

    " + }, + "resourceScopes":{ + "shape":"ResourceScopeMap", + "documentation":"

    The resource-level scoping configuration, keyed by resource type, that defines which resources within the selected accounts are in scope.

    " + } + }, + "documentation":"

    Defines which accounts and resources are in scope.

    " + }, + "ScopeId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9]{1,64}" + }, + "ScopeIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "ScopeName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _.:/=+\\-@]*" + }, + "ScopeReference":{ + "type":"structure", + "required":["scopeIdentifier"], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    " + } + }, + "documentation":"

    A reference to a scope in a create or update request.

    " + }, + "ScopeReferenceList":{ + "type":"list", + "member":{"shape":"ScopeReference"}, + "max":1, + "min":1 + }, + "ScopeResourceType":{ + "type":"string", + "enum":[ + "AWS::ApiGateway::Stage", + "AWS::CloudFront::Distribution", + "AWS::EC2::EIP", + "AWS::ElasticLoadBalancingV2::LoadBalancer::application", + "AWS::ElasticLoadBalancing::LoadBalancer" + ] + }, + "ScopeSummary":{ + "type":"structure", + "required":[ + "scopeId", + "scopeArn" + ], + "members":{ + "scopeId":{ + "shape":"ScopeId", + "documentation":"

    The service-generated id of the scope.

    " + }, + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the scope.

    " + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable), ACTIVE (published, in use), or DISABLED (deactivated; changes cannot be published until the resource is re-enabled).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated. For a snapshot, this is the time when the snapshot was created.

    " + } + }, + "documentation":"

    Summary information about a scope.

    " + }, + "ScopeSummaryList":{ + "type":"list", + "member":{"shape":"ScopeSummary"}, + "max":100, + "min":0 + }, + "SensitiveAccountEmail":{ + "type":"string", + "max":64, + "min":6, + "sensitive":true + }, + "SensitiveAccountName":{ + "type":"string", + "max":50, + "min":1, + "sensitive":true + }, + "SensitiveEmail":{ + "type":"string", + "max":256, + "min":0, + "sensitive":true + }, + "SensitiveName":{ + "type":"string", + "max":256, + "min":0, + "sensitive":true + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "quotaCode":{ + "shape":"String", + "documentation":"

    The code that identifies the service quota that was exceeded.

    " + }, + "serviceCode":{ + "shape":"String", + "documentation":"

    The code for the AWS service that owns the quota that was exceeded.

    " + }, + "resourceId":{ + "shape":"String", + "documentation":"

    The ID of the resource associated with the quota that was exceeded.

    " + }, + "resourceType":{ + "shape":"String", + "documentation":"

    The type of the resource associated with the quota that was exceeded.

    " + } + }, + "documentation":"

    The request would exceed a service quota.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "ServiceResourceType":{ + "type":"string", + "enum":[ + "Rule", + "Template", + "Policy", + "Deployment", + "Scope" + ] + }, + "ServiceUnavailableException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "retryAfterSeconds":{ + "shape":"Integer", + "documentation":"

    The number of seconds to wait before retrying the request.

    " + } + }, + "documentation":"

    The service is temporarily unavailable. This is a retryable error.

    ", + "error":{"httpStatusCode":503}, + "exception":true, + "fault":true, + "retryable":{"throttling":false} + }, + "String":{"type":"string"}, + "StringMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "max":100, + "min":0 + }, + "SynchronizationStatus":{ + "type":"string", + "enum":[ + "IN_SYNC", + "OUT_OF_SYNC", + "NOT_APPLICABLE" + ] + }, + "TagKey":{ + "type":"string", + "max":128, + "min":1, + "pattern":"([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)" + }, + "TagKeyList":{ + "type":"list", + "member":{"shape":"TagKey"}, + "max":200, + "min":0 + }, + "TagMap":{ + "type":"map", + "key":{"shape":"TagKey"}, + "value":{"shape":"TagValue"}, + "max":200, + "min":0 + }, + "TagPolicyViolationException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request violates a tag policy that is in effect for the account or organization.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "TagResourceInput":{ + "type":"structure", + "required":[ + "resourceArn", + "tags" + ], + "members":{ + "resourceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the resource to tag. The ARN must not include a :DRAFT qualifier.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tags":{ + "shape":"TagMap", + "documentation":"

    The tags to add to the resource.

    " + } + } + }, + "TagResourceOutput":{ + "type":"structure", + "members":{} + }, + "TagValue":{ + "type":"string", + "max":256, + "min":0 + }, + "TemplateAndRuleReferenceList":{ + "type":"list", + "member":{"shape":"TemplateOrRuleReference"}, + "max":100, + "min":0 + }, + "TemplateArn":{ + "type":"string", + "max":1010, + "min":20, + "pattern":"arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:(.+)" + }, + "TemplateFirewallType":{ + "type":"string", + "enum":["WAF"] + }, + "TemplateId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z0-9]{1,64}" + }, + "TemplateIdentifier":{ + "type":"string", + "max":1010, + "min":1 + }, + "TemplateName":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[a-zA-Z0-9][a-zA-Z0-9 _.:/=+\\-@]*" + }, + "TemplateOrRuleReference":{ + "type":"structure", + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    " + }, + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    " + } + }, + "documentation":"

    A reference to either a template or a rule in a create or update request. Set exactly one of templateIdentifier or ruleIdentifier.

    ", + "union":true + }, + "TemplateSummary":{ + "type":"structure", + "required":[ + "templateId", + "templateArn", + "templateName" + ], + "members":{ + "templateId":{ + "shape":"TemplateId", + "documentation":"

    The service-generated id of the template.

    " + }, + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the template.

    " + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated. For a snapshot, this is the time when the snapshot was created.

    " + } + }, + "documentation":"

    Summary information about a template.

    " + }, + "TemplateSummaryList":{ + "type":"list", + "member":{"shape":"TemplateSummary"}, + "max":100, + "min":0 + }, + "ThrottlingException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "retryAfterSeconds":{ + "shape":"Integer", + "documentation":"

    The number of seconds to wait before retrying the request.

    " + } + }, + "documentation":"

    The request was denied because of request throttling. Reduce your request rate and try again.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true, + "retryable":{"throttling":true} + }, + "Unit":{ + "type":"structure", + "members":{} + }, + "UntagResourceInput":{ + "type":"structure", + "required":[ + "resourceArn", + "tagKeys" + ], + "members":{ + "resourceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the resource to remove tags from. The ARN must not include a :DRAFT qualifier.

    ", + "location":"uri", + "locationName":"resourceArn" + }, + "tagKeys":{ + "shape":"TagKeyList", + "documentation":"

    The keys of the tags to remove from the resource.

    ", + "location":"querystring", + "locationName":"tagKeys" + } + } + }, + "UntagResourceOutput":{ + "type":"structure", + "members":{} + }, + "UpdateDeploymentInput":{ + "type":"structure", + "required":[ + "deploymentIdentifier", + "updateToken", + "isPublished" + ], + "members":{ + "deploymentIdentifier":{ + "shape":"DeploymentIdentifier", + "documentation":"

    The identifier of the deployment. This is the deployment's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"deploymentIdentifier" + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"PolicyReferenceList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"ScopeReferenceList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT).

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "UpdateDeploymentOutput":{ + "type":"structure", + "required":[ + "deploymentId", + "deploymentArn", + "deploymentName", + "status", + "associatedPolicyList", + "associatedScopeList", + "version" + ], + "members":{ + "deploymentId":{ + "shape":"DeploymentId", + "documentation":"

    The service-generated id of the deployment.

    " + }, + "deploymentArn":{ + "shape":"DeploymentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deployment.

    " + }, + "deploymentName":{ + "shape":"DeploymentName", + "documentation":"

    The name of the deployment.

    " + }, + "deploymentDescription":{ + "shape":"Description", + "documentation":"

    A description of the deployment.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "deploymentConfiguration":{ + "shape":"DeploymentConfiguration", + "documentation":"

    The configuration settings for the deployment.

    " + }, + "associatedPolicyList":{ + "shape":"AssociatedPolicyList", + "documentation":"

    The policies associated with the deployment.

    " + }, + "associatedScopeList":{ + "shape":"AssociatedScopeList", + "documentation":"

    The scope associated with the deployment. A deployment has exactly one scope.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "deploymentCoverage":{ + "shape":"DeploymentCoverageList", + "documentation":"

    The coverage information for the deployment. For each firewall type, it shows which policies have that firewall type and which in-scope resource types the firewall type protects.

    " + }, + "warnings":{ + "shape":"DeploymentWarningList", + "documentation":"

    Warnings about potential issues, such as a policy that has no applicable resources in the deployment's scope.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "UpdatePolicyInput":{ + "type":"structure", + "required":[ + "policyIdentifier", + "updateToken", + "isPublished" + ], + "members":{ + "policyIdentifier":{ + "shape":"PolicyIdentifier", + "documentation":"

    The identifier of the policy. This is the policy's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"policyIdentifier" + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"TemplateAndRuleReferenceList", + "documentation":"

    The templates and rules to associate with the policy. For AWS WAF policies, specify 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list must be empty.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT).

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "UpdatePolicyOutput":{ + "type":"structure", + "required":[ + "policyId", + "policyArn", + "policyName", + "status", + "priority", + "associatedTemplateAndRuleList", + "version", + "firewallType" + ], + "members":{ + "policyId":{ + "shape":"PolicyId", + "documentation":"

    The service-generated id of the policy.

    " + }, + "policyArn":{ + "shape":"PolicyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the policy.

    " + }, + "policyName":{ + "shape":"PolicyName", + "documentation":"

    The name of the policy.

    " + }, + "policyDescription":{ + "shape":"Description", + "documentation":"

    A description of the policy.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the resource. A lower number indicates a higher priority.

    " + }, + "associatedTemplateAndRuleList":{ + "shape":"AssociatedTemplateAndRuleList", + "documentation":"

    The templates and rules associated with the policy. For AWS WAF policies, this list contains 1 to 100 templates or rules, of which at most 2 can be templates. For AWS Shield Advanced policies, this list is empty.

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"PolicyFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "policyConfiguration":{ + "shape":"PolicyConfiguration", + "documentation":"

    The configuration settings that control the policy's behavior, including remediation and firewall-type-specific settings.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "UpdateRuleInput":{ + "type":"structure", + "required":[ + "ruleIdentifier", + "updateToken", + "isPublished" + ], + "members":{ + "ruleIdentifier":{ + "shape":"RuleIdentifier", + "documentation":"

    The identifier of the rule. This is the rule's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"ruleIdentifier" + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type. For an AWS WAF INSPECTION rule, provide an AWS WAF rule group. For an AWS WAF CONFIGURATION rule, provide a single web ACL setting, such as DefaultAction or VisibilityConfig; use wafConfigDataType to declare which setting the document contains. For the schema of each setting and complete examples, see Writing rule configurations in the AWS Network Security Manager Developer Guide.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT).

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "UpdateRuleOutput":{ + "type":"structure", + "required":[ + "ruleId", + "ruleArn", + "ruleName", + "firewallType", + "configuration", + "status", + "version" + ], + "members":{ + "ruleId":{ + "shape":"RuleId", + "documentation":"

    The service-generated id of the rule.

    " + }, + "ruleArn":{ + "shape":"RuleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the rule.

    " + }, + "ruleName":{ + "shape":"RuleName", + "documentation":"

    The name of the rule.

    " + }, + "firewallType":{ + "shape":"RuleFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "ruleType":{ + "shape":"RuleType", + "documentation":"

    The type of the rule. CONFIGURATION rules contain firewall settings, and INSPECTION rules contain rule groups.

    " + }, + "ruleDescription":{ + "shape":"Description", + "documentation":"

    A description of the rule.

    " + }, + "configuration":{ + "shape":"JsonDocument", + "documentation":"

    The firewall configuration for the rule, as a JSON document. The structure depends on the rule's firewall type and rule type.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "UpdateScopeInput":{ + "type":"structure", + "required":[ + "scopeIdentifier", + "updateToken", + "isPublished" + ], + "members":{ + "scopeIdentifier":{ + "shape":"ScopeIdentifier", + "documentation":"

    The identifier of the scope. This is the scope's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"scopeIdentifier" + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope. If you don't include this member, the scope keeps its existing configuration.

    A new configuration can change which accounts and resources are selected, but it can't add or remove the account filter itself: a scope created for multi-account use stays multi-account, and a scope created for single-account use stays single-account.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT).

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "UpdateScopeOutput":{ + "type":"structure", + "required":[ + "scopeId", + "scopeArn", + "scopeName", + "status", + "version" + ], + "members":{ + "scopeId":{ + "shape":"ScopeId", + "documentation":"

    The service-generated id of the scope.

    " + }, + "scopeArn":{ + "shape":"ScopeArn", + "documentation":"

    The Amazon Resource Name (ARN) of the scope.

    " + }, + "scopeName":{ + "shape":"ScopeName", + "documentation":"

    The name of the scope.

    " + }, + "scopeDescription":{ + "shape":"Description", + "documentation":"

    A description of the scope.

    " + }, + "scopeConfiguration":{ + "shape":"ScopeConfiguration", + "documentation":"

    The configuration that defines which accounts and resources are in scope.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "UpdateTemplateInput":{ + "type":"structure", + "required":[ + "templateIdentifier", + "updateToken", + "isPublished" + ], + "members":{ + "templateIdentifier":{ + "shape":"TemplateIdentifier", + "documentation":"

    The identifier of the template. This is the template's Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"templateIdentifier" + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "associatedRuleList":{ + "shape":"RuleReferenceList", + "documentation":"

    The rules associated with the template.

    " + }, + "isPublished":{ + "shape":"IsPublished", + "documentation":"

    Specifies whether to publish the resource. When true, the resource is saved in published (ACTIVE) state. When false, it is saved as a draft (DRAFT).

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive token that you provide to ensure that the operation completes no more than one time. If you retry a request with the same client token and the same parameters, the service returns the result of the original successful request.

    ", + "idempotencyToken":true + } + } + }, + "UpdateTemplateOutput":{ + "type":"structure", + "required":[ + "templateId", + "templateArn", + "templateName", + "status", + "version", + "associatedRuleList", + "firewallType" + ], + "members":{ + "templateId":{ + "shape":"TemplateId", + "documentation":"

    The service-generated id of the template.

    " + }, + "templateArn":{ + "shape":"TemplateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the template.

    " + }, + "templateName":{ + "shape":"TemplateName", + "documentation":"

    The name of the template.

    " + }, + "templateDescription":{ + "shape":"Description", + "documentation":"

    A description of the template.

    " + }, + "status":{ + "shape":"EntityStatus", + "documentation":"

    The current status of the resource: DRAFT (unpublished, editable) or ACTIVE (published, in use).

    " + }, + "version":{ + "shape":"EntityVersion", + "documentation":"

    The version of the resource.

    " + }, + "associatedRuleList":{ + "shape":"AssociatedRuleList", + "documentation":"

    The rules associated with the template.

    " + }, + "updateToken":{ + "shape":"UpdateToken", + "documentation":"

    A token used for optimistic concurrency control. Each read and write returns an updateToken. Provide the most recent value on your next update to detect and prevent conflicting concurrent modifications.

    " + }, + "isSnapshot":{ + "shape":"IsSnapshot", + "documentation":"

    Specifies whether the resource is a snapshot of a published version.

    " + }, + "hasPublishedVersion":{ + "shape":"HasPublishedVersion", + "documentation":"

    Specifies whether a published version of the resource exists.

    " + }, + "firewallType":{ + "shape":"TemplateFirewallType", + "documentation":"

    The firewall type associated with the resource.

    " + }, + "updatedAt":{ + "shape":"DateTimestamp", + "documentation":"

    The time when the resource was last updated.

    " + } + } + }, + "UpdateToken":{ + "type":"string", + "max":36, + "min":36, + "pattern":"([0-9a-f]{8})-([0-9a-f]{4}-){3}([0-9a-f]{12})" + }, + "ValidationException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "reason":{ + "shape":"ValidationExceptionReason", + "documentation":"

    The reason that the request failed validation.

    " + }, + "fieldList":{ + "shape":"ValidationExceptionFieldList", + "documentation":"

    The list of request fields that failed validation, if any.

    " + } + }, + "documentation":"

    The request failed validation. For details, see the reason and fieldList members of the response.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "ValidationExceptionField":{ + "type":"structure", + "required":[ + "name", + "message" + ], + "members":{ + "name":{ + "shape":"String", + "documentation":"

    The name of the field that failed validation.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A message describing the validation error for the field.

    " + } + }, + "documentation":"

    Describes a single request field that failed validation.

    " + }, + "ValidationExceptionFieldList":{ + "type":"list", + "member":{"shape":"ValidationExceptionField"}, + "max":100, + "min":0 + }, + "ValidationExceptionReason":{ + "type":"string", + "enum":[ + "ACCOUNT_NOT_ONBOARDED", + "FIELD_VALIDATION_FAILED", + "OTHER" + ] + }, + "WAFConfigDataType":{ + "type":"string", + "enum":[ + "DefaultAction", + "VisibilityConfig", + "CaptchaConfig", + "ChallengeConfig", + "CustomResponseBodies", + "LoggingConfiguration", + "DataProtectionConfig", + "AssociationConfig", + "OnSourceDDoSProtectionConfig", + "TokenDomains" + ] + }, + "WAFConflictResolutionOptions":{ + "type":"string", + "enum":["MERGE_WHERE_APPLICABLE"] + }, + "WafConfig":{ + "type":"structure", + "required":[ + "existingCustomerWebACLResolution", + "conflictResolution" + ], + "members":{ + "existingCustomerWebACLResolution":{ + "shape":"ExistingCustomerWebACLResolution", + "documentation":"

    Determines how AWS Network Security Manager handles remediation when a resource already has a customer-created web ACL. Required for AWS WAF policies.

    " + }, + "conflictResolution":{ + "shape":"WAFConflictResolutionOptions", + "documentation":"

    The conflict-resolution strategy for AWS WAF policies. Required for AWS WAF policies.

    " + } + }, + "documentation":"

    AWS WAF-specific policy configuration settings.

    " + } + }, + "documentation":"

    AWS Network Security Manager helps you centrally configure and deploy network security protections across your organization. Supported protections include AWS WAF and AWS Shield Advanced. This centralized approach reduces the overhead of managing protections individually across accounts and ensures consistent security at scale.

    You define reusable rules and templates, then combine them into policies. Next, you select the accounts and resources to protect with scopes and roll the protections out with deployments. For example, you can define a set of AWS WAF rules and group them into a policy. Then deploy that policy across all accounts in your organization with a single deployment.

    This API reference describes the operations and data types for AWS Network Security Manager.

    For conceptual information, tutorials, and guidance on writing rule configurations, see the AWS Network Security Manager Developer Guide. For the default quotas that apply to your account, see Quotas. For the service endpoints available in each Region, see AWS Network Security Manager endpoints and quotas in the AWS General Reference.

    " +} diff --git a/services/networksecuritymanager/src/main/resources/codegen-resources/waiters-2.json b/services/networksecuritymanager/src/main/resources/codegen-resources/waiters-2.json new file mode 100644 index 000000000000..13f60ee66be6 --- /dev/null +++ b/services/networksecuritymanager/src/main/resources/codegen-resources/waiters-2.json @@ -0,0 +1,5 @@ +{ + "version": 2, + "waiters": { + } +} diff --git a/services/notifications/pom.xml b/services/notifications/pom.xml index 9155a8968c75..63c9959eee00 100644 --- a/services/notifications/pom.xml +++ b/services/notifications/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT notifications AWS Java SDK :: Services :: Notifications diff --git a/services/notifications/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/notifications/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..310a8fc7ca6e --- /dev/null +++ b/services/notifications/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://notifications-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://notifications.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/notifications/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/notifications/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2684bfda0a44..000000000000 --- a/services/notifications/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://notifications-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://notifications.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/notifications/src/main/resources/codegen-resources/service-2.json b/services/notifications/src/main/resources/codegen-resources/service-2.json index 68428561f7cc..480ab994aa33 100644 --- a/services/notifications/src/main/resources/codegen-resources/service-2.json +++ b/services/notifications/src/main/resources/codegen-resources/service-2.json @@ -195,7 +195,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Deregisters a NotificationConfiguration in the specified Region.

    You can't deregister the last NotificationHub in the account. NotificationEvents stored in the deregistered NotificationConfiguration are no longer be visible. Recreating a new NotificationConfiguration in the same Region restores access to those NotificationEvents.

    ", + "documentation":"

    Deregisters a NotificationHub in the specified Region.

    You can't deregister the last NotificationHub in the account. NotificationEvents stored in the deregistered NotificationHub are no longer visible. Recreating a new NotificationHub in the same Region restores access to those NotificationEvents.

    ", "idempotent":true }, "DisableNotificationsAccessForOrganization":{ @@ -333,7 +333,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a specified EventRule.

    " + "documentation":"

    Returns a specified EventRule.

    ", + "readonly":true }, "GetManagedNotificationChildEvent":{ "name":"GetManagedNotificationChildEvent", @@ -351,7 +352,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the child event of a specific given ManagedNotificationEvent.

    " + "documentation":"

    Returns the child event of a specific given ManagedNotificationEvent.

    ", + "readonly":true }, "GetManagedNotificationConfiguration":{ "name":"GetManagedNotificationConfiguration", @@ -369,7 +371,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a specified ManagedNotificationConfiguration.

    " + "documentation":"

    Returns a specified ManagedNotificationConfiguration.

    ", + "readonly":true }, "GetManagedNotificationEvent":{ "name":"GetManagedNotificationEvent", @@ -387,7 +390,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a specified ManagedNotificationEvent.

    " + "documentation":"

    Returns a specified ManagedNotificationEvent.

    ", + "readonly":true }, "GetNotificationConfiguration":{ "name":"GetNotificationConfiguration", @@ -405,7 +409,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a specified NotificationConfiguration.

    " + "documentation":"

    Returns a specified NotificationConfiguration.

    ", + "readonly":true }, "GetNotificationEvent":{ "name":"GetNotificationEvent", @@ -423,7 +428,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a specified NotificationEvent.

    User Notifications stores notifications in the individual Regions you register as notification hubs and the Region of the source event rule. GetNotificationEvent only returns notifications stored in the same Region in which the action is called. User Notifications doesn't backfill notifications to new Regions selected as notification hubs. For this reason, we recommend that you make calls in your oldest registered notification hub. For more information, see Notification hubs in the Amazon Web Services User Notifications User Guide.

    " + "documentation":"

    Returns a specified NotificationEvent.

    User Notifications stores notifications in the individual Regions you register as notification hubs and the Region of the source event rule. GetNotificationEvent only returns notifications stored in the same Region in which the action is called. User Notifications doesn't backfill notifications to new Regions selected as notification hubs. For this reason, we recommend that you make calls in your oldest registered notification hub. For more information, see Notification hubs in the Amazon Web Services User Notifications User Guide.

    ", + "readonly":true }, "GetNotificationsAccessForOrganization":{ "name":"GetNotificationsAccessForOrganization", @@ -440,7 +446,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the AccessStatus of Service Trust Enablement for User Notifications and Amazon Web Services Organizations.

    " + "documentation":"

    Returns the AccessStatus of Service Trust Enablement for User Notifications and Amazon Web Services Organizations.

    ", + "readonly":true }, "ListChannels":{ "name":"ListChannels", @@ -458,7 +465,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of Channels for a NotificationConfiguration.

    " + "documentation":"

    Returns a list of Channels for a NotificationConfiguration.

    ", + "readonly":true }, "ListEventRules":{ "name":"ListEventRules", @@ -476,7 +484,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of EventRules according to specified filters, in reverse chronological order (newest first).

    " + "documentation":"

    Returns a list of EventRules according to specified filters, in reverse chronological order (newest first).

    ", + "readonly":true }, "ListManagedNotificationChannelAssociations":{ "name":"ListManagedNotificationChannelAssociations", @@ -494,7 +503,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of Account contacts and Channels associated with a ManagedNotificationConfiguration, in paginated format.

    " + "documentation":"

    Returns a list of Account contacts and Channels associated with a ManagedNotificationConfiguration, in paginated format.

    ", + "readonly":true }, "ListManagedNotificationChildEvents":{ "name":"ListManagedNotificationChildEvents", @@ -511,7 +521,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of ManagedNotificationChildEvents for a specified aggregate ManagedNotificationEvent, ordered by creation time in reverse chronological order (newest first).

    " + "documentation":"

    Returns a list of ManagedNotificationChildEvents for a specified aggregate ManagedNotificationEvent, ordered by creation time in reverse chronological order (newest first).

    ", + "readonly":true }, "ListManagedNotificationConfigurations":{ "name":"ListManagedNotificationConfigurations", @@ -528,7 +539,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of Managed Notification Configurations according to specified filters, ordered by creation time in reverse chronological order (newest first).

    " + "documentation":"

    Returns a list of Managed Notification Configurations according to specified filters, ordered by creation time in reverse chronological order (newest first).

    ", + "readonly":true }, "ListManagedNotificationEvents":{ "name":"ListManagedNotificationEvents", @@ -545,7 +557,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of Managed Notification Events according to specified filters, ordered by creation time in reverse chronological order (newest first).

    " + "documentation":"

    Returns a list of Managed Notification Events according to specified filters, ordered by creation time in reverse chronological order (newest first).

    ", + "readonly":true }, "ListMemberAccounts":{ "name":"ListMemberAccounts", @@ -563,7 +576,8 @@ {"shape":"ThrottlingException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Returns a list of member accounts associated with a notification configuration.

    " + "documentation":"

    Returns a list of member accounts associated with a notification configuration.

    ", + "readonly":true }, "ListNotificationConfigurations":{ "name":"ListNotificationConfigurations", @@ -580,7 +594,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of abbreviated NotificationConfigurations according to specified filters, in reverse chronological order (newest first).

    " + "documentation":"

    Returns a list of abbreviated NotificationConfigurations according to specified filters, in reverse chronological order (newest first).

    ", + "readonly":true }, "ListNotificationEvents":{ "name":"ListNotificationEvents", @@ -597,7 +612,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of NotificationEvents according to specified filters, in reverse chronological order (newest first).

    User Notifications stores notifications in the individual Regions you register as notification hubs and the Region of the source event rule. ListNotificationEvents only returns notifications stored in the same Region in which the action is called. User Notifications doesn't backfill notifications to new Regions selected as notification hubs. For this reason, we recommend that you make calls in your oldest registered notification hub. For more information, see Notification hubs in the Amazon Web Services User Notifications User Guide.

    " + "documentation":"

    Returns a list of NotificationEvents according to specified filters, in reverse chronological order (newest first).

    User Notifications stores notifications in the individual Regions you register as notification hubs and the Region of the source event rule. ListNotificationEvents only returns notifications stored in the same Region in which the action is called. User Notifications doesn't backfill notifications to new Regions selected as notification hubs. For this reason, we recommend that you make calls in your oldest registered notification hub. For more information, see Notification hubs in the Amazon Web Services User Notifications User Guide.

    ", + "readonly":true }, "ListNotificationHubs":{ "name":"ListNotificationHubs", @@ -614,7 +630,8 @@ {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of NotificationHubs.

    " + "documentation":"

    Returns a list of NotificationHubs.

    ", + "readonly":true }, "ListOrganizationalUnits":{ "name":"ListOrganizationalUnits", @@ -632,7 +649,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of organizational units associated with a notification configuration.

    " + "documentation":"

    Returns a list of organizational units associated with a notification configuration.

    ", + "readonly":true }, "ListTagsForResource":{ "name":"ListTagsForResource", @@ -650,7 +668,8 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns a list of tags for a specified Amazon Resource Name (ARN).

    For more information, see Tagging your Amazon Web Services resources in the Tagging Amazon Web Services Resources User Guide.

    This is only supported for NotificationConfigurations.

    " + "documentation":"

    Returns a list of tags for a specified Amazon Resource Name (ARN).

    For more information, see Tagging your Amazon Web Services resources in the Tagging Amazon Web Services Resources User Guide.

    This is only supported for NotificationConfigurations.

    ", + "readonly":true }, "RegisterNotificationHub":{ "name":"RegisterNotificationHub", @@ -669,7 +688,7 @@ {"shape":"ConflictException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Registers a NotificationConfiguration in the specified Region.

    There is a maximum of one NotificationConfiguration per Region. You can have a maximum of 3 NotificationHub resources at a time.

    ", + "documentation":"

    Registers a NotificationHub in the specified Region.

    There is a maximum of one NotificationHub per Region. You can have a maximum of 3 NotificationHub resources at a time.

    ", "idempotent":true }, "TagResource":{ @@ -730,6 +749,26 @@ "documentation":"

    Updates an existing EventRule.

    ", "idempotent":true }, + "UpdateManagedNotificationChannelAssociation":{ + "name":"UpdateManagedNotificationChannelAssociation", + "http":{ + "method":"PUT", + "requestUri":"/channels/update-managed-notification-channel-association", + "responseCode":200 + }, + "input":{"shape":"UpdateManagedNotificationChannelAssociationRequest"}, + "output":{"shape":"UpdateManagedNotificationChannelAssociationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the isSensitiveEventsSubscribed property of a particular ManagedNotification channel association.

    ", + "idempotent":true + }, "UpdateNotificationConfiguration":{ "name":"UpdateNotificationConfiguration", "http":{ @@ -918,6 +957,10 @@ "managedNotificationConfigurationArn":{ "shape":"ManagedNotificationConfigurationOsArn", "documentation":"

    The Amazon Resource Name (ARN) of the ManagedNotificationConfiguration to associate with the Account Contact.

    " + }, + "isSensitiveEventsSubscribed":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this contact is subscribed to sensitive events. The notifications:SubscribeSensitiveEvents permission controls access to sensitive events. Defaults to false.

    " } } }, @@ -941,6 +984,10 @@ "managedNotificationConfigurationArn":{ "shape":"ManagedNotificationConfigurationOsArn", "documentation":"

    The Amazon Resource Name (ARN) of the ManagedNotificationConfiguration to associate with the additional Channel.

    " + }, + "isSensitiveEventsSubscribed":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this channel is subscribed to sensitive events. The notifications:SubscribeSensitiveEvents permission controls access to sensitive events. Defaults to false.

    " } } }, @@ -971,13 +1018,22 @@ "type":"structure", "members":{} }, + "AttachmentContentType":{ + "type":"string", + "pattern":"[a-zA-Z0-9]+/[a-zA-Z0-9][a-zA-Z0-9!#$&\\-^_.+]*" + }, + "AttachmentDisplayName":{ + "type":"string", + "max":255, + "min":1 + }, "Boolean":{ "type":"boolean", "box":true }, "ChannelArn":{ "type":"string", - "pattern":"arn:aws:(chatbot|consoleapp|notifications-contacts):[a-zA-Z0-9-]*:[0-9]{12}:[a-zA-Z0-9-_.@]+/[a-zA-Z0-9/_.@:-]+" + "pattern":"arn:[a-z-]{3,10}:(chatbot|consoleapp|notifications-contacts):[a-zA-Z0-9-]*:[0-9]{12}:[a-zA-Z0-9-_.@]+/[a-zA-Z0-9/_.@:-]+" }, "ChannelAssociationOverrideOption":{ "type":"string", @@ -988,7 +1044,7 @@ }, "ChannelIdentifier":{ "type":"string", - "pattern":"ACCOUNT_PRIMARY|ACCOUNT_ALTERNATE_BILLING|ACCOUNT_ALTERNATE_OPERATIONS|ACCOUNT_ALTERNATE_SECURITY|arn:aws:(chatbot|consoleapp|notifications-contacts):[a-zA-Z0-9-]*:[0-9]{12}:[a-zA-Z0-9-_.@]+/[a-zA-Z0-9/_.@:-]+" + "pattern":"(ACCOUNT_PRIMARY|ACCOUNT_ALTERNATE_BILLING|ACCOUNT_ALTERNATE_OPERATIONS|ACCOUNT_ALTERNATE_SECURITY|arn:[a-z-]{3,10}:(chatbot|consoleapp|notifications-contacts):[a-zA-Z0-9-]*:[0-9]{12}:[a-zA-Z0-9-_.@]+/[a-zA-Z0-9/_.@:-]+)" }, "ChannelType":{ "type":"string", @@ -1160,7 +1216,7 @@ "members":{ "notificationHubRegion":{ "shape":"Region", - "documentation":"

    The NotificationConfiguration Region.

    ", + "documentation":"

    The NotificationHub Region.

    ", "location":"uri", "locationName":"notificationHubRegion" } @@ -1175,11 +1231,11 @@ "members":{ "notificationHubRegion":{ "shape":"Region", - "documentation":"

    The NotificationConfiguration Region.

    " + "documentation":"

    The NotificationHub Region.

    " }, "statusSummary":{ "shape":"NotificationHubStatusSummary", - "documentation":"

    NotificationConfiguration status information.

    " + "documentation":"

    NotificationHub status information.

    " } } }, @@ -1318,7 +1374,7 @@ "ErrorMessage":{"type":"string"}, "EventRuleArn":{ "type":"string", - "pattern":"arn:aws:notifications::[0-9]{12}:configuration/[a-z0-9]{27}/rule/[a-z0-9]{27}" + "pattern":"arn:[a-z-]{3,10}:notifications::[0-9]{12}:configuration/[a-z0-9]{27}/rule/[a-z0-9]{27}" }, "EventRuleEventPattern":{ "type":"string", @@ -2052,6 +2108,12 @@ "documentation":"

    The Amazon Web Services account ID associated with the Managed Notification Events.

    ", "location":"querystring", "locationName":"relatedAccount" + }, + "includeSensitiveEvents":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to include sensitive events in the result. By default, only non-sensitive events are returned. The notifications:AccessSensitiveEvents permission controls access to sensitive events.

    ", + "location":"querystring", + "locationName":"includeSensitiveEvents" } } }, @@ -2417,6 +2479,10 @@ "overrideOption":{ "shape":"ChannelAssociationOverrideOption", "documentation":"

    Controls whether users can modify channel associations for a notification configuration.

    • Values:

      • ENABLED

        • Users can associate or disassociate channels with the notification configuration.

      • DISABLED

        • Users cannot associate or disassociate channels with the notification configuration.

    " + }, + "isSensitiveEventsSubscribed":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this channel association is subscribed to sensitive events. Defaults to false for associations created without the flag.

    " } }, "documentation":"

    Provides a summary of channel associations for a managed notification configuration.

    " @@ -2425,6 +2491,10 @@ "type":"list", "member":{"shape":"ManagedNotificationChannelAssociationSummary"} }, + "ManagedNotificationChannelIdentifier":{ + "type":"string", + "pattern":"(ACCOUNT_PRIMARY|ACCOUNT_ALTERNATE_BILLING|ACCOUNT_ALTERNATE_OPERATIONS|ACCOUNT_ALTERNATE_SECURITY|arn:[a-z-]{3,10}:(chatbot|consoleapp|notifications-contacts):[a-zA-Z0-9-]*:[0-9]{12}:[a-zA-Z0-9-_.@]+/[a-zA-Z0-9/_.@:-]+)" + }, "ManagedNotificationChildEvent":{ "type":"structure", "required":[ @@ -2486,11 +2556,11 @@ "documentation":"

    Provides detailed information about the dimensions used for event summarization and aggregation.

    " } }, - "documentation":"

    A ManagedNotificationChildEvent is a notification-focused representation of an event. They contain semantic information used to create aggregated or non-aggregated end-user notifications.

    " + "documentation":"

    A notification-focused representation of an event. They contain semantic information used to create aggregated or non-aggregated end-user notifications.

    " }, "ManagedNotificationChildEventArn":{ "type":"string", - "pattern":"arn:[-.a-z0-9]{1,63}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}/event/[a-z0-9]{27}/child-event/[a-z0-9]{27}" + "pattern":"arn:[a-z-]{3,10}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}/event/[a-z0-9]{27}/child-event/[a-z0-9]{27}" }, "ManagedNotificationChildEventOverview":{ "type":"structure", @@ -2587,7 +2657,7 @@ }, "ManagedNotificationConfigurationOsArn":{ "type":"string", - "pattern":"arn:[-.a-z0-9]{1,63}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}" + "pattern":"arn:[a-z-]{3,10}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}" }, "ManagedNotificationConfigurationStructure":{ "type":"structure", @@ -2671,13 +2741,17 @@ "organizationalUnitId":{ "shape":"OrganizationalUnitId", "documentation":"

    The Organizational Unit Id that an Amazon Web Services account belongs to.

    " + }, + "attachments":{ + "shape":"NotificationEventAttachmentList", + "documentation":"

    A list of files attached to the notification event.

    " } }, "documentation":"

    A notification-focused representation of an event. They contain semantic information used by AccountContacts or Additional Channels to create end-user notifications.

    " }, "ManagedNotificationEventArn":{ "type":"string", - "pattern":"arn:[-.a-z0-9]{1,63}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}/event/[a-z0-9]{27}" + "pattern":"arn:[a-z-]{3,10}:notifications::[0-9]{12}:managed-notification-configuration/category/[a-zA-Z0-9\\-]{3,64}/sub-category/[a-zA-Z0-9\\-]{3,64}/event/[a-z0-9]{27}" }, "ManagedNotificationEventOverview":{ "type":"structure", @@ -2761,7 +2835,7 @@ }, "ManagedRuleArn":{ "type":"string", - "pattern":"arn:aws:events:[a-z-\\d]{2,25}:\\d{12}:rule\\/[a-zA-Z-\\d]{1,1024}" + "pattern":"arn:[a-z-]{3,10}:events:[a-z-\\d]{2,25}:\\d{12}:rule\\/[a-zA-Z-\\d]{1,1024}" }, "ManagedRuleArns":{ "type":"list", @@ -2793,7 +2867,7 @@ "type":"string", "max":32, "min":0, - "pattern":"([a-z]{1,2})-([a-z]{1,15}-)+([0-9])" + "pattern":"([a-z]{1,4})-([a-z]{1,15}-)+([0-9])" }, "ManagedSourceEventMetadataSummaryEventTypeString":{ "type":"string", @@ -2903,6 +2977,10 @@ "shape":"TextPartReference", "documentation":"

    A complete summary with all possible relevant information.

    " }, + "markupDescription":{ + "shape":"TextPartReference", + "documentation":"

    A rich description in Portable Text format, which you can convert to markup formats such as HTML, Markdown, or plain text. Channels that don't support rich rendering ignore this field and use the plain text components instead.

    " + }, "dimensions":{ "shape":"Dimensions", "documentation":"

    A list of properties in key-value pairs. Pairs are shown in order of importance from most important to least important. Channels may limit the number of dimensions shown to the notification viewer.

    Included dimensions, keys, and values are subject to change.

    " @@ -2934,7 +3012,7 @@ }, "NotificationConfigurationArn":{ "type":"string", - "pattern":"arn:aws:notifications::[0-9]{12}:configuration/[a-z0-9]{27}" + "pattern":"arn:[a-z-]{3,10}:notifications::[0-9]{12}:configuration/[a-z0-9]{27}" }, "NotificationConfigurationDescription":{ "type":"string", @@ -3087,7 +3165,33 @@ }, "NotificationEventArn":{ "type":"string", - "pattern":"arn:[-.a-z0-9]{1,63}:notifications:[-.a-z0-9]{1,63}:[0-9]{12}:configuration/[a-z0-9]{27}/event/[a-z0-9]{27}" + "pattern":"arn:[a-z-]{3,10}:notifications:[-.a-z0-9]{1,63}:[0-9]{12}:configuration/[a-z0-9]{27}/event/[a-z0-9]{27}" + }, + "NotificationEventAttachment":{ + "type":"structure", + "required":[ + "displayName", + "contentType" + ], + "members":{ + "displayName":{ + "shape":"AttachmentDisplayName", + "documentation":"

    The name of the attachment that recipients see.

    " + }, + "attachmentDownloadUrl":{ + "shape":"SensitiveUrl", + "documentation":"

    A temporary URL for downloading the attachment. The URL expires shortly after it's issued.

    " + }, + "contentType":{ + "shape":"AttachmentContentType", + "documentation":"

    The MIME content type of the attachment, for example application/pdf.

    " + } + }, + "documentation":"

    A file attached to a notification event.

    " + }, + "NotificationEventAttachmentList":{ + "type":"list", + "member":{"shape":"NotificationEventAttachment"} }, "NotificationEventId":{ "type":"string", @@ -3271,7 +3375,7 @@ "type":"string", "max":25, "min":2, - "pattern":"([a-z]{1,2})-([a-z]{1,15}-)+([0-9])" + "pattern":"([a-z]{1,4})-([a-z]{1,15}-)+([0-9])" }, "Regions":{ "type":"list", @@ -3302,7 +3406,7 @@ }, "statusSummary":{ "shape":"NotificationHubStatusSummary", - "documentation":"

    Provides additional information about the current NotificationConfiguration status information.

    " + "documentation":"

    Provides additional information about the current NotificationHub status information.

    " }, "creationTime":{ "shape":"CreationTime", @@ -3377,6 +3481,13 @@ "type":"string", "enum":["v1.0"] }, + "SensitiveUrl":{ + "type":"string", + "max":4096, + "min":0, + "pattern":"(https?):\\/\\/.*", + "sensitive":true + }, "ServiceCode":{"type":"string"}, "ServiceQuotaExceededException":{ "type":"structure", @@ -3467,7 +3578,7 @@ "type":"string", "max":32, "min":0, - "pattern":"([a-z]{1,2})-([a-z]{1,15}-)+([0-9])" + "pattern":"([a-z]{1,4})-([a-z]{1,15}-)+([0-9])" }, "SourceEventMetadataEventTypeString":{ "type":"string", @@ -3647,7 +3758,8 @@ "enum":[ "LOCALIZED_TEXT", "PLAIN_TEXT", - "URL" + "URL", + "PORTABLE_TEXT" ] }, "TextPartValue":{ @@ -3675,7 +3787,7 @@ }, "TextPartValueDisplayTextString":{ "type":"string", - "max":1024, + "max":12000, "min":1 }, "TextParts":{ @@ -3778,6 +3890,31 @@ } } }, + "UpdateManagedNotificationChannelAssociationRequest":{ + "type":"structure", + "required":[ + "managedNotificationConfigurationArn", + "channelIdentifier" + ], + "members":{ + "managedNotificationConfigurationArn":{ + "shape":"ManagedNotificationConfigurationOsArn", + "documentation":"

    The Amazon Resource Name (ARN) of the ManagedNotificationConfiguration whose Channel association property you want to update.

    " + }, + "channelIdentifier":{ + "shape":"ManagedNotificationChannelIdentifier", + "documentation":"

    The identifier of the channel association to update. You can specify one of the following:

    • An Account contact identifier.

    • A Channel ARN.

    " + }, + "isSensitiveEventsSubscribed":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the association is subscribed to sensitive events. The notifications:SubscribeSensitiveEvents permission controls access to sensitive events.

    " + } + } + }, + "UpdateManagedNotificationChannelAssociationResponse":{ + "type":"structure", + "members":{} + }, "UpdateNotificationConfigurationRequest":{ "type":"structure", "required":["arn"], @@ -3815,8 +3952,7 @@ "Url":{ "type":"string", "max":2000, - "min":0, - "pattern":"(https?)://.*" + "min":0 }, "ValidationException":{ "type":"structure", diff --git a/services/notificationscontacts/pom.xml b/services/notificationscontacts/pom.xml index e9578bcec596..b13922562eb2 100644 --- a/services/notificationscontacts/pom.xml +++ b/services/notificationscontacts/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT notificationscontacts AWS Java SDK :: Services :: Notifications Contacts diff --git a/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2028930ba417 --- /dev/null +++ b/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,118 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://notifications-contacts-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://notifications-contacts.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9943513378d8..000000000000 --- a/services/notificationscontacts/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://notifications-contacts-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://notifications-contacts.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/novaact/pom.xml b/services/novaact/pom.xml index 050628815b8c..183bbd98ca41 100644 --- a/services/novaact/pom.xml +++ b/services/novaact/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT novaact AWS Java SDK :: Services :: Nova Act diff --git a/services/novaact/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/novaact/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ca713940d803 --- /dev/null +++ b/services/novaact/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://nova-act-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://nova-act-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://nova-act.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://nova-act.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/novaact/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/novaact/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 62c818fe9e3b..000000000000 --- a/services/novaact/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,344 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://nova-act-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://nova-act-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://nova-act.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://nova-act.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/oam/pom.xml b/services/oam/pom.xml index 6755b3b8a8ff..83a9577b812e 100644 --- a/services/oam/pom.xml +++ b/services/oam/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT oam AWS Java SDK :: Services :: OAM diff --git a/services/oam/src/main/resources/codegen-resources/customization.config b/services/oam/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/oam/src/main/resources/codegen-resources/customization.config +++ b/services/oam/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/oam/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/oam/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6ccc6c11a30f --- /dev/null +++ b/services/oam/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oam-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oam-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oam.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oam.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/oam/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/oam/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c3a8298ae9ce..000000000000 --- a/services/oam/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oam-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oam-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oam.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oam.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/observabilityadmin/pom.xml b/services/observabilityadmin/pom.xml index bdc7011f1047..9cf02ea5cc11 100644 --- a/services/observabilityadmin/pom.xml +++ b/services/observabilityadmin/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT observabilityadmin AWS Java SDK :: Services :: Observability Admin diff --git a/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4bdafc762f19 --- /dev/null +++ b/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://observabilityadmin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://observabilityadmin-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://observabilityadmin.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://observabilityadmin.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d44d4fc3d5cb..000000000000 --- a/services/observabilityadmin/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://observabilityadmin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://observabilityadmin-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://observabilityadmin.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://observabilityadmin.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/observabilityadmin/src/main/resources/codegen-resources/paginators-1.json b/services/observabilityadmin/src/main/resources/codegen-resources/paginators-1.json index d1654bc521c8..1381264f0771 100644 --- a/services/observabilityadmin/src/main/resources/codegen-resources/paginators-1.json +++ b/services/observabilityadmin/src/main/resources/codegen-resources/paginators-1.json @@ -6,6 +6,12 @@ "limit_key": "MaxResults", "result_key": "CentralizationRuleSummaries" }, + "ListDatasetIntegrations": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "DatasetIntegrationSummaries" + }, "ListResourceTelemetry": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/observabilityadmin/src/main/resources/codegen-resources/service-2.json b/services/observabilityadmin/src/main/resources/codegen-resources/service-2.json index 11a2699368b9..2ccdcdaefae5 100644 --- a/services/observabilityadmin/src/main/resources/codegen-resources/service-2.json +++ b/services/observabilityadmin/src/main/resources/codegen-resources/service-2.json @@ -32,6 +32,24 @@ ], "documentation":"

    Creates a centralization rule that applies across an Amazon Web Services Organization. This operation can only be called by the organization's management account or a delegated administrator account.

    " }, + "CreateDatasetIntegration":{ + "name":"CreateDatasetIntegration", + "http":{ + "method":"POST", + "requestUri":"/CreateDatasetIntegration", + "responseCode":201 + }, + "input":{"shape":"CreateDatasetIntegrationInput"}, + "output":{"shape":"CreateDatasetIntegrationOutput"}, + "errors":[ + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"} + ], + "documentation":"

    Creates a dataset integration for the caller's account in the current region and returns its ARN.

    To use this operation, you must have permission to access the dataset integration resources through the IAM role specified in the RoleArn parameter.

    If a dataset integration already exists for the account, this operation fails with a ConflictException.

    " + }, "CreateS3TableIntegration":{ "name":"CreateS3TableIntegration", "http":{ @@ -125,6 +143,24 @@ ], "documentation":"

    Deletes an organization-wide centralization rule. This operation can only be called by the organization's management account or a delegated administrator account.

    " }, + "DeleteDatasetIntegration":{ + "name":"DeleteDatasetIntegration", + "http":{ + "method":"POST", + "requestUri":"/DeleteDatasetIntegration", + "responseCode":204 + }, + "input":{"shape":"DeleteDatasetIntegrationInput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"} + ], + "documentation":"

    Deletes a dataset integration for the caller's account in the current region. This operation is idempotent; if you submit the same delete more than once, each call succeeds.

    ", + "idempotent":true + }, "DeleteS3TableIntegration":{ "name":"DeleteS3TableIntegration", "http":{ @@ -216,6 +252,25 @@ "documentation":"

    Retrieves the details of a specific organization centralization rule. This operation can only be called by the organization's management account or a delegated administrator account.

    ", "readonly":true }, + "GetDatasetIntegration":{ + "name":"GetDatasetIntegration", + "http":{ + "method":"POST", + "requestUri":"/GetDatasetIntegration", + "responseCode":200 + }, + "input":{"shape":"GetDatasetIntegrationInput"}, + "output":{"shape":"GetDatasetIntegrationOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"} + ], + "documentation":"

    Returns the dataset integration for the caller's account in the current region.

    ", + "readonly":true + }, "GetS3TableIntegration":{ "name":"GetS3TableIntegration", "http":{ @@ -360,6 +415,24 @@ "documentation":"

    Lists all centralization rules in your organization. This operation can only be called by the organization's management account or a delegated administrator account.

    ", "readonly":true }, + "ListDatasetIntegrations":{ + "name":"ListDatasetIntegrations", + "http":{ + "method":"POST", + "requestUri":"/ListDatasetIntegrations", + "responseCode":200 + }, + "input":{"shape":"ListDatasetIntegrationsInput"}, + "output":{"shape":"ListDatasetIntegrationsOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"} + ], + "documentation":"

    Returns the dataset integrations in your account.

    ", + "readonly":true + }, "ListResourceTelemetry":{ "name":"ListResourceTelemetry", "http":{ @@ -652,6 +725,25 @@ ], "documentation":"

    Updates an existing centralization rule that applies across an Amazon Web Services Organization. This operation can only be called by the organization's management account or a delegated administrator account.

    " }, + "UpdateDatasetIntegration":{ + "name":"UpdateDatasetIntegration", + "http":{ + "method":"POST", + "requestUri":"/UpdateDatasetIntegration", + "responseCode":200 + }, + "input":{"shape":"UpdateDatasetIntegrationInput"}, + "output":{"shape":"UpdateDatasetIntegrationOutput"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"TooManyRequestsException"} + ], + "documentation":"

    Updates a dataset integration for the caller's account in the current region. This operation is idempotent; if you submit the same update more than once, each call succeeds.

    ", + "idempotent":true + }, "UpdateTelemetryPipeline":{ "name":"UpdateTelemetryPipeline", "http":{ @@ -916,6 +1008,10 @@ "SourceMetricsConfiguration":{ "shape":"SourceMetricsConfiguration", "documentation":"

    Metric specific configuration for centralization source metrics.

    " + }, + "SourceContextGraphConfiguration":{ + "shape":"SourceContextGraphConfiguration", + "documentation":"

    Configuration that enables centralization of the context graph for the selected sources. Including this configuration in a rule's source opts the rule into centralizing the context graph for the selected sources.

    " } }, "documentation":"

    Configuration specifying the source of telemetry data to be centralized.

    " @@ -959,6 +1055,18 @@ "shape":"CentralizationFailureReason", "documentation":"

    The reason why an organization centralization rule is marked UNHEALTHY.

    " }, + "TagPropagationStatus":{ + "shape":"TagPropagationStatus", + "documentation":"

    The health status of tag propagation for this rule. This status is independent of the overall RuleHealth for log delivery. Returns Healthy when the most recent tag-propagation attempt succeeded, or Unhealthy when the most recent attempt failed.

    " + }, + "TagPropagationFailureReason":{ + "shape":"TagPropagationFailureReason", + "documentation":"

    The reason tag propagation is unhealthy for this rule. Only present when TagPropagationStatus is Unhealthy.

    " + }, + "ContextGraphStatus":{ + "shape":"ContextGraphStatus", + "documentation":"

    The status of context graph centralization for this rule. Returns Provisioning while the context graph is being set up, Healthy once it is active, or Unhealthy if provisioning failed. This status is independent of the overall RuleHealth for log delivery.

    " + }, "DestinationAccountId":{ "shape":"String", "documentation":"

    The primary destination account of the organization centralization rule.

    " @@ -1047,6 +1155,15 @@ }, "exception":true }, + "ContextGraphStatus":{ + "type":"string", + "documentation":"

    The status of context graph centralization for a centralization rule. This status is independent of the overall RuleHealth for log delivery. Returns Provisioning while the context graph is being set up, Healthy once it is active, or Unhealthy if provisioning failed.

    ", + "enum":[ + "Healthy", + "Unhealthy", + "Provisioning" + ] + }, "CreateCentralizationRuleForOrganizationInput":{ "type":"structure", "required":[ @@ -1077,6 +1194,47 @@ } } }, + "CreateDatasetIntegrationInput":{ + "type":"structure", + "required":["RoleArn"], + "members":{ + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role that grants Amazon CloudWatch permission to access the resources needed for the dataset integration.

    " + }, + "Tags":{ + "shape":"TagMapInput", + "documentation":"

    The key-value pairs to associate with the dataset integration resource for categorization and management purposes.

    " + } + } + }, + "CreateDatasetIntegrationOutput":{ + "type":"structure", + "required":[ + "Arn", + "RoleArn", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the created dataset integration.

    " + }, + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role associated with the dataset integration.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was last updated.

    " + } + } + }, "CreateS3TableIntegrationInput":{ "type":"structure", "required":[ @@ -1220,6 +1378,33 @@ "type":"list", "member":{"shape":"DataSource"} }, + "DatasetIntegrationSummaries":{ + "type":"list", + "member":{"shape":"DatasetIntegrationSummary"} + }, + "DatasetIntegrationSummary":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the dataset integration.

    " + }, + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role associated with the dataset integration.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was last updated.

    " + } + }, + "documentation":"

    Contains summary information about a dataset integration, including its ARN, associated IAM role, and creation and update timestamps, as returned by ListDatasetIntegrations.

    " + }, "DeleteCentralizationRuleForOrganizationInput":{ "type":"structure", "required":["RuleIdentifier"], @@ -1230,6 +1415,16 @@ } } }, + "DeleteDatasetIntegrationInput":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the dataset integration to delete.

    " + } + } + }, "DeleteS3TableIntegrationInput":{ "type":"structure", "required":["Arn"], @@ -1288,6 +1483,10 @@ "LogGroupNameConfiguration":{ "shape":"LogGroupNameConfiguration", "documentation":"

    Configuration that specifies a naming pattern for destination log groups created during centralization. The pattern supports static text and dynamic variables that are replaced with source attributes when log groups are created.

    " + }, + "TagPropagationConfiguration":{ + "shape":"TagPropagationConfiguration", + "documentation":"

    Specifies the tag propagation configuration for this centralization rule. When present, LogGroupNameConfiguration must use a LogGroupNamePattern that contains ${source.logGroup}, ${source.accountId}, and ${source.region}.

    " } }, "documentation":"

    Configuration for centralization destination log groups, including encryption and backup settings.

    " @@ -1349,6 +1548,14 @@ "SKIP" ] }, + "EncryptionScope":{ + "type":"string", + "documentation":"

    Determines which newly created destination log groups are encrypted with the configured KMS key.

    ", + "enum":[ + "ENCRYPTED_SOURCE_ONLY", + "NEW_DESTINATION_LOG_GROUPS" + ] + }, "EncryptionStrategy":{ "type":"string", "enum":[ @@ -1473,12 +1680,55 @@ "shape":"CentralizationFailureReason", "documentation":"

    The reason why an organization centralization rule is marked UNHEALTHY.

    " }, + "TagPropagationStatus":{ + "shape":"TagPropagationStatus", + "documentation":"

    The health status of tag propagation for this rule. This status is independent of the overall RuleHealth for log delivery. Returns Healthy when the most recent tag-propagation attempt succeeded, or Unhealthy when the most recent attempt failed.

    " + }, + "TagPropagationFailureReason":{ + "shape":"TagPropagationFailureReason", + "documentation":"

    The reason tag propagation is unhealthy for this rule. Only present when TagPropagationStatus is Unhealthy.

    " + }, + "ContextGraphStatus":{ + "shape":"ContextGraphStatus", + "documentation":"

    The status of context graph centralization for this rule. Returns Provisioning while the context graph is being set up, Healthy once it is active, or Unhealthy if provisioning failed. This status is independent of the overall RuleHealth for log delivery.

    " + }, "CentralizationRule":{ "shape":"CentralizationRule", "documentation":"

    The configuration details for the organization centralization rule.

    " } } }, + "GetDatasetIntegrationInput":{ + "type":"structure", + "required":["Arn"], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the dataset integration to retrieve.

    " + } + } + }, + "GetDatasetIntegrationOutput":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the dataset integration.

    " + }, + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role associated with the dataset integration.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was last updated.

    " + } + } + }, "GetS3TableIntegrationInput":{ "type":"structure", "required":["Arn"], @@ -1686,6 +1936,12 @@ } } }, + "IamRoleArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws[a-zA-Z-]*:iam::\\d{12}:role/[\\w+=,.@/-]+" + }, "Integer":{ "type":"integer", "box":true @@ -1753,6 +2009,12 @@ "type":"boolean", "box":true }, + "KmsKeyArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws[a-zA-Z-]*:kms:[a-z0-9-]+:\\d{12}:key/(mrk-)?[a-f0-9-]+" + }, "LabelNameCondition":{ "type":"structure", "members":{ @@ -1814,6 +2076,39 @@ } } }, + "ListDatasetIntegrationsInput":{ + "type":"structure", + "members":{ + "MaxResults":{ + "shape":"ListDatasetIntegrationsMaxResults", + "documentation":"

    The maximum number of results to return in a single call.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results. A previous call generates this token.

    " + } + } + }, + "ListDatasetIntegrationsMaxResults":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListDatasetIntegrationsOutput":{ + "type":"structure", + "required":["DatasetIntegrationSummaries"], + "members":{ + "DatasetIntegrationSummaries":{ + "shape":"DatasetIntegrationSummaries", + "documentation":"

    The dataset integrations in your account.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    A token to resume pagination of results.

    " + } + } + }, "ListResourceTelemetryForOrganizationInput":{ "type":"structure", "members":{ @@ -1827,7 +2122,7 @@ }, "ResourceTypes":{ "shape":"ResourceTypes", - "documentation":"

    A list of resource types used to filter resources in the organization. If this parameter is provided, the resources will be returned in the same order used in the request.

    " + "documentation":"

    A list of resource types used to filter resources in the organization. If this parameter is provided, the service returns the resources in the same order as specified in the request. Currently supported resource types for discovery are:

    • AWS::EC2::Instance

    • AWS::EC2::VPC

    • AWS::Lambda::Function

    • AWS::EKS::Cluster

    • AWS::WAFv2::WebACL

    • AWS::ElasticLoadBalancingV2::LoadBalancer (Network Load Balancers only)

    " }, "TelemetryConfigurationState":{ "shape":"TelemetryConfigurationState", @@ -1875,7 +2170,7 @@ }, "ResourceTypes":{ "shape":"ResourceTypes", - "documentation":"

    A list of resource types used to filter resources supported by telemetry config. If this parameter is provided, the resources will be returned in the same order used in the request.

    " + "documentation":"

    A list of resource types used to filter resources supported by telemetry config. If this parameter is provided, the service returns the resources in the same order as specified in the request. Currently supported resource types for discovery are:

    • AWS::EC2::Instance

    • AWS::EC2::VPC

    • AWS::Lambda::Function

    • AWS::EKS::Cluster

    • AWS::WAFv2::WebACL

    • AWS::ElasticLoadBalancingV2::LoadBalancer (Network Load Balancers only)

    " }, "TelemetryConfigurationState":{ "shape":"TelemetryConfigurationState", @@ -2083,10 +2378,10 @@ "members":{ "LogTypes":{ "shape":"LogTypes", - "documentation":"

    The type of log that the source is sending.

    " + "documentation":"

    The types of logs to collect from the resource.

    " } }, - "documentation":"

    Configuration parameters for Amazon Bedrock AgentCore logging, including logType settings.

    " + "documentation":"

    The configuration parameters for log delivery, including logType settings. Applies to resource types that support configurable log delivery, such as Amazon Bedrock Knowledge Bases and Elastic Load Balancing Application Load Balancers.

    " }, "LogGroupNameConfiguration":{ "type":"structure", @@ -2108,13 +2403,17 @@ }, "LogType":{ "type":"string", + "documentation":"

    The following log types are supported for log delivery configuration:

    • APPLICATION_LOGS – Application-level logs.

    • USAGE_LOGS – Resource usage logs.

    • SECURITY_FINDING_LOGS – Security finding logs.

    • ACCESS_LOGS – Access logs (such as Elastic Load Balancing access logs).

    • CONNECTION_LOGS – Connection logs.

    • S3_SERVER_ACCESS_LOGS – Amazon S3 server access logs.

    ", "enum":[ "APPLICATION_LOGS", "USAGE_LOGS", "SECURITY_FINDING_LOGS", "ACCESS_LOGS", "CONNECTION_LOGS", - "S3_SERVER_ACCESS_LOGS" + "S3_SERVER_ACCESS_LOGS", + "ALB_ACCESS_LOGS", + "ALB_CONNECTION_LOGS", + "ALB_HEALTH_CHECK_LOGS" ] }, "LogTypes":{ @@ -2165,9 +2464,13 @@ "EncryptionConflictResolutionStrategy":{ "shape":"EncryptionConflictResolutionStrategy", "documentation":"

    Conflict resolution strategy for centralization if the encryption strategy is set to CUSTOMER_MANAGED and the destination log group is encrypted with an AWS_OWNED KMS Key. ALLOW lets centralization go through while SKIP prevents centralization into the destination log group.

    " + }, + "EncryptionScope":{ + "shape":"EncryptionScope", + "documentation":"

    Determines which newly created destination log groups are encrypted with the configured KmsKeyArn when EncryptionStrategy is CUSTOMER_MANAGED.

    If you set this to ENCRYPTED_SOURCE_ONLY (the default), only destination log groups whose source log group is encrypted with a customer managed KMS key use the configured KmsKeyArn. Destination log groups derived from Amazon Web Services owned encrypted source log groups remain Amazon Web Services owned encrypted.

    If you set this to NEW_DESTINATION_LOG_GROUPS, every new destination log group created by this rule uses the configured KmsKeyArn, regardless of the source log group's encryption posture.

    This field is not valid when EncryptionStrategy is AWS_OWNED.

    " } }, - "documentation":"

    Configuration for encrypting centralized log groups. This configuration is only applied to destination log groups for which the corresponding source log groups are encrypted using Customer Managed KMS Keys.

    " + "documentation":"

    Configuration for encrypting centralized destination log groups. By default, this configuration applies only to destination log groups whose corresponding source log groups are encrypted using customer managed KMS keys. To encrypt all destination log groups created by the rule, set EncryptionScope to NEW_DESTINATION_LOG_GROUPS.

    " }, "LogsFilterString":{ "type":"string", @@ -2385,7 +2688,8 @@ "AWS::SecurityHub::HubV2", "AWS::CloudWatch::OTelEnrichment", "AWS::MSK::Cluster", - "AWS::S3::Bucket" + "AWS::S3::Bucket", + "AWS::Bedrock::KnowledgeBase" ] }, "ResourceTypes":{ @@ -2496,6 +2800,11 @@ }, "documentation":"

    A list of source plugin types used in the pipeline configuration (such as cloudwatch_logs or s3). Currently supports a single source per pipeline, but is structured as a list to accommodate multiple pipelines in the configuration.

    " }, + "SourceContextGraphConfiguration":{ + "type":"structure", + "members":{}, + "documentation":"

    Configuration that enables centralization of the context graph for the selected sources. Including this configuration in a rule's source opts the rule into centralizing the context graph for the selected sources.

    " + }, "SourceFilterString":{ "type":"string", "max":2000, @@ -2599,6 +2908,15 @@ "type":"list", "member":{"shape":"String"} }, + "TagConflictResolutionStrategy":{ + "type":"string", + "documentation":"

    The strategy for resolving tag conflicts between source and destination log groups.

    • ADD_ONLY – Only adds new tags from the source without modifying existing destination tags.

    • UPDATE_SYNC – Adds new tags and updates existing tags from the source. Does not remove destination tags that are absent from the source.

    • IN_SYNC – Keeps destination tags fully synchronized with source tags, including removing destination tags that do not exist on the source.

    ", + "enum":[ + "IN_SYNC", + "ADD_ONLY", + "UPDATE_SYNC" + ] + }, "TagKey":{ "type":"string", "max":128, @@ -2623,6 +2941,37 @@ "key":{"shape":"String"}, "value":{"shape":"String"} }, + "TagPropagationConfiguration":{ + "type":"structure", + "required":["DestinationRoleArn"], + "members":{ + "DestinationRoleArn":{ + "shape":"IamRoleArn", + "documentation":"

    The ARN of a customer-managed IAM role in the destination account. The service assumes this role to propagate tags to destination log groups. You must have iam:PassRole permission on this role.

    " + }, + "TagConflictResolutionStrategy":{ + "shape":"TagConflictResolutionStrategy", + "documentation":"

    The strategy for resolving conflicts when a tag key exists on both the source and destination log groups. If not specified, defaults to UPDATE_SYNC.

    • ADD_ONLY – Only adds new tags from the source without modifying existing destination tags.

    • UPDATE_SYNC – Adds new tags and updates existing tags from the source. Does not remove destination tags that are absent from the source.

    • IN_SYNC – Keeps destination tags fully synchronized with source tags, including removing destination tags that do not exist on the source.

    " + } + }, + "documentation":"

    Specifies configuration for propagating resource tags from source log groups to centralized destination log groups. The service uses a customer-managed IAM role in the destination account to add, update, and remove tags on destination log groups.

    " + }, + "TagPropagationFailureReason":{ + "type":"string", + "documentation":"

    The reason tag propagation is unhealthy for a centralization rule.

    • RoleNotAssumable – The service cannot assume the destination role due to a trust policy or external ID misconfiguration.

    • RoleLacksPermissions – The role was assumed successfully but the tag API call was denied by the role's permissions policy.

    ", + "enum":[ + "RoleNotAssumable", + "RoleLacksPermissions" + ] + }, + "TagPropagationStatus":{ + "type":"string", + "documentation":"

    The health status of tag propagation for a centralization rule. This status is independent of the overall RuleHealth for log delivery.

    ", + "enum":[ + "Healthy", + "Unhealthy" + ] + }, "TagResourceInput":{ "type":"structure", "required":[ @@ -2719,11 +3068,15 @@ }, "LogDeliveryParameters":{ "shape":"LogDeliveryParameters", - "documentation":"

    Configuration parameters specific to Amazon Bedrock AgentCore logging when Amazon Bedrock AgentCore is the resource type.

    " + "documentation":"

    The configuration parameters for log delivery when the resource type supports configurable log types, such as Amazon Bedrock Knowledge Bases or Elastic Load Balancing Application Load Balancers.

    " }, "MskMonitoringParameters":{ "shape":"MskMonitoringParameters", "documentation":"

    Configuration parameters specific to MSK monitoring when MSK is the resource type.

    " + }, + "KmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The Amazon Resource Name (ARN) of the customer-managed Amazon Web Services KMS key used to encrypt the log groups created during telemetry rule remediation.

    " } }, "documentation":"

    Configuration specifying where and how telemetry data should be delivered for Amazon Web Services resources.

    " @@ -2866,7 +3219,7 @@ "members":{ "ResourceType":{ "shape":"ResourceType", - "documentation":"

    The type of Amazon Web Services resource to configure telemetry for (e.g., \"AWS::EC2::VPC\", \"AWS::EKS::Cluster\", \"AWS::WAFv2::WebACL\").

    " + "documentation":"

    The type of Amazon Web Services resource to configure telemetry for (for example, AWS::EC2::VPC, AWS::EKS::Cluster, AWS::ElasticLoadBalancingV2::LoadBalancer, or AWS::Bedrock::KnowledgeBase).

    " }, "TelemetryType":{ "shape":"TelemetryType", @@ -3005,6 +3358,7 @@ } } }, + "Timestamp":{"type":"timestamp"}, "TooManyRequestsException":{ "type":"structure", "members":{ @@ -3060,6 +3414,50 @@ } } }, + "UpdateDatasetIntegrationInput":{ + "type":"structure", + "required":[ + "Arn", + "RoleArn" + ], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the dataset integration to update.

    " + }, + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role to associate with the dataset integration.

    " + } + } + }, + "UpdateDatasetIntegrationOutput":{ + "type":"structure", + "required":[ + "Arn", + "RoleArn", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "Arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the updated dataset integration.

    " + }, + "RoleArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role associated with the updated dataset integration.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dataset integration was last updated.

    " + } + } + }, "UpdateTelemetryPipelineInput":{ "type":"structure", "required":[ diff --git a/services/odb/pom.xml b/services/odb/pom.xml index a39913ad9f0b..3f0ce58851f0 100644 --- a/services/odb/pom.xml +++ b/services/odb/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT odb AWS Java SDK :: Services :: Odb diff --git a/services/odb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/odb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d0bc5bda6fa4 --- /dev/null +++ b/services/odb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://odb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://odb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://odb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://odb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/odb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/odb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7cd2f5608768..000000000000 --- a/services/odb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://odb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://odb-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://odb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://odb.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/odb/src/main/resources/codegen-resources/paginators-1.json b/services/odb/src/main/resources/codegen-resources/paginators-1.json index e202efe5aace..8d8d17e4e988 100644 --- a/services/odb/src/main/resources/codegen-resources/paginators-1.json +++ b/services/odb/src/main/resources/codegen-resources/paginators-1.json @@ -78,6 +78,30 @@ "limit_key": "maxResults", "result_key": "dbSystemShapes" }, + "ListExadbVmClusters": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "exadbVmClusters" + }, + "ListExascaleDbStorageVaults": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "exascaleDbStorageVaults" + }, + "ListFlexComponents": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "flexComponents" + }, + "ListGiMinorVersions": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "giMinorVersions" + }, "ListGiVersions": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/odb/src/main/resources/codegen-resources/service-2.json b/services/odb/src/main/resources/codegen-resources/service-2.json index e330acfcc2ad..b9f01423a65e 100644 --- a/services/odb/src/main/resources/codegen-resources/service-2.json +++ b/services/odb/src/main/resources/codegen-resources/service-2.json @@ -51,6 +51,25 @@ ], "documentation":"

    Associates an Amazon Web Services Identity and Access Management (IAM) service role with a specified resource to enable Amazon Web Services service integration.

    " }, + "AssociateVirtualMachinesToExadbVmCluster":{ + "name":"AssociateVirtualMachinesToExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AssociateVirtualMachinesToExadbVmClusterInput"}, + "output":{"shape":"AssociateVirtualMachinesToExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Adds virtual machines to the specified Exascale VM cluster.

    " + }, "CreateAutonomousDatabase":{ "name":"CreateAutonomousDatabase", "http":{ @@ -168,6 +187,45 @@ "documentation":"

    Creates a VM cluster on the specified Exadata infrastructure.

    ", "idempotent":true }, + "CreateExadbVmCluster":{ + "name":"CreateExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateExadbVmClusterInput"}, + "output":{"shape":"CreateExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Creates an Exascale VM cluster.

    ", + "idempotent":true + }, + "CreateExascaleDbStorageVault":{ + "name":"CreateExascaleDbStorageVault", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateExascaleDbStorageVaultInput"}, + "output":{"shape":"CreateExascaleDbStorageVaultOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates an Exascale storage vault.

    ", + "idempotent":true + }, "CreateOdbNetwork":{ "name":"CreateOdbNetwork", "http":{ @@ -299,6 +357,44 @@ "documentation":"

    Deletes the specified VM cluster.

    ", "idempotent":true }, + "DeleteExadbVmCluster":{ + "name":"DeleteExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteExadbVmClusterInput"}, + "output":{"shape":"DeleteExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Deletes the specified Exascale VM cluster.

    ", + "idempotent":true + }, + "DeleteExascaleDbStorageVault":{ + "name":"DeleteExascaleDbStorageVault", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteExascaleDbStorageVaultInput"}, + "output":{"shape":"DeleteExascaleDbStorageVaultOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Deletes the specified Exascale storage vault.

    ", + "idempotent":true + }, "DeleteOdbNetwork":{ "name":"DeleteOdbNetwork", "http":{ @@ -353,6 +449,24 @@ ], "documentation":"

    Disassociates an Amazon Web Services Identity and Access Management (IAM) service role from a specified resource to disable Amazon Web Services service integration.

    " }, + "DisassociateVirtualMachinesFromExadbVmCluster":{ + "name":"DisassociateVirtualMachinesFromExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DisassociateVirtualMachinesFromExadbVmClusterInput"}, + "output":{"shape":"DisassociateVirtualMachinesFromExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Removes virtual machines from the specified Exascale VM cluster.

    " + }, "FailoverAutonomousDatabase":{ "name":"FailoverAutonomousDatabase", "http":{ @@ -533,6 +647,42 @@ "documentation":"

    Returns information about the specified database server.

    ", "readonly":true }, + "GetExadbVmCluster":{ + "name":"GetExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetExadbVmClusterInput"}, + "output":{"shape":"GetExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns information about the specified Exascale VM cluster.

    ", + "readonly":true + }, + "GetExascaleDbStorageVault":{ + "name":"GetExascaleDbStorageVault", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetExascaleDbStorageVaultInput"}, + "output":{"shape":"GetExascaleDbStorageVaultOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns information about the specified Exascale storage vault.

    ", + "readonly":true + }, "GetOciOnboardingStatus":{ "name":"GetOciOnboardingStatus", "http":{ @@ -832,6 +982,75 @@ "documentation":"

    Returns information about the shapes that are available for an Exadata infrastructure.

    ", "readonly":true }, + "ListExadbVmClusters":{ + "name":"ListExadbVmClusters", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListExadbVmClustersInput"}, + "output":{"shape":"ListExadbVmClustersOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns information about the Exascale VM clusters owned by your Amazon Web Services account.

    ", + "readonly":true + }, + "ListExascaleDbStorageVaults":{ + "name":"ListExascaleDbStorageVaults", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListExascaleDbStorageVaultsInput"}, + "output":{"shape":"ListExascaleDbStorageVaultsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns information about the Exascale storage vaults owned by your Amazon Web Services account.

    ", + "readonly":true + }, + "ListFlexComponents":{ + "name":"ListFlexComponents", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListFlexComponentsInput"}, + "output":{"shape":"ListFlexComponentsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns information about the flex components that are available for an Exadata infrastructure.

    ", + "readonly":true + }, + "ListGiMinorVersions":{ + "name":"ListGiMinorVersions", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListGiMinorVersionsInput"}, + "output":{"shape":"ListGiMinorVersionsOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns a list of the Oracle Grid Infrastructure (GI) minor versions for the specified major version.

    ", + "readonly":true + }, "ListGiVersions":{ "name":"ListGiVersions", "http":{ @@ -1158,6 +1377,42 @@ ], "documentation":"

    Updates the properties of an Exadata infrastructure resource.

    " }, + "UpdateExadbVmCluster":{ + "name":"UpdateExadbVmCluster", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateExadbVmClusterInput"}, + "output":{"shape":"UpdateExadbVmClusterOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Updates the specified Exascale VM cluster.

    " + }, + "UpdateExascaleDbStorageVault":{ + "name":"UpdateExascaleDbStorageVault", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateExascaleDbStorageVaultInput"}, + "output":{"shape":"UpdateExascaleDbStorageVaultOutput"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Updates the specified Exascale storage vault.

    " + }, "UpdateOdbNetwork":{ "name":"UpdateOdbNetwork", "http":{ @@ -1226,6 +1481,50 @@ "documentation":"

    You don't have sufficient access to perform this action. Make sure you have the required permissions and try again.

    ", "exception":true }, + "AdminPasswordSource":{ + "type":"string", + "documentation":"

    The source of the admin password for an Autonomous Database.

    ", + "enum":[ + "CUSTOMER_MANAGED_AWS_SECRET", + "API_REQUEST_PARAMETER" + ] + }, + "AdminPasswordSourceConfiguration":{ + "type":"structure", + "members":{ + "customerManagedAwsSecret":{ + "shape":"CustomerManagedAwsSecretConfiguration", + "documentation":"

    The configuration for a customer-managed Amazon Web Services Secrets Manager secret used as the admin password source.

    " + } + }, + "documentation":"

    The configuration of the admin password source. This is a union, so only one of the following members can be specified.

    ", + "union":true + }, + "AdminPasswordSourceConfigurationInput":{ + "type":"structure", + "members":{ + "customerManagedAwsSecret":{ + "shape":"CustomerManagedAwsSecretConfigurationInput", + "documentation":"

    The configuration for using a customer-managed Amazon Web Services Secrets Manager secret as the admin password source.

    " + } + }, + "documentation":"

    The input configuration for the admin password source. This is a union, so only one of the following members can be specified.

    ", + "union":true + }, + "AdminPasswordSourceSummary":{ + "type":"structure", + "members":{ + "adminPasswordSource":{ + "shape":"AdminPasswordSource", + "documentation":"

    The source of the admin password for the Autonomous Database.

    " + }, + "adminPasswordSourceConfiguration":{ + "shape":"AdminPasswordSourceConfiguration", + "documentation":"

    The configuration of the admin password source for the Autonomous Database.

    " + } + }, + "documentation":"

    A summary of the admin password source configuration for an Autonomous Database.

    " + }, "Arn":{ "type":"string", "max":2048, @@ -1263,6 +1562,50 @@ "type":"structure", "members":{} }, + "AssociateVirtualMachinesToExadbVmClusterInput":{ + "type":"structure", + "required":[ + "exadbVmClusterId", + "desiredNodeCount" + ], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster to add virtual machines to.

    " + }, + "desiredNodeCount":{ + "shape":"AssociateVirtualMachinesToExadbVmClusterInputDesiredNodeCountInteger", + "documentation":"

    The desired number of nodes in the Exascale VM cluster after the association.

    " + } + } + }, + "AssociateVirtualMachinesToExadbVmClusterInputDesiredNodeCountInteger":{ + "type":"integer", + "box":true, + "min":1 + }, + "AssociateVirtualMachinesToExadbVmClusterOutput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "exadbVmClusterId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + } + } + }, "AutonomousDatabase":{ "type":"structure", "members":{ @@ -1677,6 +2020,10 @@ "timeUndeleted":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time when the Autonomous Database was restored after deletion.

    " + }, + "adminPasswordSourceSummary":{ + "shape":"AdminPasswordSourceSummary", + "documentation":"

    The summary of the admin password source configuration for the Autonomous Database.

    " } }, "documentation":"

    Information about an Autonomous Database.

    " @@ -2409,6 +2756,10 @@ "timeUndeleted":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time when the Autonomous Database was restored after deletion.

    " + }, + "adminPasswordSourceSummary":{ + "shape":"AdminPasswordSourceSummary", + "documentation":"

    The summary of the admin password source configuration for the Autonomous Database.

    " } }, "documentation":"

    A summary of an Autonomous Database.

    " @@ -2445,6 +2796,10 @@ "timeRotated":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time when the Autonomous Database wallet was last rotated.

    " + }, + "passwordSourceSummary":{ + "shape":"WalletPasswordSourceSummary", + "documentation":"

    The summary of the password source configuration for the Autonomous Database wallet.

    " } }, "documentation":"

    The wallet details for an Autonomous Database.

    " @@ -3550,7 +3905,7 @@ }, "scanDnsName":{ "shape":"String", - "documentation":"

    The FQDN of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the VM cluster.

    " + "documentation":"

    The fully qualified domain name (FQDN) of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the VM cluster.

    " }, "scanDnsRecordId":{ "shape":"String", @@ -3727,7 +4082,7 @@ }, "scanDnsName":{ "shape":"String", - "documentation":"

    The FQDN of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the VM cluster.

    " + "documentation":"

    The fully qualified domain name (FQDN) of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the VM cluster.

    " }, "scanDnsRecordId":{ "shape":"String", @@ -4034,6 +4389,14 @@ "shape":"EncryptionKeyConfigurationInput", "documentation":"

    The configuration of the encryption key to use for the Autonomous Database.

    " }, + "adminPasswordSource":{ + "shape":"AdminPasswordSource", + "documentation":"

    The source of the admin password for the Autonomous Database. When set to CUSTOMER_MANAGED_AWS_SECRET, the admin password is retrieved from an Amazon Web Services Secrets Manager secret.

    " + }, + "adminPasswordSourceConfiguration":{ + "shape":"AdminPasswordSourceConfigurationInput", + "documentation":"

    The configuration of the admin password source for the Autonomous Database.

    " + }, "clientToken":{ "shape":"CreateAutonomousDatabaseInputClientTokenString", "documentation":"

    A client-provided token to ensure the idempotency of the request.

    ", @@ -4130,10 +4493,7 @@ }, "CreateAutonomousDatabaseWalletInput":{ "type":"structure", - "required":[ - "autonomousDatabaseId", - "password" - ], + "required":["autonomousDatabaseId"], "members":{ "autonomousDatabaseId":{ "shape":"ResourceIdOrArn", @@ -4147,6 +4507,14 @@ "shape":"CreateAutonomousDatabaseWalletInputPasswordString", "documentation":"

    The password to encrypt the keys inside the wallet.

    " }, + "passwordSource":{ + "shape":"WalletPasswordSource", + "documentation":"

    The source of the password for encrypting the wallet. When set to CUSTOMER_MANAGED_AWS_SECRET, the password is retrieved from an Amazon Web Services Secrets Manager secret.

    " + }, + "passwordSourceConfiguration":{ + "shape":"WalletPasswordSourceConfigurationInput", + "documentation":"

    The configuration of the password source for the Autonomous Database wallet.

    " + }, "clientToken":{ "shape":"CreateAutonomousDatabaseWalletInputClientTokenString", "documentation":"

    A client-provided token to ensure the idempotency of the request.

    ", @@ -4498,7 +4866,7 @@ }, "dbNodeStorageSizeInGBs":{ "shape":"Integer", - "documentation":"

    The amount of local node storage, in gigabytes (GBs), to allocate for the VM cluster.

    " + "documentation":"

    The amount of local node storage, in gigabytes (GB), to allocate for the VM cluster.

    " }, "dbServers":{ "shape":"StringList", @@ -4522,7 +4890,7 @@ }, "memorySizeInGBs":{ "shape":"Integer", - "documentation":"

    The amount of memory, in gigabytes (GBs), to allocate for the VM cluster.

    " + "documentation":"

    The amount of memory, in gigabytes (GB), to allocate for the VM cluster.

    " }, "systemVersion":{ "shape":"CreateCloudVmClusterInputSystemVersionString", @@ -4598,20 +4966,320 @@ } } }, - "CreateOdbNetworkInput":{ + "CreateExadbVmClusterInput":{ "type":"structure", "required":[ "displayName", - "clientSubnetCidr" + "enabledEcpuCount", + "exascaleDbStorageVaultId", + "gridImageId", + "hostname", + "nodeCount", + "odbNetworkId", + "shape", + "sshPublicKeys", + "totalEcpuCount", + "vmFileSystemStorageTotalSizeInGBs" ], "members":{ "displayName":{ "shape":"ResourceDisplayName", - "documentation":"

    A user-friendly name for the ODB network.

    " + "documentation":"

    A user-friendly name for the Exascale VM cluster.

    " }, - "availabilityZone":{ - "shape":"CreateOdbNetworkInputAvailabilityZoneString", - "documentation":"

    The Amazon Web Services Availability Zone (AZ) where the ODB network is located.

    This operation requires that you specify a value for either availabilityZone or availabilityZoneId.

    " + "enabledEcpuCount":{ + "shape":"CreateExadbVmClusterInputEnabledEcpuCountInteger", + "documentation":"

    The number of ECPUs to enable for the Exascale VM cluster.

    " + }, + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault for this Exascale VM cluster.

    " + }, + "gridImageId":{ + "shape":"CreateExadbVmClusterInputGridImageIdString", + "documentation":"

    The Grid Infrastructure software image ID for the Exascale VM cluster.

    " + }, + "hostname":{ + "shape":"Hostname", + "documentation":"

    The host name for the Exascale VM cluster.

    " + }, + "nodeCount":{ + "shape":"CreateExadbVmClusterInputNodeCountInteger", + "documentation":"

    The number of nodes in the Exascale VM cluster.

    " + }, + "odbNetworkId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the ODB network for the Exascale VM cluster.

    " + }, + "shape":{ + "shape":"CreateExadbVmClusterInputShapeString", + "documentation":"

    The shape of the Exascale VM cluster.

    " + }, + "sshPublicKeys":{ + "shape":"StringList", + "documentation":"

    The public key portion of one or more key pairs used for SSH access to the Exascale VM cluster.

    " + }, + "totalEcpuCount":{ + "shape":"CreateExadbVmClusterInputTotalEcpuCountInteger", + "documentation":"

    The total number of ECPUs for the Exascale VM cluster.

    " + }, + "vmFileSystemStorageTotalSizeInGBs":{ + "shape":"CreateExadbVmClusterInputVmFileSystemStorageTotalSizeInGBsInteger", + "documentation":"

    The total amount of file system storage, in gigabytes (GB), for the Exascale VM cluster.

    " + }, + "clusterName":{ + "shape":"ClusterName", + "documentation":"

    A name for the Grid Infrastructure cluster. The name isn't case sensitive.

    " + }, + "dataCollectionOptions":{ + "shape":"DataCollectionOptions", + "documentation":"

    The set of preferences for the various diagnostic collection options for the Exascale VM cluster.

    " + }, + "licenseModel":{ + "shape":"LicenseModel", + "documentation":"

    The Oracle license model to apply to the Exascale VM cluster.

    " + }, + "scanListenerPortTcp":{ + "shape":"CreateExadbVmClusterInputScanListenerPortTcpInteger", + "documentation":"

    The port number for TCP connections to the Single Client Access Name (SCAN) listener.

    " + }, + "scanListenerPortTcpSsl":{ + "shape":"CreateExadbVmClusterInputScanListenerPortTcpSslInteger", + "documentation":"

    The port number for TCP connections with SSL to the Single Client Access Name (SCAN) listener.

    " + }, + "shapeAttribute":{ + "shape":"ShapeAttribute", + "documentation":"

    The shape attribute for the Exascale VM cluster.

    " + }, + "systemVersion":{ + "shape":"CreateExadbVmClusterInputSystemVersionString", + "documentation":"

    The version of the operating system of the image for the Exascale VM cluster.

    " + }, + "tags":{ + "shape":"RequestTagMap", + "documentation":"

    The list of resource tags to apply to the Exascale VM cluster.

    " + }, + "timeZone":{ + "shape":"CreateExadbVmClusterInputTimeZoneString", + "documentation":"

    The time zone for the Exascale VM cluster.

    " + }, + "clientToken":{ + "shape":"CreateExadbVmClusterInputClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you submit the same request twice with the same client token, the service ignores the second request and returns the result of the first. If you don't specify a client token, the AWS SDK automatically generates one. The client token is valid for up to 24 hours after it's first used.

    ", + "idempotencyToken":true + } + } + }, + "CreateExadbVmClusterInputClientTokenString":{ + "type":"string", + "max":64, + "min":8, + "pattern":"[a-zA-Z0-9_\\/.=-]+" + }, + "CreateExadbVmClusterInputEnabledEcpuCountInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "CreateExadbVmClusterInputGridImageIdString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExadbVmClusterInputNodeCountInteger":{ + "type":"integer", + "box":true, + "min":1 + }, + "CreateExadbVmClusterInputScanListenerPortTcpInteger":{ + "type":"integer", + "box":true, + "max":8999, + "min":1024 + }, + "CreateExadbVmClusterInputScanListenerPortTcpSslInteger":{ + "type":"integer", + "box":true, + "max":8999, + "min":1024 + }, + "CreateExadbVmClusterInputShapeString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExadbVmClusterInputSystemVersionString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExadbVmClusterInputTimeZoneString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExadbVmClusterInputTotalEcpuCountInteger":{ + "type":"integer", + "box":true, + "min":2 + }, + "CreateExadbVmClusterInputVmFileSystemStorageTotalSizeInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "CreateExadbVmClusterOutput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "exadbVmClusterId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + } + } + }, + "CreateExascaleDbStorageVaultInput":{ + "type":"structure", + "required":[ + "displayName", + "highCapacityDatabaseStorageTotalSizeInGBs" + ], + "members":{ + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    A user-friendly name for the Exascale storage vault.

    " + }, + "highCapacityDatabaseStorageTotalSizeInGBs":{ + "shape":"CreateExascaleDbStorageVaultInputHighCapacityDatabaseStorageTotalSizeInGBsInteger", + "documentation":"

    The total size of the high-capacity database storage, in gigabytes (GB), for the Exascale storage vault.

    " + }, + "additionalFlashCacheInPercent":{ + "shape":"CreateExascaleDbStorageVaultInputAdditionalFlashCacheInPercentInteger", + "documentation":"

    The additional flash cache percentage for the Exascale storage vault.

    " + }, + "autoscaleLimitInGBs":{ + "shape":"CreateExascaleDbStorageVaultInputAutoscaleLimitInGBsInteger", + "documentation":"

    The autoscale limit in gigabytes (GB) for the Exascale storage vault.

    " + }, + "availabilityZoneId":{ + "shape":"CreateExascaleDbStorageVaultInputAvailabilityZoneIdString", + "documentation":"

    The Availability Zone ID for the Exascale storage vault.

    " + }, + "availabilityZone":{ + "shape":"CreateExascaleDbStorageVaultInputAvailabilityZoneString", + "documentation":"

    The Availability Zone for the Exascale storage vault.

    " + }, + "description":{ + "shape":"CreateExascaleDbStorageVaultInputDescriptionString", + "documentation":"

    A description of the Exascale storage vault.

    " + }, + "isAutoscaleEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether autoscaling is enabled for the Exascale storage vault.

    " + }, + "tags":{ + "shape":"RequestTagMap", + "documentation":"

    The list of resource tags to apply to the Exascale storage vault.

    " + }, + "timeZone":{ + "shape":"CreateExascaleDbStorageVaultInputTimeZoneString", + "documentation":"

    The time zone for the Exascale storage vault.

    " + }, + "clientToken":{ + "shape":"CreateExascaleDbStorageVaultInputClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the operation completes no more than one time. If you submit the same request twice with the same client token, the service ignores the second request and returns the result of the first. If you don't specify a client token, the AWS SDK automatically generates one. The client token is valid for up to 24 hours after it's first used.

    ", + "idempotencyToken":true + } + } + }, + "CreateExascaleDbStorageVaultInputAdditionalFlashCacheInPercentInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "CreateExascaleDbStorageVaultInputAutoscaleLimitInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "CreateExascaleDbStorageVaultInputAvailabilityZoneIdString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExascaleDbStorageVaultInputAvailabilityZoneString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExascaleDbStorageVaultInputClientTokenString":{ + "type":"string", + "max":64, + "min":8, + "pattern":"[a-zA-Z0-9_\\/.=-]+" + }, + "CreateExascaleDbStorageVaultInputDescriptionString":{ + "type":"string", + "max":400, + "min":1 + }, + "CreateExascaleDbStorageVaultInputHighCapacityDatabaseStorageTotalSizeInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "CreateExascaleDbStorageVaultInputTimeZoneString":{ + "type":"string", + "max":255, + "min":1 + }, + "CreateExascaleDbStorageVaultOutput":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale storage vault.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale storage vault.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale storage vault.

    " + }, + "exascaleDbStorageVaultId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale storage vault.

    " + } + } + }, + "CreateOdbNetworkInput":{ + "type":"structure", + "required":[ + "displayName", + "clientSubnetCidr" + ], + "members":{ + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    A user-friendly name for the ODB network.

    " + }, + "availabilityZone":{ + "shape":"CreateOdbNetworkInputAvailabilityZoneString", + "documentation":"

    The Amazon Web Services Availability Zone (AZ) where the ODB network is located.

    This operation requires that you specify a value for either availabilityZone or availabilityZoneId.

    " }, "availabilityZoneId":{ "shape":"CreateOdbNetworkInputAvailabilityZoneIdString", @@ -4876,6 +5544,42 @@ "type":"list", "member":{"shape":"CustomerContact"} }, + "CustomerManagedAwsSecretConfiguration":{ + "type":"structure", + "members":{ + "iamRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Web Services Identity and Access Management (IAM) role that OCI assumes to retrieve the secret value.

    " + }, + "secretId":{ + "shape":"SecretIdOrArn", + "documentation":"

    The identifier or ARN of the Amazon Web Services Secrets Manager secret that contains the password.

    " + }, + "externalIdType":{ + "shape":"ExternalIdType", + "documentation":"

    The type of Oracle Cloud Identifier (OCID) used as the external ID when assuming the IAM role.

    " + } + }, + "documentation":"

    The configuration of a customer-managed Amazon Web Services Secrets Manager secret used to supply a password.

    " + }, + "CustomerManagedAwsSecretConfigurationInput":{ + "type":"structure", + "members":{ + "secretId":{ + "shape":"SecretIdOrArn", + "documentation":"

    The identifier or ARN of the Amazon Web Services Secrets Manager secret that contains the password.

    " + }, + "iamRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Web Services Identity and Access Management (IAM) role that OCI assumes to retrieve the secret value.

    " + }, + "externalIdType":{ + "shape":"ExternalIdType", + "documentation":"

    The type of Oracle Cloud Identifier (OCID) used as the external ID when assuming the IAM role.

    The valid values depend on the operation. For the CreateAutonomousDatabase operation, only compartment_ocid and tenant_ocid are allowed. For the UpdateAutonomousDatabase and CreateAutonomousDatabaseWallet operations, database_ocid, compartment_ocid, and tenant_ocid are all allowed.

    " + } + }, + "documentation":"

    The input configuration for a customer-managed Amazon Web Services Secrets Manager secret used to supply a password.

    " + }, "DataCollectionOptions":{ "type":"structure", "members":{ @@ -5165,7 +5869,7 @@ }, "dbNodeStorageSizeInGBs":{ "shape":"Integer", - "documentation":"

    The amount of local node storage, in gigabytes (GBs), that's allocated on the DB node.

    " + "documentation":"

    The amount of local node storage, in gigabytes (GB), that's allocated on the DB node.

    " }, "dbServerId":{ "shape":"ResourceId", @@ -5669,6 +6373,10 @@ "shape":"ShapeType", "documentation":"

    The shape type. This property is determined by the CPU hardware.

    " }, + "shapeAttributes":{ + "shape":"ShapeAttributeList", + "documentation":"

    If provided and applicable, return DB System shape parameters based on the shape attribute provided.

    " + }, "name":{ "shape":"String", "documentation":"

    The name of the shape.

    " @@ -5763,6 +6471,34 @@ "type":"structure", "members":{} }, + "DeleteExadbVmClusterInput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster to delete.

    " + } + } + }, + "DeleteExadbVmClusterOutput":{ + "type":"structure", + "members":{} + }, + "DeleteExascaleDbStorageVaultInput":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault to delete.

    " + } + } + }, + "DeleteExascaleDbStorageVaultOutput":{ + "type":"structure", + "members":{} + }, "DeleteOdbNetworkInput":{ "type":"structure", "required":[ @@ -5830,22 +6566,61 @@ "type":"structure", "members":{} }, - "DisasterRecoveryConfiguration":{ + "DisassociateVirtualMachinesFromExadbVmClusterInput":{ "type":"structure", + "required":[ + "exadbVmClusterId", + "dbNodeIds" + ], "members":{ - "disasterRecoveryType":{ - "shape":"DisasterRecoveryType", - "documentation":"

    The type of disaster recovery configured for the Autonomous Database.

    " - }, - "isReplicateAutomaticBackups":{ - "shape":"Boolean", - "documentation":"

    Indicates whether automatic backups are replicated to the disaster recovery database.

    " - }, - "isSnapshotStandby":{ - "shape":"Boolean", - "documentation":"

    Indicates whether the standby database is a snapshot standby.

    " + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster to remove virtual machines from.

    " }, - "timeSnapshotStandbyEnabledTill":{ + "dbNodeIds":{ + "shape":"ResourceIdList", + "documentation":"

    The list of DB node IDs to remove from the Exascale VM cluster.

    " + } + } + }, + "DisassociateVirtualMachinesFromExadbVmClusterOutput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "exadbVmClusterId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + } + } + }, + "DisasterRecoveryConfiguration":{ + "type":"structure", + "members":{ + "disasterRecoveryType":{ + "shape":"DisasterRecoveryType", + "documentation":"

    The type of disaster recovery configured for the Autonomous Database.

    " + }, + "isReplicateAutomaticBackups":{ + "shape":"Boolean", + "documentation":"

    Indicates whether automatic backups are replicated to the disaster recovery database.

    " + }, + "isSnapshotStandby":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the standby database is a snapshot standby.

    " + }, + "timeSnapshotStandbyEnabledTill":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time until which the snapshot standby database remains enabled.

    " } @@ -5952,6 +6727,594 @@ }, "documentation":"

    The IORM settings of the Exadata DB system.

    " }, + "ExadbVmCluster":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + }, + "clusterName":{ + "shape":"ClusterName", + "documentation":"

    The name of the Grid Infrastructure (GI) cluster.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the Exascale VM cluster was created.

    " + }, + "dataCollectionOptions":{ + "shape":"DataCollectionOptions", + "documentation":"

    The set of diagnostic collection options enabled for the Exascale VM cluster.

    " + }, + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "domain":{ + "shape":"String", + "documentation":"

    The domain of the Exascale VM cluster.

    " + }, + "enabledEcpuCount":{ + "shape":"Integer", + "documentation":"

    The number of elastic compute processing units (ECPUs) enabled on the Exascale VM cluster.

    " + }, + "exadbVmClusterArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale VM cluster.

    " + }, + "exascaleDbStorageVaultArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale storage vault associated with this Exascale VM cluster.

    " + }, + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault associated with this Exascale VM cluster.

    " + }, + "giVersion":{ + "shape":"String", + "documentation":"

    The software version of the Oracle Grid Infrastructure (GI) for the Exascale VM cluster.

    " + }, + "gridImageId":{ + "shape":"String", + "documentation":"

    The Grid Infrastructure software image ID for the Exascale VM cluster.

    " + }, + "gridImageType":{ + "shape":"GridImageType", + "documentation":"

    The type of Grid Infrastructure image for the Exascale VM cluster.

    " + }, + "hostname":{ + "shape":"Hostname", + "documentation":"

    The host name for the Exascale VM cluster.

    " + }, + "iamRoles":{ + "shape":"IamRoleList", + "documentation":"

    The Amazon Web Services Identity and Access Management (IAM) service roles associated with the Exascale VM cluster.

    " + }, + "iormConfigCache":{ + "shape":"ExadataIormConfig", + "documentation":"

    The I/O Resource Management (IORM) configuration cache details for the Exascale VM cluster.

    " + }, + "lastUpdateHistoryEntryId":{ + "shape":"String", + "documentation":"

    The Oracle Cloud ID (OCID) of the last maintenance update history entry.

    " + }, + "licenseModel":{ + "shape":"LicenseModel", + "documentation":"

    The Oracle license model applied to the Exascale VM cluster.

    " + }, + "listenerPort":{ + "shape":"Integer", + "documentation":"

    The port number configured for the listener on the Exascale VM cluster.

    " + }, + "memorySizeInGBs":{ + "shape":"Integer", + "documentation":"

    The amount of memory, in gigabytes (GB), that's allocated for the Exascale VM cluster.

    " + }, + "nodeCount":{ + "shape":"Integer", + "documentation":"

    The number of nodes in the Exascale VM cluster.

    " + }, + "ocid":{ + "shape":"String", + "documentation":"

    The OCID of the Exascale VM cluster.

    " + }, + "ociResourceAnchorName":{ + "shape":"String", + "documentation":"

    The name of the OCI resource anchor for the Exascale VM cluster.

    " + }, + "ociUrl":{ + "shape":"String", + "documentation":"

    The HTTPS link to the Exascale VM cluster in Oracle Cloud Infrastructure (OCI).

    " + }, + "odbNetworkArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the ODB network associated with this Exascale VM cluster.

    " + }, + "odbNetworkId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the ODB network for the Exascale VM cluster.

    " + }, + "percentProgress":{ + "shape":"Float", + "documentation":"

    The amount of progress made on the current operation on the Exascale VM cluster, expressed as a percentage.

    " + }, + "scanDnsName":{ + "shape":"String", + "documentation":"

    The fully qualified domain name (FQDN) of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanDnsRecordId":{ + "shape":"String", + "documentation":"

    The OCID of the DNS record for the SCAN IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanIpIds":{ + "shape":"StringList", + "documentation":"

    The OCID of the SCAN IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanListenerPortTcp":{ + "shape":"Integer", + "documentation":"

    The port number for TCP connections to the Single Client Access Name (SCAN) listener for the Exascale VM cluster.

    " + }, + "scanListenerPortTcpSsl":{ + "shape":"Integer", + "documentation":"

    The port number for TCP connections with SSL to the Single Client Access Name (SCAN) listener for the Exascale VM cluster.

    " + }, + "shape":{ + "shape":"String", + "documentation":"

    The hardware model name of the Exadata infrastructure that's running the Exascale VM cluster.

    " + }, + "shapeAttribute":{ + "shape":"ShapeAttribute", + "documentation":"

    The shape attribute for the Exascale VM cluster.

    " + }, + "snapshotFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The snapshot file system storage details for the Exascale VM cluster.

    " + }, + "sshPublicKeys":{ + "shape":"StringList", + "documentation":"

    The public key portion of one or more key pairs used for SSH access to the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "systemVersion":{ + "shape":"String", + "documentation":"

    The operating system version of the image chosen for the Exascale VM cluster.

    " + }, + "timeZone":{ + "shape":"String", + "documentation":"

    The time zone of the Exascale VM cluster.

    " + }, + "totalEcpuCount":{ + "shape":"Integer", + "documentation":"

    The total number of ECPUs for the Exascale VM cluster.

    " + }, + "totalFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The total file system storage details for the Exascale VM cluster.

    " + }, + "vipIds":{ + "shape":"StringList", + "documentation":"

    The virtual IP (VIP) addresses associated with the Exascale VM cluster. One VIP address is assigned per node to support failover. If a node fails, its VIP is reassigned to another active node in the cluster.

    " + }, + "vmFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The VM file system storage details for the Exascale VM cluster.

    " + } + }, + "documentation":"

    Information about an Exascale VM cluster.

    " + }, + "ExadbVmClusterList":{ + "type":"list", + "member":{"shape":"ExadbVmClusterSummary"} + }, + "ExadbVmClusterStorageDetails":{ + "type":"structure", + "members":{ + "totalSizeInGBs":{ + "shape":"Integer", + "documentation":"

    The total storage size, in gigabytes (GB).

    " + } + }, + "documentation":"

    Storage details for an Exascale VM cluster.

    " + }, + "ExadbVmClusterSummary":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + }, + "clusterName":{ + "shape":"ClusterName", + "documentation":"

    The name of the Grid Infrastructure (GI) cluster.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the Exascale VM cluster was created.

    " + }, + "dataCollectionOptions":{ + "shape":"DataCollectionOptions", + "documentation":"

    The set of diagnostic collection options enabled for the Exascale VM cluster.

    " + }, + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "domain":{ + "shape":"String", + "documentation":"

    The domain of the Exascale VM cluster.

    " + }, + "enabledEcpuCount":{ + "shape":"Integer", + "documentation":"

    The number of elastic compute processing units (ECPUs) enabled on the Exascale VM cluster.

    " + }, + "exadbVmClusterArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale VM cluster.

    " + }, + "exascaleDbStorageVaultArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale storage vault associated with this Exascale VM cluster.

    " + }, + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault associated with this Exascale VM cluster.

    " + }, + "giVersion":{ + "shape":"String", + "documentation":"

    The software version of the Oracle Grid Infrastructure (GI) for the Exascale VM cluster.

    " + }, + "gridImageId":{ + "shape":"String", + "documentation":"

    The Grid Infrastructure software image ID for the Exascale VM cluster.

    " + }, + "gridImageType":{ + "shape":"GridImageType", + "documentation":"

    The type of Grid Infrastructure image for the Exascale VM cluster.

    " + }, + "hostname":{ + "shape":"Hostname", + "documentation":"

    The host name for the Exascale VM cluster.

    " + }, + "iamRoles":{ + "shape":"IamRoleList", + "documentation":"

    The Amazon Web Services Identity and Access Management (IAM) service roles associated with the Exascale VM cluster.

    " + }, + "iormConfigCache":{ + "shape":"ExadataIormConfig", + "documentation":"

    The I/O Resource Management (IORM) configuration cache details for the Exascale VM cluster.

    " + }, + "lastUpdateHistoryEntryId":{ + "shape":"String", + "documentation":"

    The Oracle Cloud ID (OCID) of the last maintenance update history entry.

    " + }, + "licenseModel":{ + "shape":"LicenseModel", + "documentation":"

    The Oracle license model applied to the Exascale VM cluster.

    " + }, + "listenerPort":{ + "shape":"Integer", + "documentation":"

    The port number configured for the listener on the Exascale VM cluster.

    " + }, + "memorySizeInGBs":{ + "shape":"Integer", + "documentation":"

    The amount of memory, in gigabytes (GB), that's allocated for the Exascale VM cluster.

    " + }, + "nodeCount":{ + "shape":"Integer", + "documentation":"

    The number of nodes in the Exascale VM cluster.

    " + }, + "ocid":{ + "shape":"String", + "documentation":"

    The OCID of the Exascale VM cluster.

    " + }, + "ociResourceAnchorName":{ + "shape":"String", + "documentation":"

    The name of the OCI resource anchor for the Exascale VM cluster.

    " + }, + "ociUrl":{ + "shape":"String", + "documentation":"

    The HTTPS link to the Exascale VM cluster in Oracle Cloud Infrastructure (OCI).

    " + }, + "odbNetworkArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the ODB network associated with this Exascale VM cluster.

    " + }, + "odbNetworkId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the ODB network for the Exascale VM cluster.

    " + }, + "percentProgress":{ + "shape":"Float", + "documentation":"

    The amount of progress made on the current operation on the Exascale VM cluster, expressed as a percentage.

    " + }, + "scanDnsName":{ + "shape":"String", + "documentation":"

    The fully qualified domain name (FQDN) of the DNS record for the Single Client Access Name (SCAN) IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanDnsRecordId":{ + "shape":"String", + "documentation":"

    The OCID of the DNS record for the SCAN IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanIpIds":{ + "shape":"StringList", + "documentation":"

    The OCID of the SCAN IP addresses that are associated with the Exascale VM cluster.

    " + }, + "scanListenerPortTcp":{ + "shape":"Integer", + "documentation":"

    The port number for TCP connections to the Single Client Access Name (SCAN) listener for the Exascale VM cluster.

    " + }, + "scanListenerPortTcpSsl":{ + "shape":"Integer", + "documentation":"

    The port number for TCP connections with SSL to the Single Client Access Name (SCAN) listener for the Exascale VM cluster.

    " + }, + "shape":{ + "shape":"String", + "documentation":"

    The hardware model name of the Exadata infrastructure that's running the Exascale VM cluster.

    " + }, + "shapeAttribute":{ + "shape":"ShapeAttribute", + "documentation":"

    The shape attribute for the Exascale VM cluster.

    " + }, + "snapshotFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The snapshot file system storage details for the Exascale VM cluster.

    " + }, + "sshPublicKeys":{ + "shape":"StringList", + "documentation":"

    The public key portion of one or more key pairs used for SSH access to the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "systemVersion":{ + "shape":"String", + "documentation":"

    The operating system version of the image chosen for the Exascale VM cluster.

    " + }, + "timeZone":{ + "shape":"String", + "documentation":"

    The time zone of the Exascale VM cluster.

    " + }, + "totalEcpuCount":{ + "shape":"Integer", + "documentation":"

    The total number of ECPUs for the Exascale VM cluster.

    " + }, + "totalFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The total file system storage details for the Exascale VM cluster.

    " + }, + "vipIds":{ + "shape":"StringList", + "documentation":"

    The virtual IP (VIP) addresses associated with the Exascale VM cluster. One VIP address is assigned per node to support failover. If a node fails, its VIP is reassigned to another active node in the cluster.

    " + }, + "vmFileSystemStorage":{ + "shape":"ExadbVmClusterStorageDetails", + "documentation":"

    The VM file system storage details for the Exascale VM cluster.

    " + } + }, + "documentation":"

    Summary information about an Exascale VM cluster.

    " + }, + "ExascaleDbStorageDetails":{ + "type":"structure", + "members":{ + "availableSizeInGBs":{ + "shape":"Integer", + "documentation":"

    The available storage size, in gigabytes (GB).

    " + }, + "totalSizeInGBs":{ + "shape":"Integer", + "documentation":"

    The total storage size, in gigabytes (GB).

    " + } + }, + "documentation":"

    The storage details for an Exascale storage vault.

    " + }, + "ExascaleDbStorageVault":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault.

    " + }, + "additionalFlashCacheInPercent":{ + "shape":"Integer", + "documentation":"

    The additional flash cache percentage for the Exascale storage vault.

    " + }, + "attachedShapeAttributes":{ + "shape":"ShapeAttributeList", + "documentation":"

    The list of shape attributes attached to the Exascale storage vault.

    " + }, + "autoscaleLimitInGBs":{ + "shape":"Integer", + "documentation":"

    The autoscale limit in gigabytes (GB) for the Exascale storage vault.

    " + }, + "availabilityZone":{ + "shape":"String", + "documentation":"

    The Availability Zone for the Exascale storage vault.

    " + }, + "availabilityZoneId":{ + "shape":"String", + "documentation":"

    The Availability Zone ID for the Exascale storage vault.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the Exascale storage vault was created.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the Exascale storage vault.

    " + }, + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale storage vault.

    " + }, + "vmClusterArns":{ + "shape":"ResourceArnList", + "documentation":"

    The list of Amazon Resource Names (ARNs) of the VM clusters associated with this Exascale storage vault.

    " + }, + "vmClusterCount":{ + "shape":"Integer", + "documentation":"

    The number of VM clusters associated with this Exascale storage vault.

    " + }, + "vmClusterIds":{ + "shape":"ResourceIdList", + "documentation":"

    The list of unique identifiers of the VM clusters associated with this Exascale storage vault.

    " + }, + "exascaleDbStorageVaultArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale storage vault.

    " + }, + "highCapacityDatabaseStorage":{ + "shape":"ExascaleDbStorageDetails", + "documentation":"

    The high-capacity database storage details for the Exascale storage vault.

    " + }, + "isAutoscaleEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether autoscaling is enabled for the Exascale storage vault.

    " + }, + "ocid":{ + "shape":"String", + "documentation":"

    The OCID of the Exascale storage vault.

    " + }, + "ociResourceAnchorName":{ + "shape":"String", + "documentation":"

    The name of the OCI resource anchor for the Exascale storage vault.

    " + }, + "ociUrl":{ + "shape":"String", + "documentation":"

    The HTTPS link to the Exascale storage vault in Oracle Cloud Infrastructure (OCI).

    " + }, + "percentProgress":{ + "shape":"Float", + "documentation":"

    The amount of progress made on the current operation on the Exascale storage vault, expressed as a percentage.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale storage vault.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale storage vault.

    " + }, + "timeZone":{ + "shape":"String", + "documentation":"

    The time zone of the Exascale storage vault.

    " + } + }, + "documentation":"

    Information about an Exascale storage vault.

    " + }, + "ExascaleDbStorageVaultList":{ + "type":"list", + "member":{"shape":"ExascaleDbStorageVaultSummary"} + }, + "ExascaleDbStorageVaultSummary":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault.

    " + }, + "additionalFlashCacheInPercent":{ + "shape":"Integer", + "documentation":"

    The additional flash cache percentage for the Exascale storage vault.

    " + }, + "attachedShapeAttributes":{ + "shape":"ShapeAttributeList", + "documentation":"

    The list of shape attributes attached to the Exascale storage vault.

    " + }, + "autoscaleLimitInGBs":{ + "shape":"Integer", + "documentation":"

    The autoscale limit in gigabytes (GB) for the Exascale storage vault.

    " + }, + "availabilityZone":{ + "shape":"String", + "documentation":"

    The Availability Zone for the Exascale storage vault.

    " + }, + "availabilityZoneId":{ + "shape":"String", + "documentation":"

    The Availability Zone ID for the Exascale storage vault.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the Exascale storage vault was created.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    The description of the Exascale storage vault.

    " + }, + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale storage vault.

    " + }, + "vmClusterArns":{ + "shape":"ResourceArnList", + "documentation":"

    The list of Amazon Resource Names (ARNs) of the VM clusters associated with this Exascale storage vault.

    " + }, + "vmClusterCount":{ + "shape":"Integer", + "documentation":"

    The number of VM clusters associated with this Exascale storage vault.

    " + }, + "vmClusterIds":{ + "shape":"ResourceIdList", + "documentation":"

    The list of unique identifiers of the VM clusters associated with this Exascale storage vault.

    " + }, + "exascaleDbStorageVaultArn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Exascale storage vault.

    " + }, + "highCapacityDatabaseStorage":{ + "shape":"ExascaleDbStorageDetails", + "documentation":"

    The high-capacity database storage details for the Exascale storage vault.

    " + }, + "isAutoscaleEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether autoscaling is enabled for the Exascale storage vault.

    " + }, + "ocid":{ + "shape":"String", + "documentation":"

    The OCID of the Exascale storage vault.

    " + }, + "ociResourceAnchorName":{ + "shape":"String", + "documentation":"

    The name of the OCI resource anchor for the Exascale storage vault.

    " + }, + "ociUrl":{ + "shape":"String", + "documentation":"

    The HTTPS link to the Exascale storage vault in Oracle Cloud Infrastructure (OCI).

    " + }, + "percentProgress":{ + "shape":"Float", + "documentation":"

    The amount of progress made on the current operation on the Exascale storage vault, expressed as a percentage.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale storage vault.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale storage vault.

    " + }, + "timeZone":{ + "shape":"String", + "documentation":"

    The time zone of the Exascale storage vault.

    " + } + }, + "documentation":"

    Summary information about an Exascale storage vault.

    " + }, "ExternalIdType":{ "type":"string", "enum":[ @@ -5980,21 +7343,75 @@ "members":{ "autonomousDatabaseId":{ "shape":"String", - "documentation":"

    The unique identifier of the Autonomous Database that was failed over.

    " + "documentation":"

    The unique identifier of the Autonomous Database that was failed over.

    " + }, + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name of the Autonomous Database.

    " + }, + "status":{ + "shape":"AutonomousDatabaseResourceStatus", + "documentation":"

    The current status of the Autonomous Database after the failover operation.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Autonomous Database after the failover operation.

    " + } + } + }, + "FlexComponentList":{ + "type":"list", + "member":{"shape":"FlexComponentSummary"} + }, + "FlexComponentSummary":{ + "type":"structure", + "members":{ + "availableCoreCount":{ + "shape":"Integer", + "documentation":"

    The maximum number of CPU cores that can be enabled for the flex component.

    " + }, + "availableDbStorageInGBs":{ + "shape":"Integer", + "documentation":"

    The maximum amount of database storage, in gigabytes (GB), that can be enabled for the flex component.

    " + }, + "availableLocalStorageInGBs":{ + "shape":"Integer", + "documentation":"

    The maximum amount of local storage, in gigabytes (GB), that can be enabled for the flex component.

    " + }, + "availableMemoryInGBs":{ + "shape":"Integer", + "documentation":"

    The maximum amount of memory, in gigabytes (GB), that can be enabled for the flex component.

    " + }, + "computeModel":{ + "shape":"ComputeModel", + "documentation":"

    The OCI model compute model used when you create or clone an instance: ECPU or OCPU. An ECPU is an abstracted measure of compute resources. ECPUs are based on the number of cores elastically allocated from a pool of compute and storage servers. An OCPU is a legacy physical measure of compute resources. OCPUs are based on the physical core of a processor with hyper-threading enabled.

    " + }, + "descriptionSummary":{ + "shape":"String", + "documentation":"

    A summary description of the flex component.

    " }, - "displayName":{ + "hardwareType":{ + "shape":"HardwareType", + "documentation":"

    The type of hardware for the flex component. Valid values are COMPUTE for compute servers and CELL for storage servers.

    " + }, + "minimumCoreCount":{ + "shape":"Integer", + "documentation":"

    The minimum number of CPU cores that can be enabled for the flex component.

    " + }, + "name":{ "shape":"String", - "documentation":"

    The user-friendly name of the Autonomous Database.

    " + "documentation":"

    The name of the flex component.

    " }, - "status":{ - "shape":"AutonomousDatabaseResourceStatus", - "documentation":"

    The current status of the Autonomous Database after the failover operation.

    " + "runtimeMinimumCoreCount":{ + "shape":"Integer", + "documentation":"

    The runtime minimum number of CPU cores that can be enabled for the flex component.

    " }, - "statusReason":{ + "shape":{ "shape":"String", - "documentation":"

    Additional information about the status of the Autonomous Database after the failover operation.

    " + "documentation":"

    The shape that uses the flex component.

    " } - } + }, + "documentation":"

    Information about a flex component that's available for an Exadata infrastructure. A flex component defines the hardware resources, such as CPU cores, memory, and storage, that can be allocated to a shape.

    " }, "Float":{ "type":"float", @@ -6141,14 +7558,15 @@ }, "GetDbNodeInput":{ "type":"structure", - "required":[ - "cloudVmClusterId", - "dbNodeId" - ], + "required":["dbNodeId"], "members":{ "cloudVmClusterId":{ "shape":"ResourceId", - "documentation":"

    The unique identifier of the VM cluster that contains the DB node.

    " + "documentation":"

    The unique identifier of the VM cluster that contains the DB node. You must specify either this parameter or exadbVmClusterId.

    " + }, + "exadbVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the Exascale VM cluster that contains the DB node. You must specify either this parameter or cloudVmClusterId.

    " }, "dbNodeId":{ "shape":"ResourceId", @@ -6188,6 +7606,46 @@ } } }, + "GetExadbVmClusterInput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + } + } + }, + "GetExadbVmClusterOutput":{ + "type":"structure", + "required":["exadbVmCluster"], + "members":{ + "exadbVmCluster":{ + "shape":"ExadbVmCluster", + "documentation":"

    The Exascale VM cluster.

    " + } + } + }, + "GetExascaleDbStorageVaultInput":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault.

    " + } + } + }, + "GetExascaleDbStorageVaultOutput":{ + "type":"structure", + "required":["exascaleDbStorageVault"], + "members":{ + "exascaleDbStorageVault":{ + "shape":"ExascaleDbStorageVault", + "documentation":"

    The Exascale storage vault.

    " + } + } + }, "GetOciOnboardingStatusInput":{ "type":"structure", "members":{} @@ -6261,6 +7719,25 @@ "odbPeeringConnection":{"shape":"OdbPeeringConnection"} } }, + "GiMinorVersionList":{ + "type":"list", + "member":{"shape":"GiMinorVersionSummary"} + }, + "GiMinorVersionSummary":{ + "type":"structure", + "required":["version"], + "members":{ + "version":{ + "shape":"String", + "documentation":"

    The GI minor version.

    " + }, + "gridImageId":{ + "shape":"String", + "documentation":"

    The Grid Infrastructure software image ID for this minor version.

    " + } + }, + "documentation":"

    Summary information about an Oracle Grid Infrastructure (GI) minor version.

    " + }, "GiVersionList":{ "type":"list", "member":{"shape":"GiVersionSummary"} @@ -6275,6 +7752,20 @@ }, "documentation":"

    Information about a specific version of Oracle Grid Infrastructure (GI) software that can be installed on a VM cluster.

    " }, + "GridImageType":{ + "type":"string", + "enum":[ + "RELEASE_UPDATE", + "CUSTOM_IMAGE" + ] + }, + "HardwareType":{ + "type":"string", + "enum":[ + "COMPUTE", + "CELL" + ] + }, "Hostname":{ "type":"string", "max":12, @@ -6329,6 +7820,10 @@ "ociIdentityDomain":{ "shape":"Boolean", "documentation":"

    The Oracle Cloud Infrastructure (OCI) identity domain configuration for service initialization.

    " + }, + "autonomousDatabaseOciAwsSecretsManagerIntegration":{ + "shape":"Access", + "documentation":"

    Specifies whether to enable or disable the OCI service-account role for Amazon Web Services Secrets Manager integration with Autonomous Database.

    " } } }, @@ -6803,170 +8298,384 @@ } } }, - "ListCloudVmClustersInputMaxResultsInteger":{ + "ListCloudVmClustersInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "ListCloudVmClustersInputNextTokenString":{ + "type":"string", + "max":8192, + "min":1 + }, + "ListCloudVmClustersOutput":{ + "type":"structure", + "required":["cloudVmClusters"], + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " + }, + "cloudVmClusters":{ + "shape":"CloudVmClusterList", + "documentation":"

    The list of VM clusters along with their properties.

    " + } + } + }, + "ListDbNodesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListDbNodesInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + }, + "nextToken":{ + "shape":"ListDbNodesInputNextTokenString", + "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "cloudVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the VM cluster. You must specify either this parameter or exadbVmClusterId.

    " + }, + "exadbVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the Exascale VM cluster. You must specify either this parameter or cloudVmClusterId.

    " + } + } + }, + "ListDbNodesInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "ListDbNodesInputNextTokenString":{ + "type":"string", + "max":8192, + "min":1 + }, + "ListDbNodesOutput":{ + "type":"structure", + "required":["dbNodes"], + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " + }, + "dbNodes":{ + "shape":"DbNodeList", + "documentation":"

    The list of DB nodes along with their properties.

    " + } + } + }, + "ListDbServersInput":{ + "type":"structure", + "required":["cloudExadataInfrastructureId"], + "members":{ + "cloudExadataInfrastructureId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Oracle Exadata infrastructure.

    " + }, + "maxResults":{ + "shape":"ListDbServersInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + }, + "nextToken":{ + "shape":"ListDbServersInputNextTokenString", + "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + } + } + }, + "ListDbServersInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "ListDbServersInputNextTokenString":{ + "type":"string", + "max":8192, + "min":1 + }, + "ListDbServersOutput":{ + "type":"structure", + "required":["dbServers"], + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " + }, + "dbServers":{ + "shape":"DbServerList", + "documentation":"

    The list of database servers along with their properties.

    " + } + } + }, + "ListDbSystemShapesInput":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListDbSystemShapesInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + }, + "nextToken":{ + "shape":"ListDbSystemShapesInputNextTokenString", + "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "availabilityZone":{ + "shape":"ListDbSystemShapesInputAvailabilityZoneString", + "documentation":"

    The logical name of the AZ, for example, us-east-1a. This name varies depending on the account.

    " + }, + "availabilityZoneId":{ + "shape":"ListDbSystemShapesInputAvailabilityZoneIdString", + "documentation":"

    The physical ID of the AZ, for example, use1-az4. This ID persists across accounts.

    " + }, + "shapeFamily":{ + "shape":"ListDbSystemShapesInputShapeFamilyString", + "documentation":"

    The shape family to filter results by.

    " + } + } + }, + "ListDbSystemShapesInputAvailabilityZoneIdString":{ + "type":"string", + "max":255, + "min":1 + }, + "ListDbSystemShapesInputAvailabilityZoneString":{ + "type":"string", + "max":255, + "min":1 + }, + "ListDbSystemShapesInputMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":1000, + "min":1 + }, + "ListDbSystemShapesInputNextTokenString":{ + "type":"string", + "max":8192, + "min":1 + }, + "ListDbSystemShapesInputShapeFamilyString":{ + "type":"string", + "max":255, + "min":1 + }, + "ListDbSystemShapesOutput":{ + "type":"structure", + "required":["dbSystemShapes"], + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " + }, + "dbSystemShapes":{ + "shape":"DbSystemShapeList", + "documentation":"

    The list of shapes and their properties.

    " + } + } + }, + "ListExadbVmClustersInput":{ + "type":"structure", + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault to list the associated Exascale VM clusters.

    " + }, + "maxResults":{ + "shape":"ListExadbVmClustersInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    " + }, + "nextToken":{ + "shape":"ListExadbVmClustersInputNextTokenString", + "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + } + } + }, + "ListExadbVmClustersInputMaxResultsInteger":{ "type":"integer", "box":true, "max":1000, "min":1 }, - "ListCloudVmClustersInputNextTokenString":{ + "ListExadbVmClustersInputNextTokenString":{ "type":"string", "max":8192, "min":1 }, - "ListCloudVmClustersOutput":{ + "ListExadbVmClustersOutput":{ "type":"structure", - "required":["cloudVmClusters"], + "required":["exadbVmClusters"], "members":{ "nextToken":{ "shape":"String", "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " }, - "cloudVmClusters":{ - "shape":"CloudVmClusterList", - "documentation":"

    The list of VM clusters along with their properties.

    " + "exadbVmClusters":{ + "shape":"ExadbVmClusterList", + "documentation":"

    The list of Exascale VM clusters.

    " } } }, - "ListDbNodesInput":{ + "ListExascaleDbStorageVaultsInput":{ "type":"structure", - "required":["cloudVmClusterId"], "members":{ "maxResults":{ - "shape":"ListDbNodesInputMaxResultsInteger", - "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + "shape":"ListExascaleDbStorageVaultsInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    " }, "nextToken":{ - "shape":"ListDbNodesInputNextTokenString", + "shape":"ListExascaleDbStorageVaultsInputNextTokenString", "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " - }, - "cloudVmClusterId":{ - "shape":"ResourceId", - "documentation":"

    The unique identifier of the VM cluster.

    " } } }, - "ListDbNodesInputMaxResultsInteger":{ + "ListExascaleDbStorageVaultsInputMaxResultsInteger":{ "type":"integer", "box":true, "max":1000, "min":1 }, - "ListDbNodesInputNextTokenString":{ + "ListExascaleDbStorageVaultsInputNextTokenString":{ "type":"string", "max":8192, "min":1 }, - "ListDbNodesOutput":{ + "ListExascaleDbStorageVaultsOutput":{ "type":"structure", - "required":["dbNodes"], + "required":["exascaleDbStorageVaults"], "members":{ "nextToken":{ "shape":"String", "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " }, - "dbNodes":{ - "shape":"DbNodeList", - "documentation":"

    The list of DB nodes along with their properties.

    " + "exascaleDbStorageVaults":{ + "shape":"ExascaleDbStorageVaultList", + "documentation":"

    The list of Exascale storage vaults.

    " } } }, - "ListDbServersInput":{ + "ListFlexComponentsInput":{ "type":"structure", - "required":["cloudExadataInfrastructureId"], "members":{ - "cloudExadataInfrastructureId":{ - "shape":"ResourceIdOrArn", - "documentation":"

    The unique identifier of the Oracle Exadata infrastructure.

    " - }, "maxResults":{ - "shape":"ListDbServersInputMaxResultsInteger", - "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + "shape":"ListFlexComponentsInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    " }, "nextToken":{ - "shape":"ListDbServersInputNextTokenString", + "shape":"ListFlexComponentsInputNextTokenString", "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " + }, + "shape":{ + "shape":"ListFlexComponentsInputShapeString", + "documentation":"

    The shape to return flex components for. For a list of valid shapes, use the ListDbSystemShapes operation.

    " } } }, - "ListDbServersInputMaxResultsInteger":{ + "ListFlexComponentsInputMaxResultsInteger":{ "type":"integer", "box":true, "max":1000, "min":1 }, - "ListDbServersInputNextTokenString":{ + "ListFlexComponentsInputNextTokenString":{ "type":"string", "max":8192, "min":1 }, - "ListDbServersOutput":{ + "ListFlexComponentsInputShapeString":{ + "type":"string", + "max":256, + "min":1 + }, + "ListFlexComponentsOutput":{ "type":"structure", - "required":["dbServers"], + "required":["flexComponents"], "members":{ "nextToken":{ "shape":"String", "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " }, - "dbServers":{ - "shape":"DbServerList", - "documentation":"

    The list of database servers along with their properties.

    " + "flexComponents":{ + "shape":"FlexComponentList", + "documentation":"

    The list of flex components along with their properties.

    " } } }, - "ListDbSystemShapesInput":{ + "ListGiMinorVersionsInput":{ "type":"structure", + "required":["giVersion"], "members":{ + "giVersion":{ + "shape":"ListGiMinorVersionsInputGiVersionString", + "documentation":"

    The Oracle Grid Infrastructure (GI) major version.

    " + }, "maxResults":{ - "shape":"ListDbSystemShapesInputMaxResultsInteger", - "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    Default: 10

    " + "shape":"ListGiMinorVersionsInputMaxResultsInteger", + "documentation":"

    The maximum number of items to return for this request. To get the next page of items, make another request with the token returned in the output.

    " }, "nextToken":{ - "shape":"ListDbSystemShapesInputNextTokenString", + "shape":"ListGiMinorVersionsInputNextTokenString", "documentation":"

    The token returned from a previous paginated request. Pagination continues from the end of the items returned by the previous request.

    " }, + "shapeFamily":{ + "shape":"ListGiMinorVersionsInputShapeFamilyString", + "documentation":"

    The shape family for the GI minor version.

    " + }, "availabilityZone":{ - "shape":"ListDbSystemShapesInputAvailabilityZoneString", - "documentation":"

    The logical name of the AZ, for example, us-east-1a. This name varies depending on the account.

    " + "shape":"ListGiMinorVersionsInputAvailabilityZoneString", + "documentation":"

    The Availability Zone to filter GI minor versions.

    " }, "availabilityZoneId":{ - "shape":"ListDbSystemShapesInputAvailabilityZoneIdString", - "documentation":"

    The physical ID of the AZ, for example, use1-az4. This ID persists across accounts.

    " + "shape":"ListGiMinorVersionsInputAvailabilityZoneIdString", + "documentation":"

    The Availability Zone ID to filter GI minor versions.

    " } } }, - "ListDbSystemShapesInputAvailabilityZoneIdString":{ + "ListGiMinorVersionsInputAvailabilityZoneIdString":{ "type":"string", "max":255, "min":1 }, - "ListDbSystemShapesInputAvailabilityZoneString":{ + "ListGiMinorVersionsInputAvailabilityZoneString":{ "type":"string", "max":255, "min":1 }, - "ListDbSystemShapesInputMaxResultsInteger":{ + "ListGiMinorVersionsInputGiVersionString":{ + "type":"string", + "max":255, + "min":1 + }, + "ListGiMinorVersionsInputMaxResultsInteger":{ "type":"integer", "box":true, "max":1000, "min":1 }, - "ListDbSystemShapesInputNextTokenString":{ + "ListGiMinorVersionsInputNextTokenString":{ "type":"string", "max":8192, "min":1 }, - "ListDbSystemShapesOutput":{ + "ListGiMinorVersionsInputShapeFamilyString":{ + "type":"string", + "max":255, + "min":1 + }, + "ListGiMinorVersionsOutput":{ "type":"structure", - "required":["dbSystemShapes"], + "required":["giMinorVersions"], "members":{ "nextToken":{ "shape":"String", "documentation":"

    The token to include in another request to get the next page of items. This value is null when there are no more items to return.

    " }, - "dbSystemShapes":{ - "shape":"DbSystemShapeList", - "documentation":"

    The list of shapes and their properties.

    " + "giMinorVersions":{ + "shape":"GiMinorVersionList", + "documentation":"

    The list of GI minor versions.

    " } } }, @@ -7381,7 +9090,10 @@ }, "OciAwsIntegration":{ "type":"string", - "enum":["KmsTde"] + "enum":[ + "KmsTde", + "SecretsManager" + ] }, "OciDnsForwardingConfig":{ "type":"structure", @@ -7444,6 +9156,14 @@ "awsIntegration":{ "shape":"OciAwsIntegration", "documentation":"

    The Amazon Web Services integration configuration settings for the Amazon Web Services Identity and Access Management (IAM) service role.

    " + }, + "status":{ + "shape":"OciIamRoleStatus", + "documentation":"

    The current lifecycle status of the IAM service role.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the current status of the IAM service role, if applicable.

    " } }, "documentation":"

    Information about an Amazon Web Services Identity and Access Management (IAM) service role used for Autonomous Database integration with Oracle Cloud Infrastructure (OCI).

    " @@ -7454,6 +9174,17 @@ "max":10, "min":0 }, + "OciIamRoleStatus":{ + "type":"string", + "documentation":"

    The lifecycle status of an Amazon Web Services Identity and Access Management (IAM) service role used for Autonomous Database integration with Oracle Cloud Infrastructure (OCI).

    ", + "enum":[ + "PROVISIONING", + "AVAILABLE", + "PROVISION_FAILED", + "TERMINATING", + "TERMINATE_FAILED" + ] + }, "OciIdentityDomain":{ "type":"structure", "members":{ @@ -8046,14 +9777,15 @@ }, "RebootDbNodeInput":{ "type":"structure", - "required":[ - "cloudVmClusterId", - "dbNodeId" - ], + "required":["dbNodeId"], "members":{ "cloudVmClusterId":{ "shape":"ResourceId", - "documentation":"

    The unique identifier of the VM cluster that contains the DB node to reboot.

    " + "documentation":"

    The unique identifier of the VM cluster that contains the DB node to reboot. You must specify either this parameter or exadbVmClusterId.

    " + }, + "exadbVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the Exascale VM cluster that contains the DB node to reboot. You must specify either this parameter or cloudVmClusterId.

    " }, "dbNodeId":{ "shape":"ResourceId", @@ -8115,6 +9847,10 @@ "min":20, "pattern":"arn:(?:aws|aws-cn|aws-us-gov|aws-iso-{0,1}[a-z]{0,1}):[a-z0-9-]+:[a-z0-9-]*:[0-9]+:[a-z0-9-]+/[a-z0-9-_]{6,64}" }, + "ResourceArnList":{ + "type":"list", + "member":{"shape":"ResourceArn"} + }, "ResourceDisplayName":{ "type":"string", "max":255, @@ -8319,6 +10055,12 @@ "type":"list", "member":{"shape":"ScheduledOperationDetails"} }, + "SecretIdOrArn":{ + "type":"string", + "documentation":"

    The identifier or Amazon Resource Name (ARN) of an Amazon Web Services Secrets Manager secret.

    ", + "max":2048, + "min":1 + }, "SensitiveString":{ "type":"string", "sensitive":true @@ -8367,6 +10109,17 @@ "documentation":"

    You have exceeded the service quota.

    ", "exception":true }, + "ShapeAttribute":{ + "type":"string", + "enum":[ + "SMART_STORAGE", + "BLOCK_STORAGE" + ] + }, + "ShapeAttributeList":{ + "type":"list", + "member":{"shape":"ShapeAttribute"} + }, "ShapeType":{ "type":"string", "enum":[ @@ -8493,14 +10246,15 @@ }, "StartDbNodeInput":{ "type":"structure", - "required":[ - "cloudVmClusterId", - "dbNodeId" - ], + "required":["dbNodeId"], "members":{ "cloudVmClusterId":{ "shape":"ResourceId", - "documentation":"

    The unique identifier of the VM cluster that contains the DB node to start.

    " + "documentation":"

    The unique identifier of the VM cluster that contains the DB node to start. You must specify either this parameter or exadbVmClusterId.

    " + }, + "exadbVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the Exascale VM cluster that contains the DB node to start. You must specify either this parameter or cloudVmClusterId.

    " }, "dbNodeId":{ "shape":"ResourceId", @@ -8560,14 +10314,15 @@ }, "StopDbNodeInput":{ "type":"structure", - "required":[ - "cloudVmClusterId", - "dbNodeId" - ], + "required":["dbNodeId"], "members":{ "cloudVmClusterId":{ "shape":"ResourceId", - "documentation":"

    The unique identifier of the VM cluster that contains the DB node to stop.

    " + "documentation":"

    The unique identifier of the VM cluster that contains the DB node to stop. You must specify either this parameter or exadbVmClusterId.

    " + }, + "exadbVmClusterId":{ + "shape":"ResourceId", + "documentation":"

    The unique identifier of the Exascale VM cluster that contains the DB node to stop. You must specify either this parameter or cloudVmClusterId.

    " }, "dbNodeId":{ "shape":"ResourceId", @@ -8783,6 +10538,15 @@ "type":"structure", "members":{} }, + "UpdateAction":{ + "type":"string", + "enum":[ + "ROLLING_APPLY", + "NON_ROLLING_APPLY", + "PRECHECK", + "ROLLBACK" + ] + }, "UpdateAutonomousDatabaseBackupInput":{ "type":"structure", "required":["autonomousDatabaseBackupId"], @@ -9000,6 +10764,14 @@ "encryptionKeyConfiguration":{ "shape":"EncryptionKeyConfigurationInput", "documentation":"

    The configuration of the encryption key to use for the Autonomous Database.

    " + }, + "adminPasswordSource":{ + "shape":"AdminPasswordSource", + "documentation":"

    The source of the admin password for the Autonomous Database. When set to CUSTOMER_MANAGED_AWS_SECRET, the admin password is retrieved from an Amazon Web Services Secrets Manager secret.

    " + }, + "adminPasswordSourceConfiguration":{ + "shape":"AdminPasswordSourceConfigurationInput", + "documentation":"

    The configuration of the admin password source for the Autonomous Database.

    " } } }, @@ -9127,6 +10899,179 @@ } } }, + "UpdateExadbVmClusterInput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "exadbVmClusterId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale VM cluster to update.

    " + }, + "dataCollectionOptions":{ + "shape":"DataCollectionOptions", + "documentation":"

    The set of preferences for the various diagnostic collection options for the Exascale VM cluster.

    " + }, + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    A new user-friendly name for the Exascale VM cluster.

    " + }, + "enabledEcpuCount":{ + "shape":"UpdateExadbVmClusterInputEnabledEcpuCountInteger", + "documentation":"

    The number of ECPUs to enable for the Exascale VM cluster.

    " + }, + "gridImageId":{ + "shape":"UpdateExadbVmClusterInputGridImageIdString", + "documentation":"

    The Grid Infrastructure software image ID for the Exascale VM cluster.

    " + }, + "licenseModel":{ + "shape":"LicenseModel", + "documentation":"

    The Oracle license model to apply to the Exascale VM cluster.

    " + }, + "sshPublicKeys":{ + "shape":"StringList", + "documentation":"

    The public key portion of one or more key pairs used for SSH access to the Exascale VM cluster.

    " + }, + "systemVersion":{ + "shape":"UpdateExadbVmClusterInputSystemVersionString", + "documentation":"

    The version of the operating system of the image for the Exascale VM cluster.

    " + }, + "totalEcpuCount":{ + "shape":"UpdateExadbVmClusterInputTotalEcpuCountInteger", + "documentation":"

    The total number of ECPUs for the Exascale VM cluster.

    " + }, + "updateAction":{ + "shape":"UpdateAction", + "documentation":"

    The update action to perform on the Exascale VM cluster.

    " + }, + "vmFileSystemStorageTotalSizeInGBs":{ + "shape":"UpdateExadbVmClusterInputVmFileSystemStorageTotalSizeInGBsInteger", + "documentation":"

    The total amount of file system storage, in gigabytes (GB), for the Exascale VM cluster.

    " + } + } + }, + "UpdateExadbVmClusterInputEnabledEcpuCountInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "UpdateExadbVmClusterInputGridImageIdString":{ + "type":"string", + "max":255, + "min":1 + }, + "UpdateExadbVmClusterInputSystemVersionString":{ + "type":"string", + "max":255, + "min":1 + }, + "UpdateExadbVmClusterInputTotalEcpuCountInteger":{ + "type":"integer", + "box":true, + "min":2 + }, + "UpdateExadbVmClusterInputVmFileSystemStorageTotalSizeInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "UpdateExadbVmClusterOutput":{ + "type":"structure", + "required":["exadbVmClusterId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale VM cluster.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale VM cluster.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale VM cluster.

    " + }, + "exadbVmClusterId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale VM cluster.

    " + } + } + }, + "UpdateExascaleDbStorageVaultInput":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "exascaleDbStorageVaultId":{ + "shape":"ResourceIdOrArn", + "documentation":"

    The unique identifier of the Exascale storage vault to update.

    " + }, + "additionalFlashCacheInPercent":{ + "shape":"UpdateExascaleDbStorageVaultInputAdditionalFlashCacheInPercentInteger", + "documentation":"

    The additional flash cache percentage for the Exascale storage vault.

    " + }, + "autoscaleLimitInGBs":{ + "shape":"UpdateExascaleDbStorageVaultInputAutoscaleLimitInGBsInteger", + "documentation":"

    The autoscale limit in gigabytes (GB) for the Exascale storage vault.

    " + }, + "description":{ + "shape":"UpdateExascaleDbStorageVaultInputDescriptionString", + "documentation":"

    A new description for the Exascale storage vault.

    " + }, + "displayName":{ + "shape":"ResourceDisplayName", + "documentation":"

    A new user-friendly name for the Exascale storage vault.

    " + }, + "highCapacityDatabaseStorageTotalSizeInGBs":{ + "shape":"UpdateExascaleDbStorageVaultInputHighCapacityDatabaseStorageTotalSizeInGBsInteger", + "documentation":"

    The total size of the high-capacity database storage, in gigabytes (GB), for the Exascale storage vault.

    " + }, + "isAutoscaleEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether autoscaling is enabled for the Exascale storage vault.

    " + } + } + }, + "UpdateExascaleDbStorageVaultInputAdditionalFlashCacheInPercentInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "UpdateExascaleDbStorageVaultInputAutoscaleLimitInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "UpdateExascaleDbStorageVaultInputDescriptionString":{ + "type":"string", + "max":400, + "min":1 + }, + "UpdateExascaleDbStorageVaultInputHighCapacityDatabaseStorageTotalSizeInGBsInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "UpdateExascaleDbStorageVaultOutput":{ + "type":"structure", + "required":["exascaleDbStorageVaultId"], + "members":{ + "displayName":{ + "shape":"String", + "documentation":"

    The user-friendly name for the Exascale storage vault.

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Exascale storage vault.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    Additional information about the status of the Exascale storage vault.

    " + }, + "exascaleDbStorageVaultId":{ + "shape":"String", + "documentation":"

    The unique identifier of the Exascale storage vault.

    " + } + } + }, "UpdateOdbNetworkInput":{ "type":"structure", "required":["odbNetworkId"], @@ -9306,6 +11251,50 @@ "type":"string", "enum":["SERVICENETWORK"] }, + "WalletPasswordSource":{ + "type":"string", + "documentation":"

    The source of the password for an Autonomous Database wallet.

    ", + "enum":[ + "CUSTOMER_MANAGED_AWS_SECRET", + "API_REQUEST_PARAMETER" + ] + }, + "WalletPasswordSourceConfiguration":{ + "type":"structure", + "members":{ + "customerManagedAwsSecret":{ + "shape":"CustomerManagedAwsSecretConfiguration", + "documentation":"

    The configuration for a customer-managed Amazon Web Services Secrets Manager secret used as the wallet password source.

    " + } + }, + "documentation":"

    The configuration of the wallet password source. This is a union, so only one of the following members can be specified.

    ", + "union":true + }, + "WalletPasswordSourceConfigurationInput":{ + "type":"structure", + "members":{ + "customerManagedAwsSecret":{ + "shape":"CustomerManagedAwsSecretConfigurationInput", + "documentation":"

    The configuration for using a customer-managed Amazon Web Services Secrets Manager secret as the wallet password source.

    " + } + }, + "documentation":"

    The input configuration for the wallet password source. This is a union, so only one of the following members can be specified.

    ", + "union":true + }, + "WalletPasswordSourceSummary":{ + "type":"structure", + "members":{ + "passwordSource":{ + "shape":"WalletPasswordSource", + "documentation":"

    The source of the password for the Autonomous Database wallet.

    " + }, + "passwordSourceConfiguration":{ + "shape":"WalletPasswordSourceConfiguration", + "documentation":"

    The configuration of the password source for the Autonomous Database wallet.

    " + } + }, + "documentation":"

    A summary of the password source configuration for an Autonomous Database wallet.

    " + }, "WalletType":{ "type":"string", "enum":[ diff --git a/services/omics/pom.xml b/services/omics/pom.xml index bd1ed1bd6f51..6e80fe097aba 100644 --- a/services/omics/pom.xml +++ b/services/omics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT omics AWS Java SDK :: Services :: Omics diff --git a/services/omics/src/main/resources/codegen-resources/customization.config b/services/omics/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/omics/src/main/resources/codegen-resources/customization.config +++ b/services/omics/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/omics/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/omics/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f759d26dc7be --- /dev/null +++ b/services/omics/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://omics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://omics-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://omics.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://omics.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/omics/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/omics/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ce4e8f65334e..000000000000 --- a/services/omics/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://omics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://omics-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://omics.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://omics.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/omics/src/main/resources/codegen-resources/service-2.json b/services/omics/src/main/resources/codegen-resources/service-2.json index 1e9e358d849b..c32320e2eb92 100644 --- a/services/omics/src/main/resources/codegen-resources/service-2.json +++ b/services/omics/src/main/resources/codegen-resources/service-2.json @@ -371,7 +371,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Creates a cross-account shared resource. The resource owner makes an offer to share the resource with the principal subscriber (an AWS user with a different account than the resource owner).

    The following resources support cross-account sharing:

    • HealthOmics variant stores

    • HealthOmics annotation stores

    • Private workflows

    ", + "documentation":"

    Creates a cross-account shared resource. The resource owner makes an offer to share the resource with the principal subscriber (an Amazon Web Services user with a different account than the resource owner).

    The following resources support cross-account sharing:

    • HealthOmics variant stores

    • HealthOmics annotation stores

    • Private workflows

    ", "endpoint":{"hostPrefix":"analytics-"} }, "CreateVariantStore":{ @@ -500,7 +500,7 @@ {"shape":"AccessDeniedException"}, {"shape":"RequestTimeoutException"} ], - "documentation":"

    Deletes a run batch resource and its associated metadata. This operation does not delete the individual workflow runs. To delete the runs, call DeleteRunBatch before calling DeleteBatch.

    DeleteBatch requires the batch to be in a terminal state: PROCESSED, FAILED, CANCELLED, or RUNS_DELETED. After DeleteBatch completes, the batch metadata is no longer accessible. You cannot call GetBatch, ListRunsInBatch, DeleteRunBatch, or CancelRunBatch on a deleted batch.

    ", + "documentation":"

    Deletes a run batch resource and its associated metadata. This operation does not delete the individual workflow runs. To delete the runs, call DeleteRunBatch before calling DeleteBatch.

    DeleteBatch requires the batch to be in a terminal state: PROCESSED, FAILED, CANCELLED, RUNS_DELETE_FAILED, or RUNS_DELETED. After DeleteBatch completes, the batch metadata is no longer accessible. You cannot call GetBatch, ListRunsInBatch, DeleteRunBatch, or CancelRunBatch on a deleted batch.

    ", "endpoint":{"hostPrefix":"workflows-"}, "idempotent":true }, @@ -1949,7 +1949,7 @@ {"shape":"AccessDeniedException"}, {"shape":"RequestTimeoutException"} ], - "documentation":"

    Activates an archived read set and returns its metadata in a JSON formatted output. AWS HealthOmics automatically archives unused read sets after 30 days. To monitor the status of your read set activation job, use the GetReadSetActivationJob operation.

    To learn more, see Activating read sets in the Amazon Web Services HealthOmics User Guide.

    ", + "documentation":"

    Activates an archived read set and returns its metadata in a JSON formatted output. Amazon Web Services HealthOmics automatically archives unused read sets after 30 days. To monitor the status of your read set activation job, use the GetReadSetActivationJob operation.

    To learn more, see Activating read sets in the Amazon Web Services HealthOmics User Guide.

    ", "endpoint":{"hostPrefix":"control-storage-"} }, "StartReadSetExportJob":{ @@ -2863,6 +2863,7 @@ "FAILED", "PROCESSED", "RUNS_DELETING", + "RUNS_DELETE_FAILED", "RUNS_DELETED" ], "max":64, @@ -4178,7 +4179,7 @@ }, "roleArn":{ "shape":"RunRoleArn", - "documentation":"

    The IAM role ARN that grants HealthOmics permissions to access required AWS resources such as Amazon S3 and CloudWatch. The role must have the same permissions required for individual StartRun calls.

    " + "documentation":"

    The IAM role ARN that grants HealthOmics permissions to access required Amazon Web Services resources such as Amazon S3 and CloudWatch. The role must have the same permissions required for individual StartRun calls.

    " }, "name":{ "shape":"RunName", @@ -4218,7 +4219,7 @@ }, "runTags":{ "shape":"TagMap", - "documentation":"

    AWS tags to associate with each workflow run. Merged with per-run runTags; run-specific values take precedence when keys overlap.

    " + "documentation":"

    Amazon Web Services tags to associate with each workflow run. Merged with per-run runTags; run-specific values take precedence when keys overlap.

    " }, "retentionMode":{ "shape":"RunRetentionMode", @@ -4230,11 +4231,11 @@ }, "workflowOwnerId":{ "shape":"WorkflowOwnerId", - "documentation":"

    The AWS account ID of the workflow owner, used for cross-account workflow sharing.

    " + "documentation":"

    The Amazon Web Services account ID of the workflow owner, used for cross-account workflow sharing.

    " }, "outputBucketOwnerId":{ "shape":"AwsAccountId", - "documentation":"

    The expected AWS account ID of the owner of the output S3 bucket. Can be overridden per run.

    " + "documentation":"

    The expected Amazon Web Services account ID of the owner of the output S3 bucket. Can be overridden per run.

    " }, "workflowVersionName":{ "shape":"WorkflowVersionName", @@ -4248,6 +4249,10 @@ "shape":"ConfigurationName", "documentation":"

    Optional configuration name to use for the workflow run.

    " }, + "sessionPolicy":{ + "shape":"SessionPolicy", + "documentation":"

    Optional inline policy json for scoping down permissions via a session policy on the IAM role provided in the roleArn parameter.

    " + }, "engineSettings":{ "shape":"EngineSettings", "documentation":"

    Engine-specific settings for the workflow run. Use this field to specify configuration options that are specific to the workflow engine (for example, Nextflow profiles).

    " @@ -5215,11 +5220,11 @@ }, "status":{ "shape":"BatchStatus", - "documentation":"

    The current status of the run batch. Possible values: CREATING (initial setup), PENDING (ready to submit runs), SUBMITTING (submitting runs), INPROGRESS (runs executing), STOPPING (cancellation in progress), PROCESSED (all runs completed), CANCELLED (batch cancelled), FAILED (batch failed), RUNS_DELETING (deleting runs), RUNS_DELETED (runs deleted).

    " + "documentation":"

    The current status of the run batch. Possible values: CREATING (initial setup), PENDING (ready to submit runs), SUBMITTING (submitting runs), INPROGRESS (runs executing), STOPPING (cancellation in progress), PROCESSED (all runs completed), CANCELLED (batch cancelled), FAILED (batch failed), RUNS_DELETING (deleting runs), RUNS_DELETE_FAILED (run deletion failed for some or all runs), RUNS_DELETED (runs deleted).

    " }, "tags":{ "shape":"TagMap", - "documentation":"

    AWS tags associated with the run batch.

    " + "documentation":"

    Amazon Web Services tags associated with the run batch.

    " }, "totalRuns":{ "shape":"Integer", @@ -6223,6 +6228,10 @@ "engineSettings":{ "shape":"EngineSettings", "documentation":"

    The engine-specific settings for the workflow run.

    " + }, + "sessionPolicy":{ + "shape":"SessionPolicy", + "documentation":"

    Inline policy json for scoping down permissions via a session policy on the IAM role.

    " } } }, @@ -6325,6 +6334,10 @@ "imageDetails":{ "shape":"ImageDetails", "documentation":"

    Details about the container image that this task uses.

    " + }, + "uuid":{ + "shape":"TaskUuid", + "documentation":"

    The universally unique identifier (UUID) for the workflow task.

    " } } }, @@ -7214,11 +7227,11 @@ }, "outputBucketOwnerId":{ "shape":"AwsAccountId", - "documentation":"

    The expected AWS account ID of the owner of the output S3 bucket for this run.

    " + "documentation":"

    The expected Amazon Web Services account ID of the owner of the output S3 bucket for this run.

    " }, "runTags":{ "shape":"TagMap", - "documentation":"

    Per-run AWS tags. Merged with defaultRunSetting.runTags; values in this object take precedence when keys overlap.

    " + "documentation":"

    Per-run Amazon Web Services tags. Merged with defaultRunSetting.runTags; values in this object take precedence when keys overlap.

    " }, "engineSettings":{ "shape":"EngineSettings", @@ -10310,6 +10323,12 @@ }, "exception":true }, + "SessionPolicy":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"[\\p{L}\\p{M}\\p{Z}\\p{S}\\p{N}\\p{P}\\t\\n\\r]+" + }, "ShareDetails":{ "type":"structure", "members":{ @@ -10859,7 +10878,7 @@ }, "tags":{ "shape":"TagMap", - "documentation":"

    AWS tags to associate with the batch resource. These tags are not inherited by individual runs. To tag individual runs, use defaultRunSetting.runTags.

    " + "documentation":"

    Amazon Web Services tags to associate with the batch resource. These tags are not inherited by individual runs. To tag individual runs, use defaultRunSetting.runTags.

    " }, "defaultRunSetting":{ "shape":"DefaultRunSetting", @@ -10892,7 +10911,7 @@ }, "tags":{ "shape":"TagMap", - "documentation":"

    AWS tags associated with the run batch.

    " + "documentation":"

    Amazon Web Services tags associated with the run batch.

    " } } }, @@ -10918,7 +10937,7 @@ }, "roleArn":{ "shape":"RunRoleArn", - "documentation":"

    A service role for the run. The roleArn requires access to Amazon Web Services HealthOmics, S3, Cloudwatch logs, and EC2. An example roleArn is arn:aws:iam::123456789012:role/omics-service-role-serviceRole-W8O1XMPL7QZ. In this example, the AWS account ID is 123456789012 and the role name is omics-service-role-serviceRole-W8O1XMPL7QZ.

    " + "documentation":"

    A service role for the run. The roleArn requires access to Amazon Web Services HealthOmics, S3, Cloudwatch logs, and EC2. An example roleArn is arn:aws:iam::123456789012:role/omics-service-role-serviceRole-W8O1XMPL7QZ. In this example, the Amazon Web Services account ID is 123456789012 and the role name is omics-service-role-serviceRole-W8O1XMPL7QZ.

    " }, "name":{ "shape":"RunName", @@ -10993,6 +11012,10 @@ "shape":"ConfigurationName", "documentation":"

    Optional configuration name to use for the workflow run.

    " }, + "sessionPolicy":{ + "shape":"SessionPolicy", + "documentation":"

    Optional inline policy json for scoping down permissions via a session policy on the IAM role provided in the roleArn parameter.

    " + }, "engineSettings":{ "shape":"EngineSettings", "documentation":"

    Engine-specific settings for the workflow run. Use this field to specify configuration options that are specific to the workflow engine (for example, Nextflow profiles).

    " @@ -11367,6 +11390,10 @@ "instanceType":{ "shape":"TaskInstanceType", "documentation":"

    The instance type for a task.

    " + }, + "uuid":{ + "shape":"TaskUuid", + "documentation":"

    The universally unique identifier (UUID) for the workflow task.

    " } }, "documentation":"

    A workflow run task.

    " @@ -11423,6 +11450,12 @@ "type":"timestamp", "timestampFormat":"iso8601" }, + "TaskUuid":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\p{L}||\\p{M}||\\p{Z}||\\p{S}||\\p{N}||\\p{P}]+" + }, "ThrottlingException":{ "type":"structure", "required":["message"], @@ -12073,7 +12106,7 @@ "members":{ "message":{"shape":"String"} }, - "documentation":"

    The input fails to satisfy the constraints specified by an AWS service.

    ", + "documentation":"

    The input fails to satisfy the constraints specified by an Amazon Web Services service.

    ", "error":{ "httpStatusCode":400, "senderFault":true diff --git a/services/opensearch/pom.xml b/services/opensearch/pom.xml index 04f15632cbcd..b21eb6c7afd2 100644 --- a/services/opensearch/pom.xml +++ b/services/opensearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT opensearch AWS Java SDK :: Services :: Open Search diff --git a/services/opensearch/src/main/resources/codegen-resources/customization.config b/services/opensearch/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/opensearch/src/main/resources/codegen-resources/customization.config +++ b/services/opensearch/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/opensearch/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/opensearch/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e447bfdb707f --- /dev/null +++ b/services/opensearch/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,251 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aos.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aos.{Region}.api.amazonwebservices.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://es.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 16, + "nodes": "/////wAAAAH/////AAAAAAAAAA8AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAsAAAAGAAAABAAAAAcF9eEMAAAABQAAAAgF9eELAAAABwX14QgAAAAJAAAACAX14QkAAAAKAAAACQX14QgF9eEKAAAABAAAAA0AAAAMAAAABgX14QYF9eEHAAAABQAAAA4F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAQAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/opensearch/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/opensearch/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b63207e77eac..000000000000 --- a/services/opensearch/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://es-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://es-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.amazonwebservices.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://aos.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://es.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://es.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/opensearch/src/main/resources/codegen-resources/service-2.json b/services/opensearch/src/main/resources/codegen-resources/service-2.json index a57075a545f8..66f18d2feeb3 100644 --- a/services/opensearch/src/main/resources/codegen-resources/service-2.json +++ b/services/opensearch/src/main/resources/codegen-resources/service-2.json @@ -132,7 +132,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"DisabledOperationException"} ], - "documentation":"

    Attaches a data source to an OpenSearch application. The data source can be an Amazon OpenSearch Service domain or an Amazon OpenSearch Serverless collection. If both the application and data source are in the ACTIVE state, the attachment completes immediately and returns a status of ATTACHED. If either resource is not yet active, the operation stores the request and returns a status of PENDING. A background process then completes the attachment when both resources become active. Pending attachments that are not completed within 24 hours are marked as FAILED. This operation is idempotent. If a data source is already attached or pending for the same application, the existing attachment is returned.

    " + "documentation":"

    Attaches a data source to an OpenSearch application. The data source must be an Amazon OpenSearch Service domain. If both the application and the data source are active, the attachment completes immediately with a status of ATTACHED. Otherwise, the operation returns PENDING and completes the attachment automatically once both become active. If the attachment cannot be completed, its status becomes FAILED. This operation is idempotent: If the data source is already attached or pending, the operation returns the existing attachment.

    " }, "AuthorizeVpcEndpointAccess":{ "name":"AuthorizeVpcEndpointAccess", diff --git a/services/opensearchserverless/pom.xml b/services/opensearchserverless/pom.xml index 2c6a9ae02448..ac7b4fd8a1ec 100644 --- a/services/opensearchserverless/pom.xml +++ b/services/opensearchserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT opensearchserverless AWS Java SDK :: Services :: Open Search Serverless diff --git a/services/opensearchserverless/src/main/resources/codegen-resources/customization.config b/services/opensearchserverless/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/opensearchserverless/src/main/resources/codegen-resources/customization.config +++ b/services/opensearchserverless/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fc0afb346761 --- /dev/null +++ b/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aoss-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aoss-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aoss.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://aoss.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ad54d31593ad..000000000000 --- a/services/opensearchserverless/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aoss-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aoss-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aoss.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://aoss.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/organizations/pom.xml b/services/organizations/pom.xml index 085e0286bb3f..3fb5683eeba0 100644 --- a/services/organizations/pom.xml +++ b/services/organizations/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT organizations AWS Java SDK :: Services :: AWS Organizations diff --git a/services/organizations/src/main/resources/codegen-resources/customization.config b/services/organizations/src/main/resources/codegen-resources/customization.config index cf0472a9f85f..c2122a67f377 100644 --- a/services/organizations/src/main/resources/codegen-resources/customization.config +++ b/services/organizations/src/main/resources/codegen-resources/customization.config @@ -11,6 +11,5 @@ "listHandshakesForAccount", "listRoots", "listAWSServiceAccessForOrganization" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/organizations/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/organizations/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7a756f8e0ebd --- /dev/null +++ b/services/organizations/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,397 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations-fips.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.cn-northwest-1.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.us-gov-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.us-isof-south-1.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "organizations", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://organizations.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 21, + "nodes": "/////wAAAAH/////AAAAAAAAABQAAAADAAAAAQAAAAQF9eESAAAAAgAAAAUF9eESAAAAAwAAAA4AAAAGAAAABAAAAA0AAAAHAAAABgX14QQAAAAIAAAABwX14QYAAAAJAAAACAX14QcAAAAKAAAACQX14QgAAAALAAAACwX14QkAAAAMAAAADAX14QoF9eERAAAABQX14Q8F9eEQAAAABAAAABIAAAAPAAAABgX14QUAAAAQAAAACAX14QcAAAARAAAACgX14Q0F9eEOAAAABQAAABMF9eEMAAAACgX14QsF9eEMAAAAAwX14QEAAAAVAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/organizations/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/organizations/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 872f98d208e1..000000000000 --- a/services/organizations/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,722 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations-fips.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.cn-northwest-1.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://organizations.us-isof-south-1.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "organizations", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://organizations-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://organizations-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://organizations.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://organizations.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/organizations/src/main/resources/codegen-resources/service-2.json b/services/organizations/src/main/resources/codegen-resources/service-2.json index a92e350f11f8..8aa8024bf93c 100644 --- a/services/organizations/src/main/resources/codegen-resources/service-2.json +++ b/services/organizations/src/main/resources/codegen-resources/service-2.json @@ -38,7 +38,7 @@ {"shape":"ConstraintViolationException"}, {"shape":"MasterCannotLeaveOrganizationException"} ], - "documentation":"

    Accepts a handshake by sending an ACCEPTED response to the sender. You can view accepted handshakes in API responses for 30 days before they are deleted.

    Only the management account can accept the following handshakes:

    • Enable all features final confirmation (APPROVE_ALL_FEATURES)

    • Billing transfer (TRANSFER_RESPONSIBILITY)

    For more information, see Enabling all features and Responding to a billing transfer invitation in the Organizations User Guide.

    Only a member account can accept the following handshakes:

    • Invitation to join (INVITE)

    • Approve all features request (ENABLE_ALL_FEATURES)

    For more information, see Responding to invitations and Enabling all features in the Organizations User Guide.

    When a handshake is accepted, Organizations logs membership events in CloudTrail, available only in the management account's event history. If the account was standalone and joined a new organization, an AccountJoinedOrganization event is logged with joinedMethod:Invited and joinedTime fields. If the account departed one organization and joined another, both an AccountDepartedOrganization event with departedMethod:Left and departedTime and an AccountJoinedOrganization event with joinedMethod:Invited and joinedTime are logged in their respective management accounts.

    " + "documentation":"

    Accepts a handshake by sending an ACCEPTED response to the sender. You can view accepted handshakes in API responses for 30 days before they are deleted.

    Only the management account can accept the following handshakes:

    • Enable all features final confirmation (APPROVE_ALL_FEATURES)

    • Billing transfer (TRANSFER_RESPONSIBILITY)

    For more information, see Enabling all features and Responding to a billing transfer invitation in the Organizations User Guide.

    Only a member account can accept the following handshakes:

    • Invitation to join (INVITE)

    • Approve all features request (ENABLE_ALL_FEATURES)

    For more information, see Responding to invitations and Enabling all features in the Organizations User Guide.

    When a handshake is accepted, Organizations logs membership events in CloudTrail, available only in the management account's event history. If the account was standalone and joined a new organization, an AccountJoinedOrganization event is logged with joinedMethod:INVITED and joinedTime fields. If the account departed one organization and joined another, both an AccountDepartedOrganization event with departureMethod:LEFT and departureTime and an AccountJoinedOrganization event with joinedMethod:INVITED and joinedTime are logged in their respective management accounts.

    When a billing transfer (TRANSFER_RESPONSIBILITY) handshake is accepted, Organizations publishes a ResponsibilityTransferAccepted service event to CloudTrail. Each affected account receives this event, including upstream participants such as distributors in a chained transfer. For an example log entry, see Example log entries: AcceptResponsibilityTransfer in the Organizations User Guide.

    " }, "AttachPolicy":{ "name":"AttachPolicy", @@ -104,7 +104,7 @@ {"shape":"TooManyRequestsException"}, {"shape":"UnsupportedAPIEndpointException"} ], - "documentation":"

    Closes an Amazon Web Services member account within an organization. You can close an account when all features are enabled . You can't close the management account with this API. This is an asynchronous request that Amazon Web Services performs in the background. Because CloseAccount operates asynchronously, it can return a successful completion message even though account closure might still be in progress. You need to wait a few minutes before the account is fully closed. To check the status of the request, do one of the following:

    • Use the AccountId that you sent in the CloseAccount request to provide as a parameter to the DescribeAccount operation.

      While the close account request is in progress, Account status will indicate PENDING_CLOSURE. When the close account request completes, the status will change to SUSPENDED.

    • Check the CloudTrail log for the CloseAccountResult event that gets published after the account closes successfully. For information on using CloudTrail with Organizations, see Logging and monitoring in Organizations in the Organizations User Guide.

    • Resources remaining within the account after closing will be automatically deleted after 90 days. During this 90-day period, the resources won't be available unless you contact Amazon Web Services Support to reopen the account. After 90 days, you can't reopen an account. You might still receive a bill after account closure.

    • Within a rolling 30 day period you can close the higher of either 250 or 20% of the member accounts in your organization, up to a maximum of 1,000. This quota is not bound by a calendar month, but starts when you close an account. After you reach this limit, you can't close additional accounts. For more information, see Closing a member account in your organization and Quotas for Organizations in the Organizations User Guide.

    • To reinstate a closed account, contact Amazon Web Services Support within the 90-day grace period while the account is in SUSPENDED status.

    • If the Amazon Web Services account you attempt to close is linked to an Amazon Web Services GovCloud (US) account, the CloseAccount request will close both accounts. To learn important pre-closure details, see Closing an Amazon Web Services GovCloud (US) account in the Amazon Web Services GovCloud User Guide.

    After the permanent termination of the account after the 90-day waiting period, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departedMethod:Cleaned and departedTime. This event is available only in the management account's event history.

    " + "documentation":"

    Closes an Amazon Web Services member account within an organization. You can close an account when all features are enabled . You can't close the management account with this API. This is an asynchronous request that Amazon Web Services performs in the background. Because CloseAccount operates asynchronously, it can return a successful completion message even though account closure might still be in progress. You need to wait a few minutes before the account is fully closed. To check the status of the request, do one of the following:

    • Use the AccountId that you sent in the CloseAccount request to provide as a parameter to the DescribeAccount operation.

      While the close account request is in progress, Account status will indicate PENDING_CLOSURE. When the close account request completes, the status will change to SUSPENDED.

    • Check the CloudTrail log for the CloseAccountResult event that gets published after the account closes successfully. For information on using CloudTrail with Organizations, see Logging and monitoring in Organizations in the Organizations User Guide.

    • Resources remaining within the account after closing will be automatically deleted after 90 days. During this 90-day period, the resources won't be available unless you contact Amazon Web Services Support to reopen the account. After 90 days, you can't reopen an account. You might still receive a bill after account closure.

    • Within a rolling 30 day period you can close the higher of either 250 or 20% of the member accounts in your organization, up to a maximum of 1,000. This quota is not bound by a calendar month, but starts when you close an account. After you reach this limit, you can't close additional accounts. For more information, see Closing a member account in your organization and Quotas for Organizations in the Organizations User Guide.

    • To reinstate a closed account, contact Amazon Web Services Support within the 90-day grace period while the account is in SUSPENDED status.

    • If the Amazon Web Services account you attempt to close is linked to an Amazon Web Services GovCloud (US) account, the CloseAccount request will close both accounts. To learn important pre-closure details, see Closing an Amazon Web Services GovCloud (US) account in the Amazon Web Services GovCloud User Guide.

    After the permanent termination of the account after the 90-day waiting period, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departureMethod:CLEANED and departureTime. This event is available only in the management account's event history.

    " }, "CreateAccount":{ "name":"CreateAccount", @@ -146,7 +146,7 @@ {"shape":"TooManyRequestsException"}, {"shape":"UnsupportedAPIEndpointException"} ], - "documentation":"

    This action is available if all of the following are true:

    • You're authorized to create accounts in the Amazon Web Services GovCloud (US) Region. For more information on the Amazon Web Services GovCloud (US) Region, see the Amazon Web Services GovCloud User Guide.

    • You already have an account in the Amazon Web Services GovCloud (US) Region that is paired with a management account of an organization in the commercial Region.

    • You call this action from the management account of your organization in the commercial Region.

    • You have the organizations:CreateGovCloudAccount permission.

    Organizations automatically creates the required service-linked role named AWSServiceRoleForOrganizations. For more information, see Organizations and service-linked roles in the Organizations User Guide.

    Amazon Web Services automatically enables CloudTrail for Amazon Web Services GovCloud (US) accounts, but you should also do the following:

    • Verify that CloudTrail is enabled to store logs.

    • Create an Amazon S3 bucket for CloudTrail log storage.

      For more information, see Verifying CloudTrail Is Enabled in the Amazon Web Services GovCloud User Guide.

    If the request includes tags, then the requester must have the organizations:TagResource permission. The tags are attached to the commercial account associated with the GovCloud account, rather than the GovCloud account itself. To add tags to the GovCloud account, call the TagResource operation in the GovCloud Region after the new GovCloud account exists.

    You call this action from the management account of your organization in the commercial Region to create a standalone Amazon Web Services account in the Amazon Web Services GovCloud (US) Region. After the account is created, the management account of an organization in the Amazon Web Services GovCloud (US) Region can invite it to that organization. For more information on inviting standalone accounts in the Amazon Web Services GovCloud (US) to join an organization, see Organizations in the Amazon Web Services GovCloud User Guide.

    Calling CreateGovCloudAccount is an asynchronous request that Amazon Web Services performs in the background. Because CreateGovCloudAccount operates asynchronously, it can return a successful completion message even though account initialization might still be in progress. You might need to wait a few minutes before you can successfully access the account. To check the status of the request, do one of the following:

    Additionally, the AccountJoinedOrganization event is logged in CloudTrail and is available only in the management account's event history only for the linked commercial account. This event includes joinedMethod:Created and joinedTime fields to provide context on how and when the account joined the organization.

    When you call the CreateGovCloudAccount action, you create two accounts: a standalone account in the Amazon Web Services GovCloud (US) Region and an associated account in the commercial Region for billing and support purposes. The account in the commercial Region is automatically a member of the organization whose credentials made the request. Both accounts are associated with the same email address.

    A role is created in the new account in the commercial Region that allows the management account in the organization in the commercial Region to assume it. An Amazon Web Services GovCloud (US) account is then created and associated with the commercial account that you just created. A role is also created in the new Amazon Web Services GovCloud (US) account that can be assumed by the Amazon Web Services GovCloud (US) account that is associated with the management account of the commercial organization. For more information and to view a diagram that explains how account access works, see Organizations in the Amazon Web Services GovCloud User Guide.

    For more information about creating accounts, see Creating a member account in your organization in the Organizations User Guide.

    • When you create an account in an organization using the Organizations console, API, or CLI commands, the information required for the account to operate as a standalone account is not automatically collected. This includes a payment method and signing the end user license agreement (EULA). If you must remove an account from your organization later, you can do so only after you provide the missing information. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • If you get an exception that indicates that you exceeded your account limits for the organization, contact Amazon Web Services Support.

    • If you get an exception that indicates that the operation failed because your organization is still initializing, wait one hour and then try again. If the error persists, contact Amazon Web Services Support.

    • Using CreateGovCloudAccount to create multiple temporary accounts isn't recommended. You can only close an account from the Amazon Web Services Billing and Cost Management console, and you must be signed in as the root user. For information on the requirements and process for closing an account, see Closing a member account in your organization in the Organizations User Guide.

    When you create a member account with this operation, you can choose whether to create the account with the IAM User and Role Access to Billing Information switch enabled. If you enable it, IAM users and roles that have appropriate permissions can view billing information for the account. If you disable it, only the account root user can access billing information. For information about how to disable this switch for an account, see Granting access to your billing information and tools.

    " + "documentation":"

    This action is available if all of the following are true:

    • You're authorized to create accounts in the Amazon Web Services GovCloud (US) Region. For more information on the Amazon Web Services GovCloud (US) Region, see the Amazon Web Services GovCloud User Guide.

    • You already have an account in the Amazon Web Services GovCloud (US) Region that is paired with a management account of an organization in the commercial Region.

    • You call this action from the management account of your organization in the commercial Region.

    • You have the organizations:CreateGovCloudAccount permission.

    Organizations automatically creates the required service-linked role named AWSServiceRoleForOrganizations. For more information, see Organizations and service-linked roles in the Organizations User Guide.

    Amazon Web Services automatically enables CloudTrail for Amazon Web Services GovCloud (US) accounts, but you should also do the following:

    • Verify that CloudTrail is enabled to store logs.

    • Create an Amazon S3 bucket for CloudTrail log storage.

      For more information, see Verifying CloudTrail Is Enabled in the Amazon Web Services GovCloud User Guide.

    If the request includes tags, then the requester must have the organizations:TagResource permission. The tags are attached to the commercial account associated with the GovCloud account, rather than the GovCloud account itself. To add tags to the GovCloud account, call the TagResource operation in the GovCloud Region after the new GovCloud account exists.

    You call this action from the management account of your organization in the commercial Region to create a standalone Amazon Web Services account in the Amazon Web Services GovCloud (US) Region. After the account is created, the management account of an organization in the Amazon Web Services GovCloud (US) Region can invite it to that organization. For more information on inviting standalone accounts in the Amazon Web Services GovCloud (US) to join an organization, see Organizations in the Amazon Web Services GovCloud User Guide.

    Calling CreateGovCloudAccount is an asynchronous request that Amazon Web Services performs in the background. Because CreateGovCloudAccount operates asynchronously, it can return a successful completion message even though account initialization might still be in progress. You might need to wait a few minutes before you can successfully access the account. To check the status of the request, do one of the following:

    Additionally, the AccountJoinedOrganization event is logged in CloudTrail and is available only in the management account's event history only for the linked commercial account. This event includes joinedMethod:Created and joinedTime fields to provide context on how and when the account joined the organization.

    When you call the CreateGovCloudAccount action, you create two accounts: a standalone account in the Amazon Web Services GovCloud (US) Region and an associated account in the commercial Region for billing and support purposes. The account in the commercial Region is automatically a member of the organization whose credentials made the request. Both accounts are associated with the same email address.

    A role is created in the new account in the commercial Region that allows the management account in the organization in the commercial Region to assume it. An Amazon Web Services GovCloud (US) account is then created and associated with the commercial account that you just created. A role is also created in the new Amazon Web Services GovCloud (US) account that can be assumed by the Amazon Web Services GovCloud (US) account that is associated with the management account of the commercial organization. For more information and to view a diagram that explains how account access works, see Organizations in the Amazon Web Services GovCloud User Guide.

    For more information about creating accounts, see Creating a member account in your organization in the Organizations User Guide.

    • When you create an account in an organization using the Organizations console, API, or CLI commands, the information required for the account to operate as a standalone account is not automatically collected. This includes a payment method and signing the end user license agreement (EULA). If you must remove an account from your organization later, you can do so only after you provide the missing information. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • If you get an exception that indicates that you exceeded your account limits for the organization, contact Amazon Web Services Support.

    • If you get an exception that indicates that the operation failed because your organization is still initializing, wait one hour and then try again. If the error persists, contact Amazon Web Services Support.

    • Using CreateGovCloudAccount to create multiple temporary accounts isn't recommended. You can only close an account from the Amazon Web Services Billing and Cost Management console, and you must be signed in as the root user. For information on the requirements and process for closing an account, see Closing a member account in your organization in the Organizations User Guide.

    When you create a member account with this operation, you can choose whether to create the account with the IAM User and Role Access to Billing Information switch enabled. If you enable it, IAM users and roles that have appropriate permissions can view billing information for the account. If you disable it, only the account root user can access billing information. For information about how to disable this switch for an account, see Granting access to your billing information and tools.

    " }, "CreateOrganization":{ "name":"CreateOrganization", @@ -166,7 +166,7 @@ {"shape":"TooManyRequestsException"}, {"shape":"AccessDeniedForDependencyException"} ], - "documentation":"

    Creates an Amazon Web Services organization. The account whose user is calling the CreateOrganization operation automatically becomes the management account of the new organization.

    This operation must be called using credentials from the account that is to become the new organization's management account. The principal must also have the relevant IAM permissions.

    By default (or if you set the FeatureSet parameter to ALL), the new organization is created with all features enabled and service control policies automatically enabled in the root. If you instead choose to create the organization supporting only the consolidated billing features by setting the FeatureSet parameter to CONSOLIDATED_BILLING, no policy types are enabled by default and you can't use organization policies.

    The AccountJoinedOrganization event is logged in CloudTrail and is available only in the management account's event history. This event includes joinedMethod:Invited and joinedTime fields to provide context on how and when the account joined the organization.

    " + "documentation":"

    Creates an Amazon Web Services organization. The account whose user is calling the CreateOrganization operation automatically becomes the management account of the new organization.

    This operation must be called using credentials from the account that is to become the new organization's management account. The principal must also have the relevant IAM permissions.

    By default (or if you set the FeatureSet parameter to ALL), the new organization is created with all features enabled and service control policies automatically enabled in the root. If you instead choose to create the organization supporting only the consolidated billing features by setting the FeatureSet parameter to CONSOLIDATED_BILLING, no policy types are enabled by default and you can't use organization policies.

    The AccountJoinedOrganization event is logged in CloudTrail and is available only in the management account's event history. This event includes joinedMethod:INVITED and joinedTime fields to provide context on how and when the account joined the organization.

    " }, "CreateOrganizationalUnit":{ "name":"CreateOrganizationalUnit", @@ -248,7 +248,7 @@ {"shape":"ServiceException"}, {"shape":"TooManyRequestsException"} ], - "documentation":"

    Deletes the organization. You can delete an organization only by using credentials from the management account. The organization must be empty of member accounts.

    When an organization is deleted, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departedMethod:Left and departedTime. This event is available only in the management account's event history.

    " + "documentation":"

    Deletes the organization. You can delete an organization only by using credentials from the management account. The organization must be empty of member accounts.

    When an organization is deleted, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departureMethod:LEFT and departureTime. This event is available only in the management account's event history.

    " }, "DeleteOrganizationalUnit":{ "name":"DeleteOrganizationalUnit", @@ -684,7 +684,7 @@ {"shape":"ServiceException"}, {"shape":"TooManyRequestsException"} ], - "documentation":"

    Removes a member account from its parent organization. This version of the operation is performed by the account that wants to leave. To remove a member account as a user in the management account, use RemoveAccountFromOrganization instead.

    You can only call from operation from a member account.

    When an account leaves an organization, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departedMethod:Left and departedTime. This event is available only in the management account's event history.

    • The management account in an organization with all features enabled can set service control policies (SCPs) that can restrict what administrators of member accounts can do. This includes preventing them from successfully calling LeaveOrganization and leaving the organization.

    • You can leave an organization as a member account only if the account is configured with the information required to operate as a standalone account. When you create an account in an organization using the Organizations console, API, or CLI commands, the information required of standalone accounts is not automatically collected. For each account that you want to make standalone, you must perform the following steps. If any of the steps are already completed for this account, that step doesn't appear.

      • Choose a support plan

      • Provide and verify the required contact information

      • Provide a current payment method

      Amazon Web Services uses the payment method to charge for any billable (not free tier) Amazon Web Services activity that occurs while the account isn't attached to an organization. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • The account that you want to leave must not be a delegated administrator account for any Amazon Web Services service enabled for your organization. If the account is a delegated administrator, you must first change the delegated administrator account to another account that is remaining in the organization.

    • After the account leaves the organization, all tags that were attached to the account object in the organization are deleted. Amazon Web Services accounts outside of an organization do not support tags.

    • A newly created account has a waiting period before it can be removed from its organization. You must wait until at least four days after the account was created. Invited accounts aren't subject to this waiting period.

    • If you are using an organization principal to call LeaveOrganization across multiple accounts, you can only do this up to 5 accounts per second in a single organization.

    " + "documentation":"

    Removes a member account from its parent organization. This version of the operation is performed by the account that wants to leave. To remove a member account as a user in the management account, use RemoveAccountFromOrganization instead.

    You can only call from operation from a member account.

    When an account leaves an organization, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departureMethod:LEFT and departureTime. This event is available only in the management account's event history.

    • The management account in an organization with all features enabled can set service control policies (SCPs) that can restrict what administrators of member accounts can do. This includes preventing them from successfully calling LeaveOrganization and leaving the organization.

    • You can leave an organization as a member account only if the account is configured with the information required to operate as a standalone account. When you create an account in an organization using the Organizations console, API, or CLI commands, the information required of standalone accounts is not automatically collected. For each account that you want to make standalone, you must perform the following steps. If any of the steps are already completed for this account, that step doesn't appear.

      • Choose a support plan

      • Provide and verify the required contact information

      • Provide a current payment method

      Amazon Web Services uses the payment method to charge for any billable (not free tier) Amazon Web Services activity that occurs while the account isn't attached to an organization. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • The account that you want to leave must not be a delegated administrator account for any Amazon Web Services service enabled for your organization. If the account is a delegated administrator, you must first change the delegated administrator account to another account that is remaining in the organization.

    • After the account leaves the organization, all tags that were attached to the account object in the organization are deleted. Amazon Web Services accounts outside of an organization do not support tags.

    • A newly created account has a waiting period before it can be removed from its organization. You must wait until at least four days after the account was created. Invited accounts aren't subject to this waiting period.

    • If you are using an organization principal to call LeaveOrganization across multiple accounts, you can only do this up to 5 accounts per second in a single organization.

    " }, "ListAWSServiceAccessForOrganization":{ "name":"ListAWSServiceAccessForOrganization", @@ -1138,7 +1138,7 @@ {"shape":"ServiceException"}, {"shape":"TooManyRequestsException"} ], - "documentation":"

    Removes the specified account from the organization.

    The removed account becomes a standalone account that isn't a member of any organization. It's no longer subject to any policies and is responsible for its own bill payments. The organization's management account is no longer charged for any expenses accrued by the member account after it's removed from the organization.

    You can only call this operation from the management account. Member accounts can remove themselves with LeaveOrganization instead.

    When an account is removed from an organization, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departedMethod:Removed and departedTime. This event is available only in the management account's event history.

    • You can remove an account from your organization only if the account is configured with the information required to operate as a standalone account. When you create an account in an organization using the Organizations console, API, or CLI commands, the information required of standalone accounts is not automatically collected. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • The account that you want to leave must not be a delegated administrator account for any Amazon Web Services service enabled for your organization. If the account is a delegated administrator, you must first change the delegated administrator account to another account that is remaining in the organization.

    • After the account leaves the organization, all tags that were attached to the account object in the organization are deleted. Amazon Web Services accounts outside of an organization do not support tags.

    " + "documentation":"

    Removes the specified account from the organization.

    The removed account becomes a standalone account that isn't a member of any organization. It's no longer subject to any policies and is responsible for its own bill payments. The organization's management account is no longer charged for any expenses accrued by the member account after it's removed from the organization.

    You can only call this operation from the management account. Member accounts can remove themselves with LeaveOrganization instead.

    When an account is removed from an organization, Organizations logs a membership event in CloudTrail. The event is an AccountDepartedOrganization event with departureMethod:REMOVED and departureTime. This event is available only in the management account's event history.

    • You can remove an account from your organization only if the account is configured with the information required to operate as a standalone account. When you create an account in an organization using the Organizations console, API, or CLI commands, the information required of standalone accounts is not automatically collected. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • The account that you want to leave must not be a delegated administrator account for any Amazon Web Services service enabled for your organization. If the account is a delegated administrator, you must first change the delegated administrator account to another account that is remaining in the organization.

    • After the account leaves the organization, all tags that were attached to the account object in the organization are deleted. Amazon Web Services accounts outside of an organization do not support tags.

    " }, "TagResource":{ "name":"TagResource", @@ -1180,7 +1180,7 @@ {"shape":"ResponsibilityTransferAlreadyInStatusException"}, {"shape":"InvalidResponsibilityTransferTransitionException"} ], - "documentation":"

    Ends a transfer. A transfer is an arrangement between two management accounts where one account designates the other with specified responsibilities for their organization.

    " + "documentation":"

    Ends a transfer. A transfer is an arrangement between two management accounts where one account designates the other with specified responsibilities for their organization.

    When a transfer ends, Organizations publishes a ResponsibilityTransferTerminated service event to CloudTrail. Each affected account receives this event, including upstream participants such as distributors in a chained transfer. For an example log entry, see Example log entries: TerminateResponsibilityTransfer in the Organizations User Guide.

    " }, "UntagResource":{ "name":"UntagResource", @@ -1567,7 +1567,7 @@ "Message":{"shape":"ExceptionMessage"}, "Reason":{"shape":"ConstraintViolationExceptionReason"} }, - "documentation":"

    Performing this operation violates a minimum or maximum value limit. For example, attempting to remove the last service control policy (SCP) from an OU or root, inviting or creating too many accounts to the organization, or attaching too many policies to an account, OU, or root. This exception includes a reason that contains additional information about the violated limit:

    Some of the reasons in the following list might not be applicable to this specific API or operation.

    • ACCOUNT_CANNOT_LEAVE_ORGANIZATION: You attempted to remove the management account from the organization. You can't remove the management account. Instead, after you remove all member accounts, delete the organization itself.

    • ACCOUNT_CANNOT_LEAVE_WITHOUT_PHONE_VERIFICATION: You attempted to remove an account from the organization that doesn't yet have enough information to exist as a standalone account. This account requires you to first complete phone verification. Follow the steps at Removing a member account from your organization in the Organizations User Guide.

    • ACCOUNT_CREATION_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of accounts that you can create in one day.

    • ACCOUNT_CREATION_NOT_COMPLETE: Your account setup isn't complete or your account isn't fully active. You must complete the account setup before you create an organization.

    • ACTIVE_RESPONSIBILITY_TRANSFER_PROCESS: You cannot delete organization due to an ongoing responsibility transfer process. For example, a pending invitation or an in-progress transfer. To delete the organization, you must resolve the current transfer process.

    • ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on the number of accounts in an organization. If you need more accounts, contact Amazon Web Services Support to request an increase in your limit.

      Or the number of invitations that you tried to send would cause you to exceed the limit of accounts in your organization. Send fewer invitations or contact Amazon Web Services Support to request an increase in the number of accounts.

      Deleted and closed accounts still count toward your limit.

      If you get this exception when running a command immediately after creating the organization, wait one hour and try again. After an hour, if the command continues to fail with this error, contact Amazon Web Services Support.

    • ALL_FEATURES_MIGRATION_ORGANIZATION_SIZE_LIMIT_EXCEEDED: Your organization has more than 5000 accounts, and you can only use the standard migration process for organizations with less than 5000 accounts. Use the assisted migration process to enable all features mode, or create a support case for assistance if you are unable to use assisted migration.

    • CANNOT_REGISTER_SUSPENDED_ACCOUNT_AS_DELEGATED_ADMINISTRATOR: You cannot register a suspended account as a delegated administrator.

    • CANNOT_REGISTER_MASTER_AS_DELEGATED_ADMINISTRATOR: You attempted to register the management account of the organization as a delegated administrator for an Amazon Web Services service integrated with Organizations. You can designate only a member account as a delegated administrator.

    • CANNOT_CLOSE_MANAGEMENT_ACCOUNT: You attempted to close the management account. To close the management account for the organization, you must first either remove or close all member accounts in the organization. Follow standard account closure process using root credentials.​

    • CANNOT_REMOVE_DELEGATED_ADMINISTRATOR_FROM_ORG: You attempted to remove an account that is registered as a delegated administrator for a service integrated with your organization. To complete this operation, you must first deregister this account as a delegated administrator.

    • CLOSE_ACCOUNT_QUOTA_EXCEEDED: You have exceeded close account quota for the past 30 days.

    • CLOSE_ACCOUNT_REQUESTS_LIMIT_EXCEEDED: You attempted to exceed the number of accounts that you can close at a time. ​

    • CREATE_ORGANIZATION_IN_BILLING_MODE_UNSUPPORTED_REGION: To create an organization in the specified region, you must enable all features mode.

    • DELEGATED_ADMINISTRATOR_EXISTS_FOR_THIS_SERVICE: You attempted to register an Amazon Web Services account as a delegated administrator for an Amazon Web Services service that already has a delegated administrator. To complete this operation, you must first deregister any existing delegated administrators for this service.

    • EMAIL_VERIFICATION_CODE_EXPIRED: The email verification code is only valid for a limited period of time. You must resubmit the request and generate a new verification code.

    • HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of handshakes that you can send in one day.

    • INVALID_PAYMENT_INSTRUMENT: You cannot remove an account because no supported payment method is associated with the account. Amazon Web Services does not support cards issued by financial institutions in Russia or Belarus. For more information, see Managing your Amazon Web Services payments.

    • MASTER_ACCOUNT_ADDRESS_DOES_NOT_MATCH_MARKETPLACE: To create an account in this organization, you first must migrate the organization's management account to the marketplace that corresponds to the management account's address. All accounts in an organization must be associated with the same marketplace.

    • MASTER_ACCOUNT_MISSING_BUSINESS_LICENSE: Applies only to the Amazon Web Services Regions in China. To create an organization, the master must have a valid business license. For more information, contact customer support.

    • MASTER_ACCOUNT_MISSING_CONTACT_INFO: To complete this operation, you must first provide a valid contact address and phone number for the management account. Then try the operation again.

    • MASTER_ACCOUNT_NOT_GOVCLOUD_ENABLED: To complete this operation, the management account must have an associated account in the Amazon Web Services GovCloud (US-West) Region. For more information, see Organizations in the Amazon Web Services GovCloud User Guide.

    • MASTER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To create an organization with this management account, you first must associate a valid payment instrument, such as a credit card, with the account. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • MAX_DELEGATED_ADMINISTRATORS_FOR_SERVICE_LIMIT_EXCEEDED: You attempted to register more delegated administrators than allowed for the service principal.

    • MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to exceed the number of policies of a certain type that can be attached to an entity at one time.

    • MAX_TAG_LIMIT_EXCEEDED: You have exceeded the number of tags allowed on this resource.

    • MEMBER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To complete this operation with this member account, you first must associate a valid payment instrument, such as a credit card, with the account. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • MIN_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to detach a policy from an entity that would cause the entity to have fewer than the minimum number of policies of a certain type required.

    • ORGANIZATION_NOT_IN_ALL_FEATURES_MODE: You attempted to perform an operation that requires the organization to be configured to support all features. An organization that supports only consolidated billing features can't perform this operation.

    • OU_DEPTH_LIMIT_EXCEEDED: You attempted to create an OU tree that is too many levels deep.

    • OU_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of OUs that you can have in an organization.

    • POLICY_CONTENT_LIMIT_EXCEEDED: You attempted to create a policy that is larger than the maximum size.

    • POLICY_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of policies that you can have in an organization.

    • POLICY_TYPE_ENABLED_FOR_THIS_SERVICE: You attempted to disable service access before you disabled the policy type (for example, SECURITYHUB_POLICY). To complete this operation, you must first disable the policy type.

    • RESPONSIBILITY_TRANSFER_MAX_INBOUND_QUOTA_VIOLATION: You have exceeded your inbound transfers limit.

    • RESPONSIBILITY_TRANSFER_MAX_LEVEL_VIOLATION: You have exceeded the maximum length of your transfer chain.

    • RESPONSIBILITY_TRANSFER_MAX_OUTBOUND_QUOTA_VIOLATION: You have exceeded your outbound transfers limit.

    • RESPONSIBILITY_TRANSFER_MAX_TRANSFERS_QUOTA_VIOLATION: You have exceeded the maximum number of inbound transfers allowed in a transfer chain.

    • SERVICE_ACCESS_NOT_ENABLED:

      • You attempted to register a delegated administrator before you enabled service access. Call the EnableAWSServiceAccess API first.

      • You attempted to enable a policy type before you enabled service access. Call the EnableAWSServiceAccess API first.

    • TAG_POLICY_VIOLATION: You attempted to create or update a resource with tags that are not compliant with the tag policy requirements for this account.

    • TRANSFER_RESPONSIBILITY_SOURCE_DELETION_IN_PROGRESS: The source organization cannot accept this transfer invitation because it is marked for deletion.

    • TRANSFER_RESPONSIBILITY_TARGET_DELETION_IN_PROGRESS: The source organization cannot accept this transfer invitation because target organization is marked for deletion.

    • UNSUPPORTED_PRICING: Your organization has a pricing contract that is unsupported.

    • WAIT_PERIOD_ACTIVE: After you create an Amazon Web Services account, you must wait until at least four days after the account was created. Invited accounts aren't subject to this waiting period.

    ", + "documentation":"

    Performing this operation violates a minimum or maximum value limit. For example, attempting to remove the last service control policy (SCP) from an OU or root, inviting or creating too many accounts to the organization, or attaching too many policies to an account, OU, or root. This exception includes a reason that contains additional information about the violated limit:

    Some of the reasons in the following list might not be applicable to this specific API or operation.

    • ACCOUNT_CANNOT_LEAVE_ORGANIZATION: You attempted to remove the management account from the organization. You can't remove the management account. Instead, after you remove all member accounts, delete the organization itself.

    • ACCOUNT_CANNOT_LEAVE_WITHOUT_PHONE_VERIFICATION: You attempted to remove an account from the organization that doesn't yet have enough information to exist as a standalone account. This account requires you to first complete phone verification. Follow the steps at Removing a member account from your organization in the Organizations User Guide.

    • ACCOUNT_CREATION_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of accounts that can be in progress at a time.

    • ACCOUNT_CREATION_NOT_COMPLETE: Your account setup isn't complete or your account isn't fully active. You must complete the account setup before you create an organization.

    • ACCOUNT_NOT_ACTIVE_FOR_TRANSFER_RESPONSIBILITY: Your account setup isn't complete or your account isn't fully active to invite or accept a Billing Transfer invitation.

    • ACTIVE_RESPONSIBILITY_TRANSFER_PROCESS: You cannot delete organization due to an ongoing responsibility transfer process. For example, a pending invitation or an in-progress transfer. To delete the organization, you must resolve the current transfer process.

    • ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on the number of accounts in an organization. If you need more accounts, contact Amazon Web Services Support to request an increase in your limit.

      Or the number of invitations that you tried to send would cause you to exceed the limit of accounts in your organization. Send fewer invitations or contact Amazon Web Services Support to request an increase in the number of accounts.

      Deleted and closed accounts still count toward your limit.

      If you get this exception when running a command immediately after creating the organization, wait one hour and try again. After an hour, if the command continues to fail with this error, contact Amazon Web Services Support.

    • ALL_FEATURES_MIGRATION_ORGANIZATION_SIZE_LIMIT_EXCEEDED: Your organization has more than 5000 accounts, and you can only use the standard migration process for organizations with less than 5000 accounts. Use the assisted migration process to enable all features mode, or create a support case for assistance if you are unable to use assisted migration.

    • CANNOT_REGISTER_SUSPENDED_ACCOUNT_AS_DELEGATED_ADMINISTRATOR: You cannot register a suspended account as a delegated administrator.

    • CANNOT_REGISTER_MASTER_AS_DELEGATED_ADMINISTRATOR: You attempted to register the management account of the organization as a delegated administrator for an Amazon Web Services service integrated with Organizations. You can designate only a member account as a delegated administrator.

    • CANNOT_CLOSE_MANAGEMENT_ACCOUNT: You attempted to close the management account. To close the management account for the organization, you must first either remove or close all member accounts in the organization. Follow standard account closure process using root credentials.​

    • CANNOT_REMOVE_DELEGATED_ADMINISTRATOR_FROM_ORG: You attempted to remove an account that is registered as a delegated administrator for a service integrated with your organization. To complete this operation, you must first deregister this account as a delegated administrator.

    • CLOSE_ACCOUNT_QUOTA_EXCEEDED: You have exceeded close account quota for the past 30 days.

    • CLOSE_ACCOUNT_REQUESTS_LIMIT_EXCEEDED: You attempted to exceed the number of accounts that you can close at a time. ​

    • CREATE_ORGANIZATION_IN_BILLING_MODE_UNSUPPORTED_REGION: To create an organization in the specified region, you must enable all features mode.

    • DELEGATED_ADMINISTRATOR_EXISTS_FOR_THIS_SERVICE: You attempted to register an Amazon Web Services account as a delegated administrator for an Amazon Web Services service that already has a delegated administrator. To complete this operation, you must first deregister any existing delegated administrators for this service.

    • EMAIL_VERIFICATION_CODE_EXPIRED: The email verification code is only valid for a limited period of time. You must resubmit the request and generate a new verification code.

    • HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of handshakes that you can send in one day.

    • INVALID_PAYMENT_INSTRUMENT: You cannot remove an account because no supported payment method is associated with the account. Amazon Web Services does not support cards issued by financial institutions in Russia or Belarus. For more information, see Managing your Amazon Web Services payments.

    • MASTER_ACCOUNT_ADDRESS_DOES_NOT_MATCH_MARKETPLACE: To create an account in this organization, you first must migrate the organization's management account to the marketplace that corresponds to the management account's address. All accounts in an organization must be associated with the same marketplace.

    • MASTER_ACCOUNT_MISSING_BUSINESS_LICENSE: Applies only to the Amazon Web Services Regions in China. To create an organization, the master must have a valid business license. For more information, contact customer support.

    • MASTER_ACCOUNT_MISSING_CONTACT_INFO: To complete this operation, you must first provide a valid contact address and phone number for the management account. Then try the operation again.

    • MASTER_ACCOUNT_NOT_GOVCLOUD_ENABLED: To complete this operation, the management account must have an associated account in the Amazon Web Services GovCloud (US-West) Region. For more information, see Organizations in the Amazon Web Services GovCloud User Guide.

    • MASTER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To create an organization with this management account, you first must associate a valid payment instrument, such as a credit card, with the account. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • MAX_DELEGATED_ADMINISTRATORS_FOR_SERVICE_LIMIT_EXCEEDED: You attempted to register more delegated administrators than allowed for the service principal.

    • MAX_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to exceed the number of policies of a certain type that can be attached to an entity at one time.

    • MAX_TAG_LIMIT_EXCEEDED: You have exceeded the number of tags allowed on this resource.

    • MEMBER_ACCOUNT_PAYMENT_INSTRUMENT_REQUIRED: To complete this operation with this member account, you first must associate a valid payment instrument, such as a credit card, with the account. For more information, see Considerations before removing an account from an organization in the Organizations User Guide.

    • MIN_POLICY_TYPE_ATTACHMENT_LIMIT_EXCEEDED: You attempted to detach a policy from an entity that would cause the entity to have fewer than the minimum number of policies of a certain type required.

    • ORGANIZATION_NOT_IN_ALL_FEATURES_MODE: You attempted to perform an operation that requires the organization to be configured to support all features. An organization that supports only consolidated billing features can't perform this operation.

    • OU_DEPTH_LIMIT_EXCEEDED: You attempted to create an OU tree that is too many levels deep.

    • OU_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of OUs that you can have in an organization.

    • POLICY_CONTENT_LIMIT_EXCEEDED: You attempted to create a policy that is larger than the maximum size.

    • POLICY_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the number of policies that you can have in an organization.

    • POLICY_TYPE_ENABLED_FOR_THIS_SERVICE: You attempted to disable service access before you disabled the policy type (for example, SECURITYHUB_POLICY). To complete this operation, you must first disable the policy type.

    • RESPONSIBILITY_TRANSFER_MAX_INBOUND_QUOTA_VIOLATION: You have exceeded your inbound transfers limit.

    • RESPONSIBILITY_TRANSFER_MAX_LEVEL_VIOLATION: You have exceeded the maximum length of your transfer chain.

    • RESPONSIBILITY_TRANSFER_MAX_OUTBOUND_QUOTA_VIOLATION: You have exceeded your outbound transfers limit.

    • RESPONSIBILITY_TRANSFER_MAX_TRANSFERS_QUOTA_VIOLATION: You have exceeded the maximum number of inbound transfers allowed in a transfer chain.

    • SERVICE_ACCESS_NOT_ENABLED:

      • You attempted to register a delegated administrator before you enabled service access. Call the EnableAWSServiceAccess API first.

      • You attempted to enable a policy type before you enabled service access. Call the EnableAWSServiceAccess API first.

    • TAG_POLICY_VIOLATION: You attempted to create or update a resource with tags that are not compliant with the tag policy requirements for this account.

    • TRANSFER_RESPONSIBILITY_SOURCE_DELETION_IN_PROGRESS: The source organization cannot accept this transfer invitation because it is marked for deletion.

    • TRANSFER_RESPONSIBILITY_TARGET_DELETION_IN_PROGRESS: The source organization cannot accept this transfer invitation because target organization is marked for deletion.

    • TRANSFER_RESPONSIBILITY_UPDATE_NOT_ALLOWED: You cannot update this transfer because it is no longer active. Transfers that have been withdrawn, declined, expired, or cancelled cannot be modified.

    • UNMET_BILLING_PREREQUISITE: Your current billing configuration is unsupported. Contact Amazon Web Services Support for assistance.

    • UNSUPPORTED_PRICING: Ineligible for Billing Transfer. Your organization is subject to a pricing agreement with Amazon Web Services that Billing Transfer does not support.

    • WAIT_PERIOD_ACTIVE: After you create an Amazon Web Services account, you must wait until at least four days after the account was created. Invited accounts aren't subject to this waiting period.

    ", "exception":true }, "ConstraintViolationExceptionReason":{ @@ -1617,7 +1617,10 @@ "ACTIVE_RESPONSIBILITY_TRANSFER_PROCESS", "TRANSFER_RESPONSIBILITY_TARGET_DELETION_IN_PROGRESS", "TRANSFER_RESPONSIBILITY_SOURCE_DELETION_IN_PROGRESS", - "UNSUPPORTED_PRICING" + "UNSUPPORTED_PRICING", + "UNMET_BILLING_PREREQUISITE", + "ACCOUNT_NOT_ACTIVE_FOR_TRANSFER_RESPONSIBILITY", + "TRANSFER_RESPONSIBILITY_UPDATE_NOT_ALLOWED" ] }, "CreateAccountFailureReason":{ @@ -2469,7 +2472,7 @@ "Message":{"shape":"ExceptionMessage"}, "Reason":{"shape":"HandshakeConstraintViolationExceptionReason"} }, - "documentation":"

    The requested operation would violate the constraint identified in the reason code.

    Some of the reasons in the following list might not be applicable to this specific API or operation:

    • ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on the number of accounts in an organization. Note that deleted and closed accounts still count toward your limit.

      If you get this exception immediately after creating the organization, wait one hour and try again. If after an hour it continues to fail with this error, contact Amazon Web Services Support.

    • ALREADY_IN_AN_ORGANIZATION: The handshake request is invalid because the invited account is already a member of an organization.

    • HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of handshakes that you can send in one day.

    • INVITE_DISABLED_DURING_ENABLE_ALL_FEATURES: You can't issue new invitations to join an organization while it's in the process of enabling all features. You can resume inviting accounts after you finalize the process when all accounts have agreed to the change.

    • LEGACY_PERMISSIONS_STILL_IN_USE: Your organization must migrate to use the new IAM fine-grained actions for billing, cost management, and accounts.

    • ORGANIZATION_ALREADY_HAS_ALL_FEATURES: The handshake request is invalid because the organization has already enabled all features.

    • ORGANIZATION_FROM_DIFFERENT_SELLER_OF_RECORD: The request failed because the account is from a different marketplace than the accounts in the organization.

    • ORGANIZATION_IS_ALREADY_PENDING_ALL_FEATURES_MIGRATION: The handshake request is invalid because the organization has already started the process to enable all features.

    • ORGANIZATION_MEMBERSHIP_CHANGE_RATE_LIMIT_EXCEEDED: You attempted to change the membership of an account too quickly after its previous change.

    • PAYMENT_INSTRUMENT_REQUIRED: You can't complete the operation with an account that doesn't have a payment instrument, such as a credit card, associated with it.

    • RESPONSIBILITY_TRANSFER_ALREADY_EXISTS: You cannot perform this operation with the current transfer.

    • SOURCE_AND_TARGET_CANNOT_MATCH: An account can't accept a transfer invitation if it is both the sender and recipient of the invitation.

    • UNUSED_PREPAYMENT_BALANCE: Your organization has an outstanding pre-payment balance.

    ", + "documentation":"

    The requested operation would violate the constraint identified in the reason code.

    Some of the reasons in the following list might not be applicable to this specific API or operation:

    • ACCOUNT_NUMBER_LIMIT_EXCEEDED: You attempted to exceed the limit on the number of accounts in an organization. Note that deleted and closed accounts still count toward your limit.

      If you get this exception immediately after creating the organization, wait one hour and try again. If after an hour it continues to fail with this error, contact Amazon Web Services Support.

    • ALREADY_IN_AN_ORGANIZATION: The handshake request is invalid because the invited account is already a member of an organization.

    • HANDSHAKE_RATE_LIMIT_EXCEEDED: You attempted to exceed the number of handshakes that you can send in one day.

    • INVITE_DISABLED_DURING_ENABLE_ALL_FEATURES: You can't issue new invitations to join an organization while it's in the process of enabling all features. You can resume inviting accounts after you finalize the process when all accounts have agreed to the change.

    • LEGACY_PERMISSIONS_STILL_IN_USE: Your organization must migrate to use the new IAM fine-grained actions for billing, cost management, and accounts.

    • ORGANIZATION_ALREADY_HAS_ALL_FEATURES: The handshake request is invalid because the organization has already enabled all features.

    • ORGANIZATION_FROM_DIFFERENT_SELLER_OF_RECORD: You can only join an organization that operates in the same Amazon Web Services partition as your account.

    • ORGANIZATION_IS_ALREADY_PENDING_ALL_FEATURES_MIGRATION: The handshake request is invalid because the organization has already started the process to enable all features.

    • ORGANIZATION_MEMBERSHIP_CHANGE_RATE_LIMIT_EXCEEDED: You attempted to change the membership of an account too quickly after its previous change.

    • PAST_DUE_INVOICE: Your organization has an invoice that is past due.

    • PAYMENT_INSTRUMENT_REQUIRED: You can't complete the operation with an account that doesn't have a payment instrument, such as a credit card, associated with it.

    • RESPONSIBILITY_TRANSFER_ALREADY_EXISTS: You cannot perform this operation with the current transfer.

    • SOURCE_AND_TARGET_CANNOT_MATCH: An account can't accept a transfer invitation if it is both the sender and recipient of the invitation.

    • TARGET_ACCOUNT_VALIDATION_FAILURE: Billing transfer is not available for your account. Contact your billing administrator or Amazon Web Services Support for assistance.

    • UNUSED_PREPAYMENT_BALANCE: Your organization has an outstanding pre-payment balance.

    ", "exception":true }, "HandshakeConstraintViolationExceptionReason":{ @@ -2488,7 +2491,9 @@ "RESPONSIBILITY_TRANSFER_ALREADY_EXISTS", "SOURCE_AND_TARGET_CANNOT_MATCH", "UNUSED_PREPAYMENT_BALANCE", - "LEGACY_PERMISSIONS_STILL_IN_USE" + "LEGACY_PERMISSIONS_STILL_IN_USE", + "PAST_DUE_INVOICE", + "TARGET_ACCOUNT_VALIDATION_FAILURE" ] }, "HandshakeFilter":{ @@ -2541,7 +2546,7 @@ }, "Type":{ "shape":"HandshakePartyType", - "documentation":"

    The type of ID for the participant.

    " + "documentation":"

    The type of ID for the participant.

    ORGANIZATION is valid only in the response context (identifying the inviting organization). Valid input values for the Target parameter are ACCOUNT and EMAIL only.

    " } }, "documentation":"

    Contains details for a participant in a handshake.

    " @@ -2642,7 +2647,7 @@ "Message":{"shape":"ExceptionMessage"}, "Reason":{"shape":"InvalidInputExceptionReason"} }, - "documentation":"

    The requested operation failed because you provided invalid values for one or more of the request parameters. This exception includes a reason that contains additional information about the violated limit:

    Some of the reasons in the following list might not be applicable to this specific API or operation.

    • CALLER_REQUIRED_FIELD_MISSING: At least one of the required field is missing: Caller Account Id, Management Account Id or Organization Id.

    • DUPLICATE_TAG_KEY: Tag keys must be unique among the tags attached to the same entity.

    • END_DATE_NOT_END_OF_MONTH: You provided an invalid end date. The end date must be the end of the last day of the month (23.59.59.999).

    • END_DATE_TOO_EARLY: You provided an invalid end date. The end date is too early.

    • END_DATE_TOO_LATE: You provided an invalid end date. The end date is too late.

    • IMMUTABLE_POLICY: You specified a policy that is managed by Amazon Web Services and can't be modified.

    • INPUT_REQUIRED: You must include a value for all required parameters.

    • INVALID_EMAIL_ADDRESS_TARGET: You specified an invalid email address for the invited account owner.

    • INVALID_END_DATE: The selected withdrawal date doesn't meet the terms of your partner agreement. Visit Amazon Web Services Partner Central to view your partner agreements or contact your Amazon Web Services Partner for help.

    • INVALID_ENUM: You specified an invalid value.

    • INVALID_ENUM_POLICY_TYPE: You specified an invalid policy type string.

    • INVALID_FULL_NAME_TARGET: You specified a full name that contains invalid characters.

    • INVALID_LIST_MEMBER: You provided a list to a parameter that contains at least one invalid value.

    • INVALID_PAGINATION_TOKEN: Get the value for the NextToken parameter from the response to a previous call of the operation.

    • INVALID_PARTY_TYPE_TARGET: You specified the wrong type of entity (account, organization, or email) as a party.

    • INVALID_PATTERN: You provided a value that doesn't match the required pattern.

    • INVALID_PATTERN_TARGET_ID: You specified a policy target ID that doesn't match the required pattern.

    • INVALID_PRINCIPAL: You specified an invalid principal element in the policy.

    • INVALID_ROLE_NAME: You provided a role name that isn't valid. A role name can't begin with the reserved prefix AWSServiceRoleFor.

    • INVALID_START_DATE: The start date doesn't meet the minimum requirements.

    • INVALID_SYNTAX_ORGANIZATION_ARN: You specified an invalid Amazon Resource Name (ARN) for the organization.

    • INVALID_SYNTAX_POLICY_ID: You specified an invalid policy ID.

    • INVALID_SYSTEM_TAGS_PARAMETER: You specified a tag key that is a system tag. You can’t add, edit, or delete system tag keys because they're reserved for Amazon Web Services use. System tags don’t count against your tags per resource limit.

    • MAX_FILTER_LIMIT_EXCEEDED: You can specify only one filter parameter for the operation.

    • MAX_LENGTH_EXCEEDED: You provided a string parameter that is longer than allowed.

    • MAX_VALUE_EXCEEDED: You provided a numeric parameter that has a larger value than allowed.

    • MIN_LENGTH_EXCEEDED: You provided a string parameter that is shorter than allowed.

    • MIN_VALUE_EXCEEDED: You provided a numeric parameter that has a smaller value than allowed.

    • MOVING_ACCOUNT_BETWEEN_DIFFERENT_ROOTS: You can move an account only between entities in the same root.

    • NON_DETACHABLE_POLICY: You can't detach this Amazon Web Services Managed Policy.

    • START_DATE_NOT_BEGINNING_OF_DAY: You provided an invalid start date. The start date must be the beginning of the day (00:00:00.000).

    • START_DATE_NOT_BEGINNING_OF_MONTH: You provided an invalid start date. The start date must be the first day of the month.

    • START_DATE_TOO_EARLY: You provided an invalid start date. The start date is too early.

    • START_DATE_TOO_LATE: You provided an invalid start date. The start date is too late.

    • TARGET_NOT_SUPPORTED: You can't perform the specified operation on that target entity.

    • UNRECOGNIZED_SERVICE_PRINCIPAL: You specified a service principal that isn't recognized.

    • UNSUPPORTED_ACTION_IN_RESPONSIBILITY_TRANSFER: You provided a value that is not supported by this operation.

    ", + "documentation":"

    The requested operation failed because you provided invalid values for one or more of the request parameters. This exception includes a reason that contains additional information about the violated limit:

    Some of the reasons in the following list might not be applicable to this specific API or operation.

    • CALLER_REQUIRED_FIELD_MISSING: At least one of the required field is missing: Caller Account Id, Management Account Id or Organization Id.

    • DUPLICATE_TAG_KEY: Tag keys must be unique among the tags attached to the same entity.

    • END_DATE_NOT_END_OF_MONTH: You provided an invalid end date. The end date must be the end of the last day of the month (23.59.59.999).

    • END_DATE_TOO_EARLY: You provided an invalid end date. The end date is too early.

    • END_DATE_TOO_LATE: You provided an invalid end date. The end date is too late.

    • IMMUTABLE_POLICY: You specified a policy that is managed by Amazon Web Services and can't be modified.

    • INPUT_REQUIRED: You must include a value for all required parameters.

    • INVALID_EMAIL_ADDRESS_TARGET: You specified an invalid email address for the invited account owner.

    • INVALID_END_DATE: The selected withdrawal date doesn't meet the minimum notice period required by your partner agreement. Visit Amazon Web Services Partner Central or contact your Amazon Web Services Channel Partner for help.

    • INVALID_ENUM: You specified an invalid value.

    • INVALID_ENUM_POLICY_TYPE: You specified an invalid policy type string.

    • INVALID_FULL_NAME_TARGET: You specified a full name that contains invalid characters.

    • INVALID_LIST_MEMBER: You provided a list to a parameter that contains at least one invalid value.

    • INVALID_PAGINATION_TOKEN: Get the value for the NextToken parameter from the response to a previous call of the operation.

    • INVALID_PARTY_TYPE_TARGET: You specified the wrong type of entity (account, organization, or email) as a party.

    • INVALID_PATTERN: You provided a value that doesn't match the required pattern. The service also validates your free-text field values against common cross-site scripting (XSS) patterns and rejects requests that contain matching values.

    • INVALID_PATTERN_TARGET_ID: You specified a policy target ID that doesn't match the required pattern.

    • INVALID_PRINCIPAL: You specified an invalid principal element in the policy.

    • INVALID_ROLE_NAME: You provided a role name that isn't valid. A role name can't begin with the reserved prefix AWSServiceRoleFor.

    • INVALID_START_DATE: The start date doesn't meet the minimum requirements.

    • INVALID_SYNTAX_ORGANIZATION_ARN: You specified an invalid Amazon Resource Name (ARN) for the organization.

    • INVALID_SYNTAX_POLICY_ID: You specified an invalid policy ID.

    • INVALID_SYSTEM_TAGS_PARAMETER: You specified a tag key that is a system tag. You can’t add, edit, or delete system tag keys because they're reserved for Amazon Web Services use. System tags don’t count against your tags per resource limit.

    • MAX_FILTER_LIMIT_EXCEEDED: You can specify only one filter parameter for the operation.

    • MAX_LENGTH_EXCEEDED: You provided a string parameter that is longer than allowed.

    • MAX_VALUE_EXCEEDED: You provided a numeric parameter that has a larger value than allowed.

    • MIN_LENGTH_EXCEEDED: You provided a string parameter that is shorter than allowed.

    • MIN_VALUE_EXCEEDED: You provided a numeric parameter that has a smaller value than allowed.

    • MOVING_ACCOUNT_BETWEEN_DIFFERENT_ROOTS: You can move an account only between entities in the same root.

    • NON_DETACHABLE_POLICY: You can't detach this Amazon Web Services Managed Policy.

    • START_DATE_NOT_BEGINNING_OF_DAY: You provided an invalid start date. The start date must be the beginning of the day (00:00:00.000).

    • START_DATE_NOT_BEGINNING_OF_MONTH: You provided an invalid start date. The start date must be the first day of the month.

    • START_DATE_TOO_EARLY: You provided an invalid start date. The start date is too early.

    • START_DATE_TOO_LATE: You provided an invalid start date. The start date is too late.

    • TARGET_NOT_SUPPORTED: You can't perform the specified operation on that target entity.

    • UNRECOGNIZED_SERVICE_PRINCIPAL: You specified a service principal that isn't recognized.

    • UNSUPPORTED_ACTION_IN_RESPONSIBILITY_TRANSFER: You provided a value that is not supported by this operation.

    ", "exception":true }, "InvalidInputExceptionReason":{ @@ -2687,6 +2692,7 @@ "INVALID_START_DATE", "END_DATE_NOT_END_OF_MONTH", "END_DATE_TOO_EARLY", + "END_DATE_TOO_LATE", "INVALID_END_DATE" ] }, @@ -4330,5 +4336,5 @@ } } }, - "documentation":"

    Organizations is a web service that enables you to consolidate your multiple Amazon Web Services accounts into an organization and centrally manage your accounts and their resources.

    This guide provides descriptions of the Organizations operations. For more information about using this service, see the Organizations User Guide.

    Support and feedback for Organizations

    We welcome your feedback. You can post your feedback and questions in the Organizations support forum. For more information about the Amazon Web Services Support forums, see Forums Help.

    Endpoint to call When using the CLI or the Amazon Web Services SDK

    For the current release of Organizations, specify the us-east-1 region for all Amazon Web Services API and CLI calls made from the commercial Amazon Web Services Regions outside of China. If calling from one of the Amazon Web Services Regions in China, then specify cn-northwest-1. You can do this in the CLI by using these parameters and commands:

    • Use the following parameter with each command to specify both the endpoint and its region:

      --endpoint-url https://organizations.us-east-1.amazonaws.com (from commercial Amazon Web Services Regions outside of China)

      or

      --endpoint-url https://organizations.cn-northwest-1.amazonaws.com.cn (from Amazon Web Services Regions in China)

    • Use the default endpoint, but configure your default region with this command:

      aws configure set default.region us-east-1 (from commercial Amazon Web Services Regions outside of China)

      or

      aws configure set default.region cn-northwest-1 (from Amazon Web Services Regions in China)

    • Use the following parameter with each command to specify the endpoint:

      --region us-east-1 (from commercial Amazon Web Services Regions outside of China)

      or

      --region cn-northwest-1 (from Amazon Web Services Regions in China)

    Recording API Requests

    Organizations supports CloudTrail, a service that records Amazon Web Services API calls for your Amazon Web Services account and delivers log files to an Amazon S3 bucket. By using information collected by CloudTrail, you can determine which requests the Organizations service received, who made the request and when, and so on. For more about Organizations and its support for CloudTrail, see Logging Organizations API calls with CloudTrail in the Organizations User Guide. To learn more about CloudTrail, including how to turn it on and find your log files, see the CloudTrail User Guide.

    " + "documentation":"

    Organizations is a web service that enables you to consolidate your multiple Amazon Web Services accounts into an organization and centrally manage your accounts and their resources.

    This guide provides descriptions of the Organizations API. For more information about using this service, see the Organizations User Guide.

    API version

    This version of the Organizations API Reference documents the Organizations API version 2016-11-28.

    As an alternative to using the API directly, you can use one of the Amazon Web Services SDKs, which consist of libraries and sample code for various programming languages and platforms (Java, Ruby, .NET, iOS, Android, and more). The SDKs provide a convenient way to create programmatic access to Organizations. For example, the SDKs take care of cryptographically signing requests, managing errors, and retrying requests automatically. For more information about the Amazon Web Services SDKs, including how to download and install them, see Tools for Amazon Web Services.

    We recommend that you use the Amazon Web Services SDKs to make programmatic API calls to Organizations. However, you also can use the Organizations Query API to make direct calls to the Organizations web service. To learn more about the Organizations Query API, see Calling the API by making HTTP Query requests in the Organizations User Guide. Organizations supports GET and POST requests for all actions. That is, the API doesn't require you to use GET for some actions and POST for others. However, GET requests are subject to the limitation size of a URL. Therefore, for operations that require larger sizes, use a POST request.

    Signing requests

    When you send HTTP requests to Amazon Web Services, sign the requests so that Amazon Web Services can identify who sent them. You sign requests with your Amazon Web Services access key, which consists of an access key ID and a secret access key. We strongly recommend that you don't create an access key for your root account. Anyone who has the access key for your root account has unrestricted access to all the resources in your account. Instead, create an access key for an IAM user that has administrative permissions. As another option, use Amazon Web Services Security Token Service (Amazon Web Services STS) to generate temporary security credentials, and use those credentials to sign requests.

    To sign requests, we recommend that you use Signature Version 4. If you have an existing application that uses Signature Version 2, you don't have to update it to use Signature Version 4. However, some operations now require Signature Version 4. The documentation for operations that require version 4 indicate this requirement.

    When you use the Command Line Interface (CLI) or one of the Amazon Web Services SDKs to make requests to Amazon Web Services, these tools automatically sign the requests for you with the access key that you specify when you configure the tools.

    In this release, each organization can have only one root.

    Support and feedback for Organizations

    We welcome your feedback. You can post your feedback and questions in the Organizations support forum. For more information about the Amazon Web Services Support forums, see Forums Help.

    Endpoint to call When using the CLI or the Amazon Web Services SDK

    For the current release of Organizations, specify the us-east-1 region for all Amazon Web Services API and CLI calls made from the commercial Amazon Web Services Regions outside of China. If calling from one of the Amazon Web Services Regions in China, then specify cn-northwest-1. You can do this in the CLI by using these parameters and commands:

    • Use the following parameter with each command to specify both the endpoint and its region:

      --endpoint-url https://organizations.us-east-1.amazonaws.com (from commercial Amazon Web Services Regions outside of China)

      or

      --endpoint-url https://organizations.cn-northwest-1.amazonaws.com.cn (from Amazon Web Services Regions in China)

    • Use the default endpoint, but configure your default region with this command:

      aws configure set default.region us-east-1 (from commercial Amazon Web Services Regions outside of China)

      or

      aws configure set default.region cn-northwest-1 (from Amazon Web Services Regions in China)

    • Use the following parameter with each command to specify the endpoint:

      --region us-east-1 (from commercial Amazon Web Services Regions outside of China)

      or

      --region cn-northwest-1 (from Amazon Web Services Regions in China)

    How examples are presented

    The JSON returned by the Organizations service as response to your requests arrives as a single long string without line breaks or formatting whitespace. The examples in this guide include both line breaks and whitespace to improve readability. When example input parameters also would result in long strings that would extend beyond the screen, we insert line breaks to enhance readability. Always submit the input as a single JSON text string.

    Recording API Requests

    Organizations supports CloudTrail, a service that records Amazon Web Services API calls for your Amazon Web Services account and delivers log files to an Amazon S3 bucket. By using information collected by CloudTrail, you can determine which requests the Organizations service received, who made the request and when, and so on. For more about Organizations and its support for CloudTrail, see Logging Organizations API calls with CloudTrail in the Organizations User Guide. To learn more about CloudTrail, including how to turn it on and find your log files, see the CloudTrail User Guide.

    " } diff --git a/services/osis/pom.xml b/services/osis/pom.xml index b500aa5a1ea1..14f2f4d0d4dd 100644 --- a/services/osis/pom.xml +++ b/services/osis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT osis AWS Java SDK :: Services :: OSIS diff --git a/services/osis/src/main/resources/codegen-resources/customization.config b/services/osis/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/osis/src/main/resources/codegen-resources/customization.config +++ b/services/osis/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/osis/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/osis/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f5e7cd04d91e --- /dev/null +++ b/services/osis/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://osis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://osis-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://osis.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://osis.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/osis/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/osis/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 15fb9214e3de..000000000000 --- a/services/osis/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://osis-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://osis-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://osis.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://osis.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/outposts/pom.xml b/services/outposts/pom.xml index 68dbf2084670..02cf3aca0e09 100644 --- a/services/outposts/pom.xml +++ b/services/outposts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT outposts AWS Java SDK :: Services :: Outposts diff --git a/services/outposts/src/main/resources/codegen-resources/customization.config b/services/outposts/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/outposts/src/main/resources/codegen-resources/customization.config +++ b/services/outposts/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fc952d3eae06 --- /dev/null +++ b/services/outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://outposts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://outposts.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://outposts-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://outposts.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://outposts.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/outposts/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/outposts/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index be8f87bb12fd..000000000000 --- a/services/outposts/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://outposts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://outposts.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://outposts-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://outposts.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://outposts.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/outposts/src/main/resources/codegen-resources/service-2.json b/services/outposts/src/main/resources/codegen-resources/service-2.json index f97998b0acf2..724cb2140ff0 100644 --- a/services/outposts/src/main/resources/codegen-resources/service-2.json +++ b/services/outposts/src/main/resources/codegen-resources/service-2.json @@ -85,6 +85,23 @@ ], "documentation":"

    Creates an Outpost.

    You can specify either an Availability one or an AZ ID.

    " }, + "CreatePrivateConnectivityConfig":{ + "name":"CreatePrivateConnectivityConfig", + "http":{ + "method":"POST", + "requestUri":"/outposts/{OutpostId}/privateConnectivity" + }, + "input":{"shape":"CreatePrivateConnectivityConfigInput"}, + "output":{"shape":"CreatePrivateConnectivityConfigOutput"}, + "errors":[ + {"shape":"ConflictException"}, + {"shape":"ValidationException"}, + {"shape":"NotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Creates the private connectivity configuration for the specified Outpost. Private connectivity establishes a service link VPN connection between the Outpost and its home Amazon Web Services Region using a VPC and subnet that you specify, which allows the service link traffic to flow through your VPC and minimizes public internet exposure.

    " + }, "CreateQuote":{ "name":"CreateQuote", "http":{ @@ -310,6 +327,22 @@ ], "documentation":"

    Gets the instance types that an Outpost can support in InstanceTypeCapacity. This will generally include instance types that are not currently configured and therefore cannot be launched with the current Outpost capacity configuration.

    " }, + "GetPrivateConnectivityConfig":{ + "name":"GetPrivateConnectivityConfig", + "http":{ + "method":"GET", + "requestUri":"/outposts/{OutpostId}/privateConnectivity" + }, + "input":{"shape":"GetPrivateConnectivityConfigInput"}, + "output":{"shape":"GetPrivateConnectivityConfigOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"NotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Gets the private connectivity configuration for the specified Outpost.

    " + }, "GetQuote":{ "name":"GetQuote", "http":{ @@ -716,6 +749,7 @@ "enum":[ "AWS", "EC2", + "EKS", "ELASTICACHE", "ELB", "RDS", @@ -803,7 +837,8 @@ "documentation":"

    The municipality for the address.

    " } }, - "documentation":"

    Information about an address.

    " + "documentation":"

    Information about an address.

    ", + "sensitive":true }, "AddressLine1":{ "type":"string", @@ -1224,6 +1259,10 @@ "SupportedStorage":{ "shape":"SupportedStorageList", "documentation":"

    The supported storage options for the catalog item.

    " + }, + "RackScalingType":{ + "shape":"RackScalingType", + "documentation":"

    The rack scaling type supported by the catalog item. Valid values are SINGLE_RACK and MULTI_RACK.

    " } }, "documentation":"

    Information about a catalog item.

    " @@ -1457,6 +1496,38 @@ "Outpost":{"shape":"Outpost"} } }, + "CreatePrivateConnectivityConfigInput":{ + "type":"structure", + "required":[ + "OutpostId", + "VpcInformationList" + ], + "members":{ + "OutpostId":{ + "shape":"OutpostId", + "documentation":"

    The ID or ARN of the Outpost.

    ", + "location":"uri", + "locationName":"OutpostId" + }, + "VpcInformationList":{ + "shape":"VpcInformationList", + "documentation":"

    Information about the VPC used for private connectivity, including the VPC, its subnets, and an associated VPC endpoint. You can specify at most one entry.

    " + } + } + }, + "CreatePrivateConnectivityConfigOutput":{ + "type":"structure", + "members":{ + "PrivateConnectivityConfig":{ + "shape":"PrivateConnectivityConfig", + "documentation":"

    The private connectivity configuration for the Outpost.

    " + }, + "OutpostId":{ + "shape":"OutpostId", + "documentation":"

    The ID of the Outpost.

    " + } + } + }, "CreateQuoteInput":{ "type":"structure", "required":[ @@ -2045,6 +2116,27 @@ "NextToken":{"shape":"Token"} } }, + "GetPrivateConnectivityConfigInput":{ + "type":"structure", + "required":["OutpostId"], + "members":{ + "OutpostId":{ + "shape":"OutpostId", + "documentation":"

    The ID or ARN of the Outpost.

    ", + "location":"uri", + "locationName":"OutpostId" + } + } + }, + "GetPrivateConnectivityConfigOutput":{ + "type":"structure", + "members":{ + "PrivateConnectivityConfig":{ + "shape":"PrivateConnectivityConfig", + "documentation":"

    The private connectivity configuration for the Outpost.

    " + } + } + }, "GetQuoteInput":{ "type":"structure", "required":["QuoteIdentifier"], @@ -3072,6 +3164,14 @@ "SupportedHardwareType":{ "shape":"SupportedHardwareType", "documentation":"

    The hardware type.

    " + }, + "Generation":{ + "shape":"OutpostGeneration", + "documentation":"

    The Outpost generation. Valid values are GENERATION_1 for first-generation rack deployments and GENERATION_2 for second-generation rack deployments.

    " + }, + "RackScalingType":{ + "shape":"RackScalingType", + "documentation":"

    The rack scaling type. Valid values are SINGLE_RACK for single-rack Outposts and MULTI_RACK for multi-rack Outposts that can expand across multiple racks.

    " } }, "documentation":"

    Information about an Outpost.

    " @@ -3236,6 +3336,35 @@ "UNABLE_TO_PRICE" ] }, + "PrivateConnectivityConfig":{ + "type":"structure", + "members":{ + "RoleArn":{ + "shape":"RoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the service-linked role that Amazon Web Services Outposts creates and uses to provision and attach the network interfaces for private connectivity in your VPC. The role's permissions are scoped to the specific Outpost and VPC.

    " + }, + "PrivateConnectivityStatus":{ + "shape":"PrivateConnectivityStatus", + "documentation":"

    The status of private connectivity for the Outpost. Valid values are ENABLED and DISABLED.

    " + }, + "VpcInformationList":{ + "shape":"VpcInformationList", + "documentation":"

    Information about the VPC used for private connectivity.

    " + }, + "ProvisioningRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the provisioning role in your account that Amazon Web Services Outposts uses to establish the service link connection during Outpost installation. This field is present only when VPC endpoint-based provisioning is configured.

    " + } + }, + "documentation":"

    Information about the private connectivity configuration for an Outpost.

    " + }, + "PrivateConnectivityStatus":{ + "type":"string", + "enum":[ + "ENABLED", + "DISABLED" + ] + }, "Quantity":{"type":"string"}, "Quote":{ "type":"structure", @@ -3343,7 +3472,7 @@ "members":{ "QuoteConstraintType":{ "shape":"QuoteConstraintType", - "documentation":"

    The type of constraint. Valid values are RACK_MAXIMUM, RACK_MAX_POWER_KVA, and RACK_MAX_WEIGHT_LBS.

    " + "documentation":"

    The type of constraint. Valid values are RACK_MAXIMUM, RACK_MAX_POWER_KVA, RACK_MAX_WEIGHT_LBS, and RACK_SPACE_CONSTRAINED.

    " }, "Value":{ "shape":"ConstraintValue", @@ -3362,7 +3491,8 @@ "enum":[ "RACK_MAXIMUM", "RACK_MAX_POWER_KVA", - "RACK_MAX_WEIGHT_LBS" + "RACK_MAX_WEIGHT_LBS", + "RACK_SPACE_CONSTRAINED" ] }, "QuoteDescription":{ @@ -3601,6 +3731,13 @@ }, "documentation":"

    Information about the physical and logistical details for racks at sites. For more information about hardware requirements for racks, see Network readiness checklist in the Amazon Web Services Outposts User Guide.

    " }, + "RackScalingType":{ + "type":"string", + "enum":[ + "SINGLE_RACK", + "MULTI_RACK" + ] + }, "RackSpecificationDetails":{ "type":"structure", "members":{ @@ -3662,6 +3799,12 @@ "ORDER" ] }, + "RoleArn":{ + "type":"string", + "max":150, + "min":1, + "pattern":"^arn:aws([a-z-]+)?:iam::\\d{12}:role\\/[a-zA-Z_0-9+=,.@\\-_\\/]+" + }, "ServerEndpoint":{ "type":"string", "max":21, @@ -4002,6 +4145,18 @@ "min":1, "pattern":"^[\\S \\n]+$" }, + "SubnetId":{ + "type":"string", + "max":25, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "SubnetIds":{ + "type":"list", + "member":{"shape":"SubnetId"}, + "max":10, + "min":1 + }, "Subscription":{ "type":"structure", "members":{ @@ -4438,6 +4593,42 @@ "error":{"httpStatusCode":400}, "exception":true }, + "VpcEndpointId":{ + "type":"string", + "max":25, + "min":1, + "pattern":"^vpce-[a-f0-9]+$" + }, + "VpcId":{ + "type":"string", + "max":25, + "min":1, + "pattern":"[a-z0-9-]+" + }, + "VpcInformation":{ + "type":"structure", + "members":{ + "VpcId":{ + "shape":"VpcId", + "documentation":"

    The ID of the VPC used for private connectivity.

    " + }, + "SubnetIds":{ + "shape":"SubnetIds", + "documentation":"

    The IDs of the subnets associated with the VPC endpoint. Currently, only one subnet is supported.

    " + }, + "VpcEndpointId":{ + "shape":"VpcEndpointId", + "documentation":"

    The ID of the interface VPC endpoint for the Amazon Web Services Outposts service. When specified, the endpoint must be in the available state and the specified subnets must be associated with it.

    " + } + }, + "documentation":"

    Information about a VPC used for private connectivity, including its subnets and an associated VPC endpoint.

    " + }, + "VpcInformationList":{ + "type":"list", + "member":{"shape":"VpcInformation"}, + "max":1, + "min":1 + }, "WireGuardPublicKey":{ "type":"string", "max":44, @@ -4455,5 +4646,5 @@ "documentation":"

    Information about the sites.

    " } }, - "documentation":"

    Amazon Web Services Outposts is a fully managed service that extends Amazon Web Services infrastructure, APIs, and tools to customer premises. By providing local access to Amazon Web Services managed infrastructure, Amazon Web Services Outposts enables customers to build and run applications on premises using the same programming interfaces as in Amazon Web Services Regions, while using local compute and storage resources for lower latency and local data processing needs.

    " + "documentation":"

    Amazon Web Services Outposts is a fully managed service that extends Amazon Web Services infrastructure, APIs, and tools to customer premises. By providing local access to Amazon Web Services managed infrastructure, Amazon Web Services Outposts enables customers to build and run applications on premises using the same programming interfaces as in Amazon Web Services Regions, while using local compute and storage resources for lower latency and local data processing needs.

    You can use certain Amazon EC2 API actions for Amazon Web Services Outposts. For more information on these API actions, see Amazon Web Services Outposts actions in the Amazon EC2 API Reference.

    " } diff --git a/services/partnercentralaccount/pom.xml b/services/partnercentralaccount/pom.xml index b4d7c4d9e3cb..78e0deb33b3a 100644 --- a/services/partnercentralaccount/pom.xml +++ b/services/partnercentralaccount/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT partnercentralaccount AWS Java SDK :: Services :: Partner Central Account diff --git a/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..12e85c9a8b66 --- /dev/null +++ b/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-account-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-account.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c98086f40153..000000000000 --- a/services/partnercentralaccount/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-account-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://partnercentral-account.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/partnercentralaccount/src/main/resources/codegen-resources/service-2.json b/services/partnercentralaccount/src/main/resources/codegen-resources/service-2.json index fe1a5c3a7806..96137cc1b2a7 100644 --- a/services/partnercentralaccount/src/main/resources/codegen-resources/service-2.json +++ b/services/partnercentralaccount/src/main/resources/codegen-resources/service-2.json @@ -287,6 +287,60 @@ "documentation":"

    Retrieves the visibility settings for a partner profile, determining who can see the profile information.

    ", "readonly":true }, + "GetQualificationsAssociationDetails":{ + "name":"GetQualificationsAssociationDetails", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetQualificationsAssociationDetailsRequest"}, + "output":{"shape":"GetQualificationsAssociationDetailsResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Returns your current qualifications association status, the primary partner, and the full list of partners associated under the primary partner.

    ", + "readonly":true + }, + "GetQualificationsAssociationTask":{ + "name":"GetQualificationsAssociationTask", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetQualificationsAssociationTaskRequest"}, + "output":{"shape":"GetQualificationsAssociationTaskResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the status and details of the most recent qualifications association task for your partner account. Use this operation to poll the progress of an association task initiated by StartQualificationsAssociationTask.

    ", + "readonly":true + }, + "GetQualificationsDisassociationTask":{ + "name":"GetQualificationsDisassociationTask", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetQualificationsDisassociationTaskRequest"}, + "output":{"shape":"GetQualificationsDisassociationTaskResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Retrieves the status and details of the most recent qualifications disassociation task for your partner account. Use this operation to poll the progress of a disassociation task initiated by StartQualificationsDisassociationTask.

    ", + "readonly":true + }, "GetVerification":{ "name":"GetVerification", "http":{ @@ -464,6 +518,44 @@ "documentation":"

    Initiates a profile update task to modify partner profile information asynchronously.

    ", "idempotent":true }, + "StartQualificationsAssociationTask":{ + "name":"StartQualificationsAssociationTask", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"StartQualificationsAssociationTaskRequest"}, + "output":{"shape":"StartQualificationsAssociationTaskResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Initiates an asynchronous task to associate your partner qualifications with a primary account. You must be a subsidiary of the primary account with an active subsidiary connection. Use GetQualificationsAssociationTask to monitor task progress.

    ", + "idempotent":true + }, + "StartQualificationsDisassociationTask":{ + "name":"StartQualificationsDisassociationTask", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"StartQualificationsDisassociationTaskRequest"}, + "output":{"shape":"StartQualificationsDisassociationTaskResponse"}, + "errors":[ + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Initiates an asynchronous task to disassociate your partner qualifications from a primary account. You must currently be associated and cannot disassociate if you are the primary partner. Use GetQualificationsDisassociationTask to monitor task progress.

    ", + "idempotent":true + }, "StartVerification":{ "name":"StartVerification", "http":{ @@ -680,6 +772,13 @@ "type":"structure", "members":{} }, + "AssociatedPartnerList":{ + "type":"list", + "member":{"shape":"QualificationsAssociationPartner"}, + "documentation":"

    A list of partner profile and account identifiers representing all partners associated under the primary partner.

    ", + "max":6, + "min":0 + }, "AwsAccountId":{ "type":"string", "pattern":"[0-9]{12}" @@ -694,7 +793,13 @@ "INVALID_ACCOUNT_LINKING_STATUS", "INVALID_ACCOUNT_STATE", "INCOMPATIBLE_DOMAIN", - "INELIGIBLE_ACCOUNT_TIER" + "INELIGIBLE_ACCOUNT_TIER", + "MISSING_ACTIVE_SUBSIDIARY_CONNECTION", + "INCOMPATIBLE_SUBSIDIARY_CONNECTION", + "INCOMPATIBLE_PRIMARY_PARTNER", + "QUALIFICATIONS_ASSOCIATION_LIMIT_EXCEEDED", + "QUALIFICATIONS_ASSOCIATION_NOT_FOUND", + "QUALIFICATIONS_ASSOCIATION_EXISTS" ] }, "BusinessValidationError":{ @@ -1060,7 +1165,8 @@ "INCOMPATIBLE_CONNECTION_STATE", "INCOMPATIBLE_CONNECTION_PREFERENCES_REVISION", "ACCOUNT_ALREADY_VERIFIED", - "VERIFICATION_ALREADY_IN_PROGRESS" + "VERIFICATION_ALREADY_IN_PROGRESS", + "INCOMPATIBLE_QUALIFICATIONS_ASSOCIATION_TASK_STATE" ] }, "Connection":{ @@ -2080,6 +2186,188 @@ } } }, + "GetQualificationsAssociationDetailsRequest":{ + "type":"structure", + "required":[ + "Catalog", + "Identifier" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog in which to look up the qualifications association. Valid values: AWS, Sandbox.

    " + }, + "Identifier":{ + "shape":"PartnerIdentifier", + "documentation":"

    Your partner identifier. You can provide either a partner ID (for example, partner-abc123) or a partner ARN. You must own this identifier.

    " + } + } + }, + "GetQualificationsAssociationDetailsResponse":{ + "type":"structure", + "required":[ + "Catalog", + "Arn", + "Id", + "Status" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog identifier echoed from the request.

    " + }, + "Arn":{ + "shape":"PartnerArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies your partner resource.

    " + }, + "Id":{ + "shape":"PartnerId", + "documentation":"

    Your unique partner identifier in the AWS Partner Network.

    " + }, + "Status":{ + "shape":"QualificationsAssociationStatus", + "documentation":"

    The current qualifications association status. Valid values: ASSOCIATED (the partner is associated with a primary), NOT_ASSOCIATED (the partner has no active association).

    " + }, + "PrimaryPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The primary partner's profile and account identifiers. This field is null when the status is NOT_ASSOCIATED.

    " + }, + "AssociatedPartners":{ + "shape":"AssociatedPartnerList", + "documentation":"

    The list of all partner profile and account identifiers currently associated under the primary partner. This field is null when the status is NOT_ASSOCIATED.

    " + }, + "UpdatedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications association was last updated, in ISO 8601 format. This field is null when the status is NOT_ASSOCIATED.

    " + } + } + }, + "GetQualificationsAssociationTaskRequest":{ + "type":"structure", + "required":[ + "Catalog", + "Identifier" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog in which to look up the qualifications association task. Valid values: AWS, Sandbox.

    " + }, + "Identifier":{ + "shape":"PartnerIdentifier", + "documentation":"

    Your partner identifier. You can provide either a partner ID (for example, partner-abc123) or a partner ARN. You must own this identifier.

    " + } + } + }, + "GetQualificationsAssociationTaskResponse":{ + "type":"structure", + "required":[ + "Catalog", + "Arn", + "Id", + "TaskId", + "Status", + "PrimaryPartner", + "StartedAt" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog identifier echoed from the request.

    " + }, + "Arn":{ + "shape":"PartnerArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies your partner resource.

    " + }, + "Id":{ + "shape":"PartnerId", + "documentation":"

    Your unique partner identifier in the AWS Partner Network.

    " + }, + "TaskId":{ + "shape":"QualificationsAssociationTaskId", + "documentation":"

    The unique identifier of the qualifications association task, in the format pqatask-[a-z2-7]{13}.

    " + }, + "Status":{ + "shape":"QualificationsAssociationTaskStatus", + "documentation":"

    The current status of the qualifications association task. Valid values: IN_PROGRESS, SUCCEEDED.

    " + }, + "PrimaryPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The primary partner's profile and account identifiers that the task is associating qualifications with.

    " + }, + "StartedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications association task started, in ISO 8601 format.

    " + }, + "EndedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications association task ended, in ISO 8601 format. This field is present only when the status is SUCCEEDED.

    " + } + } + }, + "GetQualificationsDisassociationTaskRequest":{ + "type":"structure", + "required":[ + "Catalog", + "Identifier" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog in which to look up the qualifications disassociation task. Valid values: AWS, Sandbox.

    " + }, + "Identifier":{ + "shape":"PartnerIdentifier", + "documentation":"

    Your partner identifier. You can provide either a partner ID (for example, partner-abc123) or a partner ARN. You must own this identifier.

    " + } + } + }, + "GetQualificationsDisassociationTaskResponse":{ + "type":"structure", + "required":[ + "Catalog", + "Arn", + "Id", + "TaskId", + "Status", + "AssociatedPartner", + "StartedAt" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog identifier echoed from the request.

    " + }, + "Arn":{ + "shape":"PartnerArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies your partner resource.

    " + }, + "Id":{ + "shape":"PartnerId", + "documentation":"

    Your unique partner identifier in the AWS Partner Network.

    " + }, + "TaskId":{ + "shape":"QualificationsDisassociationTaskId", + "documentation":"

    The unique identifier of the qualifications disassociation task, in the format pqdtask-[a-z2-7]{13}.

    " + }, + "Status":{ + "shape":"QualificationsDisassociationTaskStatus", + "documentation":"

    The current status of the qualifications disassociation task. Valid values: IN_PROGRESS, SUCCEEDED.

    " + }, + "AssociatedPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The primary partner's profile and account identifiers that the task is disassociating qualifications from.

    " + }, + "StartedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications disassociation task started, in ISO 8601 format.

    " + }, + "EndedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications disassociation task ended, in ISO 8601 format. This field is present only when the status is SUCCEEDED.

    " + } + } + }, "GetVerificationRequest":{ "type":"structure", "required":["VerificationType"], @@ -2125,6 +2413,24 @@ } } }, + "Headquarters":{ + "type":"structure", + "required":[ + "CountryCode", + "SubdivisionCode" + ], + "members":{ + "CountryCode":{ + "shape":"CountryCode", + "documentation":"

    The ISO 3166-1 alpha-2 country code of the partner's headquarters. For example, US, BR, or DE.

    " + }, + "SubdivisionCode":{ + "shape":"SubdivisionCode", + "documentation":"

    The subdivision portion of the ISO 3166-2 code for the partner's headquarters (for example, SP from BR-SP, NSW from AU-NSW, or 13 from JP-13).

    " + } + }, + "documentation":"

    Contains the partner's headquarters location using International Organization for Standardization (ISO) 3166 country and subdivision codes.

    " + }, "IndustrySegment":{ "type":"string", "enum":[ @@ -2540,6 +2846,10 @@ "shape":"LocalizedContentList", "documentation":"

    A list of localized content versions for different languages and regions.

    " }, + "Headquarters":{ + "shape":"Headquarters", + "documentation":"

    The ISO 3166 country and subdivision codes for the partner's headquarters location. If no headquarters location is set, this field is not included in the response.

    " + }, "ProfileId":{ "shape":"PartnerProfileId", "documentation":"

    The unique identifier of the partner profile.

    " @@ -2770,6 +3080,58 @@ } } }, + "QualificationsAssociationPartner":{ + "type":"structure", + "members":{ + "ProfileId":{ + "shape":"PartnerProfileId", + "documentation":"

    The unique identifier for the partner profile, in the format pprofile-*. Required in requests if AccountId is not provided.

    " + }, + "AccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The 12-digit AWS account ID linked to the partner profile. Required in requests if ProfileId is not provided.

    " + } + }, + "documentation":"

    Identifies a partner in a qualifications association group. Contains the partner's profile identifier and AWS account identifier. In requests, provide at least one of ProfileId or AccountId. In responses, both fields are populated.

    " + }, + "QualificationsAssociationStatus":{ + "type":"string", + "documentation":"

    The current state of a partner qualifications association. Valid values: ASSOCIATED (the partner is associated with a primary), NOT_ASSOCIATED (the partner has no active association).

    ", + "enum":[ + "ASSOCIATED", + "NOT_ASSOCIATED" + ] + }, + "QualificationsAssociationTaskId":{ + "type":"string", + "documentation":"

    The unique identifier for a qualifications association task, in the format pqatask-[a-z2-7]{13}.

    ", + "max":80, + "min":1, + "pattern":"pqatask-[A-Za-z0-9]{13}" + }, + "QualificationsAssociationTaskStatus":{ + "type":"string", + "documentation":"

    The current status of a qualifications association task. Valid values: IN_PROGRESS (task is running), SUCCEEDED (task completed successfully).

    ", + "enum":[ + "IN_PROGRESS", + "SUCCEEDED" + ] + }, + "QualificationsDisassociationTaskId":{ + "type":"string", + "documentation":"

    The unique identifier for a qualifications disassociation task, in the format pqdtask-[a-z2-7]{13}.

    ", + "max":80, + "min":1, + "pattern":"pqdtask-[A-Za-z0-9]{13}" + }, + "QualificationsDisassociationTaskStatus":{ + "type":"string", + "documentation":"

    The current status of a qualifications disassociation task. Valid values: IN_PROGRESS (task is running), SUCCEEDED (task completed successfully).

    ", + "enum":[ + "IN_PROGRESS", + "SUCCEEDED" + ] + }, "RegistrantVerificationDetails":{ "type":"structure", "members":{}, @@ -2940,7 +3302,9 @@ "RECEIVER_PROFILE_NOT_FOUND", "CONNECTION_INVITATION_NOT_FOUND", "CONNECTION_NOT_FOUND", - "VERIFICATION_NOT_FOUND" + "VERIFICATION_NOT_FOUND", + "QUALIFICATIONS_ASSOCIATION_TASK_NOT_FOUND", + "QUALIFICATIONS_DISASSOCIATION_TASK_NOT_FOUND" ] }, "Revision":{ @@ -3104,6 +3468,144 @@ } } }, + "StartQualificationsAssociationTaskRequest":{ + "type":"structure", + "required":[ + "Catalog", + "Identifier", + "PrimaryPartner" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog in which to perform the qualifications association. Valid values: AWS, Sandbox.

    " + }, + "Identifier":{ + "shape":"PartnerIdentifier", + "documentation":"

    Your partner identifier. You can provide either a partner ID (for example, partner-abc123) or a partner ARN. You must own this identifier.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "PrimaryPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The primary (acquiring) partner's profile and account identifier to associate qualifications with. You must provide at least one of ProfileId or AccountId. You cannot specify yourself as the primary partner.

    " + } + } + }, + "StartQualificationsAssociationTaskResponse":{ + "type":"structure", + "required":[ + "Catalog", + "Arn", + "Id", + "TaskId", + "Status", + "PrimaryPartner", + "StartedAt" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog identifier echoed from the request.

    " + }, + "Arn":{ + "shape":"PartnerArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies your partner resource.

    " + }, + "Id":{ + "shape":"PartnerId", + "documentation":"

    Your unique partner identifier in the AWS Partner Network.

    " + }, + "TaskId":{ + "shape":"QualificationsAssociationTaskId", + "documentation":"

    The unique identifier of the started qualifications association task, in the format pqatask-[a-z2-7]{13}.

    " + }, + "Status":{ + "shape":"QualificationsAssociationTaskStatus", + "documentation":"

    The current status of the qualifications association task. The initial value is IN_PROGRESS.

    " + }, + "PrimaryPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The resolved primary partner's profile and account identifiers, including both ProfileId and AccountId.

    " + }, + "StartedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications association task started, in ISO 8601 format.

    " + } + } + }, + "StartQualificationsDisassociationTaskRequest":{ + "type":"structure", + "required":[ + "Catalog", + "Identifier", + "AssociatedPartner" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog in which to perform the qualifications disassociation. Valid values: AWS, Sandbox.

    " + }, + "Identifier":{ + "shape":"PartnerIdentifier", + "documentation":"

    Your partner identifier. You can provide either a partner ID (for example, partner-abc123) or a partner ARN. You must own this identifier.

    " + }, + "ClientToken":{ + "shape":"ClientToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "AssociatedPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The primary partner's profile and account identifier that you are currently associated with and will disassociate from. You must provide at least one of ProfileId or AccountId. The specified partner must match your current primary association.

    " + } + } + }, + "StartQualificationsDisassociationTaskResponse":{ + "type":"structure", + "required":[ + "Catalog", + "Arn", + "Id", + "TaskId", + "Status", + "AssociatedPartner", + "StartedAt" + ], + "members":{ + "Catalog":{ + "shape":"Catalog", + "documentation":"

    The catalog identifier echoed from the request.

    " + }, + "Arn":{ + "shape":"PartnerArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies your partner resource.

    " + }, + "Id":{ + "shape":"PartnerId", + "documentation":"

    Your unique partner identifier in the AWS Partner Network.

    " + }, + "TaskId":{ + "shape":"QualificationsDisassociationTaskId", + "documentation":"

    The unique identifier of the started qualifications disassociation task, in the format pqdtask-[a-z2-7]{13}.

    " + }, + "Status":{ + "shape":"QualificationsDisassociationTaskStatus", + "documentation":"

    The current status of the qualifications disassociation task. The initial value is IN_PROGRESS.

    " + }, + "AssociatedPartner":{ + "shape":"QualificationsAssociationPartner", + "documentation":"

    The resolved primary partner's profile and account identifiers that the task is disassociating qualifications from.

    " + }, + "StartedAt":{ + "shape":"DateTime", + "documentation":"

    The timestamp when the qualifications disassociation task started, in ISO 8601 format.

    " + } + } + }, "StartVerificationRequest":{ "type":"structure", "members":{ @@ -3154,6 +3656,12 @@ } }, "String":{"type":"string"}, + "SubdivisionCode":{ + "type":"string", + "max":3, + "min":1, + "pattern":"[A-Z0-9]{1,3}" + }, "Tag":{ "type":"structure", "required":[ @@ -3264,6 +3772,10 @@ "LocalizedContents":{ "shape":"LocalizedContentList", "documentation":"

    The updated localized content for the partner profile.

    " + }, + "Headquarters":{ + "shape":"Headquarters", + "documentation":"

    The ISO 3166 country and subdivision codes for the partner's headquarters location. If you omit this field, the service retains the existing headquarters value.

    " } }, "documentation":"

    Contains detailed information about a profile update task including the changes to be made.

    " diff --git a/services/partnercentralbenefits/pom.xml b/services/partnercentralbenefits/pom.xml index 93444153852c..b696eca961d6 100644 --- a/services/partnercentralbenefits/pom.xml +++ b/services/partnercentralbenefits/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT partnercentralbenefits AWS Java SDK :: Services :: Partner Central Benefits diff --git a/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bc0f639564f9 --- /dev/null +++ b/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-benefits-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-benefits.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 53f6026677e4..000000000000 --- a/services/partnercentralbenefits/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-benefits-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://partnercentral-benefits.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/partnercentralchannel/pom.xml b/services/partnercentralchannel/pom.xml index dfa4760f3247..2d173c2560c8 100644 --- a/services/partnercentralchannel/pom.xml +++ b/services/partnercentralchannel/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT partnercentralchannel AWS Java SDK :: Services :: Partner Central Channel diff --git a/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9938b5efad14 --- /dev/null +++ b/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,201 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-channel.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-channel-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-channel-fips.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-channel.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 8, + "nodes": "/////wAAAAH/////AAAAAAAAAAgAAAADAAAAAQAAAAQF9eEHAAAAAgAAAAUF9eEHAAAAAwAAAAcAAAAGAAAABAX14QUF9eEGAAAABAX14QQF9eEDAAAABAX14QEF9eEC" +} \ No newline at end of file diff --git a/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index dd4839f25e56..000000000000 --- a/services/partnercentralchannel/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,269 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://partnercentral-channel.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-channel-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-channel-fips.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://partnercentral-channel.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/partnercentralrevenuemeasurement/pom.xml b/services/partnercentralrevenuemeasurement/pom.xml index d2a66ce899cf..8f30e3928295 100644 --- a/services/partnercentralrevenuemeasurement/pom.xml +++ b/services/partnercentralrevenuemeasurement/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT partnercentralrevenuemeasurement AWS Java SDK :: Services :: Partner Central Revenue Measurement diff --git a/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4b9d2a94b272 --- /dev/null +++ b/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,201 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-prm.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-prm-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-prm-fips.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-prm.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 8, + "nodes": "/////wAAAAH/////AAAAAAAAAAgAAAADAAAAAQAAAAQF9eEHAAAAAgAAAAUF9eEHAAAAAwAAAAcAAAAGAAAABAX14QUF9eEGAAAABAX14QQF9eEDAAAABAX14QEF9eEC" +} \ No newline at end of file diff --git a/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4059c3264171..000000000000 --- a/services/partnercentralrevenuemeasurement/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,269 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://partnercentral-prm.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-prm-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-prm-fips.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://partnercentral-prm.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/partnercentralselling/pom.xml b/services/partnercentralselling/pom.xml index 89cad615df70..9ab2547161e0 100644 --- a/services/partnercentralselling/pom.xml +++ b/services/partnercentralselling/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT partnercentralselling AWS Java SDK :: Services :: Partner Central Selling diff --git a/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c07c3d565749 --- /dev/null +++ b/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-selling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://partnercentral-selling.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index baf1fb426cb4..000000000000 --- a/services/partnercentralselling/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://partnercentral-selling-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://partnercentral-selling.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file 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 86e100f920d4..b6bdee24a563 100644 --- a/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json +++ b/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json @@ -1273,7 +1273,8 @@ }, "AwsMaturity":{ "type":"string", - "pattern":"(?s).{1,20}" + "max":255, + "min":0 }, "AwsMemberBusinessTitle":{ "type":"string", @@ -1283,7 +1284,8 @@ "WWPSPDM", "PDM", "PSM", - "ISVSM" + "ISVSM", + "Signatory" ] }, "AwsOpportunityCustomer":{ @@ -1459,6 +1461,10 @@ "CosellMotion":{ "shape":"String", "documentation":"

    Engagement classification for this opportunity. Read-only. Null before scoring. Known values: AWS Field-engaged, Agent-engaged, Partner-led.

    " + }, + "SoftwareRevenue":{ + "shape":"AwsSoftwareRevenue", + "documentation":"

    Seller-provided PARC deal terms: commitment value, discount, and contract dates.

    " } }, "documentation":"

    Provides a comprehensive view of AwsOpportunitySummaryFullView template.

    " @@ -1607,6 +1613,25 @@ }, "documentation":"

    Source-separated spend insights that provide independent analysis for AWS recommendations and partner estimates.

    " }, + "AwsSoftwareRevenue":{ + "type":"structure", + "members":{ + "Value":{"shape":"MonetaryValue"}, + "Discount":{ + "shape":"String", + "documentation":"

    Discount percentage offered on the software revenue. Percent convention: 15.00 means 15%.

    " + }, + "EffectiveDate":{ + "shape":"String", + "documentation":"

    Contract effective (start) date in YYYY-MM-DD format.

    " + }, + "ExpirationDate":{ + "shape":"String", + "documentation":"

    Contract expiration (end) date in YYYY-MM-DD format.

    " + } + }, + "documentation":"

    Seller-provided PARC deal terms for the opportunity, including commitment value, discount percentage, and contract dates.

    " + }, "AwsSubmission":{ "type":"structure", "required":["InvolvementType"], @@ -1656,6 +1681,7 @@ }, "CatalogIdentifier":{ "type":"string", + "documentation":"

    Value space is validated at runtime against an allowlist, so the model keeps only a coarse character-class pattern.

    ", "pattern":"[a-zA-Z]+" }, "Channel":{ @@ -2143,9 +2169,7 @@ "type":"structure", "required":[ "Catalog", - "ClientToken", - "Title", - "Description" + "ClientToken" ], "members":{ "Catalog":{ @@ -2586,7 +2610,8 @@ }, "CustomerAction":{ "type":"string", - "pattern":"(?s).{1,255}" + "max":255, + "min":0 }, "CustomerContactsList":{ "type":"list", @@ -3151,11 +3176,26 @@ }, "EngagementTitle":{ "type":"string", - "pattern":"(?s).{1,40}" + "pattern":"(?s).{0,40}" }, "EngagementUseCase":{ "type":"string", - "pattern":"(?s).{1,255}" + "max":255, + "min":0 + }, + "EnrichmentContext":{ + "type":"structure", + "members":{ + "ProspectingResultAws":{ + "shape":"InvitationProspectingResultAws", + "documentation":"

    The customer account data and propensity insights for the prospected account. It includes geographic, industry, and segment classifications, along with engagement and solution scoring.

    " + }, + "LeadInsights":{ + "shape":"LeadInsights", + "documentation":"

    The AI-generated lead readiness score for this lead. Use this score to assess lead quality and prioritize engagement efforts.

    " + } + }, + "documentation":"

    Contains enrichment data for engagement invitations. You can view propensity scores, program eligibility, and lead readiness insights directly in the invitation, before you take action on the invitation.

    " }, "EstimationUrl":{ "type":"string", @@ -3294,6 +3334,10 @@ "shape":"String", "documentation":"

    Engagement classification for this opportunity. Read-only. Null before scoring. Known values: AWS Field-engaged, Agent-engaged, Partner-led.

    " }, + "SoftwareRevenue":{ + "shape":"AwsSoftwareRevenue", + "documentation":"

    Seller-provided PARC deal terms: commitment value, discount, and contract dates.

    " + }, "Catalog":{ "shape":"CatalogIdentifier", "documentation":"

    Specifies the catalog in which the AWS Opportunity exists. This is the environment (e.g., AWS or Sandbox) where the opportunity is being managed.

    " @@ -3391,6 +3435,10 @@ "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.

    " + }, + "EnrichmentContext":{ + "shape":"EnrichmentContext", + "documentation":"

    The enrichment data for the engagement associated with this invitation. You can view propensity scores, program eligibility, and lead readiness assessments before taking action on the invitation.

    " } } }, @@ -3858,6 +3906,20 @@ "pattern":"(?s).{1,255}", "sensitive":true }, + "InvitationProspectingResultAws":{ + "type":"structure", + "members":{ + "Customer":{ + "shape":"ProspectingResultCustomer", + "documentation":"

    The prospected customer account details, including geographic classification, industry segmentation, company size, and program eligibility.

    " + }, + "Insights":{ + "shape":"ProspectingInsights", + "documentation":"

    The AI-generated insights from the prospecting analysis, including marketplace engagement scoring, solution fit assessments, and solution categorization.

    " + } + }, + "documentation":"

    A subset of prospecting result data visible to invitation receivers. It includes customer account details and AI-generated insights.

    " + }, "InvitationStatus":{ "type":"string", "enum":[ @@ -3902,6 +3964,49 @@ }, "documentation":"

    Defines a filter to retrieve opportunities based on the last modified date. This filter is useful for tracking changes or updates to opportunities over time.

    " }, + "LeadAddress":{ + "type":"structure", + "members":{ + "City":{ + "shape":"LeadAddressCityString", + "documentation":"

    The city of the lead customer's address.

    " + }, + "PostalCode":{ + "shape":"LeadAddressPostalCodeString", + "documentation":"

    The postal code of the lead customer's address.

    " + }, + "StateOrRegion":{ + "shape":"LeadAddressStateOrRegionString", + "documentation":"

    The state or region of the lead customer's address.

    " + }, + "CountryCode":{ + "shape":"LeadCountryCode", + "documentation":"

    The country code of the lead customer's address.

    " + } + }, + "documentation":"

    The address information for a lead customer, including city, state or region, postal code, and country code.

    " + }, + "LeadAddressCityString":{ + "type":"string", + "max":255, + "min":0 + }, + "LeadAddressPostalCodeString":{ + "type":"string", + "max":20, + "min":0 + }, + "LeadAddressStateOrRegionString":{ + "type":"string", + "max":255, + "min":0 + }, + "LeadBusinessProblem":{ + "type":"string", + "max":2000, + "min":0, + "sensitive":true + }, "LeadContact":{ "type":"structure", "required":[ @@ -3912,11 +4017,11 @@ ], "members":{ "BusinessTitle":{ - "shape":"JobTitle", + "shape":"LeadJobTitle", "documentation":"

    The lead contact's business title or job role associated with the engagement.

    " }, "Email":{ - "shape":"Email", + "shape":"LeadEmail", "documentation":"

    The lead contact's email address associated with the engagement.

    " }, "FirstName":{ @@ -3928,7 +4033,7 @@ "documentation":"

    The lead contact's last name associated with the engagement.

    " }, "Phone":{ - "shape":"PhoneNumber", + "shape":"LeadPhoneNumber", "documentation":"

    The lead contact's phone number associated with the engagement.

    " } }, @@ -3960,15 +4065,18 @@ }, "documentation":"

    Provides comprehensive details about a lead associated with an engagement. This structure contains information about lead qualification status, customer details, and interaction history to facilitate lead management and tracking within the engagement.

    " }, + "LeadCountryCode":{ + "type":"string", + "max":10, + "min":0, + "sensitive":true + }, "LeadCustomer":{ "type":"structure", - "required":[ - "CompanyName", - "Address" - ], + "required":["CompanyName"], "members":{ "Industry":{ - "shape":"Industry", + "shape":"LeadIndustry", "documentation":"

    Specifies the industry sector to which the lead customer's company belongs. This categorization helps in understanding the customer's business context and tailoring appropriate solutions.

    " }, "CompanyName":{ @@ -3976,21 +4084,35 @@ "documentation":"

    The name of the lead customer's company. This field is essential for identifying and tracking the customer organization associated with the lead.

    " }, "WebsiteUrl":{ - "shape":"CompanyWebsiteUrl", + "shape":"LeadWebsiteUrl", "documentation":"

    The website URL of the lead customer's company. This provides additional context about the customer organization and helps verify company legitimacy and size.

    " }, - "Address":{"shape":"AddressSummary"}, + "Address":{ + "shape":"LeadAddress", + "documentation":"

    The address information for the lead customer.

    " + }, "AwsMaturity":{ "shape":"AwsMaturity", "documentation":"

    Indicates the customer's level of experience and adoption with AWS services. This assessment helps determine the appropriate engagement approach and solution complexity.

    " }, "MarketSegment":{ - "shape":"MarketSegment", + "shape":"LeadMarketSegment", "documentation":"

    Specifies the market segment classification of the lead customer, such as enterprise, mid-market, or small business. This segmentation helps in targeting appropriate solutions and engagement strategies.

    " } }, "documentation":"

    Contains detailed information about the customer associated with the lead, including company details, industry classification, and AWS maturity level. This information helps qualify and categorize the lead for appropriate engagement strategies.

    " }, + "LeadEmail":{ + "type":"string", + "max":255, + "min":1, + "sensitive":true + }, + "LeadIndustry":{ + "type":"string", + "max":255, + "min":0 + }, "LeadInsights":{ "type":"structure", "members":{ @@ -4003,13 +4125,7 @@ }, "LeadInteraction":{ "type":"structure", - "required":[ - "SourceType", - "SourceId", - "SourceName", - "CustomerAction", - "Contact" - ], + "required":["Contact"], "members":{ "SourceType":{ "shape":"LeadSourceType", @@ -4036,7 +4152,7 @@ "documentation":"

    Describes the action taken by the customer during or as a result of the interaction, such as requesting information, scheduling a meeting, or expressing interest in a solution.

    " }, "BusinessProblem":{ - "shape":"EngagementCustomerBusinessProblem", + "shape":"LeadBusinessProblem", "documentation":"

    Describes the business problem or challenge that the customer discussed during the interaction. This information helps qualify the lead and identify appropriate solutions.

    " }, "Contact":{ @@ -4054,13 +4170,10 @@ }, "LeadInvitationCustomer":{ "type":"structure", - "required":[ - "CompanyName", - "CountryCode" - ], + "required":["CompanyName"], "members":{ "Industry":{ - "shape":"Industry", + "shape":"LeadIndustry", "documentation":"

    Specifies the industry sector of the customer company associated with the lead invitation. This categorization helps partners understand the customer's business context and assess solution fit.

    " }, "CompanyName":{ @@ -4068,11 +4181,11 @@ "documentation":"

    The name of the customer company associated with the lead invitation. This field identifies the target organization for the lead engagement opportunity.

    " }, "WebsiteUrl":{ - "shape":"CompanyWebsiteUrl", + "shape":"LeadWebsiteUrl", "documentation":"

    The website URL of the customer company. This provides additional context about the customer organization and helps partners verify company details and assess business size and legitimacy.

    " }, "CountryCode":{ - "shape":"CountryCode", + "shape":"LeadCountryCode", "documentation":"

    The country code indicating the geographic location of the customer company. This information helps partners understand regional requirements and assess their ability to serve the customer effectively.

    " }, "AwsMaturity":{ @@ -4080,7 +4193,7 @@ "documentation":"

    Indicates the customer's level of experience and adoption with AWS services. This assessment helps partners understand the customer's cloud maturity and tailor their engagement approach accordingly.

    " }, "MarketSegment":{ - "shape":"MarketSegment", + "shape":"LeadMarketSegment", "documentation":"

    Specifies the market segment classification of the customer, such as enterprise, mid-market, or small business. This segmentation helps partners determine the appropriate solution complexity and engagement strategy.

    " } }, @@ -4088,12 +4201,7 @@ }, "LeadInvitationInteraction":{ "type":"structure", - "required":[ - "SourceType", - "SourceId", - "SourceName", - "ContactBusinessTitle" - ], + "required":["ContactBusinessTitle"], "members":{ "SourceType":{ "shape":"LeadSourceType", @@ -4136,21 +4244,44 @@ }, "documentation":"

    Represents the data payload of an engagement invitation for a lead opportunity. This contains detailed information about the customer and interaction history that partners use to evaluate whether to accept the lead engagement invitation.

    " }, + "LeadJobTitle":{ + "type":"string", + "max":255, + "min":1, + "sensitive":true + }, + "LeadMarketSegment":{ + "type":"string", + "max":255, + "min":0 + }, + "LeadPhoneNumber":{ + "type":"string", + "max":255, + "min":0, + "sensitive":true + }, "LeadQualificationStatus":{ "type":"string", "pattern":"(?s).{1,255}" }, "LeadSourceId":{ "type":"string", - "pattern":"(?s).{1,255}" + "pattern":"(?s).{0,255}" }, "LeadSourceName":{ "type":"string", - "pattern":"(?s).{1,255}" + "pattern":"(?s).{0,255}" }, "LeadSourceType":{ "type":"string", - "pattern":"(?s).{1,255}" + "pattern":"(?s).{0,255}" + }, + "LeadWebsiteUrl":{ + "type":"string", + "max":255, + "min":0, + "sensitive":true }, "LifeCycle":{ "type":"structure", @@ -5176,16 +5307,6 @@ "type":"string", "enum":["StartTime"] }, - "MarketSegment":{ - "type":"string", - "enum":[ - "Enterprise", - "Large", - "Medium", - "Small", - "Micro" - ] - }, "Marketing":{ "type":"structure", "members":{ @@ -5827,6 +5948,14 @@ "ProspectingResultAws":{ "type":"structure", "members":{ + "Customer":{ + "shape":"ProspectingResultCustomer", + "documentation":"

    Contains details about the prospected customer account, including geographic, industry, and segment classifications.

    " + }, + "Insights":{ + "shape":"ProspectingInsights", + "documentation":"

    Insights that AI generates from the prospecting analysis. These insights include engagement scores and solution fit assessments for the prospected customer.

    " + }, "StartTime":{ "shape":"DateTime", "documentation":"

    The timestamp when the prospecting result context was created. The format is ISO 8601 (UTC).

    " @@ -5846,14 +5975,6 @@ "TaskName":{ "shape":"TaskName", "documentation":"

    The name that the user provides for the prospecting task that generates this result.

    " - }, - "Customer":{ - "shape":"ProspectingResultCustomer", - "documentation":"

    Contains details about the prospected customer account, including geographic, industry, and segment classifications.

    " - }, - "Insights":{ - "shape":"ProspectingInsights", - "documentation":"

    Insights that AI generates from the prospecting analysis. These insights include engagement scores and solution fit assessments for the prospected customer.

    " } }, "documentation":"

    Contains the prospecting data that AWS sources. This includes task execution details, customer account information, and insights that AI generates from the prospecting analysis.

    " @@ -7329,5 +7450,5 @@ "sensitive":true } }, - "documentation":"

    AWS Partner Central API for Selling

    AWS Partner Central API for Selling Reference Guide

    This Amazon Web Services (AWS) Partner Central API reference is designed to help AWS Partners integrate Customer Relationship Management (CRM) systems with AWS Partner Central. Partners can automate interactions with AWS Partner Central, which helps to ensure effective engagements in joint business activities.

    The API provides standard AWS API functionality. Access it by either using API Actions or by using an AWS SDK that's tailored to your programming language or platform. For more information, see Getting Started with AWS and Tools to Build on AWS.

    Features offered by AWS Partner Central API

    1. Opportunity management: Manages coselling opportunities through API actions such as CreateOpportunity, UpdateOpportunity, ListOpportunities, GetOpportunity, and AssignOpportunity.

    2. AWS referral management: Manages referrals shared by AWS using actions such as ListEngagementInvitations, GetEngagementInvitation, StartEngagementByAcceptingInvitation, and RejectEngagementInvitation.

    3. Entity association: Associates related entities such as AWS Products, Partner Solutions, and AWS Marketplace Private Offers with opportunities using the actions AssociateOpportunity, and DisassociateOpportunity.

    4. View AWS opportunity details: Retrieves real-time summaries of AWS opportunities using the GetAWSOpportunitySummary action.

    5. List solutions: Provides list APIs for listing partner offers using ListSolutions.

    6. Event subscription: Subscribe to real-time opportunity updates through AWS EventBridge by using actions such as Opportunity Created, Opportunity Updated, Engagement Invitation Accepted, Engagement Invitation Rejected, and Engagement Invitation Created.

    " + "documentation":"

    Partner Central

    This Amazon Web Services (AWS) Partner Central API reference is designed to help AWS Partners integrate Customer Relationship Management (CRM) systems with AWS Partner Central. Partners can automate interactions with AWS Partner Central, which helps to ensure effective engagements in joint business activities.

    The API provides standard AWS API functionality. Access it by either using API Actions or by using an AWS SDK that's tailored to your programming language or platform. For more information, see Getting Started with AWS and Tools to Build on AWS.

    Features offered by AWS Partner Central API

    1. Opportunity management: Manages coselling opportunities through API actions such as CreateOpportunity, UpdateOpportunity, ListOpportunities, GetOpportunity, and AssignOpportunity.

    2. AWS referral management: Manages referrals shared by AWS using actions such as ListEngagementInvitations, GetEngagementInvitation, StartEngagementByAcceptingInvitation, and RejectEngagementInvitation.

    3. Entity association: Associates related entities such as AWS Products, Partner Solutions, and AWS Marketplace Private Offers with opportunities using the actions AssociateOpportunity, and DisassociateOpportunity.

    4. View AWS opportunity details: Retrieves real-time summaries of AWS opportunities using the GetAWSOpportunitySummary action.

    5. List solutions: Provides list APIs for listing partner offers using ListSolutions.

    6. Event subscription: Subscribe to real-time opportunity updates through AWS EventBridge by using actions such as Opportunity Created, Opportunity Updated, Engagement Invitation Accepted, Engagement Invitation Rejected, and Engagement Invitation Created.

    " } diff --git a/services/paymentcryptography/pom.xml b/services/paymentcryptography/pom.xml index f07c3faf5544..ede7a6e749b1 100644 --- a/services/paymentcryptography/pom.xml +++ b/services/paymentcryptography/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT paymentcryptography AWS Java SDK :: Services :: Payment Cryptography diff --git a/services/paymentcryptography/src/main/resources/codegen-resources/customization.config b/services/paymentcryptography/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/paymentcryptography/src/main/resources/codegen-resources/customization.config +++ b/services/paymentcryptography/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..76b9bf3c3b80 --- /dev/null +++ b/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlplane.payment-cryptography-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlplane.payment-cryptography-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlplane.payment-cryptography.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://controlplane.payment-cryptography.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index af333e02061a..000000000000 --- a/services/paymentcryptography/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlplane.payment-cryptography-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlplane.payment-cryptography-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlplane.payment-cryptography.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://controlplane.payment-cryptography.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/paymentcryptographydata/pom.xml b/services/paymentcryptographydata/pom.xml index df9fb1624ad0..76d33dc7ff1e 100644 --- a/services/paymentcryptographydata/pom.xml +++ b/services/paymentcryptographydata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT paymentcryptographydata AWS Java SDK :: Services :: Payment Cryptography Data diff --git a/services/paymentcryptographydata/src/main/resources/codegen-resources/customization.config b/services/paymentcryptographydata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/paymentcryptographydata/src/main/resources/codegen-resources/customization.config +++ b/services/paymentcryptographydata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..32c873846e49 --- /dev/null +++ b/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataplane.payment-cryptography-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataplane.payment-cryptography-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataplane.payment-cryptography.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://dataplane.payment-cryptography.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b7d8a8a7a88c..000000000000 --- a/services/paymentcryptographydata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataplane.payment-cryptography-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataplane.payment-cryptography-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataplane.payment-cryptography.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://dataplane.payment-cryptography.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/paymentcryptographydata/src/main/resources/codegen-resources/service-2.json b/services/paymentcryptographydata/src/main/resources/codegen-resources/service-2.json index b6d34c71f97a..8703ff3a5916 100644 --- a/services/paymentcryptographydata/src/main/resources/codegen-resources/service-2.json +++ b/services/paymentcryptographydata/src/main/resources/codegen-resources/service-2.json @@ -173,7 +173,7 @@ {"shape":"ThrottlingException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Re-encrypt ciphertext using DUKPT or Symmetric data encryption keys.

    You can either generate an encryption key within Amazon Web Services Payment Cryptography by calling CreateKey or import your own encryption key by calling ImportKey. The KeyArn for use with this operation must be in a compatible key state with KeyModesOfUse set to Encrypt.

    This operation also supports dynamic keys, allowing you to pass a dynamic encryption key as a TR-31 WrappedKeyBlock. This can be used when key material is frequently rotated, such as during every card transaction, and there is need to avoid importing short-lived keys into Amazon Web Services Payment Cryptography. To re-encrypt using dynamic keys, the keyARN is the Key Encryption Key (KEK) of the TR-31 wrapped encryption key material. The incoming wrapped key shall have a key purpose of D0 with a mode of use of B or D. For more information, see Using Dynamic Keys in the Amazon Web Services Payment Cryptography User Guide.

    For symmetric and DUKPT encryption, Amazon Web Services Payment Cryptography supports TDES and AES algorithms. To encrypt using DUKPT, a DUKPT key must already exist within your account with KeyModesOfUse set to DeriveKey or a new DUKPT can be generated by calling CreateKey.

    For information about valid keys for this operation, see Understanding key attributes and Key types for specific data operations in the Amazon Web Services Payment Cryptography User Guide.

    Cross-account use: This operation supports cross-account use when the key has a resource-based policy that grants access. For more information, see Resource-based policies.

    Related operations:

    " + "documentation":"

    Re-encrypts ciphertext using DUKPT, symmetric, or asymmetric data encryption keys.

    You can either generate an encryption key within Amazon Web Services Payment Cryptography by calling CreateKey or import your own encryption key by calling ImportKey. The KeyArn for use with this operation must be in a compatible key state with KeyModesOfUse set to Encrypt.

    This operation also supports dynamic keys, allowing you to pass a dynamic encryption key as a TR-31 WrappedKeyBlock. This can be used when key material is frequently rotated, such as during every card transaction, and there is need to avoid importing short-lived keys into Amazon Web Services Payment Cryptography. To re-encrypt using dynamic keys, the keyARN is the Key Encryption Key (KEK) of the TR-31 wrapped encryption key material. The incoming wrapped key shall have a key purpose of D0 with a mode of use of B or D. For more information, see Using Dynamic Keys in the Amazon Web Services Payment Cryptography User Guide.

    Amazon Web Services Payment Cryptography supports the following encryption key schemes:

    • DUKPT: TDES and AES algorithms. To encrypt using DUKPT, a DUKPT key must already exist within your account with KeyModesOfUse set to DeriveKey or a new DUKPT can be generated by calling CreateKey.

    • Symmetric: TDES and AES algorithms.

    • Asymmetric: RSA. You can use an RSA key on either the incoming or the outgoing side, paired with a symmetric key on the other side.

    For information about valid keys for this operation, see Understanding key attributes and Key types for specific data operations in the Amazon Web Services Payment Cryptography User Guide.

    Cross-account use: This operation supports cross-account use when the key has a resource-based policy that grants access. For more information, see Resource-based policies.

    Related operations:

    " }, "TranslateKeyMaterial":{ "name":"TranslateKeyMaterial", @@ -2277,9 +2277,16 @@ "members":{ "Symmetric":{ "shape":"SymmetricEncryptionAttributes", - "documentation":"

    Parameters that are required to encrypt data using symmetric keys.

    " + "documentation":"

    Specifies the parameters required to encrypt data using symmetric keys.

    " }, - "Dukpt":{"shape":"DukptEncryptionAttributes"} + "Asymmetric":{ + "shape":"AsymmetricEncryptionAttributes", + "documentation":"

    Specifies the parameters required to encrypt data using an asymmetric key pair. You must specify a PaddingType.

    " + }, + "Dukpt":{ + "shape":"DukptEncryptionAttributes", + "documentation":"

    Specifies the parameters required to encrypt data using DUKPT.

    " + } }, "documentation":"

    Parameters that are required to perform reencryption operation.

    ", "union":true @@ -2353,6 +2360,10 @@ "Visa":{ "shape":"SessionKeyVisa", "documentation":"

    Parameters to derive session key for a Visa payment cardfor ARQC verification.

    " + }, + "UnionPay":{ + "shape":"SessionKeyUnionPay", + "documentation":"

    Parameters to derive session key for a UnionPay payment card for Authorization Request Cryptogram (ARQC) generation and verification.

    " } }, "documentation":"

    Parameters to derive a session key for Authorization Response Cryptogram (ARQC) verification.

    ", @@ -2365,7 +2376,8 @@ "EMV2000", "AMEX", "MASTERCARD_SESSION_KEY", - "VISA" + "VISA", + "UNION_PAY" ] }, "SessionKeyDerivationValue":{ @@ -2457,6 +2469,29 @@ }, "documentation":"

    Parameters to derive session key for Mastercard payment card for ARQC verification.

    " }, + "SessionKeyUnionPay":{ + "type":"structure", + "required":[ + "PrimaryAccountNumber", + "PanSequenceNumber", + "ApplicationTransactionCounter" + ], + "members":{ + "PrimaryAccountNumber":{ + "shape":"PrimaryAccountNumberType", + "documentation":"

    The Primary Account Number (PAN) of the cardholder. A PAN is a unique identifier for a payment credit or debit card and associates the card to a specific account holder.

    " + }, + "PanSequenceNumber":{ + "shape":"NumberLengthEquals2", + "documentation":"

    A number that identifies and differentiates payment cards with the same Primary Account Number (PAN). If not used, enter 00.

    " + }, + "ApplicationTransactionCounter":{ + "shape":"HexLengthEquals4", + "documentation":"

    The transaction counter that the terminal provides during transaction processing. This value is in hexadecimal format. For example, enter a decimal counter of 109 as 006D.

    " + } + }, + "documentation":"

    Parameters to derive session key for a UnionPay payment card for Authorization Request Cryptogram (ARQC) generation and verification.

    " + }, "SessionKeyVisa":{ "type":"structure", "required":[ diff --git a/services/pcaconnectorad/pom.xml b/services/pcaconnectorad/pom.xml index eef4651ff404..7d4a916e8488 100644 --- a/services/pcaconnectorad/pom.xml +++ b/services/pcaconnectorad/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pcaconnectorad AWS Java SDK :: Services :: Pca Connector Ad diff --git a/services/pcaconnectorad/src/main/resources/codegen-resources/customization.config b/services/pcaconnectorad/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/pcaconnectorad/src/main/resources/codegen-resources/customization.config +++ b/services/pcaconnectorad/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3a415f40ec75 --- /dev/null +++ b/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-ad-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-ad-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-ad.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-ad.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c2826905f3d7..000000000000 --- a/services/pcaconnectorad/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-ad-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-ad-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-ad.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-ad.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/pcaconnectorscep/pom.xml b/services/pcaconnectorscep/pom.xml index b36624a91917..dd2fe4073829 100644 --- a/services/pcaconnectorscep/pom.xml +++ b/services/pcaconnectorscep/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pcaconnectorscep AWS Java SDK :: Services :: Pca Connector Scep diff --git a/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8b297d6fdf27 --- /dev/null +++ b/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-scep-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-scep-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-scep.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pca-connector-scep.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 789f9ad49a53..000000000000 --- a/services/pcaconnectorscep/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-scep-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-scep-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-scep.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pca-connector-scep.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/pcs/pom.xml b/services/pcs/pom.xml index b170cb11ef37..e961fb5af30d 100644 --- a/services/pcs/pom.xml +++ b/services/pcs/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pcs AWS Java SDK :: Services :: PCS diff --git a/services/pcs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pcs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..36599f86c15f --- /dev/null +++ b/services/pcs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pcs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pcs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pcs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pcs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pcs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pcs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0a01f03f0a67..000000000000 --- a/services/pcs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pcs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pcs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pcs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pcs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/pcs/src/main/resources/codegen-resources/service-2.json b/services/pcs/src/main/resources/codegen-resources/service-2.json index d95c4c707207..774a8fa676a2 100644 --- a/services/pcs/src/main/resources/codegen-resources/service-2.json +++ b/services/pcs/src/main/resources/codegen-resources/service-2.json @@ -318,7 +318,7 @@ {"shape":"InternalServerException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Updates a cluster configuration. You can upgrade the Slurm version, modify scheduler settings, and update accounting configuration for an existing cluster. For more information about upgrading the Slurm version, see Upgrading the Slurm version on a cluster in the PCS User Guide.

    You can only update clusters that are in ACTIVE, UPDATE_FAILED, or SUSPENDED state. All associated resources (queues and compute node groups) must be in ACTIVE state before you can update the cluster.

    ", + "documentation":"

    Updates a cluster configuration. You can update the scheduler version, modify scheduler settings, and update accounting configuration for an existing cluster. For more information about updating the scheduler version, see Updating the scheduler version on a cluster in the PCS User Guide.

    You can only update clusters that are in ACTIVE, UPDATE_FAILED, or SUSPENDED state. All associated resources (queues and compute node groups) must be in ACTIVE state before you can update the cluster.

    ", "idempotent":true }, "UpdateComputeNodeGroup":{ @@ -734,6 +734,10 @@ }, "spotOptions":{"shape":"SpotOptions"}, "slurmConfiguration":{"shape":"ComputeNodeGroupSlurmConfiguration"}, + "nodeLifecycleActions":{ + "shape":"NodeLifecycleActions", + "documentation":"

    The lifecycle actions to run on compute nodes in the compute node group. Use lifecycle actions to run custom scripts at defined stages of a compute node's lifecycle, such as when a compute node finishes bootstrapping or becomes ready to accept jobs.

    " + }, "errorInfo":{ "shape":"ErrorInfoList", "documentation":"

    The list of errors that occurred during compute node group provisioning.

    " @@ -779,6 +783,10 @@ "slurmCustomSettings":{ "shape":"SlurmCustomSettings", "documentation":"

    Additional Slurm-specific configuration that directly maps to Slurm settings.

    " + }, + "gresCustomSettings":{ + "shape":"GresCustomSettings", + "documentation":"

    The additional Slurm gres.conf records for the compute node group. Each item is a map of gres.conf attribute names to values that describes one gres.conf record, such as a GPU topology, MIG, MPS, or custom GRES entry. PCS adds the NodeName= prefix and merges these records with the GPU record it derives from the instance type.

    " } }, "documentation":"

    Additional options related to the Slurm scheduler.

    " @@ -793,6 +801,10 @@ "slurmCustomSettings":{ "shape":"SlurmCustomSettings", "documentation":"

    Additional Slurm-specific configuration that directly maps to Slurm settings.

    " + }, + "gresCustomSettings":{ + "shape":"GresCustomSettings", + "documentation":"

    The additional Slurm gres.conf records for the compute node group. Each item is a map of gres.conf attribute names to values that describes one gres.conf record, such as a GPU topology, MIG, MPS, or custom GRES entry. PCS adds the NodeName= prefix and merges these records with the GPU record it derives from the instance type.

    " } }, "documentation":"

    Additional options related to the Slurm scheduler.

    " @@ -988,6 +1000,10 @@ "shape":"ComputeNodeGroupSlurmConfigurationRequest", "documentation":"

    Additional options related to the Slurm scheduler.

    " }, + "nodeLifecycleActions":{ + "shape":"NodeLifecycleActionsRequest", + "documentation":"

    The lifecycle actions to run on compute nodes in the compute node group. Use lifecycle actions to run custom scripts at defined stages of a compute node's lifecycle, such as when a compute node finishes bootstrapping or becomes ready to accept jobs.

    " + }, "clientToken":{ "shape":"SBClientToken", "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Idempotency ensures that an API request completes only once. With an idempotent request, if the original request completes successfully, the subsequent retries with the same client token return the result from the original successful request and they have no additional effect. If you don't specify a client token, the CLI and SDK automatically generate 1 for you.

    ", @@ -1195,6 +1211,14 @@ "type":"list", "member":{"shape":"ErrorInfo"} }, + "ExecutionPolicy":{ + "type":"string", + "documentation":"

    The policy that determines when a node lifecycle script runs. Valid values:

    • FIRST_BOOT_ONLY – Runs the script only the first time the compute node boots.

    • EVERY_BOOT – Runs the script every time the compute node boots, including reboots.

    ", + "enum":[ + "FIRST_BOOT_ONLY", + "EVERY_BOOT" + ] + }, "GetClusterRequest":{ "type":"structure", "required":["clusterIdentifier"], @@ -1260,6 +1284,16 @@ "queue":{"shape":"Queue"} } }, + "GresCustomSettingMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    A single Slurm gres.conf record, expressed as a map of gres.conf attribute names to their values. For example, {\"Name\": \"gpu\", \"Type\": \"a100\", \"File\": \"/dev/nvidia[0-7]\"} or {\"AutoDetect\": \"nvml\"}. PCS adds the NodeName= prefix for the compute node group.

    PCS supports a subset of gres.conf settings. For more information, see Configuring custom GRES settings in PCS in the PCS User Guide.

    " + }, + "GresCustomSettings":{ + "type":"list", + "member":{"shape":"GresCustomSettingMap"} + }, "InstanceConfig":{ "type":"structure", "members":{ @@ -1480,6 +1514,112 @@ }, "documentation":"

    The networking configuration for the cluster's control plane.

    " }, + "NodeLifecycleActions":{ + "type":"structure", + "required":["stages"], + "members":{ + "stages":{ + "shape":"NodeLifecycleStages", + "documentation":"

    The lifecycle stages where you configure scripts to run.

    " + }, + "scriptCachingPolicy":{ + "shape":"ScriptCachingPolicy", + "documentation":"

    The caching policy for node lifecycle scripts. The default value is CACHE_ONCE. Valid values:

    • CACHE_ONCE – Downloads each script once and reuses it on subsequent boots.

    • REFRESH_ON_REBOOT – Downloads each script on every boot.

    " + } + }, + "documentation":"

    The lifecycle actions configured on a compute node group. Lifecycle actions define scripts that PCS runs on compute nodes at specific stages of their lifecycle.

    " + }, + "NodeLifecycleActionsRequest":{ + "type":"structure", + "required":["stages"], + "members":{ + "stages":{ + "shape":"NodeLifecycleStages", + "documentation":"

    The lifecycle stages where you configure scripts to run.

    " + }, + "scriptCachingPolicy":{ + "shape":"ScriptCachingPolicy", + "documentation":"

    The caching policy for node lifecycle scripts. The default value is CACHE_ONCE. Valid values:

    • CACHE_ONCE – Downloads each script once and reuses it on subsequent boots.

    • REFRESH_ON_REBOOT – Downloads each script on every boot.

    " + } + }, + "documentation":"

    The lifecycle actions to configure on a compute node group when you create it. Lifecycle actions define scripts that PCS runs on compute nodes at specific stages of their lifecycle.

    " + }, + "NodeLifecycleScript":{ + "type":"structure", + "required":[ + "name", + "scriptSource" + ], + "members":{ + "name":{ + "shape":"NodeLifecycleScriptNameString", + "documentation":"

    A unique name for the script. The name can be up to 64 characters long. Valid characters are letters, numbers, spaces, underscores (_), and hyphens (-). The first character must be a letter or a number.

    " + }, + "scriptSource":{ + "shape":"ScriptSource", + "documentation":"

    The source location and integrity information for the script.

    " + }, + "arguments":{ + "shape":"NodeLifecycleScriptArguments", + "documentation":"

    The command-line arguments to pass to the script. You can specify up to 20 arguments, and each argument can be up to 256 characters long.

    " + }, + "onError":{ + "shape":"OnError", + "documentation":"

    The behavior when the script fails. The default value is TERMINATE. Valid values:

    • TERMINATE – Terminates the compute node.

    • STOP_SEQUENCE – Stops running subsequent scripts in the sequence but doesn't terminate the compute node.

    • CONTINUE – Ignores the error and continues running the next script.

    " + }, + "executionPolicy":{ + "shape":"ExecutionPolicy", + "documentation":"

    The policy that determines when the script runs. The default value is FIRST_BOOT_ONLY. Valid values:

    • FIRST_BOOT_ONLY – Runs the script only the first time the compute node boots.

    • EVERY_BOOT – Runs the script every time the compute node boots, including reboots.

    " + } + }, + "documentation":"

    A script to run during a compute node lifecycle stage.

    " + }, + "NodeLifecycleScriptArgument":{ + "type":"string", + "max":256, + "min":0 + }, + "NodeLifecycleScriptArguments":{ + "type":"list", + "member":{"shape":"NodeLifecycleScriptArgument"}, + "max":20, + "min":0 + }, + "NodeLifecycleScriptList":{ + "type":"list", + "member":{"shape":"NodeLifecycleScript"}, + "max":20, + "min":1 + }, + "NodeLifecycleScriptNameString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[A-Za-z0-9][A-Za-z0-9 _-]*" + }, + "NodeLifecycleStages":{ + "type":"structure", + "members":{ + "nodeBootstrapped":{ + "shape":"NodeLifecycleScriptList", + "documentation":"

    The scripts to run after PCS finishes setting up the compute node and before the Slurm daemon (slurmd) starts. Use this stage for tasks that must complete before the node accepts jobs, such as mounting shared storage, configuring networking, or installing software packages.

    " + }, + "nodeReady":{ + "shape":"NodeLifecycleScriptList", + "documentation":"

    The scripts to run after the Slurm daemon (slurmd) starts and the compute node registers with the Slurm controller. Use this stage for tasks that require Slurm to be running, such as running Slurm commands.

    " + } + }, + "documentation":"

    The stages of a compute node's lifecycle where you can configure scripts to run.

    " + }, + "OnError":{ + "type":"string", + "documentation":"

    The behavior when a node lifecycle script fails. Valid values:

    • TERMINATE – Terminates the compute node.

    • STOP_SEQUENCE – Stops running subsequent scripts in the sequence but doesn't terminate the compute node.

    • CONTINUE – Ignores the error and continues running the next script.

    ", + "enum":[ + "TERMINATE", + "STOP_SEQUENCE", + "CONTINUE" + ] + }, "PurchaseOption":{ "type":"string", "enum":[ @@ -1673,6 +1813,22 @@ "endpoints":{ "shape":"Endpoints", "documentation":"

    The list of endpoints available for interaction with the scheduler.

    " + }, + "clusterName":{ + "shape":"String", + "documentation":"

    The name of the cluster that the compute node registered into.

    " + }, + "computeNodeGroupId":{ + "shape":"String", + "documentation":"

    The ID of the compute node group that the compute node registered into.

    " + }, + "computeNodeGroupName":{ + "shape":"String", + "documentation":"

    The name of the compute node group that the compute node registered into.

    " + }, + "nodeLifecycleActions":{ + "shape":"NodeLifecycleActions", + "documentation":"

    The node lifecycle actions configured for the node group, including scripts to run when a compute node finishes bootstrapping or becomes ready to accept jobs.

    " } } }, @@ -1783,7 +1939,7 @@ }, "version":{ "shape":"String", - "documentation":"

    The version of the specified scheduling software that PCS uses to manage cluster scaling and job scheduling. You can upgrade this version using the UpdateCluster API action. For more information, see Upgrading the Slurm version on a cluster and Slurm versions in PCS in the PCS User Guide.

    Valid Values: 23.11 | 24.05 | 24.11 | 25.05 | 25.11

    " + "documentation":"

    The version of the specified scheduling software that PCS uses to manage cluster scaling and job scheduling. You can update this version using the UpdateCluster API action. For more information, see Updating the scheduler version on a cluster and Slurm versions in PCS in the PCS User Guide.

    Valid Values: 23.11 | 24.05 | 24.11 | 25.05 | 25.11 | 26.05

    " } }, "documentation":"

    The cluster management and job scheduling software associated with the cluster.

    " @@ -1801,7 +1957,7 @@ }, "version":{ "shape":"String", - "documentation":"

    The version of the specified scheduling software that PCS uses to manage cluster scaling and job scheduling. For more information, see Slurm versions in PCS in the PCS User Guide.

    Valid Values: 24.11 | 25.05 | 25.11

    " + "documentation":"

    The version of the specified scheduling software that PCS uses to manage cluster scaling and job scheduling. For more information, see Slurm versions in PCS in the PCS User Guide.

    Valid Values: 24.11 | 25.05 | 25.11 | 26.05

    " } }, "documentation":"

    The cluster management and job scheduling software associated with the cluster.

    " @@ -1810,6 +1966,50 @@ "type":"string", "enum":["SLURM"] }, + "ScriptCachingPolicy":{ + "type":"string", + "documentation":"

    The caching policy for a node lifecycle script. Valid values:

    • CACHE_ONCE – Downloads the script once and reuses it on subsequent boots.

    • REFRESH_ON_REBOOT – Downloads the script on every boot.

    ", + "enum":[ + "CACHE_ONCE", + "REFRESH_ON_REBOOT" + ] + }, + "ScriptSource":{ + "type":"structure", + "required":["scriptLocation"], + "members":{ + "scriptLocation":{ + "shape":"ScriptSourceScriptLocationString", + "documentation":"

    The location of the script. Specify either an Amazon S3 URI in the format s3://bucket-name/key or an HTTPS URL.

    " + }, + "s3VersionId":{ + "shape":"ScriptSourceS3VersionIdString", + "documentation":"

    The Amazon S3 version ID of the script. Use this value to pin the script to a specific version in a versioned Amazon S3 bucket. This value is only valid when scriptLocation is an Amazon S3 URI.

    " + }, + "checksum":{ + "shape":"ScriptSourceChecksumString", + "documentation":"

    The SHA-256 checksum of the script content, as a 64-character hexadecimal string. This value is optional. When specified, PCS uses this value to verify the integrity of the downloaded script.

    " + } + }, + "documentation":"

    The source location and integrity information for a node lifecycle script.

    " + }, + "ScriptSourceChecksumString":{ + "type":"string", + "max":64, + "min":64, + "pattern":"[a-fA-F0-9]{64}" + }, + "ScriptSourceS3VersionIdString":{ + "type":"string", + "max":1024, + "min":0 + }, + "ScriptSourceScriptLocationString":{ + "type":"string", + "max":1024, + "min":1, + "pattern":"(s3://[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]/.+|https://([a-zA-Z0-9](?:[a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,63}(?::[0-9]{1,5})?(?:[/?#][^\\s]*)?)" + }, "SecurityGroupId":{ "type":"string", "pattern":"sg-\\w{8,17}" @@ -2096,7 +2296,7 @@ }, "scheduler":{ "shape":"UpdateSchedulerRequest", - "documentation":"

    The scheduler configuration to update for the cluster. Use this to upgrade the Slurm version. For more information, see Upgrading the Slurm version on a cluster in the PCS User Guide.

    " + "documentation":"

    The scheduler configuration to update for the cluster. Use this to update the scheduler version. For more information, see Updating the scheduler version on a cluster in the PCS User Guide.

    " } } }, @@ -2183,6 +2383,10 @@ "shape":"UpdateComputeNodeGroupSlurmConfigurationRequest", "documentation":"

    Additional options related to the Slurm scheduler.

    " }, + "nodeLifecycleActions":{ + "shape":"UpdateNodeLifecycleActionsRequest", + "documentation":"

    The lifecycle actions to run on compute nodes in the compute node group. Use lifecycle actions to run custom scripts at defined stages of a compute node's lifecycle, such as when a compute node finishes bootstrapping or becomes ready to accept jobs.

    " + }, "clientToken":{ "shape":"SBClientToken", "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request. Idempotency ensures that an API request completes only once. With an idempotent request, if the original request completes successfully, the subsequent retries with the same client token return the result from the original successful request and they have no additional effect. If you don't specify a client token, the CLI and SDK automatically generate 1 for you.

    ", @@ -2206,6 +2410,10 @@ "slurmCustomSettings":{ "shape":"SlurmCustomSettings", "documentation":"

    Additional Slurm-specific configuration that directly maps to Slurm settings.

    " + }, + "gresCustomSettings":{ + "shape":"GresCustomSettings", + "documentation":"

    The additional Slurm gres.conf records for the compute node group. Each item is a map of gres.conf attribute names to values that describes one gres.conf record, such as a GPU topology, MIG, MPS, or custom GRES entry. PCS adds the NodeName= prefix and merges these records with the GPU record it derives from the instance type.

    " } }, "documentation":"

    Additional options related to the Slurm scheduler.

    " @@ -2216,6 +2424,21 @@ "max":10000000, "min":-1 }, + "UpdateNodeLifecycleActionsRequest":{ + "type":"structure", + "required":["stages"], + "members":{ + "stages":{ + "shape":"NodeLifecycleStages", + "documentation":"

    The lifecycle stages where you configure scripts to run.

    " + }, + "scriptCachingPolicy":{ + "shape":"ScriptCachingPolicy", + "documentation":"

    The caching policy for node lifecycle scripts. The default value is CACHE_ONCE. Valid values:

    • CACHE_ONCE – Downloads each script once and reuses it on subsequent boots.

    • REFRESH_ON_REBOOT – Downloads each script on every boot.

    " + } + }, + "documentation":"

    The lifecycle actions to configure on a compute node group when you update it. Lifecycle actions define scripts that PCS runs on compute nodes at specific stages of their lifecycle.

    " + }, "UpdateQueueRequest":{ "type":"structure", "required":[ @@ -2268,10 +2491,10 @@ "members":{ "version":{ "shape":"String", - "documentation":"

    The Slurm version to upgrade the cluster to. You can only upgrade to a newer version. For more information about supported versions and upgrade paths, see Upgrading the Slurm version on a cluster in the PCS User Guide.

    Valid Values: 24.05 | 24.11 | 25.05 | 25.11

    " + "documentation":"

    The scheduler version to update the cluster to. You can only update to a newer version. For more information about supported versions and update paths, see Updating the scheduler version on a cluster in the PCS User Guide.

    Valid Values: 24.05 | 24.11 | 25.05 | 25.11 | 26.05

    " } }, - "documentation":"

    The scheduler configuration for updating a cluster. Use this to specify the Slurm version to upgrade to.

    " + "documentation":"

    The scheduler configuration for updating a cluster. Use this to specify the scheduler version to update to.

    " }, "UpdateSlurmRestRequest":{ "type":"structure", diff --git a/services/personalize/pom.xml b/services/personalize/pom.xml index 9f18421f8769..df04496f8ff7 100644 --- a/services/personalize/pom.xml +++ b/services/personalize/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT personalize AWS Java SDK :: Services :: Personalize diff --git a/services/personalize/src/main/resources/codegen-resources/customization.config b/services/personalize/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/personalize/src/main/resources/codegen-resources/customization.config +++ b/services/personalize/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/personalize/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/personalize/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..eee48e010a65 --- /dev/null +++ b/services/personalize/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/personalize/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/personalize/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3120e08a0c5a..000000000000 --- a/services/personalize/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://personalize.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/personalizeevents/pom.xml b/services/personalizeevents/pom.xml index b80a19b1897c..831b5674c46d 100644 --- a/services/personalizeevents/pom.xml +++ b/services/personalizeevents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT personalizeevents AWS Java SDK :: Services :: Personalize Events diff --git a/services/personalizeevents/src/main/resources/codegen-resources/customization.config b/services/personalizeevents/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/personalizeevents/src/main/resources/codegen-resources/customization.config +++ b/services/personalizeevents/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/personalizeevents/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/personalizeevents/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2570d2eecee9 --- /dev/null +++ b/services/personalizeevents/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-events-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-events.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-events.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/personalizeevents/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/personalizeevents/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 090db9d095fd..000000000000 --- a/services/personalizeevents/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-events-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-events-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-events.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://personalize-events.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/personalizeruntime/pom.xml b/services/personalizeruntime/pom.xml index 0a3d59fdca14..90fda3c7f890 100644 --- a/services/personalizeruntime/pom.xml +++ b/services/personalizeruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT personalizeruntime AWS Java SDK :: Services :: Personalize Runtime diff --git a/services/personalizeruntime/src/main/resources/codegen-resources/customization.config b/services/personalizeruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/personalizeruntime/src/main/resources/codegen-resources/customization.config +++ b/services/personalizeruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cee4505e0429 --- /dev/null +++ b/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://personalize-runtime.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 01bd9e40d7e0..000000000000 --- a/services/personalizeruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-runtime-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-runtime-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://personalize-runtime.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://personalize-runtime.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pi/pom.xml b/services/pi/pom.xml index 82b144232d3b..3a0220c699f6 100644 --- a/services/pi/pom.xml +++ b/services/pi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pi AWS Java SDK :: Services :: PI diff --git a/services/pi/src/main/resources/codegen-resources/customization.config b/services/pi/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/pi/src/main/resources/codegen-resources/customization.config +++ b/services/pi/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/pi/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pi/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..236a25dce2b5 --- /dev/null +++ b/services/pi/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pi-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pi.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pi.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pi/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pi/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0724cea844d4..000000000000 --- a/services/pi/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pi-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pi-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pi.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://pi.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pinpoint/pom.xml b/services/pinpoint/pom.xml index 162737d612c2..e1ee5dec7a97 100644 --- a/services/pinpoint/pom.xml +++ b/services/pinpoint/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pinpoint AWS Java SDK :: Services :: Amazon Pinpoint diff --git a/services/pinpoint/src/main/resources/codegen-resources/customization.config b/services/pinpoint/src/main/resources/codegen-resources/customization.config index b62371178863..e0ed7172b767 100644 --- a/services/pinpoint/src/main/resources/codegen-resources/customization.config +++ b/services/pinpoint/src/main/resources/codegen-resources/customization.config @@ -5,6 +5,5 @@ "renameShapes": { "__EndpointTypesElement": "EndpointTypesElement" }, - "underscoresInNameBehavior": "ALLOW", - "enableGenerateCompiledEndpointRules": true + "underscoresInNameBehavior": "ALLOW" } diff --git a/services/pinpoint/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pinpoint/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4651f8be8e8c --- /dev/null +++ b/services/pinpoint/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,281 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.us-west-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pinpoint.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAAA0AAAAGAAAABQAAAAwAAAAHAAAABwX14QoAAAAIAAAACAX14QsAAAAJAAAACQX14QwAAAAKAAAACgX14Q0AAAALAAAACwX14Q0F9eEOAAAABgX14QgF9eEJAAAABAAAAA8AAAAOAAAABQX14QUF9eEHAAAABQAAABAF9eEGAAAABgX14QQF9eEFAAAAAwX14QEAAAASAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/pinpoint/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pinpoint/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 14d96076d714..000000000000 --- a/services/pinpoint/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,421 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pinpoint-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pinpoint-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pinpoint.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://pinpoint.us-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-2" - ] - } - ], - "endpoint": { - "url": "https://pinpoint.us-west-2.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://pinpoint.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://pinpoint.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://pinpoint.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://pinpoint.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pinpointemail/pom.xml b/services/pinpointemail/pom.xml index 0b7325947fd6..026a5ecf1d76 100644 --- a/services/pinpointemail/pom.xml +++ b/services/pinpointemail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pinpointemail AWS Java SDK :: Services :: Pinpoint Email diff --git a/services/pinpointemail/src/main/resources/codegen-resources/customization.config b/services/pinpointemail/src/main/resources/codegen-resources/customization.config index 3324fc23dfb2..e5b907464f12 100644 --- a/services/pinpointemail/src/main/resources/codegen-resources/customization.config +++ b/services/pinpointemail/src/main/resources/codegen-resources/customization.config @@ -9,6 +9,5 @@ "listDedicatedIpPools", "listDeliverabilityTestReports", "listEmailIdentities" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/pinpointemail/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pinpointemail/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..36f42a218754 --- /dev/null +++ b/services/pinpointemail/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pinpointemail/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pinpointemail/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7386f6b5cc61..000000000000 --- a/services/pinpointemail/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pinpointsmsvoice/pom.xml b/services/pinpointsmsvoice/pom.xml index 60a1f2e85082..66d2ac7aba21 100644 --- a/services/pinpointsmsvoice/pom.xml +++ b/services/pinpointsmsvoice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pinpointsmsvoice AWS Java SDK :: Services :: Pinpoint SMS Voice diff --git a/services/pinpointsmsvoice/src/main/resources/codegen-resources/customization.config b/services/pinpointsmsvoice/src/main/resources/codegen-resources/customization.config index ba02b96b8737..1250a7bd114d 100644 --- a/services/pinpointsmsvoice/src/main/resources/codegen-resources/customization.config +++ b/services/pinpointsmsvoice/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "excludedSimpleMethods": [ "listConfigurationSets" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1865db5f59d7 --- /dev/null +++ b/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.pinpoint-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.pinpoint-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.pinpoint.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.pinpoint.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4135ce7a1fa7..000000000000 --- a/services/pinpointsmsvoice/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.pinpoint-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.pinpoint-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.pinpoint.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.pinpoint.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/pinpointsmsvoicev2/pom.xml b/services/pinpointsmsvoicev2/pom.xml index df6eb9a782ef..8b2759867309 100644 --- a/services/pinpointsmsvoicev2/pom.xml +++ b/services/pinpointsmsvoicev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pinpointsmsvoicev2 AWS Java SDK :: Services :: Pinpoint SMS Voice V2 diff --git a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/customization.config b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/customization.config +++ b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..11baf14268a2 --- /dev/null +++ b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sms-voice.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 05d87d960645..000000000000 --- a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sms-voice.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/paginators-1.json b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/paginators-1.json index 2438fa3420a0..c4eac45339a2 100644 --- a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/paginators-1.json +++ b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/paginators-1.json @@ -138,6 +138,12 @@ "limit_key": "MaxResults", "result_key": "VerifiedDestinationNumbers" }, + "ListAvailablePhoneNumbers": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "AvailablePhoneNumbers" + }, "ListNotifyCountries": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/service-2.json b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/service-2.json index 455ea77b814e..ef3c9c97c921 100644 --- a/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/service-2.json +++ b/services/pinpointsmsvoicev2/src/main/resources/codegen-resources/service-2.json @@ -252,7 +252,7 @@ {"shape":"ConflictException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Create a new registration attachment to use for uploading a file or a URL to a file. The maximum file size is 500KB and valid file extensions are PDF, JPEG and PNG. For example, many sender ID registrations require a signed “letter of authorization” (LOA) to be submitted.

    Use either AttachmentUrl or AttachmentBody to upload your attachment. If both are specified then an exception is returned.

    " + "documentation":"

    Create a new registration attachment to use for uploading a file or a URL to a file. The maximum file size is 5MB and valid file extensions are PDF, JPEG and PNG. For example, many sender ID registrations require a signed “letter of authorization” (LOA) to be submitted.

    Use either AttachmentUrl or AttachmentBody to upload your attachment. If both are specified then an exception is returned.

    " }, "CreateRegistrationVersion":{ "name":"CreateRegistrationVersion", @@ -1162,6 +1162,25 @@ ], "documentation":"

    Retrieves the JSON text of the resource-based policy document attached to the End User Messaging SMS resource. A shared resource can be a Pool, Opt-out list, Sender Id, or Phone number.

    " }, + "ListAvailablePhoneNumbers":{ + "name":"ListAvailablePhoneNumbers", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListAvailablePhoneNumbersRequest"}, + "output":{"shape":"ListAvailablePhoneNumbersResult"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Search available phone numbers from aggregator inventory, optionally filtered by pattern. If NumberPreference is omitted, returns unfiltered available numbers. Returns empty list (not an exception) when no numbers match. ResourceNotFoundException is thrown only for invalid RegistrationId (campaign not found).

    ", + "readonly":true + }, "ListNotifyCountries":{ "name":"ListNotifyCountries", "http":{ @@ -2112,7 +2131,7 @@ }, "AttachmentBody":{ "type":"blob", - "max":1572864, + "max":6990508, "min":1 }, "AttachmentStatus":{ @@ -2134,6 +2153,13 @@ "min":1, "pattern":"\\S+" }, + "AvailablePhoneNumberList":{ + "type":"list", + "member":{"shape":"PhoneNumber"}, + "documentation":"

    List of available phone numbers returned by the search. Max aligns with ListAvailablePhoneNumbersMaxResults (page size bound).

    ", + "max":10, + "min":0 + }, "Boolean":{ "type":"boolean", "box":true @@ -2250,6 +2276,114 @@ }, "documentation":"

    Contains the destination configuration to use when publishing message sending events.

    " }, + "ConditionOperator":{ + "type":"string", + "documentation":"

    The operator used to compare a dependency field's value in a FieldCondition. Valid values are EQUALS, NOT_EQUALS, IN, NOT_IN, HAS_VALUE, and NO_VALUE. Unknown operators evaluate to false, which causes the containing rule to be skipped.

    ", + "max":64, + "min":1, + "pattern":"[A-Za-z0-9_]+" + }, + "ConditionValue":{ + "type":"string", + "max":256, + "min":1 + }, + "ConditionValueList":{ + "type":"list", + "member":{"shape":"ConditionValue"}, + "max":20, + "min":0 + }, + "ConditionalBehavior":{ + "type":"structure", + "required":[ + "Rules", + "DefaultBehavior" + ], + "members":{ + "Rules":{ + "shape":"ConditionalRuleList", + "documentation":"

    An ordered list of conditional rules. Rules are evaluated top-to-bottom and the first rule whose conditions all evaluate to true determines the field's behavior. Rules whose conditions do not all match are skipped and evaluation continues to the next rule.

    " + }, + "DefaultBehavior":{ + "shape":"ConditionalFieldBehavior", + "documentation":"

    The field behavior that applies when no conditional rule in Rules matches. Valid values are REQUIRED, OPTIONAL, and DISALLOWED.

    " + } + }, + "documentation":"

    The set of conditional rules that determine a field's resolved requirement based on the values of other fields in the same registration form. Attached to fields whose FieldRequirement is CONDITIONAL.

    Evaluation proceeds top-to-bottom through Rules. The first rule whose conditions all evaluate to true wins and its behavior is returned. If no rule matches, the DefaultBehavior is returned.

    " + }, + "ConditionalFieldBehavior":{ + "type":"string", + "documentation":"

    The resolved requirement for a field when a conditional rule matches. Valid values are:

    REQUIRED — the field must be present; absence causes a validation error at submission time.

    OPTIONAL — the field may be present.

    DISALLOWED — the field must not be present; a submitted value is rejected with a validation error.

    ", + "max":64, + "min":1, + "pattern":"[A-Za-z0-9_]+" + }, + "ConditionalRule":{ + "type":"structure", + "required":[ + "Conditions", + "RuleBehavior" + ], + "members":{ + "Conditions":{ + "shape":"FieldConditionList", + "documentation":"

    The conditions that must all evaluate to true for this rule to match. Conditions are combined with logical AND. Use multiple rules with the same RuleBehavior to express logical OR.

    " + }, + "RuleBehavior":{ + "shape":"ConditionalFieldBehavior", + "documentation":"

    The field behavior that applies when all conditions in this rule match. Valid values are REQUIRED, OPTIONAL, and DISALLOWED.

    " + }, + "ConditionalValidation":{ + "shape":"ConditionalValidation", + "documentation":"

    Optional per-rule validation constraints (minimum length, maximum length, regex pattern, allowed select values) that override the field's default validation when this rule matches.

    " + } + }, + "documentation":"

    A single conditional rule that resolves to a field behavior when all of its conditions evaluate to true. Conditions within a rule are combined with logical AND: all conditions must match for the rule to fire.

    " + }, + "ConditionalRuleList":{ + "type":"list", + "member":{"shape":"ConditionalRule"}, + "max":20, + "min":1 + }, + "ConditionalValidation":{ + "type":"structure", + "members":{ + "MinLength":{ + "shape":"ConditionalValidationMinLengthInteger", + "documentation":"

    The minimum length for the field value when this rule applies.

    " + }, + "MaxLength":{ + "shape":"ConditionalValidationMaxLengthInteger", + "documentation":"

    The maximum length for the field value when this rule applies.

    " + }, + "Pattern":{ + "shape":"ConditionalValidationPatternString", + "documentation":"

    A regular expression that the field value must match when this rule applies.

    " + }, + "AllowedValues":{ + "shape":"SelectChoiceList", + "documentation":"

    The allowed values for a select field when this rule applies. A subset of the field's full option list.

    " + } + }, + "documentation":"

    Per-rule validation constraints that override the field's default validation when the containing rule matches. All fields are optional; only the constraints that need to differ from the field's default validation are provided.

    " + }, + "ConditionalValidationMaxLengthInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "ConditionalValidationMinLengthInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "ConditionalValidationPatternString":{ + "type":"string", + "max":2048, + "min":1 + }, "ConfigurationSetFilter":{ "type":"structure", "required":[ @@ -3080,7 +3214,7 @@ "members":{ "AttachmentBody":{ "shape":"AttachmentBody", - "documentation":"

    The registration file to upload. The maximum file size is 500KB and valid file extensions are PDF, JPEG and PNG.

    " + "documentation":"

    The registration file to upload. The maximum file size is 5MB and valid file extensions are PDF, JPEG and PNG.

    " }, "AttachmentUrl":{ "shape":"AttachmentUrl", @@ -5335,6 +5469,34 @@ "max":52, "min":1 }, + "FieldCondition":{ + "type":"structure", + "required":[ + "DependsOnFieldPath", + "Operator" + ], + "members":{ + "DependsOnFieldPath":{ + "shape":"FieldPath", + "documentation":"

    The path of the field whose value determines this condition, for example companyInfo.businessType.

    " + }, + "Operator":{ + "shape":"ConditionOperator", + "documentation":"

    The comparison operator to apply between the dependency field's value and Values. Valid values are EQUALS, NOT_EQUALS, IN, NOT_IN, HAS_VALUE, and NO_VALUE. Operators not in this list are treated as evaluating to false, which causes the containing rule to be skipped. This allows forward-compatible additions of new operators without breaking older SDK clients.

    " + }, + "Values":{ + "shape":"ConditionValueList", + "documentation":"

    The values to compare the dependency field's value against. Required for the EQUALS, NOT_EQUALS, IN, and NOT_IN operators. Omitted for HAS_VALUE and NO_VALUE, which test only presence.

    " + } + }, + "documentation":"

    A single condition on a dependency field's value. Conditions are combined into a ConditionalRule and evaluated together with logical AND.

    " + }, + "FieldConditionList":{ + "type":"list", + "member":{"shape":"FieldCondition"}, + "max":5, + "min":1 + }, "FieldPath":{ "type":"string", "max":100, @@ -5606,6 +5768,65 @@ "ZH_TW" ] }, + "ListAvailablePhoneNumbersMaxResults":{ + "type":"integer", + "documentation":"

    Maximum number of results per page for ListAvailablePhoneNumbers. Aligned with AvailablePhoneNumberList max of 10.

    ", + "box":true, + "max":10, + "min":1 + }, + "ListAvailablePhoneNumbersRequest":{ + "type":"structure", + "required":[ + "IsoCountryCode", + "NumberCapabilities", + "NumberType" + ], + "members":{ + "IsoCountryCode":{ + "shape":"IsoCountryCode", + "documentation":"

    The two-character code, in ISO 3166-1 alpha-2 format, for the country or region in which to search for available phone numbers. This operation currently supports only US.

    " + }, + "NumberCapabilities":{ + "shape":"NumberCapabilityList", + "documentation":"

    The capabilities to filter by, such as SMS. Only phone numbers that support all of the specified capabilities are returned.

    " + }, + "NumberType":{ + "shape":"SearchableNumberType", + "documentation":"

    The type of phone number to search for.

    " + }, + "RegistrationId":{ + "shape":"RegistrationIdOrArn", + "documentation":"

    The registration associated with the request. A registration is required for regulated number types. You can specify either:

    • The unique identifier of the registration.

    • The Amazon Resource Name (ARN) of the registration.

    " + }, + "NumberPreference":{ + "shape":"NumberPreferenceList", + "documentation":"

    Optional. If omitted, returns unfiltered available numbers. Max 1 element for List API.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token returned from a previous request to retrieve the next page of results.

    " + }, + "MaxResults":{ + "shape":"ListAvailablePhoneNumbersMaxResults", + "documentation":"

    The maximum number of results to return per page. If you don't specify a value, the default is 10.

    " + } + } + }, + "ListAvailablePhoneNumbersResult":{ + "type":"structure", + "required":["AvailablePhoneNumbers"], + "members":{ + "AvailablePhoneNumbers":{ + "shape":"AvailablePhoneNumberList", + "documentation":"

    An array of phone numbers, in E.164 format, that are available to request based on the specified filters.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token to include in the next request to retrieve the next page of results. This value is null when there are no more results.

    " + } + } + }, "ListNotifyCountriesRequest":{ "type":"structure", "members":{ @@ -5822,6 +6043,11 @@ "min":20, "pattern":"arn:\\S+" }, + "LongMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"PrimitiveLong"} + }, "MCCType":{ "type":"string", "max":3, @@ -5890,6 +6116,20 @@ "max":2, "min":0 }, + "MessagingLimits":{ + "type":"structure", + "members":{ + "RateLimits":{ + "shape":"LongMap", + "documentation":"

    The maximum send rate for each supported capability, in messages per second. The map is keyed by capability, such as SMS, MMS, VOICE, or RCS.

    " + }, + "DailyMessageCaps":{ + "shape":"LongMap", + "documentation":"

    The advisory maximum number of messages that can be sent per day, keyed by provider (for example, T-MOBILE). Applies to 10DLC phone numbers and is omitted when no daily cap applies.

    " + } + }, + "documentation":"

    The messaging limits that apply to an origination identity, such as a phone number, sender ID, or RCS agent. Includes the per-capability send rates and, for supported origination identities, advisory per-provider daily message caps.

    " + }, "MonthlyLimit":{ "type":"long", "box":true, @@ -6310,6 +6550,45 @@ "max":4, "min":1 }, + "NumberFilterList":{ + "type":"list", + "member":{"shape":"NumberFilterValue"}, + "documentation":"

    List of filter values. Max 1 for pattern types (StartsWith/EndsWith/Contains), max 10 for ExactMatch.

    ", + "max":10, + "min":1 + }, + "NumberFilterValue":{ + "type":"string", + "documentation":"

    A filter value — either a pattern (e.g., "+1510") or full E.164 number.

    ", + "max":16, + "min":2, + "pattern":"\\+?[0-9]{1,15}" + }, + "NumberPreferenceItem":{ + "type":"structure", + "required":[ + "PreferenceType", + "Filter" + ], + "members":{ + "PreferenceType":{ + "shape":"PreferenceTypeList", + "documentation":"

    The type of match to apply to the filter values.

    • StartsWith: Returns numbers that begin with the filter value.

    • EndsWith: Returns numbers that end with the filter value.

    • Contains: Returns numbers that contain the filter value.

    • ExactMatch: Returns the number that exactly matches the filter value.

    " + }, + "Filter":{ + "shape":"NumberFilterList", + "documentation":"

    The digit pattern values to match against available phone numbers, using the specified preference type.

    " + } + }, + "documentation":"

    A single number preference — specifies a pattern type and filter value.

    " + }, + "NumberPreferenceList":{ + "type":"list", + "member":{"shape":"NumberPreferenceItem"}, + "documentation":"

    List of number preference objects. Max 1 element.

    ", + "max":1, + "min":1 + }, "NumberStatus":{ "type":"string", "enum":[ @@ -6626,6 +6905,10 @@ "shape":"String", "documentation":"

    The unique identifier for the registration.

    " }, + "MessagingLimits":{ + "shape":"MessagingLimits", + "documentation":"

    The messaging limits that apply to the phone number, including the per-capability send rates and any advisory per-provider daily message caps.

    " + }, "CreatedTimestamp":{ "shape":"Timestamp", "documentation":"

    The time when the phone number was created, in UNIX epoch time format.

    " @@ -6816,6 +7099,23 @@ "DELETING" ] }, + "PreferenceType":{ + "type":"string", + "documentation":"

    The type of pattern matching to apply.

    ", + "enum":[ + "StartsWith", + "EndsWith", + "Contains", + "ExactMatch" + ] + }, + "PreferenceTypeList":{ + "type":"list", + "member":{"shape":"PreferenceType"}, + "documentation":"

    List of preference types. Max 1 at launch. Modeled as list for forward compatibility — will support multiple types in future phases.

    ", + "max":1, + "min":1 + }, "PrimitiveBoolean":{"type":"boolean"}, "PrimitiveLong":{"type":"long"}, "ProtectConfigurationArn":{ @@ -7436,6 +7736,10 @@ "TestingAgent":{ "shape":"TestingAgentInformation", "documentation":"

    The testing agent information associated with the RCS agent.

    " + }, + "MessagingLimits":{ + "shape":"MessagingLimits", + "documentation":"

    The messaging limits that apply to the RCS agent, including the per-capability send rates.

    " } }, "documentation":"

    The information for an RCS agent in an Amazon Web Services account.

    " @@ -8262,6 +8566,10 @@ "DisplayHints":{ "shape":"RegistrationFieldDisplayHints", "documentation":"

    An array of RegistrationFieldDisplayHints objects for the field.

    " + }, + "ConditionalBehavior":{ + "shape":"ConditionalBehavior", + "documentation":"

    The conditional behavior rules for this field. Only present when FieldRequirement is CONDITIONAL. Rules are evaluated in order and the first matching rule determines the field's resolved requirement. If no rule matches, the DefaultBehavior applies.

    " } }, "documentation":"

    Provides a description of the specified field.

    " @@ -8919,6 +9227,10 @@ "shape":"RegistrationIdOrArn", "documentation":"

    Use this field to attach your phone number for an external registration process.

    " }, + "NumberPreference":{ + "shape":"NumberPreferenceList", + "documentation":"

    An optional selection preference used to request a specific phone number, such as a number that starts with, ends with, or contains a particular digit pattern. You can specify at most one preference. Number preferences apply only to TEN_DLC requests in the US.

    " + }, "InternationalSendingEnabled":{ "shape":"Boolean", "documentation":"

    By default this is set to false. When set to true the international sending of phone number is Enabled.

    " @@ -9164,6 +9476,11 @@ "rcs-agent" ] }, + "SearchableNumberType":{ + "type":"string", + "documentation":"

    The type of phone number to search for with ListAvailablePhoneNumbers. Currently only TEN_DLC is supported; additional number types (for example TOLL_FREE) will be added in future phases. Modeled as a dedicated enum rather than RequestableNumberType so this operation advertises only the values it actually supports. New values may be added over time (backward compatible).

    ", + "enum":["TEN_DLC"] + }, "SectionPath":{ "type":"string", "max":100, @@ -9772,6 +10089,10 @@ "RegistrationId":{ "shape":"String", "documentation":"

    The unique identifier for the registration.

    " + }, + "MessagingLimits":{ + "shape":"MessagingLimits", + "documentation":"

    The messaging limits that apply to the sender ID, including the per-capability send rates.

    " } }, "documentation":"

    The information for all SenderIds in an Amazon Web Services account.

    " diff --git a/services/pipes/pom.xml b/services/pipes/pom.xml index 37bdfd08d56e..6623396d106c 100644 --- a/services/pipes/pom.xml +++ b/services/pipes/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT pipes AWS Java SDK :: Services :: Pipes diff --git a/services/pipes/src/main/resources/codegen-resources/customization.config b/services/pipes/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/pipes/src/main/resources/codegen-resources/customization.config +++ b/services/pipes/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/pipes/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pipes/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..55be301e587e --- /dev/null +++ b/services/pipes/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pipes-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pipes-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pipes.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://pipes.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pipes/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pipes/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 351721eb4112..000000000000 --- a/services/pipes/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pipes-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pipes-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pipes.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://pipes.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/polly/pom.xml b/services/polly/pom.xml index 2be14b553ea9..f6a071fc3524 100644 --- a/services/polly/pom.xml +++ b/services/polly/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT polly AWS Java SDK :: Services :: Amazon Polly diff --git a/services/polly/src/main/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresigner.java b/services/polly/src/main/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresigner.java index 0ed43bf8df63..bc42d3440d0f 100644 --- a/services/polly/src/main/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresigner.java +++ b/services/polly/src/main/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresigner.java @@ -26,6 +26,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.function.Supplier; @@ -70,6 +71,7 @@ import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain; import software.amazon.awssdk.services.polly.auth.scheme.PollyAuthSchemeProvider; +import software.amazon.awssdk.services.polly.endpoints.PollyEndpointProvider; import software.amazon.awssdk.services.polly.internal.presigner.model.transform.SynthesizeSpeechRequestMarshaller; import software.amazon.awssdk.services.polly.model.PollyRequest; import software.amazon.awssdk.services.polly.presigner.PollyPresigner; @@ -94,6 +96,7 @@ public final class DefaultPollyPresigner implements PollyPresigner { private final URI endpointOverride; private final Boolean dualstackEnabled; private final Boolean fipsEnabled; + private final URI resolvedEndpoint; private DefaultPollyPresigner(BuilderImpl builder) { this.signingClock = builder.signingClock != null ? builder.signingClock @@ -126,6 +129,7 @@ private DefaultPollyPresigner(BuilderImpl builder) { .build() .isFipsEnabled() .orElse(false); + this.resolvedEndpoint = resolveEndpoint(); } IdentityProvider credentialsProvider() { @@ -334,27 +338,28 @@ private void applyOverrideHeadersAndQueryParams(SdkHttpFullRequest.Builder httpR } private void applyEndpoint(SdkHttpFullRequest.Builder httpRequestBuilder) { - URI uri = resolveEndpoint(); - httpRequestBuilder.protocol(uri.getScheme()) - .host(uri.getHost()) - .port(uri.getPort()); + httpRequestBuilder.protocol(resolvedEndpoint.getScheme()) + .host(resolvedEndpoint.getHost()) + .port(resolvedEndpoint.getPort()); } private URI resolveEndpoint() { - return AwsClientEndpointProvider.builder() - .clientEndpointOverride(endpointOverride) - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_POLLY") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlPolly") - .serviceProfileProperty("polly") - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol("https") - .region(region) - .profileFile(profileFile) - .profileName(profileName) - .dualstackEnabled(dualstackEnabled) - .fipsEnabled(fipsEnabled) - .build() - .clientEndpoint(); + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .clientEndpointOverride(endpointOverride) + .serviceEndpointOverrideEnvironmentVariable( + "AWS_ENDPOINT_URL_POLLY") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlPolly") + .serviceProfileProperty("polly") + .profileFile(profileFile) + .profileName(profileName) + .resolveFromOverrides(); + + return overrideEndpoint.orElseGet(() -> CompletableFutureUtils.joinLikeSync( + PollyEndpointProvider.defaultProvider() + .resolveEndpoint(p -> p.region(region) + .useDualStack(dualstackEnabled) + .useFips(fipsEnabled)) + ).url()); } public static class BuilderImpl implements PollyPresigner.Builder { diff --git a/services/polly/src/main/resources/codegen-resources/customization.config b/services/polly/src/main/resources/codegen-resources/customization.config index a32ecb08f66a..ff2beaa7b510 100644 --- a/services/polly/src/main/resources/codegen-resources/customization.config +++ b/services/polly/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "describeVoices", "listLexicons", "listSpeechSynthesisTasks" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/polly/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/polly/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2e9c2df3a7b8 --- /dev/null +++ b/services/polly/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://polly-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://polly-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://polly.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://polly.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/polly/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/polly/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ff17415e7829..000000000000 --- a/services/polly/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://polly-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://polly-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://polly.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://polly.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/polly/src/test/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresignerTest.java b/services/polly/src/test/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresignerTest.java index a56acb3be2c6..c62aee14c089 100644 --- a/services/polly/src/test/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresignerTest.java +++ b/services/polly/src/test/java/software/amazon/awssdk/services/polly/internal/presigner/DefaultPollyPresignerTest.java @@ -191,6 +191,26 @@ void presign_includesRequestLevelQueryParams_included() { assertThat(presignedSynthesizeSpeechRequest.httpRequest().rawQueryParameters().keySet()).contains("QueryParam1"); } + @Test + void presign_noEndpointOverride_usesDefaultEndpoint() { + PollyPresigner presigner = DefaultPollyPresigner.builder() + .region(Region.US_EAST_1) + .credentialsProvider(credentialsProvider) + .build(); + + SynthesizeSpeechPresignRequest presignRequest = SynthesizeSpeechPresignRequest.builder() + .synthesizeSpeechRequest(BASIC_SYNTHESIZE_SPEECH_REQUEST) + .signatureDuration(Duration.ofHours(3)) + .build(); + + PresignedSynthesizeSpeechRequest presigned = presigner.presignSynthesizeSpeech(presignRequest); + + URL presignedUrl = presigned.url(); + assertThat(presignedUrl.getProtocol()).isEqualTo("https"); + assertThat(presignedUrl.getHost()).isEqualTo("polly.us-east-1.amazonaws.com"); + assertThat(presignedUrl.getPath()).isEqualTo("/v1/speech"); + } + @Test void presign_endpointOverriden() { PollyPresigner presigner = DefaultPollyPresigner.builder() diff --git a/services/pom.xml b/services/pom.xml index 0a26caefb936..7113af8ff8ab 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT services AWS Java SDK :: Services @@ -447,6 +447,13 @@ lambdacore supportauthz partnercentralrevenuemeasurement + pricingplanmanager + agentregistry + agentregistrycontrol + accountaccess + iamtoolbox + cloudwatchomni + networksecuritymanager The AWS Java SDK services https://aws.amazon.com/sdkforjava diff --git a/services/pricing/pom.xml b/services/pricing/pom.xml index 43ea2a4f12f3..d771302dc516 100644 --- a/services/pricing/pom.xml +++ b/services/pricing/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 pricing diff --git a/services/pricing/src/main/resources/codegen-resources/customization.config b/services/pricing/src/main/resources/codegen-resources/customization.config index 9cf3a85600aa..3ea4709a4549 100644 --- a/services/pricing/src/main/resources/codegen-resources/customization.config +++ b/services/pricing/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "excludedSimpleMethods": [ "getProducts" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/pricing/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pricing/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1eeb35851960 --- /dev/null +++ b/services/pricing/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.pricing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.pricing-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.pricing.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.pricing.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.pricing.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABwX14QoF9eELAAAABQX14QgF9eEJAAAABAAAAAsAAAAKAAAABgX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/pricing/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/pricing/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c7cd2a23a8a0..000000000000 --- a/services/pricing/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.pricing-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.pricing-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.pricing.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://api.pricing.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.pricing.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/pricingplanmanager/pom.xml b/services/pricingplanmanager/pom.xml new file mode 100644 index 000000000000..9ebbfe2edbe9 --- /dev/null +++ b/services/pricingplanmanager/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + software.amazon.awssdk + services + 2.55.5-SNAPSHOT + + pricingplanmanager + AWS Java SDK :: Services :: Pricing Plan Manager + The AWS Java SDK for Pricing Plan Manager module holds the client classes that are used for + communicating with Pricing Plan Manager. + + https://aws.amazon.com/sdkforjava + + + + org.apache.maven.plugins + maven-jar-plugin + + + + software.amazon.awssdk.services.pricingplanmanager + + + + + + + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + http-auth-aws + ${awsjavasdk.version} + + + diff --git a/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2816c1670b3d --- /dev/null +++ b/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,67 @@ +{ + "version": "1.1", + "parameters": { + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint URL", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "{Endpoint}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "pricingplanmanager", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "documentation": "Route every region to the single us-east-1 endpoint, signing for us-east-1.", + "conditions": [], + "endpoint": { + "url": "https://pricingplanmanager.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "pricingplanmanager", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ], + "root": 2, + "nodeCount": 2, + "nodes": "/////wAAAAH/////AAAAAAX14QEF9eEC" +} \ No newline at end of file diff --git a/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-tests.json b/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-tests.json new file mode 100644 index 000000000000..173048ff0ce3 --- /dev/null +++ b/services/pricingplanmanager/src/main/resources/codegen-resources/endpoint-tests.json @@ -0,0 +1,66 @@ +{ + "version": "1", + "testCases": [ + { + "documentation": "Resolves the us-east-1 endpoint and signs for us-east-1.", + "params": { + "Region": "us-east-1" + }, + "expect": { + "endpoint": { + "url": "https://pricingplanmanager.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "pricingplanmanager", + "signingRegion": "us-east-1" + } + ] + } + } + } + }, + { + "documentation": "Routes any other region to the us-east-1 endpoint and still signs for us-east-1.", + "params": { + "Region": "us-west-2" + }, + "expect": { + "endpoint": { + "url": "https://pricingplanmanager.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "pricingplanmanager", + "signingRegion": "us-east-1" + } + ] + } + } + } + }, + { + "documentation": "A custom endpoint override wins over region resolution and signs for us-east-1.", + "params": { + "Region": "us-west-2", + "Endpoint": "https://pricingplanmanager.us-east-1.api.aws" + }, + "expect": { + "endpoint": { + "url": "https://pricingplanmanager.us-east-1.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "pricingplanmanager", + "signingRegion": "us-east-1" + } + ] + } + } + } + } + ] +} \ No newline at end of file diff --git a/services/pricingplanmanager/src/main/resources/codegen-resources/paginators-1.json b/services/pricingplanmanager/src/main/resources/codegen-resources/paginators-1.json new file mode 100644 index 000000000000..9c8834ba9c42 --- /dev/null +++ b/services/pricingplanmanager/src/main/resources/codegen-resources/paginators-1.json @@ -0,0 +1,9 @@ +{ + "pagination": { + "ListSubscriptions": { + "input_token": "nextToken", + "output_token": "nextToken", + "result_key": "subscriptionSummaries" + } + } +} diff --git a/services/pricingplanmanager/src/main/resources/codegen-resources/service-2.json b/services/pricingplanmanager/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..d95038ffa7a2 --- /dev/null +++ b/services/pricingplanmanager/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,882 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2025-08-05", + "auth":["aws.auth#sigv4"], + "endpointPrefix":"pricingplanmanager", + "protocol":"rest-json", + "protocols":["rest-json"], + "serviceFullName":"PricingPlanManager", + "serviceId":"Pricing Plan Manager", + "signatureVersion":"v4", + "signingName":"pricingplanmanager", + "uid":"pricing-plan-manager-2025-08-05" + }, + "operations":{ + "ApprovePaidSubscription":{ + "name":"ApprovePaidSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/ApprovePaidSubscription", + "responseCode":200 + }, + "input":{"shape":"ApprovePaidSubscriptionInput"}, + "output":{"shape":"ApprovePaidSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Approves a subscription that is in PENDING_APPROVAL status, activating it and starting billing.

    This operation requires the current ETag value for concurrency control. Retrieve it from a previous GetSubscription or ListSubscriptions response.

    " + }, + "AssociateResourcesToSubscription":{ + "name":"AssociateResourcesToSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/AssociateResourcesToSubscription", + "responseCode":200 + }, + "input":{"shape":"AssociateResourcesToSubscriptionInput"}, + "output":{"shape":"AssociateResourcesToSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Adds one or more resources to an existing subscription. The subscription must be in an active state that is not pending other changes.

    For subscriptions in the CloudFront plan family, the associated resources must include exactly one Amazon CloudFront distribution and one WAF web ACL. You can also include other supported resources, such as Amazon Route 53 hosted zones, and CloudFront KeyValueStores.

    " + }, + "CancelSubscription":{ + "name":"CancelSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/CancelSubscription", + "responseCode":200 + }, + "input":{"shape":"CancelSubscriptionInput"}, + "output":{"shape":"CancelSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Cancels a flat-rate pricing subscription.

    For active subscriptions, the cancellation is scheduled to take effect at the end of the current billing period. The subscription remains active until that date. To revert a pending cancellation, use CancelSubscriptionChange.

    For subscriptions in PENDING_APPROVAL status, the subscription is deleted immediately without scheduling.

    " + }, + "CancelSubscriptionChange":{ + "name":"CancelSubscriptionChange", + "http":{ + "method":"POST", + "requestUri":"/v1/CancelSubscriptionChange", + "responseCode":200 + }, + "input":{"shape":"CancelSubscriptionChangeInput"}, + "output":{"shape":"CancelSubscriptionChangeOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Cancels a pending scheduled change on a subscription, such as a pending downgrade or cancellation. The subscription returns to its state before the change was scheduled.

    You cannot cancel a scheduled change close to its effective date. If the change is within the processing window, this operation returns an error.

    " + }, + "CreateSubscription":{ + "name":"CreateSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/CreateSubscription", + "responseCode":200 + }, + "input":{"shape":"CreateSubscriptionInput"}, + "output":{"shape":"CreateSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a flat-rate pricing subscription for the specified resources.

    When approvalMode is set to MANUAL, paid-tier subscriptions are created in PENDING_APPROVAL status and require a separate ApprovePaidSubscription call before billing starts. Free-tier subscriptions are always activated immediately regardless of approval mode.

    When approvalMode is set to IMMEDIATE or is not specified, the subscription is activated immediately.

    " + }, + "DisassociateResourcesFromSubscription":{ + "name":"DisassociateResourcesFromSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/DisassociateResourcesFromSubscription", + "responseCode":200 + }, + "input":{"shape":"DisassociateResourcesFromSubscriptionInput"}, + "output":{"shape":"DisassociateResourcesFromSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Removes one or more resources from an existing subscription.

    For subscriptions in the CloudFront plan family, the associated resources must always include exactly one Amazon CloudFront distribution and exactly one WAF web ACL. You cannot remove these required resources.

    " + }, + "GetSubscription":{ + "name":"GetSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/GetSubscription", + "responseCode":200 + }, + "input":{"shape":"GetSubscriptionInput"}, + "output":{"shape":"GetSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns the details of a flat-rate pricing subscription, including its current status, associated resources, and any pending scheduled changes.

    ", + "readonly":true + }, + "ListSubscriptions":{ + "name":"ListSubscriptions", + "http":{ + "method":"POST", + "requestUri":"/v1/ListSubscriptions", + "responseCode":200 + }, + "input":{"shape":"ListSubscriptionsInput"}, + "output":{"shape":"ListSubscriptionsOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns a summary of all flat-rate pricing subscriptions in the calling account.

    ", + "readonly":true + }, + "UpdateSubscription":{ + "name":"UpdateSubscription", + "http":{ + "method":"POST", + "requestUri":"/v1/UpdateSubscription", + "responseCode":200 + }, + "input":{"shape":"UpdateSubscriptionInput"}, + "output":{"shape":"UpdateSubscriptionOutput"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Changes the plan tier of an existing subscription.

    Upgrades take effect immediately. Downgrades are scheduled and the current tier remains unchanged until the end of the billing cycle (calendar month). You cannot update a subscription while a scheduled change is pending. To make a new change, first cancel the pending change using CancelSubscriptionChange.

    This operation replaces the plan tier value. If you omit the optional usageLevel field, it is reset to the default.

    " + } + }, + "shapes":{ + "AccessDeniedException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    You do not have the required permissions to perform this operation. Verify that your IAM policy grants access to this action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, + "exception":true + }, + "ApprovalMode":{ + "type":"string", + "documentation":"

    Determines whether a subscription requires explicit approval before billing starts.

    ", + "enum":[ + "MANUAL", + "IMMEDIATE" + ] + }, + "ApprovePaidSubscriptionInput":{ + "type":"structure", + "required":[ + "arn", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to approve.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response. This ensures you are approving the expected version of the subscription.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "ApprovePaidSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the approved subscription.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "AssociateResourcesToSubscriptionInput":{ + "type":"structure", + "required":[ + "arn", + "resourceArns", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to add resources to.

    " + }, + "resourceArns":{ + "shape":"ResourceArns", + "documentation":"

    The ARNs of the resources to add to the subscription.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "AssociateResourcesToSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the subscription with the newly added resources.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "CancelSubscriptionChangeInput":{ + "type":"structure", + "required":[ + "arn", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription whose pending change you want to cancel.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "CancelSubscriptionChangeOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the subscription with the pending change removed.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "CancelSubscriptionInput":{ + "type":"structure", + "required":[ + "arn", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to cancel.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "CancelSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the subscription with the pending cancellation. For active subscriptions, a scheduledChange of type CANCELLATION is included.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "ConflictException":{ + "type":"structure", + "required":[ + "message", + "resourceId" + ], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource that has a conflicting state.

    " + } + }, + "documentation":"

    The request conflicts with the current state of the resource. This typically occurs when the ETag value in the If-Match header does not match the current version of the subscription. Retrieve the latest version and retry.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "CreateSubscriptionInput":{ + "type":"structure", + "required":[ + "planFamily", + "planTier", + "resourceArns" + ], + "members":{ + "planFamily":{ + "shape":"String", + "documentation":"

    The pricing plan family to subscribe to, such as CloudFront.

    " + }, + "planTier":{ + "shape":"String", + "documentation":"

    The tier level for the subscription, such as FREE, PRO, BUSINESS, or PREMIUM.

    " + }, + "usageLevel":{ + "shape":"String", + "documentation":"

    The usage level within the plan tier. Specify DEFAULT for the base configuration, or a higher level if your plan tier supports it.

    " + }, + "resourceArns":{ + "shape":"ResourceArns", + "documentation":"

    The ARNs of the resources to include in the subscription. Specify one or more supported resources.

    For subscriptions in the CloudFront plan family, the resources must include exactly one Amazon CloudFront distribution and exactly one WAF web ACL. You can also include other supported resources, such as Amazon Route 53 hosted zones and CloudFront KeyValueStores.

    " + }, + "approvalMode":{ + "shape":"ApprovalMode", + "documentation":"

    Determines whether the subscription requires explicit approval before billing starts. Set to MANUAL to require a separate ApprovePaidSubscription call, or IMMEDIATE to activate the subscription right away. For paid tier plans, this defaults to MANUAL if not specified. For the FREE plan tier, only IMMEDIATE is supported, and it is the default.

    " + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure that the request is handled only once. If you send the same request with the same client token, the API returns the original response without creating a duplicate subscription.

    ", + "idempotencyToken":true + } + } + }, + "CreateSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the newly created subscription.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The entity tag for concurrency control. Use this value in the If-Match header for subsequent operations on this subscription.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "DisassociateResourcesFromSubscriptionInput":{ + "type":"structure", + "required":[ + "arn", + "resourceArns", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to remove resources from.

    " + }, + "resourceArns":{ + "shape":"ResourceArns", + "documentation":"

    The ARNs of the resources to remove from the subscription. For subscriptions in the CloudFront plan family, you cannot remove the required CloudFront distribution or WAF web ACL.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "DisassociateResourcesFromSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the subscription with the specified resources removed.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "GetSubscriptionInput":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to retrieve.

    " + } + } + }, + "GetSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the requested subscription.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The entity tag for concurrency control. Use this value in the If-Match header for subsequent operations on this subscription.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "IdempotencyToken":{ + "type":"string", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure a request is handled only once.

    ", + "max":64, + "min":1 + }, + "InternalServerException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    An unexpected error occurred on the server. Retry the request.

    ", + "error":{"httpStatusCode":500}, + "exception":true, + "fault":true + }, + "ListSubscriptionsInput":{ + "type":"structure", + "members":{ + "nextToken":{ + "shape":"String", + "documentation":"

    A token from a previous ListSubscriptions response. If the response included a nextToken, there are more results available. Pass this value to retrieve the next page of results.

    " + } + } + }, + "ListSubscriptionsOutput":{ + "type":"structure", + "required":["subscriptionSummaries"], + "members":{ + "subscriptionSummaries":{ + "shape":"SubscriptionSummaryList", + "documentation":"

    The list of subscription summaries for the calling account.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    A token that indicates there are more results available. Pass this value in a subsequent ListSubscriptions request to retrieve the next page of results.

    " + } + } + }, + "ResourceArns":{ + "type":"list", + "member":{"shape":"String"}, + "documentation":"

    A list of 1 to 10 resource ARNs to include in the subscription.

    ", + "max":10, + "min":1 + }, + "ResourceNotFoundException":{ + "type":"structure", + "required":[ + "message", + "resourceId" + ], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource that was not found.

    " + } + }, + "documentation":"

    The specified subscription was not found. Verify that the ARN is correct and that the subscription belongs to your account.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, + "ScheduledChange":{ + "type":"structure", + "required":["changeType"], + "members":{ + "changeType":{ + "shape":"ScheduledChangeType", + "documentation":"

    The type of pending change. Possible values are DOWNGRADE (a tier change to a lower level) and CANCELLATION (subscription termination).

    " + }, + "effectiveDate":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the change takes effect, in ISO 8601 format. This value is populated after the change is confirmed by the billing system.

    " + }, + "planTier":{ + "shape":"String", + "documentation":"

    For downgrades, the tier level that the subscription will change to. Not present for cancellations.

    " + }, + "usageLevel":{ + "shape":"String", + "documentation":"

    For downgrades, the target usage level after the change takes effect.

    " + } + }, + "documentation":"

    A pending change on a subscription that takes effect at the end of the current billing period, such as a tier downgrade or cancellation.

    " + }, + "ScheduledChangeType":{ + "type":"string", + "documentation":"

    The type of pending change on a subscription.

    Possible values:

    • DOWNGRADE — The subscription tier is being lowered at the end of the billing period.

    • CANCELLATION — The subscription is being terminated at the end of the billing period.

    ", + "enum":[ + "DOWNGRADE", + "CANCELLATION" + ] + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request would exceed a service limit. You have reached the maximum number of subscriptions allowed for your account.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "Status":{ + "type":"string", + "documentation":"

    The status of a flat-rate pricing subscription.

    Possible values:

    • PENDING_APPROVAL — The subscription was created with manual approval and is waiting for an ApprovePaidSubscription call.

    • ACTIVE — The subscription is active and resources are covered by flat-rate pricing.

    • SYNC_IN_PROGRESS — A change is being applied to the subscription. Wait for the operation to complete before making additional changes.

    • FAILED — The subscription encountered an error. Check the statusReason field for details.

    ", + "enum":[ + "PENDING_APPROVAL", + "ACTIVE", + "SYNC_IN_PROGRESS", + "FAILED" + ] + }, + "String":{"type":"string"}, + "Subscription":{ + "type":"structure", + "required":[ + "arn", + "planFamily", + "planTier", + "status", + "resourceArns", + "createdAt", + "updatedAt" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies this subscription.

    " + }, + "planFamily":{ + "shape":"String", + "documentation":"

    The pricing plan family for the subscription, such as CloudFront.

    " + }, + "planTier":{ + "shape":"String", + "documentation":"

    The current tier level of the pricing plan, such as FREE, PRO, BUSINESS, or PREMIUM.

    " + }, + "usageLevel":{ + "shape":"String", + "documentation":"

    The usage level within the plan tier. When present, indicates a specific capacity configuration beyond the base tier.

    " + }, + "scheduledChange":{ + "shape":"ScheduledChange", + "documentation":"

    A pending change that will take effect at the end of the current billing period. This field is present only when a downgrade or cancellation is scheduled.

    " + }, + "status":{ + "shape":"Status", + "documentation":"

    The current status of the subscription. For the list of possible values, see the Status type.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable explanation of the current status, present when additional context is available.

    " + }, + "resourceArns":{ + "shape":"ResourceArns", + "documentation":"

    The ARNs of the resources covered by this subscription.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the subscription was created, in ISO 8601 format.

    " + }, + "updatedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the subscription was last modified, in ISO 8601 format.

    " + } + }, + "documentation":"

    The full details of a flat-rate pricing subscription, including its current configuration, status, and associated resources.

    " + }, + "SubscriptionArn":{ + "type":"string", + "documentation":"

    The Amazon Resource Name (ARN) of a flat-rate pricing subscription.

    ", + "max":2048, + "min":1 + }, + "SubscriptionSummary":{ + "type":"structure", + "required":[ + "arn", + "planFamily", + "planTier", + "status", + "resourceArns", + "createdAt", + "updatedAt", + "eTag" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies this subscription.

    " + }, + "planFamily":{ + "shape":"String", + "documentation":"

    The pricing plan family for the subscription, such as CloudFront.

    " + }, + "planTier":{ + "shape":"String", + "documentation":"

    The current tier level of the pricing plan.

    " + }, + "usageLevel":{ + "shape":"String", + "documentation":"

    The usage level within the plan tier.

    " + }, + "scheduledChange":{ + "shape":"ScheduledChange", + "documentation":"

    A pending change that will take effect at the end of the current billing period, if any.

    " + }, + "status":{ + "shape":"Status", + "documentation":"

    The current status of the subscription.

    " + }, + "statusReason":{ + "shape":"String", + "documentation":"

    A human-readable explanation of the current status, present when additional context is available.

    " + }, + "resourceArns":{ + "shape":"ResourceArns", + "documentation":"

    The ARNs of the resources covered by this subscription.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the subscription was created, in ISO 8601 format.

    " + }, + "updatedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The date and time when the subscription was last modified, in ISO 8601 format.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The entity tag for concurrency control. Pass this value in the If-Match header when making changes to this subscription.

    " + } + }, + "documentation":"

    Summary information for a flat-rate pricing subscription, as returned by list operations.

    " + }, + "SubscriptionSummaryList":{ + "type":"list", + "member":{"shape":"SubscriptionSummary"} + }, + "SyntheticTimestamp_date_time":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, + "ThrottlingException":{ + "type":"structure", + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    The request rate exceeds the allowed limit. Wait briefly and retry the request.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, + "exception":true + }, + "UpdateSubscriptionInput":{ + "type":"structure", + "required":[ + "arn", + "planTier", + "ifMatch" + ], + "members":{ + "arn":{ + "shape":"SubscriptionArn", + "documentation":"

    The ARN of the subscription to update.

    " + }, + "planTier":{ + "shape":"String", + "documentation":"

    The new tier level for the subscription.

    " + }, + "usageLevel":{ + "shape":"String", + "documentation":"

    The usage level within the plan tier. Specify DEFAULT for the base configuration. If omitted, the usage level is reset to the default.

    " + }, + "ifMatch":{ + "shape":"String", + "documentation":"

    The ETag value from a previous GetSubscription or ListSubscriptions response. This ensures you are updating the expected version of the subscription.

    ", + "location":"header", + "locationName":"If-Match" + }, + "clientToken":{ + "shape":"IdempotencyToken", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the request is handled only once.

    ", + "idempotencyToken":true + } + } + }, + "UpdateSubscriptionOutput":{ + "type":"structure", + "required":[ + "subscription", + "eTag" + ], + "members":{ + "subscription":{ + "shape":"Subscription", + "documentation":"

    The details of the updated subscription. For downgrades, the current tier remains unchanged and a scheduledChange indicates the pending change.

    " + }, + "eTag":{ + "shape":"String", + "documentation":"

    The updated entity tag for concurrency control.

    ", + "location":"header", + "locationName":"ETag" + } + }, + "payload":"subscription" + }, + "ValidationException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"}, + "resourceId":{ + "shape":"String", + "documentation":"

    The identifier of the resource that failed validation.

    " + } + }, + "documentation":"

    The request failed a business rule validation. For example, the specified resource might already be associated with another subscription, or the subscription might not be in the required state for this operation.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + } + }, + "documentation":"

    Manages flat-rate pricing subscriptions for supported services. Use this API to create, approve, update, and cancel subscriptions; associate and disassociate resources; and retrieve subscription details. With a flat-rate pricing subscription, you pay a fixed recurring fee for eligible resources instead of usage-based pricing.

    " +} diff --git a/services/proton/pom.xml b/services/proton/pom.xml index 6914973f4696..8850a9192b6e 100644 --- a/services/proton/pom.xml +++ b/services/proton/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT proton AWS Java SDK :: Services :: Proton diff --git a/services/proton/src/main/resources/codegen-resources/customization.config b/services/proton/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/proton/src/main/resources/codegen-resources/customization.config +++ b/services/proton/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/proton/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/proton/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..43531d5e5f08 --- /dev/null +++ b/services/proton/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://proton-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://proton-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://proton.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://proton.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/proton/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/proton/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2c98dda7f0f4..000000000000 --- a/services/proton/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://proton-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://proton-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://proton.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://proton.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/qapps/pom.xml b/services/qapps/pom.xml index 6e495f9bf4c2..e064a3e1735a 100644 --- a/services/qapps/pom.xml +++ b/services/qapps/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT qapps AWS Java SDK :: Services :: Q Apps diff --git a/services/qapps/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/qapps/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c7c394c795b5 --- /dev/null +++ b/services/qapps/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.qapps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.qapps-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.qapps.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data.qapps.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/qapps/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/qapps/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c1a4eee2b7d5..000000000000 --- a/services/qapps/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.qapps-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.qapps-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.qapps.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://data.qapps.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/qbusiness/pom.xml b/services/qbusiness/pom.xml index 8c5189e927c7..c7214797c426 100644 --- a/services/qbusiness/pom.xml +++ b/services/qbusiness/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT qbusiness AWS Java SDK :: Services :: Q Business diff --git a/services/qbusiness/src/main/resources/codegen-resources/customization.config b/services/qbusiness/src/main/resources/codegen-resources/customization.config index f754ccb8740d..4598243f17a8 100644 --- a/services/qbusiness/src/main/resources/codegen-resources/customization.config +++ b/services/qbusiness/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "usePriorKnowledgeForH2": true } diff --git a/services/qbusiness/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/qbusiness/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9f48e15d0771 --- /dev/null +++ b/services/qbusiness/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,157 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://qbusiness-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://qbusiness.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://qbusiness-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://qbusiness.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAAAAAkAAAADAAAAAQAAAAQF9eEIAAAAAgAAAAUF9eEIAAAAAwAAAAcAAAAGAAAABQX14QUF9eEHAAAABAAAAAgF9eEEAAAABQX14QMF9eEGAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/qbusiness/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/qbusiness/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index f1d9dbad8c9e..000000000000 --- a/services/qbusiness/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,247 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://qbusiness-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://qbusiness.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://qbusiness-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://qbusiness.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/qconnect/pom.xml b/services/qconnect/pom.xml index 0be6e63e37fd..0bf5e0019179 100644 --- a/services/qconnect/pom.xml +++ b/services/qconnect/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT qconnect AWS Java SDK :: Services :: Q Connect diff --git a/services/qconnect/src/main/resources/codegen-resources/customization.config b/services/qconnect/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/qconnect/src/main/resources/codegen-resources/customization.config +++ b/services/qconnect/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/qconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/qconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e6d91088fef7 --- /dev/null +++ b/services/qconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/qconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/qconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 85b7b38da271..000000000000 --- a/services/qconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/qconnect/src/main/resources/codegen-resources/service-2.json b/services/qconnect/src/main/resources/codegen-resources/service-2.json index 75d8f84481e6..04a8e37cf782 100644 --- a/services/qconnect/src/main/resources/codegen-resources/service-2.json +++ b/services/qconnect/src/main/resources/codegen-resources/service-2.json @@ -233,7 +233,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Creates an association between a content resource in a knowledge base and step-by-step guides. Step-by-step guides offer instructions to agents for resolving common customer issues. You create a content association to integrate Amazon Q in Connect and step-by-step guides.

    After you integrate Amazon Q and step-by-step guides, when Amazon Q provides a recommendation to an agent based on the intent that it's detected, it also provides them with the option to start the step-by-step guide that you have associated with the content.

    Note the following limitations:

    • You can create only one content association for each content resource in a knowledge base.

    • You can associate a step-by-step guide with multiple content resources.

    For more information, see Integrate Amazon Q in Connect with step-by-step guides in the Amazon Connect Administrator Guide.

    " + "documentation":"

    Creates an association between a content resource in a knowledge base and step-by-step guides. Step-by-step guides offer instructions to agents for resolving common customer issues. You create a content association to integrate Amazon Q in Connect and step-by-step guides.

    After you integrate Amazon Q and step-by-step guides, when Amazon Q provides a recommendation to an agent based on the intent that it's detected, it also provides them with the option to start the step-by-step guide that you have associated with the content.

    Note the following limitations:

    • You can create only one content association for each content resource in a knowledge base.

    • You can associate a step-by-step guide with multiple content resources.

    For more information, see Integrate Amazon Q in Connect with step-by-step guides in the Connect Customer Administrator Guide.

    " }, "CreateKnowledgeBase":{ "name":"CreateKnowledgeBase", @@ -351,7 +351,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Creates a session. A session is a contextual container used for generating recommendations. Amazon Connect creates a new Amazon Q in Connect session for each contact on which Amazon Q in Connect is enabled.

    ", + "documentation":"

    Creates a session. A session is a contextual container used for generating recommendations. Connect Customer creates a new Amazon Q in Connect session for each contact on which Amazon Q in Connect is enabled.

    ", "idempotent":true }, "DeactivateMessageTemplate":{ @@ -560,7 +560,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Deletes the content association.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Amazon Connect Administrator Guide.

    ", + "documentation":"

    Deletes the content association.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Connect Customer Administrator Guide.

    ", "idempotent":true }, "DeleteImportJob":{ @@ -783,7 +783,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Returns the content association.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Amazon Connect Administrator Guide.

    ", + "documentation":"

    Returns the content association.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Connect Customer Administrator Guide.

    ", "readonly":true }, "GetContentSummary":{ @@ -908,7 +908,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    This API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024, you will need to create a new Assistant in the Amazon Connect console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.

    Retrieves recommendations for the specified session. To avoid retrieving the same recommendations in subsequent calls, use NotifyRecommendationsReceived. This API supports long-polling behavior with the waitTimeSeconds parameter. Short poll is the default behavior and only returns recommendations already available. To perform a manual query against an assistant, use QueryAssistant.

    ", + "documentation":"

    This API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024, you will need to create a new Assistant in the Connect Customer console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.

    Retrieves recommendations for the specified session. To avoid retrieving the same recommendations in subsequent calls, use NotifyRecommendationsReceived. This API supports long-polling behavior with the waitTimeSeconds parameter. Short poll is the default behavior and only returns recommendations already available. To perform a manual query against an assistant, use QueryAssistant.

    ", "deprecated":true, "deprecatedMessage":"GetRecommendations API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024 you will need to create a new Assistant in the Connect console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.", "readonly":true @@ -1094,7 +1094,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Lists the content associations.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Amazon Connect Administrator Guide.

    ", + "documentation":"

    Lists the content associations.

    For more information about content associations--what they are and when they are used--see Integrate Amazon Q in Connect with step-by-step guides in the Connect Customer Administrator Guide.

    ", "readonly":true }, "ListContents":{ @@ -1317,7 +1317,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    This API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024, you will need to create a new Assistant in the Amazon Connect console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.

    Performs a manual search against the specified assistant. To retrieve recommendations for an assistant, use GetRecommendations.

    ", + "documentation":"

    This API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024, you will need to create a new Assistant in the Connect Customer console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.

    Performs a manual search against the specified assistant. To retrieve recommendations for an assistant, use GetRecommendations.

    ", "deprecated":true, "deprecatedMessage":"QueryAssistant API will be discontinued starting June 1, 2024. To receive generative responses after March 1, 2024 you will need to create a new Assistant in the Connect console and integrate the Amazon Q in Connect JavaScript library (amazon-q-connectjs) into your applications.", "readonly":true @@ -1740,7 +1740,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Updates a session. A session is a contextual container used for generating recommendations. Amazon Connect updates the existing Amazon Q in Connect session for each contact on which Amazon Q in Connect is enabled.

    " + "documentation":"

    Updates a session. A session is a contextual container used for generating recommendations. Connect Customer updates the existing Amazon Q in Connect session for each contact on which Amazon Q in Connect is enabled.

    " }, "UpdateSessionData":{ "name":"UpdateSessionData", @@ -2580,12 +2580,27 @@ }, "documentation":"

    Information about an agent.

    " }, + "AgentTarget":{ + "type":"structure", + "members":{ + "aiAgentId":{ + "shape":"NonEmptyString", + "documentation":"

    The identifier of an Amazon Connect AI Agent to use as the collaborator agent.

    " + }, + "applicationId":{ + "shape":"NonEmptyString", + "documentation":"

    The identifier of a third-party agent to use as the collaborator agent.

    " + } + }, + "documentation":"

    A union that identifies a collaborator agent to engage. Specify either an Amazon Connect AI Agent or a third-party agent.

    ", + "union":true + }, "AmazonConnectGuideAssociationData":{ "type":"structure", "members":{ "flowId":{ "shape":"GenericArn", - "documentation":"

    The Amazon Resource Name (ARN) of an Amazon Connect flow. Step-by-step guides are a type of flow.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an Connect Customer flow. Step-by-step guides are a type of flow.

    " } }, "documentation":"

    Content association data for a step-by-step guide.

    " @@ -3194,7 +3209,7 @@ "members":{ "connectConfiguration":{ "shape":"ConnectConfiguration", - "documentation":"

    The configuration information of the Amazon Connect data source.

    " + "documentation":"

    The configuration information of the Connect Customer data source.

    " } }, "documentation":"

    The configuration information of the external data source.

    ", @@ -3217,10 +3232,10 @@ "members":{ "instanceId":{ "shape":"NonEmptyString", - "documentation":"

    The identifier of the Amazon Connect instance. You can find the instanceId in the ARN of the instance.

    " + "documentation":"

    The identifier of the Connect Customer instance. You can find the instanceId in the ARN of the instance.

    " } }, - "documentation":"

    The configuration information of the Amazon Connect data source.

    " + "documentation":"

    The configuration information of the Connect Customer data source.

    " }, "ContactAttributeKey":{"type":"string"}, "ContactAttributeKeys":{ @@ -4401,7 +4416,7 @@ }, "channels":{ "shape":"Channels", - "documentation":"

    The Amazon Connect channels this quick response applies to.

    " + "documentation":"

    The Connect Customer channels this quick response applies to.

    " }, "language":{ "shape":"LanguageCode", @@ -4467,7 +4482,7 @@ }, "contactArn":{ "shape":"GenericArn", - "documentation":"

    The Amazon Resource Name (ARN) of the email contact in Amazon Connect. Used to retrieve email content and establish session context for AI-powered email assistance.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the email contact in Connect Customer. Used to retrieve email content and establish session context for AI-powered email assistance.

    " }, "orchestratorConfigurationList":{ "shape":"OrchestratorConfigurationList", @@ -4881,6 +4896,21 @@ } } }, + "DelegateAgentConfiguration":{ + "type":"structure", + "required":["agentTarget"], + "members":{ + "agentTarget":{ + "shape":"AgentTarget", + "documentation":"

    The collaborator agent to delegate to.

    " + }, + "instruction":{ + "shape":"MultiAgentInstruction", + "documentation":"

    The instruction that tells the Orchestration AI Agent when and how to delegate to this collaborator agent.

    " + } + }, + "documentation":"

    A collaborator agent configuration in which the Orchestration AI Agent invokes the collaborator, resuming when the collaborator returns.

    " + }, "DeleteAIAgentRequest":{ "type":"structure", "required":[ @@ -6325,7 +6355,7 @@ }, "values":{ "shape":"GroupingValues", - "documentation":"

    The list of values that define different groups of Amazon Q in Connect users.

    " + "documentation":"

    The list of values that define different groups of Amazon Q in Connect users.

    " } }, "documentation":"

    The configuration information of the grouping of Amazon Q in Connect users.

    " @@ -6485,7 +6515,7 @@ "members":{ "type":{ "shape":"GuardrailPiiEntityType", - "documentation":"

    Configure AI Guardrail type when the PII entity is detected.

    The following PIIs are used to block or mask sensitive information:

    • General

      • ADDRESS

        A physical address, such as \"100 Main Street, Anytown, USA\" or \"Suite #12, Building 123\". An address can include information such as the street, building, location, city, state, country, county, zip code, precinct, and neighborhood.

      • AGE

        An individual's age, including the quantity and unit of time. For example, in the phrase \"I am 40 years old,\" Guarrails recognizes \"40 years\" as an age.

      • NAME

        An individual's name. This entity type does not include titles, such as Dr., Mr., Mrs., or Miss. AI Guardrail doesn't apply this entity type to names that are part of organizations or addresses. For example, AI Guardrail recognizes the \"John Doe Organization\" as an organization, and it recognizes \"Jane Doe Street\" as an address.

      • EMAIL

        An email address, such as marymajor@email.com.

      • PHONE

        A phone number. This entity type also includes fax and pager numbers.

      • USERNAME

        A user name that identifies an account, such as a login name, screen name, nick name, or handle.

      • PASSWORD

        An alphanumeric string that is used as a password, such as \"* very20special#pass*\".

      • DRIVER_ID

        The number assigned to a driver's license, which is an official document permitting an individual to operate one or more motorized vehicles on a public road. A driver's license number consists of alphanumeric characters.

      • LICENSE_PLATE

        A license plate for a vehicle is issued by the state or country where the vehicle is registered. The format for passenger vehicles is typically five to eight digits, consisting of upper-case letters and numbers. The format varies depending on the location of the issuing state or country.

      • VEHICLE_IDENTIFICATION_NUMBER

        A Vehicle Identification Number (VIN) uniquely identifies a vehicle. VIN content and format are defined in the ISO 3779 specification. Each country has specific codes and formats for VINs.

    • Finance

      • CREDIT_DEBIT_CARD_CVV

        A three-digit card verification code (CVV) that is present on VISA, MasterCard, and Discover credit and debit cards. For American Express credit or debit cards, the CVV is a four-digit numeric code.

      • CREDIT_DEBIT_CARD_EXPIRY

        The expiration date for a credit or debit card. This number is usually four digits long and is often formatted as month/year or MM/YY. AI Guardrail recognizes expiration dates such as 01/21, 01/2021, and Jan 2021.

      • CREDIT_DEBIT_CARD_NUMBER

        The number for a credit or debit card. These numbers can vary from 13 to 16 digits in length. However, Amazon Comprehend also recognizes credit or debit card numbers when only the last four digits are present.

      • PIN

        A four-digit personal identification number (PIN) with which you can access your bank account.

      • INTERNATIONAL_BANK_ACCOUNT_NUMBER

        An International Bank Account Number has specific formats in each country. For more information, see www.iban.com/structure.

      • SWIFT_CODE

        A SWIFT code is a standard format of Bank Identifier Code (BIC) used to specify a particular bank or branch. Banks use these codes for money transfers such as international wire transfers.

        SWIFT codes consist of eight or 11 characters. The 11-digit codes refer to specific branches, while eight-digit codes (or 11-digit codes ending in 'XXX') refer to the head or primary office.

    • IT

      • IP_ADDRESS

        An IPv4 address, such as 198.51.100.0.

      • MAC_ADDRESS

        A media access control (MAC) address is a unique identifier assigned to a network interface controller (NIC).

      • URL

        A web address, such as www.example.com.

      • AWS_ACCESS_KEY

        A unique identifier that's associated with a secret access key; you use the access key ID and secret access key to sign programmatic Amazon Web Services requests cryptographically.

      • AWS_SECRET_KEY

        A unique identifier that's associated with an access key. You use the access key ID and secret access key to sign programmatic Amazon Web Services requests cryptographically.

    • USA specific

      • US_BANK_ACCOUNT_NUMBER

        A US bank account number, which is typically 10 to 12 digits long.

      • US_BANK_ROUTING_NUMBER

        A US bank account routing number. These are typically nine digits long,

      • US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER

        A US Individual Taxpayer Identification Number (ITIN) is a nine-digit number that starts with a \"9\" and contain a \"7\" or \"8\" as the fourth digit. An ITIN can be formatted with a space or a dash after the third and forth digits.

      • US_PASSPORT_NUMBER

        A US passport number. Passport numbers range from six to nine alphanumeric characters.

      • US_SOCIAL_SECURITY_NUMBER

        A US Social Security Number (SSN) is a nine-digit number that is issued to US citizens, permanent residents, and temporary working residents.

    • Canada specific

      • CA_HEALTH_NUMBER

        A Canadian Health Service Number is a 10-digit unique identifier, required for individuals to access healthcare benefits.

      • CA_SOCIAL_INSURANCE_NUMBER

        A Canadian Social Insurance Number (SIN) is a nine-digit unique identifier, required for individuals to access government programs and benefits.

        The SIN is formatted as three groups of three digits, such as 123-456-789. A SIN can be validated through a simple check-digit process called the Luhn algorithm .

    • UK Specific

      • UK_NATIONAL_HEALTH_SERVICE_NUMBER

        A UK National Health Service Number is a 10-17 digit number, such as 485 555 3456. The current system formats the 10-digit number with spaces after the third and sixth digits. The final digit is an error-detecting checksum.

      • UK_NATIONAL_INSURANCE_NUMBER

        A UK National Insurance Number (NINO) provides individuals with access to National Insurance (social security) benefits. It is also used for some purposes in the UK tax system.

        The number is nine digits long and starts with two letters, followed by six numbers and one letter. A NINO can be formatted with a space or a dash after the two letters and after the second, forth, and sixth digits.

      • UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER

        A UK Unique Taxpayer Reference (UTR) is a 10-digit number that identifies a taxpayer or a business.

    • Custom

      • Regex filter - You can use a regular expressions to define patterns for an AI Guardrail to recognize and act upon such as serial number, booking ID etc..

    " + "documentation":"

    Configure AI Guardrail type when the PII entity is detected.

    The following PIIs are used to block or mask sensitive information:

    • General

      • ADDRESS

        A physical address, such as \"100 Main Street, Anytown, USA\" or \"Suite #12, Building 123\". An address can include information such as the street, building, location, city, state, country, county, zip code, precinct, and neighborhood.

      • AGE

        An individual's age, including the quantity and unit of time. For example, in the phrase \"I am 40 years old,\" Guarrails recognizes \"40 years\" as an age.

      • NAME

        An individual's name. This entity type does not include titles, such as Dr., Mr., Mrs., or Miss. AI Guardrail doesn't apply this entity type to names that are part of organizations or addresses. For example, AI Guardrail recognizes the \"John Doe Organization\" as an organization, and it recognizes \"Jane Doe Street\" as an address.

      • EMAIL

        An email address, such as marymajor@email.com.

      • PHONE

        A phone number. This entity type also includes fax and pager numbers.

      • USERNAME

        A user name that identifies an account, such as a login name, screen name, nick name, or handle.

      • PASSWORD

        An alphanumeric string that is used as a password, such as \"* very20special#pass*\".

      • DRIVER_ID

        The number assigned to a driver's license, which is an official document permitting an individual to operate one or more motorized vehicles on a public road. A driver's license number consists of alphanumeric characters.

      • LICENSE_PLATE

        A license plate for a vehicle is issued by the state or country where the vehicle is registered. The format for passenger vehicles is typically five to eight digits, consisting of upper-case letters and numbers. The format varies depending on the location of the issuing state or country.

      • VEHICLE_IDENTIFICATION_NUMBER

        A Vehicle Identification Number (VIN) uniquely identifies a vehicle. VIN content and format are defined in the ISO 3779 specification. Each country has specific codes and formats for VINs.

    • Finance

      • CREDIT_DEBIT_CARD_CVV

        A three-digit card verification code (CVV) that is present on VISA, MasterCard, and Discover credit and debit cards. For American Express credit or debit cards, the CVV is a four-digit numeric code.

      • CREDIT_DEBIT_CARD_EXPIRY

        The expiration date for a credit or debit card. This number is usually four digits long and is often formatted as month/year or MM/YY. AI Guardrail recognizes expiration dates such as 01/21, 01/2021, and Jan 2021.

      • CREDIT_DEBIT_CARD_NUMBER

        The number for a credit or debit card. These numbers can vary from 13 to 16 digits in length. However, Amazon Comprehend also recognizes credit or debit card numbers when only the last four digits are present.

      • PIN

        A four-digit personal identification number (PIN) with which you can access your bank account.

      • INTERNATIONAL_BANK_ACCOUNT_NUMBER

        An International Bank Account Number has specific formats in each country. For more information, see www.iban.com/structure.

      • SWIFT_CODE

        A SWIFT code is a standard format of Bank Identifier Code (BIC) used to specify a particular bank or branch. Banks use these codes for money transfers such as international wire transfers.

        SWIFT codes consist of eight or 11 characters. The 11-digit codes refer to specific branches, while eight-digit codes (or 11-digit codes ending in 'XXX') refer to the head or primary office.

    • IT

      • IP_ADDRESS

        An IPv4 address, such as 198.51.100.0.

      • MAC_ADDRESS

        A media access control (MAC) address is a unique identifier assigned to a network interface controller (NIC).

      • URL

        A web address, such as www.example.com.

      • AWS_ACCESS_KEY

        A unique identifier that's associated with a secret access key; you use the access key ID and secret access key to sign programmatic Amazon Web Services requests cryptographically.

      • AWS_SECRET_KEY

        A unique identifier that's associated with an access key. You use the access key ID and secret access key to sign programmatic Amazon Web Services requests cryptographically.

    • USA specific

      • US_BANK_ACCOUNT_NUMBER

        A US bank account number, which is typically 10 to 12 digits long.

      • US_BANK_ROUTING_NUMBER

        A US bank account routing number. These are typically nine digits long,

      • US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER

        A US Individual Taxpayer Identification Number (ITIN) is a nine-digit number that starts with a \"9\" and contain a \"7\" or \"8\" as the fourth digit. An ITIN can be formatted with a space or a dash after the third and forth digits.

      • US_PASSPORT_NUMBER

        A US passport number. Passport numbers range from six to nine alphanumeric characters.

      • US_SOCIAL_SECURITY_NUMBER

        A US Social Security Number (SSN) is a nine-digit number that is issued to US citizens, permanent residents, and temporary working residents.

    • Canada specific

      • CA_HEALTH_NUMBER

        A Canadian Health Service Number is a 10-digit unique identifier, required for individuals to access healthcare benefits.

      • CA_SOCIAL_INSURANCE_NUMBER

        A Canadian Social Insurance Number (SIN) is a nine-digit unique identifier, required for individuals to access government programs and benefits.

        The SIN is formatted as three groups of three digits, such as 123-456-789. A SIN can be validated through a simple check-digit process called the Luhn algorithm. For more information, see Luhn algorithm on the Wikipedia website.

    • UK Specific

      • UK_NATIONAL_HEALTH_SERVICE_NUMBER

        A UK National Health Service Number is a 10-17 digit number, such as 485 555 3456. The current system formats the 10-digit number with spaces after the third and sixth digits. The final digit is an error-detecting checksum.

      • UK_NATIONAL_INSURANCE_NUMBER

        A UK National Insurance Number (NINO) provides individuals with access to National Insurance (social security) benefits. It is also used for some purposes in the UK tax system.

        The number is nine digits long and starts with two letters, followed by six numbers and one letter. A NINO can be formatted with a space or a dash after the two letters and after the second, forth, and sixth digits.

      • UK_UNIQUE_TAXPAYER_REFERENCE_NUMBER

        A UK Unique Taxpayer Reference (UTR) is a 10-digit number that identifies a taxpayer or a business.

    • Custom

      • Regex filter - You can use a regular expressions to define patterns for an AI Guardrail to recognize and act upon such as serial number, booking ID etc..

    " }, "action":{ "shape":"GuardrailSensitiveInformationAction", @@ -6732,6 +6762,29 @@ "documentation":"

    List of custom word configs.

    ", "min":1 }, + "HandoffAgentConfiguration":{ + "type":"structure", + "required":["agentTarget"], + "members":{ + "agentTarget":{ + "shape":"AgentTarget", + "documentation":"

    The collaborator agent to hand off to.

    " + }, + "instruction":{ + "shape":"MultiAgentInstruction", + "documentation":"

    The instruction that tells the Orchestration AI Agent when and how to hand off to this collaborator agent.

    " + }, + "audioStreamingEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the caller's audio is streamed directly to the collaborator agent and the collaborator's audio response is played back during the handoff. This applies only to voice handoffs.

    " + }, + "immediateHandoff":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the conversation is handed off to this collaborator agent immediately on the first turn, without any orchestration reasoning. At most one handoff in an AI Agent's configuration can set this to true.

    " + } + }, + "documentation":"

    A collaborator agent configuration in which the Orchestration AI Agent transfers control of the conversation to the collaborator agent.

    " + }, "Headers":{ "type":"map", "key":{"shape":"NonEmptyString"}, @@ -6981,6 +7034,14 @@ }, "documentation":"

    Information about the Amazon Q intent.

    " }, + "InteractionMode":{ + "type":"string", + "documentation":"

    How an orchestrator agent engaged a collaborator agent.

    • DELEGATE indicates that the orchestrator invoked the collaborator agent and retained control of the conversation, resuming when the collaborator returns.

    • HANDOFF indicates that the orchestrator transferred control of the conversation to the collaborator agent.

    ", + "enum":[ + "DELEGATE", + "HANDOFF" + ] + }, "JSONDocument":{ "type":"structure", "members":{}, @@ -8061,6 +8122,10 @@ "toolUseResult":{ "shape":"ToolUseResultData", "documentation":"

    The result of tool usage in the message.

    " + }, + "data":{ + "shape":"JSONDocument", + "documentation":"

    The message data as a structured JSON document. This is the payload for a message of type DATA, and must be a JSON object at the root level.

    " } }, "documentation":"

    The message data.

    ", @@ -8722,7 +8787,8 @@ "type":"string", "enum":[ "TEXT", - "TOOL_USE_RESULT" + "TOOL_USE_RESULT", + "DATA" ] }, "ModelDisplayName":{ @@ -8788,6 +8854,44 @@ "type":"list", "member":{"shape":"ModelSummary"} }, + "MultiAgentConfiguration":{ + "type":"structure", + "members":{ + "delegateAgentConfiguration":{ + "shape":"DelegateAgentConfiguration", + "documentation":"

    Configures the collaborator agent as a delegate that the Orchestration AI Agent invokes while retaining control of the conversation.

    " + }, + "handoffAgentConfiguration":{ + "shape":"HandoffAgentConfiguration", + "documentation":"

    Configures the collaborator agent as a handoff target that the Orchestration AI Agent transfers control of the conversation to.

    " + } + }, + "documentation":"

    A union that configures a single collaborator agent for an Orchestration AI Agent, as either a delegate or a handoff.

    ", + "union":true + }, + "MultiAgentConfigurationList":{ + "type":"list", + "member":{"shape":"MultiAgentConfiguration"} + }, + "MultiAgentExampleList":{ + "type":"list", + "member":{"shape":"String"} + }, + "MultiAgentInstruction":{ + "type":"structure", + "members":{ + "instruction":{ + "shape":"String", + "documentation":"

    The natural-language instruction that tells the Orchestration AI Agent when and how to engage the collaborator agent.

    " + }, + "examples":{ + "shape":"MultiAgentExampleList", + "documentation":"

    Example interactions that illustrate when the Orchestration AI Agent should engage the collaborator agent.

    " + } + }, + "documentation":"

    The instruction that guides how the Orchestration AI Agent works with a collaborator agent.

    ", + "sensitive":true + }, "Name":{ "type":"string", "max":255, @@ -8942,7 +9046,6 @@ }, "OrchestrationAIAgentConfiguration":{ "type":"structure", - "required":["orchestrationAIPromptId"], "members":{ "orchestrationAIPromptId":{ "shape":"UuidWithQualifier", @@ -8956,6 +9059,10 @@ "shape":"ToolConfigurationList", "documentation":"

    The tool configurations used by the Orchestration AI Agent.

    " }, + "multiAgentConfigurations":{ + "shape":"MultiAgentConfigurationList", + "documentation":"

    The collaborator agents that the Orchestration AI Agent can work with. Each entry defines another agent that the orchestrator either delegates to or hands the conversation off to.

    " + }, "connectInstanceArn":{ "shape":"GenericArn", "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Connect instance used by the Orchestration AI Agent.

    " @@ -8963,10 +9070,30 @@ "locale":{ "shape":"NonEmptyString", "documentation":"

    The locale setting for the Orchestration AI Agent.

    " + }, + "inputSchemas":{ + "shape":"OrchestrationAIAgentConfigurationInputSchemasList", + "documentation":"

    The JSON schemas that define the structure of the structured data input accepted by the Orchestration AI Agent. The data in a DATA message sent to the agent is validated against these schemas. You can specify at most one schema.

    " + }, + "outputSchemas":{ + "shape":"OrchestrationAIAgentConfigurationOutputSchemasList", + "documentation":"

    The JSON schemas that define the structure of the structured output generated by the Orchestration AI Agent. You can specify at most one schema.

    " } }, "documentation":"

    The configuration for AI Agents of type ORCHESTRATION.

    " }, + "OrchestrationAIAgentConfigurationInputSchemasList":{ + "type":"list", + "member":{"shape":"JSONDocument"}, + "max":1, + "min":0 + }, + "OrchestrationAIAgentConfigurationOutputSchemasList":{ + "type":"list", + "member":{"shape":"JSONDocument"}, + "max":1, + "min":0 + }, "OrchestratorConfigurationEntry":{ "type":"structure", "required":["orchestratorUseCase"], @@ -9594,7 +9721,7 @@ }, "channels":{ "shape":"Channels", - "documentation":"

    The Amazon Connect contact channels this quick response applies to. The supported contact channel types include Chat.

    " + "documentation":"

    The Connect Customer contact channels this quick response applies to. The supported contact channel types include Chat.

    " }, "language":{ "shape":"LanguageCode", @@ -9844,7 +9971,7 @@ }, "channels":{ "shape":"Channels", - "documentation":"

    The Amazon Connect contact channels this quick response applies to. The supported contact channel types include Chat.

    " + "documentation":"

    The Connect Customer contact channels this quick response applies to. The supported contact channel types include Chat.

    " }, "language":{ "shape":"LanguageCode", @@ -9946,7 +10073,7 @@ }, "channels":{ "shape":"Channels", - "documentation":"

    The Amazon Connect contact channels this quick response applies to. The supported contact channel types include Chat.

    " + "documentation":"

    The Connect Customer contact channels this quick response applies to. The supported contact channel types include Chat.

    " }, "tags":{ "shape":"Tags", @@ -10454,6 +10581,16 @@ "type":"list", "member":{"shape":"RetrieveResult"} }, + "ReturnReason":{ + "type":"string", + "documentation":"

    The reason a sub-agent returned control to the calling agent.

    • COMPLETE – the request was fulfilled.

    • COMPLETE_WITH_ERROR – the sub-agent attempted the request but could not fully complete it.

    • ESCALATE – the conversation should be transferred to a human agent.

    • OUT_OF_DOMAIN – the request fell outside the sub-agent's domain of expertise.

    ", + "enum":[ + "COMPLETE", + "COMPLETE_WITH_ERROR", + "ESCALATE", + "OUT_OF_DOMAIN" + ] + }, "RuntimeSessionData":{ "type":"structure", "required":[ @@ -10641,7 +10778,7 @@ }, "attributes":{ "shape":"ContactAttributes", - "documentation":"

    The user-defined Amazon Connect contact attributes to be resolved when search results are returned.

    " + "documentation":"

    The user-defined Connect Customer contact attributes to be resolved when search results are returned.

    " } } }, @@ -11209,6 +11346,18 @@ "shape":"NonEmptyString", "documentation":"

    AI agent orchestrator use case

    " }, + "interactionMode":{ + "shape":"InteractionMode", + "documentation":"

    How the orchestrator engaged the collaborator agent. Present on spans that invoke a collaborator agent.

    " + }, + "targetAgentId":{ + "shape":"NonEmptyString", + "documentation":"

    Identifier of the collaborator agent being invoked. For first-party collaborators this is the Amazon Connect AI agent ID; for third-party collaborators this is the external application ID.

    " + }, + "returnReason":{ + "shape":"ReturnReason", + "documentation":"

    Reason a sub-agent returned control to the calling agent. Present on return_to_agent spans.

    " + }, "requestModel":{ "shape":"NonEmptyString", "documentation":"

    LLM model ID for request (e.g., anthropic.claude-3-sonnet)

    " @@ -12610,7 +12759,7 @@ }, "channels":{ "shape":"Channels", - "documentation":"

    The Amazon Connect contact channels this quick response applies to. The supported contact channel types include Chat.

    " + "documentation":"

    The Connect Customer contact channels this quick response applies to. The supported contact channel types include Chat.

    " }, "language":{ "shape":"LanguageCode", @@ -13009,5 +13158,5 @@ ] } }, - "documentation":"

    Powered by Amazon Bedrock: Amazon Web Services implements automated abuse detection. Because Amazon Q in Connect is built on Amazon Bedrock, users can take full advantage of the controls implemented in Amazon Bedrock to enforce safety, security, and the responsible use of artificial intelligence (AI).

    Amazon Q in Connect is a generative AI customer service assistant. It is an LLM-enhanced evolution of Amazon Connect Wisdom that delivers real-time recommendations to help contact center agents resolve customer issues quickly and accurately.

    Amazon Q in Connect automatically detects customer intent during calls and chats using conversational analytics and natural language understanding (NLU). It then provides agents with immediate, real-time generative responses and suggested actions, and links to relevant documents and articles. Agents can also query Amazon Q in Connect directly using natural language or keywords to answer customer requests.

    Use the Amazon Q in Connect APIs to create an assistant and a knowledge base, for example, or manage content by uploading custom files.

    For more information, see Use Amazon Q in Connect for generative AI powered agent assistance in real-time in the Amazon Connect Administrator Guide.

    " + "documentation":"

    Powered by Amazon Bedrock: Amazon Web Services implements automated abuse detection. Because Amazon Q in Connect is built on Amazon Bedrock, users can take full advantage of the controls implemented in Amazon Bedrock to enforce safety, security, and the responsible use of artificial intelligence (AI).

    Amazon Q in Connect is a generative AI customer service assistant. It is an LLM-enhanced evolution of Connect Customer Wisdom that delivers real-time recommendations to help contact center agents resolve customer issues quickly and accurately.

    Amazon Q in Connect automatically detects customer intent during calls and chats using conversational analytics and natural language understanding (NLU). It then provides agents with immediate, real-time generative responses and suggested actions, and links to relevant documents and articles. Agents can also query Amazon Q in Connect directly using natural language or keywords to answer customer requests.

    Use the Amazon Q in Connect APIs to create an assistant and a knowledge base, for example, or manage content by uploading custom files.

    For more information, see Use Amazon Q in Connect for generative AI powered agent assistance in real-time in the Connect Customer Administrator Guide.

    " } diff --git a/services/quicksight/pom.xml b/services/quicksight/pom.xml index 6febfb6021a1..e8a4d8fff891 100644 --- a/services/quicksight/pom.xml +++ b/services/quicksight/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT quicksight AWS Java SDK :: Services :: QuickSight diff --git a/services/quicksight/src/main/resources/codegen-resources/customization.config b/services/quicksight/src/main/resources/codegen-resources/customization.config index 788e9cb8d991..cadacf8d10b0 100644 --- a/services/quicksight/src/main/resources/codegen-resources/customization.config +++ b/services/quicksight/src/main/resources/codegen-resources/customization.config @@ -144,6 +144,5 @@ "DataSourceParameters": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/quicksight/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/quicksight/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..303d1e3c5764 --- /dev/null +++ b/services/quicksight/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://quicksight-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://quicksight-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://quicksight.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://quicksight.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/quicksight/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/quicksight/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6c0c22f44e47..000000000000 --- a/services/quicksight/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://quicksight-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://quicksight-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://quicksight.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://quicksight.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/quicksight/src/main/resources/codegen-resources/paginators-1.json b/services/quicksight/src/main/resources/codegen-resources/paginators-1.json index d967f32c7747..cad24148afa6 100644 --- a/services/quicksight/src/main/resources/codegen-resources/paginators-1.json +++ b/services/quicksight/src/main/resources/codegen-resources/paginators-1.json @@ -24,6 +24,18 @@ "limit_key": "MaxResults", "result_key": "AnalysisSummaryList" }, + "ListApprovalPolicies": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Policies" + }, + "ListApps": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "AppSummaryList" + }, "ListAssetBundleExportJobs": { "input_token": "NextToken", "output_token": "NextToken", @@ -72,6 +84,12 @@ "limit_key": "MaxResults", "result_key": "DataSources" }, + "ListDlpSettings": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "DlpSettingSummaries" + }, "ListFlows": { "input_token": "NextToken", "output_token": "NextToken", @@ -132,6 +150,12 @@ "limit_key": "MaxResults", "result_key": "KnowledgeBaseSummaries" }, + "ListLimitsProfiles": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "profiles" + }, "ListNamespaces": { "input_token": "NextToken", "output_token": "NextToken", @@ -185,6 +209,12 @@ "output_token": "NextToken", "limit_key": "MaxResults" }, + "ListTopicsV2": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "TopicSummaryList" + }, "ListUserGroups": { "input_token": "NextToken", "output_token": "NextToken", @@ -214,6 +244,12 @@ "limit_key": "MaxResults", "result_key": "AnalysisSummaryList" }, + "SearchApps": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "AppSummaryList" + }, "SearchDashboards": { "input_token": "NextToken", "output_token": "NextToken", @@ -261,6 +297,12 @@ "output_token": "NextToken", "limit_key": "MaxResults", "result_key": "TopicSummaryList" + }, + "SearchTopicsV2": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "TopicSummaryList" } } } diff --git a/services/quicksight/src/main/resources/codegen-resources/service-2.json b/services/quicksight/src/main/resources/codegen-resources/service-2.json index 4b2f7238619a..baf2dc792623 100644 --- a/services/quicksight/src/main/resources/codegen-resources/service-2.json +++ b/services/quicksight/src/main/resources/codegen-resources/service-2.json @@ -68,6 +68,23 @@ ], "documentation":"

    Deletes reviewed answers for Q Topic.

    " }, + "BatchDescribeUserLimits":{ + "name":"BatchDescribeUserLimits", + "http":{ + "method":"POST", + "requestUri":"/governance/limits/accounts/{accountId}/user-limits", + "responseCode":200 + }, + "input":{"shape":"BatchDescribeUserLimitsRequest"}, + "output":{"shape":"BatchDescribeUserLimitsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes the effective resource limits for one or more Amazon Quick Sight users, including the limits that apply to each user based on their profile assignments.

    " + }, "CancelIngestion":{ "name":"CancelIngestion", "http":{ @@ -188,6 +205,26 @@ ], "documentation":"

    Creates an analysis in Amazon Quick Sight. Analyses can be created either from a template or from an AnalysisDefinition.

    " }, + "CreateApprovalPolicy":{ + "name":"CreateApprovalPolicy", + "http":{ + "method":"POST", + "requestUri":"/governance/approvalworkflows/policies", + "responseCode":200 + }, + "input":{"shape":"CreateApprovalPolicyRequest"}, + "output":{"shape":"CreateApprovalPolicyResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Creates an approval policy in Quick Sight.

    " + }, "CreateBrand":{ "name":"CreateBrand", "http":{ @@ -269,7 +306,7 @@ {"shape":"InvalidDataSetParameterValueException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Creates a dataset. This operation doesn't support datasets that include uploaded files as a source.

    " + "documentation":"

    Creates a dataset.

    " }, "CreateDataSource":{ "name":"CreateDataSource", @@ -292,6 +329,26 @@ ], "documentation":"

    Creates a data source.

    " }, + "CreateDlpSetting":{ + "name":"CreateDlpSetting", + "http":{ + "method":"POST", + "requestUri":"/accounts/{AwsAccountId}/data-loss-prevention/settings/{DlpSettingId}", + "responseCode":200 + }, + "input":{"shape":"CreateDlpSettingRequest"}, + "output":{"shape":"CreateDlpSettingResponse"}, + "errors":[ + {"shape":"ResourceExistsException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates a data loss prevention (DLP) setting configuration for an Amazon Web Services account. A DLP setting defines the DLP provider, the enforcement behavior, and the Quick capabilities that the setting applies to.

    " + }, "CreateFlow":{ "name":"CreateFlow", "http":{ @@ -432,6 +489,47 @@ ], "documentation":"

    Creates and starts a new SPICE ingestion for a dataset. You can manually refresh datasets in an Enterprise edition account 32 times in a 24-hour period. You can manually refresh datasets in a Standard edition account 8 times in a 24-hour period. Each 24-hour period is measured starting 24 hours before the current date and time.

    Any ingestions operating on tagged datasets inherit the same tags automatically for use in access control. For an example, see How do I create an IAM policy to control access to Amazon EC2 resources using tags? in the Amazon Web Services Knowledge Center. Tags are visible on the tagged dataset, but not on the ingestion resource.

    " }, + "CreateKnowledgeBase":{ + "name":"CreateKnowledgeBase", + "http":{ + "method":"POST", + "requestUri":"/v1/accounts/{AwsAccountId}/knowledge-bases", + "responseCode":202 + }, + "input":{"shape":"CreateKnowledgeBaseRequest"}, + "output":{"shape":"CreateKnowledgeBaseResponse"}, + "errors":[ + {"shape":"ResourceExistsException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"PreconditionNotMetException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Creates a knowledge base from a specified data source. Supported data source connector types include:

    • S3_KNOWLEDGE_BASE – Uses an Amazon S3 bucket as the data source.

    • WEB_CRAWLER – Uses web pages indexed by the built-in web crawler as the data source.

    • GOOGLE_DRIVE – Uses Google Drive as the data source. Supports service account authentication only.

    • SHAREPOINT – Uses SharePoint as the data source. Supports two-legged OAuth only.

    • ONE_DRIVE – Uses OneDrive as the data source. Supports two-legged OAuth only.

    " + }, + "CreateLimitsProfile":{ + "name":"CreateLimitsProfile", + "http":{ + "method":"POST", + "requestUri":"/governance/limits/accounts/{accountId}/profiles", + "responseCode":200 + }, + "input":{"shape":"CreateLimitsProfileRequest"}, + "output":{"shape":"CreateLimitsProfileResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Creates a limits profile that defines resource usage limits for Amazon Quick Sight users.

    " + }, "CreateNamespace":{ "name":"CreateNamespace", "http":{ @@ -655,6 +753,26 @@ ], "documentation":"

    Creates a topic refresh schedule.

    " }, + "CreateTopicV2":{ + "name":"CreateTopicV2", + "http":{ + "method":"POST", + "requestUri":"/accounts/{AwsAccountId}/topicsV2" + }, + "input":{"shape":"CreateTopicV2Request"}, + "output":{"shape":"CreateTopicV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"LimitExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceExistsException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Creates a new Q topic.

    " + }, "CreateVPCConnection":{ "name":"CreateVPCConnection", "http":{ @@ -788,6 +906,44 @@ ], "documentation":"

    Deletes an analysis from Amazon Quick Sight. You can optionally include a recovery window during which you can restore the analysis. If you don't specify a recovery window value, the operation defaults to 30 days. Amazon Quick Sight attaches a DeletionTime stamp to the response that specifies the end of the recovery window. At the end of the recovery window, Amazon Quick Sight deletes the analysis permanently.

    At any time before recovery window ends, you can use the RestoreAnalysis API operation to remove the DeletionTime stamp and cancel the deletion of the analysis. The analysis remains visible in the API until it's deleted, so you can describe it but you can't make a template from it.

    An analysis that's scheduled for deletion isn't accessible in the Amazon Quick Sight console. To access it in the console, restore it. Deleting an analysis doesn't delete the dashboards that you publish from it.

    " }, + "DeleteApp":{ + "name":"DeleteApp", + "http":{ + "method":"DELETE", + "requestUri":"/accounts/{AwsAccountId}/apps/{AppId}", + "responseCode":200 + }, + "input":{"shape":"DeleteAppRequest"}, + "output":{"shape":"DeleteAppResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes an app.

    ", + "idempotent":true + }, + "DeleteApprovalPolicy":{ + "name":"DeleteApprovalPolicy", + "http":{ + "method":"DELETE", + "requestUri":"/governance/approvalworkflows/policies/{PolicyId}", + "responseCode":200 + }, + "input":{"shape":"DeleteApprovalPolicyRequest"}, + "output":{"shape":"DeleteApprovalPolicyResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes an approval policy in Quick Sight.

    ", + "idempotent":true + }, "DeleteBrand":{ "name":"DeleteBrand", "http":{ @@ -937,6 +1093,25 @@ ], "documentation":"

    Deletes a linked Amazon Q Business application from an Quick Sight account

    " }, + "DeleteDlpSetting":{ + "name":"DeleteDlpSetting", + "http":{ + "method":"DELETE", + "requestUri":"/accounts/{AwsAccountId}/data-loss-prevention/settings/{DlpSettingId}", + "responseCode":200 + }, + "input":{"shape":"DeleteDlpSettingRequest"}, + "output":{"shape":"DeleteDlpSettingResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes a DLP setting configuration from an Amazon Web Services account.

    ", + "idempotent":true + }, "DeleteFlow":{ "name":"DeleteFlow", "http":{ @@ -1091,6 +1266,26 @@ ], "documentation":"

    Deletes a knowledge base.

    " }, + "DeleteLimitsProfile":{ + "name":"DeleteLimitsProfile", + "http":{ + "method":"DELETE", + "requestUri":"/governance/limits/accounts/{accountId}/profiles/{profileId}", + "responseCode":200 + }, + "input":{"shape":"DeleteLimitsProfileRequest"}, + "output":{"shape":"DeleteLimitsProfileResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Deletes a limits profile.

    ", + "idempotent":true + }, "DeleteNamespace":{ "name":"DeleteNamespace", "http":{ @@ -1314,6 +1509,24 @@ ], "documentation":"

    Deletes a topic refresh schedule.

    " }, + "DeleteTopicV2":{ + "name":"DeleteTopicV2", + "http":{ + "method":"DELETE", + "requestUri":"/accounts/{AwsAccountId}/topicsV2/{TopicId}" + }, + "input":{"shape":"DeleteTopicV2Request"}, + "output":{"shape":"DeleteTopicV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Deletes a Q topic.

    " + }, "DeleteUser":{ "name":"DeleteUser", "http":{ @@ -1595,6 +1808,63 @@ ], "documentation":"

    Provides the read and write permissions for an analysis.

    " }, + "DescribeApp":{ + "name":"DescribeApp", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/apps/{AppId}", + "responseCode":200 + }, + "input":{"shape":"DescribeAppRequest"}, + "output":{"shape":"DescribeAppResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes an app.

    ", + "readonly":true + }, + "DescribeAppPermissions":{ + "name":"DescribeAppPermissions", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/apps/{AppId}/permissions", + "responseCode":200 + }, + "input":{"shape":"DescribeAppPermissionsRequest"}, + "output":{"shape":"DescribeAppPermissionsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes the resource permissions for an app.

    ", + "readonly":true + }, + "DescribeApprovalPolicy":{ + "name":"DescribeApprovalPolicy", + "http":{ + "method":"GET", + "requestUri":"/governance/approvalworkflows/policies/{PolicyId}", + "responseCode":200 + }, + "input":{"shape":"DescribeApprovalPolicyRequest"}, + "output":{"shape":"DescribeApprovalPolicyResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes an approval policy in Quick Sight.

    ", + "readonly":true + }, "DescribeAssetBundleExportJob":{ "name":"DescribeAssetBundleExportJob", "http":{ @@ -1847,7 +2117,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Describes a dataset. This operation doesn't support datasets that include uploaded files as a source.

    " + "documentation":"

    Describes a dataset.

    " }, "DescribeDataSetPermissions":{ "name":"DescribeDataSetPermissions", @@ -1936,6 +2206,25 @@ ], "documentation":"

    Describes a Amazon Q Business application that is linked to an Quick Sight account.

    " }, + "DescribeDlpSetting":{ + "name":"DescribeDlpSetting", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/data-loss-prevention/settings/{DlpSettingId}", + "responseCode":200 + }, + "input":{"shape":"DescribeDlpSettingRequest"}, + "output":{"shape":"DescribeDlpSettingResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes the full configuration of a DLP setting in an Amazon Web Services account.

    ", + "readonly":true + }, "DescribeFlow":{ "name":"DescribeFlow", "http":{ @@ -2162,6 +2451,25 @@ "documentation":"

    Describes the resource permissions for a knowledge base.

    ", "readonly":true }, + "DescribeLimitsProfile":{ + "name":"DescribeLimitsProfile", + "http":{ + "method":"GET", + "requestUri":"/governance/limits/accounts/{accountId}/profiles/{profileId}", + "responseCode":200 + }, + "input":{"shape":"DescribeLimitsProfileRequest"}, + "output":{"shape":"DescribeLimitsProfileResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Describes the properties of an existing limits profile.

    ", + "readonly":true + }, "DescribeNamespace":{ "name":"DescribeNamespace", "http":{ @@ -2491,6 +2799,23 @@ ], "documentation":"

    Describes the permissions of a topic.

    " }, + "DescribeTopicPermissionsV2":{ + "name":"DescribeTopicPermissionsV2", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/topicsV2/{TopicId}/permissions" + }, + "input":{"shape":"DescribeTopicPermissionsV2Request"}, + "output":{"shape":"DescribeTopicPermissionsV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Describes the permissions of a topic.

    " + }, "DescribeTopicRefresh":{ "name":"DescribeTopicRefresh", "http":{ @@ -2528,6 +2853,24 @@ ], "documentation":"

    Deletes a topic refresh schedule.

    " }, + "DescribeTopicV2":{ + "name":"DescribeTopicV2", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/topicsV2/{TopicId}" + }, + "input":{"shape":"DescribeTopicV2Request"}, + "output":{"shape":"DescribeTopicV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Describes a Q topic.

    ", + "readonly":true + }, "DescribeUser":{ "name":"DescribeUser", "http":{ @@ -2783,6 +3126,43 @@ ], "documentation":"

    Lists Amazon Quick Sight analyses that exist in the specified Amazon Web Services account.

    " }, + "ListApprovalPolicies":{ + "name":"ListApprovalPolicies", + "http":{ + "method":"GET", + "requestUri":"/governance/approvalworkflows/policies", + "responseCode":200 + }, + "input":{"shape":"ListApprovalPoliciesRequest"}, + "output":{"shape":"ListApprovalPoliciesResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists all approval policies in the specified Quick Sight account. The results are paginated. If the response includes a NextToken value, pass it in a subsequent call to retrieve the next set of results.

    ", + "readonly":true + }, + "ListApps":{ + "name":"ListApps", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/apps", + "responseCode":200 + }, + "input":{"shape":"ListAppsRequest"}, + "output":{"shape":"ListAppsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the apps in an Amazon Web Services account. Results are paginated; use the NextToken parameter to retrieve additional results.

    ", + "readonly":true + }, "ListAssetBundleExportJobs":{ "name":"ListAssetBundleExportJobs", "http":{ @@ -2922,6 +3302,24 @@ ], "documentation":"

    Lists data sources in current Amazon Web Services Region that belong to this Amazon Web Services account.

    " }, + "ListDlpSettings":{ + "name":"ListDlpSettings", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/data-loss-prevention/settings", + "responseCode":200 + }, + "input":{"shape":"ListDlpSettingsRequest"}, + "output":{"shape":"ListDlpSettingsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists all DLP settings in an Amazon Web Services account.

    ", + "readonly":true + }, "ListFlows":{ "name":"ListFlows", "http":{ @@ -3130,6 +3528,24 @@ "documentation":"

    Lists all knowledge bases in an Amazon QuickSight account.

    ", "readonly":true }, + "ListLimitsProfiles":{ + "name":"ListLimitsProfiles", + "http":{ + "method":"GET", + "requestUri":"/governance/limits/accounts/{accountId}/profiles", + "responseCode":200 + }, + "input":{"shape":"ListLimitsProfilesRequest"}, + "output":{"shape":"ListLimitsProfilesResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists all limits profiles in an Amazon Quick Sight account. Results are paginated. Use the maxResults parameter to limit the number of results returned in a single call, and use the nextToken parameter to retrieve the next page of results.

    ", + "readonly":true + }, "ListNamespaces":{ "name":"ListNamespaces", "http":{ @@ -3447,6 +3863,23 @@ ], "documentation":"

    Lists all of the topics within an account.

    " }, + "ListTopicsV2":{ + "name":"ListTopicsV2", + "http":{ + "method":"GET", + "requestUri":"/accounts/{AwsAccountId}/topicsV2" + }, + "input":{"shape":"ListTopicsV2Request"}, + "output":{"shape":"ListTopicsV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidNextTokenException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Lists all of the Q topics in the specified Amazon Web Services account in an Amazon Web Services Region.

    " + }, "ListUserGroups":{ "name":"ListUserGroups", "http":{ @@ -3656,6 +4089,23 @@ ], "documentation":"

    Searches for analyses that belong to the user specified in the filter.

    This operation is eventually consistent. The results are best effort and may not reflect very recent updates and changes.

    " }, + "SearchApps":{ + "name":"SearchApps", + "http":{ + "method":"POST", + "requestUri":"/accounts/{AwsAccountId}/search/apps", + "responseCode":200 + }, + "input":{"shape":"SearchAppsRequest"}, + "output":{"shape":"SearchAppsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Searches for apps in an Amazon Web Services account using the specified filters. This operation is eventually consistent; the results might not reflect very recent updates. Results are paginated; use the NextToken parameter to retrieve additional results.

    " + }, "SearchDashboards":{ "name":"SearchDashboards", "http":{ @@ -3822,10 +4272,29 @@ {"shape":"InvalidParameterValueException"}, {"shape":"UnsupportedUserEditionException"}, {"shape":"InvalidNextTokenException"}, + {"shape":"AccessDeniedException"}, {"shape":"InternalFailureException"} ], "documentation":"

    Searches for any Q topic that exists in an Quick account.

    " }, + "SearchTopicsV2":{ + "name":"SearchTopicsV2", + "http":{ + "method":"POST", + "requestUri":"/accounts/{AwsAccountId}/search/topicsV2" + }, + "input":{"shape":"SearchTopicsV2Request"}, + "output":{"shape":"SearchTopicsV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ThrottlingException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidNextTokenException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Searches for any Q topic that exists in an Amazon Web Services account.

    " + }, "StartAssetBundleExportJob":{ "name":"StartAssetBundleExportJob", "http":{ @@ -4135,6 +4604,26 @@ ], "documentation":"

    Updates the read and write permissions for an analysis.

    " }, + "UpdateAppPermissions":{ + "name":"UpdateAppPermissions", + "http":{ + "method":"PUT", + "requestUri":"/accounts/{AwsAccountId}/apps/{AppId}/permissions", + "responseCode":200 + }, + "input":{"shape":"UpdateAppPermissionsRequest"}, + "output":{"shape":"UpdateAppPermissionsResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the resource permissions for an app. You can grant or revoke permissions and, optionally, change the app's visibility.

    ", + "idempotent":true + }, "UpdateApplicationWithTokenExchangeGrant":{ "name":"UpdateApplicationWithTokenExchangeGrant", "http":{ @@ -4154,6 +4643,25 @@ ], "documentation":"

    Updates an Quick application with a token exchange grant. This operation only supports Quick applications that are registered with IAM Identity Center.

    " }, + "UpdateApprovalPolicy":{ + "name":"UpdateApprovalPolicy", + "http":{ + "method":"PATCH", + "requestUri":"/governance/approvalworkflows/policies/{PolicyId}", + "responseCode":200 + }, + "input":{"shape":"UpdateApprovalPolicyRequest"}, + "output":{"shape":"UpdateApprovalPolicyResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Updates an approval policy in Quick Sight.

    " + }, "UpdateBrand":{ "name":"UpdateBrand", "http":{ @@ -4346,7 +4854,7 @@ {"shape":"InvalidDataSetParameterValueException"}, {"shape":"InternalFailureException"} ], - "documentation":"

    Updates a dataset. This operation doesn't support datasets that include uploaded files as a source. Partial updates are not supported by this operation.

    " + "documentation":"

    Updates a dataset. Partial updates are not supported by this operation.

    " }, "UpdateDataSetPermissions":{ "name":"UpdateDataSetPermissions", @@ -4421,6 +4929,26 @@ ], "documentation":"

    Updates a Amazon Q Business application that is linked to a Quick Sight account.

    " }, + "UpdateDlpSetting":{ + "name":"UpdateDlpSetting", + "http":{ + "method":"PUT", + "requestUri":"/accounts/{AwsAccountId}/data-loss-prevention/settings/{DlpSettingId}", + "responseCode":200 + }, + "input":{"shape":"UpdateDlpSettingRequest"}, + "output":{"shape":"UpdateDlpSettingResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates an existing DLP setting configuration in an Amazon Web Services account. Fields that are omitted from the request retain their current values.

    ", + "idempotent":true + }, "UpdateFlow":{ "name":"UpdateFlow", "http":{ @@ -4588,6 +5116,29 @@ ], "documentation":"

    Updates a customer managed key in a Quick Sight account.

    " }, + "UpdateKnowledgeBase":{ + "name":"UpdateKnowledgeBase", + "http":{ + "method":"POST", + "requestUri":"/v1/accounts/{AwsAccountId}/knowledge-bases/{KnowledgeBaseId}", + "responseCode":202 + }, + "input":{"shape":"UpdateKnowledgeBaseRequest"}, + "output":{"shape":"UpdateKnowledgeBaseResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidRequestException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"PreconditionNotMetException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"LimitExceededException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the properties of an existing knowledge base.

    ", + "idempotent":true + }, "UpdateKnowledgeBasePermissions":{ "name":"UpdateKnowledgeBasePermissions", "http":{ @@ -4611,6 +5162,25 @@ "documentation":"

    Updates the resource permissions for a knowledge base.

    ", "idempotent":true }, + "UpdateLimitsProfile":{ + "name":"UpdateLimitsProfile", + "http":{ + "method":"PUT", + "requestUri":"/governance/limits/accounts/{accountId}/profiles/{profileId}", + "responseCode":200 + }, + "input":{"shape":"UpdateLimitsProfileRequest"}, + "output":{"shape":"UpdateLimitsProfileResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"InternalFailureException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the properties of an existing limits profile.

    " + }, "UpdateOAuthClientApplication":{ "name":"UpdateOAuthClientApplication", "http":{ @@ -4999,6 +5569,26 @@ ], "documentation":"

    Updates the permissions of a topic.

    " }, + "UpdateTopicPermissionsV2":{ + "name":"UpdateTopicPermissionsV2", + "http":{ + "method":"PUT", + "requestUri":"/accounts/{AwsAccountId}/topicsV2/{TopicId}/permissions" + }, + "input":{"shape":"UpdateTopicPermissionsV2Request"}, + "output":{"shape":"UpdateTopicPermissionsV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"UnsupportedUserEditionException"}, + {"shape":"ConflictException"}, + {"shape":"LimitExceededException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Updates the permissions of a topic.

    " + }, "UpdateTopicRefreshSchedule":{ "name":"UpdateTopicRefreshSchedule", "http":{ @@ -5019,6 +5609,27 @@ ], "documentation":"

    Updates a topic refresh schedule.

    " }, + "UpdateTopicV2":{ + "name":"UpdateTopicV2", + "http":{ + "method":"PUT", + "requestUri":"/accounts/{AwsAccountId}/topicsV2/{TopicId}" + }, + "input":{"shape":"UpdateTopicV2Request"}, + "output":{"shape":"UpdateTopicV2Response"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"InvalidParameterValueException"}, + {"shape":"LimitExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ResourceExistsException"}, + {"shape":"ThrottlingException"}, + {"shape":"InternalFailureException"} + ], + "documentation":"

    Updates the definition of a Q topic.

    ", + "idempotent":true + }, "UpdateUser":{ "name":"UpdateUser", "http":{ @@ -5106,6 +5717,17 @@ }, "documentation":"

    Configuration for API key-based authentication to external services.

    " }, + "AccessControlConfiguration":{ + "type":"structure", + "members":{ + "isACLEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether ACLs are enabled for the knowledge base.

    This setting works together with the data source connector's ACL crawling. To enforce document-level access control end to end, set isACLEnabled to true and enable ACL crawling on the connector. For example, for an Amazon S3 data source, set accessControlConfiguration.crawlAcl to true in the connector template. For more information, see KbTemplateConfiguration. Enabling only one of the two settings does not produce a fully ACL-enforced knowledge base.

    ", + "box":true + } + }, + "documentation":"

    The access control settings for a knowledge base. Use this structure to enable or disable document-level access control lists (ACLs) that filter query results based on the permissions from the source data connector.

    " + }, "AccessDeniedException":{ "type":"structure", "members":{ @@ -6012,6 +6634,10 @@ "shape":"DataSetArnsList", "documentation":"

    The ARNs of the datasets of the analysis.

    " }, + "TopicArns":{ + "shape":"TopicArnsList", + "documentation":"

    The ARNs of the topics associated with the analysis.

    " + }, "ThemeArn":{ "shape":"Arn", "documentation":"

    The ARN of the theme of the analysis.

    " @@ -6050,6 +6676,10 @@ "shape":"DataSetIdentifierDeclarationList", "documentation":"

    An array of dataset identifier declarations. This mapping allows the usage of dataset identifiers instead of dataset ARNs throughout analysis sub-structures.

    " }, + "TopicIdentifierDeclarations":{ + "shape":"TopicIdentifierDeclarationList", + "documentation":"

    An array of topic identifier declarations. This mapping allows the usage of topic identifiers instead of topic ARNs throughout analysis sub-structures.

    " + }, "Sheets":{ "shape":"SheetDefinitionList", "documentation":"

    An array of sheet definitions for an analysis. Each SheetDefinition provides detailed information about a sheet within this analysis.

    " @@ -6187,6 +6817,10 @@ "shape":"DataSetReferenceList", "documentation":"

    The dataset references of the source template of an analysis.

    " }, + "TopicReferences":{ + "shape":"TopicReferenceList", + "documentation":"

    The topic references of the source template of an analysis.

    " + }, "Arn":{ "shape":"Arn", "documentation":"

    The Amazon Resource Name (ARN) of the source template of an analysis.

    " @@ -6396,6 +7030,58 @@ "type":"list", "member":{"shape":"AnswerId"} }, + "AppId":{ + "type":"string", + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "AppName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[\\S\\s]+" + }, + "AppSummary":{ + "type":"structure", + "members":{ + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app.

    " + }, + "Arn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the app.

    " + }, + "Name":{ + "shape":"AppName", + "documentation":"

    The display name of the app.

    " + }, + "CreatedTime":{ + "shape":"Timestamp", + "documentation":"

    The time that the app was created.

    " + }, + "LastUpdatedTime":{ + "shape":"Timestamp", + "documentation":"

    The time that the app was last updated.

    " + }, + "Visibility":{ + "shape":"AppVisibility", + "documentation":"

    The sharing status of the app: PUBLIC if the app is shared publicly, or PRIVATE if it is private.

    " + } + }, + "documentation":"

    A summary of an app, including its identifier, name, and metadata.

    " + }, + "AppSummaryList":{ + "type":"list", + "member":{"shape":"AppSummary"} + }, + "AppVisibility":{ + "type":"string", + "documentation":"

    The visibility of an app. Valid values are:

    • PRIVATE – The app is reachable only by authorized Amazon QuickSight principals.

    • PUBLIC – The published app is reachable by anyone on the internet without signing in.

    ", + "enum":[ + "PRIVATE", + "PUBLIC" + ] + }, "AppendOperation":{ "type":"structure", "required":[ @@ -6446,6 +7132,25 @@ "max":2048, "min":0 }, + "ApplicableTo":{ + "type":"structure", + "required":["Type"], + "members":{ + "Type":{ + "shape":"ApplicableToType", + "documentation":"

    The type of scoping that determines which principals the approval policy applies to. Valid values are defined as follows:

    • GROUP: The policy applies only to principals in the groups specified by GroupArns. When you use GROUP, you must also provide a value for GroupArns.

    " + }, + "GroupArns":{ + "shape":"GroupArnList", + "documentation":"

    The list of group ARNs that the policy applies to. Required when type is GROUP.

    " + } + }, + "documentation":"

    The scoping configuration that determines which principals an approval policy applies to.

    " + }, + "ApplicableToType":{ + "type":"string", + "enum":["GROUP"] + }, "ApplicationArn":{ "type":"string", "max":1284, @@ -6470,6 +7175,72 @@ }, "documentation":"

    The application theme.

    " }, + "ApprovalGroupList":{ + "type":"list", + "member":{"shape":"Arn"}, + "min":1 + }, + "ApprovalPolicy":{ + "type":"structure", + "required":[ + "PolicyId", + "PolicyArn", + "Name", + "Actions", + "AssetTypes", + "ApplicableTo", + "ApprovalGroups", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "PolicyId":{ + "shape":"PolicyId", + "documentation":"

    The unique identifier of the approval policy.

    " + }, + "PolicyArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the approval policy.

    " + }, + "Name":{ + "shape":"PolicyName", + "documentation":"

    The name of the approval policy.

    " + }, + "Description":{ + "shape":"PolicyDescription", + "documentation":"

    A description of the approval policy.

    " + }, + "Actions":{ + "shape":"GovernedActionList", + "documentation":"

    The list of governed actions that trigger the approval workflow.

    " + }, + "AssetTypes":{ + "shape":"AssetTypeList", + "documentation":"

    The list of asset types that the approval policy applies to.

    " + }, + "ApplicableTo":{ + "shape":"ApplicableTo", + "documentation":"

    The scoping configuration that determines who the approval policy applies to.

    " + }, + "ApprovalGroups":{ + "shape":"ApprovalGroupList", + "documentation":"

    The list of group ARNs whose members can approve requests.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the approval policy was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the approval policy was last updated.

    " + } + }, + "documentation":"

    A governance approval policy that specifies which principals and governed actions require approval, and which assets the policy applies to.

    " + }, + "ApprovalPolicyList":{ + "type":"list", + "member":{"shape":"ApprovalPolicy"} + }, "ArcAxisConfiguration":{ "type":"structure", "members":{ @@ -6585,6 +7356,10 @@ "Folders":{ "shape":"AssetBundleExportJobFolderOverridePropertiesList", "documentation":"

    An optional list of structures that controls how Folder resources are parameterized in the returned CloudFormation template.

    " + }, + "TopicsV2":{ + "shape":"AssetBundleExportJobTopicV2OverridePropertiesList", + "documentation":"

    An optional list of structures that controls how Topic resources are parameterized in the returned CloudFormation template.

    " } }, "documentation":"

    An optional collection of CloudFormation property configurations that control how the export job is generated.

    " @@ -6942,6 +7717,43 @@ "max":10, "min":1 }, + "AssetBundleExportJobTopicV2OverrideProperties":{ + "type":"structure", + "required":[ + "Arn", + "Properties" + ], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The ARN of the specific Topic resource whose override properties are configured in this structure.

    " + }, + "Properties":{ + "shape":"AssetBundleExportJobTopicV2PropertyToOverrideList", + "documentation":"

    A list of Topic resource properties to generate variables for in the returned CloudFormation template.

    " + } + }, + "documentation":"

    Controls how a specific Topic resource is parameterized in the returned CloudFormation template.

    " + }, + "AssetBundleExportJobTopicV2OverridePropertiesList":{ + "type":"list", + "member":{"shape":"AssetBundleExportJobTopicV2OverrideProperties"}, + "max":50, + "min":1 + }, + "AssetBundleExportJobTopicV2PropertyToOverride":{ + "type":"string", + "enum":[ + "Name", + "Description" + ] + }, + "AssetBundleExportJobTopicV2PropertyToOverrideList":{ + "type":"list", + "member":{"shape":"AssetBundleExportJobTopicV2PropertyToOverride"}, + "max":10, + "min":1 + }, "AssetBundleExportJobVPCConnectionOverrideProperties":{ "type":"structure", "required":[ @@ -7466,6 +8278,10 @@ "Folders":{ "shape":"AssetBundleImportJobFolderOverrideParametersList", "documentation":"

    A list of overrides for any Folder resources that are present in the asset bundle that is imported.

    " + }, + "TopicsV2":{ + "shape":"AssetBundleImportJobTopicV2OverrideParametersList", + "documentation":"

    A list of overrides for any Topic resources that are present in the asset bundle that is imported.

    " } }, "documentation":"

    A list of overrides that modify the asset bundle resource configuration before the resource is imported.

    " @@ -7496,6 +8312,10 @@ "Folders":{ "shape":"AssetBundleImportJobFolderOverridePermissionsList", "documentation":"

    A list of permissions for the folders that you want to apply overrides to.

    " + }, + "TopicsV2":{ + "shape":"AssetBundleImportJobTopicV2OverridePermissionsList", + "documentation":"

    A list of permissions for the topics that you want to apply overrides to.

    " } }, "documentation":"

    A structure that contains the override permission configurations that modify the permissions for specified resources before the resource is imported.

    " @@ -7530,6 +8350,10 @@ "Folders":{ "shape":"AssetBundleImportJobFolderOverrideTagsList", "documentation":"

    A list of tag overrides for any Folder resources that are present in the asset bundle that is imported.

    " + }, + "TopicsV2":{ + "shape":"AssetBundleImportJobTopicV2OverrideTagsList", + "documentation":"

    A list of tag overrides for any Topic resources that are present in the asset bundle that is imported.

    " } }, "documentation":"

    A structure that contains the override tag configuration that modify the tags that are assigned to specified resources before the resource is imported.

    " @@ -7693,6 +8517,79 @@ "max":5, "min":1 }, + "AssetBundleImportJobTopicV2OverrideParameters":{ + "type":"structure", + "required":["TopicId"], + "members":{ + "TopicId":{ + "shape":"ResourceId", + "documentation":"

    The ID of the topic that you want to apply overrides to.

    " + }, + "Name":{ + "shape":"ResourceName", + "documentation":"

    A new name for the topic.

    " + }, + "Description":{ + "shape":"TopicDescription", + "documentation":"

    A new description for the topic.

    " + } + }, + "documentation":"

    The override parameters for a single topic that is being imported.

    " + }, + "AssetBundleImportJobTopicV2OverrideParametersList":{ + "type":"list", + "member":{"shape":"AssetBundleImportJobTopicV2OverrideParameters"}, + "max":50, + "min":1 + }, + "AssetBundleImportJobTopicV2OverridePermissions":{ + "type":"structure", + "required":[ + "TopicIds", + "Permissions" + ], + "members":{ + "TopicIds":{ + "shape":"AssetBundleRestrictiveResourceIdList", + "documentation":"

    A list of topic IDs that you want to apply overrides to. You can use * to override all topics in this asset bundle.

    " + }, + "Permissions":{ + "shape":"AssetBundleResourcePermissions", + "documentation":"

    A list of permissions for the topics that you want to apply overrides to.

    " + } + }, + "documentation":"

    An object that contains a list of permissions to be applied to a list of topic IDs.

    " + }, + "AssetBundleImportJobTopicV2OverridePermissionsList":{ + "type":"list", + "member":{"shape":"AssetBundleImportJobTopicV2OverridePermissions"}, + "max":2, + "min":1 + }, + "AssetBundleImportJobTopicV2OverrideTags":{ + "type":"structure", + "required":[ + "TopicIds", + "Tags" + ], + "members":{ + "TopicIds":{ + "shape":"AssetBundleRestrictiveResourceIdList", + "documentation":"

    A list of topic IDs that you want to apply overrides to. You can use * to override all topics in this asset bundle.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of tags for the topics that you want to apply overrides to.

    " + } + }, + "documentation":"

    An object that contains a list of tags to be assigned to a list of topic IDs.

    " + }, + "AssetBundleImportJobTopicV2OverrideTagsList":{ + "type":"list", + "member":{"shape":"AssetBundleImportJobTopicV2OverrideTags"}, + "max":5, + "min":1 + }, "AssetBundleImportJobVPCConnectionOverrideParameters":{ "type":"structure", "required":["VPCConnectionId"], @@ -7872,10 +8769,27 @@ "CustomActionDefaults":{ "shape":"VisualCustomActionDefaults", "documentation":"

    A list of visual custom actions for the analysis.

    " + }, + "VisualMessages":{ + "shape":"VisualMessages", + "documentation":"

    The configuration options for the messages that are displayed on visuals in the analysis.

    " } }, "documentation":"

    An array of analysis level configurations.

    " }, + "AssetType":{ + "type":"string", + "enum":[ + "AGENT", + "SPACE", + "KNOWLEDGE_BASE" + ] + }, + "AssetTypeList":{ + "type":"list", + "member":{"shape":"AssetType"}, + "min":1 + }, "AssignmentStatus":{ "type":"string", "enum":[ @@ -8002,6 +8916,14 @@ }, "documentation":"

    Authentication configuration for connecting to external services.

    " }, + "AuthType":{ + "type":"string", + "enum":[ + "THREE_LEGGED_OAUTH", + "TWO_LEGGED_OAUTH", + "SERVICE_ACCOUNT" + ] + }, "AuthenticationMetadata":{ "type":"structure", "members":{ @@ -8866,6 +9788,83 @@ } } }, + "BatchDescribeUserLimitsError":{ + "type":"structure", + "required":[ + "errorCode", + "message" + ], + "members":{ + "userName":{ + "shape":"String", + "documentation":"

    The name of the user that failed.

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    The namespace of the user that failed.

    " + }, + "userArn":{ + "shape":"String", + "documentation":"

    The ARN of the user that failed.

    " + }, + "errorCode":{ + "shape":"String", + "documentation":"

    The error code for the failure.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    The error message for the failure.

    " + } + }, + "documentation":"

    Information about a user whose limits could not be described in a batch operation.

    " + }, + "BatchDescribeUserLimitsErrorList":{ + "type":"list", + "member":{"shape":"BatchDescribeUserLimitsError"} + }, + "BatchDescribeUserLimitsRequest":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the users.

    ", + "location":"uri", + "locationName":"accountId" + }, + "users":{ + "shape":"BatchDescribeUserLimitsRequestUsersList", + "documentation":"

    A list of users to describe limits for. Each entry contains a user name and namespace.

    " + }, + "resourceTypes":{ + "shape":"ResourceTypeList", + "documentation":"

    An optional filter that limits the results to specific resource types. If you don't specify a value, the operation returns limits for all resource types.

    " + } + } + }, + "BatchDescribeUserLimitsRequestUsersList":{ + "type":"list", + "member":{"shape":"UserLimitsEntry"}, + "max":100, + "min":1 + }, + "BatchDescribeUserLimitsResponse":{ + "type":"structure", + "required":[ + "userLimits", + "errors" + ], + "members":{ + "userLimits":{ + "shape":"UserLimitsList", + "documentation":"

    A list of user limits results. Each entry contains the effective limits for a user.

    " + }, + "errors":{ + "shape":"BatchDescribeUserLimitsErrorList", + "documentation":"

    A list of errors for users whose limits could not be described.

    " + } + } + }, "BigQueryParameters":{ "type":"structure", "required":["ProjectId"], @@ -9490,7 +10489,6 @@ "CalculatedField":{ "type":"structure", "required":[ - "DataSetIdentifier", "Name", "Expression" ], @@ -9499,6 +10497,10 @@ "shape":"DataSetIdentifier", "documentation":"

    The data set that is used in this calculated field.

    " }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that is used in this calculated field.

    " + }, "Name":{ "shape":"ColumnName", "documentation":"

    The name of the calculated field.

    " @@ -9749,6 +10751,48 @@ "shape":"CapabilityState", "documentation":"

    The ability to use knowledge bases to specify content from external applications.

    " }, + "CreateAndUpdateKnowledgeBases":{"shape":"CapabilityState"}, + "ShareKnowledgeBases":{"shape":"CapabilityState"}, + "SharePointKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateSharePointKnowledgeBase":{"shape":"CapabilityState"}, + "ShareSharePointKnowledgeBase":{"shape":"CapabilityState"}, + "UseSharePointKnowledgeBase":{"shape":"CapabilityState"}, + "GoogleDriveKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateGoogleDriveKnowledgeBase":{"shape":"CapabilityState"}, + "ShareGoogleDriveKnowledgeBase":{"shape":"CapabilityState"}, + "UseGoogleDriveKnowledgeBase":{"shape":"CapabilityState"}, + "WebCrawlerKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateWebCrawlerKnowledgeBase":{"shape":"CapabilityState"}, + "ShareWebCrawlerKnowledgeBase":{"shape":"CapabilityState"}, + "UseWebCrawlerKnowledgeBase":{"shape":"CapabilityState"}, + "S3KnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateS3KnowledgeBase":{"shape":"CapabilityState"}, + "ShareS3KnowledgeBase":{"shape":"CapabilityState"}, + "UseS3KnowledgeBase":{"shape":"CapabilityState"}, + "ConfluenceKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateConfluenceKnowledgeBase":{"shape":"CapabilityState"}, + "ShareConfluenceKnowledgeBase":{"shape":"CapabilityState"}, + "UseConfluenceKnowledgeBase":{"shape":"CapabilityState"}, + "OneDriveKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateOneDriveKnowledgeBase":{"shape":"CapabilityState"}, + "ShareOneDriveKnowledgeBase":{"shape":"CapabilityState"}, + "UseOneDriveKnowledgeBase":{"shape":"CapabilityState"}, + "QBusinessKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateQBusinessKnowledgeBase":{"shape":"CapabilityState"}, + "ShareQBusinessKnowledgeBase":{"shape":"CapabilityState"}, + "UseQBusinessKnowledgeBase":{"shape":"CapabilityState"}, + "BedrockManagedKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateBedrockManagedKnowledgeBase":{"shape":"CapabilityState"}, + "ShareBedrockManagedKnowledgeBase":{"shape":"CapabilityState"}, + "UseBedrockManagedKnowledgeBase":{"shape":"CapabilityState"}, + "BoxKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateBoxKnowledgeBase":{"shape":"CapabilityState"}, + "ShareBoxKnowledgeBase":{"shape":"CapabilityState"}, + "UseBoxKnowledgeBase":{"shape":"CapabilityState"}, + "IDCKnowledgeBase":{"shape":"CapabilityState"}, + "CreateAndUpdateIDCKnowledgeBase":{"shape":"CapabilityState"}, + "ShareIDCKnowledgeBase":{"shape":"CapabilityState"}, + "UseIDCKnowledgeBase":{"shape":"CapabilityState"}, "Action":{ "shape":"CapabilityState", "documentation":"

    The ability to perform actions in external services through Action connectors. Actions allow users to interact with third-party systems.

    " @@ -10441,6 +11485,454 @@ "shape":"CapabilityState", "documentation":"

    The ability to use New Relic actions.

    " }, + "PagerDutyAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using PagerDuty Agent connectors.

    " + }, + "CreateAndUpdatePagerDutyAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update PagerDuty Agent actions.

    " + }, + "SharePagerDutyAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share PagerDuty Agent actions.

    " + }, + "UsePagerDutyAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use PagerDuty Agent actions.

    " + }, + "VisierAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Visier Agent connectors.

    " + }, + "CreateAndUpdateVisierAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Visier Agent actions.

    " + }, + "ShareVisierAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Visier Agent actions.

    " + }, + "UseVisierAgentAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Visier Agent actions.

    " + }, + "ZoomAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Zoom connectors.

    " + }, + "CreateAndUpdateZoomAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Zoom actions.

    " + }, + "ShareZoomAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Zoom actions.

    " + }, + "UseZoomAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Zoom actions.

    " + }, + "SnowFlakeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Snowflake Cortex Agent connectors.

    " + }, + "CreateAndUpdateSnowFlakeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Snowflake Cortex Agent actions.

    " + }, + "ShareSnowFlakeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Snowflake Cortex Agent actions.

    " + }, + "UseSnowFlakeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Snowflake Cortex Agent actions.

    " + }, + "ZapierAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Zapier Agent connectors.

    " + }, + "CreateAndUpdateZapierAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Zapier Agent actions.

    " + }, + "ShareZapierAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Zapier Agent actions.

    " + }, + "UseZapierAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Zapier Agent actions.

    " + }, + "AirtableAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Airtable connectors.

    " + }, + "CreateAndUpdateAirtableAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Airtable actions.

    " + }, + "ShareAirtableAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Airtable actions.

    " + }, + "UseAirtableAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Airtable actions.

    " + }, + "DropboxAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Dropbox connectors.

    " + }, + "CreateAndUpdateDropboxAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Dropbox actions.

    " + }, + "ShareDropboxAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Dropbox actions.

    " + }, + "UseDropboxAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Dropbox actions.

    " + }, + "GmailAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Gmail connectors.

    " + }, + "CreateAndUpdateGmailAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Gmail actions.

    " + }, + "ShareGmailAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Gmail actions.

    " + }, + "UseGmailAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Gmail actions.

    " + }, + "GoogleAnalyticsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Analytics connectors.

    " + }, + "CreateAndUpdateGoogleAnalyticsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Analytics actions.

    " + }, + "ShareGoogleAnalyticsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Analytics actions.

    " + }, + "UseGoogleAnalyticsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Analytics actions.

    " + }, + "GoogleDocsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Docs connectors.

    " + }, + "CreateAndUpdateGoogleDocsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Docs actions.

    " + }, + "ShareGoogleDocsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Docs actions.

    " + }, + "UseGoogleDocsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Docs actions.

    " + }, + "GoogleDriveAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Drive connectors.

    " + }, + "CreateAndUpdateGoogleDriveAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Drive actions.

    " + }, + "ShareGoogleDriveAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Drive actions.

    " + }, + "UseGoogleDriveAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Drive actions.

    " + }, + "GoogleMeetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Meet connectors.

    " + }, + "CreateAndUpdateGoogleMeetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Meet actions.

    " + }, + "ShareGoogleMeetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Meet actions.

    " + }, + "UseGoogleMeetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Meet actions.

    " + }, + "GoogleSheetsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Sheets connectors.

    " + }, + "CreateAndUpdateGoogleSheetsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Sheets actions.

    " + }, + "ShareGoogleSheetsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Sheets actions.

    " + }, + "UseGoogleSheetsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Sheets actions.

    " + }, + "GoogleSlidesAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Slides connectors.

    " + }, + "CreateAndUpdateGoogleSlidesAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Slides actions.

    " + }, + "ShareGoogleSlidesAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Slides actions.

    " + }, + "UseGoogleSlidesAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Slides actions.

    " + }, + "QuickBooksAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using QuickBooks connectors.

    " + }, + "CreateAndUpdateQuickBooksAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update QuickBooks actions.

    " + }, + "ShareQuickBooksAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share QuickBooks actions.

    " + }, + "UseQuickBooksAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use QuickBooks actions.

    " + }, + "FigmaAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Figma connectors.

    " + }, + "CreateAndUpdateFigmaAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Figma actions.

    " + }, + "ShareFigmaAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Figma actions.

    " + }, + "UseFigmaAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Figma actions.

    " + }, + "WhatsAppAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using WhatsApp connectors.

    " + }, + "CreateAndUpdateWhatsAppAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update WhatsApp actions.

    " + }, + "ShareWhatsAppAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share WhatsApp actions.

    " + }, + "UseWhatsAppAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use WhatsApp actions.

    " + }, + "GoogleChatAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Google Chat connectors.

    " + }, + "CreateAndUpdateGoogleChatAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Google Chat actions.

    " + }, + "ShareGoogleChatAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Google Chat actions.

    " + }, + "UseGoogleChatAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Google Chat actions.

    " + }, + "OneNoteAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Microsoft OneNote connectors.

    " + }, + "CreateAndUpdateOneNoteAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Microsoft OneNote actions.

    " + }, + "ShareOneNoteAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Microsoft OneNote actions.

    " + }, + "UseOneNoteAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Microsoft OneNote actions.

    " + }, + "ShopifyAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Shopify connectors.

    " + }, + "CreateAndUpdateShopifyAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Shopify actions.

    " + }, + "ShareShopifyAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Shopify actions.

    " + }, + "UseShopifyAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Shopify actions.

    " + }, + "AdobeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Adobe Marketing Agent connectors.

    " + }, + "CreateAndUpdateAdobeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Adobe Marketing Agent actions.

    " + }, + "ShareAdobeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Adobe Marketing Agent actions.

    " + }, + "UseAdobeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Adobe Marketing Agent actions.

    " + }, + "CiscoWebexVidcastAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Cisco Webex Video Messaging Agent connectors.

    " + }, + "CreateAndUpdateCiscoWebexVidcastAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Cisco Webex Video Messaging Agent actions.

    " + }, + "ShareCiscoWebexVidcastAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Cisco Webex Video Messaging Agent actions.

    " + }, + "UseCiscoWebexVidcastAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Cisco Webex Video Messaging Agent actions.

    " + }, + "CiscoWebexMeetingsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Cisco Webex Meetings connectors.

    " + }, + "CreateAndUpdateCiscoWebexMeetingsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Cisco Webex Meetings actions.

    " + }, + "ShareCiscoWebexMeetingsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Cisco Webex Meetings actions.

    " + }, + "UseCiscoWebexMeetingsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Cisco Webex Meetings actions.

    " + }, + "DunAndBradstreetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Dun and Bradstreet connectors.

    " + }, + "CreateAndUpdateDunAndBradstreetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Dun and Bradstreet actions.

    " + }, + "ShareDunAndBradstreetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Dun and Bradstreet actions.

    " + }, + "UseDunAndBradstreetAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Dun and Bradstreet actions.

    " + }, + "HGInsightsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using HG Insights Agent connectors.

    " + }, + "CreateAndUpdateHGInsightsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update HG Insights Agent actions.

    " + }, + "ShareHGInsightsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share HG Insights Agent actions.

    " + }, + "UseHGInsightsAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use HG Insights Agent actions.

    " + }, + "ZoomInfoAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using ZoomInfo Agent connectors.

    " + }, + "CreateAndUpdateZoomInfoAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update ZoomInfo Agent actions.

    " + }, + "ShareZoomInfoAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share ZoomInfo Agent actions.

    " + }, + "UseZoomInfoAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use ZoomInfo Agent actions.

    " + }, + "MoodysAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Moody's GenAI Ready Data connectors.

    " + }, + "CreateAndUpdateMoodysAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Moody's GenAI Ready Data actions.

    " + }, + "ShareMoodysAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Moody's GenAI Ready Data actions.

    " + }, + "UseMoodysAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Moody's GenAI Ready Data actions.

    " + }, + "BeeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to perform actions using Bee connectors.

    " + }, + "CreateAndUpdateBeeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create and update Bee actions.

    " + }, + "ShareBeeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to share Bee actions.

    " + }, + "UseBeeAction":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Bee actions.

    " + }, "Topic":{ "shape":"CapabilityState", "documentation":"

    The ability to perform Topic-related actions.

    " @@ -10493,6 +11985,26 @@ "shape":"CapabilityState", "documentation":"

    The ability to perform Extension-related actions.

    " }, + "UseBrowserExtension":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Amazon Quick through the browser extension for Chrome, Firefox, and Edge.

    " + }, + "UseWordAddInExtension":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Amazon Quick through the Microsoft Word add-in.

    " + }, + "UseOutlookAddInExtension":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Amazon Quick through the Microsoft Outlook add-in.

    " + }, + "UseExcelAddInExtension":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Amazon Quick through the Microsoft Excel add-in.

    " + }, + "UsePowerpointAddInExtension":{ + "shape":"CapabilityState", + "documentation":"

    The ability to use Amazon Quick through the Microsoft PowerPoint add-in.

    " + }, "ManageSharedFolders":{ "shape":"CapabilityState", "documentation":"

    The ability to create, update, delete and view shared folders (both restricted and unrestricted), ability to add any asset to shared folders, and ability to share the folders.

    Note: This does not prevent inheriting access to assets that others share with them through folder membership.

    " @@ -10508,13 +12020,33 @@ "Scenario":{ "shape":"CapabilityState", "documentation":"

    The ability to perform Scenario-related actions.

    " + }, + "Trigger":{ + "shape":"CapabilityState", + "documentation":"

    The ability to manage trigger-related settings for flows and automations.

    " + }, + "ScheduleTrigger":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create, view, edit, delete, and run schedule triggers for flows and automations.

    " + }, + "InboundEmailTrigger":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create, view, edit, delete, and run inbound email triggers for flows and automations.

    " + }, + "QuickEventTrigger":{ + "shape":"CapabilityState", + "documentation":"

    The ability to create, view, edit, delete, and run Quick event triggers for flows and automations.

    " } }, "documentation":"

    A set of actions that correspond to Amazon Quick Sight permissions.

    " }, "CapabilityState":{ "type":"string", - "enum":["DENY"] + "documentation":"

    The permission state of a capability in a custom permissions profile. Valid values:

    • DENY – Amazon Quick denies this capability for users assigned to the profile.

    • ALLOW – Amazon Quick grants this capability to users assigned to the profile. This value is only relevant when governance is enabled for the capability's category. Without governance, the default effect is always ALLOW. In a governed category, this value overrides the category-level deny-by-default behavior for that capability only.

    ", + "enum":[ + "DENY", + "ALLOW" + ] }, "CapacityBytesRangeFilter":{ "type":"structure", @@ -10811,11 +12343,11 @@ "type":"structure", "members":{ "CellValue":{ - "shape":"LimitedString", + "shape":"SynonymString", "documentation":"

    The cell value.

    " }, "Synonyms":{ - "shape":"StringList", + "shape":"SensitiveStringList", "documentation":"

    Other names or aliases for the cell value.

    " } }, @@ -11175,15 +12707,16 @@ }, "ColumnIdentifier":{ "type":"structure", - "required":[ - "DataSetIdentifier", - "ColumnName" - ], + "required":["ColumnName"], "members":{ "DataSetIdentifier":{ "shape":"DataSetIdentifier", "documentation":"

    The data set that the column belongs to.

    " }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that the column belongs to.

    " + }, "ColumnName":{ "shape":"ColumnName", "documentation":"

    The name of the column.

    " @@ -12545,7 +14078,7 @@ }, "SourceEntity":{ "shape":"AnalysisSourceEntity", - "documentation":"

    A source entity to use for the analysis that you're creating. This metadata structure contains details that describe a source template and one or more datasets.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " + "documentation":"

    A source entity to use for the analysis that you're creating. This metadata structure contains details that describe a source template and one or more datasets or topics.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " }, "ThemeArn":{ "shape":"Arn", @@ -12595,6 +14128,57 @@ } } }, + "CreateApprovalPolicyRequest":{ + "type":"structure", + "required":[ + "PolicyId", + "Name", + "Actions", + "AssetTypes", + "ApplicableTo", + "ApprovalGroups" + ], + "members":{ + "PolicyId":{ + "shape":"PolicyId", + "documentation":"

    The unique identifier to assign to the approval policy. You cannot change this value after you create the policy.

    " + }, + "Name":{ + "shape":"PolicyName", + "documentation":"

    The name of the approval policy.

    " + }, + "Description":{ + "shape":"PolicyDescription", + "documentation":"

    A description of the approval policy.

    " + }, + "Actions":{ + "shape":"GovernedActionList", + "documentation":"

    The list of governed actions that trigger the approval workflow.

    " + }, + "AssetTypes":{ + "shape":"AssetTypeList", + "documentation":"

    The list of asset types that the approval policy applies to.

    " + }, + "ApplicableTo":{ + "shape":"ApplicableTo", + "documentation":"

    The scoping configuration that determines who the approval policy applies to.

    " + }, + "ApprovalGroups":{ + "shape":"ApprovalGroupList", + "documentation":"

    The list of group ARNs whose members can approve requests.

    " + } + } + }, + "CreateApprovalPolicyResponse":{ + "type":"structure", + "required":["Policy"], + "members":{ + "Policy":{ + "shape":"ApprovalPolicy", + "documentation":"

    The approval policy that was created.

    " + } + } + }, "CreateBrandRequest":{ "type":"structure", "required":[ @@ -12681,6 +14265,10 @@ "shape":"Capabilities", "documentation":"

    A set of actions to include in the custom permissions profile.

    " }, + "Governance":{ + "shape":"Governance", + "documentation":"

    The governance configuration for the custom permissions profile. When governance controls are defined for a category, any capabilities in that category not explicitly set to ALLOW in Capabilities are denied. Even newly added capabilities in the category are implicitly disabled when Amazon Quick releases them.

    " + }, "Tags":{ "shape":"TagList", "documentation":"

    The tags to associate with the custom permissions profile.

    " @@ -12738,7 +14326,7 @@ }, "SourceEntity":{ "shape":"DashboardSourceEntity", - "documentation":"

    The entity that you are using as a source when you create the dashboard. In SourceEntity, you specify the type of object you're using as source. You can only create a dashboard from a template, so you use a SourceTemplate entity. If you need to create a dashboard from an analysis, first convert the analysis to a template by using the CreateTemplate API operation. For SourceTemplate, specify the Amazon Resource Name (ARN) of the source template. The SourceTemplateARN can contain any Amazon Web Services account and any Amazon Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " + "documentation":"

    The entity that you are using as a source when you create the dashboard. In SourceEntity, you specify the type of object you're using as source. You can only create a dashboard from a template, so you use a SourceTemplate entity. If you need to create a dashboard from an analysis, first convert the analysis to a template by using the CreateTemplate API operation. For SourceTemplate, specify the Amazon Resource Name (ARN) of the source template. The SourceTemplateARN can contain any Amazon Web Services account and any Amazon Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder. Use the TopicReferences entity to list the replacement topics for the topic placeholders listed in the original. The schema in each topic must match its placeholder.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " }, "Tags":{ "shape":"TagList", @@ -13021,6 +14609,77 @@ } } }, + "CreateDlpSettingRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "DlpSettingId", + "Name", + "ProviderType", + "ProviderConfig", + "ProviderOutageAction", + "Enabled" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account in which to create the DLP setting.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    A unique identifier for the DLP setting.

    ", + "location":"uri", + "locationName":"DlpSettingId" + }, + "Name":{ + "shape":"DlpSettingName", + "documentation":"

    A human-readable display name for the DLP setting.

    " + }, + "ProviderType":{ + "shape":"DlpProviderType", + "documentation":"

    The type of external DLP provider to use for sensitivity label classification. Currently, the only supported value is MICROSOFT_PURVIEW.

    " + }, + "ProviderConfig":{ + "shape":"ProviderConfig", + "documentation":"

    The provider-specific configuration for the DLP integration. This is a union type structure. For this structure to be valid, only one of the attributes can be defined.

    " + }, + "ProviderOutageAction":{ + "shape":"DlpAction", + "documentation":"

    The behavior to apply when the DLP provider is unreachable. Valid values are ALLOW, WARN, and BLOCK.

    " + }, + "Enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether DLP enforcement is active for this setting. Set to true to enable enforcement, or false to disable it at time of setting creation.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of resource tags to apply to the DLP setting. You can use tags to manage access to your Amazon Web Services resources.

    " + } + } + }, + "CreateDlpSettingResponse":{ + "type":"structure", + "required":[ + "Arn", + "DlpSettingId" + ], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the created DLP setting.

    " + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the created DLP setting.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "CreateFlowRequest":{ "type":"structure", "required":[ @@ -13442,6 +15101,151 @@ } } }, + "CreateKnowledgeBaseRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "KnowledgeBaseId", + "Name", + "DataSourceArn", + "KnowledgeBaseConfiguration" + ], + "members":{ + "AwsAccountId":{ + "shape":"KbAwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the knowledge base.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "KnowledgeBaseId":{ + "shape":"KnowledgeBaseId", + "documentation":"

    The unique identifier for the knowledge base.

    " + }, + "Name":{ + "shape":"KnowledgeBaseName", + "documentation":"

    The name of the knowledge base.

    " + }, + "DataSourceArn":{ + "shape":"DataSourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the data source for the knowledge base.

    " + }, + "KnowledgeBaseConfiguration":{"shape":"KnowledgeBaseConfiguration"}, + "Description":{ + "shape":"KnowledgeBaseDescription", + "documentation":"

    A description for the knowledge base. If you don't specify a description, the knowledge base is created without one.

    " + }, + "Permissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    A list of resource permissions on the knowledge base. Each entry grants a specified Amazon QuickSight principal either owner or viewer access. If you don't specify permissions, only the primary owner (if provided) receives owner access.

    " + }, + "MediaExtractionConfiguration":{"shape":"MediaExtractionConfiguration"}, + "AccessControlConfiguration":{ + "shape":"AccessControlConfiguration", + "documentation":"

    The access control configuration for the knowledge base. If you don't specify this parameter, document-level ACLs are disabled.

    " + }, + "PrimaryOwnerArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon QuickSight user or group to set as the primary owner of the knowledge base. The specified principal is always granted owner access, regardless of what is specified in the Permissions field.

    This must be an Amazon QuickSight principal ARN, not an IAM user or role ARN. The API caller is never assigned as the owner automatically. If you don't specify a primary owner and don't grant owner access in Permissions, the knowledge base is created without an owner, even when you call the operation as an Amazon QuickSight user.

    When you call CreateKnowledgeBase as an IAM user or an assumed IAM role, specify PrimaryOwnerArn (as an Amazon QuickSight principal ARN) or an owner entry in Permissions so that the knowledge base has an owner. Although optional, specifying a primary owner is recommended.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    The tags to assign to the knowledge base. If you don't specify tags, the knowledge base is created without tags.

    " + } + } + }, + "CreateKnowledgeBaseResponse":{ + "type":"structure", + "required":[ + "KnowledgeBaseArn", + "KnowledgeBaseId", + "CreationStatus" + ], + "members":{ + "KnowledgeBaseArn":{ + "shape":"KnowledgeBaseArn", + "documentation":"

    The Amazon Resource Name (ARN) of the knowledge base.

    " + }, + "KnowledgeBaseId":{ + "shape":"KnowledgeBaseId", + "documentation":"

    The unique identifier for the knowledge base.

    " + }, + "CreationStatus":{ + "shape":"DataSetStatus", + "documentation":"

    The creation status of the knowledge base.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "box":true, + "location":"statusCode" + } + } + }, + "CreateLimitsProfileRequest":{ + "type":"structure", + "required":[ + "accountId", + "profileName", + "resourceLimits", + "clientToken" + ], + "members":{ + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profile.

    ", + "location":"uri", + "locationName":"accountId" + }, + "profileName":{ + "shape":"ProfileName", + "documentation":"

    A display name for the limits profile.

    " + }, + "description":{ + "shape":"ProfileDescription", + "documentation":"

    A description for the limits profile.

    " + }, + "resourceLimits":{ + "shape":"CreateLimitsProfileRequestResourceLimitsMap", + "documentation":"

    A map of resource types to their limit values for this profile.

    " + }, + "clientToken":{ + "shape":"CreateLimitsProfileRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier to ensure that the operation completes no more than one time. If this token matches a previous request, the service ignores the request, but does not return an error.

    " + } + } + }, + "CreateLimitsProfileRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1 + }, + "CreateLimitsProfileRequestResourceLimitsMap":{ + "type":"map", + "key":{"shape":"ResourceType"}, + "value":{"shape":"ProfileLimitValue"}, + "min":1 + }, + "CreateLimitsProfileResponse":{ + "type":"structure", + "required":[ + "arn", + "profileId" + ], + "members":{ + "arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the created limits profile.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique identifier for the created limits profile.

    " + } + } + }, "CreateNamespaceRequest":{ "type":"structure", "required":[ @@ -13814,7 +15618,7 @@ }, "SourceEntity":{ "shape":"TemplateSourceEntity", - "documentation":"

    The entity that you are using as a source when you create the template. In SourceEntity, you specify the type of object you're using as source: SourceTemplate for a template or SourceAnalysis for an analysis. Both of these require an Amazon Resource Name (ARN). For SourceTemplate, specify the ARN of the source template. For SourceAnalysis, specify the ARN of the source analysis. The SourceTemplate ARN can contain any Amazon Web Services account and any Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate or SourceAnalysis to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " + "documentation":"

    The entity that you are using as a source when you create the template. In SourceEntity, you specify the type of object you're using as source: SourceTemplate for a template or SourceAnalysis for an analysis. Both of these require an Amazon Resource Name (ARN). For SourceTemplate, specify the ARN of the source template. For SourceAnalysis, specify the ARN of the source analysis. The SourceTemplate ARN can contain any Amazon Web Services account and any Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate or SourceAnalysis to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder. Use the TopicReferences entity to list the replacement topics for the topic placeholders listed in the original. The schema in each topic must match its placeholder.

    Either a SourceEntity or a Definition must be provided in order for the request to be valid.

    " }, "Tags":{ "shape":"TagList", @@ -14133,7 +15937,7 @@ "documentation":"

    The Dataset arn for the CreateTopicReviewedAnswer.

    " }, "Question":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The Question to be created.

    " }, "Mir":{ @@ -14157,6 +15961,61 @@ "max":100, "min":0 }, + "CreateTopicV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId", + "Topic" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that you want to create a topic in.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID for the topic that you want to create. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "Topic":{ + "shape":"TopicV2Details", + "documentation":"

    The definition of a topic to create.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    Contains a map of the key-value pairs for the resource tag or tags that are assigned to the topic.

    " + }, + "FolderArns":{ + "shape":"FolderArnList", + "documentation":"

    The Amazon Resource Names (ARNs) of the folders that you want the topic to reside in.

    " + }, + "CustomInstructions":{"shape":"CustomInstructions"} + } + }, + "CreateTopicV2Response":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID for the topic that you want to create. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + } + } + }, "CreateVPCConnectionRequest":{ "type":"structure", "required":[ @@ -14256,6 +16115,14 @@ }, "documentation":"

    The combination of user name and password that are used as credentials.

    " }, + "CredentialStatus":{ + "type":"string", + "enum":[ + "CONNECTED", + "AUTH_FAILED", + "NOT_VERIFIED" + ] + }, "CrossDatasetTypes":{ "type":"string", "enum":[ @@ -14441,10 +16308,7 @@ }, "CustomContentVisual":{ "type":"structure", - "required":[ - "VisualId", - "DataSetIdentifier" - ], + "required":["VisualId"], "members":{ "VisualId":{ "shape":"ShortRestrictiveResourceId", @@ -14468,7 +16332,11 @@ }, "DataSetIdentifier":{ "shape":"DataSetIdentifier", - "documentation":"

    The dataset that is used to create the custom content visual. You can't create a visual without a dataset.

    " + "documentation":"

    The dataset that is used to create the custom content visual. You can't create a visual without a dataset or a topic.

    " + }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that is used in the custom content visual. You can't create a visual without a dataset or a topic.

    " }, "VisualContentAltText":{ "shape":"LongPlainText", @@ -14617,6 +16485,10 @@ "Capabilities":{ "shape":"Capabilities", "documentation":"

    A set of actions in the custom permissions profile.

    " + }, + "Governance":{ + "shape":"Governance", + "documentation":"

    The governance configuration for the custom permissions profile. When you enable governance for a category, Amazon Quick denies access to any current or new capability in that category unless you explicitly set that capability to ALLOW in Capabilities.

    " } }, "documentation":"

    The custom permissions profile.

    " @@ -15042,6 +16914,10 @@ "shape":"DataSetReferenceList", "documentation":"

    Dataset references.

    " }, + "TopicReferences":{ + "shape":"TopicReferenceList", + "documentation":"

    The topic references for the source template of a dashboard.

    " + }, "Arn":{ "shape":"Arn", "documentation":"

    The Amazon Resource Name (ARN) of the resource.

    " @@ -15124,7 +17000,11 @@ }, "DataSetArns":{ "shape":"DataSetArnsList", - "documentation":"

    The Amazon Resource Numbers (ARNs) for the datasets that are associated with this version of the dashboard.

    " + "documentation":"

    The Amazon Resource Names (ARNs) for the datasets that are associated with this version of the dashboard.

    " + }, + "TopicArns":{ + "shape":"TopicArnsList", + "documentation":"

    The Amazon Resource Names (ARNs) for the topics that are associated with this version of the dashboard.

    " }, "Description":{ "shape":"VersionDescription", @@ -15149,6 +17029,10 @@ "shape":"DataSetIdentifierDeclarationList", "documentation":"

    An array of dataset identifier declarations. With this mapping,you can use dataset identifiers instead of dataset Amazon Resource Names (ARNs) throughout the dashboard's sub-structures.

    " }, + "TopicIdentifierDeclarations":{ + "shape":"TopicIdentifierDeclarationList", + "documentation":"

    An array of topic identifier declarations. With this mapping, you can use topic identifiers instead of topic Amazon Resource Names (ARNs) throughout the dashboard's sub-structures.

    " + }, "Sheets":{ "shape":"SheetDefinitionList", "documentation":"

    An array of sheet definitions for a dashboard.

    " @@ -16013,7 +17897,7 @@ "DataSetIdentifier":{ "type":"string", "max":2048, - "min":1 + "min":0 }, "DataSetIdentifierDeclaration":{ "type":"structure", @@ -16037,7 +17921,7 @@ "type":"list", "member":{"shape":"DataSetIdentifierDeclaration"}, "max":50, - "min":1 + "min":0 }, "DataSetImportMode":{ "type":"string", @@ -16151,7 +18035,7 @@ "DataSetReferenceList":{ "type":"list", "member":{"shape":"DataSetReference"}, - "min":1 + "min":0 }, "DataSetRefreshProperties":{ "type":"structure", @@ -16474,6 +18358,14 @@ "SecretArn":{ "shape":"SecretArn", "documentation":"

    The Amazon Resource Name (ARN) of the secret associated with the data source in Amazon Secrets Manager.

    " + }, + "CredentialStatus":{ + "shape":"CredentialStatus", + "documentation":"

    The credential verification status of the data source. Valid values include:

    • CONNECTED – Credential validation succeeded.

    • AUTH_FAILED – Credential validation failed.

    • NOT_VERIFIED – Credential validation has not been performed.

    " + }, + "LastCredentialVerifiedAt":{ + "shape":"Timestamp", + "documentation":"

    The time that the credentials were last verified.

    " } }, "documentation":"

    The structure of a data source.

    " @@ -16689,6 +18581,22 @@ "QBusinessParameters":{ "shape":"QBusinessParameters", "documentation":"

    The parameters for Amazon Q Business.

    " + }, + "SharePointParameters":{ + "shape":"SharePointParameters", + "documentation":"

    The parameters for a SharePoint data source.

    " + }, + "GoogleDriveParameters":{ + "shape":"GoogleDriveParameters", + "documentation":"

    The parameters for a Google Drive data source.

    " + }, + "OneDriveParameters":{ + "shape":"OneDriveParameters", + "documentation":"

    The parameters for an OneDrive data source.

    " + }, + "FMKBParameters":{ + "shape":"FMKBParameters", + "documentation":"

    The parameters for a fully managed knowledge base data source.

    " } }, "documentation":"

    The parameters that Quick Sight uses to connect to your underlying data source. This is a variant type structure. For this structure to be valid, only one of the attributes can be non-null.

    " @@ -17512,6 +19420,17 @@ "VARP" ] }, + "DefaultCategoryEffect":{ + "type":"string", + "documentation":"

    The default effect that Amazon Quick applies to capabilities in a governed category when you do not explicitly list those capabilities in Capabilities. Valid values:

    • DENY_BY_DEFAULT – Amazon Quick denies any capability access in the given category that the profile does not explicitly set to ALLOW.

    ", + "enum":["DENY_BY_DEFAULT"] + }, + "DefaultCategoryEffectsMap":{ + "type":"map", + "key":{"shape":"GovernanceCategoryName"}, + "value":{"shape":"DefaultCategoryEffect"}, + "max":50 + }, "DefaultDateTimePickerControlOptions":{ "type":"structure", "members":{ @@ -18004,6 +19923,52 @@ } } }, + "DeleteAppRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "AppId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the app.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app that you want to delete.

    ", + "location":"uri", + "locationName":"AppId" + } + } + }, + "DeleteAppResponse":{ + "type":"structure", + "members":{ + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, + "DeleteApprovalPolicyRequest":{ + "type":"structure", + "required":["PolicyId"], + "members":{ + "PolicyId":{ + "shape":"PolicyId", + "documentation":"

    The unique identifier of the approval policy to delete.

    ", + "location":"uri", + "locationName":"PolicyId" + } + } + }, + "DeleteApprovalPolicyResponse":{ + "type":"structure", + "members":{} + }, "DeleteBrandAssignmentRequest":{ "type":"structure", "required":["AwsAccountId"], @@ -18295,6 +20260,48 @@ } } }, + "DeleteDlpSettingRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "DlpSettingId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the DLP setting that you want to delete.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the DLP setting that you want to delete.

    ", + "location":"uri", + "locationName":"DlpSettingId" + } + } + }, + "DeleteDlpSettingResponse":{ + "type":"structure", + "required":[ + "Arn", + "DlpSettingId" + ], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the deleted DLP setting.

    " + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the deleted DLP setting.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "DeleteFlowRequest":{ "type":"structure", "required":[ @@ -18641,6 +20648,37 @@ } } }, + "DeleteLimitsProfileRequest":{ + "type":"structure", + "required":[ + "profileId", + "accountId" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique identifier for the limits profile to delete.

    ", + "location":"uri", + "locationName":"profileId" + }, + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profile.

    ", + "location":"uri", + "locationName":"accountId" + } + } + }, + "DeleteLimitsProfileResponse":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the deleted limits profile.

    " + } + } + }, "DeleteNamespaceRequest":{ "type":"structure", "required":[ @@ -19201,6 +21239,49 @@ } } }, + "DeleteTopicV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want to delete.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to delete. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    ", + "location":"uri", + "locationName":"TopicId" + } + } + }, + "DeleteTopicV2Response":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to delete. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + } + } + }, "DeleteUserByPrincipalIdRequest":{ "type":"structure", "required":[ @@ -19841,6 +21922,105 @@ } } }, + "DescribeAppPermissionsRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "AppId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the app.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app.

    ", + "location":"uri", + "locationName":"AppId" + } + } + }, + "DescribeAppPermissionsResponse":{ + "type":"structure", + "members":{ + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app.

    " + }, + "Arn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the app.

    " + }, + "Permissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    The resource permissions for the app.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, + "DescribeAppRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "AppId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the app.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app that you want to describe.

    ", + "location":"uri", + "locationName":"AppId" + } + } + }, + "DescribeAppResponse":{ + "type":"structure", + "required":["App"], + "members":{ + "App":{ + "shape":"AppSummary", + "documentation":"

    The information about the app.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, + "DescribeApprovalPolicyRequest":{ + "type":"structure", + "required":["PolicyId"], + "members":{ + "PolicyId":{ + "shape":"PolicyId", + "documentation":"

    The unique identifier of the approval policy to describe.

    ", + "location":"uri", + "locationName":"PolicyId" + } + } + }, + "DescribeApprovalPolicyResponse":{ + "type":"structure", + "required":["Policy"], + "members":{ + "Policy":{ + "shape":"ApprovalPolicy", + "documentation":"

    The approval policy.

    " + } + } + }, "DescribeAssetBundleExportJobRequest":{ "type":"structure", "required":[ @@ -20865,6 +23045,41 @@ } } }, + "DescribeDlpSettingRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "DlpSettingId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the DLP setting that you want to describe.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the DLP setting that you want to describe.

    ", + "location":"uri", + "locationName":"DlpSettingId" + } + } + }, + "DescribeDlpSettingResponse":{ + "type":"structure", + "required":["DlpSetting"], + "members":{ + "DlpSetting":{ + "shape":"DlpSettingDetails", + "documentation":"

    The full configuration of the requested DLP setting, returned as a DlpSettingDetails object.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "DescribeFlowRequest":{ "type":"structure", "required":[ @@ -21461,6 +23676,37 @@ } } }, + "DescribeLimitsProfileRequest":{ + "type":"structure", + "required":[ + "profileId", + "accountId" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique identifier for the limits profile.

    ", + "location":"uri", + "locationName":"profileId" + }, + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profile.

    ", + "location":"uri", + "locationName":"accountId" + } + } + }, + "DescribeLimitsProfileResponse":{ + "type":"structure", + "required":["profile"], + "members":{ + "profile":{ + "shape":"LimitsProfile", + "documentation":"

    The details of the requested limits profile, including its name, description, resource limits, and metadata.

    " + } + } + }, "DescribeNamespaceRequest":{ "type":"structure", "required":[ @@ -22238,6 +24484,53 @@ } } }, + "DescribeTopicPermissionsV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want described.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to describe. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    ", + "location":"uri", + "locationName":"TopicId" + } + } + }, + "DescribeTopicPermissionsV2Response":{ + "type":"structure", + "members":{ + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to describe. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "TopicArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "Permissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    A list of resource permissions that are configured to the topic.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "DescribeTopicRefreshRequest":{ "type":"structure", "required":[ @@ -22393,6 +24686,54 @@ } } }, + "DescribeTopicV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want to describe.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to describe. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    ", + "location":"uri", + "locationName":"TopicId" + } + } + }, + "DescribeTopicV2Response":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to describe. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "Topic":{ + "shape":"TopicV2Details", + "documentation":"

    The definition of a topic.

    " + }, + "CustomInstructions":{"shape":"CustomInstructions"}, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "DescribeUserRequest":{ "type":"structure", "required":[ @@ -22483,6 +24824,12 @@ "min":1, "pattern":"[ -ÿ]+" }, + "DescriptionSensitiveString":{ + "type":"string", + "max":500, + "min":0, + "sensitive":true + }, "DestinationParameterValueConfiguration":{ "type":"structure", "members":{ @@ -22642,6 +24989,139 @@ }, "documentation":"

    A structure that represents additional options for display formatting.

    " }, + "DlpAction":{ + "type":"string", + "enum":[ + "ALLOW", + "WARN", + "BLOCK" + ] + }, + "DlpProviderType":{ + "type":"string", + "enum":["MICROSOFT_PURVIEW"] + }, + "DlpSettingDetails":{ + "type":"structure", + "required":[ + "DlpSettingId", + "Name", + "Arn", + "Status", + "ProviderType", + "ProviderConfig", + "ProviderOutageAction", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the DLP setting.

    " + }, + "Name":{ + "shape":"DlpSettingName", + "documentation":"

    The display name of the DLP setting.

    " + }, + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the DLP setting.

    " + }, + "Status":{ + "shape":"DlpSettingStatus", + "documentation":"

    The status of the DLP setting. Valid values are ACTIVE and INACTIVE.

    " + }, + "ProviderType":{ + "shape":"DlpProviderType", + "documentation":"

    The type of external DLP provider used for sensitivity label classification.

    " + }, + "ProviderConfig":{ + "shape":"ProviderConfig", + "documentation":"

    The provider-specific configuration for the DLP integration.

    " + }, + "ProviderOutageAction":{ + "shape":"DlpAction", + "documentation":"

    The behavior applied when the DLP provider is unreachable. Valid values are ALLOW, WARN, and BLOCK.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the DLP setting was created, in ISO 8601 format.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the DLP setting was most recently updated, in ISO 8601 format.

    " + } + }, + "documentation":"

    The full configuration details of a DLP setting.

    " + }, + "DlpSettingId":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[a-zA-Z0-9\\-_]+" + }, + "DlpSettingName":{ + "type":"string", + "max":255, + "min":1, + "pattern":"[A-Za-z0-9](?:[\\w- &]*[A-Za-z0-9])?" + }, + "DlpSettingStatus":{ + "type":"string", + "enum":[ + "ACTIVE", + "INACTIVE" + ] + }, + "DlpSettingSummary":{ + "type":"structure", + "required":[ + "DlpSettingId", + "Name", + "Arn", + "Status", + "ProviderType", + "CreatedAt", + "UpdatedAt" + ], + "members":{ + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the DLP setting.

    " + }, + "Name":{ + "shape":"DlpSettingName", + "documentation":"

    The display name of the DLP setting.

    " + }, + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the DLP setting.

    " + }, + "Status":{ + "shape":"DlpSettingStatus", + "documentation":"

    The status of the DLP setting. Valid values are ACTIVE and INACTIVE.

    " + }, + "ProviderType":{ + "shape":"DlpProviderType", + "documentation":"

    The type of external DLP provider used for sensitivity label classification.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the DLP setting was created, in ISO 8601 format.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the DLP setting was most recently updated, in ISO 8601 format.

    " + } + }, + "documentation":"

    A summary of a DLP setting returned by list operations.

    " + }, + "DlpSettingSummaryList":{ + "type":"list", + "member":{"shape":"DlpSettingSummary"}, + "max":10, + "min":0 + }, "DnsResolverList":{ "type":"list", "member":{"shape":"IPv4Address"}, @@ -22758,6 +25238,48 @@ "ENTERPRISE_AND_Q" ] }, + "EffectiveLimit":{ + "type":"structure", + "required":[ + "resourceType", + "limitValue", + "limitUnit", + "source", + "profileId" + ], + "members":{ + "resourceType":{ + "shape":"ResourceType", + "documentation":"

    The type of resource that the limit applies to.

    " + }, + "limitValue":{ + "shape":"EffectiveLimitLimitValueLong", + "documentation":"

    The maximum allowed value for the resource.

    " + }, + "limitUnit":{ + "shape":"LimitUnit", + "documentation":"

    The unit of measurement for the limit.

    " + }, + "source":{ + "shape":"LimitSource", + "documentation":"

    The source from which this limit was inherited. Possible values:

    • DIRECT_USER – The limit comes from a profile directly assigned to the user.

    • GROUP – The limit comes from a profile assigned to a group the user belongs to.

    • ROLE – The limit comes from a profile assigned to a role the user has.

    • ACCOUNT – The limit comes from the account-level default profile.

    • SYSTEM_DEFAULT – The limit comes from the built-in system default.

    " + }, + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The identifier of the limits profile that defines this limit.

    " + } + }, + "documentation":"

    The effective limit for a resource type that applies to a user, considering all applicable profile assignments and inheritance rules.

    " + }, + "EffectiveLimitLimitValueLong":{ + "type":"long", + "box":true, + "min":0 + }, + "EffectiveLimitList":{ + "type":"list", + "member":{"shape":"EffectiveLimit"} + }, "ElementValue":{ "type":"string", "max":1024 @@ -22781,10 +25303,7 @@ }, "EmptyVisual":{ "type":"structure", - "required":[ - "VisualId", - "DataSetIdentifier" - ], + "required":["VisualId"], "members":{ "VisualId":{ "shape":"ShortRestrictiveResourceId", @@ -22792,7 +25311,11 @@ }, "DataSetIdentifier":{ "shape":"DataSetIdentifier", - "documentation":"

    The data set that is used in the empty visual. Every visual requires a dataset to render.

    " + "documentation":"

    The data set that is used in the empty visual. Every visual requires a dataset or a topic to render.

    " + }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that is used in the empty visual. Every visual requires a dataset or a topic to render.

    " }, "Actions":{ "shape":"VisualCustomActionList", @@ -22991,6 +25514,27 @@ "min":1, "sensitive":true }, + "FMKBKnowledgeBaseArn":{ + "type":"string", + "max":128, + "min":47, + "pattern":"^arn:aws(-cn|-us-gov)?:bedrock:[a-zA-Z0-9-]*:[0-9]{12}:knowledge-base/[0-9a-zA-Z]+" + }, + "FMKBParameters":{ + "type":"structure", + "required":["KnowledgeBaseArn"], + "members":{ + "KnowledgeBaseArn":{ + "shape":"FMKBKnowledgeBaseArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Amazon Bedrock knowledge base.

    " + }, + "LinkedDataSourceIds":{ + "shape":"LinkedDataSourceIds", + "documentation":"

    The IDs of the linked data sources.

    " + } + }, + "documentation":"

    The connection parameters for a fully managed knowledge base data source. Provide these parameters in the DataSourceParameters object when you create or update a data source that uses a fully managed knowledge base.

    " + }, "FailedKeyRegistrationEntries":{ "type":"list", "member":{"shape":"FailedKeyRegistrationEntry"} @@ -23534,7 +26078,8 @@ "enum":[ "ENFORCED_VALUE_FILTER", "CONDITIONAL_VALUE_FILTER", - "NAMED_VALUE_FILTER" + "NAMED_VALUE_FILTER", + "DASHBOARD_DEFAULT_FILTER" ] }, "FilterControl":{ @@ -26499,6 +29044,42 @@ }, "documentation":"

    Determines the border options for a table visual.

    " }, + "GoogleDriveParameters":{ + "type":"structure", + "members":{ + "AuthType":{ + "shape":"AuthType", + "documentation":"

    The authentication type for the Google Drive data source. Valid values include:

    • SERVICE_ACCOUNT – Server-to-server authentication using a Google service account key.

    • THREE_LEGGED_OAUTH – Interactive OAuth that requires user consent.

    " + } + }, + "documentation":"

    The connection parameters for a Google Drive data source. Provide these parameters in the DataSourceParameters object when you create or update a data source that uses Google Drive.

    " + }, + "Governance":{ + "type":"structure", + "members":{ + "DefaultCategoryEffects":{ + "shape":"DefaultCategoryEffectsMap", + "documentation":"

    A map of DefaultCategoryEffects.

    " + } + }, + "documentation":"

    Contains the governance configuration for a custom permissions profile. When governance controls are defined for a category, any capabilities in that category not explicitly set to ALLOW in Capabilities are denied. Even newly added capabilities in the category are implicitly disabled when Amazon Quick releases them.

    " + }, + "GovernanceCategoryName":{ + "type":"string", + "documentation":"

    The name of a governance category. A governance category groups related capabilities so that you can apply a default effect to all capabilities in the category at once. Valid values:

    • AI – Capabilities related to Amazon Quick AI features.

    ", + "max":128, + "min":1 + }, + "GovernedAction":{ + "type":"string", + "enum":["SHARE"] + }, + "GovernedActionList":{ + "type":"list", + "member":{"shape":"GovernedAction"}, + "max":10, + "min":1 + }, "GradientColor":{ "type":"structure", "members":{ @@ -26708,6 +29289,11 @@ }, "documentation":"

    A group in Quick Sight consists of a set of users. You can use groups to make it easier to manage access and security.

    " }, + "GroupArnList":{ + "type":"list", + "member":{"shape":"Arn"}, + "min":1 + }, "GroupByColumnNameList":{ "type":"list", "member":{"shape":"ColumnName"}, @@ -27862,10 +30448,7 @@ }, "InsightVisual":{ "type":"structure", - "required":[ - "VisualId", - "DataSetIdentifier" - ], + "required":["VisualId"], "members":{ "VisualId":{ "shape":"ShortRestrictiveResourceId", @@ -27891,6 +30474,10 @@ "shape":"DataSetIdentifier", "documentation":"

    The dataset that is used in the insight visual.

    " }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that is used in the insight visual.

    " + }, "VisualContentAltText":{ "shape":"LongPlainText", "documentation":"

    The alt text for the visual.

    " @@ -28619,10 +31206,10 @@ "members":{ "template":{ "shape":"KbTemplate", - "documentation":"

    The template document that defines the knowledge base behavior.

    " + "documentation":"

    The connector configuration for the knowledge base data source. The structure depends on the connector type of the data source referenced by DataSourceArn.

    The template must be a JSON object. All connector types share the following top-level keys. The value of type and the contents of connectionConfiguration vary by connector type.

    • type – (Required) The connector type of the data source. This value identifies the connector. Valid values: S3V2, WEBCRAWLERV3, GOOGLEDRIVEV3, ONEDRIVEV3, SHAREPOINTV3. For the fields required by each connector, see the connector-specific list that follows.

    • connectionConfiguration – (Required) The connection details for the data source. The keys in this object vary by connector type; see the connector-specific list that follows.

    • filterConfiguration – (Optional) Rules that determine which content is crawled, such as inclusion and exclusion prefixes, patterns, or file-size limits.

    • accessControlConfiguration – (Optional) Document-level access control (ACL) settings. Supported by all connector types except Web Crawler (WEBCRAWLERV3). The available fields depend on the connector type.

    • deletionProtectionConfiguration – (Optional) Deletion-protection settings, supported by all connector types. Contains enableDeletionProtection (Boolean) and deletionProtectionThreshold (String; a value from 1 to 100).

    The following list describes the valid type value, the connectionConfiguration contents, and any connector-specific fields for each connector type:

    • Amazon S3 (type: S3V2) – The type value must be S3V2. connectionConfiguration is required and contains:

      • bucketName – (Required) The name of the Amazon S3 bucket to crawl. Type: String. Length: 3–63 characters. Pattern: ^[a-z0-9][.\\-a-z0-9]{1,61}[a-z0-9]$.

      • bucketOwnerAccountId – (Required) The ID of the AWS account that owns the bucket. Type: String. Pattern: ^\\d{12}$.

      Amazon S3 supports the following optional filterConfiguration fields:

      • inclusionPrefixes or exclusionPrefixes – Amazon S3 key prefixes to include or exclude. Type: Array of String. Up to 350 items, each 1–1,024 characters.

      • inclusionPatterns or exclusionPatterns – Patterns to include or exclude objects. Type: Array of String. Up to 350 items, each 1–1,024 characters.

      • maxFileSizeInMegaBytes – The maximum size, in MB, of a file to ingest. Type: String. Pattern: ^\\d+$.

      For Amazon S3, accessControlConfiguration supports the following fields:

      • crawlAcl – Specifies whether the connector crawls and enforces document access control lists (ACLs). Type: Boolean. When set to true, provide ACLs either in a global ACL configuration file (aclConfigurationFilePath) or in per-document metadata files.

      • aclConfigurationFilePath – The Amazon S3 URI of the global ACL configuration file. Type: String. Length: 1–1,024 characters. Optional. If you don't provide a global ACL configuration file, define ACLs in per-document metadata files.

      • defaultAccessType – The access behavior applied to Amazon S3 prefixes that are not listed in the ACL configuration. Type: String. The only supported value is ALLOW.

      metadataFilesPrefix – (Optional) The Amazon S3 prefix under which per-document metadata files are stored. Each metadata file describes a single source document and its indexable attributes. This is not the global ACL configuration file. For a single global ACL file, use accessControlConfiguration.aclConfigurationFilePath. Type: String. Length: 1–1,024 characters.

    • Google Drive (type: GOOGLEDRIVEV3) – Requires connectionConfiguration with authType set to SERVICE_ACCOUNT. Supports dataEntityConfiguration with crawlMyDrive, crawlSharedWithMe, and crawlSharedDrives.

    • OneDrive (type: ONEDRIVEV3) – Requires authType at the template root level set to TWO_LEGGED_OAUTH. Requires connectionConfiguration with tenantId in UUID format. Supports dataEntityConfiguration with crawlPersonalDrives and crawlSharedWithMe.

    • SharePoint (type: SHAREPOINTV3) – Requires connectionConfiguration with tenantId in UUID format. Supports dataEntityConfiguration with siteUrls, crawlFiles, and crawlPages.

    • Web Crawler (type: WEBCRAWLERV3) – Requires connectionConfiguration with seedUrls or siteMapUrls (mutually exclusive) and authType. Supports crawlConfiguration for crawl depth, rate limits, and scope. Supports filterConfiguration for file size limits and URL patterns. Valid values for authType: NO_AUTH, BASIC_AUTH, FORM, SAML.

    Enabling document-level access control for Amazon S3

    For an Amazon S3 (S3V2) knowledge base, document-level access control is governed by two settings that must both be enabled:

    1. In this template, set accessControlConfiguration.crawlAcl to true. Define ACLs either in a global ACL configuration file, referenced by accessControlConfiguration.aclConfigurationFilePath, or in per-document metadata files. To control access for prefixes that are not listed in the ACL file, you can also set accessControlConfiguration.defaultAccessType.

    2. In the CreateKnowledgeBase or UpdateKnowledgeBase request, set the top-level AccessControlConfiguration.isACLEnabled to true.

    " } }, - "documentation":"

    The template configuration for a knowledge base.

    " + "documentation":"

    The template configuration for a knowledge base. This object contains connector-specific configuration that defines how data is crawled and indexed.

    " }, "KeyPairCredentials":{ "type":"structure", @@ -28689,6 +31276,10 @@ "shape":"MediaExtractionConfiguration", "documentation":"

    The media extraction configuration for the knowledge base.

    " }, + "AccessControlConfiguration":{ + "shape":"AccessControlConfiguration", + "documentation":"

    The access control configuration for the knowledge base.

    " + }, "Type":{ "shape":"String", "documentation":"

    The type of the knowledge base.

    " @@ -28707,7 +31298,7 @@ }, "IsEmailNotificationOptedForIngestionFailures":{ "shape":"Boolean", - "documentation":"

    Indicates whether email notifications are enabled for ingestion failures.

    ", + "documentation":"

    Specifies whether email notifications are enabled for ingestion failures.

    ", "box":true }, "FirstCompletedIngestionSummary":{ @@ -28754,12 +31345,7 @@ "members":{ "templateConfiguration":{ "shape":"KbTemplateConfiguration", - "documentation":"

    The template configuration for the knowledge base.

    " - }, - "eventEnabled":{ - "shape":"Boolean", - "documentation":"

    Indicates whether event notifications are enabled for the knowledge base.

    ", - "box":true + "documentation":"

    The template configuration that defines how the data source connector crawls and indexes data for the knowledge base. The template structure varies by connector type. See KbTemplateConfiguration for connector-specific details.

    " } }, "documentation":"

    The configuration settings for a knowledge base.

    ", @@ -28834,6 +31420,7 @@ }, "KnowledgeBaseSearchFilterName":{ "type":"string", + "documentation":"

    The name of a field that you can use to filter knowledge base search results. Valid values include:

    • DATASOURCE_ARN – The Amazon Resource Name (ARN) of the associated data source.

    • DIRECT_QUICKSIGHT_OWNER – An Amazon QuickSight user or group with direct owner permissions.

    • DIRECT_QUICKSIGHT_SOLE_OWNER – An Amazon QuickSight user or group that is the sole direct owner.

    • DIRECT_QUICKSIGHT_VIEWER_OR_OWNER – An Amazon QuickSight user or group with direct viewer or owner permissions.

    • KNOWLEDGE_BASE_ID – The unique identifier of the knowledge base.

    • KNOWLEDGE_BASE_NAME – The display name of the knowledge base.

    • KNOWLEDGE_BASE_SIZE_BYTES – The size of the knowledge base in bytes.

    • PRIMARY_OWNER – The Amazon Resource Name (ARN) of the primary owner of the knowledge base.

    ", "enum":[ "KNOWLEDGE_BASE_ID", "KNOWLEDGE_BASE_NAME", @@ -28841,13 +31428,14 @@ "DIRECT_QUICKSIGHT_VIEWER_OR_OWNER", "DIRECT_QUICKSIGHT_SOLE_OWNER", "KNOWLEDGE_BASE_SIZE_BYTES", - "PRIMARY_OWNER" + "PRIMARY_OWNER", + "DATASOURCE_ARN" ] }, "KnowledgeBaseSearchFilters":{ "type":"list", "member":{"shape":"KnowledgeBaseSearchFilter"}, - "max":5, + "max":6, "min":1 }, "KnowledgeBaseSearchOperator":{ @@ -28951,6 +31539,45 @@ }, "documentation":"

    A summary of a knowledge base, including its identifier, name, status, and metadata.

    " }, + "LabelActionMapping":{ + "type":"structure", + "required":[ + "LabelId", + "LabelName", + "Action" + ], + "members":{ + "LabelId":{ + "shape":"LabelId", + "documentation":"

    The identifier of the sensitivity label from the DLP provider.

    " + }, + "LabelName":{ + "shape":"LabelName", + "documentation":"

    The display name of the sensitivity label from the DLP provider.

    " + }, + "Action":{ + "shape":"DlpAction", + "documentation":"

    The enforcement action to apply when content with this sensitivity label is detected. Valid values are ALLOW, BLOCK, and WARN.

    " + } + }, + "documentation":"

    Maps a sensitivity label from Microsoft Purview to an enforcement action.

    " + }, + "LabelActionMappingList":{ + "type":"list", + "member":{"shape":"LabelActionMapping"}, + "max":100, + "min":0 + }, + "LabelId":{ + "type":"string", + "max":512, + "min":1 + }, + "LabelName":{ + "type":"string", + "max":512, + "min":1 + }, "LabelOptions":{ "type":"structure", "members":{ @@ -29041,10 +31668,7 @@ }, "LayerMapVisual":{ "type":"structure", - "required":[ - "VisualId", - "DataSetIdentifier" - ], + "required":["VisualId"], "members":{ "VisualId":{ "shape":"ShortRestrictiveResourceId", @@ -29058,7 +31682,11 @@ }, "DataSetIdentifier":{ "shape":"DataSetIdentifier", - "documentation":"

    The dataset that is used to create the layer map visual. You can't create a visual without a dataset.

    " + "documentation":"

    The dataset that is used to create the layer map visual. You can't create a visual without a dataset or a topic.

    " + }, + "TopicIdentifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The topic that is used in the layer map visual. You can't create a visual without a dataset or a topic.

    " }, "VisualContentAltText":{ "shape":"LongPlainText", @@ -29169,10 +31797,87 @@ "error":{"httpStatusCode":409}, "exception":true }, + "LimitSource":{ + "type":"string", + "documentation":"

    The source from which an effective limit was inherited.

    ", + "enum":[ + "DIRECT_USER", + "GROUP", + "ROLE", + "ACCOUNT", + "SYSTEM_DEFAULT" + ] + }, + "LimitUnit":{ + "type":"string", + "documentation":"

    The unit of measurement for a resource limit value.

    ", + "enum":[ + "MB", + "GB", + "HOURS", + "DAYS" + ] + }, + "LimitedSensitiveString":{ + "type":"string", + "max":256, + "sensitive":true + }, "LimitedString":{ "type":"string", "max":256 }, + "LimitsProfile":{ + "type":"structure", + "required":[ + "profileId", + "arn", + "accountId", + "profileName", + "resourceLimits", + "createdAt", + "updatedAt" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique identifier for the limits profile.

    " + }, + "arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the limits profile.

    " + }, + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profile.

    " + }, + "profileName":{ + "shape":"ProfileName", + "documentation":"

    The display name of the limits profile.

    " + }, + "description":{ + "shape":"ProfileDescription", + "documentation":"

    The description of the limits profile.

    " + }, + "resourceLimits":{ + "shape":"ResourceLimitsMap", + "documentation":"

    A map of resource types to their limit values.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the limits profile was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time that the limits profile was last updated.

    " + } + }, + "documentation":"

    A limits profile that defines resource usage limits for Amazon Quick Sight users. Limits profiles can be assigned to users, groups, or roles to control resource consumption.

    " + }, + "LimitsProfileList":{ + "type":"list", + "member":{"shape":"LimitsProfile"} + }, "LineChartAggregatedFieldWells":{ "type":"structure", "members":{ @@ -29506,6 +32211,18 @@ }, "documentation":"

    A structure that contains the configuration of a shareable link to the dashboard.

    " }, + "LinkedDataSourceId":{ + "type":"string", + "max":10, + "min":1, + "pattern":"^[0-9a-zA-Z]+$" + }, + "LinkedDataSourceIds":{ + "type":"list", + "member":{"shape":"LinkedDataSourceId"}, + "max":5, + "min":0 + }, "ListActionConnectorsRequest":{ "type":"structure", "required":["AwsAccountId"], @@ -29648,6 +32365,81 @@ } } }, + "ListApprovalPoliciesRequest":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    ", + "location":"querystring", + "locationName":"next-token" + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. If you don't specify a value, the service returns a default number of results. Use the NextToken value in the response to retrieve additional results.

    ", + "box":true, + "location":"querystring", + "locationName":"max-results" + } + } + }, + "ListApprovalPoliciesResponse":{ + "type":"structure", + "required":["Policies"], + "members":{ + "Policies":{ + "shape":"ApprovalPolicyList", + "documentation":"

    The list of approval policies.

    " + }, + "NextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + } + } + }, + "ListAppsRequest":{ + "type":"structure", + "required":["AwsAccountId"], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the apps.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single request. Valid range is 1 to 100. If you don't specify a value, the default is 20.

    ", + "box":true, + "location":"querystring", + "locationName":"max-results" + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    ", + "location":"querystring", + "locationName":"next-token" + } + } + }, + "ListAppsResponse":{ + "type":"structure", + "required":["AppSummaryList"], + "members":{ + "AppSummaryList":{ + "shape":"AppSummaryList", + "documentation":"

    A list of app summaries.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "ListAssetBundleExportJobsRequest":{ "type":"structure", "required":["AwsAccountId"], @@ -30066,6 +32858,49 @@ } } }, + "ListDlpSettingsRequest":{ + "type":"structure", + "required":["AwsAccountId"], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the DLP settings that you want to list.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "NextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    ", + "location":"querystring", + "locationName":"next-token" + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return per request.

    ", + "box":true, + "location":"querystring", + "locationName":"max-results" + } + } + }, + "ListDlpSettingsResponse":{ + "type":"structure", + "required":["DlpSettingSummaries"], + "members":{ + "DlpSettingSummaries":{ + "shape":"DlpSettingSummaryList", + "documentation":"

    A list of DlpSettingSummary objects for the DLP settings in the account. The list is empty if no DLP settings have been configured.

    " + }, + "NextToken":{ + "shape":"PaginationToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "ListFlowsInput":{ "type":"structure", "required":["AwsAccountId"], @@ -30672,6 +33507,56 @@ } } }, + "ListLimitsProfilesRequest":{ + "type":"structure", + "required":["accountId"], + "members":{ + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profiles.

    ", + "location":"uri", + "locationName":"accountId" + }, + "resourceType":{ + "shape":"ResourceType", + "documentation":"

    An optional filter that limits the results to profiles that contain the specified resource type. If you don't specify a value, the operation returns all profiles.

    ", + "location":"querystring", + "locationName":"resourceType" + }, + "maxResults":{ + "shape":"ListLimitsProfilesRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return in a single call. If you don't specify a value, the service uses the default maximum.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListLimitsProfilesRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, + "ListLimitsProfilesResponse":{ + "type":"structure", + "required":["profiles"], + "members":{ + "profiles":{ + "shape":"LimitsProfileList", + "documentation":"

    A list of limits profiles.

    " + }, + "nextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + } + } + }, "ListNamespacesRequest":{ "type":"structure", "required":["AwsAccountId"], @@ -31518,6 +34403,53 @@ } } }, + "ListTopicsV2Request":{ + "type":"structure", + "required":["AwsAccountId"], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topics that you want to list.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    ", + "location":"querystring", + "locationName":"next-token" + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to be returned per request.

    ", + "box":true, + "location":"querystring", + "locationName":"max-results" + } + } + }, + "ListTopicsV2Response":{ + "type":"structure", + "members":{ + "TopicSummaryList":{ + "shape":"TopicV2Summaries", + "documentation":"

    A list of topic summaries.

    " + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + } + } + }, "ListUserGroupsRequest":{ "type":"structure", "required":[ @@ -32202,6 +35134,40 @@ }, "documentation":"

    The metric comparison computation configuration.

    " }, + "MicrosoftPurviewCredentials":{ + "type":"structure", + "required":["SecretArn"], + "members":{ + "SecretArn":{ + "shape":"SecretManagerArn", + "documentation":"

    The ARN of the Amazon Web Services Secrets Manager secret that contains the Microsoft Purview OAuth credentials. The secret includes the Azure tenant ID, client ID, and client secret or certificate.

    " + } + }, + "documentation":"

    The credentials for Microsoft Purview DLP integration. The credentials are stored in Amazon Web Services Secrets Manager and referenced by ARN.

    " + }, + "MicrosoftPurviewProviderConfig":{ + "type":"structure", + "required":[ + "Credentials", + "LabelActionMappings", + "UnmappedAction" + ], + "members":{ + "Credentials":{ + "shape":"MicrosoftPurviewCredentials", + "documentation":"

    The credentials used to authenticate with Microsoft Purview.

    " + }, + "LabelActionMappings":{ + "shape":"LabelActionMappingList", + "documentation":"

    The mappings from Microsoft Purview sensitivity labels to enforcement actions.

    " + }, + "UnmappedAction":{ + "shape":"DlpAction", + "documentation":"

    The default action to apply to content that has no sensitivity label or whose label is not mapped. Valid values are ALLOW, BLOCK, and WARN.

    " + } + }, + "documentation":"

    The full configuration for Microsoft Purview DLP integration, including the provider credentials and the label-action mappings that define the enforcement policy.

    " + }, "MinimumLabelType":{ "type":"structure", "members":{ @@ -32310,6 +35276,18 @@ "Metric":{ "shape":"NamedEntityDefinitionMetric", "documentation":"

    The definition of a metric.

    " + }, + "RankOrder":{ + "shape":"NullableInteger", + "documentation":"

    The rank order of the named entity definition.

    " + }, + "PresentationOrder":{ + "shape":"NullableInteger", + "documentation":"

    The presentation order of the named entity definition.

    " + }, + "IsHidden":{ + "shape":"NullableBoolean", + "documentation":"

    A Boolean value that indicates whether the named entity definition is hidden.

    " } }, "documentation":"

    A structure that represents a named entity.

    " @@ -32342,6 +35320,29 @@ }, "documentation":"

    The definition for a NamedEntityRef.

    " }, + "NamedEntitySort":{ + "type":"structure", + "required":[ + "FieldName", + "Direction" + ], + "members":{ + "FieldName":{ + "shape":"LimitedString", + "documentation":"

    The name of the field that is used for the sort.

    " + }, + "Direction":{ + "shape":"TopicSortDirection", + "documentation":"

    The direction of the sort. Valid values are ASCENDING and DESCENDING.

    " + } + }, + "documentation":"

    A structure that represents a sort for a named entity.

    " + }, + "NamedEntitySortList":{ + "type":"list", + "member":{"shape":"NamedEntitySort"}, + "max":1 + }, "NamedFilterAggType":{ "type":"string", "enum":[ @@ -32657,6 +35658,7 @@ "documentation":"

    The options that determine the null value format configuration.

    " }, "NullableBoolean":{"type":"boolean"}, + "NullableInteger":{"type":"integer"}, "NumberDisplayFormatConfiguration":{ "type":"structure", "members":{ @@ -33170,6 +36172,34 @@ "max":512, "min":1 }, + "OneDriveClientId":{ + "type":"string", + "max":100, + "min":1 + }, + "OneDriveParameters":{ + "type":"structure", + "members":{ + "TenantId":{ + "shape":"OneDriveTenantId", + "documentation":"

    The tenant ID for the OneDrive data source.

    " + }, + "ClientId":{ + "shape":"OneDriveClientId", + "documentation":"

    The client ID for the OneDrive data source.

    " + }, + "AuthType":{ + "shape":"AuthType", + "documentation":"

    The authentication type for the OneDrive data source. Valid values include:

    • TWO_LEGGED_OAUTH – Server-to-server authentication using client credentials that do not require user interaction.

    • THREE_LEGGED_OAUTH – Interactive OAuth that requires user consent.

    " + } + }, + "documentation":"

    The connection parameters for an OneDrive data source. Provide these parameters in the DataSourceParameters object when you create or update a data source that uses OneDrive.

    " + }, + "OneDriveTenantId":{ + "type":"string", + "max":100, + "min":1 + }, "Opacity":{ "type":"double", "max":1, @@ -33316,6 +36346,11 @@ }, "documentation":"

    The pagination configuration for a table visual or boxplot.

    " }, + "PaginationToken":{ + "type":"string", + "max":4096, + "min":1 + }, "Palette":{ "type":"structure", "members":{ @@ -34912,6 +37947,22 @@ }, "documentation":"

    The table query sorting options for the plugin visual.

    " }, + "PolicyDescription":{ + "type":"string", + "max":1024, + "min":0 + }, + "PolicyId":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-zA-Z0-9\\-_]+" + }, + "PolicyName":{ + "type":"string", + "max":256, + "min":1 + }, "Port":{ "type":"integer", "max":65535, @@ -35107,6 +38158,45 @@ "max":256, "sensitive":true }, + "ProfileDescription":{ + "type":"string", + "max":1024, + "min":0 + }, + "ProfileId":{ + "type":"string", + "max":128, + "min":1, + "pattern":"lp-[a-f0-9-]+" + }, + "ProfileLimitValue":{ + "type":"structure", + "required":[ + "maxValue", + "unit" + ], + "members":{ + "maxValue":{ + "shape":"ProfileLimitValueMaxValueLong", + "documentation":"

    The maximum allowed value for the resource.

    " + }, + "unit":{ + "shape":"LimitUnit", + "documentation":"

    The unit of measurement for the limit value.

    " + } + }, + "documentation":"

    A value that defines a resource usage limit, consisting of a maximum value and a unit of measurement.

    " + }, + "ProfileLimitValueMaxValueLong":{ + "type":"long", + "box":true, + "min":0 + }, + "ProfileName":{ + "type":"string", + "max":256, + "min":1 + }, "ProgressBarOptions":{ "type":"structure", "members":{ @@ -35162,6 +38252,17 @@ "MEASURE" ] }, + "ProviderConfig":{ + "type":"structure", + "members":{ + "MicrosoftPurview":{ + "shape":"MicrosoftPurviewProviderConfig", + "documentation":"

    The configuration for a Microsoft Purview DLP integration.

    " + } + }, + "documentation":"

    The provider-specific configuration for a DLP integration. This is a union type structure. For this structure to be valid, only one of the attributes can be defined.

    ", + "union":true + }, "PublicSpaceArn":{ "type":"string", "max":512, @@ -35592,11 +38693,11 @@ "type":"structure", "members":{ "Minimum":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The minimum value for a range constant.

    " }, "Maximum":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The maximum value for a range constant.

    " } }, @@ -36721,6 +39822,11 @@ "exception":true }, "ResourceId":{"type":"string"}, + "ResourceLimitsMap":{ + "type":"map", + "key":{"shape":"ResourceType"}, + "value":{"shape":"ProfileLimitValue"} + }, "ResourceName":{ "type":"string", "max":128, @@ -36779,6 +39885,18 @@ "DELETED" ] }, + "ResourceType":{ + "type":"string", + "documentation":"

    The type of resource that a limit applies to.

    ", + "enum":[ + "INDEX_STORAGE", + "AGENT_HOURS" + ] + }, + "ResourceTypeList":{ + "type":"list", + "member":{"shape":"ResourceType"} + }, "ResourceUnavailableException":{ "type":"structure", "members":{ @@ -37130,10 +40248,10 @@ }, "MetadataFilesLocation":{ "shape":"MetadataFilesLocation", - "documentation":"

    The location of metadata files within the S3 bucket that describe the structure and content of the knowledge base.

    " + "documentation":"

    The Amazon S3 location (prefix) of per-document metadata files. Each metadata file describes a single source document and its indexable attributes, such as title, category, and version. This is not the global ACL configuration file. To apply a single global ACL file to the entire knowledge base, use the access control configuration instead.

    " } }, - "documentation":"

    The parameters that are required to connect to a S3 Knowledge Base data source.

    " + "documentation":"

    The parameters that are required to connect to an S3 knowledge base data source.

    Prerequisites: Amazon S3 bucket access

    Before you call CreateKnowledgeBase for an Amazon S3 knowledge base, an administrator must grant Amazon QuickSight access to the source S3 bucket. If access has not been granted for the bucket, knowledge base creation fails.

    To grant access, an administrator adds the bucket in the Amazon QuickSight admin console, under Permissions, Amazon Web Services resources, Amazon S3, Select S3 buckets. This authorizes the Amazon QuickSight service role to read the bucket. The bucket can be in the same Amazon Web Services account or, when the bucket owner has authorized your account, in a different account.

    The service role requires at least the following permissions on the bucket:

    • s3:GetObject

    • s3:ListBucket

    • s3:GetBucketLocation

    • s3:GetObjectVersion

    • s3:ListBucketVersions

    For the full procedure, including cross-account buckets and KMS-encrypted buckets, see the Amazon S3 knowledge base administrator setup guide.

    To grant access for a specific S3 knowledge base data source without granting account-wide S3 access, provide a custom IAM role on the data source by using RoleArn.

    " }, "S3Parameters":{ "type":"structure", @@ -37679,6 +40797,90 @@ } } }, + "SearchAppsFilter":{ + "type":"structure", + "required":[ + "Name", + "Operator", + "Value" + ], + "members":{ + "Name":{ + "shape":"SearchAppsFilterName", + "documentation":"

    The name of the filter attribute.

    " + }, + "Operator":{ + "shape":"FilterOperator", + "documentation":"

    The comparison operator for the filter.

    " + }, + "Value":{ + "shape":"String", + "documentation":"

    The value to filter on.

    " + } + }, + "documentation":"

    A filter to apply when searching for apps.

    " + }, + "SearchAppsFilterList":{ + "type":"list", + "member":{"shape":"SearchAppsFilter"} + }, + "SearchAppsFilterName":{ + "type":"string", + "documentation":"

    The name of a field that you can use to filter app search results. Valid values are:

    • APP_ID – The unique identifier of the app.

    • APP_NAME – The display name of the app.

    • DIRECT_QUICKSIGHT_SOLE_OWNER – An Amazon QuickSight user or group that is the sole direct owner.

    • DIRECT_QUICKSIGHT_OWNER – An Amazon QuickSight user or group with direct owner permissions.

    • DIRECT_QUICKSIGHT_VIEWER_OR_OWNER – An Amazon QuickSight user or group with direct viewer or owner permissions.

    ", + "enum":[ + "APP_ID", + "APP_NAME", + "DIRECT_QUICKSIGHT_SOLE_OWNER", + "DIRECT_QUICKSIGHT_OWNER", + "DIRECT_QUICKSIGHT_VIEWER_OR_OWNER" + ] + }, + "SearchAppsRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "Filters" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the apps to search.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "Filters":{ + "shape":"SearchAppsFilterList", + "documentation":"

    The filters to apply to the search.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single request. Valid range is 1 to 100. If you don't specify a value, the default is 20.

    ", + "box":true + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + } + } + }, + "SearchAppsResponse":{ + "type":"structure", + "required":["AppSummaryList"], + "members":{ + "AppSummaryList":{ + "shape":"AppSummaryList", + "documentation":"

    A list of app summaries that match the search criteria.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "SearchDashboardsRequest":{ "type":"structure", "required":[ @@ -38183,6 +41385,56 @@ } } }, + "SearchTopicsV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "Filters" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want to search.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "Filters":{ + "shape":"TopicSearchFilterList", + "documentation":"

    The filters that you want to use to search for the topic.

    " + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to be returned per request.

    ", + "box":true + } + } + }, + "SearchTopicsV2Response":{ + "type":"structure", + "members":{ + "TopicSummaryList":{ + "shape":"TopicV2Summaries", + "documentation":"

    A list of topic summaries that is returned by the search topic request.

    " + }, + "NextToken":{ + "shape":"String", + "documentation":"

    The token for the next set of results, or null if there are no more results.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "Seasonality":{ "type":"integer", "max":180, @@ -38204,6 +41456,12 @@ "min":1, "pattern":"^arn:[-a-z0-9]*:secretsmanager:[-a-z0-9]*:[0-9]{12}:secret:.+" }, + "SecretManagerArn":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"arn:aws(-[\\w]+)*:secretsmanager:[a-z0-9\\-]+:\\d{12}:secret:.+" + }, "SectionAfterPageBreak":{ "type":"structure", "members":{ @@ -38654,7 +41912,8 @@ "enum":[ "REDSHIFT", "QBUSINESS", - "ATHENA" + "ATHENA", + "GLUE_DATA_CATALOG" ] }, "SessionLifetimeInMinutes":{ @@ -38748,6 +42007,44 @@ }, "documentation":"

    The shape conditional formatting of a filled map visual.

    " }, + "SharePointClientId":{ + "type":"string", + "max":100, + "min":1 + }, + "SharePointDomain":{ + "type":"string", + "max":1024, + "min":1 + }, + "SharePointParameters":{ + "type":"structure", + "required":["SharePointDomain"], + "members":{ + "SharePointDomain":{ + "shape":"SharePointDomain", + "documentation":"

    The SharePoint domain for the data source.

    " + }, + "TenantId":{ + "shape":"SharePointTenantId", + "documentation":"

    The tenant ID for the SharePoint data source.

    " + }, + "ClientId":{ + "shape":"SharePointClientId", + "documentation":"

    The client ID for the SharePoint data source.

    " + }, + "AuthType":{ + "shape":"AuthType", + "documentation":"

    The authentication type for the SharePoint data source. Valid values include:

    • TWO_LEGGED_OAUTH – Server-to-server authentication using client credentials that do not require user interaction.

    • THREE_LEGGED_OAUTH – Interactive OAuth that requires user consent.

    " + } + }, + "documentation":"

    The connection parameters for a SharePoint data source. Provide these parameters in the DataSourceParameters object when you create or update a data source that uses SharePoint.

    " + }, + "SharePointTenantId":{ + "type":"string", + "max":100, + "min":1 + }, "SharedColumnSemanticMetadata":{ "type":"structure", "required":["ColumnProperties"], @@ -41017,9 +44314,15 @@ "min":1, "sensitive":true }, + "SynonymString":{ + "type":"string", + "max":256, + "min":0, + "sensitive":true + }, "Synonyms":{ "type":"list", - "member":{"shape":"LimitedString"} + "member":{"shape":"SynonymString"} }, "TableAggregatedFieldWells":{ "type":"structure", @@ -41828,6 +45131,10 @@ "DataSetReferences":{ "shape":"DataSetReferenceList", "documentation":"

    A structure containing information about the dataset references used as placeholders in the template.

    " + }, + "TopicReferences":{ + "shape":"TopicReferenceList", + "documentation":"

    A structure containing information about the topic references used as placeholders in the template.

    " } }, "documentation":"

    The source analysis of the template.

    " @@ -41915,6 +45222,10 @@ "shape":"DataSetConfigurationList", "documentation":"

    Schema of the dataset identified by the placeholder. Any dashboard created from this template should be bound to new datasets matching the same schema described through this API operation.

    " }, + "TopicConfigurations":{ + "shape":"TopicConfigurationList", + "documentation":"

    Schema of the topic identified by the placeholder. Any dashboard created from this template should be bound to new topics matching the same schema described through this API operation.

    " + }, "Description":{ "shape":"VersionDescription", "documentation":"

    The description of the template.

    " @@ -41942,6 +45253,10 @@ "shape":"DataSetConfigurationList", "documentation":"

    An array of dataset configurations. These configurations define the required columns for each dataset used within a template.

    " }, + "TopicConfigurations":{ + "shape":"TopicConfigurationList", + "documentation":"

    An array of topic configurations. These configurations define the required columns for each topic used within a template.

    " + }, "Sheets":{ "shape":"SheetDefinitionList", "documentation":"

    An array of sheet definitions for a template.

    " @@ -42879,6 +46194,11 @@ "ABSOLUTE_DIFFERENCE" ] }, + "TopicArnsList":{ + "type":"list", + "member":{"shape":"Arn"}, + "max":100 + }, "TopicCalculatedField":{ "type":"structure", "required":[ @@ -42887,11 +46207,11 @@ ], "members":{ "CalculatedFieldName":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The calculated field name.

    " }, "CalculatedFieldDescription":{ - "shape":"LimitedString", + "shape":"DescriptionSensitiveString", "documentation":"

    The calculated field description.

    " }, "Expression":{ @@ -42979,6 +46299,10 @@ "Inverse":{ "shape":"Boolean", "documentation":"

    A Boolean value that indicates if the filter is inverse.

    " + }, + "NullFilter":{ + "shape":"NullFilterType", + "documentation":"

    The null filter that is applied to the category filter.

    " } }, "documentation":"

    A structure that represents a category filter.

    " @@ -42991,7 +46315,7 @@ "documentation":"

    The type of category filter constant. This element is used to specify whether a constant is a singular or collective. Valid values are SINGULAR and COLLECTIVE.

    " }, "SingularConstant":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    A singular constant used in a category filter. This element is used to specify a single value for the constant.

    " }, "CollectiveConstant":{ @@ -43011,11 +46335,11 @@ "documentation":"

    The name of the column.

    " }, "ColumnFriendlyName":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    A user-friendly name for the column.

    " }, "ColumnDescription":{ - "shape":"LimitedString", + "shape":"DescriptionSensitiveString", "documentation":"

    A description of the column and its contents.

    " }, "ColumnSynonyms":{ @@ -43091,6 +46415,29 @@ }, "documentation":"

    Configuration options for a Topic.

    " }, + "TopicConfiguration":{ + "type":"structure", + "members":{ + "Placeholder":{ + "shape":"String", + "documentation":"

    The placeholder for the topic configuration.

    " + }, + "DataSetSchema":{ + "shape":"DataSetSchema", + "documentation":"

    Topic schema.

    " + }, + "ColumnGroupSchemaList":{ + "shape":"ColumnGroupSchemaList", + "documentation":"

    The list of column group schemas in the topic configuration.

    " + } + }, + "documentation":"

    The configuration of a topic.

    " + }, + "TopicConfigurationList":{ + "type":"list", + "member":{"shape":"TopicConfiguration"}, + "max":30 + }, "TopicConstantValue":{ "type":"structure", "members":{ @@ -43127,10 +46474,20 @@ "Constant":{ "shape":"TopicRangeFilterConstant", "documentation":"

    The constant used in a date range filter.

    " + }, + "NullFilter":{ + "shape":"NullFilterType", + "documentation":"

    The null filter that is applied to the date range filter.

    " } }, "documentation":"

    A filter used to restrict data based on a range of dates or times.

    " }, + "TopicDescription":{ + "type":"string", + "max":256, + "min":1, + "pattern":".*\\S.*" + }, "TopicDetails":{ "type":"structure", "members":{ @@ -43165,7 +46522,7 @@ ], "members":{ "FilterDescription":{ - "shape":"LimitedString", + "shape":"DescriptionSensitiveString", "documentation":"

    A description of the filter used to select items for a topic.

    " }, "FilterClass":{ @@ -43506,6 +46863,34 @@ "max":256, "pattern":"^[A-Za-z0-9-_.\\\\+]*$" }, + "TopicIdentifier":{ + "type":"string", + "max":2048, + "min":1 + }, + "TopicIdentifierDeclaration":{ + "type":"structure", + "required":[ + "Identifier", + "TopicArn" + ], + "members":{ + "Identifier":{ + "shape":"TopicIdentifier", + "documentation":"

    The identifier of the topic, typically the topic's name.

    " + }, + "TopicArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + } + }, + "documentation":"

    A topic.

    " + }, + "TopicIdentifierDeclarationList":{ + "type":"list", + "member":{"shape":"TopicIdentifierDeclaration"}, + "max":50 + }, "TopicNamedEntities":{ "type":"list", "member":{"shape":"TopicNamedEntity"} @@ -43519,7 +46904,7 @@ "documentation":"

    The name of the named entity.

    " }, "EntityDescription":{ - "shape":"LimitedString", + "shape":"DescriptionSensitiveString", "documentation":"

    The description of the named entity.

    " }, "EntitySynonyms":{ @@ -43533,6 +46918,18 @@ "Definition":{ "shape":"NamedEntityDefinitions", "documentation":"

    The definition of a named entity.

    " + }, + "Sort":{ + "shape":"NamedEntitySortList", + "documentation":"

    The sort configuration of the named entity.

    " + }, + "RankOrder":{ + "shape":"NullableInteger", + "documentation":"

    The rank order of the named entity.

    " + }, + "PresentationOrder":{ + "shape":"NullableInteger", + "documentation":"

    The presentation order of the named entity.

    " } }, "documentation":"

    A structure that represents a named entity.

    " @@ -43562,6 +46959,14 @@ "Aggregation":{ "shape":"NamedFilterAggType", "documentation":"

    An aggregation function that specifies how to calculate the value of a numeric field for a topic. Valid values for this structure are NO_AGGREGATION, SUM, AVERAGE, COUNT, DISTINCT_COUNT, MAX, MEDIAN, MIN, STDEV, STDEVP, VAR, and VARP.

    " + }, + "Inverse":{ + "shape":"Boolean", + "documentation":"

    A Boolean value that indicates if the filter is inverse.

    " + }, + "NullFilter":{ + "shape":"NullFilterType", + "documentation":"

    The null filter that is applied to the numeric equality filter.

    " } }, "documentation":"

    A filter that filters topics based on the value of a numeric field. The filter includes only topics whose numeric field value matches the specified value.

    " @@ -43580,6 +46985,14 @@ "Aggregation":{ "shape":"NamedFilterAggType", "documentation":"

    An aggregation function that specifies how to calculate the value of a numeric field for a topic, Valid values for this structure are NO_AGGREGATION, SUM, AVERAGE, COUNT, DISTINCT_COUNT, MAX, MEDIAN, MIN, STDEV, STDEVP, VAR, and VARP.

    " + }, + "Inverse":{ + "shape":"Boolean", + "documentation":"

    A Boolean value that indicates if the filter is inverse.

    " + }, + "NullFilter":{ + "shape":"NullFilterType", + "documentation":"

    The null filter that is applied to the numeric range filter.

    " } }, "documentation":"

    A filter that filters topics based on the value of a numeric field. The filter includes only topics whose numeric field value falls within the specified range.

    " @@ -43606,6 +47019,29 @@ "documentation":"

    A constant value that is used in a range filter to specify the endpoints of the range.

    ", "sensitive":true }, + "TopicReference":{ + "type":"structure", + "required":[ + "TopicPlaceholder", + "TopicArn" + ], + "members":{ + "TopicPlaceholder":{ + "shape":"TopicIdentifier", + "documentation":"

    Topic placeholder.

    " + }, + "TopicArn":{ + "shape":"Arn", + "documentation":"

    Topic Amazon Resource Name (ARN).

    " + } + }, + "documentation":"

    Topic reference.

    " + }, + "TopicReferenceList":{ + "type":"list", + "member":{"shape":"TopicReference"}, + "min":1 + }, "TopicRefreshDetails":{ "type":"structure", "members":{ @@ -43708,6 +47144,10 @@ "Constant":{ "shape":"TopicSingularFilterConstant", "documentation":"

    The constant used in a relative date filter.

    " + }, + "NullFilter":{ + "shape":"NullFilterType", + "documentation":"

    The null filter that is applied to the relative date filter.

    " } }, "documentation":"

    A structure that represents a relative date filter.

    " @@ -43743,7 +47183,7 @@ "documentation":"

    The Dataset ARN for the TopicReviewedAnswer.

    " }, "Question":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The question for the TopicReviewedAnswer.

    " }, "Mir":{ @@ -43791,7 +47231,7 @@ "documentation":"

    The name of the topic search filter.

    " }, "Value":{ - "shape":"String", + "shape":"SensitiveString", "documentation":"

    The value of the topic search filter.

    " } }, @@ -43811,7 +47251,7 @@ "documentation":"

    The type of the singular filter constant. Valid values for this structure are SINGULAR.

    " }, "SingularConstant":{ - "shape":"LimitedString", + "shape":"LimitedSensitiveString", "documentation":"

    The value of the singular filter constant.

    " } }, @@ -43899,6 +47339,126 @@ "NEW_READER_EXPERIENCE" ] }, + "TopicV2DataSetReference":{ + "type":"structure", + "required":["DataSetArn"], + "members":{ + "DataSetArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the data set.

    " + }, + "DataSetName":{ + "shape":"LimitedString", + "documentation":"

    The name of the data set.

    " + } + }, + "documentation":"

    A structure that represents a data set reference of a topic.

    " + }, + "TopicV2DataSetReferences":{ + "type":"list", + "member":{"shape":"TopicV2DataSetReference"}, + "max":100, + "min":1 + }, + "TopicV2DataSetRelation":{ + "type":"structure", + "required":[ + "Left", + "Right" + ], + "members":{ + "Left":{ + "shape":"TopicV2DataSetRelationEndpoint", + "documentation":"

    The left endpoint of the data set relation.

    " + }, + "Right":{ + "shape":"TopicV2DataSetRelationEndpoint", + "documentation":"

    The right endpoint of the data set relation.

    " + } + }, + "documentation":"

    A structure that represents a relation between two data sets of a topic.

    " + }, + "TopicV2DataSetRelationColumnNames":{ + "type":"list", + "member":{"shape":"String"}, + "max":5, + "min":1 + }, + "TopicV2DataSetRelationEndpoint":{ + "type":"structure", + "required":[ + "DataSetArn", + "ColumnNames" + ], + "members":{ + "DataSetArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the data set at this endpoint of the relation.

    " + }, + "ColumnNames":{ + "shape":"TopicV2DataSetRelationColumnNames", + "documentation":"

    The names of the columns that are used in the data set relation.

    " + } + }, + "documentation":"

    A structure that represents an endpoint of a data set relation of a topic.

    " + }, + "TopicV2DataSetRelationList":{ + "type":"list", + "member":{"shape":"TopicV2DataSetRelation"}, + "max":100 + }, + "TopicV2Details":{ + "type":"structure", + "required":["Name"], + "members":{ + "Name":{ + "shape":"ResourceName", + "documentation":"

    The name of the topic.

    " + }, + "Description":{ + "shape":"LimitedString", + "documentation":"

    The description of the topic.

    " + }, + "DataSets":{ + "shape":"TopicV2DataSetReferences", + "documentation":"

    The data sets that the topic is associated with.

    " + }, + "DataSetRelations":{ + "shape":"TopicV2DataSetRelationList", + "documentation":"

    The relations between the data sets that the topic is associated with.

    " + } + }, + "documentation":"

    The definition of a topic.

    " + }, + "TopicV2PublishOption":{ + "type":"string", + "enum":[ + "DRAFT", + "PUBLISH" + ] + }, + "TopicV2Summaries":{ + "type":"list", + "member":{"shape":"TopicV2Summary"} + }, + "TopicV2Summary":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "Name":{ + "shape":"ResourceName", + "documentation":"

    The name of the topic.

    " + } + }, + "documentation":"

    A summary of the topic.

    " + }, "TopicVisual":{ "type":"structure", "members":{ @@ -45190,7 +48750,7 @@ }, "SourceEntity":{ "shape":"AnalysisSourceEntity", - "documentation":"

    A source entity to use for the analysis that you're updating. This metadata structure contains details that describe a source template and one or more datasets.

    " + "documentation":"

    A source entity to use for the analysis that you're updating. This metadata structure contains details that describe a source template and one or more datasets or topics.

    " }, "ThemeArn":{ "shape":"Arn", @@ -45232,6 +48792,64 @@ } } }, + "UpdateAppPermissionsRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "AppId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the app.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app.

    ", + "location":"uri", + "locationName":"AppId" + }, + "GrantPermissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    The permissions that you want to grant on the app.

    " + }, + "RevokePermissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    The permissions that you want to revoke from the app.

    " + }, + "Visibility":{ + "shape":"AppVisibility", + "documentation":"

    The visibility to set for the app. Currently, only PRIVATE is accepted, which removes public (anonymous) access from the app. If you don't specify a value, the app's visibility is unchanged. Setting an app to PUBLIC through this operation is not supported.

    " + } + } + }, + "UpdateAppPermissionsResponse":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the app.

    " + }, + "AppId":{ + "shape":"AppId", + "documentation":"

    The ID of the app.

    " + }, + "Permissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    The updated resource permissions for the app.

    " + }, + "Visibility":{ + "shape":"AppVisibility", + "documentation":"

    The visibility of the app after the update (PRIVATE or PUBLIC).

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "UpdateApplicationWithTokenExchangeGrantRequest":{ "type":"structure", "required":[ @@ -45267,6 +48885,52 @@ } } }, + "UpdateApprovalPolicyRequest":{ + "type":"structure", + "required":["PolicyId"], + "members":{ + "PolicyId":{ + "shape":"PolicyId", + "documentation":"

    The unique identifier of the approval policy to update.

    ", + "location":"uri", + "locationName":"PolicyId" + }, + "Name":{ + "shape":"PolicyName", + "documentation":"

    The name of the approval policy.

    " + }, + "Description":{ + "shape":"PolicyDescription", + "documentation":"

    A description of the approval policy.

    " + }, + "Actions":{ + "shape":"GovernedActionList", + "documentation":"

    The list of governed actions that trigger the approval workflow.

    " + }, + "AssetTypes":{ + "shape":"AssetTypeList", + "documentation":"

    The list of asset types that the approval policy applies to.

    " + }, + "ApplicableTo":{ + "shape":"ApplicableTo", + "documentation":"

    The scoping configuration that determines who the approval policy applies to.

    " + }, + "ApprovalGroups":{ + "shape":"ApprovalGroupList", + "documentation":"

    The list of group ARNs whose members can approve requests.

    " + } + } + }, + "UpdateApprovalPolicyResponse":{ + "type":"structure", + "required":["Policy"], + "members":{ + "Policy":{ + "shape":"ApprovalPolicy", + "documentation":"

    The updated approval policy.

    " + } + } + }, "UpdateBrandAssignmentRequest":{ "type":"structure", "required":[ @@ -45402,6 +49066,10 @@ "Capabilities":{ "shape":"Capabilities", "documentation":"

    A set of actions to include in the custom permissions profile.

    " + }, + "Governance":{ + "shape":"Governance", + "documentation":"

    The governance configuration for the custom permissions profile. The UpdateCustomPermissions operation replaces all existing Capabilities and Governance values. If you omit this parameter, Amazon Quick removes governance from the profile and the existing custom permission behavior applies.

    " } } }, @@ -45613,7 +49281,7 @@ }, "SourceEntity":{ "shape":"DashboardSourceEntity", - "documentation":"

    The entity that you are using as a source when you update the dashboard. In SourceEntity, you specify the type of object you're using as source. You can only update a dashboard from a template, so you use a SourceTemplate entity. If you need to update a dashboard from an analysis, first convert the analysis to a template by using the CreateTemplate API operation. For SourceTemplate, specify the Amazon Resource Name (ARN) of the source template. The SourceTemplate ARN can contain any Amazon Web Services account and any Amazon Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder.

    " + "documentation":"

    The entity that you are using as a source when you update the dashboard. In SourceEntity, you specify the type of object you're using as source. You can only update a dashboard from a template, so you use a SourceTemplate entity. If you need to update a dashboard from an analysis, first convert the analysis to a template by using the CreateTemplate API operation. For SourceTemplate, specify the Amazon Resource Name (ARN) of the source template. The SourceTemplate ARN can contain any Amazon Web Services account and any Amazon Quick Sight-supported Amazon Web Services Region.

    Use the DataSetReferences entity within SourceTemplate to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder. Use the TopicReferences entity to list the replacement topics for the topic placeholders listed in the original. The schema in each topic must match its placeholder.

    " }, "Parameters":{ "shape":"Parameters", @@ -46032,6 +49700,69 @@ } } }, + "UpdateDlpSettingRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "DlpSettingId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the DLP setting that you want to update.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the DLP setting that you want to update.

    ", + "location":"uri", + "locationName":"DlpSettingId" + }, + "Name":{ + "shape":"DlpSettingName", + "documentation":"

    An updated display name for the DLP setting.

    " + }, + "ProviderType":{ + "shape":"DlpProviderType", + "documentation":"

    An updated DLP provider type. Currently, the only supported value is MICROSOFT_PURVIEW.

    " + }, + "ProviderConfig":{ + "shape":"ProviderConfig", + "documentation":"

    An updated provider-specific configuration for the DLP integration. This is a union type structure. For this structure to be valid, only one of the attributes can be defined.

    " + }, + "ProviderOutageAction":{ + "shape":"DlpAction", + "documentation":"

    An updated behavior to apply when the DLP provider is unreachable. Valid values are ALLOW, WARN, and BLOCK.

    " + }, + "Enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether DLP enforcement is active for this setting. Set to true to enable enforcement, or false to disable it.

    ", + "box":true + } + } + }, + "UpdateDlpSettingResponse":{ + "type":"structure", + "required":[ + "Arn", + "DlpSettingId" + ], + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the updated DLP setting.

    " + }, + "DlpSettingId":{ + "shape":"DlpSettingId", + "documentation":"

    The ID of the updated DLP setting.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "UpdateFlowPermissionsInput":{ "type":"structure", "required":[ @@ -46581,6 +50312,116 @@ } } }, + "UpdateKnowledgeBaseRequest":{ + "type":"structure", + "required":[ + "AwsAccountId", + "KnowledgeBaseId" + ], + "members":{ + "AwsAccountId":{ + "shape":"KbAwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the knowledge base.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "KnowledgeBaseId":{ + "shape":"KnowledgeBaseId", + "documentation":"

    The unique identifier for the knowledge base.

    ", + "location":"uri", + "locationName":"KnowledgeBaseId" + }, + "Name":{ + "shape":"KnowledgeBaseName", + "documentation":"

    The name of the knowledge base. If you don't specify a name, the existing name is retained.

    " + }, + "Description":{ + "shape":"KnowledgeBaseDescription", + "documentation":"

    A description for the knowledge base. If you don't specify a description, the existing description is retained.

    " + }, + "KnowledgeBaseConfiguration":{"shape":"KnowledgeBaseConfiguration"}, + "MediaExtractionConfiguration":{"shape":"MediaExtractionConfiguration"}, + "IsEmailNotificationOptedForIngestionFailures":{ + "shape":"Boolean", + "documentation":"

    Specifies whether email notifications are enabled for ingestion failures.

    ", + "box":true + }, + "AccessControlConfiguration":{ + "shape":"AccessControlConfiguration", + "documentation":"

    The access control configuration for the knowledge base. If you don't specify this parameter, the existing setting is retained.

    " + } + } + }, + "UpdateKnowledgeBaseResponse":{ + "type":"structure", + "required":[ + "KnowledgeBaseArn", + "KnowledgeBaseId" + ], + "members":{ + "KnowledgeBaseArn":{ + "shape":"KnowledgeBaseArn", + "documentation":"

    The Amazon Resource Name (ARN) of the knowledge base.

    " + }, + "KnowledgeBaseId":{ + "shape":"KnowledgeBaseId", + "documentation":"

    The unique identifier for the knowledge base.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "box":true, + "location":"statusCode" + } + } + }, + "UpdateLimitsProfileRequest":{ + "type":"structure", + "required":[ + "profileId", + "accountId" + ], + "members":{ + "profileId":{ + "shape":"ProfileId", + "documentation":"

    The unique identifier for the limits profile to update.

    ", + "location":"uri", + "locationName":"profileId" + }, + "accountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the limits profile.

    ", + "location":"uri", + "locationName":"accountId" + }, + "profileName":{ + "shape":"ProfileName", + "documentation":"

    A new display name for the limits profile.

    " + }, + "description":{ + "shape":"ProfileDescription", + "documentation":"

    A new description for the limits profile.

    " + }, + "resourceLimits":{ + "shape":"ResourceLimitsMap", + "documentation":"

    A map of resource types to their updated limit values.

    " + } + } + }, + "UpdateLimitsProfileResponse":{ + "type":"structure", + "required":["arn"], + "members":{ + "arn":{ + "shape":"ResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the updated limits profile.

    " + } + } + }, "UpdateLinkPermissionList":{ "type":"list", "member":{"shape":"ResourcePermission"}, @@ -47264,7 +51105,7 @@ }, "SourceEntity":{ "shape":"TemplateSourceEntity", - "documentation":"

    The entity that you are using as a source when you update the template. In SourceEntity, you specify the type of object you're using as source: SourceTemplate for a template or SourceAnalysis for an analysis. Both of these require an Amazon Resource Name (ARN). For SourceTemplate, specify the ARN of the source template. For SourceAnalysis, specify the ARN of the source analysis. The SourceTemplate ARN can contain any Amazon Web Services account and any Quick Sight-supported Amazon Web Services Region;.

    Use the DataSetReferences entity within SourceTemplate or SourceAnalysis to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder.

    " + "documentation":"

    The entity that you are using as a source when you update the template. In SourceEntity, you specify the type of object you're using as source: SourceTemplate for a template or SourceAnalysis for an analysis. Both of these require an Amazon Resource Name (ARN). For SourceTemplate, specify the ARN of the source template. For SourceAnalysis, specify the ARN of the source analysis. The SourceTemplate ARN can contain any Amazon Web Services account and any Quick Sight-supported Amazon Web Services Region;.

    Use the DataSetReferences entity within SourceTemplate or SourceAnalysis to list the replacement datasets for the placeholders listed in the original. The schema in each dataset must match its placeholder. Use the TopicReferences entity to list the replacement topics for the topic placeholders listed in the original. The schema in each topic must match its placeholder.

    " }, "VersionDescription":{ "shape":"VersionDescription", @@ -47543,6 +51384,61 @@ } } }, + "UpdateTopicPermissionsV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want to update the permissions for.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to modify. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    ", + "location":"uri", + "locationName":"TopicId" + }, + "GrantPermissions":{ + "shape":"UpdateResourcePermissionList", + "documentation":"

    The resource permissions that you want to grant to the topic.

    " + }, + "RevokePermissions":{ + "shape":"UpdateResourcePermissionList", + "documentation":"

    The resource permissions that you want to revoke from the topic.

    " + } + } + }, + "UpdateTopicPermissionsV2Response":{ + "type":"structure", + "members":{ + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to modify. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "TopicArn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "Permissions":{ + "shape":"ResourcePermissionList", + "documentation":"

    A list of resource permissions on the topic.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + } + } + }, "UpdateTopicRefreshScheduleRequest":{ "type":"structure", "required":[ @@ -47658,6 +51554,59 @@ } } }, + "UpdateTopicV2Request":{ + "type":"structure", + "required":[ + "AwsAccountId", + "TopicId", + "Topic" + ], + "members":{ + "AwsAccountId":{ + "shape":"AwsAccountId", + "documentation":"

    The ID of the Amazon Web Services account that contains the topic that you want to update.

    ", + "location":"uri", + "locationName":"AwsAccountId" + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to modify. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    ", + "location":"uri", + "locationName":"TopicId" + }, + "Topic":{ + "shape":"TopicV2Details", + "documentation":"

    The definition of the topic that you want to update.

    " + }, + "CustomInstructions":{"shape":"CustomInstructions"}, + "PublishOption":{ + "shape":"TopicV2PublishOption", + "documentation":"

    The publish option for the topic that you want to update.

    " + } + } + }, + "UpdateTopicV2Response":{ + "type":"structure", + "members":{ + "Arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the topic.

    " + }, + "TopicId":{ + "shape":"TopicId", + "documentation":"

    The ID of the topic that you want to modify. This ID is unique per Amazon Web Services Region for each Amazon Web Services account.

    " + }, + "RequestId":{ + "shape":"String", + "documentation":"

    The Amazon Web Services request ID for this operation.

    " + }, + "Status":{ + "shape":"StatusCode", + "documentation":"

    The HTTP status of the request.

    ", + "location":"statusCode" + } + } + }, "UpdateUserCustomPermissionRequest":{ "type":"structure", "required":[ @@ -48050,6 +51999,51 @@ "DESC" ] }, + "UserLimits":{ + "type":"structure", + "required":[ + "userName", + "namespace", + "effectiveLimits" + ], + "members":{ + "userName":{ + "shape":"String", + "documentation":"

    The name of the user.

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    The namespace of the user.

    " + }, + "effectiveLimits":{ + "shape":"EffectiveLimitList", + "documentation":"

    A list of effective limits for the user.

    " + } + }, + "documentation":"

    The effective limits for an Amazon Quick Sight user.

    " + }, + "UserLimitsEntry":{ + "type":"structure", + "required":[ + "userName", + "namespace" + ], + "members":{ + "userName":{ + "shape":"String", + "documentation":"

    The name of the user.

    " + }, + "namespace":{ + "shape":"String", + "documentation":"

    The namespace of the user.

    " + } + }, + "documentation":"

    Identifies a user for the BatchDescribeUserLimits operation.

    " + }, + "UserLimitsList":{ + "type":"list", + "member":{"shape":"UserLimits"} + }, "UserList":{ "type":"list", "member":{"shape":"User"} @@ -48607,6 +52601,64 @@ }, "documentation":"

    The menu options for a visual.

    " }, + "VisualMessageConfiguration":{ + "type":"structure", + "members":{ + "Enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the custom message is displayed on the visual. When set to true, the custom message appears in place of the default message. When set to false or omitted, the default message is displayed.

    " + }, + "Title":{ + "shape":"VisualMessageText", + "documentation":"

    The title text of the message that is displayed on the visual.

    " + }, + "TitleVisibility":{ + "shape":"Visibility", + "documentation":"

    Specifies whether the title of the message is displayed.

    " + }, + "Description":{ + "shape":"VisualMessageText", + "documentation":"

    The description text of the message that is displayed on the visual.

    " + }, + "DescriptionVisibility":{ + "shape":"Visibility", + "documentation":"

    Specifies whether the description of the message is displayed.

    " + }, + "LinkText":{ + "shape":"VisualMessageText", + "documentation":"

    The display text of the hyperlink that is shown in the message.

    " + }, + "LinkUrl":{ + "shape":"VisualMessageLinkUrl", + "documentation":"

    The destination URL of the hyperlink that is shown in the message. Only valid http, https, and mailto URLs are supported.

    " + }, + "LinkVisibility":{ + "shape":"Visibility", + "documentation":"

    Specifies whether the hyperlink in the message is displayed.

    " + } + }, + "documentation":"

    The configuration for a customizable message displayed on a visual. Supports parameter substitution in text fields.

    " + }, + "VisualMessageLinkUrl":{ + "type":"string", + "max":120, + "pattern":"(?i)\\A(?:(?:https?://|mailto:)\\S*<<\\$.+?>>\\S*|https?://[a-z\\d.-]+\\.[a-z]{2,63}(?::\\d+)?(?:[/?#][^\\s]*)?|mailto:[^\\s@]+@[a-z\\d.-]+\\.[a-z]{2,63})\\z" + }, + "VisualMessageText":{ + "type":"string", + "max":120, + "pattern":"\\A[\\p{L}\\p{M}\\p{N}\\s.,/\\\\:_()\\[\\]<>$!?'\"#@%+&|^\\-]*\\z" + }, + "VisualMessages":{ + "type":"structure", + "members":{ + "NoDataMessage":{ + "shape":"VisualMessageConfiguration", + "documentation":"

    The message that is displayed on a visual when there is no data to display.

    " + } + }, + "documentation":"

    The messages that are displayed on a visual under specific conditions, such as when the visual returns no data.

    " + }, "VisualOptions":{ "type":"structure", "members":{ diff --git a/services/ram/pom.xml b/services/ram/pom.xml index a114c02f5089..2f85ecd6312c 100644 --- a/services/ram/pom.xml +++ b/services/ram/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ram AWS Java SDK :: Services :: RAM diff --git a/services/ram/src/main/resources/codegen-resources/customization.config b/services/ram/src/main/resources/codegen-resources/customization.config index 0aab6ae18cac..962559b5c74c 100644 --- a/services/ram/src/main/resources/codegen-resources/customization.config +++ b/services/ram/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "getResourceShareInvitations", "enableSharingWithAwsOrganization" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ram/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ram/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2dc271f95581 --- /dev/null +++ b/services/ram/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ram-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ram.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ram-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ram.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ram.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ram/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ram/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index cc45792de595..000000000000 --- a/services/ram/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ram-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://ram.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ram-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ram.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ram.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rbin/pom.xml b/services/rbin/pom.xml index 8373afe2e27f..f319c237a6a8 100644 --- a/services/rbin/pom.xml +++ b/services/rbin/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rbin AWS Java SDK :: Services :: Rbin diff --git a/services/rbin/src/main/resources/codegen-resources/customization.config b/services/rbin/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/rbin/src/main/resources/codegen-resources/customization.config +++ b/services/rbin/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/rbin/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rbin/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8e4164776a8f --- /dev/null +++ b/services/rbin/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rbin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rbin-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rbin.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rbin.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rbin/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rbin/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0dc4350c0882..000000000000 --- a/services/rbin/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rbin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rbin-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rbin.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rbin.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rds/pom.xml b/services/rds/pom.xml index ff5255ff1041..f64f20a6a388 100644 --- a/services/rds/pom.xml +++ b/services/rds/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rds AWS Java SDK :: Services :: Amazon RDS diff --git a/services/rds/src/main/java/software/amazon/awssdk/services/rds/internal/RdsPresignInterceptor.java b/services/rds/src/main/java/software/amazon/awssdk/services/rds/internal/RdsPresignInterceptor.java index f3b9cb723277..d35815b2392d 100644 --- a/services/rds/src/main/java/software/amazon/awssdk/services/rds/internal/RdsPresignInterceptor.java +++ b/services/rds/src/main/java/software/amazon/awssdk/services/rds/internal/RdsPresignInterceptor.java @@ -24,9 +24,7 @@ import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsExecutionAttribute; -import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.core.ClientEndpointProvider; -import software.amazon.awssdk.core.Protocol; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -35,7 +33,6 @@ 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.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; @@ -48,6 +45,7 @@ import software.amazon.awssdk.identity.spi.Identity; import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory; import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.rds.endpoints.RdsEndpointProvider; import software.amazon.awssdk.services.rds.model.RdsRequest; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -72,7 +70,6 @@ public abstract class RdsPresignInterceptor implements Exe .build()) .build(); - private static final String SERVICE_NAME = "rds"; private static final String PARAM_SOURCE_REGION = "SourceRegion"; private static final String PARAM_DESTINATION_REGION = "DestinationRegion"; private static final String PARAM_PRESIGNED_URL = "PreSignedUrl"; @@ -109,7 +106,7 @@ public final SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, SelectedAuthScheme selectedAuthScheme = resolveAuthScheme(context.request(), executionAttributes); String sourceRegion = presignableRequest.getSourceRegion(); String destinationRegion = selectedAuthScheme.authSchemeOption().signerProperty(AwsV4HttpSigner.REGION_NAME); - URI endpoint = createEndpoint(sourceRegion, SERVICE_NAME, executionAttributes); + URI endpoint = createEndpoint(sourceRegion, executionAttributes); SdkHttpFullRequest.Builder marshalledRequest = presignableRequest.marshall().toBuilder().uri(endpoint); SdkHttpFullRequest requestToPresign = @@ -223,17 +220,14 @@ private SdkHttpFullRequest toSdkHttpFullRequest(SignedRequest signedRequest) { .build(); } - private URI createEndpoint(String regionName, String serviceName, ExecutionAttributes attributes) { - return AwsClientEndpointProvider.builder() - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol(Protocol.HTTPS.toString()) - .region(Region.of(regionName)) - .profileFile(attributes.getAttribute(SdkExecutionAttribute.PROFILE_FILE_SUPPLIER)) - .profileName(attributes.getAttribute(SdkExecutionAttribute.PROFILE_NAME)) - .dualstackEnabled( - attributes.getAttribute(AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) - .fipsEnabled(attributes.getAttribute(AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED)) - .build() - .clientEndpoint(); + private URI createEndpoint(String regionName, ExecutionAttributes attributes) { + return CompletableFutureUtils.joinLikeSync( + RdsEndpointProvider.defaultProvider() + .resolveEndpoint(p -> p.region(Region.of(regionName)) + .useDualStack(attributes.getAttribute( + AwsExecutionAttribute.DUALSTACK_ENDPOINT_ENABLED)) + .useFips(attributes.getAttribute( + AwsExecutionAttribute.FIPS_ENDPOINT_ENABLED))) + ).url(); } } diff --git a/services/rds/src/main/resources/codegen-resources/customization.config b/services/rds/src/main/resources/codegen-resources/customization.config index b51679336614..c7ccf3e50397 100644 --- a/services/rds/src/main/resources/codegen-resources/customization.config +++ b/services/rds/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { - "enableGenerateCompiledEndpointRules": true, "shapeModifiers" : { "CopyDBSnapshotMessage" : { "inject" : [ diff --git a/services/rds/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rds/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fd1d9901492d --- /dev/null +++ b/services/rds/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rds/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rds/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index eaad8e6d0e8d..000000000000 --- a/services/rds/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://rds.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rds/src/main/resources/codegen-resources/service-2.json b/services/rds/src/main/resources/codegen-resources/service-2.json index 710809a7e43e..d6264e8fa036 100644 --- a/services/rds/src/main/resources/codegen-resources/service-2.json +++ b/services/rds/src/main/resources/codegen-resources/service-2.json @@ -335,12 +335,13 @@ {"shape":"InvalidDBInstanceStateFault"}, {"shape":"KMSKeyNotAccessibleFault"}, {"shape":"InvalidVPCNetworkStateFault"}, + {"shape":"DBClusterRoleQuotaExceededFault"}, {"shape":"InvalidDBClusterStateFault"}, {"shape":"InvalidDBSubnetGroupStateFault"}, {"shape":"DBSubnetGroupNotFoundFault"}, {"shape":"DBClusterQuotaExceededFault"} ], - "documentation":"

    Creates a new Amazon Aurora DB cluster or Multi-AZ DB cluster.

    If you create an Aurora DB cluster, the request creates an empty cluster. You must explicitly create the writer instance for your DB cluster using the CreateDBInstance operation. If you create a Multi-AZ DB cluster, the request creates a writer and two reader DB instances for you, each in a different Availability Zone.

    You can use the ReplicationSourceIdentifier parameter to create an Amazon Aurora DB cluster as a read replica of another DB cluster or Amazon RDS for MySQL or PostgreSQL DB instance. For more information about Amazon Aurora, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    You can also use the ReplicationSourceIdentifier parameter to create a Multi-AZ DB cluster read replica with an RDS for MySQL or PostgreSQL DB instance as the source. For more information about Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    You can use the WithExpressConfiguration parameter to create an Aurora DB Cluster with express configuration and create cluster in seconds. Express configuration provides a cluster with a writer instance and feature specific values set to all other input parameters of this API.

    " + "documentation":"

    Creates a new Amazon Aurora DB cluster or Multi-AZ DB cluster.

    If you create an Aurora DB cluster, the request creates an empty cluster. You must explicitly create the writer instance for your DB cluster using the CreateDBInstance operation. If you create a Multi-AZ DB cluster, the request creates a writer and two reader DB instances for you, each in a different Availability Zone.

    You can use the ReplicationSourceIdentifier parameter to create an Amazon Aurora DB cluster as a read replica of another DB cluster or Amazon RDS for MySQL or PostgreSQL DB instance. For more information about Amazon Aurora, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    You can also use the ReplicationSourceIdentifier parameter to create a Multi-AZ DB cluster read replica with an RDS for MySQL or PostgreSQL DB instance as the source. For more information about Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    You can use the WithExpressConfiguration parameter to create an Aurora DB Cluster with express configuration and create cluster in seconds. Express configuration provides a cluster with a writer instance and feature specific values set to all other input parameters of this API.

    You can use the AssociatedRoles parameter to associate one or more Amazon Web Services Identity and Access Management (IAM) roles with an Aurora DB cluster. Each associated role lets the DB cluster access other Amazon Web Services on your behalf, such as Amazon S3 for data import and export, or Amazon Web Services Lambda for invoking functions.

    " }, "CreateDBClusterEndpoint":{ "name":"CreateDBClusterEndpoint", @@ -2666,6 +2667,7 @@ {"shape":"DBClusterNotFoundFault"}, {"shape":"StorageTypeNotSupportedFault"}, {"shape":"InvalidVPCNetworkStateFault"}, + {"shape":"DBClusterRoleQuotaExceededFault"}, {"shape":"InvalidDBClusterStateFault"}, {"shape":"DBClusterAlreadyExistsFault"}, {"shape":"NetworkTypeNotSupported"}, @@ -2674,7 +2676,7 @@ {"shape":"InvalidS3BucketFault"}, {"shape":"DBClusterQuotaExceededFault"} ], - "documentation":"

    Creates an Amazon Aurora DB cluster from MySQL data stored in an Amazon S3 bucket. Amazon RDS must be authorized to access the Amazon S3 bucket and the data must be created using the Percona XtraBackup utility as described in Migrating Data from MySQL by Using an Amazon S3 Bucket in the Amazon Aurora User Guide.

    This operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterFromS3 operation has completed and the DB cluster is available.

    For more information on Amazon Aurora, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    This operation only applies to Aurora DB clusters. The source DB engine must be MySQL.

    " + "documentation":"

    Creates an Amazon Aurora DB cluster from MySQL data stored in an Amazon S3 bucket. Amazon RDS must be authorized to access the Amazon S3 bucket and the data must be created using the Percona XtraBackup utility as described in Migrating Data from MySQL by Using an Amazon S3 Bucket in the Amazon Aurora User Guide.

    This operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterFromS3 operation has completed and the DB cluster is available.

    For more information on Amazon Aurora, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    This operation only applies to Aurora DB clusters. The source DB engine must be MySQL.

    You can use the AssociatedRoles parameter to associate one or more Amazon Web Services Identity and Access Management (IAM) roles with the Aurora DB cluster when you restore it from Amazon S3.

    " }, "RestoreDBClusterFromSnapshot":{ "name":"RestoreDBClusterFromSnapshot", @@ -2708,11 +2710,12 @@ {"shape":"InvalidDBInstanceStateFault"}, {"shape":"KMSKeyNotAccessibleFault"}, {"shape":"InvalidVPCNetworkStateFault"}, + {"shape":"DBClusterRoleQuotaExceededFault"}, {"shape":"DBSubnetGroupNotFoundFault"}, {"shape":"InvalidRestoreFault"}, {"shape":"DBClusterQuotaExceededFault"} ], - "documentation":"

    Creates a new DB cluster from a DB snapshot or DB cluster snapshot.

    The target DB cluster is created from the source snapshot with a default configuration. If you don't specify a security group, the new DB cluster is associated with the default security group.

    You can use the EnableVPCNetworking and EnableInternetAccessGateway parameters together to restore an Aurora PostgreSQL cluster without VPC networking and with internet-based connectivity. These two parameters must always be specified together. Set EnableVPCNetworking to false to disable the VPC network interface (ENI) for the cluster. EnableInternetAccessGateway enables internet-based connectivity through an internet access gateway. IAM database authentication is required and must be enabled using EnableIAMDatabaseAuthentication. Once the cluster is restored, you need to modify the DB cluster to update MasterUserAuthenticationType to iam-db-auth.

    This operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterFromSnapshot operation has completed and the DB cluster is available.

    For more information on Amazon Aurora DB clusters, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    For more information on Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    " + "documentation":"

    Creates a new DB cluster from a DB snapshot or DB cluster snapshot.

    The target DB cluster is created from the source snapshot with a default configuration. If you don't specify a security group, the new DB cluster is associated with the default security group.

    You can use the EnableVPCNetworking and EnableInternetAccessGateway parameters together to restore an Aurora PostgreSQL cluster without VPC networking and with internet-based connectivity. These two parameters must always be specified together. Set EnableVPCNetworking to false to disable the VPC network interface (ENI) for the cluster. EnableInternetAccessGateway enables internet-based connectivity through an internet access gateway. IAM database authentication is required and must be enabled using EnableIAMDatabaseAuthentication. Once the cluster is restored, you need to modify the DB cluster to update MasterUserAuthenticationType to iam-db-auth.

    You can use the AssociatedRoles parameter to associate one or more Amazon Web Services Identity and Access Management (IAM) roles with an Aurora DB cluster when you restore it from a snapshot.

    This operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterFromSnapshot operation has completed and the DB cluster is available.

    For more information on Amazon Aurora DB clusters, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    For more information on Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    " }, "RestoreDBClusterToPointInTime":{ "name":"RestoreDBClusterToPointInTime", @@ -2745,12 +2748,13 @@ {"shape":"KMSKeyNotAccessibleFault"}, {"shape":"DBClusterAutomatedBackupNotFoundFault"}, {"shape":"InvalidVPCNetworkStateFault"}, + {"shape":"DBClusterRoleQuotaExceededFault"}, {"shape":"InvalidDBClusterStateFault"}, {"shape":"DBSubnetGroupNotFoundFault"}, {"shape":"InvalidRestoreFault"}, {"shape":"DBClusterQuotaExceededFault"} ], - "documentation":"

    Restores a DB cluster to an arbitrary point in time. Users can restore to any point in time before LatestRestorableTime for up to BackupRetentionPeriod days. The target DB cluster is created from the source DB cluster with the same configuration as the original DB cluster, except that the new DB cluster is created with the default DB security group. Unless the RestoreType is set to copy-on-write, the restore may occur in a different Availability Zone (AZ) from the original DB cluster. The AZ where RDS restores the DB cluster depends on the AZs in the specified subnet group.

    You can use the EnableVPCNetworking and EnableInternetAccessGateway parameters together to restore an Aurora PostgreSQL cluster without VPC networking and with internet-based connectivity. These two parameters must always be specified together. Set EnableVPCNetworking to false to disable the VPC network interface (ENI) for the cluster. EnableInternetAccessGateway enables internet-based connectivity through an internet access gateway. IAM database authentication is required and must be enabled using EnableIAMDatabaseAuthentication. Once the cluster is restored, you need to modify the DB cluster to update MasterUserAuthenticationType to iam-db-auth.

    For Aurora, this operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterToPointInTime operation has completed and the DB cluster is available.

    For more information on Amazon Aurora DB clusters, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    For more information on Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    " + "documentation":"

    Restores a DB cluster to an arbitrary point in time. Users can restore to any point in time before LatestRestorableTime for up to BackupRetentionPeriod days. The target DB cluster is created from the source DB cluster with the same configuration as the original DB cluster, except that the new DB cluster is created with the default DB security group. Unless the RestoreType is set to copy-on-write, the restore may occur in a different Availability Zone (AZ) from the original DB cluster. The AZ where RDS restores the DB cluster depends on the AZs in the specified subnet group.

    You can use the EnableVPCNetworking and EnableInternetAccessGateway parameters together to restore an Aurora PostgreSQL cluster without VPC networking and with internet-based connectivity. These two parameters must always be specified together. Set EnableVPCNetworking to false to disable the VPC network interface (ENI) for the cluster. EnableInternetAccessGateway enables internet-based connectivity through an internet access gateway. IAM database authentication is required and must be enabled using EnableIAMDatabaseAuthentication. Once the cluster is restored, you need to modify the DB cluster to update MasterUserAuthenticationType to iam-db-auth.

    You can use the AssociatedRoles parameter to associate one or more Amazon Web Services Identity and Access Management (IAM) roles with an Aurora DB cluster when you restore it to a point in time.

    For Aurora, this operation only restores the DB cluster, not the DB instances for that DB cluster. You must invoke the CreateDBInstance operation to create DB instances for the restored DB cluster, specifying the identifier of the restored DB cluster in DBClusterIdentifier. You can create DB instances only after the RestoreDBClusterToPointInTime operation has completed and the DB cluster is available.

    For more information on Amazon Aurora DB clusters, see What is Amazon Aurora? in the Amazon Aurora User Guide.

    For more information on Multi-AZ DB clusters, see Multi-AZ DB cluster deployments in the Amazon RDS User Guide.

    " }, "RestoreDBInstanceFromDBSnapshot":{ "name":"RestoreDBInstanceFromDBSnapshot", @@ -3209,7 +3213,7 @@ "documentation":"

    The name of the DB cluster to associate the IAM role with.

    " }, "RoleArn":{ - "shape":"String", + "shape":"IAMRoleArn", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role to associate with the Aurora DB cluster, for example arn:aws:iam::123456789012:role/AuroraAccessRole.

    " }, "FeatureName":{ @@ -3324,6 +3328,14 @@ "shape":"String", "documentation":"

    The status of the additional storage volume.

    Valid Values: ACTIVE | CREATING | DELETING | MODIFYING | NOT-IN-USE | STORAGE-OPTIMIZATION | VOLUME-FULL

    " }, + "StorageOperationStatus":{ + "shape":"String", + "documentation":"

    The status of an in-progress storage operation on the additional storage volume. This field appears only while a storage operation is in progress. It isn't present when no storage operation is active. Possible values:

    • Initializing - The volume is initializing from a snapshot, such as during a snapshot restore, point-in-time restore, read replica creation, or blue/green deployment. Performance can be lower than provisioned until initialization completes.

    • Optimizing - The volume is optimizing following a storage scaling or modification operation.

    " + }, + "StorageOperationPercentProgress":{ + "shape":"IntegerOptional", + "documentation":"

    The percentage of the in-progress storage operation on the additional storage volume that has completed, from 0 to 100. This field appears only while a storage operation is in progress. It isn't present when no storage operation is active.

    " + }, "AllocatedStorage":{ "shape":"Integer", "documentation":"

    The amount of storage allocated for the additional storage volume, in gibibytes (GiB). The minimum is 20 GiB. The maximum is 65,536 GiB (64 TiB).

    " @@ -4599,7 +4611,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the DB cluster will fail if the DB major version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the DB cluster will fail if the DB major version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "TagSpecifications":{ "shape":"TagSpecificationList", @@ -4612,6 +4624,10 @@ "WithExpressConfiguration":{ "shape":"BooleanOptional", "documentation":"

    Specifies to create an Aurora DB Cluster with express configuration in seconds. Express configuration provides a cluster with a writer instance and feature specific values set to all other input parameters of this API.

    Valid for Cluster Type: Aurora DB clusters

    " + }, + "AssociatedRoles":{ + "shape":"DBClusterAssociatedRoles", + "documentation":"

    A list of Amazon Web Services Identity and Access Management (IAM) roles to associate with the DB cluster. Each role grants the DB cluster permission to access other Amazon Web Services on your behalf. For each role, specify a role ARN and, optionally, the feature name (such as s3Import, s3Export, or Lambda).

    Valid for Cluster Type: Aurora DB clusters only

    " } }, "documentation":"

    " @@ -4945,7 +4961,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the DB instance will fail if the DB major version is past its end of standard support date.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the life cycle type is managed by the DB cluster.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the DB instance will fail if the DB major version is past its end of standard support date.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the engine lifecycle support is managed by the DB cluster.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "AdditionalStorageVolumes":{ "shape":"AdditionalStorageVolumesList", @@ -5507,7 +5523,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this global database cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your global cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the global cluster will fail if the DB major version is past its end of standard support date.

    This setting only applies to Aurora PostgreSQL-based global databases.

    You can use this setting to enroll your global cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your global cluster past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon Aurora in the Amazon Aurora User Guide.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this global database cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your global cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, creating the global cluster will fail if the DB major version is past its end of standard support date.

    This setting only applies to Aurora PostgreSQL-based global databases.

    You can use this setting to enroll your global cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your global cluster past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon Aurora in the Amazon Aurora User Guide.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "DeletionProtection":{ "shape":"BooleanOptional", @@ -6101,6 +6117,30 @@ }, "exception":true }, + "DBClusterAssociatedRole":{ + "type":"structure", + "required":["RoleArn"], + "members":{ + "RoleArn":{ + "shape":"IAMRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role to associate with the DB cluster.

    " + }, + "FeatureName":{ + "shape":"String", + "documentation":"

    The name of the feature associated with the IAM role. For information about supported feature names, see DBEngineVersion.

    " + } + }, + "documentation":"

    Contains information about an Amazon Web Services Identity and Access Management (IAM) role to associate with a DB cluster. You can specify this structure in the AssociatedRoles parameter of CreateDBCluster, RestoreDBClusterFromS3, RestoreDBClusterFromSnapshot, and RestoreDBClusterToPointInTime.

    " + }, + "DBClusterAssociatedRoles":{ + "type":"list", + "member":{ + "shape":"DBClusterAssociatedRole", + "locationName":"DBClusterAssociatedRole" + }, + "max":15, + "min":0 + }, "DBClusterAutomatedBackup":{ "type":"structure", "members":{ @@ -7442,6 +7482,14 @@ "StorageVolumeStatus":{ "shape":"String", "documentation":"

    The detailed status information for storage volumes associated with the DB instance. This information helps identify which specific volume is causing the instance to be in a storage-full state.

    " + }, + "StorageOperationStatus":{ + "shape":"String", + "documentation":"

    The status of an in-progress storage operation on the DB instance. This field appears only while a storage operation is in progress. It isn't present when no storage operation is active. Possible values:

    • Initializing - The volume is initializing from a snapshot, such as during a snapshot restore, point-in-time restore, read replica creation, or blue/green deployment. Performance can be lower than provisioned until initialization completes.

    • Optimizing - The volume is optimizing following a storage scaling or modification operation.

    " + }, + "StorageOperationPercentProgress":{ + "shape":"IntegerOptional", + "documentation":"

    The percentage of the in-progress storage operation on the DB instance that has completed, from 0 to 100. This field appears only while a storage operation is in progress. It isn't present when no storage operation is active.

    " } }, "documentation":"

    Contains the details of an Amazon RDS DB instance.

    This data type is used as a response element in the operations CreateDBInstance, CreateDBInstanceReadReplica, DeleteDBInstance, DescribeDBInstances, ModifyDBInstance, PromoteReadReplica, RebootDBInstance, RestoreDBInstanceFromDBSnapshot, RestoreDBInstanceFromS3, RestoreDBInstanceToPointInTime, StartDBInstance, and StopDBInstance.

    ", @@ -8797,6 +8845,10 @@ "SnapshotAvailabilityZone":{ "shape":"String", "documentation":"

    Specifies the name of the Availability Zone where RDS stores the DB snapshot. This value is valid only for snapshots that RDS stores on a Dedicated Local Zone.

    " + }, + "FullSnapshotSizeInBytes":{ + "shape":"LongOptional", + "documentation":"

    The full size of the DB snapshot, in bytes.

    This is not the incremental size of the snapshot. This is the full snapshot size and represents the size of all the blocks that were written to the source volume at the time the snapshot was created.

    " } }, "documentation":"

    Contains the details of an Amazon RDS DB snapshot.

    This data type is used as a response element in the DescribeDBSnapshots action.

    ", @@ -11792,6 +11844,12 @@ "ENABLED" ] }, + "IAMRoleArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws[a-z-]*:iam::[0-9]*:role/.*" + }, "IPRange":{ "type":"structure", "members":{ @@ -12968,6 +13026,10 @@ "MasterUserAuthenticationType":{ "shape":"MasterUserAuthenticationType", "documentation":"

    Specifies the authentication type for the master user. With IAM master user authentication, you can change the master DB user to use IAM database authentication.

    You can specify one of the following values:

    • password - Use standard database authentication with a password.

    • iam-db-auth - Use IAM database authentication for the master user.

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    This option is only valid for RDS for PostgreSQL and Aurora PostgreSQL engines.

    " + }, + "EngineLifecycleSupport":{ + "shape":"String", + "documentation":"

    The lifecycle type for this DB cluster.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support or to opt out. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    " } }, "documentation":"

    " @@ -13287,6 +13349,10 @@ "MasterUserAuthenticationType":{ "shape":"MasterUserAuthenticationType", "documentation":"

    Specifies the authentication type for the master user. With IAM master user authentication, you can change the master DB user to use IAM database authentication.

    You can specify one of the following values:

    • password - Use standard database authentication with a password.

    • iam-db-auth - Use IAM database authentication for the master user.

    This option is only valid for RDS for PostgreSQL and Aurora PostgreSQL engines.

    " + }, + "EngineLifecycleSupport":{ + "shape":"String", + "documentation":"

    The lifecycle type for this DB instance.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the engine lifecycle support is managed by the DB cluster.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support or to opt out. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    This setting doesn't apply to RDS Custom DB instances.

    " } }, "documentation":"

    " @@ -15066,7 +15132,7 @@ "documentation":"

    The name of the DB cluster to disassociate the IAM role from.

    " }, "RoleArn":{ - "shape":"String", + "shape":"IAMRoleArn", "documentation":"

    The Amazon Resource Name (ARN) of the IAM role to disassociate from the Aurora DB cluster, for example arn:aws:iam::123456789012:role/AuroraAccessRole.

    " }, "FeatureName":{ @@ -15566,11 +15632,15 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "TagSpecifications":{ "shape":"TagSpecificationList", "documentation":"

    Tags to assign to resources associated with the DB cluster.

    Valid Values:

    • cluster-auto-backup - The DB cluster's automated backup.

    " + }, + "AssociatedRoles":{ + "shape":"DBClusterAssociatedRoles", + "documentation":"

    A list of Amazon Web Services Identity and Access Management (IAM) roles to associate with the DB cluster when it's restored from Amazon S3. Each role grants the DB cluster permission to access other Amazon Web Services on your behalf. For each role, specify a role ARN and, optionally, the feature name (such as s3Import, s3Export, or Lambda).

    " } } }, @@ -15731,7 +15801,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "TagSpecifications":{ "shape":"TagSpecificationList", @@ -15744,6 +15814,10 @@ "EnableInternetAccessGateway":{ "shape":"BooleanOptional", "documentation":"

    Specifies that the restored DB cluster should use internet-based connectivity through an internet access gateway. This allows clients to connect to the cluster over the internet without requiring a VPC.

    This parameter must be used together with EnableVPCNetworking set to false. When both parameters are specified, IAM database authentication is required. You must also specify EnableIAMDatabaseAuthentication.

    Valid for Cluster Type: Aurora PostgreSQL clusters

    " + }, + "AssociatedRoles":{ + "shape":"DBClusterAssociatedRoles", + "documentation":"

    A list of Amazon Web Services Identity and Access Management (IAM) roles to associate with the DB cluster when it's restored from a snapshot. Each role grants the DB cluster permission to access other Amazon Web Services on your behalf. For each role, specify a role ARN and, optionally, the feature name (such as s3Import, s3Export, or Lambda).

    Valid for Cluster Type: Aurora DB clusters only

    " } }, "documentation":"

    " @@ -15898,7 +15972,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB cluster.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB cluster into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB cluster to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB cluster into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB cluster past the end of standard support for that engine version. For more information, see the following sections:

    Valid for Cluster Type: Aurora DB clusters and Multi-AZ DB clusters

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "TagSpecifications":{ "shape":"TagSpecificationList", @@ -15911,6 +15985,10 @@ "EnableInternetAccessGateway":{ "shape":"BooleanOptional", "documentation":"

    Specifies that the restored DB cluster should use internet-based connectivity through an internet access gateway. This allows clients to connect to the cluster over the internet without requiring a VPC.

    This parameter must be used together with EnableVPCNetworking set to false. When both parameters are specified, IAM database authentication is required. You must also specify EnableIAMDatabaseAuthentication.

    Valid for Cluster Type: Aurora PostgreSQL clusters

    " + }, + "AssociatedRoles":{ + "shape":"DBClusterAssociatedRoles", + "documentation":"

    A list of Amazon Web Services Identity and Access Management (IAM) roles to associate with the DB cluster when it's restored to a point in time. Each role grants the DB cluster permission to access other Amazon Web Services on your behalf. For each role, specify a role ARN and, optionally, the feature name (such as s3Import, s3Export, or Lambda).

    Valid for Cluster Type: Aurora DB clusters only

    " } }, "documentation":"

    " @@ -16096,7 +16174,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the life cycle type is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the engine lifecycle support is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "AdditionalStorageVolumes":{ "shape":"AdditionalStorageVolumesList", @@ -16341,7 +16419,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the life cycle type is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the engine lifecycle support is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "AdditionalStorageVolumes":{ "shape":"AdditionalStorageVolumesList", @@ -16550,7 +16628,7 @@ }, "EngineLifecycleSupport":{ "shape":"String", - "documentation":"

    The life cycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the life cycle type is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " + "documentation":"

    The lifecycle type for this DB instance.

    By default, this value is set to open-source-rds-extended-support, which enrolls your DB instance into Amazon RDS Extended Support. At the end of standard support, you can avoid charges for Extended Support by setting the value to open-source-rds-extended-support-disabled. In this case, RDS automatically upgrades your restored DB instance to a higher engine version, if the major engine version is past its end of standard support date.

    You can use this setting to enroll your DB instance into Amazon RDS Extended Support. With RDS Extended Support, you can run the selected major engine version on your DB instance past the end of standard support for that engine version. For more information, see Amazon RDS Extended Support with Amazon RDS in the Amazon RDS User Guide.

    This setting applies only to RDS for MySQL and RDS for PostgreSQL. For Amazon Aurora DB instances, the engine lifecycle support is managed by the DB cluster.

    Valid Values: open-source-rds-extended-support | open-source-rds-extended-support-disabled

    Default: open-source-rds-extended-support

    " }, "AdditionalStorageVolumes":{ "shape":"AdditionalStorageVolumesList", diff --git a/services/rds/src/test/java/software/amazon/awssdk/services/rds/internal/PresignRequestHandlerTest.java b/services/rds/src/test/java/software/amazon/awssdk/services/rds/internal/PresignRequestHandlerTest.java index fff1e649fc40..866f4b03dc58 100644 --- a/services/rds/src/test/java/software/amazon/awssdk/services/rds/internal/PresignRequestHandlerTest.java +++ b/services/rds/src/test/java/software/amazon/awssdk/services/rds/internal/PresignRequestHandlerTest.java @@ -100,6 +100,9 @@ public void testExpectations(TestCase testCase) { if (testCase.expectedUri != null) { assertEquals(normalize(URI.create(testCase.expectedUri)), normalize(presignedUrlAsUri)); } + if (testCase.expectedPresignedUrlHost != null) { + assertEquals(testCase.expectedPresignedUrlHost, presignedUrlAsUri.getHost()); + } } else { assertFalse(rawQueryParameters.containsKey("PreSignedUrl")); } @@ -169,6 +172,24 @@ public static List testCases() { builder("StartDBInstanceAutomatedBackupsReplication Without SourceRegion Does NOT Send PresignedUrl") .clientConsumer(c -> c.startDBInstanceAutomatedBackupsReplication(r -> r.kmsKeyId(TEST_KMS_KEY_ID))) .shouldContainPreSignedUrl(false) + .build(), + + builder("CopyDbClusterSnapshot - With FIPS enabled resolves to fips endpoint") + .clientConfigure(c -> c.region(Region.US_EAST_1).fipsEnabled(true)) + .clientConsumer(c -> c.copyDBClusterSnapshot(makeTestRequestBuilder() + .sourceRegion("us-west-2") + .build())) + .shouldContainPreSignedUrl(true) + .expectedPresignedUrlHost("rds-fips.us-west-2.amazonaws.com") + .build(), + + builder("CopyDbClusterSnapshot - With dualstack enabled resolves to dualstack endpoint") + .clientConfigure(c -> c.region(Region.US_EAST_1).dualstackEnabled(true)) + .clientConsumer(c -> c.copyDBClusterSnapshot(makeTestRequestBuilder() + .sourceRegion("us-west-2") + .build())) + .shouldContainPreSignedUrl(true) + .expectedPresignedUrlHost("rds.us-west-2.api.aws") .build() ); } @@ -296,6 +317,7 @@ static class TestCase { private final String expectedDestinationRegion; private final Clock signingClockOverride; private final String expectedUri; + private final String expectedPresignedUrlHost; TestCase(TestCaseBuilder builder) { this.name = Validate.notNull(builder.name, "name"); @@ -305,6 +327,7 @@ static class TestCase { this.expectedDestinationRegion = builder.expectedDestinationRegion; this.signingClockOverride = builder.signingClockOverride; this.expectedUri = builder.expectedUri; + this.expectedPresignedUrlHost = builder.expectedPresignedUrlHost; } } @@ -316,6 +339,7 @@ static class TestCaseBuilder { private String expectedDestinationRegion; private Clock signingClockOverride; private String expectedUri; + private String expectedPresignedUrlHost; private TestCaseBuilder name(String name) { this.name = name; @@ -352,6 +376,11 @@ public TestCaseBuilder expectedUri(String expectedUri) { return this; } + public TestCaseBuilder expectedPresignedUrlHost(String expectedPresignedUrlHost) { + this.expectedPresignedUrlHost = expectedPresignedUrlHost; + return this; + } + public TestCase build() { return new TestCase(this); } diff --git a/services/rdsdata/pom.xml b/services/rdsdata/pom.xml index 899e2028f663..aee94949eada 100644 --- a/services/rdsdata/pom.xml +++ b/services/rdsdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rdsdata AWS Java SDK :: Services :: RDS Data diff --git a/services/rdsdata/src/main/resources/codegen-resources/customization.config b/services/rdsdata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/rdsdata/src/main/resources/codegen-resources/customization.config +++ b/services/rdsdata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/rdsdata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rdsdata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..69c98e40aadb --- /dev/null +++ b/services/rdsdata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-data-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-data.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rds-data.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rdsdata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rdsdata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d7305cfb77db..000000000000 --- a/services/rdsdata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-data-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rds-data.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rds-data.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/redshift/pom.xml b/services/redshift/pom.xml index 7b3f931b2298..ed5a6f9da3ed 100644 --- a/services/redshift/pom.xml +++ b/services/redshift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT redshift AWS Java SDK :: Services :: Amazon Redshift diff --git a/services/redshift/src/main/resources/codegen-resources/customization.config b/services/redshift/src/main/resources/codegen-resources/customization.config index 2c9b5b0e6292..41ba62504dea 100644 --- a/services/redshift/src/main/resources/codegen-resources/customization.config +++ b/services/redshift/src/main/resources/codegen-resources/customization.config @@ -24,8 +24,6 @@ "excludedSimpleMethods": [ "describeTableRestoreStatus", "describeClusterSecurityGroups" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/redshift/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/redshift/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a0b2e8c1f9a0 --- /dev/null +++ b/services/redshift/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/redshift/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/redshift/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ddfe4576d1bc..000000000000 --- a/services/redshift/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://redshift.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://redshift-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://redshift.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/redshift/src/main/resources/codegen-resources/paginators-1.json b/services/redshift/src/main/resources/codegen-resources/paginators-1.json index 130a29747441..81a95dae279e 100644 --- a/services/redshift/src/main/resources/codegen-resources/paginators-1.json +++ b/services/redshift/src/main/resources/codegen-resources/paginators-1.json @@ -144,6 +144,12 @@ "output_token": "Marker", "result_key": "OrderableClusterOptions" }, + "DescribeQev2IdcApplications": { + "input_token": "Marker", + "limit_key": "MaxRecords", + "output_token": "Marker", + "result_key": "Qev2IdcApplications" + }, "DescribeRedshiftIdcApplications": { "input_token": "Marker", "limit_key": "MaxRecords", diff --git a/services/redshift/src/main/resources/codegen-resources/service-2.json b/services/redshift/src/main/resources/codegen-resources/service-2.json index aec7771805b1..a172a61a6262 100644 --- a/services/redshift/src/main/resources/codegen-resources/service-2.json +++ b/services/redshift/src/main/resources/codegen-resources/service-2.json @@ -496,6 +496,25 @@ ], "documentation":"

    Creates a zero-ETL integration or S3 event integration with Amazon Redshift.

    " }, + "CreateQev2IdcApplication":{ + "name":"CreateQev2IdcApplication", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateQev2IdcApplicationMessage"}, + "output":{ + "shape":"CreateQev2IdcApplicationResult", + "resultWrapper":"CreateQev2IdcApplicationResult" + }, + "errors":[ + {"shape":"Qev2IdcApplicationAlreadyExistsFault"}, + {"shape":"DependentServiceUnavailableFault"}, + {"shape":"UnsupportedOperationFault"}, + {"shape":"DependentServiceAccessDeniedFault"} + ], + "documentation":"

    Creates an Amazon Redshift Query Editor (QEV2) IAM Identity Center application.

    " + }, "CreateRedshiftIdcApplication":{ "name":"CreateRedshiftIdcApplication", "http":{ @@ -842,6 +861,21 @@ ], "documentation":"

    Deletes a partner integration from a cluster. Data can still flow to the cluster until the integration is deleted at the partner's website.

    " }, + "DeleteQev2IdcApplication":{ + "name":"DeleteQev2IdcApplication", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteQev2IdcApplicationMessage"}, + "errors":[ + {"shape":"Qev2IdcApplicationNotExistsFault"}, + {"shape":"DependentServiceUnavailableFault"}, + {"shape":"UnsupportedOperationFault"}, + {"shape":"DependentServiceAccessDeniedFault"} + ], + "documentation":"

    Deletes an Amazon Redshift Query Editor (QEV2) IAM Identity Center application.

    " + }, "DeleteRedshiftIdcApplication":{ "name":"DeleteRedshiftIdcApplication", "http":{ @@ -1426,6 +1460,25 @@ ], "documentation":"

    Returns information about the partner integrations defined for a cluster.

    " }, + "DescribeQev2IdcApplications":{ + "name":"DescribeQev2IdcApplications", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeQev2IdcApplicationsMessage"}, + "output":{ + "shape":"DescribeQev2IdcApplicationsResult", + "resultWrapper":"DescribeQev2IdcApplicationsResult" + }, + "errors":[ + {"shape":"Qev2IdcApplicationNotExistsFault"}, + {"shape":"DependentServiceUnavailableFault"}, + {"shape":"UnsupportedOperationFault"}, + {"shape":"DependentServiceAccessDeniedFault"} + ], + "documentation":"

    Lists the Amazon Redshift Query Editor (QEV2) IAM Identity Center applications. To retrieve additional results, use the MaxRecords and Marker parameters.

    " + }, "DescribeRedshiftIdcApplications":{ "name":"DescribeRedshiftIdcApplications", "http":{ @@ -2182,6 +2235,25 @@ ], "documentation":"

    Modifies the lakehouse configuration for a cluster. This operation allows you to manage Amazon Redshift federated permissions and Amazon Web Services IAM Identity Center trusted identity propagation.

    " }, + "ModifyQev2IdcApplication":{ + "name":"ModifyQev2IdcApplication", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ModifyQev2IdcApplicationMessage"}, + "output":{ + "shape":"ModifyQev2IdcApplicationResult", + "resultWrapper":"ModifyQev2IdcApplicationResult" + }, + "errors":[ + {"shape":"Qev2IdcApplicationNotExistsFault"}, + {"shape":"DependentServiceUnavailableFault"}, + {"shape":"UnsupportedOperationFault"}, + {"shape":"DependentServiceAccessDeniedFault"} + ], + "documentation":"

    Modifies an Amazon Redshift Query Editor (QEV2) IAM Identity Center application.

    " + }, "ModifyRedshiftIdcApplication":{ "name":"ModifyRedshiftIdcApplication", "http":{ @@ -2431,7 +2503,7 @@ {"shape":"DependentServiceUnavailableFault"}, {"shape":"ReservedNodeAlreadyExistsFault"} ], - "documentation":"

    Changes the size of the cluster. You can change the cluster's type, or change the number or type of nodes. The default behavior is to use the elastic resize method. With an elastic resize, your cluster is available for read and write operations more quickly than with the classic resize method.

    Elastic resize operations have the following restrictions:

    • You can only resize clusters of the following types:

      • dc2.large

      • dc2.8xlarge

      • rg.xlarge

      • rg.4xlarge

      • ra3.large

      • ra3.xlplus

      • ra3.4xlarge

      • ra3.16xlarge

    • The type of nodes that you add must match the node type for the cluster.

    " + "documentation":"

    Changes the size of the cluster. You can change the cluster's type, or change the number or type of nodes. The default behavior is to use the elastic resize method. With an elastic resize, your cluster is available for read and write operations more quickly than with the classic resize method.

    Elastic resize operations have the following restrictions:

    • You can only resize clusters of the following types:

      • dc2.large

      • dc2.8xlarge

      • rg.large

      • rg.xlarge

      • rg.4xlarge

      • rg.12xlarge

      • ra3.large

      • ra3.xlplus

      • ra3.4xlarge

      • ra3.16xlarge

    • The type of nodes that you add must match the node type for the cluster.

    " }, "RestoreFromClusterSnapshot":{ "name":"RestoreFromClusterSnapshot", @@ -3481,6 +3553,10 @@ "ExtraComputeForAutomaticOptimization":{ "shape":"String", "documentation":"

    A boolean value that, if true, indicates that the cluster allocates additional compute resources to run automatic optimization operations.

    Default: false

    " + }, + "LoggingPublishStatus":{ + "shape":"LoggingPublishStatus", + "documentation":"

    The status of system table publishing for the cluster. This field is present only when system table publishing is configured.

    " } }, "documentation":"

    Describes a cluster.

    ", @@ -4267,7 +4343,7 @@ }, "NodeType":{ "shape":"String", - "documentation":"

    The node type to be provisioned for the cluster. For information about node types, go to Working with Clusters in the Amazon Redshift Cluster Management Guide.

    Valid Values: dc2.large | dc2.8xlarge| rg.xlarge | rg.4xlarge | ra3.large | ra3.xlplus | ra3.4xlarge | ra3.16xlarge

    " + "documentation":"

    The node type to be provisioned for the cluster. For information about node types, go to Working with Clusters in the Amazon Redshift Cluster Management Guide.

    Valid Values: dc2.large | dc2.8xlarge | rg.large | rg.xlarge | rg.4xlarge | rg.12xlarge | ra3.large | ra3.xlplus | ra3.4xlarge | ra3.16xlarge

    " }, "MasterUsername":{ "shape":"String", @@ -4779,6 +4855,38 @@ } } }, + "CreateQev2IdcApplicationMessage":{ + "type":"structure", + "required":[ + "IdcInstanceArn", + "Qev2IdcApplicationName", + "IdcDisplayName" + ], + "members":{ + "IdcInstanceArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM Identity Center instance used to create the Amazon Redshift Query Editor (QEV2) managed application.

    " + }, + "Qev2IdcApplicationName":{ + "shape":"Qev2IdcApplicationName", + "documentation":"

    The name of the Amazon Redshift Query Editor (QEV2) application in IAM Identity Center.

    " + }, + "IdcDisplayName":{ + "shape":"IdcDisplayNameString", + "documentation":"

    The display name for the Amazon Redshift Query Editor (QEV2) IAM Identity Center application. It appears in the console.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of tags to associate with the application. Tags are key-value pairs that you can use to organize and identify your resources.

    " + } + } + }, + "CreateQev2IdcApplicationResult":{ + "type":"structure", + "members":{ + "Qev2IdcApplication":{"shape":"Qev2IdcApplication"} + } + }, "CreateRedshiftIdcApplicationMessage":{ "type":"structure", "required":[ @@ -5430,6 +5538,16 @@ } } }, + "DeleteQev2IdcApplicationMessage":{ + "type":"structure", + "required":["Qev2IdcApplicationArn"], + "members":{ + "Qev2IdcApplicationArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the Amazon Redshift Query Editor (QEV2) IAM Identity Center application to delete.

    " + } + } + }, "DeleteRedshiftIdcApplicationMessage":{ "type":"structure", "required":["RedshiftIdcApplicationArn"], @@ -6345,6 +6463,36 @@ } } }, + "DescribeQev2IdcApplicationsMessage":{ + "type":"structure", + "members":{ + "Qev2IdcApplicationArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the Amazon Redshift Query Editor (QEV2) application that integrates with IAM Identity Center.

    " + }, + "MaxRecords":{ + "shape":"IntegerOptional", + "documentation":"

    The maximum number of response records to return in each call. If the number of remaining response records exceeds the specified MaxRecords value, a value is returned in a marker field of the response. You can retrieve the next set of records by retrying the command with the returned marker value.

    " + }, + "Marker":{ + "shape":"String", + "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned marker value in the Marker parameter and retrying the command. If the Marker field is empty, all response records have been retrieved for the request.

    " + } + } + }, + "DescribeQev2IdcApplicationsResult":{ + "type":"structure", + "members":{ + "Qev2IdcApplications":{ + "shape":"Qev2IdcApplicationList", + "documentation":"

    The list of Amazon Redshift Query Editor (QEV2) IAM Identity Center applications.

    " + }, + "Marker":{ + "shape":"String", + "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned marker value in the Marker parameter and retrying the command. If the Marker field is empty, all response records have been retrieved for the request.

    " + } + } + }, "DescribeRedshiftIdcApplicationsMessage":{ "type":"structure", "members":{ @@ -6659,6 +6807,14 @@ "ClusterIdentifier":{ "shape":"String", "documentation":"

    The identifier of the cluster on which logging is to be stopped.

    Example: examplecluster

    " + }, + "LogDestinationType":{ + "shape":"LogDestinationType", + "documentation":"

    The log destination type. An enum with possible values of s3, cloudwatch, and s3table. When set to s3table, stops system table publishing. When omitted, the operation disables audit logging.

    " + }, + "LogExports":{ + "shape":"LogTypeList", + "documentation":"

    The collection of log types to stop exporting. When LogDestinationType is s3table, the values are the names of the system tables to stop publishing. Omitting this parameter or passing all stops publishing all system tables.

    " } }, "documentation":"

    " @@ -6772,11 +6928,19 @@ }, "LogDestinationType":{ "shape":"LogDestinationType", - "documentation":"

    The log destination type. An enum with possible values of s3 and cloudwatch.

    " + "documentation":"

    The log destination type. An enum with possible values of s3, cloudwatch, and s3table.

    " }, "LogExports":{ "shape":"LogTypeList", - "documentation":"

    The collection of exported log types. Possible values are connectionlog, useractivitylog, and userlog.

    " + "documentation":"

    The collection of exported log types. When LogDestinationType is s3 or cloudwatch, possible values are connectionlog, useractivitylog, and userlog. When LogDestinationType is s3table, the values are the names of the system tables to publish. Omitting this parameter, passing an empty list, or including the value all publishes all current and future system tables.

    " + }, + "S3TableKmsKeyId":{ + "shape":"String", + "documentation":"

    The identifier of a customer managed KMS key used to encrypt the S3 tables. This parameter is valid only when LogDestinationType is s3table.

    " + }, + "S3TableGranularity":{ + "shape":"String", + "documentation":"

    The scope of system table publishing. Valid values are cluster and account. A value of cluster scopes publishing to the individual cluster. A value of account scopes publishing to the Amazon Web Services account. This parameter is valid only when LogDestinationType is s3table.

    " } }, "documentation":"

    " @@ -8417,13 +8581,24 @@ "type":"string", "enum":[ "s3", - "cloudwatch" + "cloudwatch", + "s3table" ] }, "LogTypeList":{ "type":"list", "member":{"shape":"String"} }, + "LoggingPublishStatus":{ + "type":"structure", + "members":{ + "S3Tables":{ + "shape":"S3TablePublishStatus", + "documentation":"

    The status of system table publishing to S3 Tables.

    " + } + }, + "documentation":"

    Describes the system table publishing status for a cluster.

    " + }, "LoggingStatus":{ "type":"structure", "members":{ @@ -8453,11 +8628,15 @@ }, "LogDestinationType":{ "shape":"LogDestinationType", - "documentation":"

    The log destination type. An enum with possible values of s3 and cloudwatch.

    " + "documentation":"

    The log destination type. An enum with possible values of s3, cloudwatch, and s3table.

    " }, "LogExports":{ "shape":"LogTypeList", - "documentation":"

    The collection of exported log types. Possible values are connectionlog, useractivitylog, and userlog.

    " + "documentation":"

    The collection of exported log types. When LogDestinationType is s3 or cloudwatch, possible values are connectionlog, useractivitylog, and userlog. When LogDestinationType is s3table, the values are the names of the system tables being published.

    " + }, + "S3Tables":{ + "shape":"S3TablePublishStatus", + "documentation":"

    The status of system table publishing to S3 Tables. This field is populated only when system table publishing is active.

    " } }, "documentation":"

    Describes the status of logging for a cluster.

    " @@ -8644,7 +8823,7 @@ }, "NodeType":{ "shape":"String", - "documentation":"

    The new node type of the cluster. If you specify a new node type, you must also specify the number of nodes parameter.

    For more information about resizing clusters, go to Resizing Clusters in Amazon Redshift in the Amazon Redshift Cluster Management Guide.

    Valid Values: dc2.large | dc2.8xlarge| rg.xlarge | rg.4xlarge | ra3.large | ra3.xlplus | ra3.4xlarge | ra3.16xlarge

    " + "documentation":"

    The new node type of the cluster. If you specify a new node type, you must also specify the number of nodes parameter.

    For more information about resizing clusters, go to Resizing Clusters in Amazon Redshift in the Amazon Redshift Cluster Management Guide.

    Valid Values: dc2.large | dc2.8xlarge | rg.large | rg.xlarge | rg.4xlarge | rg.12xlarge | ra3.large | ra3.xlplus | ra3.4xlarge | ra3.16xlarge

    " }, "NumberOfNodes":{ "shape":"IntegerOptional", @@ -8997,6 +9176,26 @@ } } }, + "ModifyQev2IdcApplicationMessage":{ + "type":"structure", + "required":["Qev2IdcApplicationArn"], + "members":{ + "Qev2IdcApplicationArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the Amazon Redshift Query Editor (QEV2) application that integrates with IAM Identity Center.

    " + }, + "IdcDisplayName":{ + "shape":"IdcDisplayNameString", + "documentation":"

    The display name for the Amazon Redshift Query Editor (QEV2) IAM Identity Center application. It appears in the console.

    " + } + } + }, + "ModifyQev2IdcApplicationResult":{ + "type":"structure", + "members":{ + "Qev2IdcApplication":{"shape":"Qev2IdcApplication"} + } + }, "ModifyRedshiftIdcApplicationMessage":{ "type":"structure", "required":["RedshiftIdcApplicationArn"], @@ -9659,6 +9858,73 @@ } } }, + "Qev2IdcApplication":{ + "type":"structure", + "members":{ + "IdcInstanceArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the IAM Identity Center instance that the Amazon Redshift Query Editor (QEV2) application integrates with.

    " + }, + "Qev2IdcApplicationName":{ + "shape":"Qev2IdcApplicationName", + "documentation":"

    The name of the Amazon Redshift Query Editor (QEV2) application in IAM Identity Center.

    " + }, + "Qev2IdcApplicationArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the Amazon Redshift Query Editor (QEV2) application that integrates with IAM Identity Center.

    " + }, + "IdcManagedApplicationArn":{ + "shape":"String", + "documentation":"

    The Amazon Resource Name (ARN) for the Amazon Redshift Query Editor (QEV2) IAM Identity Center managed application.

    " + }, + "IdcOnboardStatus":{ + "shape":"String", + "documentation":"

    The onboarding status for the Amazon Redshift Query Editor (QEV2) IAM Identity Center application.

    " + }, + "IdcDisplayName":{ + "shape":"IdcDisplayNameString", + "documentation":"

    The display name for the Amazon Redshift Query Editor (QEV2) IAM Identity Center application. It appears in the console.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of tags associated with the application. Tags are key-value pairs that you can use to organize and identify your resources.

    " + } + }, + "documentation":"

    Contains configuration and status information for an Amazon Redshift Query Editor (QEV2) application that is registered with IAM Identity Center.

    ", + "wrapper":true + }, + "Qev2IdcApplicationAlreadyExistsFault":{ + "type":"structure", + "members":{}, + "documentation":"

    The Amazon Redshift Query Editor (QEV2) IAM Identity Center application already exists. Use a different application name or describe existing applications to find the ARN.

    ", + "error":{ + "code":"Qev2IdcApplicationAlreadyExists", + "httpStatusCode":400, + "senderFault":true + }, + "exception":true + }, + "Qev2IdcApplicationList":{ + "type":"list", + "member":{"shape":"Qev2IdcApplication"} + }, + "Qev2IdcApplicationName":{ + "type":"string", + "max":63, + "min":1, + "pattern":"[a-z][a-z0-9]*(-[a-z0-9]+)*" + }, + "Qev2IdcApplicationNotExistsFault":{ + "type":"structure", + "members":{}, + "documentation":"

    The specified Amazon Redshift Query Editor (QEV2) IAM Identity Center application doesn't exist. Verify that the application ARN is correct and that the application exists in this Region.

    ", + "error":{ + "code":"Qev2IdcApplicationNotExists", + "httpStatusCode":404, + "senderFault":true + }, + "exception":true + }, "ReadWriteAccess":{ "type":"structure", "required":["Authorization"], @@ -10895,6 +11161,37 @@ "max":256, "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*" }, + "S3TableLastIngestionTimeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "S3TablePublishStatus":{ + "type":"structure", + "members":{ + "S3Tables":{ + "shape":"LogTypeList", + "documentation":"

    The system tables currently being published.

    " + }, + "S3TableNamespace":{ + "shape":"String", + "documentation":"

    The namespace in the S3 table bucket that holds the published tables.

    " + }, + "S3TableGranularity":{ + "shape":"String", + "documentation":"

    The scope of system table publishing in effect. Possible values are cluster and account.

    " + }, + "EnabledAll":{ + "shape":"BooleanOptional", + "documentation":"

    true if the cluster is enrolled in all current and future system tables rather than an explicit subset.

    " + }, + "LastIngestionTimes":{ + "shape":"S3TableLastIngestionTimeMap", + "documentation":"

    A map whose keys are the names of the published system tables and whose values are the time each table last received data. Use this to judge data freshness.

    " + } + }, + "documentation":"

    Describes the status of system table publishing to S3 Tables for a cluster.

    " + }, "SNSInvalidTopicFault":{ "type":"structure", "members":{}, diff --git a/services/redshiftdata/pom.xml b/services/redshiftdata/pom.xml index 63d8d958edcc..7d26f82ec04a 100644 --- a/services/redshiftdata/pom.xml +++ b/services/redshiftdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT redshiftdata AWS Java SDK :: Services :: Redshift Data diff --git a/services/redshiftdata/src/main/resources/codegen-resources/customization.config b/services/redshiftdata/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/redshiftdata/src/main/resources/codegen-resources/customization.config +++ b/services/redshiftdata/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/redshiftdata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/redshiftdata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ed65509db0fb --- /dev/null +++ b/services/redshiftdata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-data-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-data.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-data.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/redshiftdata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/redshiftdata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 35b9150d3013..000000000000 --- a/services/redshiftdata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-data-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-data-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-data.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://redshift-data.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/redshiftdata/src/main/resources/codegen-resources/paginators-1.json b/services/redshiftdata/src/main/resources/codegen-resources/paginators-1.json index 8f610ac3898d..7501183352a8 100644 --- a/services/redshiftdata/src/main/resources/codegen-resources/paginators-1.json +++ b/services/redshiftdata/src/main/resources/codegen-resources/paginators-1.json @@ -28,6 +28,12 @@ "limit_key": "MaxResults", "result_key": "Schemas" }, + "ListSessions": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Sessions" + }, "ListStatements": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/redshiftdata/src/main/resources/codegen-resources/service-2.json b/services/redshiftdata/src/main/resources/codegen-resources/service-2.json index b2242306d097..b77bdc1f981c 100644 --- a/services/redshiftdata/src/main/resources/codegen-resources/service-2.json +++ b/services/redshiftdata/src/main/resources/codegen-resources/service-2.json @@ -61,6 +61,7 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ActiveWaitingRequestsExceededException"}, {"shape":"InternalServerException"} ], "documentation":"

    Describes the details about a specific instance when a query was run by the Amazon Redshift Data API. The information includes when the query started, when it finished, the query status, the number of rows returned, and the SQL statement.

    For more information about the Amazon Redshift Data API and CLI usage examples, see Using the Amazon Redshift Data API in the Amazon Redshift Management Guide.

    ", @@ -113,6 +114,7 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ActiveWaitingRequestsExceededException"}, {"shape":"InternalServerException"} ], "documentation":"

    Fetches the temporarily cached result of an SQL statement in JSON format. The ExecuteStatement or BatchExecuteStatement operation that ran the SQL statement must have specified ResultFormat as JSON , or let the format default to JSON. A token is returned to page through the statement results.

    For more information about the Amazon Redshift Data API and CLI usage examples, see Using the Amazon Redshift Data API in the Amazon Redshift Management Guide.

    ", @@ -129,6 +131,7 @@ "errors":[ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ActiveWaitingRequestsExceededException"}, {"shape":"InternalServerException"} ], "documentation":"

    Fetches the temporarily cached result of an SQL statement in CSV format. The ExecuteStatement or BatchExecuteStatement operation that ran the SQL statement must have specified ResultFormat as CSV. A token is returned to page through the statement results.

    For more information about the Amazon Redshift Data API and CLI usage examples, see Using the Amazon Redshift Data API in the Amazon Redshift Management Guide.

    ", @@ -170,6 +173,22 @@ "documentation":"

    Lists the schemas in a database. A token is returned to page through the schema list. Depending on the authorization method, use one of the following combinations of request parameters:

    • Secrets Manager - when connecting to a cluster, provide the secret-arn of a secret stored in Secrets Manager which has username and password. The specified secret contains credentials to connect to the database you specify. When you are connecting to a cluster, you also supply the database name, If you provide a cluster identifier (dbClusterIdentifier), it must match the cluster identifier stored in the secret. When you are connecting to a serverless workgroup, you also supply the database name.

    • Temporary credentials - when connecting to your data warehouse, choose one of the following options:

      • When connecting to a serverless workgroup, specify the workgroup name and database name. The database user name is derived from the IAM identity. For example, arn:iam::123456789012:user:foo has the database user name IAM:foo. Also, permission to call the redshift-serverless:GetCredentials operation is required.

      • When connecting to a cluster as an IAM identity, specify the cluster identifier and the database name. The database user name is derived from the IAM identity. For example, arn:iam::123456789012:user:foo has the database user name IAM:foo. Also, permission to call the redshift:GetClusterCredentialsWithIAM operation is required.

      • When connecting to a cluster as a database user, specify the cluster identifier, the database name, and the database user name. Also, permission to call the redshift:GetClusterCredentials operation is required.

    For more information about the Amazon Redshift Data API and CLI usage examples, see Using the Amazon Redshift Data API in the Amazon Redshift Management Guide.

    ", "readonly":true }, + "ListSessions":{ + "name":"ListSessions", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListSessionsRequest"}, + "output":{"shape":"ListSessionsResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InternalServerException"} + ], + "documentation":"

    Lists the sessions that the caller created in the last 24 hours. By default, only sessions with a status of AVAILABLE or BUSY are returned. You can filter the results by session status, compute target (cluster or serverless workgroup), or database. To retrieve the metadata for a single session, provide the SessionId parameter. Use NextToken to page through the session list.

    Returns only the sessions that the caller created. When identity-enhanced role sessions are used, you must provide either the ClusterIdentifier or WorkgroupName parameter to ensure that the AWS IAM Identity Center user can only access the Amazon Redshift IAM Identity Center applications they are assigned. For more information, see Trusted identity propagation overview.

    ", + "readonly":true + }, "ListStatements":{ "name":"ListStatements", "http":{ @@ -222,6 +241,14 @@ "documentation":"

    The number of active statements exceeds the limit.

    ", "exception":true }, + "ActiveWaitingRequestsExceededException":{ + "type":"structure", + "members":{ + "Message":{"shape":"String"} + }, + "documentation":"

    The number of active requests with WaitTimeSeconds for the same SQL statement exceeds the limit.

    ", + "exception":true + }, "BatchExecuteStatementException":{ "type":"structure", "required":[ @@ -245,7 +272,7 @@ "members":{ "Sqls":{ "shape":"SqlList", - "documentation":"

    One or more SQL statements to run. The SQL statements are run as a single transaction. They run serially in the order of the array. Subsequent SQL statements don't start until the previous statement in the array completes. If any SQL statement fails, then because they are run as one transaction, all work is rolled back.

    " + "documentation":"

    One or more SQL statements to run. The SQL statements run serially in the order of the array. Subsequent SQL statements don't start until the previous statement in the array completes. By default, the SQL statements are run as a single transaction. If any SQL statement fails, all work is rolled back. To change this behavior, see the ExecutionMode parameter.

    " }, "ClusterIdentifier":{ "shape":"ClusterIdentifierString", @@ -273,7 +300,7 @@ }, "Parameters":{ "shape":"SqlParametersList", - "documentation":"

    The parameters for the SQL statements. The parameters are shared across all SQL statements in the batch.

    " + "documentation":"

    The parameters for the SQL statements. The parameters are available to all SQL statements in the batch. Each statement can reference any subset of the provided parameters. Each provided parameter must be referenced by at least one SQL statement in the batch.

    " }, "WorkgroupName":{ "shape":"WorkgroupNameString", @@ -295,6 +322,14 @@ "SessionId":{ "shape":"UUID", "documentation":"

    The session identifier of the query.

    " + }, + "ExecutionMode":{ + "shape":"ExecutionMode", + "documentation":"

    Determines how the SQL statements in the batch are run. If set to TRANSACTION (the default), all SQL statements are run as a single transaction and they are committed or rolled back together. If set to AUTO_COMMIT, each SQL statement is committed individually, and a failure of one statement does not affect the others.

    " + }, + "WaitTimeSeconds":{ + "shape":"WaitTimeSeconds", + "documentation":"

    The number of seconds to wait for all SQL statements in the batch to complete execution before returning the response. If the SQL statements do not complete within the specified time, the response returns the current status. The maximum value is 30 seconds.

    " } } }, @@ -336,6 +371,18 @@ "SessionId":{ "shape":"UUID", "documentation":"

    The session identifier of the query.

    " + }, + "Status":{ + "shape":"StatementStatusString", + "documentation":"

    The status of the SQL statement. Status values are defined as follows:

    • ABORTED - The query run was stopped by the user.

    • FAILED - The query run failed.

    • FINISHED - The query has finished running.

    • PICKED - The query has been chosen to be run.

    • STARTED - The query run has started.

    • SUBMITTED - The query was submitted, but not yet processed.

    " + }, + "RedshiftPid":{ + "shape":"BoxedLong", + "documentation":"

    The process identifier from Amazon Redshift.

    " + }, + "HasResultSet":{ + "shape":"BoxedBoolean", + "documentation":"

    A value that indicates whether the statement has a result set. The result set can be empty. The value is true for an empty result set. The value is true if any substatement returns a result set.

    " } } }, @@ -477,6 +524,10 @@ "Id":{ "shape":"UUID", "documentation":"

    The identifier of the SQL statement to describe. This value is a universally unique identifier (UUID) generated by Amazon Redshift Data API. A suffix indicates the number of the SQL statement. For example, d9b6c0c9-0747-4bf4-b142-e8883122f766:2 has a suffix of :2 that indicates the second SQL statement of a batch query. This identifier is returned by BatchExecuteStatment, ExecuteStatement, and ListStatements.

    " + }, + "WaitTimeSeconds":{ + "shape":"WaitTimeSeconds", + "documentation":"

    The number of seconds to wait for the SQL statement to complete execution before returning the description. The maximum value is 30 seconds.

    " } } }, @@ -567,6 +618,10 @@ "SessionId":{ "shape":"String", "documentation":"

    The session identifier of the query.

    " + }, + "ExecutionMode":{ + "shape":"ExecutionMode", + "documentation":"

    The execution mode of the batch request. TRANSACTION indicates all SQL statements are run as a single transaction. AUTO_COMMIT indicates each SQL statement is committed individually.

    " } } }, @@ -709,6 +764,10 @@ "SessionId":{ "shape":"UUID", "documentation":"

    The session identifier of the query.

    " + }, + "WaitTimeSeconds":{ + "shape":"WaitTimeSeconds", + "documentation":"

    The number of seconds to wait for the SQL statement to complete execution before returning the response. If the SQL statement does not complete within the specified time, the response returns the current status. The maximum value is 30 seconds.

    " } } }, @@ -750,9 +809,28 @@ "SessionId":{ "shape":"UUID", "documentation":"

    The session identifier of the query.

    " + }, + "Status":{ + "shape":"StatementStatusString", + "documentation":"

    The status of the SQL statement. Status values are defined as follows:

    • ABORTED - The query run was stopped by the user.

    • FAILED - The query run failed.

    • FINISHED - The query has finished running.

    • PICKED - The query has been chosen to be run.

    • STARTED - The query run has started.

    • SUBMITTED - The query was submitted, but not yet processed.

    " + }, + "RedshiftPid":{ + "shape":"BoxedLong", + "documentation":"

    The process identifier from Amazon Redshift.

    " + }, + "HasResultSet":{ + "shape":"BoxedBoolean", + "documentation":"

    A value that indicates whether the statement has a result set. The result set can be empty. The value is true for an empty result set.

    " } } }, + "ExecutionMode":{ + "type":"string", + "enum":[ + "TRANSACTION", + "AUTO_COMMIT" + ] + }, "Field":{ "type":"structure", "members":{ @@ -803,6 +881,10 @@ "NextToken":{ "shape":"String", "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned NextToken value in the next NextToken parameter and retrying the command. If the NextToken field is empty, all response records have been retrieved for the request.

    " + }, + "WaitTimeSeconds":{ + "shape":"WaitTimeSeconds", + "documentation":"

    The number of seconds to wait for the SQL statement to complete execution before returning the result. The maximum value is 30 seconds.

    " } } }, @@ -839,6 +921,10 @@ "NextToken":{ "shape":"String", "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned NextToken value in the next NextToken parameter and retrying the command. If the NextToken field is empty, all response records have been retrieved for the request.

    " + }, + "WaitTimeSeconds":{ + "shape":"WaitTimeSeconds", + "documentation":"

    The number of seconds to wait for the SQL statement to complete execution before returning the result. The maximum value is 30 seconds.

    " } } }, @@ -984,6 +1070,57 @@ } } }, + "ListSessionsRequest":{ + "type":"structure", + "members":{ + "NextToken":{ + "shape":"String", + "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned NextToken value in the next NextToken parameter and retrying the command. If the NextToken field is empty, all response records have been retrieved for the request.

    " + }, + "MaxResults":{ + "shape":"ListStatementsLimit", + "documentation":"

    The maximum number of sessions to return in the response. If more sessions exist than fit in one response, the operation returns NextToken to paginate the results.

    " + }, + "SessionId":{ + "shape":"UUID", + "documentation":"

    The identifier of a specific session to return metadata for. This value is a universally unique identifier (UUID) generated by Amazon Redshift Data API. When you provide SessionId, you can't specify Status, ClusterIdentifier, WorkgroupName, or Database.

    " + }, + "Status":{ + "shape":"SessionStatusString", + "documentation":"

    The status of the sessions to list. If no status is specified, sessions with a status of AVAILABLE or BUSY are returned. Status values are defined as follows:

    • AVAILABLE – The session is open and ready to run a SQL statement.

    • BUSY – The session is currently running a SQL statement.

    • CLOSED – The session is closed and can no longer run SQL statements.

    " + }, + "RoleLevel":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to return all sessions created by the caller's IAM role, including sessions from previous IAM sessions. If false, only sessions created in the current IAM session are returned. The default is true.

    " + }, + "ClusterIdentifier":{ + "shape":"ClusterIdentifierString", + "documentation":"

    The cluster identifier. Only sessions on this cluster are returned. When providing ClusterIdentifier, then WorkgroupName can't be specified.

    " + }, + "WorkgroupName":{ + "shape":"WorkgroupNameString", + "documentation":"

    The serverless workgroup name or Amazon Resource Name (ARN). Only sessions on this workgroup are returned. When providing WorkgroupName, then ClusterIdentifier can't be specified.

    " + }, + "Database":{ + "shape":"String", + "documentation":"

    The name of the database. Only sessions connected to this database are returned.

    " + } + } + }, + "ListSessionsResponse":{ + "type":"structure", + "required":["Sessions"], + "members":{ + "Sessions":{ + "shape":"SessionList", + "documentation":"

    The sessions that match the request.

    " + }, + "NextToken":{ + "shape":"String", + "documentation":"

    A value that indicates the starting point for the next set of response records in a subsequent request. If a value is returned in a response, you can retrieve the next set of records by providing this returned NextToken value in the next NextToken parameter and retrying the command. If the NextToken field is empty, all response records have been retrieved for the request.

    " + } + } + }, "ListStatementsLimit":{ "type":"integer", "max":100, @@ -1169,6 +1306,73 @@ "max":86400, "min":0 }, + "SessionData":{ + "type":"structure", + "required":[ + "SessionId", + "Status", + "CreatedAt" + ], + "members":{ + "SessionId":{ + "shape":"UUID", + "documentation":"

    The session identifier. This value is a universally unique identifier (UUID) generated by Amazon Redshift Data API.

    " + }, + "Status":{ + "shape":"SessionStatusString", + "documentation":"

    The status of the session. Status values are defined as follows:

    • AVAILABLE – The session is open and ready to run a SQL statement.

    • BUSY – The session is currently running a SQL statement.

    • CLOSED – The session is closed and can no longer run SQL statements.

    " + }, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time (UTC) when the session was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time (UTC) that the session metadata was last updated. An example is the time the status last changed.

    " + }, + "Database":{ + "shape":"String", + "documentation":"

    The name of the database that the session is connected to.

    " + }, + "DbUser":{ + "shape":"String", + "documentation":"

    The database user name.

    " + }, + "ClusterIdentifier":{ + "shape":"String", + "documentation":"

    The cluster identifier. This element is not returned when connecting to a serverless workgroup.

    " + }, + "WorkgroupName":{ + "shape":"WorkgroupNameString", + "documentation":"

    The serverless workgroup name or Amazon Resource Name (ARN). This element is not returned when connecting to a provisioned cluster.

    " + }, + "SessionAliveSeconds":{ + "shape":"SessionAliveSeconds", + "documentation":"

    The number of seconds that the session is kept alive after a query finishes.

    " + }, + "SessionTtl":{ + "shape":"Timestamp", + "documentation":"

    The date and time (UTC) when the session is set to expire and be closed.

    " + }, + "CurrentStatementId":{ + "shape":"UUID", + "documentation":"

    The identifier of the SQL statement currently running in the session. This value is a universally unique identifier (UUID) generated by Amazon Redshift Data API. This element is returned only when the session status is BUSY.

    " + } + }, + "documentation":"

    Contains the metadata for a session returned by ListSessions, including its status, compute target, database connection, and lifecycle timestamps.

    " + }, + "SessionList":{ + "type":"list", + "member":{"shape":"SessionData"} + }, + "SessionStatusString":{ + "type":"string", + "enum":[ + "AVAILABLE", + "BUSY", + "CLOSED" + ] + }, "SqlList":{ "type":"list", "member":{"shape":"StatementString"}, @@ -1388,11 +1592,17 @@ "documentation":"

    The Amazon Redshift Data API operation failed due to invalid input.

    ", "exception":true }, + "WaitTimeSeconds":{ + "type":"integer", + "box":true, + "max":30, + "min":1 + }, "WorkgroupNameString":{ "type":"string", "max":128, "min":3, - "pattern":".*((^[a-z0-9-]{3,63}$)|^(arn:(aws(-[a-z]+)*):redshift-serverless:[a-z]{2}(-gov|(-iso[a-z]?))?-[a-z]+-\\d{1}:\\d{12}:workgroup/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}))" + "pattern":"([a-z0-9-]{3,63}|arn:(aws(-[a-z]+)*):redshift-serverless:([a-z]{2}(-gov|(-iso[a-z]?))?|eusc-[a-z]+)-[a-z]+-\\d{1}:\\d{12}:workgroup/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})" }, "bool":{"type":"boolean"} }, diff --git a/services/redshiftserverless/pom.xml b/services/redshiftserverless/pom.xml index d79830630a59..91ce7d56a9c6 100644 --- a/services/redshiftserverless/pom.xml +++ b/services/redshiftserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT redshiftserverless AWS Java SDK :: Services :: Redshift Serverless diff --git a/services/redshiftserverless/src/main/resources/codegen-resources/customization.config b/services/redshiftserverless/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/redshiftserverless/src/main/resources/codegen-resources/customization.config +++ b/services/redshiftserverless/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b23ced92832c --- /dev/null +++ b/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-serverless-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://redshift-serverless.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0405f5d7f3a7..000000000000 --- a/services/redshiftserverless/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-serverless-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-serverless-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://redshift-serverless.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://redshift-serverless.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/redshiftserverless/src/main/resources/codegen-resources/service-2.json b/services/redshiftserverless/src/main/resources/codegen-resources/service-2.json index 0341b4ac7ed8..ed33c0e87b64 100644 --- a/services/redshiftserverless/src/main/resources/codegen-resources/service-2.json +++ b/services/redshiftserverless/src/main/resources/codegen-resources/service-2.json @@ -1006,7 +1006,7 @@ {"shape":"ValidationException"}, {"shape":"ConflictException"} ], - "documentation":"

    Updates a namespace with the specified settings. Unless required, you can't update multiple parameters in one request. For example, you must specify both adminUsername and adminUserPassword to update either field, but you can't update both kmsKeyId and logExports in a single request.

    " + "documentation":"

    Updates a namespace with the specified settings. Unless required, you can't update multiple parameters in one request. For example, you must specify both adminUsername and adminUserPassword to update either field, but you can't update both kmsKeyId and logExports in a single request.

    Similarly, an S3 Tables log-publishing update (a request where logDestinationType is s3table) cannot be combined with any other namespace configuration change and must be submitted as its own request.

    " }, "UpdateScheduledAction":{ "name":"UpdateScheduledAction", @@ -1155,7 +1155,7 @@ "members":{ "parameterKey":{ "shape":"ParameterKey", - "documentation":"

    The key of the parameter. The options are auto_mv, datestyle, enable_case_sensitive_identifier, enable_user_activity_logging, query_group, search_path, require_ssl, use_fips_ssl, and either wlm_json_configuration or query monitoring metrics that let you define performance boundaries. You can either specify individual query monitoring metrics (such as max_scan_row_count, max_query_execution_time) or use wlm_json_configuration to define query queues with rules, but not both. For more information about query monitoring rules and available metrics, see Query monitoring metrics for Amazon Redshift Serverless.

    " + "documentation":"

    The key of the parameter. The options are auto_mv, datestyle, enable_case_sensitive_identifier, enable_user_activity_logging, query_group, search_path, require_ssl, use_fips_ssl, and either wlm_json_configuration or query monitoring metrics that let you define performance boundaries. You can either specify individual query monitoring metrics (such as max_scan_row_count, max_query_execution_time) or use wlm_json_configuration to define query queues with rules, but not both. If you're using wlm_json_configuration, the maximum size of parameterValue is 8000 characters. For more information about query monitoring rules and available metrics, see Query monitoring metrics for Amazon Redshift Serverless.

    " }, "parameterValue":{ "shape":"ParameterValue", @@ -2922,6 +2922,14 @@ } } }, + "LogDestinationType":{ + "type":"string", + "documentation":"

    Destination type for log publishing.

    ", + "enum":[ + "s3table", + "cloudwatch" + ] + }, "LogExport":{ "type":"string", "enum":[ @@ -3045,6 +3053,10 @@ "shape":"NamespaceName", "documentation":"

    The name of the namespace. Must be between 3-64 alphanumeric characters in lowercase, and it cannot be a reserved word. A list of reserved words can be found in Reserved Words in the Amazon Redshift Database Developer Guide.

    " }, + "s3TablePublishStatus":{ + "shape":"S3TablePublishStatus", + "documentation":"

    The current Amazon S3 Tables log-publishing status for the namespace. Not returned when S3 Tables publishing has never been configured for the namespace.

    " + }, "status":{ "shape":"NamespaceStatus", "documentation":"

    The status of the namespace.

    " @@ -3338,6 +3350,10 @@ "workgroupName" ], "members":{ + "maintainIntegration":{ + "shape":"Boolean", + "documentation":"

    If true, maintain existing data sharing, zero-ETL and S3 event integrations when restoring. Otherwise, integrations will not be maintained after the restore operation. Integrations are only maintained when restored to the same serverless namespace.

    Default: true

    " + }, "namespaceName":{ "shape":"NamespaceName", "documentation":"

    The name of the namespace to restore data into.

    " @@ -3376,6 +3392,10 @@ "shape":"KmsKeyId", "documentation":"

    The ID of the Key Management Service (KMS) key used to encrypt and store the namespace's admin credentials secret.

    " }, + "maintainIntegration":{ + "shape":"Boolean", + "documentation":"

    If true, maintain existing data sharing, zero-ETL and S3 event integrations when restoring. Otherwise, integrations will not be maintained after the restore operation. Integrations are only maintained when restored to the same serverless namespace.

    Default: true

    " + }, "manageAdminPassword":{ "shape":"Boolean", "documentation":"

    If true, Amazon Redshift uses Secrets Manager to manage the restored snapshot's admin credentials. If MmanageAdminPassword is false or not set, Amazon Redshift uses the admin credentials that the namespace or cluster had at the time the snapshot was taken.

    " @@ -3537,6 +3557,68 @@ } } }, + "S3TableAction":{ + "type":"string", + "documentation":"

    Action to perform for S3 Table log publishing.

    ", + "enum":[ + "Enable", + "Disable" + ] + }, + "S3TableGranularity":{ + "type":"string", + "documentation":"

    Granularity for S3 Table scoping in serverless.

    ", + "enum":[ + "namespace", + "account" + ] + }, + "S3TableLastIngestionTimeMap":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"}, + "documentation":"

    Map of system table name to the last ingestion time (ISO-8601) for that table.

    " + }, + "S3TableName":{ + "type":"string", + "documentation":"

    A system-table view name to publish to S3 Tables (e.g. "sys_query_history"), or the keyword "all" to publish every current and future system table.

    ", + "max":128, + "min":1, + "pattern":"^(all|sys_[a-z0-9_]+)$" + }, + "S3TableNameList":{ + "type":"list", + "member":{"shape":"S3TableName"}, + "documentation":"

    List of system table names (or "all") to publish to S3 Tables. Sized to hold the full SYS_* universe (28+ today, grows as new views are onboarded) plus headroom.

    ", + "max":256, + "min":0 + }, + "S3TablePublishStatus":{ + "type":"structure", + "members":{ + "enabledAll":{ + "shape":"Boolean", + "documentation":"

    true when the namespace is enrolled in every current and future system table rather than an explicit list of tables.

    " + }, + "lastIngestionTimes":{ + "shape":"S3TableLastIngestionTimeMap", + "documentation":"

    A map of system table name to the time that table last received data, as an ISO-8601 timestamp. A table that has not yet been ingested is absent from the map. Use it to judge data freshness.

    " + }, + "s3TableGranularity":{ + "shape":"S3TableGranularity", + "documentation":"

    The scope currently in effect. Values are namespace or account.

    " + }, + "s3TableNamespace":{ + "shape":"String", + "documentation":"

    The identifier of the namespace in the S3 table bucket that holds the published tables.

    " + }, + "s3Tables":{ + "shape":"S3TableNameList", + "documentation":"

    The system tables currently being published.

    " + } + }, + "documentation":"

    Describes the state of Amazon S3 Tables system-table log publishing for a namespace.

    " + }, "Schedule":{ "type":"structure", "members":{ @@ -4155,7 +4237,7 @@ }, "adminUserPassword":{ "shape":"DbPassword", - "documentation":"

    The password of the administrator for the first database created in the namespace. This parameter must be updated together with adminUsername.

    You can't use adminUserPassword if manageAdminPassword is true.

    " + "documentation":"

    The password of the administrator for the first database created in the namespace. This parameter must be updated together with adminUsername.

    You can't use adminUserPassword if manageAdminPassword is true.

    If your admin user account is locked, this operation also unlocks your account and resets the failed-login counter. This option is available only when account lockout security is enabled for the namespace.

    " }, "adminUsername":{ "shape":"DbUser", @@ -4173,6 +4255,10 @@ "shape":"String", "documentation":"

    The ID of the Amazon Web Services Key Management Service key used to encrypt your data.

    " }, + "logDestinationType":{ + "shape":"LogDestinationType", + "documentation":"

    The destination for the log data. Valid values are s3table and cloudwatch.

    Set this to s3table to manage Amazon S3 Tables system-table publishing for the namespace.

    " + }, "logExports":{ "shape":"LogExportList", "documentation":"

    The types of logs the namespace can export. The export types are userlog, connectionlog, and useractivitylog.

    " @@ -4184,6 +4270,22 @@ "namespaceName":{ "shape":"NamespaceName", "documentation":"

    The name of the namespace to update. You can't update the name of a namespace once it is created.

    " + }, + "s3TableAction":{ + "shape":"S3TableAction", + "documentation":"

    Whether to enable or disable Amazon S3 Tables publishing. Valid values are Enable and Disable, matched case-insensitively.

    When omitted, defaults to Enable. Valid only when logDestinationType is s3table.

    " + }, + "s3TableGranularity":{ + "shape":"S3TableGranularity", + "documentation":"

    The scope of the Amazon S3 Tables destination. Valid values are namespace and account, matched case-insensitively. namespace scopes the published tables to this namespace; account scopes them to the Amazon Web Services account.

    Required when enabling. Omitting this parameter or passing a blank value fails with ValidationException. Valid only when logDestinationType is s3table.

    " + }, + "s3TableKmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The identifier of the Key Management Service key used to encrypt the published Amazon S3 Tables data. When omitted, the data is encrypted with SSE-S3 (Amazon S3 managed keys).

    Valid only when logDestinationType is s3table.

    " + }, + "s3TableNames":{ + "shape":"S3TableNameList", + "documentation":"

    The system tables to publish (on enable) or to stop publishing (on disable). Each value is either a system table view name that begins with sys_ or the keyword all.

    Omitting this parameter, passing an empty list, or including all each select every current and future system table. Each name must be 1-128 characters, and the list can contain up to 256 names.

    Valid only when logDestinationType is s3table.

    " } } }, diff --git a/services/rekognition/pom.xml b/services/rekognition/pom.xml index 12317f16d351..1878304df337 100644 --- a/services/rekognition/pom.xml +++ b/services/rekognition/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rekognition AWS Java SDK :: Services :: Amazon Rekognition diff --git a/services/rekognition/src/main/resources/codegen-resources/customization.config b/services/rekognition/src/main/resources/codegen-resources/customization.config index 284e705d144f..2c703da2ab1e 100644 --- a/services/rekognition/src/main/resources/codegen-resources/customization.config +++ b/services/rekognition/src/main/resources/codegen-resources/customization.config @@ -6,6 +6,5 @@ "excludedSimpleMethods": [ "describeTableRestoreStatus", "describeClusterSecurityGroups" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/rekognition/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rekognition/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1f4c4aed44c1 --- /dev/null +++ b/services/rekognition/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rekognition-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rekognition-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rekognition.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rekognition.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rekognition/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rekognition/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d681270a70e0..000000000000 --- a/services/rekognition/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rekognition-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rekognition-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rekognition.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rekognition.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/repostspace/pom.xml b/services/repostspace/pom.xml index 7f1bb2255d45..243c5c8f858f 100644 --- a/services/repostspace/pom.xml +++ b/services/repostspace/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT repostspace AWS Java SDK :: Services :: Repostspace diff --git a/services/repostspace/src/main/resources/codegen-resources/customization.config b/services/repostspace/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/repostspace/src/main/resources/codegen-resources/customization.config +++ b/services/repostspace/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/repostspace/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/repostspace/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..826bca8a6e23 --- /dev/null +++ b/services/repostspace/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://repostspace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://repostspace-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://repostspace.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://repostspace.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/repostspace/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/repostspace/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 306ffe373168..000000000000 --- a/services/repostspace/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://repostspace-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://repostspace-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://repostspace.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://repostspace.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/resiliencehub/pom.xml b/services/resiliencehub/pom.xml index f0c440e042a1..229d896b6b56 100644 --- a/services/resiliencehub/pom.xml +++ b/services/resiliencehub/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT resiliencehub AWS Java SDK :: Services :: Resiliencehub diff --git a/services/resiliencehub/src/main/resources/codegen-resources/customization.config b/services/resiliencehub/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/resiliencehub/src/main/resources/codegen-resources/customization.config +++ b/services/resiliencehub/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/resiliencehub/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/resiliencehub/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c4144c622a2c --- /dev/null +++ b/services/resiliencehub/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/resiliencehub/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/resiliencehub/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5ff01a2547a2..000000000000 --- a/services/resiliencehub/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/resiliencehubv2/pom.xml b/services/resiliencehubv2/pom.xml index dc9406319b12..bca5de33dca4 100644 --- a/services/resiliencehubv2/pom.xml +++ b/services/resiliencehubv2/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT resiliencehubv2 AWS Java SDK :: Services :: Resiliencehubv2 diff --git a/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c4144c622a2c --- /dev/null +++ b/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resiliencehub.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e0c7d68d8686..000000000000 --- a/services/resiliencehubv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resiliencehub.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/resiliencehubv2/src/main/resources/codegen-resources/paginators-1.json b/services/resiliencehubv2/src/main/resources/codegen-resources/paginators-1.json index b6851b4956dc..48b0a7b9c423 100644 --- a/services/resiliencehubv2/src/main/resources/codegen-resources/paginators-1.json +++ b/services/resiliencehubv2/src/main/resources/codegen-resources/paginators-1.json @@ -36,12 +36,24 @@ "limit_key": "maxResults", "result_key": "policySummaries" }, + "ListPolicyEvents": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "events" + }, "ListReports": { "input_token": "nextToken", "output_token": "nextToken", "limit_key": "maxResults", "result_key": "reportGenerationResults" }, + "ListResolvedTestRunTargetResources": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "resolvedTargetResources" + }, "ListResources": { "input_token": "nextToken", "output_token": "nextToken", @@ -84,6 +96,48 @@ "limit_key": "maxResults", "result_key": "systemSummaries" }, + "ListTestRunDependencies": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "dependencies" + }, + "ListTestRunEvents": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "events" + }, + "ListTestRunSourceEvents": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "testRunSourceEvents" + }, + "ListTestRunSources": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "testRunSources" + }, + "ListTestRuns": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "testRuns" + }, + "ListTestSources": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "testSources" + }, + "ListTests": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "tests" + }, "ListUserJourneys": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/resiliencehubv2/src/main/resources/codegen-resources/service-2.json b/services/resiliencehubv2/src/main/resources/codegen-resources/service-2.json index 7550ce73b46b..fd81fa624b93 100644 --- a/services/resiliencehubv2/src/main/resources/codegen-resources/service-2.json +++ b/services/resiliencehubv2/src/main/resources/codegen-resources/service-2.json @@ -164,6 +164,24 @@ ], "documentation":"

    Creates a system that represents a logical grouping of services.

    " }, + "CreateTest":{ + "name":"CreateTest", + "http":{ + "method":"POST", + "requestUri":"/v2/create-test", + "responseCode":200 + }, + "input":{"shape":"CreateTestRequest"}, + "output":{"shape":"CreateTestResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Creates a test for a service by configuring a test template. Each service has one test per template.

    " + }, "CreateUserJourney":{ "name":"CreateUserJourney", "http":{ @@ -307,6 +325,42 @@ ], "documentation":"

    Deletes a system.

    " }, + "DeleteTest":{ + "name":"DeleteTest", + "http":{ + "method":"POST", + "requestUri":"/v2/delete-test", + "responseCode":200 + }, + "input":{"shape":"DeleteTestRequest"}, + "output":{"shape":"DeleteTestResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Deletes a test.

    " + }, + "DeleteTestSources":{ + "name":"DeleteTestSources", + "http":{ + "method":"POST", + "requestUri":"/v2/delete-test-sources", + "responseCode":200 + }, + "input":{"shape":"DeleteTestSourcesRequest"}, + "output":{"shape":"DeleteTestSourcesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Removes monitoring sources from a test. The operation is transactional and idempotent — removing a source that is not attached is a no-op.

    " + }, "DeleteUserJourney":{ "name":"DeleteUserJourney", "http":{ @@ -325,6 +379,25 @@ ], "documentation":"

    Deletes a user journey.

    " }, + "GetDependencyInsights":{ + "name":"GetDependencyInsights", + "http":{ + "method":"GET", + "requestUri":"/v2/get-dependency-insights", + "responseCode":200 + }, + "input":{"shape":"GetDependencyInsightsRequest"}, + "output":{"shape":"GetDependencyInsightsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Retrieves the dependency insights generated for a service. The response reports the current generation status; insights are populated once generation has completed. If generation failed, the response includes an error code, whose possible values are listed under the response's errorCode field, and a message describing the cause. To use this operation, you must have the resiliencehub:GetDependencyInsights permission on the service.

    ", + "readonly":true + }, "GetFailureModeFinding":{ "name":"GetFailureModeFinding", "http":{ @@ -397,6 +470,60 @@ "documentation":"

    Retrieves a system by ARN.

    ", "readonly":true }, + "GetTest":{ + "name":"GetTest", + "http":{ + "method":"GET", + "requestUri":"/v2/get-test", + "responseCode":200 + }, + "input":{"shape":"GetTestRequest"}, + "output":{"shape":"GetTestResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Retrieves a test by ID.

    ", + "readonly":true + }, + "GetTestRun":{ + "name":"GetTestRun", + "http":{ + "method":"GET", + "requestUri":"/v2/get-test-run", + "responseCode":200 + }, + "input":{"shape":"GetTestRunRequest"}, + "output":{"shape":"GetTestRunResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Retrieves a test run by ID, including its status, results, and the configuration snapshotted when the run started.

    ", + "readonly":true + }, + "GetTestTemplate":{ + "name":"GetTestTemplate", + "http":{ + "method":"GET", + "requestUri":"/v2/get-test-template", + "responseCode":200 + }, + "input":{"shape":"GetTestTemplateRequest"}, + "output":{"shape":"GetTestTemplateResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Retrieves a resilience test template by ARN, including the parameters it accepts and the fault actions it runs.

    ", + "readonly":true + }, "GetUserJourney":{ "name":"GetUserJourney", "http":{ @@ -558,6 +685,24 @@ "documentation":"

    Lists resilience policies.

    ", "readonly":true }, + "ListPolicyEvents":{ + "name":"ListPolicyEvents", + "http":{ + "method":"GET", + "requestUri":"/v2/list-policy-events", + "responseCode":200 + }, + "input":{"shape":"ListPolicyEventsRequest"}, + "output":{"shape":"ListPolicyEventsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists events for a resilience policy, including services that started or stopped using it, changes to cross-account sharing, and deletion of the policy.

    ", + "readonly":true + }, "ListReports":{ "name":"ListReports", "http":{ @@ -577,6 +722,24 @@ "documentation":"

    List reports for a service, or all reports owned by the account if serviceArn is not provided.

    ", "readonly":true }, + "ListResolvedTestRunTargetResources":{ + "name":"ListResolvedTestRunTargetResources", + "http":{ + "method":"GET", + "requestUri":"/v2/test-runs/{testRunId}/resolved-target-resources", + "responseCode":200 + }, + "input":{"shape":"ListResolvedTestRunTargetResourcesRequest"}, + "output":{"shape":"ListResolvedTestRunTargetResourcesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the AWS resources that AWS Fault Injection Service (AWS FIS) resolved as targets for a test run.

    ", + "readonly":true + }, "ListResources":{ "name":"ListResources", "http":{ @@ -719,6 +882,149 @@ "documentation":"

    Lists the tags for a resource.

    ", "readonly":true }, + "ListTestRunDependencies":{ + "name":"ListTestRunDependencies", + "http":{ + "method":"GET", + "requestUri":"/v2/test-runs/{testRunId}/dependencies", + "responseCode":200 + }, + "input":{"shape":"ListTestRunDependenciesRequest"}, + "output":{"shape":"ListTestRunDependenciesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the dependencies that a test run blocked. Each dependency reflects the discovered classification captured when the run started, so results do not change if a dependency is reclassified after the run.

    ", + "readonly":true + }, + "ListTestRunEvents":{ + "name":"ListTestRunEvents", + "http":{ + "method":"GET", + "requestUri":"/v2/test-runs/{testRunId}/events", + "responseCode":200 + }, + "input":{"shape":"ListTestRunEventsRequest"}, + "output":{"shape":"ListTestRunEventsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the events in a test run's timeline.

    ", + "readonly":true + }, + "ListTestRunSourceEvents":{ + "name":"ListTestRunSourceEvents", + "http":{ + "method":"GET", + "requestUri":"/v2/test-runs/{testRunId}/source-events", + "responseCode":200 + }, + "input":{"shape":"ListTestRunSourceEventsRequest"}, + "output":{"shape":"ListTestRunSourceEventsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the state-change events observed for a test run monitoring source. Events are returned for one source per call, in chronological order.

    ", + "readonly":true + }, + "ListTestRunSources":{ + "name":"ListTestRunSources", + "http":{ + "method":"GET", + "requestUri":"/v2/test-runs/{testRunId}/sources", + "responseCode":200 + }, + "input":{"shape":"ListTestRunSourcesRequest"}, + "output":{"shape":"ListTestRunSourcesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the monitoring source snapshots captured for a test run, optionally filtered by type.

    ", + "readonly":true + }, + "ListTestRuns":{ + "name":"ListTestRuns", + "http":{ + "method":"GET", + "requestUri":"/v2/list-test-runs", + "responseCode":200 + }, + "input":{"shape":"ListTestRunsRequest"}, + "output":{"shape":"ListTestRunsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the runs of a test, or all test runs for a service.

    ", + "readonly":true + }, + "ListTestSources":{ + "name":"ListTestSources", + "http":{ + "method":"GET", + "requestUri":"/v2/tests/{testId}/sources", + "responseCode":200 + }, + "input":{"shape":"ListTestSourcesRequest"}, + "output":{"shape":"ListTestSourcesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the monitoring sources attached to a test, optionally filtered by type.

    ", + "readonly":true + }, + "ListTestTemplates":{ + "name":"ListTestTemplates", + "http":{ + "method":"GET", + "requestUri":"/v2/list-test-templates", + "responseCode":200 + }, + "input":{"shape":"ListTestTemplatesRequest"}, + "output":{"shape":"ListTestTemplatesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the available resilience test templates. A test template is a pre-configured, AWS recommended test that defines which resilience capability to validate.

    ", + "readonly":true + }, + "ListTests":{ + "name":"ListTests", + "http":{ + "method":"GET", + "requestUri":"/v2/list-tests", + "responseCode":200 + }, + "input":{"shape":"ListTestsRequest"}, + "output":{"shape":"ListTestsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Lists the tests configured for a service.

    ", + "readonly":true + }, "ListUserJourneys":{ "name":"ListUserJourneys", "http":{ @@ -737,6 +1043,44 @@ "documentation":"

    Lists user journeys for a system.

    ", "readonly":true }, + "PutTestSources":{ + "name":"PutTestSources", + "http":{ + "method":"POST", + "requestUri":"/v2/put-test-sources", + "responseCode":200 + }, + "input":{"shape":"PutTestSourcesRequest"}, + "output":{"shape":"PutTestSourcesResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Adds or updates the monitoring sources on a test. The operation is transactional — either every source is written or the call fails and nothing is written.

    " + }, + "StartDependencyInsights":{ + "name":"StartDependencyInsights", + "http":{ + "method":"POST", + "requestUri":"/v2/start-dependency-insights", + "responseCode":202 + }, + "input":{"shape":"StartDependencyInsightsRequest"}, + "output":{"shape":"StartDependencyInsightsResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Starts generating dependency insights for a service. Generation runs asynchronously; the response returns the initial status, and you retrieve the results with GetDependencyInsights. To use this operation, you must have the resiliencehub:StartDependencyInsights permission on the service.

    " + }, "StartFailureModeAssessment":{ "name":"StartFailureModeAssessment", "http":{ @@ -756,6 +1100,42 @@ ], "documentation":"

    Starts a failure mode assessment.

    " }, + "StartTestRun":{ + "name":"StartTestRun", + "http":{ + "method":"POST", + "requestUri":"/v2/start-test-run", + "responseCode":200 + }, + "input":{"shape":"StartTestRunRequest"}, + "output":{"shape":"StartTestRunResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Starts a run of a test. Each run scopes to the current resources in the service and produces a pass or fail outcome.

    " + }, + "StopTestRun":{ + "name":"StopTestRun", + "http":{ + "method":"POST", + "requestUri":"/v2/stop-test-run", + "responseCode":200 + }, + "input":{"shape":"StopTestRunRequest"}, + "output":{"shape":"StopTestRunResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Stops an in-progress test run.

    " + }, "TagResource":{ "name":"TagResource", "http":{ @@ -920,11 +1300,29 @@ ], "documentation":"

    Updates an existing system.

    " }, - "UpdateUserJourney":{ - "name":"UpdateUserJourney", + "UpdateTest":{ + "name":"UpdateTest", "http":{ "method":"POST", - "requestUri":"/v2/update-user-journey", + "requestUri":"/v2/update-test", + "responseCode":200 + }, + "input":{"shape":"UpdateTestRequest"}, + "output":{"shape":"UpdateTestResponse"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"} + ], + "documentation":"

    Updates the configuration of an existing test.

    " + }, + "UpdateUserJourney":{ + "name":"UpdateUserJourney", + "http":{ + "method":"POST", + "requestUri":"/v2/update-user-journey", "responseCode":200 }, "input":{"shape":"UpdateUserJourneyRequest"}, @@ -959,6 +1357,14 @@ "min":12, "pattern":"[0-9]{12}" }, + "AccountTargeting":{ + "type":"string", + "documentation":"

    Whether a test run targets resources in a single AWS account or across multiple accounts.

    ", + "enum":[ + "SINGLE_ACCOUNT", + "MULTI_ACCOUNT" + ] + }, "Achievability":{ "type":"structure", "members":{ @@ -995,6 +1401,39 @@ "SYSTEM" ] }, + "AlarmState":{ + "type":"string", + "documentation":"

    The state of a CloudWatch alarm.

    ", + "enum":[ + "OK", + "ALARM", + "INSUFFICIENT_DATA" + ] + }, + "AlarmStateChangeDetail":{ + "type":"structure", + "required":["state"], + "members":{ + "state":{ + "shape":"AlarmState", + "documentation":"

    The state the alarm transitioned to.

    " + }, + "previousState":{ + "shape":"AlarmState", + "documentation":"

    The state the alarm transitioned from. Absent on the initial event, which records the alarm's state when collection began.

    " + }, + "reason":{ + "shape":"AlarmStateChangeDetailReasonString", + "documentation":"

    A human-readable explanation of the state change, as reported by CloudWatch.

    " + } + }, + "documentation":"

    Details about a CloudWatch alarm state change observed during a test run.

    " + }, + "AlarmStateChangeDetailReasonString":{ + "type":"string", + "max":1023, + "min":0 + }, "Arn":{ "type":"string", "documentation":"

    ARN identifier.

    ", @@ -1271,6 +1710,13 @@ "min":1, "pattern":"[A-Za-z0-9_.-]{0,63}" }, + "CloudWatchAlarmArn":{ + "type":"string", + "documentation":"

    The ARN of a CloudWatch alarm.

    ", + "max":1024, + "min":31, + "pattern":"arn:aws[a-zA-Z-]*:cloudwatch:[a-z]{2}(-[a-z]+)+-\\d{1}:\\d{12}:alarm:.+" + }, "ConflictException":{ "type":"structure", "required":["message"], @@ -1367,6 +1813,10 @@ "shape":"DataRecoveryTargets", "documentation":"

    The data recovery targets for the resilience policy.

    " }, + "sharingEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether cross-account sharing is enabled for the policy. Only a delegated administrator or the management account can enable sharing.

    " + }, "kmsKeyId":{"shape":"KmsKeyId"}, "tags":{"shape":"TagMap"}, "clientToken":{ @@ -1494,7 +1944,7 @@ "policyArn":{"shape":"Arn"}, "regions":{ "shape":"RegionList", - "documentation":"

    The AWS Regions where the service operates.

    " + "documentation":"

    The Regions where the service operates.

    " }, "permissionModel":{ "shape":"PermissionModel", @@ -1548,6 +1998,49 @@ } } }, + "CreateTestRequest":{ + "type":"structure", + "required":[ + "serviceArn", + "testTemplateArn" + ], + "members":{ + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service to create the test for.

    " + }, + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template to configure.

    " + }, + "loggingConfiguration":{ + "shape":"LoggingConfiguration", + "documentation":"

    The logging configuration for the test.

    " + }, + "stopConditions":{ + "shape":"StopConditionList", + "documentation":"

    The stop conditions for the test.

    " + }, + "roleName":{ + "shape":"IamRoleName", + "documentation":"

    The name of the IAM execution role to use when running the test.

    " + }, + "parameters":{ + "shape":"TestParameters", + "documentation":"

    The parameter values for the test.

    " + } + } + }, + "CreateTestResponse":{ + "type":"structure", + "required":["test"], + "members":{ + "test":{ + "shape":"Test", + "documentation":"

    The created test.

    " + } + } + }, "CreateUserJourneyRequest":{ "type":"structure", "required":[ @@ -1762,6 +2255,59 @@ "systemArn":{"shape":"Arn"} } }, + "DeleteTestRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to delete.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " + } + } + }, + "DeleteTestResponse":{ + "type":"structure", + "required":["testId"], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the deleted test.

    " + } + } + }, + "DeleteTestSourcesRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn", + "testSources" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to remove sources from.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " + }, + "testSources":{ + "shape":"TestSourceInputList", + "documentation":"

    The monitoring sources to remove.

    " + } + } + }, + "DeleteTestSourcesResponse":{ + "type":"structure", + "members":{} + }, "DeleteUserJourneyRequest":{ "type":"structure", "required":[ @@ -1788,6 +2334,7 @@ }, "DependencyCriticality":{ "type":"string", + "documentation":"

    The criticality classification of a dependency.

    ", "enum":[ "HARD", "SOFT", @@ -1843,6 +2390,51 @@ "DISABLED" ] }, + "DependencyInsight":{ + "type":"structure", + "required":[ + "category", + "description" + ], + "members":{ + "category":{ + "shape":"InsightsCategory", + "documentation":"

    The category of the insight. Valid values:

    • CROSS_REGION - The insight relates to dependencies used across multiple Regions.

    • NEW_DEPENDENCY - The insight relates to a recently detected dependency.

    • THIRD_PARTY - The insight relates to a third-party dependency.

    • UNEVEN_USAGE - The insight relates to a dependency with uneven usage across the service.

    • AWS_SERVICE - The insight relates to a dependency on an Amazon Web Services service.

    " + }, + "description":{ + "shape":"DependencyInsightDescriptionString", + "documentation":"

    A human-readable explanation of the insight, describing the dependency behavior or condition that was detected.

    " + } + }, + "documentation":"

    Contains a single insight about a service's dependencies.

    " + }, + "DependencyInsightDescriptionString":{ + "type":"string", + "max":1024, + "min":0 + }, + "DependencyInsightsErrorCode":{ + "type":"string", + "enum":[ + "INSUFFICIENT_DATA", + "LLM_GENERATION_FAILED", + "INTERNAL_ERROR" + ] + }, + "DependencyInsightsList":{ + "type":"list", + "member":{"shape":"DependencyInsight"}, + "max":5, + "min":0 + }, + "DependencyInsightsStatus":{ + "type":"string", + "enum":[ + "IN_PROGRESS", + "COMPLETED", + "FAILED" + ] + }, "DependencySummary":{ "type":"structure", "required":[ @@ -1982,6 +2574,88 @@ }, "documentation":"

    Contains the effective resilience policy values for a service.

    " }, + "EksLabelKey":{ + "type":"string", + "documentation":"

    A Kubernetes label key. It can include an optional DNS subdomain prefix.

    ", + "max":317, + "min":1, + "pattern":"([a-z0-9]([-a-z0-9.]*[a-z0-9])?/)?[A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])?" + }, + "EksLabelSelector":{ + "type":"structure", + "members":{ + "matchLabels":{ + "shape":"EksLabelSelectorMatchLabelsMap", + "documentation":"

    The label key-value pairs that an object must have. All pairs must match for the object to be selected.

    " + }, + "matchExpressions":{ + "shape":"EksLabelSelectorMatchExpressionsList", + "documentation":"

    The label requirements that an object must satisfy. All requirements in the list must match for the object to be selected.

    " + } + }, + "documentation":"

    A label selector that filters the Kubernetes objects discovered from an Amazon EKS input source. An object must satisfy both matchLabels and matchExpressions to match the selector. A selector with neither matches every object. The selector must render to 2,048 characters or fewer in Kubernetes label selector syntax.

    " + }, + "EksLabelSelectorMatchExpressionsList":{ + "type":"list", + "member":{"shape":"EksLabelSelectorRequirement"}, + "max":20, + "min":0, + "sensitive":true + }, + "EksLabelSelectorMatchLabelsMap":{ + "type":"map", + "key":{"shape":"EksLabelKey"}, + "value":{"shape":"EksLabelValue"}, + "documentation":"

    Specifies Kubernetes labels as a map of label keys to values.

    ", + "max":20, + "min":0, + "sensitive":true + }, + "EksLabelSelectorOperator":{ + "type":"string", + "documentation":"

    The operator that a label selector requirement applies to its key and values.

    • IN — the key's value must be one of the specified values.

    • NOT_IN — the key's value must not be one of the specified values.

    • EXISTS — the key must be present, regardless of its value.

    • DOES_NOT_EXIST — the key must not be present.

    ", + "enum":[ + "IN", + "NOT_IN", + "EXISTS", + "DOES_NOT_EXIST" + ] + }, + "EksLabelSelectorRequirement":{ + "type":"structure", + "required":[ + "key", + "operator" + ], + "members":{ + "key":{ + "shape":"EksLabelKey", + "documentation":"

    The label key that the requirement applies to.

    " + }, + "operator":{ + "shape":"EksLabelSelectorOperator", + "documentation":"

    The operator that relates the label key to the values.

    " + }, + "values":{ + "shape":"EksLabelSelectorRequirementValuesList", + "documentation":"

    The label values to compare against. Specify values when the operator is IN or NOT_IN. Leave this empty when the operator is EXISTS or DOES_NOT_EXIST.

    " + } + }, + "documentation":"

    A single label requirement in a label selector, expressed as a key, an operator, and an optional list of values.

    " + }, + "EksLabelSelectorRequirementValuesList":{ + "type":"list", + "member":{"shape":"EksLabelValue"}, + "max":20, + "min":0 + }, + "EksLabelValue":{ + "type":"string", + "documentation":"

    A Kubernetes label value. This value can be empty.

    ", + "max":63, + "min":0, + "pattern":"([A-Za-z0-9]([-A-Za-z0-9_.]*[A-Za-z0-9])?)?" + }, "EksNamespace":{ "type":"string", "documentation":"

    Kubernetes namespace name (RFC 1123 Label).

    ", @@ -2000,6 +2674,10 @@ "namespaces":{ "shape":"EksSourceNamespacesList", "documentation":"

    The list of Kubernetes namespaces within the EKS cluster.

    " + }, + "labelSelector":{ + "shape":"EksLabelSelector", + "documentation":"

    Filters discovery to the Kubernetes objects whose labels match the selector. When omitted, all supported objects in the specified namespaces are discovered.

    " } }, "documentation":"

    Defines an Amazon EKS cluster and its namespaces as an input source for resource discovery.

    " @@ -2062,6 +2740,29 @@ }, "documentation":"

    Identifies the actor that triggered an event.

    " }, + "ExperimentArnList":{ + "type":"list", + "member":{"shape":"Arn"} + }, + "ExperimentDetails":{ + "type":"structure", + "required":["experimentArn"], + "members":{ + "experimentArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the AWS FIS experiment.

    " + }, + "details":{ + "shape":"String", + "documentation":"

    Additional details about the experiment.

    " + } + }, + "documentation":"

    Details about an AWS Fault Injection Service (AWS FIS) experiment run as part of a test run.

    " + }, + "ExperimentDetailsList":{ + "type":"list", + "member":{"shape":"ExperimentDetails"} + }, "FailedReportOutput":{ "type":"structure", "required":["errorCode"], @@ -2213,6 +2914,57 @@ "max":20, "min":0 }, + "GetDependencyInsightsRequest":{ + "type":"structure", + "required":["serviceArn"], + "members":{ + "serviceArn":{ + "shape":"Arn", + "location":"querystring", + "locationName":"serviceArn" + } + } + }, + "GetDependencyInsightsResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "overview":{ + "shape":"GetDependencyInsightsResponseOverviewString", + "documentation":"

    A summary of the dependency insights for the service. This field is not returned until the status is COMPLETED.

    " + }, + "insights":{ + "shape":"DependencyInsightsList", + "documentation":"

    The list of dependency insights generated for the service. This field is not returned until the status is COMPLETED.

    " + }, + "status":{ + "shape":"DependencyInsightsStatus", + "documentation":"

    The status of the dependency insights generation. Valid values:

    • IN_PROGRESS - Insights generation is in progress.

    • COMPLETED - Insights generation completed successfully.

    • FAILED - Insights generation failed. See errorCode and errorMessage for details.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the dependency insights were generated.

    " + }, + "errorCode":{ + "shape":"DependencyInsightsErrorCode", + "documentation":"

    The error code returned when insights generation failed. Valid values:

    • INSUFFICIENT_DATA - There was not enough dependency data to generate insights.

    • LLM_GENERATION_FAILED - The insights could not be generated.

    • INTERNAL_ERROR - An internal error occurred while generating insights.

    " + }, + "errorMessage":{ + "shape":"GetDependencyInsightsResponseErrorMessageString", + "documentation":"

    A message describing why insights generation failed.

    " + } + } + }, + "GetDependencyInsightsResponseErrorMessageString":{ + "type":"string", + "max":1024, + "min":0 + }, + "GetDependencyInsightsResponseOverviewString":{ + "type":"string", + "max":4096, + "min":0 + }, "GetFailureModeFindingRequest":{ "type":"structure", "required":[ @@ -2305,63 +3057,147 @@ } } }, - "GetUserJourneyRequest":{ + "GetTestRequest":{ "type":"structure", "required":[ - "systemArn", - "userJourneyId" + "testId", + "serviceArn" ], "members":{ - "systemArn":{ - "shape":"Arn", + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to retrieve.

    ", "location":"querystring", - "locationName":"systemArn" + "locationName":"testId" }, - "userJourneyId":{ - "shape":"UserJourneyId", - "documentation":"

    The identifier of the user journey to retrieve.

    ", + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    ", "location":"querystring", - "locationName":"userJourneyId" + "locationName":"serviceArn" } } }, - "GetUserJourneyResponse":{ + "GetTestResponse":{ "type":"structure", - "required":["userJourney"], + "required":["test"], "members":{ - "userJourney":{ - "shape":"UserJourney", - "documentation":"

    The requested user journey.

    " + "test":{ + "shape":"Test", + "documentation":"

    The requested test.

    " } } }, - "IamRoleArn":{ - "type":"string", - "documentation":"

    ARN of the IAM Role for the profile. Null if the permission profile is the 'Admin' profile.

    ", - "min":32, - "pattern":"arn:(aws|aws-cn|aws-iso|aws-iso-[a-z]{1}|aws-us-gov):iam::[0-9]{12}:role/(([^/][!-~]+/){1,511})?[A-Za-z0-9_+=,.@-]{1,64}" - }, - "IamRoleName":{ - "type":"string", - "documentation":"

    IAM role name (supports up to 64 characters per IAM limits).

    ", - "max":64, - "min":1, - "pattern":"[A-Za-z0-9_+=,.@\\-]{1,64}" - }, - "ImportAppRequest":{ + "GetTestRunRequest":{ "type":"structure", - "required":["v1AppArn"], + "required":[ + "testRunId", + "serviceArn" + ], "members":{ - "v1AppArn":{"shape":"Arn"}, - "policyArn":{"shape":"Arn"}, - "kmsKeyId":{"shape":"KmsKeyId"}, - "skipManuallyAddedResources":{ - "shape":"Boolean", - "documentation":"

    Whether to skip manually added resources during import.

    " + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to retrieve.

    ", + "location":"querystring", + "locationName":"testRunId" }, - "associatedSystems":{ - "shape":"AssociatedSystemList", - "documentation":"

    The systems to associate with the imported service.

    " + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" + } + } + }, + "GetTestRunResponse":{ + "type":"structure", + "required":["testRun"], + "members":{ + "testRun":{ + "shape":"TestRun", + "documentation":"

    The requested test run.

    " + } + } + }, + "GetTestTemplateRequest":{ + "type":"structure", + "required":["testTemplateArn"], + "members":{ + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template to retrieve.

    ", + "location":"querystring", + "locationName":"testTemplateArn" + } + } + }, + "GetTestTemplateResponse":{ + "type":"structure", + "required":["testTemplate"], + "members":{ + "testTemplate":{ + "shape":"TestTemplate", + "documentation":"

    The requested test template.

    " + } + } + }, + "GetUserJourneyRequest":{ + "type":"structure", + "required":[ + "systemArn", + "userJourneyId" + ], + "members":{ + "systemArn":{ + "shape":"Arn", + "location":"querystring", + "locationName":"systemArn" + }, + "userJourneyId":{ + "shape":"UserJourneyId", + "documentation":"

    The identifier of the user journey to retrieve.

    ", + "location":"querystring", + "locationName":"userJourneyId" + } + } + }, + "GetUserJourneyResponse":{ + "type":"structure", + "required":["userJourney"], + "members":{ + "userJourney":{ + "shape":"UserJourney", + "documentation":"

    The requested user journey.

    " + } + } + }, + "IamRoleArn":{ + "type":"string", + "documentation":"

    ARN of the IAM Role for the profile. Null if the permission profile is the 'Admin' profile.

    ", + "min":32, + "pattern":"arn:(aws|aws-cn|aws-iso|aws-iso-[a-z]{1}|aws-us-gov):iam::[0-9]{12}:role/(([^/][!-~]+/){1,511})?[A-Za-z0-9_+=,.@-]{1,64}" + }, + "IamRoleName":{ + "type":"string", + "documentation":"

    IAM role name (supports up to 64 characters per IAM limits).

    ", + "max":576, + "min":1, + "pattern":"([A-Za-z0-9_+=,.@\\-]+/)*[A-Za-z0-9_+=,.@\\-]+" + }, + "ImportAppRequest":{ + "type":"structure", + "required":["v1AppArn"], + "members":{ + "v1AppArn":{"shape":"Arn"}, + "policyArn":{"shape":"Arn"}, + "kmsKeyId":{"shape":"KmsKeyId"}, + "skipManuallyAddedResources":{ + "shape":"Boolean", + "documentation":"

    Whether to skip manually added resources during import.

    " + }, + "associatedSystems":{ + "shape":"AssociatedSystemList", + "documentation":"

    The systems to associate with the imported service.

    " }, "tags":{"shape":"TagMap"}, "clientToken":{ @@ -2500,6 +3336,16 @@ "MONITORING" ] }, + "InsightsCategory":{ + "type":"string", + "enum":[ + "CROSS_REGION", + "NEW_DEPENDENCY", + "THIRD_PARTY", + "UNEVEN_USAGE", + "AWS_SERVICE" + ] + }, "Integer":{ "type":"integer", "box":true @@ -2761,6 +3607,12 @@ "ListPoliciesRequest":{ "type":"structure", "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The identifier of the account that owns the policies to include in the results.

    ", + "location":"querystring", + "locationName":"accountId" + }, "maxResults":{ "shape":"MaxResults", "location":"querystring", @@ -2784,6 +3636,56 @@ "nextToken":{"shape":"NextToken"} } }, + "ListPolicyEventsRequest":{ + "type":"structure", + "required":["policyArn"], + "members":{ + "policyArn":{ + "shape":"Arn", + "location":"querystring", + "locationName":"policyArn" + }, + "eventTypes":{ + "shape":"PolicyEventTypeList", + "documentation":"

    The type of events to include in the results.

    ", + "location":"querystring", + "locationName":"eventTypes" + }, + "startTime":{ + "shape":"Timestamp", + "documentation":"

    The start time for filtering events.

    ", + "location":"querystring", + "locationName":"startTime" + }, + "endTime":{ + "shape":"Timestamp", + "documentation":"

    The end time for filtering events.

    ", + "location":"querystring", + "locationName":"endTime" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListPolicyEventsResponse":{ + "type":"structure", + "required":["events"], + "members":{ + "events":{ + "shape":"PolicyEventList", + "documentation":"

    The list of policy events.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, "ListReportsRequest":{ "type":"structure", "members":{ @@ -2799,6 +3701,11 @@ "location":"querystring", "locationName":"reportType" }, + "testRunId":{ + "shape":"TestRunId", + "location":"querystring", + "locationName":"testRunId" + }, "maxResults":{ "shape":"MaxResults", "location":"querystring", @@ -2822,6 +3729,48 @@ "nextToken":{"shape":"NextToken"} } }, + "ListResolvedTestRunTargetResourcesRequest":{ + "type":"structure", + "required":[ + "testRunId", + "serviceArn" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to list resolved target resources for.

    ", + "location":"uri", + "locationName":"testRunId" + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListResolvedTestRunTargetResourcesResponse":{ + "type":"structure", + "required":["resolvedTargetResources"], + "members":{ + "resolvedTargetResources":{ + "shape":"ResolvedTargetResourceList", + "documentation":"

    The list of resolved target resources.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, "ListResourcesRequest":{ "type":"structure", "required":["serviceArn"], @@ -2892,7 +3841,7 @@ }, "eventTypes":{ "shape":"ServiceEventTypeList", - "documentation":"

    Filter events by type.

    ", + "documentation":"

    The type of events to include in the results.

    ", "location":"querystring", "locationName":"eventTypes" }, @@ -3065,7 +4014,7 @@ }, "eventTypes":{ "shape":"SystemEventTypeList", - "documentation":"

    Filter events by type.

    ", + "documentation":"

    The type of events to include in the results.

    ", "location":"querystring", "locationName":"eventTypes" }, @@ -3153,14 +4102,24 @@ "tags":{"shape":"TagMap"} } }, - "ListUserJourneysRequest":{ + "ListTestRunDependenciesRequest":{ "type":"structure", - "required":["systemArn"], + "required":[ + "testRunId", + "serviceArn" + ], "members":{ - "systemArn":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to list dependencies for.

    ", + "location":"uri", + "locationName":"testRunId" + }, + "serviceArn":{ "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", "location":"querystring", - "locationName":"systemArn" + "locationName":"serviceArn" }, "maxResults":{ "shape":"MaxResults", @@ -3174,68 +4133,403 @@ } } }, - "ListUserJourneysResponse":{ + "ListTestRunDependenciesResponse":{ "type":"structure", - "required":["userJourneySummaries"], + "required":["dependencies"], "members":{ - "userJourneySummaries":{ - "shape":"UserJourneySummaryList", - "documentation":"

    The list of user journey summaries.

    " + "dependencies":{ + "shape":"TestRunDependencySummaryList", + "documentation":"

    The list of dependencies the test run blocked.

    " }, "nextToken":{"shape":"NextToken"} } }, - "Long":{ - "type":"long", - "box":true - }, - "LongDescription":{ - "type":"string", - "documentation":"

    Resource description for services and policies.

    ", - "max":615, - "min":0 - }, - "MaxResults":{ - "type":"integer", - "documentation":"

    Pagination page size.

    ", - "box":true, - "max":100, - "min":1 - }, - "MultiAzDisasterRecoveryApproach":{ - "type":"string", - "enum":[ - "ACTIVE_ACTIVE", - "HOT_STANDBY", - "WARM_STANDBY", - "PILOT_LIGHT", - "BACKUP_AND_RESTORE" - ] - }, - "MultiAzTargets":{ + "ListTestRunEventsRequest":{ "type":"structure", + "required":[ + "testRunId", + "serviceArn" + ], "members":{ - "rtoInMinutes":{ - "shape":"MultiAzTargetsRtoInMinutesInteger", - "documentation":"

    The recovery time objective (RTO) target for multi-AZ, in minutes.

    " + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to list events for.

    ", + "location":"uri", + "locationName":"testRunId" }, - "rpoInMinutes":{ - "shape":"MultiAzTargetsRpoInMinutesInteger", - "documentation":"

    The recovery point objective (RPO) target for multi-AZ, in minutes.

    " + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" }, - "disasterRecoveryApproach":{ - "shape":"MultiAzDisasterRecoveryApproach", - "documentation":"

    The disaster recovery approach for multi-AZ.

    " + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    Return events at or after this timestamp.

    ", + "location":"querystring", + "locationName":"startedAt" + }, + "endedAt":{ + "shape":"Timestamp", + "documentation":"

    Return events at or before this timestamp.

    ", + "location":"querystring", + "locationName":"endedAt" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" } - }, - "documentation":"

    Defines the multi-AZ disaster recovery targets for a resilience policy.

    " + } }, - "MultiAzTargetsRpoInMinutesInteger":{ - "type":"integer", - "box":true, - "min":0 + "ListTestRunEventsResponse":{ + "type":"structure", + "required":["events"], + "members":{ + "events":{ + "shape":"TestRunEventList", + "documentation":"

    The list of test run events.

    " + }, + "nextToken":{"shape":"NextToken"} + } }, - "MultiAzTargetsRtoInMinutesInteger":{ + "ListTestRunSourceEventsRequest":{ + "type":"structure", + "required":[ + "testRunId", + "serviceArn", + "sourceArn" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to list source events for.

    ", + "location":"uri", + "locationName":"testRunId" + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "sourceArn":{ + "shape":"TestRunSourceArn", + "documentation":"

    The ARN of the monitoring source to list events for, such as the ARN of a CloudWatch alarm. If the source was not monitored during the test run, the response is an empty list.

    ", + "location":"querystring", + "locationName":"sourceArn" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTestRunSourceEventsResponse":{ + "type":"structure", + "required":["testRunSourceEvents"], + "members":{ + "testRunSourceEvents":{ + "shape":"TestRunSourceEventList", + "documentation":"

    The list of source events, in chronological order.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "ListTestRunSourcesRequest":{ + "type":"structure", + "required":[ + "testRunId", + "serviceArn" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to list sources for.

    ", + "location":"uri", + "locationName":"testRunId" + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "type":{ + "shape":"TestRunSourceType", + "documentation":"

    Filter sources by type.

    ", + "location":"querystring", + "locationName":"type" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTestRunSourcesResponse":{ + "type":"structure", + "required":["testRunSources"], + "members":{ + "testRunSources":{ + "shape":"TestRunSourceSummaryList", + "documentation":"

    The list of monitoring source snapshots.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "ListTestRunsRequest":{ + "type":"structure", + "required":["serviceArn"], + "members":{ + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service to list test runs for.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "testId":{ + "shape":"TestId", + "documentation":"

    Filter test runs by test identifier.

    ", + "location":"querystring", + "locationName":"testId" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTestRunsResponse":{ + "type":"structure", + "required":["testRuns"], + "members":{ + "testRuns":{ + "shape":"TestRunSummaryList", + "documentation":"

    The list of test run summaries.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "ListTestSourcesRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to list sources for.

    ", + "location":"uri", + "locationName":"testId" + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "type":{ + "shape":"TestSourceType", + "documentation":"

    Filter sources by type.

    ", + "location":"querystring", + "locationName":"type" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTestSourcesResponse":{ + "type":"structure", + "required":["testSources"], + "members":{ + "testSources":{ + "shape":"TestSourceSummaryList", + "documentation":"

    The list of configured monitoring sources.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "ListTestTemplatesRequest":{ + "type":"structure", + "members":{} + }, + "ListTestTemplatesResponse":{ + "type":"structure", + "required":["testTemplates"], + "members":{ + "testTemplates":{ + "shape":"TestTemplateSummaryList", + "documentation":"

    The list of test template summaries.

    " + } + } + }, + "ListTestsRequest":{ + "type":"structure", + "required":["serviceArn"], + "members":{ + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service to list tests for.

    ", + "location":"querystring", + "locationName":"serviceArn" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListTestsResponse":{ + "type":"structure", + "required":["tests"], + "members":{ + "tests":{ + "shape":"TestSummaryList", + "documentation":"

    The list of test summaries.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "ListUserJourneysRequest":{ + "type":"structure", + "required":["systemArn"], + "members":{ + "systemArn":{ + "shape":"Arn", + "location":"querystring", + "locationName":"systemArn" + }, + "maxResults":{ + "shape":"MaxResults", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"NextToken", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListUserJourneysResponse":{ + "type":"structure", + "required":["userJourneySummaries"], + "members":{ + "userJourneySummaries":{ + "shape":"UserJourneySummaryList", + "documentation":"

    The list of user journey summaries.

    " + }, + "nextToken":{"shape":"NextToken"} + } + }, + "LoggingConfiguration":{ + "type":"structure", + "members":{ + "s3BucketName":{ + "shape":"String", + "documentation":"

    The name of the S3 bucket for log delivery.

    " + }, + "cloudWatchLogGroupArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the CloudWatch Logs log group for log delivery.

    " + }, + "logSchemaVersion":{ + "shape":"String", + "documentation":"

    The version of the log schema.

    " + } + }, + "documentation":"

    Configuration for test execution logging destinations.

    " + }, + "Long":{ + "type":"long", + "box":true + }, + "LongDescription":{ + "type":"string", + "documentation":"

    Resource description for services and policies.

    ", + "max":615, + "min":0 + }, + "MaxResults":{ + "type":"integer", + "documentation":"

    Pagination page size.

    ", + "box":true, + "max":100, + "min":1 + }, + "MultiAzDisasterRecoveryApproach":{ + "type":"string", + "enum":[ + "ACTIVE_ACTIVE", + "HOT_STANDBY", + "WARM_STANDBY", + "PILOT_LIGHT", + "BACKUP_AND_RESTORE" + ] + }, + "MultiAzTargets":{ + "type":"structure", + "members":{ + "rtoInMinutes":{ + "shape":"MultiAzTargetsRtoInMinutesInteger", + "documentation":"

    The recovery time objective (RTO) target for multi-AZ, in minutes.

    " + }, + "rpoInMinutes":{ + "shape":"MultiAzTargetsRpoInMinutesInteger", + "documentation":"

    The recovery point objective (RPO) target for multi-AZ, in minutes.

    " + }, + "disasterRecoveryApproach":{ + "shape":"MultiAzDisasterRecoveryApproach", + "documentation":"

    The disaster recovery approach for multi-AZ.

    " + } + }, + "documentation":"

    Defines the multi-AZ disaster recovery targets for a resilience policy.

    " + }, + "MultiAzTargetsRpoInMinutesInteger":{ + "type":"integer", + "box":true, + "min":0 + }, + "MultiAzTargetsRtoInMinutesInteger":{ "type":"integer", "box":true, "min":0 @@ -3285,7 +4579,50 @@ "min":1, "pattern":"\\S{1,2000}" }, - "ObservabilityRecommendation":{ + "ObservabilityAlarmInput":{ + "type":"structure", + "required":["alarmArn"], + "members":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + } + }, + "documentation":"

    Identifies an observability alarm by its ARN.

    " + }, + "ObservabilityAlarmSummary":{ + "type":"structure", + "required":[ + "alarmArn", + "alarmName", + "region", + "accountId" + ], + "members":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + }, + "alarmName":{ + "shape":"String", + "documentation":"

    The name of the CloudWatch alarm.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The Region of the CloudWatch alarm.

    " + }, + "accountId":{ + "shape":"String", + "documentation":"

    The account ID that owns the CloudWatch alarm.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the source was configured.

    " + } + }, + "documentation":"

    Summary information about a configured observability alarm.

    " + }, + "ObservabilityRecommendation":{ "type":"structure", "members":{ "suggestedChanges":{ @@ -3313,6 +4650,28 @@ "min":16, "pattern":"ou-[a-z0-9]{4,32}-[a-z0-9]{8,32}" }, + "ParameterKey":{ + "type":"string", + "documentation":"

    The key of a test parameter.

    ", + "max":256, + "min":1, + "pattern":"[\\w.-]+" + }, + "ParameterType":{ + "type":"string", + "documentation":"

    The data type of a test template parameter.

    ", + "enum":[ + "STRING", + "STRING_LIST", + "INTEGER" + ] + }, + "ParameterValue":{ + "type":"string", + "documentation":"

    A value of a test parameter.

    ", + "max":1024, + "min":0 + }, "PermissionModel":{ "type":"structure", "required":["invokerRoleName"], @@ -3351,6 +4710,14 @@ "shape":"DataRecoveryTargets", "documentation":"

    The data recovery targets defined in the policy.

    " }, + "sharingEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether cross-account sharing is enabled.

    " + }, + "organizationId":{ + "shape":"OrganizationId", + "documentation":"

    The identifier of the organization this policy is shared with.

    " + }, "kmsKeyId":{"shape":"KmsKeyId"}, "tags":{"shape":"TagMap"}, "associatedServiceCount":{ @@ -3368,6 +4735,17 @@ }, "documentation":"

    Represents a resilience policy that defines availability and disaster recovery requirements.

    " }, + "PolicyAttachedToServiceMetadata":{ + "type":"structure", + "members":{ + "serviceArn":{"shape":"Arn"}, + "accountId":{ + "shape":"AccountId", + "documentation":"

    The account that owns the service.

    " + } + }, + "documentation":"

    Contains details about the service that started using the policy, such as the account that owns the service.

    " + }, "PolicyComponent":{ "type":"string", "enum":[ @@ -3377,6 +4755,141 @@ "DATA_RECOVERY" ] }, + "PolicyDeletedMetadata":{ + "type":"structure", + "members":{ + "affectedServiceCount":{ + "shape":"Integer", + "documentation":"

    The number of services that were using the policy when it was deleted.

    " + } + }, + "documentation":"

    Contains details about a policy that was deleted, including the number of services that were affected.

    " + }, + "PolicyDetachedFromServiceMetadata":{ + "type":"structure", + "members":{ + "serviceArn":{"shape":"Arn"}, + "accountId":{ + "shape":"AccountId", + "documentation":"

    The account that owns the service.

    " + } + }, + "documentation":"

    Contains details about the service that stopped using the policy, such as the account that owns the service.

    " + }, + "PolicyDisassociationReason":{ + "type":"string", + "enum":[ + "REPLACED_BY_UPDATE", + "SHARING_REVOKED", + "POLICY_DELETED" + ] + }, + "PolicyEvent":{ + "type":"structure", + "required":[ + "eventId", + "timestamp", + "eventType", + "policyArn", + "actor", + "eventDetails" + ], + "members":{ + "eventId":{ + "shape":"Uuid", + "documentation":"

    The identifier of the event.

    " + }, + "timestamp":{ + "shape":"Timestamp", + "documentation":"

    The time the event occurred.

    " + }, + "eventType":{ + "shape":"PolicyEventType", + "documentation":"

    The type of the event.

    " + }, + "policyArn":{"shape":"Arn"}, + "actor":{"shape":"EventActor"}, + "eventDetails":{ + "shape":"PolicyEventDetails", + "documentation":"

    The details of the event.

    " + } + }, + "documentation":"

    An event on the timeline of a resilience policy.

    " + }, + "PolicyEventDetails":{ + "type":"structure", + "required":[ + "title", + "description" + ], + "members":{ + "title":{ + "shape":"String", + "documentation":"

    A short summary of the event.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    A description of the event.

    " + }, + "eventMetadata":{ + "shape":"PolicyEventMetadata", + "documentation":"

    The event-specific metadata, with one member populated according to the event type.

    " + } + }, + "documentation":"

    Contains the title, description, and event-specific metadata for a single event on the timeline of a resilience policy.

    " + }, + "PolicyEventList":{ + "type":"list", + "member":{"shape":"PolicyEvent"} + }, + "PolicyEventMetadata":{ + "type":"structure", + "members":{ + "policyAttachedToService":{ + "shape":"PolicyAttachedToServiceMetadata", + "documentation":"

    Contains details about the service that started using the policy, such as the account that owns the service.

    " + }, + "policyDetachedFromService":{ + "shape":"PolicyDetachedFromServiceMetadata", + "documentation":"

    Contains details about the service that stopped using the policy, such as the account that owns the service.

    " + }, + "policySharingRevoked":{ + "shape":"PolicySharingRevokedMetadata", + "documentation":"

    Contains details about a policy for which organization sharing was revoked, including the number of services that were affected.

    " + }, + "policyDeleted":{ + "shape":"PolicyDeletedMetadata", + "documentation":"

    Contains details about a policy that was deleted, including the number of services that were affected.

    " + } + }, + "documentation":"

    Contains the event-specific metadata for a policy event. Exactly one member is populated, according to the event type.

    • policyAttachedToService — a service started using the policy.

    • policyDetachedFromService — a service stopped using the policy.

    • policySharingRevoked — cross-account sharing was disabled for the policy.

    • policyDeleted — the policy was deleted.

    ", + "union":true + }, + "PolicyEventType":{ + "type":"string", + "enum":[ + "POLICY_ATTACHED_TO_SERVICE", + "POLICY_DETACHED_FROM_SERVICE", + "POLICY_SHARING_REVOKED", + "POLICY_DELETED" + ] + }, + "PolicyEventTypeList":{ + "type":"list", + "member":{"shape":"PolicyEventType"}, + "max":4, + "min":0 + }, + "PolicySharingRevokedMetadata":{ + "type":"structure", + "members":{ + "affectedServiceCount":{ + "shape":"Integer", + "documentation":"

    The number of services that were using the policy when sharing was revoked.

    " + } + }, + "documentation":"

    Contains details about a policy for which organization sharing was revoked, including the number of services that were affected.

    " + }, "PolicySummary":{ "type":"structure", "required":[ @@ -3402,6 +4915,14 @@ "shape":"DataRecoveryTargets", "documentation":"

    The data recovery targets defined in the policy.

    " }, + "sharingEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether cross-account sharing is enabled.

    " + }, + "organizationId":{ + "shape":"OrganizationId", + "documentation":"

    The identifier of the organization this policy is shared with.

    " + }, "associatedServiceCount":{ "shape":"Integer", "documentation":"

    The number of services associated with this policy.

    " @@ -3428,6 +4949,32 @@ "CROSS_ACCOUNT" ] }, + "PutTestSourcesRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn", + "testSources" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to add sources to.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " + }, + "testSources":{ + "shape":"TestSourceInputList", + "documentation":"

    The monitoring sources to add or update.

    " + } + } + }, + "PutTestSourcesResponse":{ + "type":"structure", + "members":{} + }, "QueryDataPoint":{ "type":"structure", "required":[ @@ -3493,6 +5040,13 @@ "max":5, "min":1 }, + "RegionSwitchExecutionId":{ + "type":"string", + "documentation":"

    The identifier of an ARC Region switch plan execution detected during a test run.

    ", + "max":64, + "min":1, + "pattern":"[a-z]{2}(-[a-z]+)+-[0-9]+/[0-9a-fA-F]{16}" + }, "ReportGenerationErrorCode":{ "type":"string", "documentation":"

    Error codes for failed report generation.

    ", @@ -3525,6 +5079,8 @@ "shape":"Uuid", "documentation":"

    Present for FAILURE_MODE reports.

    " }, + "testRunId":{"shape":"TestRunId"}, + "testTemplateArn":{"shape":"ServiceOwnedArn"}, "createdAt":{ "shape":"Timestamp", "documentation":"

    The timestamp when the report was created.

    " @@ -3581,7 +5137,68 @@ }, "ReportType":{ "type":"string", - "enum":["FAILURE_MODE"] + "enum":[ + "FAILURE_MODE", + "TESTING" + ] + }, + "ResolvedTargetInformation":{ + "type":"map", + "key":{"shape":"ResolvedTargetInformationKey"}, + "value":{"shape":"ResolvedTargetInformationValue"}, + "max":50, + "min":0 + }, + "ResolvedTargetInformationKey":{ + "type":"string", + "documentation":"

    The key of a resolved target information entry.

    ", + "max":128, + "min":1 + }, + "ResolvedTargetInformationValue":{ + "type":"string", + "documentation":"

    The value of a resolved target information entry.

    ", + "max":2048, + "min":0 + }, + "ResolvedTargetResource":{ + "type":"structure", + "required":[ + "resourceType", + "targetName", + "targetInformation" + ], + "members":{ + "resourceType":{ + "shape":"ResolvedTargetResourceResourceTypeString", + "documentation":"

    The AWS FIS resource type the target belongs to, such as aws:ec2:instance, aws:ecs:task, or aws:eks:pod.

    " + }, + "targetName":{ + "shape":"ResolvedTargetResourceTargetNameString", + "documentation":"

    The name of the target in the AWS FIS experiment template.

    " + }, + "targetInformation":{ + "shape":"ResolvedTargetInformation", + "documentation":"

    The raw target information map as returned by AWS FIS.

    " + } + }, + "documentation":"

    A single AWS resource that AWS Fault Injection Service (AWS FIS) resolved as a target during a test run.

    " + }, + "ResolvedTargetResourceList":{ + "type":"list", + "member":{"shape":"ResolvedTargetResource"}, + "max":100, + "min":0 + }, + "ResolvedTargetResourceResourceTypeString":{ + "type":"string", + "max":256, + "min":1 + }, + "ResolvedTargetResourceTargetNameString":{ + "type":"string", + "max":256, + "min":1 }, "Resource":{ "type":"structure", @@ -3797,7 +5414,7 @@ "policyArn":{"shape":"Arn"}, "regions":{ "shape":"RegionList", - "documentation":"

    The AWS Regions where the service operates.

    " + "documentation":"

    The Regions where the service operates.

    " }, "permissionModel":{ "shape":"PermissionModel", @@ -4169,52 +5786,776 @@ "shape":"String", "documentation":"

    The identifier of the service function.

    " }, - "serviceFunctionName":{ + "serviceFunctionName":{ + "shape":"String", + "documentation":"

    The name of the service function.

    " + }, + "resourcesRemoved":{ + "shape":"ArnList", + "documentation":"

    The list of resource ARNs that were removed.

    " + } + }, + "documentation":"

    Metadata for a service function resources removed event.

    " + }, + "ServiceFunctionSource":{ + "type":"string", + "enum":[ + "AI_GENERATED", + "USER" + ] + }, + "ServiceFunctionUpdatedMetadata":{ + "type":"structure", + "members":{ + "serviceFunctionId":{ + "shape":"String", + "documentation":"

    The identifier of the service function.

    " + }, + "serviceFunctionName":{ + "shape":"String", + "documentation":"

    The name of the service function.

    " + }, + "resourcesAdded":{ + "shape":"ArnList", + "documentation":"

    The list of resource ARNs that were added.

    " + }, + "resourcesRemoved":{ + "shape":"ArnList", + "documentation":"

    The list of resource ARNs that were removed.

    " + } + }, + "documentation":"

    Metadata for a service function updated event.

    " + }, + "ServiceInputSourcesUpdatedMetadata":{ + "type":"structure", + "members":{}, + "documentation":"

    Metadata for a service input sources updated event.

    " + }, + "ServiceOwnedArn":{ + "type":"string", + "documentation":"

    An ARN owned by the service. Accepts either a standard 12-digit account ID or the literal \"aws\" for AWS-managed resources, such as AWS-managed test templates.

    ", + "min":31, + "pattern":"arn:(aws|aws-cn|aws-iso|aws-iso-[a-z]{1}|aws-us-gov):[A-Za-z0-9][A-Za-z0-9_/.-]{0,62}:([a-z]{2}-((iso[a-z]{0,1}-)|(gov-)){0,1}[a-z]+-[0-9]):([0-9]{12}|aws):[A-Za-z0-9/][A-Za-z0-9:_/+.-]{0,1023}" + }, + "ServicePolicyAssociatedMetadata":{ + "type":"structure", + "members":{ + "policyName":{ + "shape":"String", + "documentation":"

    The name of the associated policy.

    " + }, + "policyArn":{"shape":"Arn"}, + "policyOwnerAccountId":{ + "shape":"String", + "documentation":"

    The account that owns the policy.

    " + }, + "policySource":{ + "shape":"PolicyValueSource", + "documentation":"

    The source of the policy.

    • SELF — the policy belongs to the account that owns the service.

    • CROSS_ACCOUNT — the policy belongs to another account and was shared with the organization.

    " + } + }, + "documentation":"

    Metadata for a service policy associated event.

    " + }, + "ServicePolicyDisassociatedMetadata":{ + "type":"structure", + "members":{ + "policyName":{ + "shape":"String", + "documentation":"

    The name of the disassociated policy.

    " + }, + "policyArn":{"shape":"Arn"}, + "policyOwnerAccountId":{ + "shape":"String", + "documentation":"

    The account that owns the policy.

    " + }, + "policySource":{ + "shape":"PolicyValueSource", + "documentation":"

    The source of the policy.

    • SELF — the policy belongs to the account that owns the service.

    • CROSS_ACCOUNT — the policy belongs to another account and was shared with the organization.

    " + }, + "reason":{ + "shape":"PolicyDisassociationReason", + "documentation":"

    The reason the policy was disassociated from the service.

    " + } + }, + "documentation":"

    Metadata for a service policy disassociated event.

    " + }, + "ServiceQuotaExceededException":{ + "type":"structure", + "required":["message"], + "members":{ + "message":{"shape":"String"} + }, + "documentation":"

    Service quota exceeded.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, + "exception":true + }, + "ServiceReference":{ + "type":"structure", + "members":{ + "serviceId":{ + "shape":"String", + "documentation":"

    The identifier of the referenced service.

    " + }, + "serviceName":{ + "shape":"String", + "documentation":"

    The name of the referenced service.

    " + } + }, + "documentation":"

    A reference to a service by ID and name.

    " + }, + "ServiceReferenceChanges":{ + "type":"structure", + "members":{ + "added":{ + "shape":"ServiceReferenceList", + "documentation":"

    The list of service references that were added.

    " + }, + "removed":{ + "shape":"ServiceReferenceList", + "documentation":"

    The list of service references that were removed.

    " + } + }, + "documentation":"

    Describes changes to service references.

    " + }, + "ServiceReferenceList":{ + "type":"list", + "member":{"shape":"ServiceReference"} + }, + "ServiceReportConfiguration":{ + "type":"structure", + "required":["reportOutputs"], + "members":{ + "reportOutputs":{ + "shape":"ReportOutputConfigurationList", + "documentation":"

    Output destinations for generated reports.

    " + } + }, + "documentation":"

    Configuration for automatic report generation on a Service.

    " + }, + "ServiceResource":{ + "type":"structure", + "required":[ + "resourceIdentifier", + "resource" + ], + "members":{ + "resourceIdentifier":{ + "shape":"String", + "documentation":"

    The identifier of the resource.

    " + }, + "inputSource":{ + "shape":"InputSource", + "documentation":"

    The input source that discovered the resource.

    " + }, + "resource":{ + "shape":"Resource", + "documentation":"

    The resource details.

    " + } + }, + "documentation":"

    Represents a resource associated with a service.

    " + }, + "ServiceResourceList":{ + "type":"list", + "member":{"shape":"ServiceResource"} + }, + "ServiceResourcesAssociatedMetadata":{ + "type":"structure", + "members":{ + "resourceCount":{ + "shape":"Integer", + "documentation":"

    The number of resources associated.

    " + }, + "resourceTypes":{ + "shape":"ResourceTypeList", + "documentation":"

    The types of resources associated.

    " + } + }, + "documentation":"

    Metadata for a service resources associated event.

    " + }, + "ServiceResourcesDisassociatedMetadata":{ + "type":"structure", + "members":{ + "resourceCount":{ + "shape":"Integer", + "documentation":"

    The number of resources disassociated.

    " + }, + "resourceTypes":{ + "shape":"ResourceTypeList", + "documentation":"

    The types of resources disassociated.

    " + } + }, + "documentation":"

    Metadata for a service resources disassociated event.

    " + }, + "ServiceSummary":{ + "type":"structure", + "required":[ + "serviceArn", + "name" + ], + "members":{ + "serviceArn":{"shape":"Arn"}, + "name":{"shape":"EntityName"}, + "associatedSystems":{ + "shape":"AssociatedSystemList", + "documentation":"

    The systems associated with the service.

    " + }, + "regions":{ + "shape":"RegionList", + "documentation":"

    The Regions where the service operates.

    " + }, + "policyArn":{"shape":"Arn"}, + "assessmentStatus":{ + "shape":"AssessmentStatus", + "documentation":"

    The current assessment status of the service.

    " + }, + "openFindingsCount":{ + "shape":"Integer", + "documentation":"

    The number of open findings.

    " + }, + "resolvedFindingsCount":{ + "shape":"Integer", + "documentation":"

    The number of resolved findings.

    " + }, + "dependencyDiscovery":{ + "shape":"DependencyDiscoveryConfig", + "documentation":"

    The dependency discovery configuration.

    " + }, + "achievability":{ + "shape":"Achievability", + "documentation":"

    The achievability status of the service's resilience targets.

    " + }, + "organizationId":{ + "shape":"OrganizationId", + "documentation":"

    Displayed only if caller has access.

    " + }, + "ouId":{ + "shape":"OuId", + "documentation":"

    Displayed only if caller has access.

    " + }, + "accountId":{ + "shape":"AccountId", + "documentation":"

    Displayed only if caller has access.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the service was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the service was last updated.

    " + } + }, + "documentation":"

    Contains summary information about a service.

    " + }, + "ServiceSummaryList":{ + "type":"list", + "member":{"shape":"ServiceSummary"} + }, + "ServiceSystemAssociatedMetadata":{ + "type":"structure", + "members":{ + "systemName":{ + "shape":"String", + "documentation":"

    The name of the associated system.

    " + }, + "systemArn":{"shape":"Arn"} + }, + "documentation":"

    Metadata for a service system associated event.

    " + }, + "ServiceSystemDisassociatedMetadata":{ + "type":"structure", + "members":{ + "systemId":{ + "shape":"String", + "documentation":"

    The identifier of the disassociated system.

    " + }, + "systemName":{ + "shape":"String", + "documentation":"

    The name of the disassociated system.

    " + }, + "systemArn":{"shape":"Arn"} + }, + "documentation":"

    Metadata for a service system disassociated event.

    " + }, + "ServiceTopologyEdgeSummary":{ + "type":"structure", + "required":[ + "sourceResourceIdentifier", + "destinationResourceIdentifier" + ], + "members":{ + "sourceResourceIdentifier":{ + "shape":"String", + "documentation":"

    The identifier of the source resource.

    " + }, + "destinationResourceIdentifier":{ + "shape":"String", + "documentation":"

    The identifier of the destination resource.

    " + }, + "sourceRegion":{ + "shape":"AwsRegion", + "documentation":"

    The AWS Region of the source resource.

    " + }, + "destinationRegion":{ + "shape":"AwsRegion", + "documentation":"

    The AWS Region of the destination resource.

    " + }, + "sourceAccount":{ + "shape":"AwsAccountId", + "documentation":"

    The AWS account ID of the source resource.

    " + }, + "destinationAccount":{ + "shape":"AwsAccountId", + "documentation":"

    The AWS account ID of the destination resource.

    " + }, + "properties":{ + "shape":"EdgePropertyList", + "documentation":"

    The properties of the topology edge.

    " + } + }, + "documentation":"

    Contains summary information about a service topology edge.

    " + }, + "ServiceTopologyEdgeSummaryList":{ + "type":"list", + "member":{"shape":"ServiceTopologyEdgeSummary"} + }, + "ServiceWorkflowUpdatedMetadata":{ + "type":"structure", + "members":{ + "serviceFunctionId":{ + "shape":"String", + "documentation":"

    The identifier of the service function.

    " + }, + "serviceFunctionName":{ + "shape":"String", + "documentation":"

    The name of the service function.

    " + } + }, + "documentation":"

    Metadata for a service workflow updated event.

    " + }, + "SloSource":{ + "type":"structure", + "members":{ + "value":{ + "shape":"Double", + "documentation":"

    The availability SLO percentage value.

    " + }, + "policyName":{"shape":"EntityName"}, + "source":{ + "shape":"PolicyValueSource", + "documentation":"

    Indicates whether the value comes from the service's own account or a cross-account policy.

    " + } + }, + "documentation":"

    Contains the effective availability SLO value and its source.

    " + }, + "SortOrder":{ + "type":"string", + "documentation":"

    The order in which to sort results.

    ", + "enum":[ + "ASC", + "DESC" + ] + }, + "StartDependencyInsightsRequest":{ + "type":"structure", + "required":["serviceArn"], + "members":{ + "serviceArn":{"shape":"Arn"}, + "clientToken":{ + "shape":"ClientToken", + "idempotencyToken":true + } + } + }, + "StartDependencyInsightsResponse":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"DependencyInsightsStatus", + "documentation":"

    The status of the dependency insights generation. Valid values:

    • IN_PROGRESS - Insights generation is in progress.

    • COMPLETED - Insights generation completed successfully.

    • FAILED - Insights generation failed. Call GetDependencyInsights for the error code and message.

    " + } + } + }, + "StartFailureModeAssessmentRequest":{ + "type":"structure", + "required":["serviceArn"], + "members":{ + "serviceArn":{"shape":"Arn"}, + "clientToken":{ + "shape":"ClientToken", + "idempotencyToken":true + } + } + }, + "StartFailureModeAssessmentResponse":{ + "type":"structure", + "members":{ + "assessmentId":{ + "shape":"Uuid", + "documentation":"

    The unique identifier of the started assessment.

    " + }, + "serviceArn":{"shape":"Arn"}, + "assessmentStatus":{ + "shape":"AssessmentStatus", + "documentation":"

    The status of the started assessment.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the assessment started.

    " + } + } + }, + "StartTestRunRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to run.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " + } + } + }, + "StartTestRunResponse":{ + "type":"structure", + "required":[ + "testRunId", + "status", + "experimentArns" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the started test run.

    " + }, + "status":{ + "shape":"TestRunStatus", + "documentation":"

    The status of the started test run.

    " + }, + "experimentArns":{ + "shape":"ExperimentArnList", + "documentation":"

    The ARNs of the AWS Fault Injection Service (AWS FIS) experiments started for the run.

    " + } + } + }, + "StopCondition":{ + "type":"structure", + "required":[ + "source", + "value" + ], + "members":{ + "source":{ + "shape":"StopConditionSource", + "documentation":"

    The source of the stop condition.

    " + }, + "value":{ + "shape":"String", + "documentation":"

    The value of the stop condition, such as the ARN of the CloudWatch alarm.

    " + } + }, + "documentation":"

    A CloudWatch alarm that automatically stops a test run if it breaches its threshold.

    " + }, + "StopConditionList":{ + "type":"list", + "member":{"shape":"StopCondition"} + }, + "StopConditionSource":{ + "type":"string", + "documentation":"

    The source of a test stop condition, matching AWS Fault Injection Service (AWS FIS) stop condition sources.

    ", + "enum":[ + "aws:cloudwatch:alarm", + "none" + ] + }, + "StopTestRunRequest":{ + "type":"structure", + "required":[ + "testRunId", + "serviceArn" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the test run to stop.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    " + } + } + }, + "StopTestRunResponse":{ + "type":"structure", + "required":[ + "testRunId", + "status" + ], + "members":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The identifier of the stopped test run.

    " + }, + "status":{ + "shape":"TestRunStatus", + "documentation":"

    The status of the test run.

    " + } + } + }, + "String":{"type":"string"}, + "StringChange":{ + "type":"structure", + "members":{ + "oldValue":{ + "shape":"String", + "documentation":"

    The old value.

    " + }, + "newValue":{ + "shape":"String", + "documentation":"

    The new value.

    " + } + }, + "documentation":"

    Describes a change from one string value to another.

    " + }, + "StringList":{ + "type":"list", + "member":{"shape":"ParameterValue"}, + "max":10, + "min":0 + }, + "SuccessCriteriaAlarmInput":{ + "type":"structure", + "required":["alarmArn"], + "members":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + } + }, + "documentation":"

    Identifies a success criteria alarm by its ARN.

    " + }, + "SuccessCriteriaAlarmSummary":{ + "type":"structure", + "required":[ + "alarmArn", + "alarmName", + "region", + "accountId" + ], + "members":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + }, + "alarmName":{ + "shape":"String", + "documentation":"

    The name of the CloudWatch alarm.

    " + }, + "region":{ + "shape":"String", + "documentation":"

    The Region of the CloudWatch alarm.

    " + }, + "accountId":{ + "shape":"String", + "documentation":"

    The account ID that owns the CloudWatch alarm.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the source was configured.

    " + } + }, + "documentation":"

    Summary information about a configured success criteria alarm.

    " + }, + "SuggestedChangesList":{ + "type":"list", + "member":{"shape":"EntityDescription"}, + "max":10, + "min":0 + }, + "System":{ + "type":"structure", + "required":[ + "systemArn", + "systemId", + "name" + ], + "members":{ + "systemArn":{"shape":"Arn"}, + "systemId":{"shape":"SystemId"}, + "name":{"shape":"EntityName"}, + "description":{"shape":"EntityDescription"}, + "sharingEnabled":{ + "shape":"Boolean", + "documentation":"

    Indicates whether cross-account sharing is enabled.

    " + }, + "tags":{"shape":"TagMap"}, + "kmsKeyId":{"shape":"KmsKeyId"}, + "organizationId":{ + "shape":"OrganizationId", + "documentation":"

    The AWS Organizations identifier for the system.

    " + }, + "ouId":{ + "shape":"OuId", + "documentation":"

    The organizational unit (OU) identifier for the system.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the system was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the system was last updated.

    " + } + }, + "documentation":"

    Represents a system in Resilience Hub. A system is a logical grouping of services.

    " + }, + "SystemCreatedMetadata":{ + "type":"structure", + "members":{}, + "documentation":"

    Metadata for a system created event.

    " + }, + "SystemDeletedMetadata":{ + "type":"structure", + "members":{}, + "documentation":"

    Metadata for a system deleted event.

    " + }, + "SystemEvent":{ + "type":"structure", + "required":[ + "eventId", + "timestamp", + "eventType", + "systemArn", + "actor", + "eventDetails" + ], + "members":{ + "eventId":{ + "shape":"Uuid", + "documentation":"

    The unique identifier of the event.

    " + }, + "timestamp":{ + "shape":"Timestamp", + "documentation":"

    The timestamp of the event.

    " + }, + "eventType":{ + "shape":"SystemEventType", + "documentation":"

    The type of the event.

    " + }, + "systemArn":{"shape":"Arn"}, + "actor":{ + "shape":"EventActor", + "documentation":"

    The actor that triggered the event.

    " + }, + "eventDetails":{ + "shape":"SystemEventDetails", + "documentation":"

    The details of the event.

    " + } + }, + "documentation":"

    Represents an event in the system event log.

    " + }, + "SystemEventDetails":{ + "type":"structure", + "required":[ + "title", + "description" + ], + "members":{ + "title":{ + "shape":"String", + "documentation":"

    The title of the event.

    " + }, + "description":{ "shape":"String", - "documentation":"

    The name of the service function.

    " + "documentation":"

    The description of the event.

    " }, - "resourcesRemoved":{ - "shape":"ArnList", - "documentation":"

    The list of resource ARNs that were removed.

    " - } + "eventMetadata":{"shape":"SystemEventMetadata"} }, - "documentation":"

    Metadata for a service function resources removed event.

    " + "documentation":"

    Contains the details of a system event.

    " }, - "ServiceFunctionSource":{ - "type":"string", - "enum":[ - "AI_GENERATED", - "USER" - ] + "SystemEventList":{ + "type":"list", + "member":{"shape":"SystemEvent"} }, - "ServiceFunctionUpdatedMetadata":{ + "SystemEventMetadata":{ "type":"structure", "members":{ - "serviceFunctionId":{ - "shape":"String", - "documentation":"

    The identifier of the service function.

    " + "systemCreated":{ + "shape":"SystemCreatedMetadata", + "documentation":"

    Metadata for a system created event.

    " }, - "serviceFunctionName":{ - "shape":"String", - "documentation":"

    The name of the service function.

    " + "systemDeleted":{ + "shape":"SystemDeletedMetadata", + "documentation":"

    Metadata for a system deleted event.

    " }, - "resourcesAdded":{ - "shape":"ArnList", - "documentation":"

    The list of resource ARNs that were added.

    " + "systemUserJourneyCreated":{ + "shape":"SystemUserJourneyCreatedMetadata", + "documentation":"

    Metadata for a system user journey created event.

    " }, - "resourcesRemoved":{ - "shape":"ArnList", - "documentation":"

    The list of resource ARNs that were removed.

    " + "systemUserJourneyUpdated":{ + "shape":"SystemUserJourneyUpdatedMetadata", + "documentation":"

    Metadata for a system user journey updated event.

    " + }, + "systemUserJourneyDeleted":{ + "shape":"SystemUserJourneyDeletedMetadata", + "documentation":"

    Metadata for a system user journey deleted event.

    " + }, + "systemServiceAssociated":{ + "shape":"SystemServiceAssociatedMetadata", + "documentation":"

    Metadata for a system service associated event.

    " + }, + "systemServiceDisassociated":{ + "shape":"SystemServiceDisassociatedMetadata", + "documentation":"

    Metadata for a system service disassociated event.

    " + }, + "systemPolicyAssociated":{ + "shape":"SystemPolicyAssociatedMetadata", + "documentation":"

    Metadata for a system policy associated event.

    " + }, + "systemPolicyDisassociated":{ + "shape":"SystemPolicyDisassociatedMetadata", + "documentation":"

    Metadata for a system policy disassociated event.

    " } }, - "documentation":"

    Metadata for a service function updated event.

    " + "documentation":"

    Type-specific metadata for each system event type.

    ", + "union":true }, - "ServiceInputSourcesUpdatedMetadata":{ - "type":"structure", - "members":{}, - "documentation":"

    Metadata for a service input sources updated event.

    " + "SystemEventType":{ + "type":"string", + "enum":[ + "SYSTEM_CREATED", + "SYSTEM_DELETED", + "SYSTEM_USER_JOURNEY_CREATED", + "SYSTEM_USER_JOURNEY_UPDATED", + "SYSTEM_USER_JOURNEY_DELETED", + "SYSTEM_SERVICE_ASSOCIATED", + "SYSTEM_SERVICE_DISASSOCIATED", + "SYSTEM_POLICY_ASSOCIATED", + "SYSTEM_POLICY_DISASSOCIATED" + ] }, - "ServicePolicyAssociatedMetadata":{ + "SystemEventTypeList":{ + "type":"list", + "member":{"shape":"SystemEventType"} + }, + "SystemId":{ + "type":"string", + "documentation":"

    System ID for cross-account use without exposing account structure.

    ", + "max":255, + "min":1, + "pattern":"\\S{1,255}" + }, + "SystemPolicyAssociatedMetadata":{ "type":"structure", "members":{ "policyName":{ @@ -4223,9 +6564,9 @@ }, "policyArn":{"shape":"Arn"} }, - "documentation":"

    Metadata for a service policy associated event.

    " + "documentation":"

    Metadata for a system policy associated event.

    " }, - "ServicePolicyDisassociatedMetadata":{ + "SystemPolicyDisassociatedMetadata":{ "type":"structure", "members":{ "policyName":{ @@ -4234,713 +6575,1029 @@ }, "policyArn":{"shape":"Arn"} }, - "documentation":"

    Metadata for a service policy disassociated event.

    " + "documentation":"

    Metadata for a system policy disassociated event.

    " }, - "ServiceQuotaExceededException":{ + "SystemServiceAssociatedMetadata":{ "type":"structure", - "required":["message"], "members":{ - "message":{"shape":"String"} - }, - "documentation":"

    Service quota exceeded.

    ", - "error":{ - "httpStatusCode":402, - "senderFault":true + "serviceName":{ + "shape":"String", + "documentation":"

    The name of the associated service.

    " + }, + "serviceArn":{"shape":"Arn"}, + "userJourneys":{ + "shape":"UserJourneyNameList", + "documentation":"

    The user journeys linking the service to the system.

    " + } }, - "exception":true + "documentation":"

    Metadata for a system service associated event.

    " }, - "ServiceReference":{ + "SystemServiceDisassociatedMetadata":{ "type":"structure", "members":{ - "serviceId":{ + "serviceName":{ "shape":"String", - "documentation":"

    The identifier of the referenced service.

    " + "documentation":"

    The name of the disassociated service.

    " }, - "serviceName":{ + "serviceArn":{"shape":"Arn"}, + "userJourneysAffected":{ + "shape":"UserJourneyNameList", + "documentation":"

    The user journeys affected by the disassociation.

    " + }, + "comment":{ "shape":"String", - "documentation":"

    The name of the referenced service.

    " + "documentation":"

    A comment about the disassociation.

    " } }, - "documentation":"

    A reference to a service by ID and name.

    " + "documentation":"

    Metadata for a system service disassociated event.

    " }, - "ServiceReferenceChanges":{ + "SystemSummary":{ "type":"structure", + "required":[ + "systemId", + "name" + ], "members":{ - "added":{ - "shape":"ServiceReferenceList", - "documentation":"

    The list of service references that were added.

    " + "systemId":{"shape":"SystemId"}, + "name":{"shape":"EntityName"}, + "systemArn":{"shape":"Arn"}, + "userJourneysCount":{ + "shape":"Integer", + "documentation":"

    The number of user journeys in the system.

    " }, - "removed":{ - "shape":"ServiceReferenceList", - "documentation":"

    The list of service references that were removed.

    " + "servicesCount":{ + "shape":"Integer", + "documentation":"

    The number of services in the system.

    " + }, + "organizationId":{ + "shape":"OrganizationId", + "documentation":"

    Displayed only if caller has access.

    " + }, + "ouId":{ + "shape":"OuId", + "documentation":"

    Displayed only if caller has access.

    " + }, + "createdAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the system was created.

    " + }, + "updatedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the system was last updated.

    " } }, - "documentation":"

    Describes changes to service references.

    " + "documentation":"

    Contains summary information about a system.

    " }, - "ServiceReferenceList":{ + "SystemSummaryList":{ "type":"list", - "member":{"shape":"ServiceReference"} + "member":{"shape":"SystemSummary"} }, - "ServiceReportConfiguration":{ + "SystemUserJourneyCreatedMetadata":{ "type":"structure", - "required":["reportOutputs"], "members":{ - "reportOutputs":{ - "shape":"ReportOutputConfigurationList", - "documentation":"

    Output destinations for generated reports.

    " + "userJourneyName":{ + "shape":"String", + "documentation":"

    The name of the created user journey.

    " + }, + "associatedServices":{ + "shape":"ServiceReferenceList", + "documentation":"

    The services associated with the created user journey.

    " } }, - "documentation":"

    Configuration for automatic report generation on a Service.

    " + "documentation":"

    Metadata for a system user journey created event.

    " }, - "ServiceResource":{ + "SystemUserJourneyDeletedMetadata":{ "type":"structure", - "required":[ - "resourceIdentifier", - "resource" - ], "members":{ - "resourceIdentifier":{ + "userJourneyName":{ "shape":"String", - "documentation":"

    The identifier of the resource.

    " + "documentation":"

    The name of the deleted user journey.

    " }, - "inputSource":{ - "shape":"InputSource", - "documentation":"

    The input source that discovered the resource.

    " + "associatedServicesAtDeletion":{ + "shape":"ServiceReferenceList", + "documentation":"

    The services that were associated at the time of deletion.

    " + } + }, + "documentation":"

    Metadata for a system user journey deleted event.

    " + }, + "SystemUserJourneyUpdatedMetadata":{ + "type":"structure", + "members":{ + "userJourneyName":{ + "shape":"String", + "documentation":"

    The name of the updated user journey.

    " }, - "resource":{ - "shape":"Resource", - "documentation":"

    The resource details.

    " + "changes":{ + "shape":"UserJourneyChanges", + "documentation":"

    The changes made to the user journey.

    " } }, - "documentation":"

    Represents a resource associated with a service.

    " + "documentation":"

    Metadata for a system user journey updated event.

    " }, - "ServiceResourceList":{ + "TagKey":{ + "type":"string", + "documentation":"

    Tag key.

    ", + "max":128, + "min":1, + "pattern":"[^\\x00-\\x1f\\x22]+" + }, + "TagKeyList":{ "type":"list", - "member":{"shape":"ServiceResource"} + "member":{"shape":"TagKey"}, + "max":50, + "min":1, + "sensitive":true + }, + "TagMap":{ + "type":"map", + "key":{"shape":"TagKey"}, + "value":{"shape":"TagValue"}, + "documentation":"

    Resource tags.

    ", + "max":50, + "min":1, + "sensitive":true }, - "ServiceResourcesAssociatedMetadata":{ + "TagResourceRequest":{ "type":"structure", + "required":[ + "resourceArn", + "tags" + ], "members":{ - "resourceCount":{ - "shape":"Integer", - "documentation":"

    The number of resources associated.

    " + "resourceArn":{ + "shape":"Arn", + "location":"uri", + "locationName":"resourceArn" }, - "resourceTypes":{ - "shape":"ResourceTypeList", - "documentation":"

    The types of resources associated.

    " - } - }, - "documentation":"

    Metadata for a service resources associated event.

    " + "tags":{"shape":"TagMap"} + } }, - "ServiceResourcesDisassociatedMetadata":{ + "TagResourceResponse":{ + "type":"structure", + "members":{} + }, + "TagValue":{ + "type":"string", + "documentation":"

    Tag value.

    ", + "max":256, + "min":0, + "pattern":"[^\\x00-\\x1f\\x22]*" + }, + "TargetSource":{ "type":"structure", "members":{ - "resourceCount":{ + "value":{ "shape":"Integer", - "documentation":"

    The number of resources disassociated.

    " + "documentation":"

    The RTO or RPO value in minutes.

    " }, - "resourceTypes":{ - "shape":"ResourceTypeList", - "documentation":"

    The types of resources disassociated.

    " + "policyName":{"shape":"EntityName"}, + "source":{ + "shape":"PolicyValueSource", + "documentation":"

    Indicates whether the value comes from the service's own account or a cross-account policy.

    " } }, - "documentation":"

    Metadata for a service resources disassociated event.

    " + "documentation":"

    Contains an effective RTO or RPO value and its source.

    " }, - "ServiceSummary":{ + "Test":{ "type":"structure", "required":[ + "testId", + "testTemplateArn", "serviceArn", - "name" + "name", + "totalTestRuns", + "successfulTestRuns", + "creationTime" ], "members":{ - "serviceArn":{"shape":"Arn"}, - "name":{"shape":"EntityName"}, - "associatedSystems":{ - "shape":"AssociatedSystemList", - "documentation":"

    The systems associated with the service.

    " + "testId":{ + "shape":"TestId", + "documentation":"

    The unique identifier of the test.

    " }, - "regions":{ - "shape":"RegionList", - "documentation":"

    The AWS Regions where the service operates.

    " + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template the test was created from.

    " }, - "policyArn":{"shape":"Arn"}, - "assessmentStatus":{ - "shape":"AssessmentStatus", - "documentation":"

    The current assessment status of the service.

    " + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " }, - "openFindingsCount":{ - "shape":"Integer", - "documentation":"

    The number of open findings.

    " + "name":{ + "shape":"String", + "documentation":"

    The name of the test.

    " }, - "resolvedFindingsCount":{ - "shape":"Integer", - "documentation":"

    The number of resolved findings.

    " + "actions":{ + "shape":"TestActionList", + "documentation":"

    The fault actions the test runs.

    " }, - "dependencyDiscovery":{ - "shape":"DependencyDiscoveryConfig", - "documentation":"

    The dependency discovery configuration.

    " + "loggingConfiguration":{ + "shape":"LoggingConfiguration", + "documentation":"

    The logging configuration for the test.

    " }, - "achievability":{ - "shape":"Achievability", - "documentation":"

    The achievability status of the service's resilience targets.

    " + "stopConditions":{ + "shape":"StopConditionList", + "documentation":"

    The stop conditions for the test.

    " }, - "organizationId":{ - "shape":"OrganizationId", - "documentation":"

    Displayed only if caller has access.

    " + "roleName":{ + "shape":"IamRoleName", + "documentation":"

    The name of the IAM execution role used to run the test.

    " }, - "ouId":{ - "shape":"OuId", - "documentation":"

    Displayed only if caller has access.

    " + "parameters":{ + "shape":"TestParameters", + "documentation":"

    The parameter values configured for the test.

    " }, - "accountId":{ - "shape":"AccountId", - "documentation":"

    Displayed only if caller has access.

    " + "totalTestRuns":{ + "shape":"Integer", + "documentation":"

    The total number of runs of the test.

    " }, - "createdAt":{ - "shape":"Timestamp", - "documentation":"

    The timestamp when the service was created.

    " + "successfulTestRuns":{ + "shape":"Integer", + "documentation":"

    The number of successful runs of the test.

    " }, - "updatedAt":{ + "creationTime":{ "shape":"Timestamp", - "documentation":"

    The timestamp when the service was last updated.

    " + "documentation":"

    The timestamp when the test was created.

    " } }, - "documentation":"

    Contains summary information about a service.

    " - }, - "ServiceSummaryList":{ - "type":"list", - "member":{"shape":"ServiceSummary"} + "documentation":"

    Represents a test created for a service by configuring a test template.

    " }, - "ServiceSystemAssociatedMetadata":{ + "TestAction":{ "type":"structure", + "required":[ + "actionId", + "resourceType" + ], "members":{ - "systemName":{ + "actionId":{ "shape":"String", - "documentation":"

    The name of the associated system.

    " + "documentation":"

    The identifier of the fault action.

    " }, - "systemArn":{"shape":"Arn"} - }, - "documentation":"

    Metadata for a service system associated event.

    " - }, - "ServiceSystemDisassociatedMetadata":{ - "type":"structure", - "members":{ - "systemId":{ + "description":{ "shape":"String", - "documentation":"

    The identifier of the disassociated system.

    " + "documentation":"

    A description of the fault action.

    " }, - "systemName":{ + "resourceType":{ "shape":"String", - "documentation":"

    The name of the disassociated system.

    " - }, - "systemArn":{"shape":"Arn"} + "documentation":"

    The resource type that the action targets.

    " + } }, - "documentation":"

    Metadata for a service system disassociated event.

    " + "documentation":"

    Represents a fault action that a test runs, along with the resource type it targets.

    " }, - "ServiceTopologyEdgeSummary":{ + "TestActionList":{ + "type":"list", + "member":{"shape":"TestAction"} + }, + "TestId":{ + "type":"string", + "documentation":"

    The unique identifier of a test.

    ", + "min":1 + }, + "TestParameters":{ + "type":"map", + "key":{"shape":"ParameterKey"}, + "value":{"shape":"StringList"}, + "max":20, + "min":0 + }, + "TestRun":{ "type":"structure", "required":[ - "sourceResourceIdentifier", - "destinationResourceIdentifier" + "testRunId", + "testId", + "status", + "startedAt", + "testTemplateArn" ], "members":{ - "sourceResourceIdentifier":{ - "shape":"String", - "documentation":"

    The identifier of the source resource.

    " + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The unique identifier of the test run.

    " }, - "destinationResourceIdentifier":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test that was run.

    " + }, + "status":{ + "shape":"TestRunStatus", + "documentation":"

    The current status of the test run.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the test run started.

    " + }, + "endedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the test run ended.

    " + }, + "experiments":{ + "shape":"ExperimentDetailsList", + "documentation":"

    The AWS Fault Injection Service (AWS FIS) experiments run as part of the test run.

    " + }, + "eventCount":{ + "shape":"Integer", + "documentation":"

    The number of events recorded for the test run. Use ListTestRunEvents to retrieve the details.

    " + }, + "parameters":{ + "shape":"TestParameters", + "documentation":"

    The parameter values used for the test run.

    " + }, + "errorMessage":{ "shape":"String", - "documentation":"

    The identifier of the destination resource.

    " + "documentation":"

    A human-readable reason for test run failure. Only present when the status is FAILED or ERROR.

    " }, - "sourceRegion":{ - "shape":"AwsRegion", - "documentation":"

    The AWS Region of the source resource.

    " + "stopConditions":{ + "shape":"StopConditionList", + "documentation":"

    The stop conditions snapshotted from the test when the run was started.

    " }, - "destinationRegion":{ - "shape":"AwsRegion", - "documentation":"

    The AWS Region of the destination resource.

    " + "loggingConfiguration":{ + "shape":"LoggingConfiguration", + "documentation":"

    The logging configuration snapshotted from the test when the run was started.

    " }, - "sourceAccount":{ - "shape":"AwsAccountId", - "documentation":"

    The AWS account ID of the source resource.

    " + "roleName":{ + "shape":"IamRoleName", + "documentation":"

    The IAM execution role name snapshotted from the test when the run was started.

    " }, - "destinationAccount":{ - "shape":"AwsAccountId", - "documentation":"

    The AWS account ID of the destination resource.

    " + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template snapshotted from the test when the run was started.

    " }, - "properties":{ - "shape":"EdgePropertyList", - "documentation":"

    The properties of the topology edge.

    " + "reportConfiguration":{ + "shape":"TestRunReportConfiguration", + "documentation":"

    The report configuration snapshotted from the service when the run was started.

    " + }, + "policy":{ + "shape":"TestRunPolicySnapshot", + "documentation":"

    The resilience policy snapshotted from the service when the run was started.

    " + }, + "reportOutput":{ + "shape":"ReportGenerationResult", + "documentation":"

    The report generation result for the test run. Present after report generation completes or fails.

    " + }, + "regionSwitchPlanArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the ARC Region switch plan associated with the test run.

    " + }, + "regionSwitchExecutionId":{ + "shape":"RegionSwitchExecutionId", + "documentation":"

    The identifier of the ARC Region switch execution detected during the test run.

    " + }, + "permissionModel":{ + "shape":"PermissionModel", + "documentation":"

    The permission model snapshotted from the service when the run was started.

    " + }, + "regions":{ + "shape":"RegionList", + "documentation":"

    The Regions snapshotted from the service when the run was started.

    " + }, + "accountTargeting":{ + "shape":"AccountTargeting", + "documentation":"

    Indicates whether the test run targets resources in a single AWS account or across multiple accounts.

    " } }, - "documentation":"

    Contains summary information about a service topology edge.

    " + "documentation":"

    Represents a single run of a test. Configuration is snapshotted from the test and service at the time the run is started.

    " }, - "ServiceTopologyEdgeSummaryList":{ - "type":"list", - "member":{"shape":"ServiceTopologyEdgeSummary"} + "TestRunDependencySource":{ + "type":"string", + "documentation":"

    The origin of a blocked dependency.

    ", + "enum":[ + "DISCOVERED", + "MANUAL" + ] }, - "ServiceWorkflowUpdatedMetadata":{ + "TestRunDependencySummary":{ "type":"structure", + "required":[ + "dependencyName", + "dnsName", + "criticality", + "source" + ], "members":{ - "serviceFunctionId":{ - "shape":"String", - "documentation":"

    The identifier of the service function.

    " + "dependencyId":{ + "shape":"Uuid", + "documentation":"

    The unique identifier of the dependency. Absent when the dependency was entered manually and was not part of dependency discovery.

    " }, - "serviceFunctionName":{ - "shape":"String", - "documentation":"

    The name of the service function.

    " - } - }, - "documentation":"

    Metadata for a service workflow updated event.

    " - }, - "SloSource":{ - "type":"structure", - "members":{ - "value":{ - "shape":"Double", - "documentation":"

    The availability SLO percentage value.

    " + "dependencyName":{ + "shape":"TestRunDependencySummaryDependencyNameString", + "documentation":"

    The name of the dependency.

    " + }, + "dnsName":{ + "shape":"TestRunDependencySummaryDnsNameString", + "documentation":"

    The DNS name of the dependency that the test run blocked.

    " + }, + "criticality":{ + "shape":"DependencyCriticality", + "documentation":"

    The criticality classification of the dependency when the run started. A dependency that was not discovered has the UNKNOWN criticality.

    " }, - "policyName":{"shape":"EntityName"}, "source":{ - "shape":"PolicyValueSource", - "documentation":"

    Indicates whether the value comes from the service's own account or a cross-account policy.

    " + "shape":"TestRunDependencySource", + "documentation":"

    The origin of the dependency. A discovered dependency was found by dependency discovery; a manual dependency was entered when the run started.

    " + }, + "location":{ + "shape":"TestRunDependencySummaryLocationString", + "documentation":"

    The location of the dependency.

    " + }, + "sourceRegions":{ + "shape":"RegionList", + "documentation":"

    The source Regions from which the dependency was detected.

    " + }, + "provider":{ + "shape":"TestRunDependencySummaryProviderString", + "documentation":"

    The provider of the dependency.

    " } }, - "documentation":"

    Contains the effective availability SLO value and its source.

    " + "documentation":"

    Contains summary information about a dependency that a test run blocked, as captured when the run started.

    " }, - "SortOrder":{ + "TestRunDependencySummaryDependencyNameString":{ "type":"string", - "documentation":"

    The order in which to sort results.

    ", - "enum":[ - "ASC", - "DESC" - ] + "max":1024, + "min":1 + }, + "TestRunDependencySummaryDnsNameString":{ + "type":"string", + "max":253, + "min":1 + }, + "TestRunDependencySummaryList":{ + "type":"list", + "member":{"shape":"TestRunDependencySummary"}, + "max":100, + "min":0 + }, + "TestRunDependencySummaryLocationString":{ + "type":"string", + "max":1024, + "min":1 }, - "StartFailureModeAssessmentRequest":{ - "type":"structure", - "required":["serviceArn"], - "members":{ - "serviceArn":{"shape":"Arn"}, - "clientToken":{ - "shape":"ClientToken", - "idempotencyToken":true - } - } + "TestRunDependencySummaryProviderString":{ + "type":"string", + "max":1024, + "min":1 }, - "StartFailureModeAssessmentResponse":{ + "TestRunEvent":{ "type":"structure", + "required":[ + "eventId", + "eventType", + "message", + "timestamp" + ], "members":{ - "assessmentId":{ - "shape":"Uuid", - "documentation":"

    The unique identifier of the started assessment.

    " + "eventId":{ + "shape":"TestRunEventEventIdString", + "documentation":"

    The unique identifier of the event.

    " }, - "serviceArn":{"shape":"Arn"}, - "assessmentStatus":{ - "shape":"AssessmentStatus", - "documentation":"

    The status of the started assessment.

    " + "eventType":{ + "shape":"TestRunEventEventTypeString", + "documentation":"

    The type of the event, such as action_started, action_completed, or rto_recovery_detected.

    " }, - "startedAt":{ + "message":{ + "shape":"TestRunEventMessageString", + "documentation":"

    A human-readable description of what happened.

    " + }, + "timestamp":{ "shape":"Timestamp", - "documentation":"

    The timestamp when the assessment started.

    " + "documentation":"

    The timestamp when the event occurred.

    " + }, + "attributes":{ + "shape":"TestRunEventAttributes", + "documentation":"

    Machine-parseable key-value attributes for the event.

    " } - } + }, + "documentation":"

    A single event in a test run's timeline.

    " }, - "String":{"type":"string"}, - "StringChange":{ + "TestRunEventAttributeKey":{ + "type":"string", + "documentation":"

    The key of a test run event attribute.

    ", + "max":128, + "min":1 + }, + "TestRunEventAttributeValue":{ + "type":"string", + "documentation":"

    The value of a test run event attribute.

    ", + "max":1024, + "min":0 + }, + "TestRunEventAttributes":{ + "type":"map", + "key":{"shape":"TestRunEventAttributeKey"}, + "value":{"shape":"TestRunEventAttributeValue"}, + "max":50, + "min":0 + }, + "TestRunEventEventIdString":{ + "type":"string", + "max":64, + "min":1 + }, + "TestRunEventEventTypeString":{ + "type":"string", + "max":256, + "min":1 + }, + "TestRunEventList":{ + "type":"list", + "member":{"shape":"TestRunEvent"}, + "max":100, + "min":0 + }, + "TestRunEventMessageString":{ + "type":"string", + "max":2048, + "min":1 + }, + "TestRunId":{ + "type":"string", + "documentation":"

    The unique identifier of a test run.

    ", + "min":1 + }, + "TestRunObservabilityAlarmSummary":{ "type":"structure", + "required":[ + "alarmArn", + "alarmName", + "region", + "accountId" + ], "members":{ - "oldValue":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + }, + "alarmName":{ "shape":"String", - "documentation":"

    The old value.

    " + "documentation":"

    The name of the CloudWatch alarm.

    " }, - "newValue":{ + "region":{ "shape":"String", - "documentation":"

    The new value.

    " + "documentation":"

    The Region of the CloudWatch alarm.

    " + }, + "accountId":{ + "shape":"String", + "documentation":"

    The account ID that owns the CloudWatch alarm.

    " } }, - "documentation":"

    Describes a change from one string value to another.

    " - }, - "SuggestedChangesList":{ - "type":"list", - "member":{"shape":"EntityDescription"}, - "max":10, - "min":0 + "documentation":"

    Summary information about an observability alarm snapshot captured for a test run.

    " }, - "System":{ + "TestRunPolicySnapshot":{ "type":"structure", - "required":[ - "systemArn", - "systemId", - "name" - ], "members":{ - "systemArn":{"shape":"Arn"}, - "systemId":{"shape":"SystemId"}, - "name":{"shape":"EntityName"}, - "description":{"shape":"EntityDescription"}, - "sharingEnabled":{ - "shape":"Boolean", - "documentation":"

    Indicates whether cross-account sharing is enabled.

    " + "policyArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the policy.

    " }, - "tags":{"shape":"TagMap"}, - "kmsKeyId":{"shape":"KmsKeyId"}, - "organizationId":{ - "shape":"OrganizationId", - "documentation":"

    The AWS Organizations identifier for the system.

    " + "name":{ + "shape":"EntityName", + "documentation":"

    The name of the policy.

    " }, - "ouId":{ - "shape":"OuId", - "documentation":"

    The organizational unit (OU) identifier for the system.

    " + "availabilitySlo":{ + "shape":"AvailabilitySlo", + "documentation":"

    The availability SLO targets.

    " }, - "createdAt":{ - "shape":"Timestamp", - "documentation":"

    The timestamp when the system was created.

    " + "multiAz":{ + "shape":"MultiAzTargets", + "documentation":"

    The multi-AZ resilience targets.

    " }, - "updatedAt":{ - "shape":"Timestamp", - "documentation":"

    The timestamp when the system was last updated.

    " + "multiRegion":{ + "shape":"MultiRegionTargets", + "documentation":"

    The multi-Region resilience targets.

    " + }, + "dataRecovery":{ + "shape":"DataRecoveryTargets", + "documentation":"

    The data recovery targets.

    " } }, - "documentation":"

    Represents a system in Resilience Hub. A system is a logical grouping of services.

    " + "documentation":"

    A snapshot of the resilience policy captured onto a test run from the service when the run was started.

    " }, - "SystemCreatedMetadata":{ + "TestRunReportConfiguration":{ "type":"structure", - "members":{}, - "documentation":"

    Metadata for a system created event.

    " + "required":["reportOutput"], + "members":{ + "reportOutput":{ + "shape":"ReportOutputConfigurationList", + "documentation":"

    The output destinations for generated reports.

    " + } + }, + "documentation":"

    A snapshot of the report configuration captured onto a test run from the service when the run was started.

    " }, - "SystemDeletedMetadata":{ - "type":"structure", - "members":{}, - "documentation":"

    Metadata for a system deleted event.

    " + "TestRunSourceArn":{ + "type":"string", + "documentation":"

    The ARN of a test run monitoring source, such as a CloudWatch alarm.

    ", + "max":1024, + "min":31, + "pattern":"arn:aws[a-zA-Z-]*:[a-z][a-z0-9-]*:[a-z]{2}(-[a-z]+)+-\\d{1}:\\d{12}:.+" }, - "SystemEvent":{ + "TestRunSourceEvent":{ "type":"structure", "required":[ - "eventId", "timestamp", + "sourceArn", "eventType", - "systemArn", - "actor", - "eventDetails" + "detail" ], "members":{ - "eventId":{ - "shape":"Uuid", - "documentation":"

    The unique identifier of the event.

    " - }, "timestamp":{ "shape":"Timestamp", - "documentation":"

    The timestamp of the event.

    " + "documentation":"

    The timestamp when the event occurred.

    " + }, + "sourceArn":{ + "shape":"TestRunSourceArn", + "documentation":"

    The ARN of the monitoring source the event belongs to.

    " }, "eventType":{ - "shape":"SystemEventType", - "documentation":"

    The type of the event.

    " + "shape":"TestRunSourceEventType", + "documentation":"

    The type of the event. ALARM indicates an event from a CloudWatch alarm source; the detail member carries either the alarm state change or a collection error.

    " }, - "systemArn":{"shape":"Arn"}, - "actor":{ - "shape":"EventActor", - "documentation":"

    The actor that triggered the event.

    " + "detail":{ + "shape":"TestRunSourceEventDetail", + "documentation":"

    The event payload.

    " + } + }, + "documentation":"

    A state-change event observed for a test run monitoring source.

    " + }, + "TestRunSourceEventDetail":{ + "type":"structure", + "members":{ + "alarmStateChange":{ + "shape":"AlarmStateChangeDetail", + "documentation":"

    A CloudWatch alarm state change.

    " }, - "eventDetails":{ - "shape":"SystemEventDetails", - "documentation":"

    The details of the event.

    " + "error":{ + "shape":"TestRunSourceEventError", + "documentation":"

    An error that prevented event collection from the source.

    " } }, - "documentation":"

    Represents an event in the system event log.

    " + "documentation":"

    The payload of a test run source event. Exactly one member is set.

    ", + "union":true }, - "SystemEventDetails":{ + "TestRunSourceEventError":{ "type":"structure", "required":[ - "title", - "description" + "errorCode", + "errorMessage" ], "members":{ - "title":{ - "shape":"String", - "documentation":"

    The title of the event.

    " - }, - "description":{ - "shape":"String", - "documentation":"

    The description of the event.

    " + "errorCode":{ + "shape":"TestRunSourceEventErrorCode", + "documentation":"

    The error code.

    " }, - "eventMetadata":{"shape":"SystemEventMetadata"} + "errorMessage":{ + "shape":"TestRunSourceEventErrorErrorMessageString", + "documentation":"

    A human-readable description of the error.

    " + } }, - "documentation":"

    Contains the details of a system event.

    " + "documentation":"

    Describes an error that prevented event collection from a test run monitoring source.

    " }, - "SystemEventList":{ + "TestRunSourceEventErrorCode":{ + "type":"string", + "documentation":"

    The cause of a source event collection error.

    ", + "enum":[ + "ACCESS_DENIED", + "INTERNAL_ERROR" + ] + }, + "TestRunSourceEventErrorErrorMessageString":{ + "type":"string", + "max":2048, + "min":0 + }, + "TestRunSourceEventList":{ "type":"list", - "member":{"shape":"SystemEvent"} + "member":{"shape":"TestRunSourceEvent"}, + "max":100, + "min":0 }, - "SystemEventMetadata":{ + "TestRunSourceEventType":{ + "type":"string", + "documentation":"

    The type of a test run source event. ALARM indicates an event produced from a CloudWatch alarm source.

    ", + "enum":["ALARM"] + }, + "TestRunSourceSummary":{ "type":"structure", "members":{ - "systemCreated":{ - "shape":"SystemCreatedMetadata", - "documentation":"

    Metadata for a system created event.

    " - }, - "systemDeleted":{ - "shape":"SystemDeletedMetadata", - "documentation":"

    Metadata for a system deleted event.

    " - }, - "systemUserJourneyCreated":{ - "shape":"SystemUserJourneyCreatedMetadata", - "documentation":"

    Metadata for a system user journey created event.

    " - }, - "systemUserJourneyUpdated":{ - "shape":"SystemUserJourneyUpdatedMetadata", - "documentation":"

    Metadata for a system user journey updated event.

    " - }, - "systemUserJourneyDeleted":{ - "shape":"SystemUserJourneyDeletedMetadata", - "documentation":"

    Metadata for a system user journey deleted event.

    " - }, - "systemServiceAssociated":{ - "shape":"SystemServiceAssociatedMetadata", - "documentation":"

    Metadata for a system service associated event.

    " - }, - "systemServiceDisassociated":{ - "shape":"SystemServiceDisassociatedMetadata", - "documentation":"

    Metadata for a system service disassociated event.

    " - }, - "systemPolicyAssociated":{ - "shape":"SystemPolicyAssociatedMetadata", - "documentation":"

    Metadata for a system policy associated event.

    " + "successCriteriaAlarm":{ + "shape":"TestRunSuccessCriteriaAlarmSummary", + "documentation":"

    A success criteria alarm snapshot captured for the test run.

    " }, - "systemPolicyDisassociated":{ - "shape":"SystemPolicyDisassociatedMetadata", - "documentation":"

    Metadata for a system policy disassociated event.

    " + "observabilityAlarm":{ + "shape":"TestRunObservabilityAlarmSummary", + "documentation":"

    An observability alarm snapshot captured for the test run.

    " } }, - "documentation":"

    Type-specific metadata for each system event type.

    ", + "documentation":"

    A monitoring-source snapshot captured for a test run. Exactly one member is set.

    ", "union":true }, - "SystemEventType":{ - "type":"string", - "enum":[ - "SYSTEM_CREATED", - "SYSTEM_DELETED", - "SYSTEM_USER_JOURNEY_CREATED", - "SYSTEM_USER_JOURNEY_UPDATED", - "SYSTEM_USER_JOURNEY_DELETED", - "SYSTEM_SERVICE_ASSOCIATED", - "SYSTEM_SERVICE_DISASSOCIATED", - "SYSTEM_POLICY_ASSOCIATED", - "SYSTEM_POLICY_DISASSOCIATED" - ] - }, - "SystemEventTypeList":{ + "TestRunSourceSummaryList":{ "type":"list", - "member":{"shape":"SystemEventType"} + "member":{"shape":"TestRunSourceSummary"}, + "max":25, + "min":0 + }, + "TestRunSourceType":{ + "type":"string", + "documentation":"

    The type of a test run monitoring-source snapshot.

    ", + "enum":[ + "SUCCESS_CRITERIA", + "OBSERVABILITY" + ] }, - "SystemId":{ + "TestRunStatus":{ "type":"string", - "documentation":"

    System ID for cross-account use without exposing account structure.

    ", - "max":255, - "min":1, - "pattern":"\\S{1,255}" + "documentation":"

    The status of a test run through its lifecycle.

    ", + "enum":[ + "INITIALIZING", + "RUNNING", + "STOPPING", + "PASSED", + "FAILED", + "STOPPED", + "ERROR" + ] }, - "SystemPolicyAssociatedMetadata":{ + "TestRunSuccessCriteriaAlarmSummary":{ "type":"structure", + "required":[ + "alarmArn", + "alarmName", + "region", + "accountId" + ], "members":{ - "policyName":{ + "alarmArn":{ + "shape":"CloudWatchAlarmArn", + "documentation":"

    The ARN of the CloudWatch alarm.

    " + }, + "alarmName":{ "shape":"String", - "documentation":"

    The name of the associated policy.

    " + "documentation":"

    The name of the CloudWatch alarm.

    " }, - "policyArn":{"shape":"Arn"} + "region":{ + "shape":"String", + "documentation":"

    The Region of the CloudWatch alarm.

    " + }, + "accountId":{ + "shape":"String", + "documentation":"

    The account ID that owns the CloudWatch alarm.

    " + }, + "outcome":{ + "shape":"TestSourceOutcome", + "documentation":"

    The evaluation outcome of the source. Absent while the source has not yet been evaluated; set to the terminal outcome afterwards.

    " + }, + "outcomeReason":{ + "shape":"String", + "documentation":"

    A human-readable reason for the outcome.

    " + } }, - "documentation":"

    Metadata for a system policy associated event.

    " + "documentation":"

    Summary information about a success criteria alarm snapshot captured for a test run.

    " }, - "SystemPolicyDisassociatedMetadata":{ + "TestRunSummary":{ "type":"structure", + "required":[ + "testRunId", + "status", + "startedAt", + "testTemplateArn" + ], "members":{ - "policyName":{ + "testRunId":{ + "shape":"TestRunId", + "documentation":"

    The unique identifier of the test run.

    " + }, + "status":{ + "shape":"TestRunStatus", + "documentation":"

    The current status of the test run.

    " + }, + "startedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the test run started.

    " + }, + "endedAt":{ + "shape":"Timestamp", + "documentation":"

    The timestamp when the test run ended.

    " + }, + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template the test run was based on.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test run belongs to.

    " + }, + "errorMessage":{ "shape":"String", - "documentation":"

    The name of the disassociated policy.

    " + "documentation":"

    A human-readable reason for test run failure. Only present when the status is FAILED or ERROR.

    " }, - "policyArn":{"shape":"Arn"} + "accountTargeting":{ + "shape":"AccountTargeting", + "documentation":"

    Indicates whether the test run targets resources in a single AWS account or across multiple accounts.

    " + } }, - "documentation":"

    Metadata for a system policy disassociated event.

    " + "documentation":"

    Contains summary information about a test run.

    " }, - "SystemServiceAssociatedMetadata":{ + "TestRunSummaryList":{ + "type":"list", + "member":{"shape":"TestRunSummary"} + }, + "TestSourceInput":{ "type":"structure", "members":{ - "serviceName":{ - "shape":"String", - "documentation":"

    The name of the associated service.

    " + "successCriteriaAlarm":{ + "shape":"SuccessCriteriaAlarmInput", + "documentation":"

    A success criteria alarm that determines whether the test passes or fails.

    " }, - "serviceArn":{"shape":"Arn"}, - "userJourneys":{ - "shape":"UserJourneyNameList", - "documentation":"

    The user journeys linking the service to the system.

    " + "observabilityAlarm":{ + "shape":"ObservabilityAlarmInput", + "documentation":"

    An observability alarm included for visibility only.

    " } }, - "documentation":"

    Metadata for a system service associated event.

    " + "documentation":"

    Identifies a monitoring source to add to or remove from a test. Exactly one member is set.

    ", + "union":true }, - "SystemServiceDisassociatedMetadata":{ + "TestSourceInputList":{ + "type":"list", + "member":{"shape":"TestSourceInput"}, + "max":5, + "min":1 + }, + "TestSourceOutcome":{ + "type":"string", + "documentation":"

    The evaluation outcome of a test run success criteria source.

    ", + "enum":[ + "PASSED", + "FAILED", + "ERROR" + ] + }, + "TestSourceSummary":{ "type":"structure", "members":{ - "serviceName":{ - "shape":"String", - "documentation":"

    The name of the disassociated service.

    " - }, - "serviceArn":{"shape":"Arn"}, - "userJourneysAffected":{ - "shape":"UserJourneyNameList", - "documentation":"

    The user journeys affected by the disassociation.

    " + "successCriteriaAlarm":{ + "shape":"SuccessCriteriaAlarmSummary", + "documentation":"

    A configured success criteria alarm.

    " }, - "comment":{ - "shape":"String", - "documentation":"

    A comment about the disassociation.

    " + "observabilityAlarm":{ + "shape":"ObservabilityAlarmSummary", + "documentation":"

    A configured observability alarm.

    " } }, - "documentation":"

    Metadata for a system service disassociated event.

    " + "documentation":"

    A configured monitoring source returned by ListTestSources. Exactly one member is set.

    ", + "union":true }, - "SystemSummary":{ + "TestSourceSummaryList":{ + "type":"list", + "member":{"shape":"TestSourceSummary"}, + "max":25, + "min":0 + }, + "TestSourceType":{ + "type":"string", + "documentation":"

    The purpose of a test monitoring source.

    ", + "enum":[ + "SUCCESS_CRITERIA", + "OBSERVABILITY" + ] + }, + "TestSummary":{ "type":"structure", "required":[ - "systemId", - "name" + "testId", + "testTemplateArn", + "serviceArn", + "totalTestRuns", + "successfulTestRuns", + "creationTime" ], "members":{ - "systemId":{"shape":"SystemId"}, - "name":{"shape":"EntityName"}, - "systemArn":{"shape":"Arn"}, - "userJourneysCount":{ - "shape":"Integer", - "documentation":"

    The number of user journeys in the system.

    " + "testId":{ + "shape":"TestId", + "documentation":"

    The unique identifier of the test.

    " }, - "servicesCount":{ - "shape":"Integer", - "documentation":"

    The number of services in the system.

    " + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template the test was created from.

    " }, - "organizationId":{ - "shape":"OrganizationId", - "documentation":"

    Displayed only if caller has access.

    " + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " }, - "ouId":{ - "shape":"OuId", - "documentation":"

    Displayed only if caller has access.

    " + "totalTestRuns":{ + "shape":"Integer", + "documentation":"

    The total number of runs of the test.

    " }, - "createdAt":{ - "shape":"Timestamp", - "documentation":"

    The timestamp when the system was created.

    " + "successfulTestRuns":{ + "shape":"Integer", + "documentation":"

    The number of successful runs of the test.

    " }, - "updatedAt":{ + "creationTime":{ "shape":"Timestamp", - "documentation":"

    The timestamp when the system was last updated.

    " + "documentation":"

    The timestamp when the test was created.

    " } }, - "documentation":"

    Contains summary information about a system.

    " + "documentation":"

    Contains summary information about a test.

    " }, - "SystemSummaryList":{ + "TestSummaryList":{ "type":"list", - "member":{"shape":"SystemSummary"} + "member":{"shape":"TestSummary"} }, - "SystemUserJourneyCreatedMetadata":{ + "TestTemplate":{ "type":"structure", + "required":[ + "testTemplateArn", + "name" + ], "members":{ - "userJourneyName":{ + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template.

    " + }, + "name":{ "shape":"String", - "documentation":"

    The name of the created user journey.

    " + "documentation":"

    The name of the test template.

    " }, - "associatedServices":{ - "shape":"ServiceReferenceList", - "documentation":"

    The services associated with the created user journey.

    " - } - }, - "documentation":"

    Metadata for a system user journey created event.

    " - }, - "SystemUserJourneyDeletedMetadata":{ - "type":"structure", - "members":{ - "userJourneyName":{ + "description":{ "shape":"String", - "documentation":"

    The name of the deleted user journey.

    " + "documentation":"

    A description of the test template.

    " }, - "associatedServicesAtDeletion":{ - "shape":"ServiceReferenceList", - "documentation":"

    The services that were associated at the time of deletion.

    " + "parameters":{ + "shape":"TestTemplateParameterList", + "documentation":"

    The parameters the test template accepts.

    " + }, + "actions":{ + "shape":"TestActionList", + "documentation":"

    The fault actions the test template runs.

    " } }, - "documentation":"

    Metadata for a system user journey deleted event.

    " + "documentation":"

    A pre-configured, AWS recommended test that defines which resilience capability to validate, the fault actions it runs, and the parameters it accepts.

    " }, - "SystemUserJourneyUpdatedMetadata":{ + "TestTemplateParameter":{ "type":"structure", + "required":[ + "name", + "type", + "required" + ], "members":{ - "userJourneyName":{ + "name":{ "shape":"String", - "documentation":"

    The name of the updated user journey.

    " + "documentation":"

    The name of the parameter.

    " }, - "changes":{ - "shape":"UserJourneyChanges", - "documentation":"

    The changes made to the user journey.

    " + "description":{ + "shape":"String", + "documentation":"

    A description of the parameter.

    " + }, + "type":{ + "shape":"ParameterType", + "documentation":"

    The data type of the parameter.

    " + }, + "required":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the parameter is required.

    " + }, + "defaultValue":{ + "shape":"String", + "documentation":"

    The default value of the parameter.

    " + }, + "maxValues":{ + "shape":"Integer", + "documentation":"

    The maximum number of values the parameter accepts.

    " } }, - "documentation":"

    Metadata for a system user journey updated event.

    " - }, - "TagKey":{ - "type":"string", - "documentation":"

    Tag key.

    ", - "max":128, - "min":1, - "pattern":"[^\\x00-\\x1f\\x22]+" + "documentation":"

    Describes a parameter accepted by a test template.

    " }, - "TagKeyList":{ + "TestTemplateParameterList":{ "type":"list", - "member":{"shape":"TagKey"}, - "max":50, - "min":1, - "sensitive":true - }, - "TagMap":{ - "type":"map", - "key":{"shape":"TagKey"}, - "value":{"shape":"TagValue"}, - "documentation":"

    Resource tags.

    ", - "max":50, - "min":1, - "sensitive":true + "member":{"shape":"TestTemplateParameter"} }, - "TagResourceRequest":{ + "TestTemplateSummary":{ "type":"structure", "required":[ - "resourceArn", - "tags" + "testTemplateArn", + "name", + "description" ], "members":{ - "resourceArn":{ - "shape":"Arn", - "location":"uri", - "locationName":"resourceArn" + "testTemplateArn":{ + "shape":"ServiceOwnedArn", + "documentation":"

    The ARN of the test template.

    " }, - "tags":{"shape":"TagMap"} - } - }, - "TagResourceResponse":{ - "type":"structure", - "members":{} - }, - "TagValue":{ - "type":"string", - "documentation":"

    Tag value.

    ", - "max":256, - "min":0, - "pattern":"[^\\x00-\\x1f\\x22]*" - }, - "TargetSource":{ - "type":"structure", - "members":{ - "value":{ - "shape":"Integer", - "documentation":"

    The RTO or RPO value in minutes.

    " + "name":{ + "shape":"String", + "documentation":"

    The name of the test template.

    " }, - "policyName":{"shape":"EntityName"}, - "source":{ - "shape":"PolicyValueSource", - "documentation":"

    Indicates whether the value comes from the service's own account or a cross-account policy.

    " + "description":{ + "shape":"String", + "documentation":"

    A description of the test template.

    " } }, - "documentation":"

    Contains an effective RTO or RPO value and its source.

    " + "documentation":"

    Contains summary information about a test template.

    " + }, + "TestTemplateSummaryList":{ + "type":"list", + "member":{"shape":"TestTemplateSummary"} }, "TestingRecommendation":{ "type":"structure", @@ -5157,6 +7814,10 @@ "dataRecovery":{ "shape":"DataRecoveryTargets", "documentation":"

    The updated data recovery targets for the policy.

    " + }, + "sharingEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether cross-account sharing is enabled for the policy. Disabling sharing stops member services from using the policy.

    " } } }, @@ -5255,6 +7916,49 @@ } } }, + "UpdateTestRequest":{ + "type":"structure", + "required":[ + "testId", + "serviceArn" + ], + "members":{ + "testId":{ + "shape":"TestId", + "documentation":"

    The identifier of the test to update.

    " + }, + "serviceArn":{ + "shape":"Arn", + "documentation":"

    The ARN of the service the test belongs to.

    " + }, + "loggingConfiguration":{ + "shape":"LoggingConfiguration", + "documentation":"

    The updated logging configuration for the test.

    " + }, + "stopConditions":{ + "shape":"StopConditionList", + "documentation":"

    The updated stop conditions for the test.

    " + }, + "roleName":{ + "shape":"IamRoleName", + "documentation":"

    The updated IAM execution role name.

    " + }, + "parameters":{ + "shape":"TestParameters", + "documentation":"

    The updated parameter values for the test.

    " + } + } + }, + "UpdateTestResponse":{ + "type":"structure", + "required":["test"], + "members":{ + "test":{ + "shape":"Test", + "documentation":"

    The updated test.

    " + } + } + }, "UpdateUserJourneyRequest":{ "type":"structure", "required":[ diff --git a/services/resourceexplorer2/pom.xml b/services/resourceexplorer2/pom.xml index 40bf00d20a1c..12d970c2a04a 100644 --- a/services/resourceexplorer2/pom.xml +++ b/services/resourceexplorer2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT resourceexplorer2 AWS Java SDK :: Services :: Resource Explorer 2 diff --git a/services/resourceexplorer2/src/main/resources/codegen-resources/customization.config b/services/resourceexplorer2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/resourceexplorer2/src/main/resources/codegen-resources/customization.config +++ b/services/resourceexplorer2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bb5029d3ccae --- /dev/null +++ b/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-explorer-2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-explorer-2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-explorer-2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-explorer-2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2ec6f2e641c7..000000000000 --- a/services/resourceexplorer2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resource-explorer-2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resource-explorer-2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resource-explorer-2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://resource-explorer-2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/resourcegroups/pom.xml b/services/resourcegroups/pom.xml index 8254411cd4ae..f4ed84d07cda 100644 --- a/services/resourcegroups/pom.xml +++ b/services/resourcegroups/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 resourcegroups diff --git a/services/resourcegroups/src/main/resources/codegen-resources/customization.config b/services/resourcegroups/src/main/resources/codegen-resources/customization.config index f5f6e2d56258..cc94b90656a0 100644 --- a/services/resourcegroups/src/main/resources/codegen-resources/customization.config +++ b/services/resourcegroups/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listGroups" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/resourcegroups/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/resourcegroups/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4b6abc3d1baf --- /dev/null +++ b/services/resourcegroups/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-groups-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-groups.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-groups-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-groups.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://resource-groups.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/resourcegroups/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/resourcegroups/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3bfa2d01d4ae..000000000000 --- a/services/resourcegroups/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resource-groups-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://resource-groups.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://resource-groups-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://resource-groups.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://resource-groups.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/resourcegroupstaggingapi/pom.xml b/services/resourcegroupstaggingapi/pom.xml index 9d71390c42eb..a6fa3c821bc2 100644 --- a/services/resourcegroupstaggingapi/pom.xml +++ b/services/resourcegroupstaggingapi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT resourcegroupstaggingapi AWS Java SDK :: Services :: AWS Resource Groups Tagging API diff --git a/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/customization.config b/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/customization.config index c93cb9be664c..6e999de4f630 100644 --- a/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/customization.config +++ b/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "getResources", "getTagKeys" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9f0e5d72db47 --- /dev/null +++ b/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tagging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tagging-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tagging.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tagging.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8d6f1077f6f4..000000000000 --- a/services/resourcegroupstaggingapi/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tagging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tagging-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tagging.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://tagging.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rolesanywhere/pom.xml b/services/rolesanywhere/pom.xml index 621366155d59..8117b2db7fee 100644 --- a/services/rolesanywhere/pom.xml +++ b/services/rolesanywhere/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rolesanywhere AWS Java SDK :: Services :: Roles Anywhere diff --git a/services/rolesanywhere/src/main/resources/codegen-resources/customization.config b/services/rolesanywhere/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/rolesanywhere/src/main/resources/codegen-resources/customization.config +++ b/services/rolesanywhere/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a7e75cd818e9 --- /dev/null +++ b/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rolesanywhere-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rolesanywhere-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rolesanywhere.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rolesanywhere.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ea99ee679b0d..000000000000 --- a/services/rolesanywhere/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rolesanywhere-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rolesanywhere-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rolesanywhere.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rolesanywhere.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rolesanywhere/src/main/resources/codegen-resources/service-2.json b/services/rolesanywhere/src/main/resources/codegen-resources/service-2.json index e57657851bf1..d10e0f5ab3fe 100644 --- a/services/rolesanywhere/src/main/resources/codegen-resources/service-2.json +++ b/services/rolesanywhere/src/main/resources/codegen-resources/service-2.json @@ -1336,7 +1336,7 @@ }, "SourceDataX509CertificateDataString":{ "type":"string", - "max":16000, + "max":204800, "min":1 }, "SpecifierList":{ diff --git a/services/route53/pom.xml b/services/route53/pom.xml index 89cd41077566..842331f64b02 100644 --- a/services/route53/pom.xml +++ b/services/route53/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53 AWS Java SDK :: Services :: Amazon Route53 diff --git a/services/route53/src/main/resources/codegen-resources/customization.config b/services/route53/src/main/resources/codegen-resources/customization.config index c25907200ffd..4c4407cd52d2 100644 --- a/services/route53/src/main/resources/codegen-resources/customization.config +++ b/services/route53/src/main/resources/codegen-resources/customization.config @@ -19,8 +19,6 @@ ], "interceptors": [ "software.amazon.awssdk.services.route53.internal.Route53IdInterceptor" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/route53/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a210f4e1de11 --- /dev/null +++ b/services/route53/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,560 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-fips.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-fips.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.global.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "cn-northwest-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.us-gov.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.us-gov.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.cloud.adc-e.uk", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eu-isoe-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.csp.hci.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-isof-south-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.amazonaws.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.global.api.amazonwebservices.eu", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "eusc-de-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-fips.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-fips.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 28, + "nodes": "/////wAAAAH/////AAAAAAAAABsAAAADAAAAAQAAAAQF9eEZAAAAAgAAAAUF9eEZAAAAAwAAABMAAAAGAAAABAAAABIAAAAHAAAABQAAABEAAAAIAAAABgAAABkAAAAJAAAABwAAAA8AAAAKAAAACQX14QwAAAALAAAACgX14Q0AAAAMAAAACwX14Q4AAAANAAAADAX14Q8AAAAOAAAADQX14RAF9eEYAAAADQX14REAAAAQAAAADgX14RYF9eEXAAAABwX14QkF9eEIAAAABwX14QYF9eEEAAAABAAAABoAAAAUAAAABgAAABkAAAAVAAAABwAAABcAAAAWAAAACAX14RQF9eEVAAAACAAAABgF9eETAAAADgX14RIF9eETAAAABwX14QsF9eEKAAAABwX14QcF9eEFAAAAAwX14QEAAAAcAAAABwX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e6eb00511549..000000000000 --- a/services/route53/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,1172 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53-fips.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53-fips.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53.global.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "cn-northwest-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.us-gov.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.us-gov.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53.us-gov.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53.us-gov.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.cloud.adc-e.uk", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eu-isoe-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.csp.hci.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-isof-south-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53.amazonaws.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53.global.api.amazonwebservices.eu", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "eusc-de-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-fips.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-fips.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/route53/src/test/java/software/amazon/awssdk/services/route53/QueryParamBindingTest.java b/services/route53/src/test/java/software/amazon/awssdk/services/route53/QueryParamBindingTest.java index 78a21d9e145e..98dd63bfcc79 100644 --- a/services/route53/src/test/java/software/amazon/awssdk/services/route53/QueryParamBindingTest.java +++ b/services/route53/src/test/java/software/amazon/awssdk/services/route53/QueryParamBindingTest.java @@ -15,11 +15,14 @@ package software.amazon.awssdk.services.route53; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import java.net.URI; import java.util.List; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.ClientEndpointProvider; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -33,6 +36,8 @@ public class QueryParamBindingTest { + private static final Pattern API_VERSION_PREFIX = Pattern.compile("^/\\d{4}-\\d{2}-\\d{2}(?=/)"); + protected static final AwsXmlProtocolFactory PROTOCOL_FACTORY = AwsXmlProtocolFactory .builder() .clientConfiguration(SdkClientConfiguration.builder() @@ -58,7 +63,7 @@ public void testReservedCharInParamValue() { .build(); SdkHttpFullRequest httpReq_List = new ListHealthChecksRequestMarshaller(PROTOCOL_FACTORY).marshall(listReq); - assertEquals("/2013-04-01/healthcheck", httpReq_List.encodedPath()); + assertEquals("/healthcheck", pathAfterApiVersion(httpReq_List.encodedPath())); Map> queryParams = httpReq_List.rawQueryParameters(); assertEquals(2, queryParams.size()); @@ -74,10 +79,18 @@ public void testReservedCharInParamValue() { System.out.println(httpReq_GetFailure); // parameter value should be URL encoded assertEquals( - "/2013-04-01/healthcheck/%3Fcharlie/lastfailurereason", - httpReq_GetFailure.encodedPath()); + "/healthcheck/%3Fcharlie/lastfailurereason", + pathAfterApiVersion(httpReq_GetFailure.encodedPath())); queryParams = httpReq_GetFailure.rawQueryParameters(); assertEquals(0, queryParams.size()); } + + private static String pathAfterApiVersion(String encodedPath) { + Matcher matcher = API_VERSION_PREFIX.matcher(encodedPath); + assertThat(matcher.lookingAt()) + .withFailMessage("Expected path to start with an API version segment, but was: %s", encodedPath) + .isTrue(); + return encodedPath.substring(matcher.end()); + } } diff --git a/services/route53domains/pom.xml b/services/route53domains/pom.xml index f25935136d76..2f8b46a61e04 100644 --- a/services/route53domains/pom.xml +++ b/services/route53domains/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53domains AWS Java SDK :: Services :: Amazon Route53 Domains diff --git a/services/route53domains/src/main/resources/codegen-resources/customization.config b/services/route53domains/src/main/resources/codegen-resources/customization.config index f0538c37cbb6..476aefd61bb5 100644 --- a/services/route53domains/src/main/resources/codegen-resources/customization.config +++ b/services/route53domains/src/main/resources/codegen-resources/customization.config @@ -7,6 +7,5 @@ "excludedSimpleMethods": [ "viewBilling", "getContactReachabilityStatus" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/route53domains/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53domains/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1db5e9c4c1f5 --- /dev/null +++ b/services/route53domains/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53domains-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53domains-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53domains.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53domains.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53domains/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53domains/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e9e9673b6251..000000000000 --- a/services/route53domains/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53domains-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53domains-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53domains.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53domains.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/route53globalresolver/pom.xml b/services/route53globalresolver/pom.xml index a5709748dd18..aed32845570c 100644 --- a/services/route53globalresolver/pom.xml +++ b/services/route53globalresolver/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53globalresolver AWS Java SDK :: Services :: Route53 Global Resolver diff --git a/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c9b7de207d06 --- /dev/null +++ b/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53globalresolver-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53globalresolver.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ff13029163b7..000000000000 --- a/services/route53globalresolver/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://route53globalresolver-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53globalresolver.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/route53profiles/pom.xml b/services/route53profiles/pom.xml index 9e7d6c5a16e7..cd0e929bd824 100644 --- a/services/route53profiles/pom.xml +++ b/services/route53profiles/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53profiles AWS Java SDK :: Services :: Route53 Profiles diff --git a/services/route53profiles/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53profiles/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4b0e469de75f --- /dev/null +++ b/services/route53profiles/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53profiles-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53profiles-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53profiles.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53profiles.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53profiles/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53profiles/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3c8901eba229..000000000000 --- a/services/route53profiles/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53profiles-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53profiles-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53profiles.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53profiles.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/route53recoverycluster/pom.xml b/services/route53recoverycluster/pom.xml index 3cea8218c0c1..0c3315ac3724 100644 --- a/services/route53recoverycluster/pom.xml +++ b/services/route53recoverycluster/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53recoverycluster AWS Java SDK :: Services :: Route53 Recovery Cluster diff --git a/services/route53recoverycluster/src/main/resources/codegen-resources/customization.config b/services/route53recoverycluster/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/route53recoverycluster/src/main/resources/codegen-resources/customization.config +++ b/services/route53recoverycluster/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0ea90e5a6b26 --- /dev/null +++ b/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-cluster-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-cluster-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-cluster.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-cluster.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 640f4a857881..000000000000 --- a/services/route53recoverycluster/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-cluster-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-cluster-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-cluster.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-cluster.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/route53recoverycontrolconfig/pom.xml b/services/route53recoverycontrolconfig/pom.xml index 86fc3448d95f..095b37b377fa 100644 --- a/services/route53recoverycontrolconfig/pom.xml +++ b/services/route53recoverycontrolconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53recoverycontrolconfig AWS Java SDK :: Services :: Route53 Recovery Control Config diff --git a/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/customization.config b/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/customization.config +++ b/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..34852867a3a3 --- /dev/null +++ b/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,263 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-control-config.us-west-2.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://arc-recovery-control-config.us-west-2.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-west-2" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-control-config-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-control-config-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-control-config.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-control-config.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAoAAAAGAAAABAAAAAgAAAAHAAAABQX14QQF9eEMAAAABQX14QUAAAAJAAAABgX14QoF9eELAAAABAAAAAwAAAALAAAABwX14QgF9eEJAAAABgAAAA0F9eEHAAAABwX14QYF9eEHAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e8fda7a9360b..000000000000 --- a/services/route53recoverycontrolconfig/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,472 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://route53-recovery-control-config.us-west-2.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://arc-recovery-control-config.us-west-2.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "us-west-2" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-control-config-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-control-config-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-control-config.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-control-config.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/route53recoveryreadiness/pom.xml b/services/route53recoveryreadiness/pom.xml index b071d16d72a9..522743cc22d8 100644 --- a/services/route53recoveryreadiness/pom.xml +++ b/services/route53recoveryreadiness/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53recoveryreadiness AWS Java SDK :: Services :: Route53 Recovery Readiness diff --git a/services/route53recoveryreadiness/src/main/resources/codegen-resources/customization.config b/services/route53recoveryreadiness/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/route53recoveryreadiness/src/main/resources/codegen-resources/customization.config +++ b/services/route53recoveryreadiness/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..48999a9bffd9 --- /dev/null +++ b/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-readiness-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-readiness-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-readiness.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53-recovery-readiness.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 04f1b7b1d231..000000000000 --- a/services/route53recoveryreadiness/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-readiness-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-readiness-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-readiness.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53-recovery-readiness.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/route53resolver/pom.xml b/services/route53resolver/pom.xml index f96fa2a2e40f..6eeabc3e0619 100644 --- a/services/route53resolver/pom.xml +++ b/services/route53resolver/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT route53resolver AWS Java SDK :: Services :: Route53Resolver diff --git a/services/route53resolver/src/main/resources/codegen-resources/customization.config b/services/route53resolver/src/main/resources/codegen-resources/customization.config index f7a32e6808c0..c9e00f244c0a 100644 --- a/services/route53resolver/src/main/resources/codegen-resources/customization.config +++ b/services/route53resolver/src/main/resources/codegen-resources/customization.config @@ -8,6 +8,5 @@ "listResolverEndpoints", "listResolverRuleAssociations", "listResolverRules" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/route53resolver/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/route53resolver/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6c71393af694 --- /dev/null +++ b/services/route53resolver/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://route53resolver.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/route53resolver/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/route53resolver/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index db174658fe7f..000000000000 --- a/services/route53resolver/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53resolver-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://route53resolver.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://route53resolver.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53resolver-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://route53resolver.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://route53resolver.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/rtbfabric/pom.xml b/services/rtbfabric/pom.xml index 5a028e13981d..686a09471843 100644 --- a/services/rtbfabric/pom.xml +++ b/services/rtbfabric/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rtbfabric AWS Java SDK :: Services :: RTB Fabric diff --git a/services/rtbfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rtbfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..aee0e3029e20 --- /dev/null +++ b/services/rtbfabric/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rtbfabric-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rtbfabric-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rtbfabric.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rtbfabric.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rtbfabric/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rtbfabric/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7bd12ff04705..000000000000 --- a/services/rtbfabric/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,344 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rtbfabric-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rtbfabric-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rtbfabric.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rtbfabric.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/rtbfabric/src/main/resources/codegen-resources/service-2.json b/services/rtbfabric/src/main/resources/codegen-resources/service-2.json index 0185d17fc380..18ec295b4764 100644 --- a/services/rtbfabric/src/main/resources/codegen-resources/service-2.json +++ b/services/rtbfabric/src/main/resources/codegen-resources/service-2.json @@ -719,7 +719,7 @@ {"shape":"InternalServerException"}, {"shape":"ValidationException"} ], - "documentation":"

    Updates a responder gateway.

    ", + "documentation":"

    Updates the description, Auto Scaling group managed endpoint configuration, trust store configuration, and client routing policy of a responder gateway. This operation also updates the protocols list in the listener configuration.

    You cannot change the domainName, port, and protocol values that you set when you create a responder gateway. To change any of them, delete the gateway and create a new one.

    ", "idempotent":true } }, @@ -870,7 +870,7 @@ }, "clientToken":{ "shape":"String", - "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same ClientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true } } @@ -989,6 +989,13 @@ "max":2, "min":0 }, + "ClientRoutingPolicy":{ + "type":"string", + "enum":[ + "AVAILABILITY_ZONE_AFFINITY", + "ANY_AVAILABILITY_ZONE" + ] + }, "ConflictException":{ "type":"structure", "required":["message"], @@ -1022,7 +1029,7 @@ "members":{ "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -1104,7 +1111,7 @@ }, "logSettings":{ "shape":"LinkLogSettings", - "documentation":"

    Settings for the application logs.

    " + "documentation":"

    Application log settings for the link. This value is required. Under applicationLogs.sampling, the errorLog and filterLog fields set the percentage of eligible events to log. Valid values range from 0 through 100. To turn off application logs, set both fields to 0, as in {\"applicationLogs\":{\"sampling\":{\"errorLog\":0,\"filterLog\":0}}}.

    " }, "timeoutInMillis":{ "shape":"LinkTimeoutInMillis", @@ -1190,7 +1197,7 @@ "members":{ "clientToken":{ "shape":"String", - "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same ClientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -1252,7 +1259,7 @@ "members":{ "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -1324,7 +1331,7 @@ }, "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "description":{ @@ -1392,7 +1399,7 @@ }, "subnetIds":{ "shape":"CreateResponderGatewayRequestSubnetIdsList", - "documentation":"

    The unique identifiers of the subnets.

    " + "documentation":"

    Unique identifiers of the subnets. A service quota for your account sets the number of Availability Zones that your subnets can span. By default, this quota is one Availability Zone. To span more Availability Zones, request a quota increase.

    " }, "securityGroupIds":{ "shape":"CreateResponderGatewayRequestSecurityGroupIdsList", @@ -1421,7 +1428,7 @@ }, "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "description":{ @@ -1435,6 +1442,10 @@ "gatewayType":{ "shape":"GatewayType", "documentation":"

    The type of gateway. Valid values are EXTERNAL or INTERNAL.

    " + }, + "clientRoutingPolicy":{ + "shape":"ClientRoutingPolicy", + "documentation":"

    The client routing policy of the gateway. This policy controls which Availability Zones RTB Fabric uses to reach the gateway for the requester gateways that send traffic to it. Valid values are the following:

    • AVAILABILITY_ZONE_AFFINITY: RTB Fabric routes each requester's traffic to gateway capacity in the requester's own Availability Zone when the gateway has capacity available there. Otherwise, RTB Fabric routes the traffic to gateway capacity in the other Availability Zones of the gateway.

    • ANY_AVAILABILITY_ZONE: RTB Fabric routes each requester's traffic to gateway capacity in every Availability Zone that the subnets of the gateway span. The Availability Zone that the requester is in does not change this.

    If you don't specify a value, RTB Fabric uses AVAILABILITY_ZONE_AFFINITY. To get the behavior of ANY_AVAILABILITY_ZONE, create the gateway with subnets in more than one Availability Zone. RTB Fabric does not support partial Availability Zone affinity, so PARTIAL_AVAILABILITY_ZONE_AFFINITY is not a valid value. For more information, see Configuring Availability Zone affinity in the Amazon Web Services RTB Fabric User Guide.

    " } } }, @@ -1482,6 +1493,10 @@ "externalInboundEndpoint":{ "shape":"DomainName", "documentation":"

    The external inbound endpoint for the responder gateway.

    " + }, + "clientRoutingPolicy":{ + "shape":"ClientRoutingPolicy", + "documentation":"

    The client routing policy of the gateway. This policy controls which Availability Zones RTB Fabric uses to reach the gateway for the requester gateways that send traffic to it. For more information, see Configuring Availability Zone affinity in the Amazon Web Services RTB Fabric User Guide.

    " } } }, @@ -2440,13 +2455,6 @@ "shape":"Integer", "documentation":"

    The total count of links for the responder gateway.

    " }, - "inboundLinksCount":{ - "shape":"Integer", - "documentation":"

    Deprecated. Use 'linksRequestedCount' instead.

    ", - "deprecated":true, - "deprecatedMessage":"Use linksRequestedCount instead", - "deprecatedSince":"2026-05-11" - }, "linksRequestedCount":{ "shape":"Integer", "documentation":"

    The count of requested links waiting for the responder gateway to accept or reject.

    " @@ -2458,6 +2466,10 @@ "externalInboundEndpoint":{ "shape":"DomainName", "documentation":"

    The external inbound endpoint for the responder gateway.

    " + }, + "clientRoutingPolicy":{ + "shape":"ClientRoutingPolicy", + "documentation":"

    The client routing policy of the gateway. This policy controls which Availability Zones RTB Fabric uses to reach the gateway for the requester gateways that send traffic to it. RTB Fabric omits this member if the gateway has never had a client routing policy. An omitted value means that the gateway uses AVAILABILITY_ZONE_AFFINITY. For more information, see Configuring Availability Zone affinity in the Amazon Web Services RTB Fabric User Guide.

    " } } }, @@ -3691,7 +3703,7 @@ "members":{ "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -3849,7 +3861,7 @@ "members":{ "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -3896,15 +3908,15 @@ "members":{ "domainName":{ "shape":"DomainName", - "documentation":"

    The domain name for the responder gateway.

    " + "documentation":"

    Domain name for the responder gateway. This operation does not change the domain name of an existing gateway. To use a different domain name, delete the gateway and create a new one.

    " }, "port":{ "shape":"UpdateResponderGatewayRequestPortInteger", - "documentation":"

    The networking port to use.

    " + "documentation":"

    Networking port to use. This operation does not change the port of an existing gateway. To use a different port, delete the gateway and create a new one.

    " }, "protocol":{ "shape":"Protocol", - "documentation":"

    The networking protocol to use.

    " + "documentation":"

    Networking protocol to use. This operation does not change the protocol of an existing gateway. To use a different protocol, delete the gateway and create a new one.

    " }, "listenerConfig":{ "shape":"ListenerConfig", @@ -3920,7 +3932,7 @@ }, "clientToken":{ "shape":"String", - "documentation":"

    The unique client token.

    ", + "documentation":"

    Specifies a unique, case-sensitive identifier that you provide to ensure the idempotency of the request. This lets you safely retry the request without accidentally performing the same operation a second time. Passing the same value to a later call to an operation requires that you also pass the same value for all other parameters. We recommend that you use a UUID type of value.

    If you don't provide this value, then Amazon Web Services generates a random one for you.

    If you retry the operation with the same clientToken, but with different parameters, the retry fails with an IdempotentParameterMismatch error.

    ", "idempotencyToken":true }, "gatewayId":{ @@ -3932,6 +3944,10 @@ "description":{ "shape":"UpdateResponderGatewayRequestDescriptionString", "documentation":"

    An optional description for the responder gateway.

    " + }, + "clientRoutingPolicy":{ + "shape":"ClientRoutingPolicy", + "documentation":"

    The client routing policy of the gateway. This policy controls which Availability Zones RTB Fabric uses to reach the gateway for the requester gateways that send traffic to it. Valid values are the following:

    • AVAILABILITY_ZONE_AFFINITY: RTB Fabric routes each requester's traffic to gateway capacity in the requester's own Availability Zone when the gateway has capacity available there. Otherwise, RTB Fabric routes the traffic to gateway capacity in the other Availability Zones of the gateway.

    • ANY_AVAILABILITY_ZONE: RTB Fabric routes each requester's traffic to gateway capacity in every Availability Zone that the subnets of the gateway span. The Availability Zone that the requester is in does not change this.

    If you don't specify a value, the gateway keeps its current client routing policy. Changing the policy sets the gateway status to PENDING_UPDATE until the change is complete. RTB Fabric does not support partial Availability Zone affinity, so PARTIAL_AVAILABILITY_ZONE_AFFINITY is not a valid value. For more information, see Configuring Availability Zone affinity in the Amazon Web Services RTB Fabric User Guide.

    " } } }, @@ -3959,6 +3975,10 @@ "status":{ "shape":"ResponderGatewayStatus", "documentation":"

    The status of the request.

    " + }, + "clientRoutingPolicy":{ + "shape":"ClientRoutingPolicy", + "documentation":"

    The client routing policy of the gateway. If the operation changed this policy, the gateway uses the new policy after its status returns to ACTIVE. For more information, see Configuring Availability Zone affinity in the Amazon Web Services RTB Fabric User Guide.

    " } } }, diff --git a/services/rum/pom.xml b/services/rum/pom.xml index c303991a0bd4..53133e553a59 100644 --- a/services/rum/pom.xml +++ b/services/rum/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT rum AWS Java SDK :: Services :: RUM diff --git a/services/rum/src/main/resources/codegen-resources/customization.config b/services/rum/src/main/resources/codegen-resources/customization.config index cdf857bdc287..e8d9faf606f5 100644 --- a/services/rum/src/main/resources/codegen-resources/customization.config +++ b/services/rum/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/rum/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/rum/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7736a3b65018 --- /dev/null +++ b/services/rum/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rum-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rum-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rum.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://rum.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/rum/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/rum/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 44f626381175..000000000000 --- a/services/rum/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rum-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rum-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://rum.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://rum.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/s3/pom.xml b/services/s3/pom.xml index ac3033feb2f1..62e985df2a07 100644 --- a/services/s3/pom.xml +++ b/services/s3/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3 AWS Java SDK :: Services :: Amazon S3 @@ -180,11 +180,6 @@ wiremock-jre8-standalone test - - org.reactivestreams - reactive-streams-tck - test - software.amazon.awssdk auth-crt 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 dbe6681d027b..875f03353116 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 @@ -36,6 +36,7 @@ import java.util.List; import java.util.Random; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.apache.commons.lang3.RandomStringUtils; @@ -57,6 +58,7 @@ import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.http.ContentStreamProvider; +import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient; import software.amazon.awssdk.metrics.MetricCollection; import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.services.s3.model.GetObjectResponse; @@ -94,6 +96,23 @@ public static Stream s3Clients() { Arguments.of(crtClientBuilder().build())); } + @Test + public void crtAsyncClient_chunkedEncodingDisabled_shouldNotHang() throws Exception { + try (S3AsyncClient s3Async = S3AsyncClient.builder() + .region(DEFAULT_REGION) + .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) + .httpClientBuilder(AwsCrtAsyncHttpClient.builder()) + .serviceConfiguration(S3Configuration.builder() + .chunkedEncodingEnabled(false) + .build()) + .build()) { + PutObjectResponse response = s3Async.putObject(r -> r.bucket(BUCKET).key(SYNC_KEY), + AsyncRequestBody.fromString("TESTING")) + .get(30, TimeUnit.SECONDS); + assertThat(response.eTag()).isNotNull(); + } + } + @Test public void objectInputStreamsAreClosed() { TestContentProvider provider = new TestContentProvider(CONTENT); diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/ResponsePublisherTimeoutIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/ResponsePublisherTimeoutIntegrationTest.java index cabd234977bd..4645e75a0106 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/ResponsePublisherTimeoutIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/ResponsePublisherTimeoutIntegrationTest.java @@ -43,7 +43,9 @@ public class ResponsePublisherTimeoutIntegrationTest extends S3IntegrationTestBa private static final String BUCKET = temporaryBucketName(GetObjectIntegrationTest.class); private static final String KEY = "TestKey"; - private static final String CONTENT = "Hello"; + // Large enough to trigger StreamedHttpResponse instead of FullHttpResponse in Netty. + // FullHttpResponse releases the connection immediately, defeating pool-exhaustion tests. + private static final int CONTENT_LENGTH = 2 * 1024 * 1024; private static final GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket(BUCKET) .key(KEY) @@ -61,7 +63,7 @@ public static void setupFixture() throws IOException { s3.putObject(PutObjectRequest.builder() .bucket(BUCKET) .key(KEY) - .build(), RequestBody.fromString(CONTENT)); + .build(), RequestBody.fromBytes(new byte[CONTENT_LENGTH])); } @AfterClass @@ -87,7 +89,7 @@ public void defaultTimeout_firstPublisherConsumed_secondRequestSucceeds() { CompletableFuture> get2 = getObjectWithDefaultTimeoutPublisher(); GetObjectResponse getObjectResponse = get2.join().response(); - assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT.length()); + assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT_LENGTH); } @Test @@ -97,7 +99,7 @@ public void defaultTimeout_cancelFirstRequestFuture_secondRequestSucceeds() { CompletableFuture> get2 = getObjectWithDefaultTimeoutPublisher(); GetObjectResponse getObjectResponse = get2.join().response(); - assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT.length()); + assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT_LENGTH); } @Test @@ -107,7 +109,7 @@ public void customTimeout_waitForTimeout_secondRequestSucceeds() throws Interrup CompletableFuture> get2 = getObjectWithDefaultTimeoutPublisher(); GetObjectResponse getObjectResponse = get2.join().response(); - assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT.length()); + assertThat(getObjectResponse.contentLength()).isEqualTo(CONTENT_LENGTH); } private CompletableFuture> getObjectWithDefaultTimeoutPublisher() { diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionIntegrationTest.java new file mode 100644 index 000000000000..1ec2cf2df702 --- /dev/null +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionIntegrationTest.java @@ -0,0 +1,32 @@ +/* + * 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.presignedurl; + +import org.junit.jupiter.api.BeforeAll; +import software.amazon.awssdk.services.s3.S3AsyncClient; + +public class AsyncPresignedUrlExtensionIntegrationTest extends AsyncPresignedUrlExtensionTestSuite { + + @BeforeAll + static void setUpIntegrationTest() { + S3AsyncClient s3AsyncClient = s3AsyncClientBuilder().build(); + presignedUrlExtension = s3AsyncClient.presignedUrlExtension(); + } + + @Override + protected S3AsyncClient createS3AsyncClient() { + return s3AsyncClientBuilder().build(); + } +} diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionMultipartIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionMultipartIntegrationTest.java new file mode 100644 index 000000000000..16e41325817f --- /dev/null +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionMultipartIntegrationTest.java @@ -0,0 +1,35 @@ +/* + * 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.presignedurl; + +import org.junit.jupiter.api.BeforeAll; +import software.amazon.awssdk.services.s3.S3AsyncClient; + + +public class AsyncPresignedUrlExtensionMultipartIntegrationTest extends AsyncPresignedUrlExtensionTestSuite { + + @BeforeAll + static void setUpIntegrationTest() { + S3AsyncClient s3AsyncClient = s3AsyncClientBuilder() + .multipartEnabled(true) + .build(); + presignedUrlExtension = s3AsyncClient.presignedUrlExtension(); + } + + @Override + protected S3AsyncClient createS3AsyncClient() { + return s3AsyncClientBuilder().build(); + } +} diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTestSuite.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTestSuite.java new file mode 100644 index 000000000000..b5a3edbfd8f7 --- /dev/null +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTestSuite.java @@ -0,0 +1,534 @@ +/* + * 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.presignedurl; + +import static org.apache.commons.lang3.RandomStringUtils.randomAscii; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +import java.io.ByteArrayInputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +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.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricPublisher; +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.CompletedMultipartUpload; +import software.amazon.awssdk.services.s3.model.CompletedPart; +import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.model.UploadPartResponse; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; +import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.services.s3.utils.S3TestUtils; +import software.amazon.awssdk.testutils.service.S3BucketUtils; +import software.amazon.awssdk.utils.Md5Utils; + +/** + * Abstract test suite for AsyncPresignedUrlExtension integration tests. + */ +public abstract class AsyncPresignedUrlExtensionTestSuite extends S3IntegrationTestBase { + protected static S3Presigner presigner; + protected static AsyncPresignedUrlExtension presignedUrlExtension; + protected static String testBucket; + + @TempDir + static Path temporaryFolder; + + protected static String testGetObjectKey; + protected static String testLargeObjectKey; + protected static String testMpuChecksumKey; + protected static String testObjectContent; + protected static byte[] testLargeObjectContent; + protected static byte[] testMpuObjectContent; + protected static String expectedLargeObjectMd5; + + protected abstract S3AsyncClient createS3AsyncClient(); + + @BeforeAll + static void setUpTestSuite() throws Exception { + setUp(); + + presigner = S3Presigner.builder() + .region(DEFAULT_REGION) + .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) + .build(); + testBucket = S3BucketUtils.temporaryBucketName("async-presigned-url-extension-test"); + createBucket(testBucket); + testGetObjectKey = generateRandomObjectKey(); + testLargeObjectKey = generateRandomObjectKey() + "-large"; + testObjectContent = "Hello AsyncPresignedUrlExtension Integration Test"; + testLargeObjectContent = randomAscii(5 * 1024 * 1024).getBytes(StandardCharsets.UTF_8); + + try (ByteArrayInputStream originalStream = new ByteArrayInputStream(testLargeObjectContent)) { + expectedLargeObjectMd5 = Md5Utils.md5AsBase64(originalStream); + } catch (Exception e) { + throw new RuntimeException("Failed to compute MD5 for test data", e); + } + + S3TestUtils.putObject(AsyncPresignedUrlExtensionTestSuite.class, s3, testBucket, testGetObjectKey, testObjectContent); + s3Async.putObject( + PutObjectRequest.builder() + .bucket(testBucket) + .key(testLargeObjectKey) + .build(), + AsyncRequestBody.fromBytes(testLargeObjectContent) + ).join(); + uploadMpuObjectWithChecksum(); + S3TestUtils.addCleanupTask(AsyncPresignedUrlExtensionTestSuite.class, () -> { + s3.deleteObject(DeleteObjectRequest.builder() + .bucket(testBucket) + .key(testGetObjectKey) + .build()); + s3.deleteObject(DeleteObjectRequest.builder() + .bucket(testBucket) + .key(testLargeObjectKey) + .build()); + s3.deleteObject(DeleteObjectRequest.builder() + .bucket(testBucket) + .key(testMpuChecksumKey) + .build()); + deleteBucketAndAllContents(testBucket); + }); + } + + @AfterAll + static void tearDownTestSuite() { + try { + S3TestUtils.runCleanupTasks(AsyncPresignedUrlExtensionTestSuite.class); + } catch (Exception e) { + } + if (presigner != null) { + presigner.close(); + } + cleanUpResources(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("basicFunctionalityTestData") + void getObject_withValidPresignedUrl_returnsContent(String testDescription, + String objectKey, + String expectedContent) throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(objectKey); + + CompletableFuture> future = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + ResponseBytes response = future.get(); + + assertThat(response).isNotNull(); + if (expectedContent != null) { + assertThat(response.asUtf8String()).isEqualTo(expectedContent); + assertThat(response.response().contentLength()).isEqualTo(expectedContent.length()); + } else { + try (ByteArrayInputStream downloadedStream = new ByteArrayInputStream(response.asByteArray())) { + String downloadedMd5 = Md5Utils.md5AsBase64(downloadedStream); + assertThat(downloadedMd5).isEqualTo(expectedLargeObjectMd5); + assertThat(response.asByteArray().length).isEqualTo(testLargeObjectContent.length); + } + assertThat(response.response()).isNotNull(); + assertThat(response.response().contentLength()).isEqualTo((long) testLargeObjectContent.length); + assertThat(response.response().sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } + } + + @Test + void getObject_withValidPresignedUrl_savesContentToFile() throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(testGetObjectKey); + Path downloadFile = temporaryFolder.resolve("download-" + UUID.randomUUID() + ".txt"); + CompletableFuture future = + presignedUrlExtension.getObject(request, downloadFile); + GetObjectResponse response = future.get(); + + assertThat(response).isNotNull(); + assertThat(downloadFile).exists(); + assertThat(downloadFile).hasContent(testObjectContent); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("rangeTestData") + void getObject_withRangeRequest_returnsSpecifiedRange(String testDescription, + String range, + String expectedContent) throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(testGetObjectKey, range); + + CompletableFuture> future = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + ResponseBytes response = future.get(); + + assertThat(response.asUtf8String()).isEqualTo(expectedContent); + } + + @Test + void getObject_withMultipleRangeRequestsConcurrently_returnsCorrectContent() throws Exception { + String concurrentTestKey = uploadTestObject("concurrent-test", "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + List>> futures = new ArrayList<>(); + + futures.add(presignedUrlExtension.getObject( + createRequestForKey(concurrentTestKey, "bytes=0-8"), // "012345678" + AsyncResponseTransformer.toBytes())); + futures.add(presignedUrlExtension.getObject( + createRequestForKey(concurrentTestKey, "bytes=9-17"), // "9ABCDEFGH" + AsyncResponseTransformer.toBytes())); + futures.add(presignedUrlExtension.getObject( + createRequestForKey(concurrentTestKey, "bytes=18-26"), // "IJKLMNOPQ" + AsyncResponseTransformer.toBytes())); + futures.add(presignedUrlExtension.getObject( + createRequestForKey(concurrentTestKey, "bytes=27-35"), // "RSTUVWXYZ" + AsyncResponseTransformer.toBytes())); + + CompletableFuture allFutures = CompletableFuture.allOf( + futures.toArray(new CompletableFuture[0])); + allFutures.get(30, TimeUnit.SECONDS); + + StringBuilder result = new StringBuilder(); + for (CompletableFuture> future : futures) { + result.append(future.get().asUtf8String()); + } + + assertThat(result.toString()).isEqualTo("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + } + + @Test + void getObject_withLargeObjectToFile_savesCompleteContentAndCollectsMetrics() throws Exception { + List collectedMetrics = new ArrayList<>(); + MetricPublisher metricPublisher = new MetricPublisher() { + @Override + public void publish(MetricCollection metricCollection) { + collectedMetrics.add(metricCollection); + } + @Override + public void close() {} + }; + + try (S3AsyncClient clientWithMetrics = s3AsyncClientBuilder() + .overrideConfiguration(o -> o.addMetricPublisher(metricPublisher)) + .build()) { + + AsyncPresignedUrlExtension metricsExtension = clientWithMetrics.presignedUrlExtension(); + PresignedUrlDownloadRequest request = createRequestForKey(testLargeObjectKey); + Path downloadFile = temporaryFolder.resolve("large-download-with-metrics-" + UUID.randomUUID() + ".bin"); + + CompletableFuture future = + metricsExtension.getObject(request, downloadFile); + GetObjectResponse response = future.get(60, TimeUnit.SECONDS); + + assertThat(response).isNotNull(); + assertThat(downloadFile).exists(); + assertThat(downloadFile.toFile().length()).isEqualTo(testLargeObjectContent.length); + assertThat(response.contentLength()).isEqualTo((long) testLargeObjectContent.length); + assertThat(response.sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + assertThat(collectedMetrics).isNotEmpty(); + } + } + + @Test + void getObject_emptyObject_toBytes_shouldSucceed() throws Exception { + String emptyKey = uploadTestObject("empty-object-bytes", ""); + + PresignedUrlDownloadRequest request = createRequestForKey(emptyKey); + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response.asByteArray()).isEmpty(); + assertThat(response.response().contentLength()).isEqualTo(0L); + } + + @Test + void getObject_emptyObject_toFile_shouldSucceed() throws Exception { + String emptyKey = uploadTestObject("empty-object-file", ""); + + PresignedUrlDownloadRequest request = createRequestForKey(emptyKey); + Path downloadFile = temporaryFolder.resolve("empty-download-" + UUID.randomUUID() + ".bin"); + GetObjectResponse response = + presignedUrlExtension.getObject(request, downloadFile) + .get(30, TimeUnit.SECONDS); + + assertThat(downloadFile).exists(); + assertThat(downloadFile.toFile().length()).isEqualTo(0L); + } + + @Test + void getObject_emptyObject_withRange_shouldThrow416() throws Exception { + String emptyKey = uploadTestObject("empty-object-range", ""); + + PresignedUrlDownloadRequest request = createRequestForKey(emptyKey, "bytes=0-1024"); + + assertThatThrownBy(() -> presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS)) + .hasCauseInstanceOf(S3Exception.class); + } + + @Test + void getObject_withChecksumModeEnabled_returnsChecksumHeaders() throws Exception { + PresignedGetObjectRequest presigned = presigner.presignGetObject(r -> r + .getObjectRequest(req -> req.bucket(testBucket).key(testGetObjectKey) + .checksumMode(ChecksumMode.ENABLED)) + .signatureDuration(Duration.ofMinutes(10))); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presigned.url()) + .build(); + + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response.asUtf8String()).isEqualTo(testObjectContent); + assertThat(response.response().checksumTypeAsString()).isNotNull(); + } + + @Test + void getObject_withoutChecksumMode_doesNotReturnChecksumHeaders() throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(testGetObjectKey); + + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response.asUtf8String()).isEqualTo(testObjectContent); + assertThat(response.response().checksumTypeAsString()).isNull(); + } + + @Test + void getObject_withChecksumModeEnabled_requestContainsChecksumHeader() throws Exception { + PresignedGetObjectRequest presigned = presigner.presignGetObject(r -> r + .getObjectRequest(req -> req.bucket(testBucket).key(testGetObjectKey) + .checksumMode(ChecksumMode.ENABLED)) + .signatureDuration(Duration.ofMinutes(10))); + + // Verify the presigned URL has checksum-mode in SignedHeaders + assertThat(presigned.signedHeaders()).containsKey("x-amz-checksum-mode"); + assertThat(presigned.isBrowserExecutable()).isFalse(); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presigned.url()) + .build(); + + // Download should succeed (proves marshaller sent the header) + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response).isNotNull(); + assertThat(response.asUtf8String()).isEqualTo(testObjectContent); + } + + static Stream basicFunctionalityTestData() { + return Stream.of( + Arguments.of("getObject_withValidUrl_returnsContent", + testGetObjectKey, testObjectContent), + Arguments.of("getObject_withValidLargeObjectUrl_returnsContent", + testLargeObjectKey, null) + ); + } + + static Stream rangeTestData() { + String content = "Hello AsyncPresignedUrlExtension Integration Test"; + return Stream.of( + Arguments.of("getObject_withPrefix10BytesRange_returnsFirst10Bytes", + "bytes=0-9", content.substring(0, 10)), + Arguments.of("getObject_withSuffix10BytesRange_returnsLast10Bytes", + "bytes=-10", content.substring(content.length() - 10)), + Arguments.of("getObject_withMiddle10BytesRange_returnsMiddle10Bytes", + "bytes=10-19", content.substring(10, 20)), + Arguments.of("getObject_withSingleByteRange_returnsSingleByte", + "bytes=0-0", content.substring(0, 1)) + ); + } + + @Test + void getObject_withRangeRequest_preservesPartialMetadata() throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(testLargeObjectKey, "bytes=0-1048575"); + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response.response().contentLength()).isEqualTo(1048576L); + assertThat(response.response().contentRange()).isNotNull(); + assertThat(response.response().sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } + + @ParameterizedTest(name = "getObject_largeObject_{0}_hasCorrectFullObjectMetadata") + @MethodSource("transformerTypes") + void getObject_largeObject_hasCorrectFullObjectMetadata(String type) throws Exception { + PresignedUrlDownloadRequest request = createRequestForKey(testLargeObjectKey); + + if ("toFile".equals(type)) { + Path downloadFile = temporaryFolder.resolve("large-metadata-test-" + UUID.randomUUID() + ".bin"); + GetObjectResponse response = + presignedUrlExtension.getObject(request, downloadFile) + .get(60, TimeUnit.SECONDS); + + assertThat(response.contentLength()).isEqualTo((long) testLargeObjectContent.length); + assertThat(downloadFile.toFile().length()).isEqualTo(testLargeObjectContent.length); + assertThat(response.sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } else { + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(60, TimeUnit.SECONDS); + + assertThat(response.asByteArray().length).isEqualTo(testLargeObjectContent.length); + assertThat(response.response().contentLength()).isEqualTo((long) testLargeObjectContent.length); + assertThat(response.response().sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } + } + + static Stream transformerTypes() { + return Stream.of("toFile", "toBytes"); + } + + @ParameterizedTest(name = "getObject_mpuObject_{0}_hasCorrectMetadata") + @MethodSource("checksumModes") + void getObject_mpuObject_hasCorrectMetadata(String mode) throws Exception { + PresignedUrlDownloadRequest request; + if ("withChecksumMode".equals(mode)) { + PresignedGetObjectRequest presigned = presigner.presignGetObject(r -> r + .getObjectRequest(req -> req.bucket(testBucket).key(testMpuChecksumKey) + .checksumMode(ChecksumMode.ENABLED)) + .signatureDuration(Duration.ofMinutes(10))); + request = PresignedUrlDownloadRequest.builder().presignedUrl(presigned.url()).build(); + } else { + request = PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedUrl(testMpuChecksumKey)) + .build(); + } + + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(60, TimeUnit.SECONDS); + + assertThat(response.asByteArray().length).isEqualTo(testMpuObjectContent.length); + assertThat(response.response().contentLength()).isEqualTo((long) testMpuObjectContent.length); + assertThat(response.response().sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } + + static Stream checksumModes() { + return Stream.of("withChecksumMode", "withoutChecksumMode"); + } + + @Test + void getObject_mpuObjectWithRange_preservesPartialMetadata() throws Exception { + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedUrl(testMpuChecksumKey)) + .range("bytes=0-1048575") + .build(); + + ResponseBytes response = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()) + .get(30, TimeUnit.SECONDS); + + assertThat(response.response().contentLength()).isEqualTo(1048576L); + assertThat(response.response().contentRange()).contains("bytes 0-1048575/"); + assertThat(response.response().sdkHttpResponse().firstMatchingHeader("x-amz-request-id")).isPresent(); + } + + // Helper methods + private static void uploadMpuObjectWithChecksum() { + testMpuChecksumKey = generateRandomObjectKey() + "-mpu-checksum"; + int partSize = 5 * 1024 * 1024; + int numParts = 2; + testMpuObjectContent = new byte[partSize * numParts]; + new Random(42).nextBytes(testMpuObjectContent); + + CreateMultipartUploadResponse createResp = + s3.createMultipartUpload(b -> b.bucket(testBucket).key(testMpuChecksumKey) + .checksumAlgorithm(ChecksumAlgorithm.CRC32)); + String uploadId = createResp.uploadId(); + List parts = new ArrayList<>(); + + for (int i = 0; i < numParts; i++) { + byte[] partData = Arrays.copyOfRange(testMpuObjectContent, i * partSize, (i + 1) * partSize); + final int partNum = i + 1; + UploadPartResponse uploadResp = s3.uploadPart( + b -> b.bucket(testBucket).key(testMpuChecksumKey).uploadId(uploadId).partNumber(partNum) + .checksumAlgorithm(ChecksumAlgorithm.CRC32), + RequestBody.fromBytes(partData)); + parts.add(CompletedPart.builder() + .partNumber(partNum).eTag(uploadResp.eTag()) + .checksumCRC32(uploadResp.checksumCRC32()).build()); + } + + s3.completeMultipartUpload(b -> b.bucket(testBucket).key(testMpuChecksumKey).uploadId(uploadId) + .multipartUpload(CompletedMultipartUpload.builder() + .parts(parts).build())); + } + + private static String generateRandomObjectKey() { + return "async-presigned-url-extension-test-" + UUID.randomUUID(); + } + + private PresignedUrlDownloadRequest createRequestForKey(String key) { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedUrl(key)) + .build(); + } + + private PresignedUrlDownloadRequest createRequestForKey(String key, String range) { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(createPresignedUrl(key)) + .range(range) + .build(); + } + + private URL createPresignedUrl(String key) { + PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(r -> r + .getObjectRequest(req -> req.bucket(testBucket).key(key)) + .signatureDuration(Duration.ofMinutes(10))); + return presignedRequest.url(); + } + + private String uploadTestObject(String keyPrefix, String content) { + String key = keyPrefix + "-" + UUID.randomUUID(); + S3TestUtils.putObject(AsyncPresignedUrlExtensionTestSuite.class, s3, testBucket, key, content); + + S3TestUtils.addCleanupTask(AsyncPresignedUrlExtensionTestSuite.class, () -> { + s3.deleteObject(DeleteObjectRequest.builder() + .bucket(testBucket) + .key(key) + .build()); + }); + return key; + } +} 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 697601df9ab9..bc3006899f8d 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 @@ -248,8 +248,8 @@ public boolean chunkedEncodingEnabled() { * By default, the SDK sends the {@code Expect: 100-continue} header for these operations, allowing the server to * reject the request before the client sends the full payload. Setting this to {@code false} disables this behavior. *

    - * If enabling cross region access on the client, this setting has no effect as the client needs to set this header - * for correct redirect behavior. + * When cross region access is enabled, the header is sent by default so S3 can issue its cross region redirect before + * the body is streamed. Setting this to {@code false} is still honored, but opts out of that protection. *

    * Note: When using the {@code ApacheHttpClient} (Apache 4), the Apache 4 client also independently adds the * {@code Expect: 100-continue} header by default via its own {@code expectContinueEnabled} setting. To fully diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Utilities.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Utilities.java index e5f4d07df7e3..b777fe4d37a0 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Utilities.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Utilities.java @@ -417,22 +417,25 @@ private Region resolveRegionForGetUrl(GetUrlRequest getUrlRequest) { } /** - * If endpoint is not present, construct a default endpoint using the region information. + * Resolve the client endpoint provider for request marshalling. Checks client override, + * environment variables, system properties, and profile configuration. If no override is found, + * a localhost placeholder is used — the actual endpoint is resolved by S3EndpointProvider + * during the getUrl flow. */ private ClientEndpointProvider clientEndpointProvider(URI overrideEndpoint, Region region) { - return AwsClientEndpointProvider.builder() - .clientEndpointOverride(overrideEndpoint) - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_S3") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlS3") - .serviceProfileProperty("s3") - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol("https") - .region(region) - .profileFile(profileFile) - .profileName(profileName) - .dualstackEnabled(s3Configuration.dualstackEnabled()) - .fipsEnabled(fipsEnabled) - .build(); + Optional resolvedOverride = AwsClientEndpointProvider.builder() + .clientEndpointOverride(overrideEndpoint) + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_S3") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlS3") + .serviceProfileProperty("s3") + .profileFile(profileFile) + .profileName(profileName) + .resolveFromOverrides(); + + return resolvedOverride + .map(uri -> ClientEndpointProvider.create(uri, true)) + // Need an endpoint to marshall but this will be overwritten later with Endpoints 2.0 resolution + .orElseGet(() -> ClientEndpointProvider.create(URI.create("https://localhost"), false)); } private URI getEndpointOverride(GetUrlRequest request) { @@ -518,7 +521,7 @@ private SdkHttpRequest resolveEndpointAndApply(GetObjectRequest request, SdkHttp ClientEndpointProvider clientEndpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER); SdkHttpRequest result = AwsEndpointProviderUtils.setUri(httpRequest, - clientEndpointProvider.clientEndpoint(), endpoint.url()); + clientEndpointProvider.clientEndpoint(), endpoint.endpointUrl()); if (!endpoint.headers().isEmpty()) { SdkHttpRequest.Builder builder = result.toBuilder(); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactory.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactory.java new file mode 100644 index 000000000000..dd822aaccc5f --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactory.java @@ -0,0 +1,106 @@ +/* + * 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.endpoints.authscheme; + +import software.amazon.awssdk.annotations.NotThreadSafe; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.core.exception.SdkClientException; + +/** + * Builds an {@link EndpointAuthScheme} whose scheme name is only known at runtime. + * + *

    Endpoint rulesets normally declare the auth scheme name as a string literal, which lets codegen emit a direct call to the + * matching concrete builder (for example {@code SigV4AuthScheme.builder()}). S3 is the one exception: its BDD-based ruleset + * merges two otherwise identical results whose auth scheme names differ, lifting the difference into a runtime conditional: + * + * {@snippet : + * _s3e_auth = ite(coalesce(DisableS3ExpressSessionAuth, false), "sigv4", "sigv4-s3express"); + * } + * + *

    The merged result then refers to the name indirectly, so the concrete type cannot be selected at codegen time. This factory + * collects the auth scheme properties up front and defers the type selection to {@link #create(String)}. + * + *

    Only {@code sigv4} and {@code sigv4-s3express} are supported, since those are the only names the S3 ruleset can produce + * here. The two schemes share the same property set ({@code signingName}, {@code signingRegion}, + * {@code disableDoubleEncoding}), so the properties are modelled directly rather than generically. Any other name is a + * programming error and fails fast. + * + *

    Instances are mutable and are not safe for concurrent use. Generated endpoint providers create a fresh instance per + * resolution, so each instance is confined to a single resolution. + */ +@SdkProtectedApi +@NotThreadSafe +public final class DynamicEndpointAuthSchemeFactory { + private static final String SIGV4_NAME = "sigv4"; + private static final String S3EXPRESS_NAME = "sigv4-s3express"; + + private String signingName; + private String signingRegion; + private Boolean disableDoubleEncoding; + + private DynamicEndpointAuthSchemeFactory() { + } + + public static DynamicEndpointAuthSchemeFactory builder() { + return new DynamicEndpointAuthSchemeFactory(); + } + + public DynamicEndpointAuthSchemeFactory signingName(String signingName) { + this.signingName = signingName; + return this; + } + + public DynamicEndpointAuthSchemeFactory signingRegion(String signingRegion) { + this.signingRegion = signingRegion; + return this; + } + + public DynamicEndpointAuthSchemeFactory disableDoubleEncoding(Boolean disableDoubleEncoding) { + this.disableDoubleEncoding = disableDoubleEncoding; + return this; + } + + /** + * Create the endpoint auth scheme matching {@code name}, applying the properties collected on this factory. + * + *

    Unset properties are passed through as {@code null}, which the concrete auth schemes treat as "not set" in the same way + * they do when codegen emits a direct builder call. + * + * @param name the auth scheme name; must be {@code sigv4} or {@code sigv4-s3express} + * @return the constructed endpoint auth scheme + * @throws SdkClientException if {@code name} is not a supported auth scheme name, including when it is {@code null} + */ + public EndpointAuthScheme create(String name) { + if (SIGV4_NAME.equals(name)) { + return SigV4AuthScheme.builder() + .signingName(signingName) + .signingRegion(signingRegion) + .disableDoubleEncoding(disableDoubleEncoding) + .build(); + } + if (S3EXPRESS_NAME.equals(name)) { + return S3ExpressEndpointAuthScheme.builder() + .signingName(signingName) + .signingRegion(signingRegion) + .disableDoubleEncoding(disableDoubleEncoding) + .build(); + } + throw SdkClientException.create("Unsupported dynamic endpoint auth scheme name: '" + name + "'. Expected '" + + SIGV4_NAME + "' or '" + S3EXPRESS_NAME + "'."); + } +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/KnownS3ExpressEndpointProperty.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/KnownS3ExpressEndpointProperty.java index 0bb694100826..c87b9aef20b8 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/KnownS3ExpressEndpointProperty.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/KnownS3ExpressEndpointProperty.java @@ -15,12 +15,7 @@ package software.amazon.awssdk.services.s3.endpoints.internal; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; import software.amazon.awssdk.endpoints.EndpointAttributeKey; @SdkInternalApi @@ -32,49 +27,6 @@ public final class KnownS3ExpressEndpointProperty { public static final EndpointAttributeKey BACKEND = new EndpointAttributeKey<>("Backend", String.class); - public static final List> KNOWN_S3_ENDPOINT_PROPERTIES = Collections.unmodifiableList( - Arrays.asList( - new AuthSchemesProperty(), - new BackendProperty() - ) - ); - private KnownS3ExpressEndpointProperty() { } - - private static class AuthSchemesProperty implements EndpointAttributeProvider> { - @Override - public String propertyName() { - return "authSchemes"; - } - - @Override - public EndpointAttributeKey> attributeKey() { - return AwsEndpointAttribute.AUTH_SCHEMES; - } - - @Override - public List attributeValue(Value value) { - EndpointAuthSchemeStrategyFactory endpointAuthSchemeStrategyFactory = new S3EndpointAuthSchemeStrategyFactory(); - EndpointAuthSchemeStrategy strategy = endpointAuthSchemeStrategyFactory.endpointAuthSchemeStrategy(); - return strategy.createAuthSchemes(value); - } - } - - private static class BackendProperty implements EndpointAttributeProvider { - @Override - public String propertyName() { - return "backend"; - } - - @Override - public EndpointAttributeKey attributeKey() { - return BACKEND; - } - - @Override - public String attributeValue(Value value) { - return value.expectString(); - } - } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/S3EndpointAuthSchemeStrategyFactory.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/S3EndpointAuthSchemeStrategyFactory.java deleted file mode 100644 index 57555d45843d..000000000000 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/endpoints/internal/S3EndpointAuthSchemeStrategyFactory.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.endpoints.internal; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.services.s3.endpoints.authscheme.S3ExpressEndpointAuthScheme; - -@SdkInternalApi -public final class S3EndpointAuthSchemeStrategyFactory implements EndpointAuthSchemeStrategyFactory { - - public static final String SIGNING_NAME_ID = "signingName"; - public static final String SIGNING_REGION_SET_ID = "signingRegionSet"; - public static final String DISABLE_DOUBLE_ENCODING_ID = "disableDoubleEncoding"; - public static final String SIGNING_REGION_ID = "signingRegion"; - - private static final String SIGV4_NAME = "sigv4"; - private static final String SIGV4A_NAME = "sigv4a"; - private static final String S3EXPRESS_NAME = "sigv4-s3express"; - - @Override - public EndpointAuthSchemeStrategy endpointAuthSchemeStrategy() { - Map> knownAuthSchemesMapping = new HashMap<>(); - knownAuthSchemesMapping.put(SIGV4A_NAME, this::sigV4A); - knownAuthSchemesMapping.put(SIGV4_NAME, this::sigV4); - knownAuthSchemesMapping.put(S3EXPRESS_NAME, this::s3Express); - return new DefaultEndpointAuthSchemeStrategy(knownAuthSchemesMapping); - } - - private EndpointAuthScheme sigV4A(Value.Record scheme) { - SigV4aAuthScheme.Builder schemeBuilder = SigV4aAuthScheme.builder(); - - Value signingName = scheme.get(Identifier.of(SIGNING_NAME_ID)); - if (signingName != null) { - schemeBuilder.signingName(signingName.expectString()); - } - - Value signingRegionSet = scheme.get(Identifier.of(SIGNING_REGION_SET_ID)); - if (signingRegionSet != null) { - Value.Array signingRegionSetArray = signingRegionSet.expectArray(); - for (int j = 0; j < signingRegionSetArray.size(); ++j) { - schemeBuilder.addSigningRegion(signingRegionSetArray.get(j).expectString()); - } - } - - Value disableDoubleEncoding = scheme.get(Identifier.of(DISABLE_DOUBLE_ENCODING_ID)); - if (disableDoubleEncoding != null) { - schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool()); - } - - return schemeBuilder.build(); - } - - private EndpointAuthScheme sigV4(Value.Record scheme) { - SigV4AuthScheme.Builder schemeBuilder = SigV4AuthScheme.builder(); - - Value signingName = scheme.get(Identifier.of(SIGNING_NAME_ID)); - if (signingName != null) { - schemeBuilder.signingName(signingName.expectString()); - } - - Value signingRegion = scheme.get(Identifier.of(SIGNING_REGION_ID)); - if (signingRegion != null) { - schemeBuilder.signingRegion(signingRegion.expectString()); - } - - Value disableDoubleEncoding = scheme.get(Identifier.of(DISABLE_DOUBLE_ENCODING_ID)); - if (disableDoubleEncoding != null) { - schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool()); - } - - return schemeBuilder.build(); - } - - private EndpointAuthScheme s3Express(Value.Record scheme) { - S3ExpressEndpointAuthScheme.Builder schemeBuilder = S3ExpressEndpointAuthScheme.builder(); - - Value signingName = scheme.get(Identifier.of(SIGNING_NAME_ID)); - if (signingName != null) { - schemeBuilder.signingName(signingName.expectString()); - } - - Value signingRegion = scheme.get(Identifier.of(SIGNING_REGION_ID)); - if (signingRegion != null) { - schemeBuilder.signingRegion(signingRegion.expectString()); - } - - Value disableDoubleEncoding = scheme.get(Identifier.of(DISABLE_DOUBLE_ENCODING_ID)); - if (disableDoubleEncoding != null) { - schemeBuilder.disableDoubleEncoding(disableDoubleEncoding.expectBool()); - } - - return schemeBuilder.build(); - } -} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtContentLengthOnlyAsyncFileRequestBody.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtContentLengthOnlyAsyncFileRequestBody.java index 72e8b0dba363..0de6ea3339eb 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtContentLengthOnlyAsyncFileRequestBody.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtContentLengthOnlyAsyncFileRequestBody.java @@ -51,4 +51,9 @@ public void cancel() { }); } + + @Override + public String body() { + return asyncRequestBody.body(); + } } 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 8a7bfebbff43..6f0fef9c5f8f 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 @@ -80,6 +80,7 @@ import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.CollectionUtils; import software.amazon.awssdk.utils.Validate; @@ -90,6 +91,8 @@ public final class DefaultS3CrtAsyncClient extends DelegatingS3AsyncClient imple public static final ExecutionAttribute RESPONSE_FILE_PATH = new ExecutionAttribute<>("responseFilePath"); public static final ExecutionAttribute RESPONSE_FILE_OPTION = new ExecutionAttribute<>("responseFileOption"); + public static final ExecutionAttribute RESPONSE_FILE_DELETE_ON_FAILURE = + new ExecutionAttribute<>("responseFileDeleteOnFailure"); private static final String CRT_CLIENT_CLASSPATH = "software.amazon.awssdk.crt.s3.S3Client"; private final CopyObjectHelper copyObjectHelper; @@ -123,10 +126,12 @@ public CompletableFuture getObject(GetObjectRequest getObject AwsRequestOverrideConfiguration overrideConfig = getObjectRequest.overrideConfiguration() - .map(config -> config.toBuilder().putExecutionAttribute(RESPONSE_FILE_PATH, destinationPath)) - .orElseGet(() -> AwsRequestOverrideConfiguration.builder() - .putExecutionAttribute(RESPONSE_FILE_PATH, - destinationPath)) + .map(AwsRequestOverrideConfiguration::toBuilder) + .orElseGet(AwsRequestOverrideConfiguration::builder) + .putExecutionAttribute(RESPONSE_FILE_PATH, destinationPath) + .putExecutionAttribute(RESPONSE_FILE_OPTION, + S3MetaRequestOptions.ResponseFileOption.CREATE_NEW) + .putExecutionAttribute(RESPONSE_FILE_DELETE_ON_FAILURE, true) .build(); return getObject(getObjectRequest.toBuilder().overrideConfiguration(overrideConfig).build(), responseTransformer); @@ -438,7 +443,9 @@ public void afterMarshalling(Context.AfterMarshalling context, .put(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_PATH, executionAttributes.getAttribute(RESPONSE_FILE_PATH)) .put(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_OPTION, - executionAttributes.getAttribute(RESPONSE_FILE_OPTION)); + executionAttributes.getAttribute(RESPONSE_FILE_OPTION)) + .put(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_DELETE_ON_FAILURE, + executionAttributes.getAttribute(RESPONSE_FILE_DELETE_ON_FAILURE)); SdkRequest request = context.request(); if (request instanceof AwsRequest) { @@ -515,4 +522,10 @@ private static void validateCrtInClassPath() { + "on the classpath.", e); } } + + @Override + public AsyncPresignedUrlExtension presignedUrlExtension() { + // TODO: Implement presigned URL extension support for CRT client + throw new UnsupportedOperationException("Presigned URL extension is not supported for CRT client"); + } } 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 b48d9528800c..0ccc0e0f60cc 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 @@ -24,6 +24,7 @@ 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.RESPONSE_FILE_DELETE_ON_FAILURE; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_OPTION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_PATH; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_NAME; @@ -32,6 +33,7 @@ import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import java.net.URI; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.Path; import java.time.Duration; import java.util.ArrayList; @@ -43,6 +45,7 @@ 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.CrtRuntimeException; import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; import software.amazon.awssdk.crt.http.HttpHeader; @@ -138,7 +141,7 @@ private S3ClientOptions createS3ClientOption() { public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { CompletableFuture executeFuture = new CompletableFuture<>(); URI uri = asyncRequest.request().getUri(); - HttpRequest httpRequest = toCrtRequest(asyncRequest); + HttpRequest httpRequest = toCrtRequest(asyncRequest, executeFuture); SdkHttpExecutionAttributes httpExecutionAttributes = asyncRequest.httpExecutionAttributes(); CompletableFuture s3MetaRequestFuture = new CompletableFuture<>(); @@ -159,6 +162,7 @@ public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { Path responseFilePath = httpExecutionAttributes.getAttribute(RESPONSE_FILE_PATH); S3MetaRequestOptions.ResponseFileOption responseFileOption = httpExecutionAttributes.getAttribute(RESPONSE_FILE_OPTION); + Boolean responseFileDeleteOnFailure = httpExecutionAttributes.getAttribute(RESPONSE_FILE_DELETE_ON_FAILURE); S3CrtResponseHandlerAdapter responseHandler = new S3CrtResponseHandlerAdapter( @@ -186,6 +190,9 @@ public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { if (responseFileOption != null) { requestOptions = requestOptions.withResponseFileOption(responseFileOption); } + if (responseFileDeleteOnFailure != null) { + requestOptions = requestOptions.withResponseFileDeleteOnFailure(responseFileDeleteOnFailure); + } CrtCredentialsProviderAdapter requestCredentialsAdapter = httpExecutionAttributes.getAttribute(S3InternalSdkHttpExecutionAttribute.CRT_CREDENTIALS_PROVIDER_ADAPTER); @@ -204,6 +211,16 @@ public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { if (requestCredentialsAdapter != null) { requestCredentialsAdapter.close(); } + if (isResponseFileAlreadyExistsError(t, responseFilePath)) { + FileAlreadyExistsException fileAlreadyExistsException = + new FileAlreadyExistsException(responseFilePath.toString()); + fileAlreadyExistsException.addSuppressed(t); + // Native initialization failed before creating a meta-request. Complete its placeholder first because + // completing executeFuture invokes the response adapter synchronously, which otherwise waits for a timeout. + s3MetaRequestFuture.complete(null); + executeFuture.completeExceptionally(fileAlreadyExistsException); + return executeFuture; + } throw t; } finally { signingConfig.close(); @@ -216,6 +233,12 @@ public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { return executeFuture; } + private static boolean isResponseFileAlreadyExistsError(Throwable throwable, Path responseFilePath) { + return responseFilePath != null + && throwable instanceof CrtRuntimeException + && "AWS_ERROR_S3_RECV_FILE_ALREADY_EXISTS".equals(((CrtRuntimeException) throwable).errorName); + } + private AwsSigningConfig awsSigningConfig(Region signingRegion, SdkHttpExecutionAttributes httpExecutionAttributes) { CrtCredentialsProviderAdapter requestAdapter = httpExecutionAttributes.getAttribute(S3InternalSdkHttpExecutionAttribute.CRT_CREDENTIALS_PROVIDER_ADAPTER); @@ -261,7 +284,7 @@ private static S3MetaRequestOptions.MetaRequestType requestType(String operation return S3MetaRequestOptions.MetaRequestType.DEFAULT; } - private static HttpRequest toCrtRequest(AsyncExecuteRequest asyncRequest) { + private static HttpRequest toCrtRequest(AsyncExecuteRequest asyncRequest, CompletableFuture executeFuture) { SdkHttpRequest sdkRequest = asyncRequest.request(); Path requestFilePath = asyncRequest.httpExecutionAttributes().getAttribute(OBJECT_FILE_PATH); @@ -280,7 +303,9 @@ private static HttpRequest toCrtRequest(AsyncExecuteRequest asyncRequest) { S3CrtRequestBodyStreamAdapter sdkToCrtRequestPublisher = - requestFilePath == null ? new S3CrtRequestBodyStreamAdapter(asyncRequest.requestContentPublisher()) : null; + requestFilePath == null + ? new S3CrtRequestBodyStreamAdapter(asyncRequest.requestContentPublisher(), executeFuture) + : null; return new HttpRequest(method, encodedPath + encodedQueryString, crtHeaderArray, sdkToCrtRequestPublisher); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapter.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapter.java index e91736ea4901..39a9fe13480c 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapter.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapter.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.services.s3.internal.crt; import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.http.HttpRequestBodyStream; @@ -30,12 +31,14 @@ public final class S3CrtRequestBodyStreamAdapter implements HttpRequestBodyStrea private static final long MINIMUM_BYTES_BUFFERED = 16 * 1024 * 1024L; private final SdkHttpContentPublisher bodyPublisher; private final ByteBufferStoringSubscriber requestBodySubscriber; + private final CompletableFuture executeFuture; private final AtomicBoolean subscribed = new AtomicBoolean(false); - public S3CrtRequestBodyStreamAdapter(SdkHttpContentPublisher bodyPublisher) { + public S3CrtRequestBodyStreamAdapter(SdkHttpContentPublisher bodyPublisher, CompletableFuture executeFuture) { this.bodyPublisher = bodyPublisher; this.requestBodySubscriber = new ByteBufferStoringSubscriber(MINIMUM_BYTES_BUFFERED); + this.executeFuture = executeFuture; } @Override @@ -44,7 +47,14 @@ public boolean sendRequestBody(ByteBuffer outBuffer) { bodyPublisher.subscribe(requestBodySubscriber); } - return requestBodySubscriber.transferTo(outBuffer) == ByteBufferStoringSubscriber.TransferResult.END_OF_STREAM; + try { + return requestBodySubscriber.transferTo(outBuffer) == ByteBufferStoringSubscriber.TransferResult.END_OF_STREAM; + } catch (RuntimeException e) { + // This is a native JNI upcall: an escaping exception is printed to stderr and discarded by CRT (#6715). + // Fail the operation with the original publisher error instead; completing executeFuture cancels the meta request. + executeFuture.completeExceptionally(e); + return false; + } } @Override diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapter.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapter.java index 7c778b173687..20980a132c59 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapter.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapter.java @@ -28,6 +28,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.awscore.exception.AwsErrorDetails; @@ -68,6 +69,10 @@ public final class S3CrtResponseHandlerAdapter implements S3MetaRequestResponseH private volatile boolean responseHandlingInitiated; + // Guards the single terminal responseHandler.onError notification. The first error to complete resultFuture wins; + // the later cancel-derived AWS_ERROR_S3_CANCELED must not re-notify. See #6715. + private final AtomicBoolean responseHandlerNotified = new AtomicBoolean(false); + public S3CrtResponseHandlerAdapter(CompletableFuture executeFuture, SdkAsyncHttpResponseHandler responseHandler, PublisherListener progressListener, @@ -83,8 +88,17 @@ public S3CrtResponseHandlerAdapter(CompletableFuture executeFuture, Duration s3MetaRequestTimeout) { this.resultFuture = executeFuture; this.metaRequestFuture = metaRequestFuture; + this.responseHandler = responseHandler; + this.progressListener = progressListener == null ? new NoOpPublisherListener() : progressListener; + this.s3MetaRequestTimeout = s3MetaRequestTimeout; + // Registered last: the callback reads responseHandler and s3MetaRequestTimeout, so all fields must be assigned + // first in case resultFuture is already complete and the callback runs synchronously here. resultFuture.whenComplete((r, t) -> { + if (t != null) { + notifyResponseHandlerOnError(t); + } + S3MetaRequestWrapper s3MetaRequest = s3MetaRequest(); if (s3MetaRequest == null) { return; @@ -95,10 +109,6 @@ public S3CrtResponseHandlerAdapter(CompletableFuture executeFuture, } s3MetaRequest.close(); }); - - this.responseHandler = responseHandler; - this.progressListener = progressListener == null ? new NoOpPublisherListener() : progressListener; - this.s3MetaRequestTimeout = s3MetaRequestTimeout; } private S3MetaRequestWrapper s3MetaRequest() { @@ -290,11 +300,17 @@ private void onErrorResponseComplete(byte[] errorPayload) { } private void failResponseHandlerAndFuture(Throwable exception) { - runAndLogError(log.logger(), "Exception thrown in SdkAsyncHttpResponseHandler#onError, ignoring", - () -> responseHandler.onError(exception)); + notifyResponseHandlerOnError(exception); resultFuture.completeExceptionally(exception); } + private void notifyResponseHandlerOnError(Throwable exception) { + if (responseHandlerNotified.compareAndSet(false, true)) { + runAndLogError(log.logger(), "Exception thrown in SdkAsyncHttpResponseHandler#onError, ignoring", + () -> responseHandler.onError(exception)); + } + } + private static boolean isServiceError(int responseStatus) { return responseStatus != 0; } 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 c9138539c81c..7ddf40998a48 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 @@ -64,6 +64,9 @@ public final class S3InternalSdkHttpExecutionAttribute extends SdkHttpExecuti public static final S3InternalSdkHttpExecutionAttribute RESPONSE_FILE_OPTION = new S3InternalSdkHttpExecutionAttribute<>(S3MetaRequestOptions.ResponseFileOption.class); + public static final S3InternalSdkHttpExecutionAttribute RESPONSE_FILE_DELETE_ON_FAILURE = + new S3InternalSdkHttpExecutionAttribute<>(Boolean.class); + public static final S3InternalSdkHttpExecutionAttribute CRT_CREDENTIALS_PROVIDER_ADAPTER = new S3InternalSdkHttpExecutionAttribute<>(CrtCredentialsProviderAdapter.class); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservable.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservable.java index 5ddb41219d39..19f732579240 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservable.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservable.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.services.s3.internal.crt; +import java.util.concurrent.CompletableFuture; import java.util.function.Function; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.s3.ResumeToken; @@ -43,7 +44,25 @@ public void subscribe(S3MetaRequestWrapper request) { * Pause the request */ public ResumeToken pause() { - return pause.apply(request); + if (this.request != null) { + return pause.apply(this.request); + } + return null; + } + + /** + * Asynchronously pause the request. Unlike {@link #pause()}, this is supported for GetObject as well as PutObject, and the + * returned future only completes once CRT has finished any in-flight work. + * + * @return a future completed with the resume token, or completed with {@code null} if the request has not been subscribed + * yet or CRT captured no resumable state. + */ + public CompletableFuture pauseAsync() { + S3MetaRequestWrapper metaRequest = this.request; + if (metaRequest != null) { + return metaRequest.pauseAsync(); + } + return CompletableFuture.completedFuture(null); } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestWrapper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestWrapper.java index 72074e1b47a3..5029ad4a2a77 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestWrapper.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestWrapper.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.services.s3.internal.crt; +import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.crt.s3.ResumeToken; import software.amazon.awssdk.crt.s3.S3MetaRequest; @@ -59,6 +60,23 @@ public ResumeToken pause() { return null; } + /** + * Asynchronously pauses the meta request. Unlike {@link #pause()}, this is supported for GetObject as well as PutObject, and + * the returned future only completes once all in-flight work has settled, which for a download to a file means the file has + * been written and closed. + * + * @return a future completed with the resume token, or completed with {@code null} if the meta request has already been + * closed or CRT captured no resumable state. + */ + public CompletableFuture pauseAsync() { + synchronized (lock) { + if (!isClosed) { + return delegate.pauseAsync(); + } + } + return CompletableFuture.completedFuture(null); + } + public void cancel() { synchronized (lock) { if (!isClosed) { 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 7e13f6b97473..5929765d3b29 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 @@ -28,6 +28,7 @@ import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; import software.amazon.awssdk.core.internal.util.HttpChecksumUtils; import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.services.s3.internal.presignedurl.model.PresignedUrlDownloadRequestWrapper; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.utils.Pair; @@ -43,7 +44,8 @@ public class GetObjectInterceptor implements ExecutionInterceptor { @Override public void afterTransmission(Context.AfterTransmission context, ExecutionAttributes executionAttributes) { - if (!(context.request() instanceof GetObjectRequest)) { + if (!(context.request() instanceof GetObjectRequest) + && !(context.request() instanceof PresignedUrlDownloadRequestWrapper)) { return; } ChecksumSpecs resolvedChecksumSpecs = executionAttributes.getAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/StreamingRequestInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/StreamingRequestInterceptor.java index cce812afa646..f78e9fdd23c0 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/StreamingRequestInterceptor.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/StreamingRequestInterceptor.java @@ -29,6 +29,7 @@ import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.UploadPartRequest; import software.amazon.awssdk.utils.AttributeMap; +import software.amazon.awssdk.utils.Logger; /** * Interceptor to add an 'Expect: 100-continue' header to the HTTP Request if it represents a PUT Object or Upload Part @@ -38,6 +39,8 @@ //TODO: This should be generalized for all streaming requests public final class StreamingRequestInterceptor implements ExecutionInterceptor { + private static final Logger log = Logger.loggerFor(StreamingRequestInterceptor.class); + private static final String DECODED_CONTENT_LENGTH_HEADER = "x-amz-decoded-content-length"; private static final String CONTENT_LENGTH_HEADER = "Content-Length"; @@ -58,16 +61,24 @@ private boolean shouldAddExpectContinueHeader(Context.ModifyHttpRequest context, return false; } - // The header is necessary for cross region PUT because sending the body unconditionally to the wrong region where S3 - // will respond with a 3xx and close the connection will cause I/O errors rather than resulting in the client retrying - // based on the region given in the 3xx response. - if (isCrossRegionAccessEnabled(executionAttributes)) { + S3Configuration s3Config = getS3Configuration(executionAttributes); + boolean expectContinueEnabled = s3Config == null || s3Config.expectContinueEnabled(); + boolean crossRegionAccessEnabled = isCrossRegionAccessEnabled(executionAttributes); + + // For cross region PUT, the header defaults to on: sending the body unconditionally to the wrong region where S3 + // responds with a 3xx and closes the connection can surface as an I/O error before the client can retry based on the + // region in the 3xx response. Users who explicitly disable expectContinueEnabled opt out of this. + if (crossRegionAccessEnabled && expectContinueEnabled) { return true; } - S3Configuration s3Config = getS3Configuration(executionAttributes); - - if (s3Config != null && !s3Config.expectContinueEnabled()) { + if (!expectContinueEnabled) { + if (crossRegionAccessEnabled) { + log.debug(() -> "Expect: 100-continue is explicitly disabled while cross region access is enabled. The " + + "header will not be added, so the first call to a bucket whose region " + + "has not yet been resolved may fail with an I/O error instead of being transparently " + + "redirected."); + } return false; } 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 fddcf1cb843b..eddc1cd9e078 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 @@ -207,7 +207,7 @@ public void onNext(CloseableAsyncRequestBody asyncRequestBody) { subscription.request(1); } } - completeMultipartUploadIfFinished(inFlight); + completeMultipartUploadIfFinished(); } }); } @@ -263,12 +263,13 @@ public void onComplete() { log.debug(() -> "Received onComplete()"); isDone = true; if (!isPaused) { - completeMultipartUploadIfFinished(asyncRequestBodyInFlight.get()); + completeMultipartUploadIfFinished(); } } - private void completeMultipartUploadIfFinished(int requestsInFlight) { - if (isDone && requestsInFlight == 0 && completedMultipartInitiated.compareAndSet(false, true)) { + private void completeMultipartUploadIfFinished() { + // All atomics including asyncRequestBodyInFlight MUST be re-read here rather than passed in by the caller. + if (isDone && asyncRequestBodyInFlight.get() == 0 && completedMultipartInitiated.compareAndSet(false, true)) { CompletedPart[] parts; if (existingParts.isEmpty()) { diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartAsyncPresignedUrlExtension.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartAsyncPresignedUrlExtension.java new file mode 100644 index 000000000000..3e4b9ade0033 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartAsyncPresignedUrlExtension.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.services.s3.internal.multipart; + +import java.util.concurrent.CompletableFuture; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.utils.Validate; + +/** + * An {@link AsyncPresignedUrlExtension} that automatically converts presigned URL downloads + * to multipart downloads. + */ +@SdkInternalApi +public class MultipartAsyncPresignedUrlExtension implements AsyncPresignedUrlExtension { + private final PresignedUrlDownloadHelper downloadHelper; + + public MultipartAsyncPresignedUrlExtension( + S3AsyncClient s3AsyncClient, + AsyncPresignedUrlExtension asyncPresignedUrlExtension, + long bufferSizeInBytes, + long partSizeInBytes) { + Validate.paramNotNull(s3AsyncClient, "s3AsyncClient"); + Validate.paramNotNull(asyncPresignedUrlExtension, "asyncPresignedUrlExtension"); + this.downloadHelper = new PresignedUrlDownloadHelper( + s3AsyncClient, + asyncPresignedUrlExtension, + bufferSizeInBytes, + partSizeInBytes); + } + + @Override + public CompletableFuture getObject( + PresignedUrlDownloadRequest presignedUrlDownloadRequest, + AsyncResponseTransformer asyncResponseTransformer) { + Validate.paramNotNull(presignedUrlDownloadRequest, "presignedUrlDownloadRequest"); + Validate.paramNotNull(asyncResponseTransformer, "asyncResponseTransformer"); + return downloadHelper.downloadObject(presignedUrlDownloadRequest, asyncResponseTransformer); + } +} \ No newline at end of file diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtils.java index 807b6a8bbbc0..a9145f1bc1dc 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtils.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtils.java @@ -20,12 +20,23 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.SplittingTransformerConfiguration; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.AsyncResponseTransformer.SplitResult; +import software.amazon.awssdk.services.s3.model.ChecksumType; import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Request; @SdkInternalApi public final class MultipartDownloadUtils { + private static final Pattern CONTENT_RANGE_PATTERN = Pattern.compile("bytes\\s+(\\d+)-(\\d+)/(\\d+)"); + private MultipartDownloadUtils() { } @@ -58,4 +69,117 @@ public static Optional multipartDownloadResumeCo .flatMap(conf -> Optional.ofNullable(conf.executionAttributes().getAttribute(MULTIPART_DOWNLOAD_RESUME_CONTEXT))); } + /** + * This method checks the + * {@link software.amazon.awssdk.services.s3.multipart.S3MultipartExecutionAttribute#MULTIPART_DOWNLOAD_RESUME_CONTEXT} + * execution attributes for a context object and returns it if it finds one. Otherwise, returns an empty Optional. + * + * @param request the request to look for execution attributes + * @return the MultipartDownloadResumeContext if one is found, otherwise an empty Optional. + */ + public static Optional multipartDownloadResumeContext(S3Request request) { + return request + .overrideConfiguration() + .flatMap(conf -> Optional.ofNullable(conf.executionAttributes().getAttribute(MULTIPART_DOWNLOAD_RESUME_CONTEXT))); + } + + /** + * Parses start byte and end byte from a Content-Range header. + * + * @param contentRange the Content-Range header value (e.g., "bytes 0-1023/2048") + * @return array of [startByte, endByte], or null if parsing fails + */ + public static long[] parseContentRange(String contentRange) { + if (contentRange == null) { + return null; + } + Matcher matcher = CONTENT_RANGE_PATTERN.matcher(contentRange); + if (!matcher.matches()) { + return null; + } + return new long[] { + Long.parseLong(matcher.group(1)), + Long.parseLong(matcher.group(2)) + }; + } + + /** + * Parses the total size from a Content-Range header. + * + * @param contentRange the Content-Range header value (e.g., "bytes 0-1023/2048") + * @return the total size, or empty if parsing fails + */ + public static Optional parseContentRangeForTotalSize(String contentRange) { + if (contentRange == null) { + return Optional.empty(); + } + Matcher matcher = CONTENT_RANGE_PATTERN.matcher(contentRange); + if (!matcher.matches()) { + return Optional.empty(); + } + return Optional.of(Long.parseLong(matcher.group(3))); + } + + /** + * Calculates the total number of parts needed to download an object of the given size. + * + * @param contentLength total object size in bytes + * @param partSize size of each part in bytes + * @return the number of parts + */ + public static long calculateTotalParts(long contentLength, long partSize) { + return (contentLength / partSize) + (contentLength % partSize == 0 ? 0 : 1); + + } + + /** + * Rewrites a first-part response to represent the full object. + * + * @param firstPartResponse the GetObjectResponse from the first part request + * @return full-object response with total content-length, full content-range, + * and checksum values nulled if checksum type is COMPOSITE + */ + public static GetObjectResponse toFullObjectResponse(GetObjectResponse firstPartResponse) { + String contentRange = firstPartResponse.contentRange(); + Optional totalOpt = parseContentRangeForTotalSize(contentRange); + if (!totalOpt.isPresent()) { + return firstPartResponse; + } + long totalLength = totalOpt.get(); + String fullRange = "bytes 0-" + (totalLength - 1) + "/" + totalLength; + + GetObjectResponse.Builder builder = firstPartResponse.toBuilder() + .contentLength(totalLength) + .contentRange(fullRange); + + if (firstPartResponse.checksumType() == ChecksumType.COMPOSITE) { + builder.sdkFields().stream() + .filter(f -> f.memberName().startsWith("Checksum") && !"ChecksumType".equals(f.memberName())) + .forEach(f -> f.set(builder, null)); + } + + return builder.build(); + } + + /** + * Splits the given transformer with a response mapper that applies {@link #toFullObjectResponse} + * to the first part's response before it reaches the customer's transformer. + */ + public static SplitResult splitWithResponseRewrite( + AsyncResponseTransformer transformer, + SplittingTransformerConfiguration splitConfig) { + SplittingTransformerConfiguration configWithMapper = + splitConfig.toBuilder() + .responseMapper(MultipartDownloadUtils::mapToFullObjectResponse) + .build(); + return transformer.split(configWithMapper); + } + + private static SdkResponse mapToFullObjectResponse(SdkResponse response) { + if (response instanceof GetObjectResponse) { + return toFullObjectResponse((GetObjectResponse) response); + } + return response; + } + } 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 499f36a6dd1b..6d3aca4970e1 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 @@ -35,6 +35,7 @@ import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.services.s3.model.S3Request; import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; import software.amazon.awssdk.utils.Validate; /** @@ -52,6 +53,8 @@ public final class MultipartS3AsyncClient extends DelegatingS3AsyncClient { private final CopyObjectHelper copyObjectHelper; private final DownloadObjectHelper downloadObjectHelper; private final boolean checksumEnabled; + private final long apiCallBufferSize; + private final long minPartSizeInBytes; private MultipartS3AsyncClient(S3AsyncClient delegate, MultipartConfiguration multipartConfiguration, boolean checksumEnabled) { @@ -63,6 +66,8 @@ private MultipartS3AsyncClient(S3AsyncClient delegate, MultipartConfiguration mu long threshold = resolver.thresholdInBytes(); long apiCallBufferSize = resolver.apiCallBufferSize(); int maxInFlightParts = resolver.maxInFlightParts(); + this.apiCallBufferSize = apiCallBufferSize; + this.minPartSizeInBytes = minPartSizeInBytes; mpuHelper = new UploadObjectHelper(delegate, resolver); copyObjectHelper = new CopyObjectHelper(delegate, minPartSizeInBytes, threshold); downloadObjectHelper = new DownloadObjectHelper(delegate, apiCallBufferSize, maxInFlightParts); @@ -111,4 +116,14 @@ protected CompletableFuture invokeOperat }; return new MultipartS3AsyncClient(clientWithUserAgent, multipartConfiguration, checksumEnabled); } + + @Override + public AsyncPresignedUrlExtension presignedUrlExtension() { + AsyncPresignedUrlExtension delegateExtension = ((S3AsyncClient) delegate()).presignedUrlExtension(); + return new MultipartAsyncPresignedUrlExtension( + (S3AsyncClient) delegate(), + delegateExtension, + apiCallBufferSize, + minPartSizeInBytes); + } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelMultipartDownloaderSubscriber.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelMultipartDownloaderSubscriber.java index a0550d2a10f1..7c895388cd82 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelMultipartDownloaderSubscriber.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelMultipartDownloaderSubscriber.java @@ -198,7 +198,9 @@ public void onSubscribe(Subscription s) { return; } this.subscription = s; - subscription.request(maxInFlightParts); + synchronized (subscriptionLock) { + subscription.request(maxInFlightParts); + } } @Override @@ -352,7 +354,9 @@ private boolean isMultipartObject(GetObjectResponse response) { if (response.partsCount() == null || response.partsCount() == 1) { // Single part object detected, skip multipart and complete everything now log.debug(() -> "Single Part object detected, skipping multipart download"); - subscription.cancel(); + synchronized (subscriptionLock) { + subscription.cancel(); + } resultFuture.complete(response); return false; } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriber.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriber.java new file mode 100644 index 000000000000..3497aa3745e6 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriber.java @@ -0,0 +1,336 @@ +/* + * 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.Map; +import java.util.Optional; +import java.util.Queue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicBoolean; +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.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.Pair; + +/** + * A parallel subscriber for multipart presigned URL downloads that writes parts concurrently. + * Used with {@link software.amazon.awssdk.core.internal.async.FileAsyncResponseTransformerPublisher} + * when {@code parallelSplitSupported() == true} (i.e., toFile() downloads). + * + *

    Unlike {@link PresignedUrlMultipartDownloaderSubscriber} which requests one part at a time, + * this subscriber requests up to {@code maxInFlightParts} concurrently, similar to + * {@link ParallelMultipartDownloaderSubscriber} for regular multipart downloads.

    + */ +@SdkInternalApi +public class ParallelPresignedUrlMultipartDownloaderSubscriber + implements Subscriber> { + + private static final Logger log = Logger.loggerFor(ParallelPresignedUrlMultipartDownloaderSubscriber.class); + + private final S3AsyncClient s3AsyncClient; + private final PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private final long configuredPartSizeInBytes; + /** + * The future returned by the SplitResult, representing the overall download completion. + * Completed exceptionally on error (before cancel) to prevent ByteArraySplittingTransformer + * from assembling invalid data. + */ + private final CompletableFuture resultFuture; + private final int maxInFlightParts; + + private final AtomicLong partNumber = new AtomicLong(0); + private final AtomicLong completedParts = new AtomicLong(0); + private final Semaphore inFlightPermits; + /** + * CAS gate ensuring only the first part failure triggers error handling and cancellation. + */ + private final AtomicBoolean downloadFailed = new AtomicBoolean(false); + private final AtomicBoolean processingPending = new AtomicBoolean(false); + private final Map> inFlightRequests = new ConcurrentHashMap<>(); + private final Queue>> pendingTransformers = + new ConcurrentLinkedQueue<>(); + + private final Object subscriptionLock = new Object(); + private Subscription subscription; + + private volatile Long totalContentLength; + private volatile Long totalParts; + private volatile String eTag; + private volatile GetObjectResponse firstResponse; + + public ParallelPresignedUrlMultipartDownloaderSubscriber( + S3AsyncClient s3AsyncClient, + PresignedUrlDownloadRequest presignedUrlDownloadRequest, + long configuredPartSizeInBytes, + CompletableFuture resultFuture, + int maxInFlightParts) { + this.s3AsyncClient = s3AsyncClient; + this.presignedUrlDownloadRequest = presignedUrlDownloadRequest; + this.configuredPartSizeInBytes = configuredPartSizeInBytes; + this.resultFuture = resultFuture; + this.maxInFlightParts = maxInFlightParts; + this.inFlightPermits = new Semaphore(maxInFlightParts); + } + + @Override + public void onSubscribe(Subscription s) { + if (this.subscription != null) { + s.cancel(); + return; + } + this.subscription = s; + s.request(1); + } + + @Override + public void onNext(AsyncResponseTransformer asyncResponseTransformer) { + if (asyncResponseTransformer == null) { + throw new NullPointerException("onNext must not be called with null asyncResponseTransformer"); + } + + long currentPart = partNumber.getAndIncrement(); + + if (currentPart == 0) { + sendFirstRequest(asyncResponseTransformer); + } else { + if (totalParts != null && currentPart >= totalParts) { + return; + } + if (totalParts != null) { + processRequest(asyncResponseTransformer, currentPart); + } else { + pendingTransformers.offer(Pair.of(currentPart, asyncResponseTransformer)); + } + } + } + + private void sendFirstRequest(AsyncResponseTransformer transformer) { + PresignedUrlDownloadRequest partRequest = createRangedGetRequest(0L); + log.debug(() -> "Sending first range request with range=" + partRequest.range()); + + if (!inFlightPermits.tryAcquire()) { + throw new IllegalStateException("Failed to acquire permit for first request"); + } + + CompletableFuture response = + s3AsyncClient.presignedUrlExtension().getObject(partRequest, transformer); + + inFlightRequests.put(0L, response); + CompletableFutureUtils.forwardExceptionTo(resultFuture, response); + + response.whenComplete((res, error) -> { + inFlightRequests.remove(0L); + inFlightPermits.release(); + + if (error != null) { + if (PresignedUrlDownloadHelper.isRangeNotSatisfiable(error)) { + resultFuture.completeExceptionally( + new PresignedUrlDownloadHelper.EmptyObjectRangeNotSatisfiableException(error)); + synchronized (subscriptionLock) { + subscription.cancel(); + } + } else { + handlePartError(error, 0L); + } + return; + } + + if (downloadFailed.get()) { + return; + } + + completedParts.incrementAndGet(); + + this.eTag = res.eTag(); + this.firstResponse = res; + + String contentRange = res.contentRange(); + if (contentRange == null) { + handlePartError(PresignedUrlDownloadHelper.missingContentRangeHeader(), 0L); + return; + } + + Optional parsedTotal = MultipartDownloadUtils.parseContentRangeForTotalSize(contentRange); + if (!parsedTotal.isPresent()) { + handlePartError(PresignedUrlDownloadHelper.invalidContentRangeHeader(contentRange), 0L); + return; + } + + this.totalContentLength = parsedTotal.get(); + this.totalParts = MultipartDownloadUtils.calculateTotalParts(totalContentLength, configuredPartSizeInBytes); + log.debug(() -> String.format("Total content length: %d, Total parts: %d", totalContentLength, totalParts)); + + Optional validationError = validatePartResponse(res, 0L); + if (validationError.isPresent()) { + handlePartError(validationError.get(), 0L); + return; + } + + if (totalParts <= 1) { + resultFuture.complete(MultipartDownloadUtils.toFullObjectResponse(firstResponse)); + synchronized (subscriptionLock) { + subscription.cancel(); + } + return; + } + + processPendingTransformers(); + + long remainingParts = totalParts - 1; + long toRequest = Math.min(remainingParts, maxInFlightParts); + synchronized (subscriptionLock) { + subscription.request(toRequest); + } + }); + } + + private void processRequest(AsyncResponseTransformer transformer, + long currentPart) { + if (currentPart >= totalParts) { + return; + } + + if (!inFlightPermits.tryAcquire()) { + pendingTransformers.offer(Pair.of(currentPart, transformer)); + return; + } + + sendPartRequest(transformer, currentPart); + processPendingTransformers(); + } + + private void sendPartRequest(AsyncResponseTransformer transformer, + long partIndex) { + if (downloadFailed.get()) { + inFlightPermits.release(); + return; + } + + PresignedUrlDownloadRequest partRequest = createRangedGetRequest(partIndex); + log.debug(() -> "Sending range request for part " + partIndex + " with range=" + partRequest.range()); + + CompletableFuture response = + s3AsyncClient.presignedUrlExtension().getObject(partRequest, transformer); + + inFlightRequests.put(partIndex, response); + CompletableFutureUtils.forwardExceptionTo(resultFuture, response); + + response.whenComplete((res, error) -> { + inFlightRequests.remove(partIndex); + inFlightPermits.release(); + + if (error != null) { + handlePartError(error, partIndex); + return; + } + if (downloadFailed.get()) { + log.debug(() -> "Ignoring late completion for part " + partIndex + ", download already failed"); + return; + } + + Optional validationError = validatePartResponse(res, partIndex); + if (validationError.isPresent()) { + handlePartError(validationError.get(), partIndex); + return; + } + + log.debug(() -> "Completed part: " + partIndex); + long totalComplete = completedParts.incrementAndGet(); + + if (totalComplete == totalParts) { + resultFuture.complete(MultipartDownloadUtils.toFullObjectResponse(firstResponse)); + synchronized (subscriptionLock) { + subscription.cancel(); + } + } else { + processPendingTransformers(); + synchronized (subscriptionLock) { + subscription.request(1); + } + } + }); + } + + private void processPendingTransformers() { + // Re-check after releasing the gate to catch permits that arrived + // while exiting — prevents "missed signal" where no thread drains the queue. + do { + if (!processingPending.compareAndSet(false, true)) { + return; + } + try { + // Drain pending queue while permits are available + while (!pendingTransformers.isEmpty() && inFlightPermits.tryAcquire()) { + Pair> pendingPart = + pendingTransformers.poll(); + if (pendingPart != null && pendingPart.left() < totalParts) { + sendPartRequest(pendingPart.right(), pendingPart.left()); + } else { + inFlightPermits.release(); + } + } + } finally { + processingPending.set(false); + } + } while (!pendingTransformers.isEmpty() && inFlightPermits.availablePermits() > 0); + } + + private Optional validatePartResponse(GetObjectResponse response, long partIndex) { + return PresignedUrlDownloadHelper.validatePartResponse( + response, partIndex, configuredPartSizeInBytes, totalContentLength, totalParts); + } + + private void handlePartError(Throwable error, long partIndex) { + if (downloadFailed.compareAndSet(false, true)) { + log.debug(() -> "Error on part " + partIndex, error); + resultFuture.completeExceptionally(error); + inFlightRequests.values().forEach(future -> future.cancel(true)); + synchronized (subscriptionLock) { + if (subscription != null) { + subscription.cancel(); + } + } + } + } + + private PresignedUrlDownloadRequest createRangedGetRequest(long partIndex) { + return PresignedUrlDownloadHelper.createRangedGetRequest( + presignedUrlDownloadRequest, partIndex, configuredPartSizeInBytes, totalContentLength, eTag); + } + + @Override + public void onError(Throwable t) { + log.debug(() -> "Error in parallel multipart download", t); + resultFuture.completeExceptionally(t); + inFlightRequests.values().forEach(future -> future.cancel(true)); + } + + @Override + public void onComplete() { + // Completion is handled by resultFuture + } +} \ No newline at end of file diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelper.java new file mode 100644 index 000000000000..7b0166a250dc --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelper.java @@ -0,0 +1,255 @@ +/* + * 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 java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SplittingTransformerConfiguration; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.utils.Logger; +import software.amazon.awssdk.utils.Validate; + +@SdkInternalApi +public class PresignedUrlDownloadHelper { + private static final Logger log = Logger.loggerFor(PresignedUrlDownloadHelper.class); + private static final int DEFAULT_MAX_IN_FLIGHT_PARTS = 10; + + private final S3AsyncClient s3AsyncClient; + private final AsyncPresignedUrlExtension asyncPresignedUrlExtension; + private final long bufferSizeInBytes; + private final long configuredPartSizeInBytes; + + public PresignedUrlDownloadHelper(S3AsyncClient s3AsyncClient, + AsyncPresignedUrlExtension asyncPresignedUrlExtension, + long bufferSizeInBytes, + long configuredPartSizeInBytes) { + this.s3AsyncClient = Validate.paramNotNull(s3AsyncClient, "s3AsyncClient"); + this.asyncPresignedUrlExtension = Validate.paramNotNull(asyncPresignedUrlExtension, "asyncPresignedUrlExtension"); + this.bufferSizeInBytes = Validate.isPositive(bufferSizeInBytes, "bufferSizeInBytes"); + this.configuredPartSizeInBytes = Validate.isPositive(configuredPartSizeInBytes, "configuredPartSizeInBytes"); + } + + public CompletableFuture downloadObject( + PresignedUrlDownloadRequest presignedRequest, + AsyncResponseTransformer asyncResponseTransformer) { + + Validate.paramNotNull(presignedRequest, "presignedRequest"); + Validate.paramNotNull(asyncResponseTransformer, "asyncResponseTransformer"); + + if (presignedRequest.range() != null) { + log.debug(() -> "Using single part download because presigned URL request range is included in the request. range = " + + presignedRequest.range()); + return asyncPresignedUrlExtension.getObject(presignedRequest, asyncResponseTransformer); + } + + CompletableFuture resultFuture = new CompletableFuture<>(); + doMultipartDownload(presignedRequest, asyncResponseTransformer) + .whenComplete((result, error) -> { + Throwable cause = error instanceof CompletionException ? error.getCause() : error; + // Parallel path wraps it as EmptyObjectRangeNotSatisfiableException; + // serial path (toBytes, custom transformers) surfaces raw S3Exception. + if (cause instanceof EmptyObjectRangeNotSatisfiableException + || isRangeNotSatisfiable(cause)) { + log.debug(() -> "Received 416 on first request, falling back to non-range GET for empty object"); + asyncPresignedUrlExtension.getObject(presignedRequest, asyncResponseTransformer) + .whenComplete((r, e) -> { + if (e != null) { + resultFuture.completeExceptionally(e); + } else { + resultFuture.complete(r); + } + }); + } else if (error != null) { + resultFuture.completeExceptionally(error); + } else { + resultFuture.complete(result); + } + }); + return resultFuture; + } + + private CompletableFuture doMultipartDownload( + PresignedUrlDownloadRequest presignedRequest, + AsyncResponseTransformer asyncResponseTransformer) { + + SplittingTransformerConfiguration splittingConfig = SplittingTransformerConfiguration.builder() + .bufferSizeInBytes(bufferSizeInBytes) + .build(); + + AsyncResponseTransformer.SplitResult split = + MultipartDownloadUtils.splitWithResponseRewrite(asyncResponseTransformer, splittingConfig); + + if (split.parallelSplitSupported()) { + return downloadPartsInParallel(presignedRequest, split); + } + return downloadPartsSerially(presignedRequest, split); + } + + private CompletableFuture downloadPartsInParallel( + PresignedUrlDownloadRequest presignedRequest, + AsyncResponseTransformer.SplitResult split) { + log.debug(() -> "Using parallel multipart download for presigned URL"); + ParallelPresignedUrlMultipartDownloaderSubscriber subscriber = + new ParallelPresignedUrlMultipartDownloaderSubscriber( + s3AsyncClient, + presignedRequest, + configuredPartSizeInBytes, + (CompletableFuture) split.resultFuture(), + DEFAULT_MAX_IN_FLIGHT_PARTS); + split.publisher().subscribe(subscriber); + return split.resultFuture(); + } + + private CompletableFuture downloadPartsSerially( + PresignedUrlDownloadRequest presignedRequest, + AsyncResponseTransformer.SplitResult split) { + log.debug(() -> "Using serial multipart download for presigned URL"); + PresignedUrlMultipartDownloaderSubscriber subscriber = + new PresignedUrlMultipartDownloaderSubscriber( + s3AsyncClient, + presignedRequest, + configuredPartSizeInBytes, + split.resultFuture()); + split.publisher().subscribe(subscriber); + return split.resultFuture(); + } + + static SdkClientException invalidContentRangeHeader(String contentRange) { + return SdkClientException.create("Invalid Content-Range header: " + contentRange); + } + + static SdkClientException missingContentRangeHeader() { + return SdkClientException.create("No Content-Range header in response"); + } + + static SdkClientException invalidContentLength() { + return SdkClientException.create("Invalid or missing Content-Length in response"); + } + + /** + * Validates a part response for data integrity. Checks that Content-Range and Content-Length + * match the expected values based on part index, part size, and total object size. + * + * @param response the GetObject response to validate + * @param partIndex zero-based index of this part + * @param partSizeInBytes configured part size + * @param totalContentLength total object size (from Content-Range), or null if not yet known + * @param totalParts total number of parts, or null if not yet known + * @return empty if valid, or an SdkClientException describing the mismatch + */ + static Optional validatePartResponse(GetObjectResponse response, + long partIndex, + long partSizeInBytes, + Long totalContentLength, + Long totalParts) { + String contentRange = response.contentRange(); + if (contentRange == null) { + return Optional.of(missingContentRangeHeader()); + } + + Long contentLength = response.contentLength(); + if (contentLength == null || contentLength < 0) { + return Optional.of(invalidContentLength()); + } + + long expectedStartByte = partIndex * partSizeInBytes; + long[] parsedRange = MultipartDownloadUtils.parseContentRange(contentRange); + if (parsedRange == null) { + return Optional.of(invalidContentRangeHeader(contentRange)); + } + long actualStartByte = parsedRange[0]; + long actualEndByte = parsedRange[1]; + if (actualStartByte != expectedStartByte) { + return Optional.of(SdkClientException.create( + String.format("Content-Range mismatch for part %d. Expected start byte: %d, but got: bytes %d-%d", + partIndex, expectedStartByte, actualStartByte, actualEndByte))); + } + if (totalContentLength != null) { + long expectedEndByte = Math.min(expectedStartByte + partSizeInBytes - 1, totalContentLength - 1); + if (actualEndByte != expectedEndByte) { + return Optional.of(SdkClientException.create( + String.format("Content-Range mismatch for part %d. Expected: bytes %d-%d, but got: bytes %d-%d", + partIndex, expectedStartByte, expectedEndByte, actualStartByte, actualEndByte))); + } + } + + if (totalContentLength != null && totalParts != null) { + long expectedPartSize = (partIndex == totalParts - 1) + ? totalContentLength - (partIndex * partSizeInBytes) + : partSizeInBytes; + if (!contentLength.equals(expectedPartSize)) { + return Optional.of(SdkClientException.create( + String.format("Part content length validation failed for part %d. Expected: %d, but got: %d", + partIndex, expectedPartSize, contentLength))); + } + } + return Optional.empty(); + } + + /** + * Creates a range-based GET request for a specific part of a presigned URL download. + * + * @param originalRequest the original presigned URL request + * @param partIndex zero-based index of this part + * @param partSizeInBytes configured part size + * @param totalContentLength total object size, or null if not yet known (first part) + * @param eTag ETag from first response, used for If-Match on parts 1+ + * @return a new PresignedUrlDownloadRequest with the appropriate Range and If-Match headers + */ + static PresignedUrlDownloadRequest createRangedGetRequest(PresignedUrlDownloadRequest originalRequest, + long partIndex, + long partSizeInBytes, + Long totalContentLength, + String eTag) { + long startByte = partIndex * partSizeInBytes; + long endByte = totalContentLength != null + ? Math.min(startByte + partSizeInBytes - 1, totalContentLength - 1) + : startByte + partSizeInBytes - 1; + PresignedUrlDownloadRequest.Builder builder = originalRequest.toBuilder() + .range("bytes=" + startByte + "-" + endByte); + if (partIndex > 0 && eTag != null) { + builder.ifMatch(eTag); + } + return builder.build(); + } + + /** + * Returns true if the error is a 416 Range Not Satisfiable response from S3. + * Used by subscribers to detect empty object responses on the first range request. + */ + static boolean isRangeNotSatisfiable(Throwable error) { + Throwable cause = error instanceof CompletionException ? error.getCause() : error; + return cause instanceof S3Exception && ((S3Exception) cause).statusCode() == 416; + } + + /** + * Marker exception wrapping a 416 on the first range request, signaling an empty object. + * Used to distinguish from 416 errors on subsequent requests which should propagate as failures. + */ + static class EmptyObjectRangeNotSatisfiableException extends RuntimeException { + EmptyObjectRangeNotSatisfiableException(Throwable cause) { + super("Object is empty (416 on first range request)", cause); + } + } +} \ No newline at end of file diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriber.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriber.java new file mode 100644 index 000000000000..86c4c76308ca --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriber.java @@ -0,0 +1,254 @@ +/* + * 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 java.util.Queue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicLong; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.ThreadSafe; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.utils.Logger; + +/** + * A subscriber implementation that will download all individual parts for a multipart presigned URL download request. + * It receives individual {@link AsyncResponseTransformer} instances which will be used to perform the individual + * range-based part requests using presigned URLs. This is a 'one-shot' class, it should NOT be reused + * for more than one multipart download. + * + *

    Unlike the standard {@link MultipartDownloaderSubscriber} which uses S3's native multipart API with part numbers, + * this subscriber uses HTTP range requests against presigned URLs to achieve multipart download functionality. + *

    This implementation is thread-safe and handles concurrent part downloads while maintaining proper + * ordering and validation of responses.

    + */ +@ThreadSafe +@SdkInternalApi +public class PresignedUrlMultipartDownloaderSubscriber + implements Subscriber> { + + private static final Logger log = Logger.loggerFor(PresignedUrlMultipartDownloaderSubscriber.class); + + private final S3AsyncClient s3AsyncClient; + private final PresignedUrlDownloadRequest presignedUrlDownloadRequest; + private final Long configuredPartSizeInBytes; + + /** + * Internal lifecycle future for this subscriber. Completed when all parts are downloaded + * or when an error occurs. + */ + private final CompletableFuture future; + + /** + * The split transformer's completion future (from {@code SplitResult.resultFuture()}). + * Completing this signals the download result to the caller. Must be completed exceptionally + * before cancelling the subscription to prevent ByteArraySplittingTransformer from assembling + * invalid data. + */ + private final CompletableFuture resultFuture; + private final Object lock = new Object(); + private final AtomicLong nextPartIndex; + private final AtomicLong requestsSent; + + /** + * Store the GetObject futures so we can cancel them if onError() is invoked. + */ + private final Queue> getObjectFutures = new ConcurrentLinkedQueue<>(); + + private volatile Long totalContentLength; + private volatile Long totalParts; + private volatile String eTag; + private Subscription subscription; + + public PresignedUrlMultipartDownloaderSubscriber( + S3AsyncClient s3AsyncClient, + PresignedUrlDownloadRequest presignedUrlDownloadRequest, + long configuredPartSizeInBytes, + CompletableFuture resultFuture) { + this.s3AsyncClient = s3AsyncClient; + this.presignedUrlDownloadRequest = presignedUrlDownloadRequest; + this.configuredPartSizeInBytes = configuredPartSizeInBytes; + this.nextPartIndex = new AtomicLong(0); + this.requestsSent = new AtomicLong(0); + this.future = new CompletableFuture<>(); + this.resultFuture = resultFuture; + } + + @Override + public void onSubscribe(Subscription s) { + if (subscription != null) { + s.cancel(); + return; + } + this.subscription = s; + s.request(1); + } + + @Override + public void onNext(AsyncResponseTransformer asyncResponseTransformer) { + if (asyncResponseTransformer == null) { + throw new NullPointerException("onNext must not be called with null asyncResponseTransformer"); + } + + long currentPartIndex; + synchronized (lock) { + currentPartIndex = nextPartIndex.get(); + if (totalParts != null && currentPartIndex >= totalParts) { + log.debug(() -> String.format("Completing multipart download after a total of %d parts downloaded.", totalParts)); + subscription.cancel(); + return; + } + nextPartIndex.incrementAndGet(); + } + makeRangeRequest(currentPartIndex, asyncResponseTransformer); + } + + private void makeRangeRequest(long partIndex, + AsyncResponseTransformer asyncResponseTransformer) { + PresignedUrlDownloadRequest partRequest = createRangedGetRequest(partIndex); + log.debug(() -> "Sending range request for part " + partIndex + " with range=" + partRequest.range()); + + requestsSent.incrementAndGet(); + CompletableFuture responseFuture = s3AsyncClient.presignedUrlExtension() + .getObject(partRequest, asyncResponseTransformer); + getObjectFutures.add(responseFuture); + responseFuture.whenComplete((response, error) -> { + if (error != null) { + if (partIndex == 0 && PresignedUrlDownloadHelper.isRangeNotSatisfiable(error)) { + log.debug(() -> "Received 416 on first range request, object is empty"); + resultFuture.completeExceptionally( + new PresignedUrlDownloadHelper.EmptyObjectRangeNotSatisfiableException(error)); + synchronized (lock) { + subscription.cancel(); + } + } else { + handleError(error); + } + return; + } + if (validatePart(response, partIndex, asyncResponseTransformer)) { + requestMoreIfNeeded(nextPartIndex.get()); + } + }); + } + + private boolean validatePart(GetObjectResponse response, long partIndex, + AsyncResponseTransformer asyncResponseTransformer) { + long dispatched = nextPartIndex.get(); + log.debug(() -> String.format("Dispatched %d parts so far", dispatched)); + + String responseETag = response.eTag(); + String responseContentRange = response.contentRange(); + if (eTag == null) { + this.eTag = responseETag; + log.debug(() -> String.format("Multipart object ETag: %s", this.eTag)); + } + + if (totalContentLength == null && responseContentRange != null) { + Optional parsedContentLength = MultipartDownloadUtils.parseContentRangeForTotalSize(responseContentRange); + if (!parsedContentLength.isPresent()) { + SdkClientException error = PresignedUrlDownloadHelper.invalidContentRangeHeader(responseContentRange); + log.debug(() -> "Failed to parse content range", error); + asyncResponseTransformer.exceptionOccurred(error); + handleError(error); + return false; + } + + this.totalContentLength = parsedContentLength.get(); + this.totalParts = MultipartDownloadUtils.calculateTotalParts(totalContentLength, configuredPartSizeInBytes); + log.debug(() -> String.format("Total content length: %d, Total parts: %d", totalContentLength, totalParts)); + } + + Optional validationError = validateResponse(response, partIndex); + if (validationError.isPresent()) { + log.debug(() -> "Response validation failed", validationError.get()); + asyncResponseTransformer.exceptionOccurred(validationError.get()); + handleError(validationError.get()); + return false; + } + + return true; + } + + private void requestMoreIfNeeded(long dispatched) { + synchronized (lock) { + if (hasMoreParts(dispatched)) { + subscription.request(1); + } else { + if (totalParts != null && requestsSent.get() != totalParts) { + handleError(new IllegalStateException( + "Request count mismatch. Expected: " + totalParts + ", sent: " + requestsSent.get())); + return; + } + log.debug(() -> String.format("Completing multipart download after a total of %d parts downloaded.", totalParts)); + subscription.cancel(); + } + } + } + + private Optional validateResponse(GetObjectResponse response, long partIndex) { + return PresignedUrlDownloadHelper.validatePartResponse( + response, partIndex, configuredPartSizeInBytes, totalContentLength, totalParts); + } + + private boolean hasMoreParts(long dispatched) { + return totalParts != null && dispatched < totalParts; + } + + private PresignedUrlDownloadRequest createRangedGetRequest(long partIndex) { + return PresignedUrlDownloadHelper.createRangedGetRequest( + presignedUrlDownloadRequest, partIndex, configuredPartSizeInBytes, totalContentLength, eTag); + } + + private void handleError(Throwable t) { + future.completeExceptionally(t); + if (resultFuture != null) { + resultFuture.completeExceptionally(t); + } + synchronized (lock) { + if (subscription != null) { + subscription.cancel(); + } + } + } + + @Override + public void onError(Throwable t) { + log.debug(() -> "Error in multipart download", t); + CompletableFuture partFuture; + while ((partFuture = getObjectFutures.poll()) != null) { + partFuture.cancel(true); + } + future.completeExceptionally(t); + if (resultFuture != null) { + resultFuture.completeExceptionally(t); + } + } + + @Override + public void onComplete() { + future.complete(null); + } + +} \ 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 a7b3ea56126f..64a09d278ea9 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 @@ -96,6 +96,9 @@ public final class SdkPojoConversionUtils { "ObjectLockMode", "ObjectLockRetainUntilDate", "ObjectLockLegalHoldStatus", + "ObjectLockEventHold", + "ObjectLockEventHoldDurationDays", + "ObjectLockEventHoldDurationYears", "ExpectedBucketOwner", "ChecksumXXHASH128", "ChecksumSHA512", @@ -148,6 +151,9 @@ public final class SdkPojoConversionUtils { "ObjectLockMode", "ObjectLockRetainUntilDate", "ObjectLockLegalHoldStatus", + "ObjectLockEventHold", + "ObjectLockEventHoldDurationDays", + "ObjectLockEventHoldDurationYears", "ExpectedBucketOwner", "ExpectedSourceBucketOwner", "ChecksumXXHASH128", diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriber.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriber.java index f264307f1984..40ed3d7ecabb 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriber.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriber.java @@ -232,7 +232,7 @@ private void sendUploadPartRequest(String uploadId, subscription.request(1); } } - completeMultipartUploadIfFinish(inFlight); + completeMultipartUploadIfFinish(); } }); } @@ -266,12 +266,13 @@ public void onComplete() { multipartUploadHelper.uploadInOneChunk(putObjectRequest, entireRequestBody, returnFuture); } else { isDone = true; - completeMultipartUploadIfFinish(asyncRequestBodyInFlight.get()); + completeMultipartUploadIfFinish(); } } - private void completeMultipartUploadIfFinish(int requestsInFlight) { - if (isDone && requestsInFlight == 0 && completedMultipartInitiated.compareAndSet(false, true)) { + private void completeMultipartUploadIfFinish() { + // All atomics including asyncRequestBodyInFlight MUST be re-read here rather than passed in by the caller. + if (isDone && asyncRequestBodyInFlight.get() == 0 && completedMultipartInitiated.compareAndSet(false, true)) { CompletedPart[] parts = completedParts.stream() .sorted(Comparator.comparingInt(CompletedPart::partNumber)) .toArray(CompletedPart[]::new); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java new file mode 100644 index 000000000000..1fcefcd98b9a --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtension.java @@ -0,0 +1,181 @@ +/* + * 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.presignedurl; + +import static software.amazon.awssdk.core.client.config.SdkClientOption.SIGNER_OVERRIDDEN; +import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.exception.AwsServiceException; +import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.AsyncResponseTransformerUtils; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.AsyncClientHandler; +import software.amazon.awssdk.core.client.handler.ClientExecutionParams; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.core.signer.NoOpSigner; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.metrics.NoOpMetricCollector; +import software.amazon.awssdk.protocols.xml.AwsS3ProtocolFactory; +import software.amazon.awssdk.protocols.xml.XmlOperationMetadata; +import software.amazon.awssdk.services.s3.internal.presignedurl.model.PresignedUrlDownloadRequestWrapper; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.InvalidObjectStateException; +import software.amazon.awssdk.services.s3.model.NoSuchKeyException; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.utils.CompletableFutureUtils; +import software.amazon.awssdk.utils.Pair; + +/** + * Default implementation of {@link AsyncPresignedUrlExtension} for executing S3 operations asynchronously using presigned URLs. + */ +@SdkInternalApi +public final class DefaultAsyncPresignedUrlExtension implements AsyncPresignedUrlExtension { + private static final Logger log = LoggerFactory.getLogger(DefaultAsyncPresignedUrlExtension.class); + + /** + * Checksum configuration matching the codegen-produced GetObject operation. + * Enables the HttpChecksumValidationInterceptor to validate response checksums. + */ + private static final HttpChecksum RESPONSE_CHECKSUM_CONFIG = + HttpChecksum.builder() + .requestValidationMode("ENABLED") + .responseAlgorithmsV2( + DefaultChecksumAlgorithm.values() + .toArray(new ChecksumAlgorithm[0])) + .build(); + + private final AsyncClientHandler clientHandler; + private final AwsS3ProtocolFactory protocolFactory; + private final SdkClientConfiguration clientConfiguration; + private final List metricPublishers; + private final AwsProtocolMetadata protocolMetadata; + + public DefaultAsyncPresignedUrlExtension(AsyncClientHandler clientHandler, + AwsS3ProtocolFactory protocolFactory, + SdkClientConfiguration clientConfiguration, + AwsProtocolMetadata protocolMetadata) { + this.clientHandler = clientHandler; + this.protocolFactory = protocolFactory; + this.protocolMetadata = protocolMetadata; + this.clientConfiguration = updateSdkClientConfiguration(clientConfiguration); + this.metricPublishers = Optional.ofNullable( + this.clientConfiguration.option(SdkClientOption.METRIC_PUBLISHERS)) + .orElse(Collections.emptyList()); + } + + @Override + public CompletableFuture getObject( + PresignedUrlDownloadRequest presignedUrlDownloadRequest, + AsyncResponseTransformer asyncResponseTransformer) + throws NoSuchKeyException, InvalidObjectStateException, + AwsServiceException, SdkClientException, S3Exception { + + PresignedUrlDownloadRequestWrapper internalRequest = PresignedUrlDownloadRequestWrapper.builder() + .url(presignedUrlDownloadRequest.presignedUrl()) + .range(presignedUrlDownloadRequest.range()) + .ifMatch(presignedUrlDownloadRequest.ifMatch()) + .build(); + + MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? + NoOpMetricCollector.create() : MetricCollector.create("ApiCall"); + + try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "S3"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PresignedUrlDownload"); + + Pair, CompletableFuture> pair = + AsyncResponseTransformerUtils.wrapWithEndOfStreamFuture(asyncResponseTransformer); + AsyncResponseTransformer finalAsyncResponseTransformer = pair.left(); + asyncResponseTransformer = finalAsyncResponseTransformer; + CompletableFuture endOfStreamFuture = pair.right(); + + HttpResponseHandler responseHandler = protocolFactory.createResponseHandler( + GetObjectResponse::builder, new XmlOperationMetadata().withHasStreamingSuccessResponse(true)); + + HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); + + CompletableFuture executeFuture = clientHandler.execute( + new ClientExecutionParams() + .withOperationName("PresignedUrlDownload") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(internalRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.SKIP_ENDPOINT_RESOLUTION, true) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM, + checksumConfigForUrl(presignedUrlDownloadRequest.presignedUrl())) + .withMarshaller(new PresignedUrlDownloadRequestMarshaller(protocolFactory)), + asyncResponseTransformer); + + CompletableFuture whenCompleteFuture = executeFuture.whenComplete((r, e) -> { + if (e != null) { + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + } + endOfStreamFuture.whenComplete((r2, e2) -> { + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + }); + }); + return CompletableFutureUtils.forwardExceptionTo(whenCompleteFuture, executeFuture); + } catch (Throwable t) { + AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; + runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); + return CompletableFutureUtils.failedFuture(t); + } + } + + private SdkClientConfiguration updateSdkClientConfiguration(SdkClientConfiguration clientConfiguration) { + SdkClientConfiguration.Builder configBuilder = clientConfiguration.toBuilder(); + configBuilder.option(SdkAdvancedClientOption.SIGNER, new NoOpSigner()); + configBuilder.option(SIGNER_OVERRIDDEN, true); + return configBuilder.build(); + } + + /** + * Returns the checksum validation config if the presigned URL was signed with checksum mode, + * or null otherwise. + */ + private static HttpChecksum checksumConfigForUrl(java.net.URL presignedUrl) { + if (PresignedUrlDownloadRequestMarshaller.hasChecksumModeInSignedHeaders(presignedUrl.getQuery())) { + return RESPONSE_CHECKSUM_CONFIG; + } + return null; + } + +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshaller.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshaller.java new file mode 100644 index 000000000000..a15d6cb29216 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshaller.java @@ -0,0 +1,143 @@ +/* + * 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.presignedurl; + +import java.net.URI; +import java.net.URISyntaxException; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.runtime.transform.Marshaller; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.xml.AwsXmlProtocolFactory; +import software.amazon.awssdk.services.s3.internal.presignedurl.model.PresignedUrlDownloadRequestWrapper; +import software.amazon.awssdk.utils.Validate; + +/** + * {@link PresignedUrlDownloadRequestWrapper} Marshaller + * + *

    + * Marshalls presigned URL requests by using the complete URL directly and adding optional Range headers. + * Unlike regular S3 marshalers, this preserves all embedded authentication parameters in the presigned URL. + *

    + */ +@SdkInternalApi +public class PresignedUrlDownloadRequestMarshaller implements Marshaller { + private static final OperationInfo SDK_OPERATION_BINDING = OperationInfo.builder() + .requestUri("").httpMethod(SdkHttpMethod.GET).hasExplicitPayloadMember(false).hasPayloadMembers(false) + .putAdditionalMetadata(AwsXmlProtocolFactory.ROOT_MARSHALL_LOCATION_ATTRIBUTE, null) + .putAdditionalMetadata(AwsXmlProtocolFactory.XML_NAMESPACE_ATTRIBUTE, null).build(); + + private final AwsXmlProtocolFactory protocolFactory; + + public PresignedUrlDownloadRequestMarshaller(AwsXmlProtocolFactory protocolFactory) { + this.protocolFactory = protocolFactory; + } + + /** + * Marshalls the presigned URL request into an HTTP GET request. + * + * @param presignedUrlDownloadRequestWrapper the request to marshall + * @return HTTP request ready for execution + * @throws SdkClientException if URL conversion fails + */ + @Override + public SdkHttpFullRequest marshall(PresignedUrlDownloadRequestWrapper presignedUrlDownloadRequestWrapper) { + Validate.paramNotNull(presignedUrlDownloadRequestWrapper, "presignedUrlDownloadRequestWrapper"); + try { + ProtocolMarshaller protocolMarshaller = protocolFactory + .createProtocolMarshaller(SDK_OPERATION_BINDING); + URI presignedUri = presignedUrlDownloadRequestWrapper.url().toURI(); + + SdkHttpFullRequest.Builder requestBuilder = protocolMarshaller + .marshall(presignedUrlDownloadRequestWrapper) + .toBuilder() + .uri(presignedUri); + + addChecksumModeHeaderIfSignedInUrl(requestBuilder, presignedUri); + + return requestBuilder.build(); + } catch (Exception e) { + String redactedUrl = PresignedUrlRedactionUtils.redactQueryString(presignedUrlDownloadRequestWrapper.url()); + throw SdkClientException.builder() + .message("Unable to marshall pre-signed URL Request for " + redactedUrl + ": " + failureDescription(e)) + .cause(redactedCause(e, redactedUrl)) + .build(); + } + } + + /** + * Describes a marshalling failure without echoing the presigned URL: {@link URISyntaxException#getMessage()} appends + * the URL it was given, query string included, so only the reason and the index are used. + */ + private static String failureDescription(Exception e) { + if (e instanceof URISyntaxException) { + URISyntaxException syntaxException = (URISyntaxException) e; + int index = syntaxException.getIndex(); + return index < 0 ? syntaxException.getReason() + : syntaxException.getReason() + " at index " + index; + } + return e.getClass().getName(); + } + + /** + * Rebuilds the failure around the redacted URL, because the chained cause is read back by + * {@code getCause().getMessage()} and printed by every stack trace that renders the exception. A + * {@link URISyntaxException} keeps its type, reason and index; any other failure is named by its class only, since its + * message is not known to be free of the URL. Both carry the frames of the original failure. + */ + private static Throwable redactedCause(Exception e, String redactedUrl) { + String url = redactedUrl == null ? "null" : redactedUrl; + Throwable redacted; + if (e instanceof URISyntaxException && ((URISyntaxException) e).getReason() != null) { + URISyntaxException syntaxException = (URISyntaxException) e; + redacted = new URISyntaxException(url, syntaxException.getReason(), syntaxException.getIndex()); + } else { + redacted = SdkClientException.builder() + .message(e.getClass().getName() + " for " + url) + .build(); + } + redacted.setStackTrace(e.getStackTrace()); + return redacted; + } + + /** + * If the presigned URL's X-Amz-SignedHeaders contains "x-amz-checksum-mode", automatically add + * the header with value "ENABLED" so S3 returns checksum headers in the response. + */ + private void addChecksumModeHeaderIfSignedInUrl(SdkHttpFullRequest.Builder requestBuilder, URI uri) { + if (hasChecksumModeInSignedHeaders(uri.getQuery())) { + requestBuilder.putHeader("x-amz-checksum-mode", "ENABLED"); + } + } + + /** + * Returns true if the decoded query string's X-Amz-SignedHeaders parameter contains "x-amz-checksum-mode". + */ + static boolean hasChecksumModeInSignedHeaders(String query) { + if (query == null) { + return false; + } + for (String param : query.split("&")) { + if (param.startsWith("X-Amz-SignedHeaders=")) { + return param.substring("X-Amz-SignedHeaders=".length()).contains("x-amz-checksum-mode"); + } + } + return false; + } +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlRedactionUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlRedactionUtils.java new file mode 100644 index 000000000000..459ac9841835 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlRedactionUtils.java @@ -0,0 +1,61 @@ +/* + * 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.presignedurl; + +import java.net.URL; +import software.amazon.awssdk.annotations.SdkInternalApi; + +/** + * Renders a presigned URL for logs and exception messages. + */ +@SdkInternalApi +public final class PresignedUrlRedactionUtils { + private static final String SENSITIVE_DATA_REDACTED = "*** Sensitive Data Redacted ***"; + + private PresignedUrlRedactionUtils() { + } + + /** + * Renders only the non-secret components of a presigned URL: protocol, host, port and path. The query string of a + * presigned URL carries the signature, the credential scope and (for session credentials) the security token, so it + * is replaced with a placeholder. The user-info and fragment components are dropped. + * + * @param url the presigned URL, may be null + * @return the rendered URL, or null if {@code url} is null + */ + public static String redactQueryString(URL url) { + if (url == null) { + return null; + } + StringBuilder result = new StringBuilder(); + if (url.getProtocol() != null) { + result.append(url.getProtocol()).append("://"); + } + if (url.getHost() != null) { + result.append(url.getHost()); + } + if (url.getPort() != -1) { + result.append(':').append(url.getPort()); + } + if (url.getPath() != null) { + result.append(url.getPath()); + } + if (url.getQuery() != null) { + result.append('?').append(SENSITIVE_DATA_REDACTED); + } + return result.toString(); + } +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapper.java new file mode 100644 index 000000000000..5d5569523967 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapper.java @@ -0,0 +1,175 @@ +/* + * 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.presignedurl.model; + +import java.net.URL; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.protocol.MarshallLocation; +import software.amazon.awssdk.core.protocol.MarshallingType; +import software.amazon.awssdk.core.traits.LocationTrait; +import software.amazon.awssdk.services.s3.model.S3Request; + +/** + * Internal request object for presigned URL GetObject operations. + *

    + * This class is used internally by the AWS SDK to process presigned URL requests for S3 GetObject operations. It contains minimal + * SdkField definitions needed for custom marshalling and is not intended for direct use by SDK users. + *

    + * Note: This is an internal implementation class and should not be used + * directly. Use {@code PresignedUrlDownloadRequest} for public API interactions. + */ +@SdkInternalApi +public final class PresignedUrlDownloadRequestWrapper extends S3Request { + private static final SdkField RANGE_FIELD = SdkField + .builder(MarshallingType.STRING) + .memberName("Range") + .getter(getter(PresignedUrlDownloadRequestWrapper::range)) + .traits(LocationTrait.builder().location(MarshallLocation.HEADER).locationName("Range") + .unmarshallLocationName("Range").build()).build(); + + private static final SdkField IF_MATCH_FIELD = SdkField + .builder(MarshallingType.STRING) + .memberName("IfMatch") + .getter(getter(PresignedUrlDownloadRequestWrapper::ifMatch)) + .traits(LocationTrait.builder().location(MarshallLocation.HEADER).locationName("If-Match") + .unmarshallLocationName("If-Match").build()).build(); + + private static final List> SDK_FIELDS = Collections.unmodifiableList( + Arrays.asList(RANGE_FIELD, IF_MATCH_FIELD)); + + private static final Map> SDK_NAME_TO_FIELD = memberNameToFieldInitializer(); + + private final URL url; + private final String range; + private final String ifMatch; + + private PresignedUrlDownloadRequestWrapper(Builder builder) { + super(builder); + this.url = builder.url; + this.range = builder.range; + this.ifMatch = builder.ifMatch; + } + + public URL url() { + return url; + } + + public String range() { + return range; + } + + public String ifMatch() { + return ifMatch; + } + + @Override + public List> sdkFields() { + return SDK_FIELDS; + } + + @Override + public Map> sdkFieldNameToField() { + return SDK_NAME_TO_FIELD; + } + + private static Function getter(Function g) { + return obj -> g.apply((PresignedUrlDownloadRequestWrapper) obj); + } + + private static Map> memberNameToFieldInitializer() { + Map> map = new HashMap<>(); + map.put("Range", RANGE_FIELD); + map.put("IfMatch", IF_MATCH_FIELD); + return Collections.unmodifiableMap(map); + } + + @Override + public Builder toBuilder() { + return new Builder(this); + } + + public static Builder builder() { + return new Builder(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + if (!super.equals(obj)) { + return false; + } + PresignedUrlDownloadRequestWrapper that = (PresignedUrlDownloadRequestWrapper) obj; + return Objects.equals(url, that.url) && Objects.equals(range, that.range) && Objects.equals(ifMatch, that.ifMatch); + } + + @Override + public int hashCode() { + int result = Objects.hashCode(super.hashCode()); + result = 31 * result + Objects.hashCode(url); + result = 31 * result + Objects.hashCode(range); + result = 31 * result + Objects.hashCode(ifMatch); + return result; + } + + public static final class Builder extends S3Request.BuilderImpl { + private URL url; + private String range; + private String ifMatch; + + public Builder() { + } + + Builder(PresignedUrlDownloadRequestWrapper request) { + super(request); + this.url = request.url(); + this.range = request.range(); + this.ifMatch = request.ifMatch(); + } + + public Builder url(URL url) { + this.url = url; + return this; + } + + public Builder range(String range) { + this.range = range; + return this; + } + + public Builder ifMatch(String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + @Override + public PresignedUrlDownloadRequestWrapper build() { + return new PresignedUrlDownloadRequestWrapper(this); + } + } +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtils.java index 42c7928db434..adddf4270c22 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtils.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtils.java @@ -55,7 +55,7 @@ public static boolean isS3ExpressAuthRequest(SdkRequest request, ExecutionAttrib AuthSchemeOptionsResolver resolver = executionAttributes.getAttribute(SdkInternalExecutionAttribute.AUTH_SCHEME_OPTIONS_RESOLVER); if (resolver != null) { - List options = resolver.resolve(request); + List options = resolver.resolve(request, executionAttributes); return options.stream().anyMatch(o -> S3ExpressAuthScheme.SCHEME_ID.equals(o.schemeId())); } return false; diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/signing/DefaultS3Presigner.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/signing/DefaultS3Presigner.java index d40ad32c01c2..639995b6c70b 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/signing/DefaultS3Presigner.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/signing/DefaultS3Presigner.java @@ -21,6 +21,7 @@ import static software.amazon.awssdk.utils.CollectionUtils.mergeLists; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; +import java.net.URI; import java.time.Clock; import java.time.Duration; import java.time.Instant; @@ -261,28 +262,32 @@ private List initializeInterceptors() { * Copied from {@link AwsDefaultClientBuilder}. */ private SdkClientConfiguration createClientConfiguration() { - AwsClientEndpointProvider endpointProvider = - AwsClientEndpointProvider.builder() - .clientEndpointOverride(endpointOverride()) - .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_S3") - .serviceEndpointOverrideSystemProperty("aws.endpointUrlS3") - .serviceProfileProperty("s3") - .serviceEndpointPrefix(SERVICE_NAME) - .defaultProtocol("https") - .region(region()) - .profileFile(profileFileSupplier()) - .profileName(profileName()) - .dualstackEnabled(serviceConfiguration.dualstackEnabled()) - .fipsEnabled(fipsEnabled()) - .build(); - - // Make sure the endpoint resolver can actually resolve an endpoint, so that we fail now instead of - // when a request is made. - endpointProvider.clientEndpoint(); + Optional overrideEndpoint = AwsClientEndpointProvider.builder() + .clientEndpointOverride(endpointOverride()) + .serviceEndpointOverrideEnvironmentVariable("AWS_ENDPOINT_URL_S3") + .serviceEndpointOverrideSystemProperty("aws.endpointUrlS3") + .serviceProfileProperty("s3") + .profileFile(profileFileSupplier()) + .profileName(profileName()) + .resolveFromOverrides(); + + ClientEndpointProvider endpointProvider; + if (overrideEndpoint.isPresent()) { + endpointProvider = ClientEndpointProvider.create(overrideEndpoint.get(), true); + } else { + // Validate region at construction time to fail fast for invalid regions (e.g., US_EAST_1 with underscores). + URI testEndpoint = URI.create("https://s3." + region().id() + ".amazonaws.com"); + if (testEndpoint.getHost() == null) { + throw SdkClientException.create("Configured region (" + region() + ") resulted in an invalid URI: " + + testEndpoint + ". This is usually caused by an invalid region " + + "configuration."); + } + // Need an endpoint to marshall but this will be overwritten later with Endpoints 2.0 resolution + endpointProvider = ClientEndpointProvider.create(URI.create("https://localhost"), false); + } return SdkClientConfiguration.builder() - .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, - endpointProvider) + .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, endpointProvider) .build(); } @@ -677,7 +682,7 @@ private void resolveEndpointAndUpdateContext(ExecutionContext execCtx, String op ClientEndpointProvider clientEndpointProvider = executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER); SdkHttpRequest updatedRequest = AwsEndpointProviderUtils.setUri(httpRequest, - clientEndpointProvider.clientEndpoint(), endpoint.url()); + clientEndpointProvider.clientEndpoint(), endpoint.endpointUrl()); if (!endpoint.headers().isEmpty()) { SdkHttpRequest.Builder requestBuilder = updatedRequest.toBuilder(); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtension.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtension.java new file mode 100644 index 000000000000..11103a101580 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtension.java @@ -0,0 +1,132 @@ +/* + * 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.presignedurl; + +import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +/** + * Interface for executing S3 operations asynchronously using presigned URLs. This can be accessed using + * {@link S3AsyncClient#presignedUrlExtension()}. + * + *

    Checksum Validation: If the presigned URL was generated with + * {@link software.amazon.awssdk.services.s3.presigner.S3Presigner#presignGetObject} using + * {@code checksumMode(ChecksumMode.ENABLED)}, the SDK automatically sends the required header + * and S3 returns checksums for full object downloads (HTTP 200). For ranged downloads (HTTP 206), + * checksums are only returned for multipart-uploaded objects when the range aligns with original + * upload part boundaries. The downloader cannot enable checksums if the URL was not presigned + * with checksum mode. + */ +@SdkPublicApi +public interface AsyncPresignedUrlExtension { + /** + *

    + * Downloads an S3 object asynchronously using a presigned URL. + *

    + * + *

    + * This operation uses a presigned URL to download an object from Amazon S3. The presigned URL must be valid and not expired. + *

    + * + *

    + * To download a specific byte range of the object, use the range parameter in the request. + *

    + * + * @param request The presigned URL request containing the URL and optional parameters + * @param responseTransformer Transforms the response to the desired return type + * @param The type of the transformed response + * @return A {@link CompletableFuture} containing the transformed result + * @throws SdkClientException If any client side error occurs + * @throws S3Exception Base class for all S3 service exceptions + */ + default CompletableFuture getObject(PresignedUrlDownloadRequest request, + AsyncResponseTransformer responseTransformer) { + throw new UnsupportedOperationException(); + } + + /** + *

    + * Downloads an S3 object asynchronously using a presigned URL with a consumer-based request builder. + *

    + * + *

    + * This is a convenience method that creates a {@link PresignedUrlDownloadRequest} using the provided consumer. + *

    + * + * @param requestConsumer Consumer that will configure a {@link PresignedUrlDownloadRequest.Builder} + * @param responseTransformer Transforms the response to the desired return type + * @param The type of the transformed response + * @return A {@link CompletableFuture} containing the transformed result + * @throws SdkClientException If any client side error occurs + * @throws S3Exception Base class for all S3 service exceptions + */ + default CompletableFuture getObject(Consumer requestConsumer, + AsyncResponseTransformer responseTransformer) { + return getObject(PresignedUrlDownloadRequest.builder().applyMutation(requestConsumer).build(), responseTransformer); + } + + /** + *

    + * Downloads an S3 object asynchronously using a presigned URL and saves it to the specified file path. + *

    + * + *

    + * This is a convenience method that uses {@link AsyncResponseTransformer#toFile(Path)} to save the object + * directly to a file. + *

    + * + * @param request The presigned URL request containing the URL and optional parameters + * @param destinationPath The path where the downloaded object will be saved + * @return A {@link CompletableFuture} containing the {@link GetObjectResponse} + * @throws SdkClientException If any client side error occurs + * @throws S3Exception Base class for all S3 service exceptions + */ + default CompletableFuture getObject(PresignedUrlDownloadRequest request, + Path destinationPath) { + return getObject(request, AsyncResponseTransformer.toFile(destinationPath)); + } + + /** + *

    + * Downloads an S3 object asynchronously using a presigned URL with a consumer-based request builder + * and saves it to the specified file path. + *

    + * + *

    + * This is a convenience method that combines consumer-based request building with file-based response handling. + *

    + * + * @param requestConsumer Consumer that will configure a {@link PresignedUrlDownloadRequest.Builder} + * @param destinationPath The path where the downloaded object will be saved + * @return A {@link CompletableFuture} containing the {@link GetObjectResponse} + * @throws SdkClientException If any client side error occurs + * @throws S3Exception Base class for all S3 service exceptions + */ + default CompletableFuture getObject(Consumer requestConsumer, + Path destinationPath) { + return getObject(requestConsumer, AsyncResponseTransformer.toFile(destinationPath)); + } +} \ No newline at end of file diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequest.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequest.java new file mode 100644 index 000000000000..a33eb9e5e3c2 --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequest.java @@ -0,0 +1,196 @@ +/* + * 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.presignedurl.model; + +import java.net.URL; +import java.util.Objects; +import software.amazon.awssdk.annotations.SdkPublicApi; +import software.amazon.awssdk.services.s3.internal.presignedurl.PresignedUrlRedactionUtils; +import software.amazon.awssdk.utils.ToString; +import software.amazon.awssdk.utils.Validate; +import software.amazon.awssdk.utils.builder.CopyableBuilder; +import software.amazon.awssdk.utils.builder.ToCopyableBuilder; + +/** + * Request object for performing download operations using a presigned URL. + */ +@SdkPublicApi +public final class PresignedUrlDownloadRequest implements ToCopyableBuilder { + private final URL presignedUrl; + private final String range; + private final String ifMatch; + + private PresignedUrlDownloadRequest(BuilderImpl builder) { + this.presignedUrl = builder.presignedUrl; + this.range = builder.range; + this.ifMatch = builder.ifMatch; + } + + /** + *

    + * The presigned URL for the S3 object. This URL contains all necessary authentication information and can be used to download + * the object without additional credentials. + *

    + * Note: Presigned URLs have a limited lifetime and will expire after the + * specified duration. Ensure the URL is used before expiration. + * + * @return The presigned URL for the S3 object + */ + public URL presignedUrl() { + return presignedUrl; + } + + /** + *

    + * Specifies the byte range of an object. For more information about the HTTP Range header, see + * + * https://www.rfc-editor.org/rfc/rfc9110.html#name-range. + *

    + * Note: Amazon S3 doesn't support retrieving multiple ranges of data per GET request. + * + * @return The HTTP Range header value, or null if not specified. + */ + public String range() { + return range; + } + + /** + *

    + * Return the object only if its entity tag (ETag) is the same as the one specified in this header, + * otherwise return a 412 (precondition failed) error. + *

    + * + * @return The If-Match header value, or null if not specified. + */ + public String ifMatch() { + return ifMatch; + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(this); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + public static Class serializableBuilderClass() { + return BuilderImpl.class; + } + + @Override + public int hashCode() { + int hashCode = 1; + hashCode = 31 * hashCode + Objects.hashCode(presignedUrl()); + hashCode = 31 * hashCode + Objects.hashCode(range()); + hashCode = 31 * hashCode + Objects.hashCode(ifMatch()); + return hashCode; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + PresignedUrlDownloadRequest other = (PresignedUrlDownloadRequest) obj; + return Objects.equals(presignedUrl(), other.presignedUrl()) && + Objects.equals(range(), other.range()) && + Objects.equals(ifMatch(), other.ifMatch()); + } + + /** + * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be + * redacted from this string using a placeholder value: the query string of the presigned URL carries the request + * signature, the credential scope and, for session credentials, the security token, so it is never rendered. The + * user-info and fragment components of the URL are omitted entirely. Use {@link #presignedUrl()} to obtain the + * unmodified URL. + */ + @Override + public String toString() { + return ToString.builder("PresignedUrlDownloadRequest") + .add("PresignedUrl", PresignedUrlRedactionUtils.redactQueryString(presignedUrl())) + .add("Range", range()) + .add("IfMatch", ifMatch()) + .build(); + } + + public interface Builder extends CopyableBuilder { + /** + * Sets the presigned URL for the S3 object. + * @param presignedUrl + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder presignedUrl(URL presignedUrl); + + /** + * Specifies the byte range of an object. + * @param range The HTTP Range header value (e.g., "bytes=0-1023") + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder range(String range); + + /** + * Return the object only if its entity tag (ETag) is the same as the one specified in this header. + * @param ifMatch The If-Match header value (ETag) + * @return Returns a reference to this object so that method calls can be chained together. + */ + Builder ifMatch(String ifMatch); + } + + static final class BuilderImpl implements Builder { + private URL presignedUrl; + private String range; + private String ifMatch; + + private BuilderImpl() { + } + + private BuilderImpl(PresignedUrlDownloadRequest presignedUrlDownloadRequest) { + presignedUrl(presignedUrlDownloadRequest.presignedUrl()); + range(presignedUrlDownloadRequest.range()); + ifMatch(presignedUrlDownloadRequest.ifMatch()); + } + + @Override + public Builder presignedUrl(URL presignedUrl) { + this.presignedUrl = presignedUrl; + return this; + } + + @Override + public Builder range(String range) { + this.range = range; + return this; + } + + @Override + public Builder ifMatch(String ifMatch) { + this.ifMatch = ifMatch; + return this; + } + + @Override + public PresignedUrlDownloadRequest build() { + Validate.paramNotNull(presignedUrl, "presignedUrl"); + return new PresignedUrlDownloadRequest(this); + } + } +} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/presigner/S3Presigner.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presigner/S3Presigner.java index e23516178e92..b5fd634255fa 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/presigner/S3Presigner.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/presigner/S3Presigner.java @@ -294,6 +294,12 @@ static Builder builder() { * signing or authentication. *

    * + * Checksum support: Setting {@code checksumMode(ChecksumMode.ENABLED)} on the + * {@code GetObjectRequest} enables the downloader to receive checksums from S3 for data integrity + * validation. The resulting URL will not be browser-executable (requires the + * {@code x-amz-checksum-mode} header at download time, which the SDK sends automatically). + *

    + * * Example Usage *

    * diff --git a/services/s3/src/main/resources/codegen-resources/customization.config b/services/s3/src/main/resources/codegen-resources/customization.config index 1b772237a1dc..863f9d0eba06 100644 --- a/services/s3/src/main/resources/codegen-resources/customization.config +++ b/services/s3/src/main/resources/codegen-resources/customization.config @@ -317,13 +317,11 @@ "enableEndpointAuthSchemeParams": true, "customClientContextParams":{ "CrossRegionAccessEnabled":{ - "documentation":"Enables cross-region bucket access for this client. Note: When enabling this feature, the S3 client will always set the 'Expect: 100-continue' header; the S3Configuration.expectContinueEnabled and S3Configuration.expectContinueThresholdInBytes configurations have no effect.", + "documentation":"Enables cross-region bucket access for this client. Note: When enabling this feature, the S3 client sets the 'Expect: 100-continue' header by default so that S3 can issue its cross-region redirect before the request body is sent. This can be overridden by explicitly setting S3Configuration.expectContinueEnabled to false, in which case the first request to a not yet resolved bucket may fail with an I/O error and rely on normal retries.", "type":"boolean" } }, "endpointAuthSchemeConfig": { - "authSchemeStrategyFactoryClass": "software.amazon.awssdk.services.s3.endpoints.internal.S3EndpointAuthSchemeStrategyFactory", - "knownEndpointProperties": "software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty.KNOWN_S3_ENDPOINT_PROPERTIES", "endpointProviderTestKeys": { "backend": { "key": "software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty.BACKEND", @@ -332,7 +330,6 @@ } }, - "enableGenerateCompiledEndpointRules": true, "endpointParameters": { "DeleteObjectKeys": { "required": false, @@ -359,5 +356,6 @@ "methodName": "modifyUploadPartCopyRequest", "className": "software.amazon.awssdk.services.s3.internal.CustomRequestTransformerUtils" } - } + }, + "presignedUrlExtensionSupported": true } diff --git a/services/s3/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3f427f9c104f --- /dev/null +++ b/services/s3/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,2551 @@ +{ + "version": "1.1", + "parameters": { + "Bucket": { + "required": false, + "documentation": "The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "ForcePathStyle": { + "builtIn": "AWS::S3::ForcePathStyle", + "required": true, + "default": false, + "documentation": "When true, force a path-style endpoint to be used where the bucket name is part of the path.", + "type": "boolean" + }, + "Accelerate": { + "builtIn": "AWS::S3::Accelerate", + "required": true, + "default": false, + "documentation": "When true, use S3 Accelerate. NOTE: Not all regions support S3 accelerate.", + "type": "boolean" + }, + "UseGlobalEndpoint": { + "builtIn": "AWS::S3::UseGlobalEndpoint", + "required": true, + "default": false, + "documentation": "Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.", + "type": "boolean" + }, + "UseObjectLambdaEndpoint": { + "required": false, + "documentation": "Internal parameter to use object lambda endpoint for an operation (eg: WriteGetObjectResponse)", + "type": "boolean" + }, + "Key": { + "required": false, + "documentation": "The S3 Key used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Key.", + "type": "string" + }, + "Prefix": { + "required": false, + "documentation": "The S3 Prefix used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Prefix.", + "type": "string" + }, + "CopySource": { + "required": false, + "documentation": "The Copy Source used for Copy Object request. This is an optional parameter that will be set automatically for operations that are scoped to Copy Source.", + "type": "string" + }, + "DisableAccessPoints": { + "required": false, + "documentation": "Internal parameter to disable Access Point Buckets", + "type": "boolean" + }, + "DisableMultiRegionAccessPoints": { + "builtIn": "AWS::S3::DisableMultiRegionAccessPoints", + "required": true, + "default": false, + "documentation": "Whether multi-region access points (MRAP) should be disabled.", + "type": "boolean" + }, + "UseArnRegion": { + "builtIn": "AWS::S3::UseArnRegion", + "required": false, + "documentation": "When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN's region when constructing the endpoint instead of the client's configured region.", + "type": "boolean" + }, + "UseS3ExpressControlEndpoint": { + "required": false, + "documentation": "Internal parameter to indicate whether S3Express operation should use control plane, (ex. CreateBucket)", + "type": "boolean" + }, + "DisableS3ExpressSessionAuth": { + "required": false, + "documentation": "Parameter to indicate whether S3Express session auth should be disabled", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "Accelerate" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Bucket" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 6, + true + ] + }, + "" + ] + }, + "--x-s3" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 7, + true + ] + }, + "" + ] + }, + "--xa-s3" + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "partitionResult" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 7, + true + ], + "assign": "accessPointSuffix" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "accessPointSuffix" + }, + "--op-s3" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 8, + 12, + true + ], + "assign": "regionPrefix" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 32, + 49, + true + ], + "assign": "outpostId_ssa_2" + }, + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 49, + 50, + true + ], + "assign": "hardwareType" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "ForcePathStyle" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "ite", + "argv": [ + { + "ref": "UseDualStack" + }, + ".dualstack", + "" + ], + "assign": "_s3e_ds" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_2" + }, + false + ] + }, + { + "fn": "ite", + "argv": [ + { + "ref": "UseFIPS" + }, + "-fips", + "" + ], + "assign": "_s3e_fips" + }, + { + "fn": "ite", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "DisableS3ExpressSessionAuth" + }, + false + ] + }, + "sigv4", + "sigv4-s3express" + ], + "assign": "_s3e_auth" + }, + { + "fn": "aws.isVirtualHostableS3Bucket", + "argv": [ + { + "ref": "Bucket" + }, + false + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "url" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseS3ExpressControlEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "aws.isVirtualHostableS3Bucket", + "argv": [ + { + "ref": "Bucket" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "url" + }, + "scheme" + ] + }, + "http" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "Region" + }, + false + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "Bucket" + } + ], + "assign": "bucketArn" + }, + { + "fn": "getAttr", + "argv": [ + { + "fn": "split", + "argv": [ + { + "ref": "Bucket" + }, + "--", + 0 + ] + }, + "[-2]" + ], + "assign": "s3expressAvailabilityZoneId" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 0, + 4, + false + ] + }, + "" + ] + }, + "arn:" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 16, + 18, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "url" + }, + "isIp" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 21, + 23, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 27, + 29, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "regionPrefix" + }, + "beta" + ] + }, + { + "fn": "uriEncode", + "argv": [ + { + "ref": "Bucket" + } + ], + "assign": "uri_encoded_bucket" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "Region" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseObjectLambdaEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[0]" + ], + "assign": "arnType" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType" + }, + "accesspoint" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[1]" + ], + "assign": "accessPointName_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 14, + 16, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "hardwareType" + }, + "e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "hardwareType" + }, + "o" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-global" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 19, + 21, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3-object-lambda" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "DisableAccessPoints" + }, + false + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3-outposts" + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ], + "assign": "bucketPartition" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 26, + 28, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 15, + 17, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[4]" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "Bucket" + }, + 20, + 22, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseGlobalEndpoint" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[1]" + ], + "assign": "outpostId_ssa_1" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseArnRegion" + }, + true + ] + }, + true + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_1" + }, + false + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[2]" + ], + "assign": "outpostType" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketPartition" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "DisableMultiRegionAccessPoints" + }, + true + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "partition" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[3]" + ], + "assign": "accessPointName_ssa_2" + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_1" + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "outpostType" + }, + "accesspoint" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "accessPointName_ssa_2" + }, + false + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Accelerate cannot be used with FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "Cannot set dual-stack in combination with a custom endpoint.", + "type": "error" + }, + { + "conditions": [], + "error": "A custom endpoint cannot be combined with FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "A custom endpoint cannot be combined with S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3Express does not support S3 Accelerate.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "S3Express bucket name is not a valid virtual hostable name.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control{_s3e_fips}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3express{_s3e_fips}-{s3expressAvailabilityZoneId}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Unrecognized S3Express bucket name format.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "{_s3e_auth}", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control{_s3e_fips}{_s3e_ds}.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "backend": "S3Express", + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Expected a endpoint to be specified but no endpoint was found", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.ec2.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.ec2.s3-outposts.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.op-{outpostId_ssa_2}.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.op-{outpostId_ssa_2}.s3-outposts.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Unrecognized hardware type: \"Expected hardware type o or e but got {hardwareType}\"", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Outposts Bucket alias - it must be a valid bucket name.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`.", + "type": "error" + }, + { + "conditions": [], + "error": "Custom endpoint `{Endpoint}` was not a valid URI", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Accelerate cannot be used in this region", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid region: region was not a valid DNS name.", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Object Lambda does not support Dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Object Lambda does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Access points are not supported for this operation", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Missing account id", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{accessPointName_ssa_1}-{bucketArn#accountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-object-lambda-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-object-lambda.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", + "type": "error" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: bucket ARN is missing a region", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `{arnType}`", + "type": "error" + }, + { + "conditions": [], + "error": "Access Points do not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint-fips.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{accessPointName_ssa_1}-{bucketArn#accountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}-{bucketArn#accountId}.s3-accesspoint.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The ARN was not for the S3 service, found: {bucketArn#service}", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3 MRAP does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: Multi-Region Access Point ARNs are disabled.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_1}.accesspoint.s3-global.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but bucket referred to partition `{bucketArn#partition}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Access Point Name", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support Dual-stack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Outposts does not support S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Arn: Outpost Access Point ARN contains sub resources", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_2}-{bucketArn#accountId}.{outpostId_ssa_1}.{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{accessPointName_ssa_2}-{bucketArn#accountId}.{outpostId_ssa_1}.s3-outposts.{bucketArn#region}.{bucketPartition#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4a", + "signingName": "s3-outposts", + "signingRegionSet": [ + "*" + ] + }, + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName_ssa_2}`", + "type": "error" + }, + { + "conditions": [], + "error": "Expected an outpost type `accesspoint`, found {outpostType}", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: expected an access point name", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected a 4-component resource", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `{outpostId_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The Outpost Id was not set", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Unrecognized format: {Bucket} (type: {arnType})", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: No ARN type specified", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: `{Bucket}` was not a valid ARN", + "type": "error" + }, + { + "conditions": [], + "error": "Path-style addressing cannot be used with ARN buckets", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Path-style addressing cannot be used with S3 Accelerate", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-object-lambda-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-object-lambda.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-object-lambda", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "A region must be set when sending requests to S3.", + "type": "error" + } + ], + "root": 2, + "nodeCount": 553, + "nodes": "/////wAAAAH/////AAAAAAAAAAMF9eFzAAAAAQAAAagAAAAEAAAAAgAAARAAAAAFAAAAAwAAAOkAAAAGAAAABAAAAFUAAAAHAAAABQAAAA8AAAAIAAAACAAAAAkF9eFzAAAAEAAAAAoAAAANAAAAEgAAAAsAAAANAAAAEwAAAAwAAAANAAAAFgX14Q4AAAANAAAAIwAAAA4F9eEqAAAAJAX14WcAAAGzAAAABgAAAQ8AAAAQAAAABwAAAQ4AAAARAAAACAAAABMAAAASAAAADgAAAfUAAABqAAAACQAAABQAAAAYAAAACgAAABUAAAAYAAAACwAAABYAAAAYAAAADAAAABcAAAAYAAAADQAAAiMAAAAYAAAADgAAAE0AAAAZAAAAFAAAAEkAAAAaAAAAGgAAABsAAABOAAAAJQAAABwF9eFWAAAAJgX14VYAAAAdAAAAJwAAAC8AAAAeAAAAMAX14ToAAAAfAAAAMgAAACAF9eFVAAAAMwAAACEAAACIAAAANwX14UwAAAAiAAAAOwAAACMF9eFUAAAAPAAAACcAAAAkAAAAPQAAACUF9eFTAAAAPgAAACYAAACSAAAAPwAAACkF9eEuAAAAPQAAACgF9eFTAAAAPgAAACkAAACWAAAAQAAAACoF9eE2AAAAQgAAACsF9eE1AAAARgAAACwF9eE0AAAARwAAAC0F9eFRAAAASQAAAC4F9eFQAAAASgX14U4F9eFPAAAAKAAAADAF9eE5AAAAKQX14TkAAAAxAAAAKgAAALkAAAAyAAAAMAAAAD4AAAAzAAAAMQX14S0AAAA0AAAAMwAAADUAAAIOAAAAPAAAADgAAAA2AAAAPgX14TcAAAA3AAAAPwAAADkF9eEuAAAAPgX14TcAAAA5AAAAQAAAADoF9eE2AAAAQgAAADsF9eE1AAAARQAAADwF9eFBAAAARgAAAD0F9eE0AAAASAX14UAF9eEzAAAAMQX14S0AAAA/AAAAMwAAAEAAAAIOAAAAPAAAAEMAAABBAAAAPgX14TcAAABCAAAAPwAAAEQF9eEuAAAAPgX14TcAAABEAAAAQAAAAEUF9eE2AAAAQgAAAEYF9eE1AAAARAX14S8AAABHAAAARgAAAEgF9eE0AAAASAX14TIF9eEzAAAAGQAAAEoF9eEqAAAALgX14ScAAABLAAAAOQAAAEwF9eEpAAAAOgX14SgF9eEpAAAAGgX14VgAAABOAAAAHAX14VcAAABPAAAAIgAAAFIAAABQAAAAIwAAAFEAAAIhAAAAJAX14WcF9eFzAAAALgX14WEAAABTAAAAOQAAAFQF9eFjAAAAOgX14WIF9eFjAAAABQAAAGUAAABWAAAACAAAAFcF9eFzAAAAEAAAAFgAAABZAAAAEgAAAFsAAABZAAAAEwAAAFoAAABcAAAAFQAAAGEAAABfAAAAEwAAAF0AAABcAAAAFQAAAGIAAABfAAAAFQAAAGEAAABeAAAAFgX14Q4AAABfAAAAIwAAAGAF9eEqAAAAJAX14WcF9eEqAAAAFgX14Q0AAABiAAAAIwAAAGMF9eEqAAAAJAX14WUAAABkAAAALgX14W4F9eFvAAAABgAAANYAAABmAAAABwAAANAAAABnAAAACAAAAHcAAABoAAAADgAAAHYAAABpAAAAFQAAAGoF9eEXAAAAGgAAAGsAAAH2AAAAJQAAAGwF9eFWAAAAJgX14VYAAABtAAAAJwAAAHAAAABuAAAAMAX14ToAAABvAAAAMgAAAIgF9eFVAAAAKAAAAHEF9eE5AAAAKQX14TkAAAByAAAAKgAAAHMAAAH0AAAAMAX14TgAAAB0AAAANAAAAHUF9eFIAAAAQQX14UUF9eFIAAAAFQAAAfUF9eEXAAAACQAAAHgAAAB8AAAACgAAAHkAAAB8AAAACwAAAHoAAAB8AAAADAAAAHsAAAB8AAAADQAAAMoAAAB8AAAADgAAAMMAAAB9AAAAFAAAAL4AAAB+AAAAFQAAAH8F9eEXAAAAFwAAAIAAAACBAAAAGAAAAL0AAACBAAAAGgAAAIIAAADFAAAAJQAAAIMF9eFWAAAAJgX14VYAAACEAAAAJwAAAJ8AAACFAAAAMAX14ToAAACGAAAAMgAAAIcF9eFVAAAAMwAAAI0AAACIAAAANwX14UwAAACJAAAAOwAAAIoF9eFUAAAAPAX14VMAAACLAAAAPQAAAIwF9eFTAAAAPwX14VMF9eEuAAAANwX14UwAAACOAAAAOwAAAI8F9eFUAAAAPAAAAJQAAACQAAAAPQAAAJEF9eFTAAAAPgAAAJMAAACSAAAAPwAAAJYF9eEuAAAAPwAAAJkF9eEuAAAAPQAAAJUF9eFTAAAAPgAAAJkAAACWAAAAQAAAAJcF9eE2AAAAQgAAAJgF9eE1AAAARgX14VIF9eE0AAAAQAAAAJoF9eE2AAAAQgAAAJsF9eE1AAAARgAAAJwF9eE0AAAARwAAAJ0F9eFRAAAASQAAAJ4F9eFQAAAASgX14U0F9eFPAAAAKAAAAKAF9eE5AAAAKQX14TkAAAChAAAAKgAAALkAAACiAAAAMAAAAK4AAACjAAAAMQX14S0AAACkAAAAMwAAAKUAAAIOAAAAPAAAAKgAAACmAAAAPgX14TcAAACnAAAAPwAAAKkF9eEuAAAAPgX14TcAAACpAAAAQAAAAKoF9eE2AAAAQgAAAKsF9eE1AAAARQAAAKwF9eFBAAAARgAAAK0F9eE0AAAASAX14T8F9eEzAAAAMQX14S0AAACvAAAAMwAAALAAAAIOAAAAPAAAALMAAACxAAAAPgX14TcAAACyAAAAPwAAALQF9eEuAAAAPgX14TcAAAC0AAAAQAAAALUF9eE2AAAAQgAAALYF9eE1AAAARAX14S8AAAC3AAAARgAAALgF9eE0AAAASAX14TAF9eEzAAAAMAX14TgAAAC6AAAANAAAALsF9eFIAAAAQQX14UUAAAC8AAAAQwX14UYF9eFHAAAAGQX14SQF9eEqAAAAFQAAAL8F9eEXAAAAGQAAAMAF9eEqAAAAHgAAAMIAAADBAAAALgX14SIF9eEkAAAALgX14SEF9eEjAAAAFQAAAMQF9eEXAAAAGgX14VgAAADFAAAAHAX14VcAAADGAAAAIgAAAMkAAADHAAAAIwAAAMgAAAIhAAAAJAX14WUF9eFzAAAALgX14V8F9eFgAAAAEQAAAMsF9eEWAAAAFAAAAMwF9eEVAAAAFQAAAM0AAAImAAAAIQAAAM4AAAImAAAALAX14RAAAADPAAAALQX14RIF9eEUAAAACAAAANEAAADXAAAAEAAAANIAAADcAAAAEgAAANMAAADcAAAAEwAAANQAAADgAAAAFAAAANUAAADjAAAAFQAAAOcAAAGRAAAACAAAANoAAADXAAAAEwAAANgF9eEJAAAAFAAAANkAAADjAAAAFQAAAOcF9eEJAAAAEAAAANsAAADcAAAAEgAAAN8AAADcAAAAEwAAAN0AAADgAAAAFAAAAN4AAADjAAAAFQAAAOcF9eEMAAAAEwAAAOIAAADgAAAAFAAAAOEF9eEJAAAAFQX14QkF9eEMAAAAFAAAAOYAAADjAAAAFQAAAOQF9eEJAAAAHgAAAOUF9eEJAAAAIgX14QcF9eEJAAAAFQAAAOcAAAGfAAAAHgAAAOgF9eEIAAAAIgX14QcF9eEIAAAABAX14QIAAADqAAAABQAAAOsAAAHgAAAABgAAAQ8AAADsAAAABwAAAQ4AAADtAAAACAAAAO4AAAHrAAAACQAAAO8AAADzAAAACgAAAPAAAADzAAAACwAAAPEAAADzAAAADAAAAPIAAADzAAAADQAAAiMAAADzAAAADgAAAQoAAAD0AAAAFAAAAQgAAAD1AAAAGgAAAPYAAAELAAAAJQAAAPcF9eFWAAAAJgX14VYAAAD4AAAAJwAAAPkAAAIGAAAAKAAAAPoF9eE5AAAAKQX14TkAAAD7AAAAKgAAAhoAAAD8AAAAMAX14SsAAAD9AAAAMQX14S0AAAD+AAAAMwAAAP8AAAIOAAAAPAAAAQIAAAEAAAAAPgX14TcAAAEBAAAAPwAAAQMF9eEuAAAAPgX14TcAAAEDAAAAQAAAAQQF9eE2AAAAQgAAAQUF9eE1AAAARQAAAQYF9eFBAAAARgAAAQcF9eE0AAAASAX14T4F9eEzAAAAGQAAAQkF9eEqAAAALgX14R8F9eEgAAAAGgX14VgAAAELAAAAHAX14VcAAAEMAAAAIgAAAQ0AAAIgAAAALgX14V0F9eFeAAAACAAAAY0F9eEJAAAACAAAAZcF9eEJAAAAAwAAAVoAAAERAAAABAX14QMAAAESAAAABQAAARwAAAETAAAACAAAARQF9eFzAAAADwX14QUAAAEVAAAAEAAAARYAAAEZAAAAEgAAARcAAAEZAAAAEwAAARgAAAEZAAAAFgX14Q4AAAEZAAAAIwAAARoF9eEqAAAAJAX14WYAAAEbAAAALgX14WoF9eFrAAAABgAAAZUAAAEdAAAABwAAAYsAAAEeAAAACAAAAScAAAEfAAAADgAAAfUAAAEgAAAAGgAAASEAAAH2AAAAJQAAASIF9eFWAAAAJgX14VYAAAEjAAAAJwAAASQAAAEzAAAAKAAAASUF9eE5AAAAKQX14TkAAAEmAAAAKgAAAU8AAAH0AAAACQAAASgAAAEsAAAACgAAASkAAAEsAAAACwAAASoAAAEsAAAADAAAASsAAAEsAAAADQAAAYoAAAEsAAAADgAAAVMAAAEtAAAADwX14QUAAAEuAAAAFAAAAVEAAAEvAAAAGgAAATAAAAFVAAAAJQAAATEF9eFWAAAAJgX14VYAAAEyAAAAJwAAATUAAAEzAAAAMAX14ToAAAE0AAAAMgX14UoF9eFVAAAAKAAAATYF9eE5AAAAKQX14TkAAAE3AAAAKgAAAU8AAAE4AAAAMAAAAUQAAAE5AAAAMQX14S0AAAE6AAAAMwAAATsAAAIOAAAAPAAAAT4AAAE8AAAAPgX14TcAAAE9AAAAPwAAAT8F9eEuAAAAPgX14TcAAAE/AAAAQAAAAUAF9eE2AAAAQgAAAUEF9eE1AAAARQAAAUIF9eFBAAAARgAAAUMF9eE0AAAASAX14T0F9eEzAAAAMQX14S0AAAFFAAAAMwAAAUYAAAIOAAAAPAAAAUkAAAFHAAAAPgX14TcAAAFIAAAAPwAAAUoF9eEuAAAAPgX14TcAAAFKAAAAQAAAAUsF9eE2AAAAQgAAAUwF9eE1AAAARAX14S8AAAFNAAAARgAAAU4F9eE0AAAASAX14TEF9eEzAAAAMAX14TgAAAFQAAAANAX14UMF9eFIAAAAGQAAAVIF9eEqAAAALgX14RsF9eEcAAAADwX14QUAAAFUAAAAGgX14VgAAAFVAAAAHAX14VcAAAFWAAAAIgAAAVkAAAFXAAAAIwAAAVgAAAIhAAAAJAX14WYF9eFzAAAALgX14VsF9eFcAAAABAX14QIAAAFbAAAABQAAAWUAAAFcAAAACAAAAV0F9eFzAAAADwX14QUAAAFeAAAAEAAAAV8AAAFiAAAAEgAAAWAAAAFiAAAAEwAAAWEAAAFiAAAAFgX14Q4AAAFiAAAAIwAAAWMF9eEqAAAAJAX14SsAAAFkAAAALgX14WgF9eFpAAAABgAAAZUAAAFmAAAABwAAAYsAAAFnAAAACAAAAWgAAAHrAAAACQAAAWkAAAFtAAAACgAAAWoAAAFtAAAACwAAAWsAAAFtAAAADAAAAWwAAAFtAAAADQAAAYoAAAFtAAAADgAAAYUAAAFuAAAADwX14QUAAAFvAAAAFAAAAYMAAAFwAAAAGgAAAXEAAAGHAAAAJQAAAXIF9eFWAAAAJgX14VYAAAFzAAAAJwAAAXQAAAIGAAAAKAAAAXUF9eE5AAAAKQX14TkAAAF2AAAAKgAAAhoAAAF3AAAAMAX14SsAAAF4AAAAMQX14S0AAAF5AAAAMwAAAXoAAAIOAAAAPAAAAX0AAAF7AAAAPgX14TcAAAF8AAAAPwAAAX4F9eEuAAAAPgX14TcAAAF+AAAAQAAAAX8F9eE2AAAAQgAAAYAF9eE1AAAARQAAAYEF9eFBAAAARgAAAYIF9eE0AAAASAX14TwF9eEzAAAAGQAAAYQF9eEqAAAALgX14RkF9eEaAAAADwX14QUAAAGGAAAAGgX14VgAAAGHAAAAHAX14VcAAAGIAAAAIgAAAYkAAAIgAAAALgX14VkF9eFaAAAADwX14QUAAAIjAAAACAAAAYwF9eEJAAAADwX14QUAAAGNAAAAEAAAAY4AAAGaAAAAEgAAAY8AAAGaAAAAEwAAAZAAAAGaAAAAFAAAAZEF9eEJAAAAGwAAAZIF9eEMAAAAHQX14QsAAAGTAAAAHwX14QsAAAGUAAAAIAX14QsAAAGmAAAACAAAAZYF9eEJAAAADwX14QUAAAGXAAAAEAAAAZgAAAGaAAAAEgAAAZkAAAGaAAAAEwAAAZsAAAGaAAAAFAX14QwF9eEJAAAAFAAAAZ4AAAGcAAAAFgAAAZ0F9eEJAAAAIgX14QoF9eEJAAAAFgAAAaAAAAGfAAAAGwAAAaMF9eEMAAAAGwAAAaIAAAGhAAAAIgX14QoF9eEMAAAAIgX14QoAAAGjAAAAKwX14QsAAAGkAAAALwX14QsAAAGlAAAANQX14QsAAAGmAAAANgX14QsAAAGnAAAAOAX14QsF9eEMAAAAAgX14QEAAAGpAAAAAwAAAd4AAAGqAAAABAX14QQAAAGrAAAABQAAAbYAAAGsAAAACAAAAa0F9eFzAAAAEAAAAa4AAAGxAAAAEgAAAa8AAAGxAAAAEwAAAbAAAAGxAAAAFgX14Q4AAAGxAAAAIwAAAbIF9eEqAAAAJAX14SwAAAGzAAAALgX14XAAAAG0AAAAOQAAAbUF9eFyAAAAOgX14XEF9eFyAAAABgX14QYAAAG3AAAABwX14QYAAAG4AAAACAAAAcIAAAG5AAAADgAAAfUAAAG6AAAAGgAAAbsAAAH2AAAAJQAAAbwF9eFWAAAAJgX14VYAAAG9AAAAJwAAAb4AAAHRAAAAKAAAAb8F9eE5AAAAKQX14TkAAAHAAAAAKgAAAdcAAAHBAAAAMAX14SwAAAH0AAAACQAAAcMAAAHHAAAACgAAAcQAAAHHAAAACwAAAcUAAAHHAAAADAAAAcYAAAHHAAAADQAAAiMAAAHHAAAADgAAAdkAAAHIAAAADwAAAcwAAAHJAAAAFAAAAcoAAAHNAAAAGQAAAcsF9eEqAAAALgX14SUF9eEmAAAAFAAAAhwAAAHNAAAAGgAAAc4AAAHaAAAAJQAAAc8F9eFWAAAAJgX14VYAAAHQAAAAJwAAAdMAAAHRAAAAMAX14ToAAAHSAAAAMgX14UsF9eFVAAAAKAAAAdQF9eE5AAAAKQX14TkAAAHVAAAAKgAAAdcAAAHWAAAAMAX14SwAAAIMAAAAMAX14SwAAAHYAAAANAX14UQF9eFIAAAAGgX14VgAAAHaAAAAHAX14VcAAAHbAAAAIgX14WQAAAHcAAAAIwAAAd0AAAIhAAAAJAX14SwF9eFzAAAABAX14QIAAAHfAAAABQAAAegAAAHgAAAACAAAAeEF9eFzAAAAEAAAAeIAAAHlAAAAEgAAAeMAAAHlAAAAEwAAAeQAAAHlAAAAFgX14Q4AAAHlAAAAIwAAAeYF9eEqAAAAJAX14SsAAAHnAAAALgX14WwF9eFtAAAABgX14QYAAAHpAAAABwX14QYAAAHqAAAACAAAAfcAAAHrAAAADgAAAfUAAAHsAAAAGgAAAe0AAAH2AAAAJQAAAe4F9eFWAAAAJgX14VYAAAHvAAAAJwAAAfAAAAIGAAAAKAAAAfEF9eE5AAAAKQX14TkAAAHyAAAAKgAAAhoAAAHzAAAAMAX14SsAAAH0AAAAMQX14S0AAAIOAAAAGgX14VgAAAH2AAAAHAX14VcF9eFzAAAACQAAAfgAAAH8AAAACgAAAfkAAAH8AAAACwAAAfoAAAH8AAAADAAAAfsAAAH8AAAADQAAAiMAAAH8AAAADgAAAh0AAAH9AAAADwAAAgEAAAH+AAAAFAAAAf8AAAICAAAAGQAAAgAF9eEqAAAALgX14R0F9eEeAAAAFAAAAhwAAAICAAAAGgAAAgMAAAIeAAAAJQAAAgQF9eFWAAAAJgX14VYAAAIFAAAAJwAAAggAAAIGAAAAMAX14ToAAAIHAAAAMgX14UkF9eFVAAAAKAAAAgkF9eE5AAAAKQX14TkAAAIKAAAAKgAAAhoAAAILAAAAMAX14SsAAAIMAAAAMQX14S0AAAINAAAAMwAAAhEAAAIOAAAAPAX14TcAAAIPAAAAPgX14TcAAAIQAAAAPwX14TcF9eEuAAAAPAAAAhQAAAISAAAAPgX14TcAAAITAAAAPwAAAhUF9eEuAAAAPgX14TcAAAIVAAAAQAAAAhYF9eE2AAAAQgAAAhcF9eE1AAAARQAAAhgF9eFBAAAARgAAAhkF9eE0AAAASAX14TsF9eEzAAAAMAX14SsAAAIbAAAANAX14UIF9eFIAAAAGQX14RgF9eEqAAAAGgX14VgAAAIeAAAAHAX14VcAAAIfAAAAIgX14WQAAAIgAAAAIwAAAiIAAAIhAAAAJAX14SoF9eFzAAAAJAX14SsF9eFzAAAAEQAAAiQF9eEWAAAAFAAAAiUF9eEVAAAAIQAAAigAAAImAAAALAX14REAAAInAAAALQX14RMF9eEUAAAALAX14Q8AAAIpAAAALQX14Q8F9eEU" +} \ No newline at end of file diff --git a/services/s3/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a4d9d1b92847..000000000000 --- a/services/s3/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,12431 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Bucket": { - "required": false, - "documentation": "The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "ForcePathStyle": { - "builtIn": "AWS::S3::ForcePathStyle", - "required": true, - "default": false, - "documentation": "When true, force a path-style endpoint to be used where the bucket name is part of the path.", - "type": "boolean" - }, - "Accelerate": { - "builtIn": "AWS::S3::Accelerate", - "required": true, - "default": false, - "documentation": "When true, use S3 Accelerate. NOTE: Not all regions support S3 accelerate.", - "type": "boolean" - }, - "UseGlobalEndpoint": { - "builtIn": "AWS::S3::UseGlobalEndpoint", - "required": true, - "default": false, - "documentation": "Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.", - "type": "boolean" - }, - "UseObjectLambdaEndpoint": { - "required": false, - "documentation": "Internal parameter to use object lambda endpoint for an operation (eg: WriteGetObjectResponse)", - "type": "boolean" - }, - "Key": { - "required": false, - "documentation": "The S3 Key used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Key.", - "type": "string" - }, - "Prefix": { - "required": false, - "documentation": "The S3 Prefix used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 Prefix.", - "type": "string" - }, - "CopySource": { - "required": false, - "documentation": "The Copy Source used for Copy Object request. This is an optional parameter that will be set automatically for operations that are scoped to Copy Source.", - "type": "string" - }, - "DisableAccessPoints": { - "required": false, - "documentation": "Internal parameter to disable Access Point Buckets", - "type": "boolean" - }, - "DisableMultiRegionAccessPoints": { - "builtIn": "AWS::S3::DisableMultiRegionAccessPoints", - "required": true, - "default": false, - "documentation": "Whether multi-region access points (MRAP) should be disabled.", - "type": "boolean" - }, - "UseArnRegion": { - "builtIn": "AWS::S3::UseArnRegion", - "required": false, - "documentation": "When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN's region when constructing the endpoint instead of the client's configured region.", - "type": "boolean" - }, - "UseS3ExpressControlEndpoint": { - "required": false, - "documentation": "Internal parameter to indicate whether S3Express operation should use control plane, (ex. CreateBucket)", - "type": "boolean" - }, - "DisableS3ExpressSessionAuth": { - "required": false, - "documentation": "Parameter to indicate whether S3Express session auth should be disabled", - "type": "boolean" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Accelerate cannot be used with FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "error": "Cannot set dual-stack in combination with a custom endpoint.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "A custom endpoint cannot be combined with FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "A custom endpoint cannot be combined with S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "error": "Partition does not support FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 0, - 6, - true - ], - "assign": "bucketSuffix" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "bucketSuffix" - }, - "--x-s3" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3Express does not support S3 Accelerate.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 14, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 14, - 16, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 15, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 15, - 17, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 19, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 19, - 21, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 20, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 20, - 22, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 26, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 26, - 28, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized S3Express bucket name format.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 14, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 14, - 16, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 15, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 15, - 17, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 19, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 19, - 21, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 20, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 20, - 22, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 6, - 26, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 26, - 28, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized S3Express bucket name format.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 0, - 7, - true - ], - "assign": "accessPointSuffix" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "accessPointSuffix" - }, - "--xa-s3" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3Express does not support S3 Accelerate.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}/{uri_encoded_bucket}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableS3ExpressSessionAuth" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 15, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 15, - 17, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 16, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 16, - 18, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 20, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 20, - 22, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 21, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 21, - 23, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 27, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 27, - 29, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized S3Express bucket name format.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 15, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 15, - 17, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 16, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 16, - 18, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 20, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 20, - 22, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 21, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 21, - 23, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 7, - 27, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 27, - 29, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-fips-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3express-{s3expressAvailabilityZoneId}.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4-s3express", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized S3Express bucket name format.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "S3Express bucket name is not a valid virtual hostable name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "backend": "S3Express", - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 49, - 50, - true - ], - "assign": "hardwareType" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 8, - 12, - true - ], - "assign": "regionPrefix" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 0, - 7, - true - ], - "assign": "bucketAliasSuffix" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 32, - 49, - true - ], - "assign": "outpostId" - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "regionPartition" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "bucketAliasSuffix" - }, - "--op-s3" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "outpostId" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "hardwareType" - }, - "e" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "regionPrefix" - }, - "beta" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - } - ], - "error": "Expected a endpoint to be specified but no endpoint was found", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "https://{Bucket}.ec2.{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.ec2.s3-outposts.{Region}.{regionPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "hardwareType" - }, - "o" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "regionPrefix" - }, - "beta" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - } - ], - "error": "Expected a endpoint to be specified but no endpoint was found", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "https://{Bucket}.op-{outpostId}.{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.op-{outpostId}.s3-outposts.{Region}.{regionPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized hardware type: \"Expected hardware type o or e but got {hardwareType}\"", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Outposts Bucket alias - it must be a valid bucket name.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - } - ] - } - ], - "error": "Custom endpoint `{Endpoint}` was not a valid URI", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "ForcePathStyle" - }, - false - ] - }, - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "error": "S3 Accelerate cannot be used in this region", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-fips.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.dualstack.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.dualstack.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - false - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{Bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "isIp" - ] - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3-accelerate.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Bucket}.s3.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "url" - }, - "scheme" - ] - }, - "http" - ] - }, - { - "fn": "aws.isVirtualHostableS3Bucket", - "argv": [ - { - "ref": "Bucket" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "ForcePathStyle" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{Bucket}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "ForcePathStyle" - }, - false - ] - }, - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "bucketArn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "service" - ] - }, - "s3-object-lambda" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "accesspoint" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[1]" - ], - "assign": "accessPointName" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "accessPointName" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3 Object Lambda does not support Dual-stack", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3 Object Lambda does not support S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableAccessPoints" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableAccessPoints" - }, - true - ] - } - ], - "error": "Access points are not supported for this operation", - "type": "error" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[2]" - ] - } - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - } - ], - "assign": "bucketPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - "" - ] - } - ], - "error": "Invalid ARN: Missing account id", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "accessPointName" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{accessPointName}-{bucketArn#accountId}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-object-lambda.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: bucket ARN is missing a region", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Object Lambda ARNs only support `accesspoint` arn types, but found: `{arnType}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "accesspoint" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[1]" - ], - "assign": "accessPointName" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "accessPointName" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "accesspoint" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "DisableAccessPoints" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableAccessPoints" - }, - true - ] - } - ], - "error": "Access points are not supported for this operation", - "type": "error" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[2]" - ] - } - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - } - ], - "assign": "bucketPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketPartition" - }, - "name" - ] - }, - "{partitionResult#name}" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "service" - ] - }, - "s3" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "accessPointName" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "Access Points do not support S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint-fips.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.dualstack.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{accessPointName}-{bucketArn#accountId}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.s3-accesspoint.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN was not for the S3 service, found: {bucketArn#service}", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The ARN may only contain a single resource component after `accesspoint`.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "accessPointName" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3 MRAP does not support dual-stack", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "S3 MRAP does not support FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3 MRAP does not support S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "DisableMultiRegionAccessPoints" - }, - true - ] - } - ], - "error": "Invalid configuration: Multi-Region Access Point ARNs are disabled.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "mrapPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "mrapPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "partition" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{accessPointName}.accesspoint.s3-global.{mrapPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{mrapPartition#name}` but bucket referred to partition `{bucketArn#partition}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Access Point Name", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected a resource of the format `accesspoint:` but no name was provided", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "service" - ] - }, - "s3-outposts" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3 Outposts does not support Dual-stack", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "S3 Outposts does not support FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3 Outposts does not support S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[4]" - ] - } - ] - } - ], - "error": "Invalid Arn: Outpost Access Point ARN contains sub resources", - "type": "error" - }, - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[1]" - ], - "assign": "outpostId" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "outpostId" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - } - ], - "assign": "bucketPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[2]" - ], - "assign": "outpostType" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[3]" - ], - "assign": "accessPointName" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "outpostType" - }, - "accesspoint" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "accessPointName" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{accessPointName}-{bucketArn#accountId}.{outpostId}.s3-outposts.{bucketArn#region}.{bucketPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4a", - "signingName": "s3-outposts", - "signingRegionSet": [ - "*" - ] - }, - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The access point name may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointName}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Expected an outpost type `accesspoint`, found {outpostType}", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: expected an access point name", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected a 4-component resource", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN (`{Bucket}`) has `{bucketPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The outpost Id may only contain a-z, A-Z, 0-9 and `-`. Found: `{outpostId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The Outpost Id was not set", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Unrecognized format: {Bucket} (type: {arnType})", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "Bucket" - }, - 0, - 4, - false - ], - "assign": "arnPrefix" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnPrefix" - }, - "arn:" - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "Bucket" - } - ] - } - ] - } - ] - } - ], - "error": "Invalid ARN: `{Bucket}` was not a valid ARN", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "ForcePathStyle" - }, - true - ] - }, - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "Bucket" - } - ] - } - ], - "error": "Path-style addressing cannot be used with ARN buckets", - "type": "error" - }, - { - "conditions": [ - { - "fn": "uriEncode", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "uri_encoded_bucket" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#normalizedPath}{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://s3.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3.{Region}.{partitionResult#dnsSuffix}/{uri_encoded_bucket}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Path-style addressing cannot be used with S3 Accelerate", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseObjectLambdaEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseObjectLambdaEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3 Object Lambda does not support Dual-stack", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "Accelerate" - }, - true - ] - } - ], - "error": "S3 Object Lambda does not support S3 Accelerate", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-object-lambda-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3-object-lambda.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-object-lambda", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3-fips.dualstack.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3-fips.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3.dualstack.us-east-1.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://s3.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://s3.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "A region must be set when sending requests to S3.", - "type": "error" - } - ] -} \ No newline at end of file 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 41e585d59805..ef18bc4a9a91 100644 --- a/services/s3/src/main/resources/codegen-resources/service-2.json +++ b/services/s3/src/main/resources/codegen-resources/service-2.json @@ -1587,7 +1587,7 @@ {"shape":"InvalidRequest"}, {"shape":"AccessDenied"} ], - "documentation":"

    This operation is not supported for directory buckets or Amazon S3 on Outposts buckets.

    Updates the server-side encryption type of an existing encrypted object in a general purpose bucket. You can use the UpdateObjectEncryption operation to change encrypted objects from server-side encryption with Amazon S3 managed keys (SSE-S3) to server-side encryption with Key Management Service (KMS) keys (SSE-KMS), or to apply S3 Bucket Keys. You can also use the UpdateObjectEncryption operation to change the customer-managed KMS key used to encrypt your data so that you can comply with custom key-rotation standards.

    Using the UpdateObjectEncryption operation, you can atomically update the server-side encryption type of an existing object in a general purpose bucket without any data movement. The UpdateObjectEncryption operation uses envelope encryption to re-encrypt the data key used to encrypt and decrypt your object with your newly specified server-side encryption type. In other words, when you use the UpdateObjectEncryption operation, your data isn't copied, archived objects in the S3 Glacier Flexible Retrieval and S3 Glacier Deep Archive storage classes aren't restored, and objects in the S3 Intelligent-Tiering storage class aren't moved between tiers. Additionally, the UpdateObjectEncryption operation preserves all object metadata properties, including the storage class, creation date, last modified date, ETag, and checksum properties. For more information, see Updating server-side encryption for existing objects in the Amazon S3 User Guide.

    By default, all UpdateObjectEncryption requests that specify a customer-managed KMS key are restricted to KMS keys that are owned by the bucket owner's Amazon Web Services account. If you're using Organizations, you can request the ability to use KMS keys owned by other member accounts within your organization by contacting Amazon Web Services Support.

    Source objects that are unencrypted, or encrypted with either dual-layer server-side encryption with KMS keys (DSSE-KMS) or server-side encryption with customer-provided keys (SSE-C) aren't supported by this operation. Additionally, you cannot specify SSE-S3 encryption as the requested new encryption type UpdateObjectEncryption request.

    Permissions
    • To use the UpdateObjectEncryption operation, you must have the following permissions:

      • s3:PutObject

      • s3:UpdateObjectEncryption

      • kms:Encrypt

      • kms:Decrypt

      • kms:GenerateDataKey

      • kms:ReEncrypt*

    • If you're using Organizations, to use this operation with customer-managed KMS keys from other Amazon Web Services accounts within your organization, you must have the organizations:DescribeAccount permission.

    Errors
    • You might receive an InvalidRequest error for several reasons. Depending on the reason for the error, you might receive one of the following messages:

      • The UpdateObjectEncryption operation doesn't supported unencrypted source objects. Only source objects encrypted with SSE-S3 or SSE-KMS are supported.

      • The UpdateObjectEncryption operation doesn't support source objects with the encryption type DSSE-KMS or SSE-C. Only source objects encrypted with SSE-S3 or SSE-KMS are supported.

      • The UpdateObjectEncryption operation doesn't support updating the encryption type to DSSE-KMS or SSE-C. Modify the request to specify SSE-KMS for the updated encryption type, and then try again.

      • Requests that modify an object encryption configuration require Amazon Web Services Signature Version 4. Modify the request to use Amazon Web Services Signature Version 4, and then try again.

      • Requests that modify an object encryption configuration require a valid new encryption type. Valid values are SSEKMS. Modify the request to specify SSE-KMS for the updated encryption type, and then try again.

      • Requests that modify an object's encryption type to SSE-KMS require an Amazon Web Services KMS key Amazon Resource Name (ARN). Modify the request to specify a KMS key ARN, and then try again.

      • Requests that modify an object's encryption type to SSE-KMS require a valid Amazon Web Services KMS key Amazon Resource Name (ARN). Confirm that you have a correctly formatted KMS key ARN in your request, and then try again.

      • The BucketKeyEnabled value isn't valid. Valid values are true or false. Modify the request to specify a valid value, and then try again.

    • You might receive an AccessDenied error for several reasons. Depending on the reason for the error, you might receive one of the following messages:

      • The Amazon Web Services KMS key in the request must be owned by the same account as the bucket. Modify the request to specify a KMS key from the same account, and then try again.

      • The bucket owner's account was approved to make UpdateObjectEncryption requests that use any Amazon Web Services KMS key in their organization, but the bucket owner's account isn't part of an organization in Organizations. Make sure that the bucket owner's account and the specified KMS key belong to the same organization, and then try again.

      • The specified Amazon Web Services KMS key must be from the same organization in Organizations as the bucket. Specify a KMS key that belongs to the same organization as the bucket, and then try again.

      • The encryption type for the specified object can’t be updated because that object is protected by S3 Object Lock. If the object has a governance-mode retention period or a legal hold, you must first remove the Object Lock status on the object before you issue your UpdateObjectEncryption request. You can't use the UpdateObjectEncryption operation with objects that have an Object Lock compliance mode retention period applied to them.

    ", + "documentation":"

    This operation is not supported for directory buckets or Amazon S3 on Outposts buckets.

    Updates the server-side encryption type of an existing encrypted object in a general purpose bucket. You can use the UpdateObjectEncryption operation to change encrypted objects from server-side encryption with Amazon S3 managed keys (SSE-S3) to server-side encryption with Key Management Service (KMS) keys (SSE-KMS), or to apply S3 Bucket Keys. You can also use the UpdateObjectEncryption operation to change the customer-managed KMS key used to encrypt your data so that you can comply with custom key-rotation standards.

    Using the UpdateObjectEncryption operation, you can atomically update the server-side encryption type of an existing object in a general purpose bucket without any data movement. The UpdateObjectEncryption operation uses envelope encryption to re-encrypt the data key used to encrypt and decrypt your object with your newly specified server-side encryption type. In other words, when you use the UpdateObjectEncryption operation, your data isn't copied, archived objects in the S3 Glacier Flexible Retrieval and S3 Glacier Deep Archive storage classes aren't restored, and objects in the S3 Intelligent-Tiering storage class aren't moved between tiers. Additionally, the UpdateObjectEncryption operation preserves all object metadata properties, including the storage class, creation date, last modified date, ETag, and checksum properties. For more information, see Updating server-side encryption for existing objects in the Amazon S3 User Guide.

    By default, all UpdateObjectEncryption requests that specify a customer-managed KMS key are restricted to KMS keys that are owned by the bucket owner's Amazon Web Services account. If you're using Organizations, you can request the ability to use KMS keys owned by other member accounts within your organization by contacting Amazon Web Services Support.

    Source objects that are unencrypted, or encrypted with either dual-layer server-side encryption with KMS keys (DSSE-KMS) or server-side encryption with customer-provided keys (SSE-C) aren't supported by this operation. Additionally, you cannot specify SSE-S3 encryption as the requested new encryption type UpdateObjectEncryption request.

    Permissions
    • To use the UpdateObjectEncryption operation, you must have the following permissions:

      • s3:UpdateObjectEncryption

      • kms:Encrypt

      • kms:Decrypt

      • kms:GenerateDataKey

      • kms:ReEncrypt*

    • If you're using Organizations, to use this operation with customer-managed KMS keys from other Amazon Web Services accounts within your organization, you must have the organizations:DescribeAccount permission.

    Errors
    • You might receive an InvalidRequest error for several reasons. Depending on the reason for the error, you might receive one of the following messages:

      • The UpdateObjectEncryption operation doesn't supported unencrypted source objects. Only source objects encrypted with SSE-S3 or SSE-KMS are supported.

      • The UpdateObjectEncryption operation doesn't support source objects with the encryption type DSSE-KMS or SSE-C. Only source objects encrypted with SSE-S3 or SSE-KMS are supported.

      • The UpdateObjectEncryption operation doesn't support updating the encryption type to DSSE-KMS or SSE-C. Modify the request to specify SSE-KMS for the updated encryption type, and then try again.

      • Requests that modify an object encryption configuration require Amazon Web Services Signature Version 4. Modify the request to use Amazon Web Services Signature Version 4, and then try again.

      • Requests that modify an object encryption configuration require a valid new encryption type. Valid values are SSEKMS. Modify the request to specify SSE-KMS for the updated encryption type, and then try again.

      • Requests that modify an object's encryption type to SSE-KMS require an Amazon Web Services KMS key Amazon Resource Name (ARN). Modify the request to specify a KMS key ARN, and then try again.

      • Requests that modify an object's encryption type to SSE-KMS require a valid Amazon Web Services KMS key Amazon Resource Name (ARN). Confirm that you have a correctly formatted KMS key ARN in your request, and then try again.

      • The BucketKeyEnabled value isn't valid. Valid values are true or false. Modify the request to specify a valid value, and then try again.

    • You might receive an AccessDenied error for several reasons. Depending on the reason for the error, you might receive one of the following messages:

      • The Amazon Web Services KMS key in the request must be owned by the same account as the bucket. Modify the request to specify a KMS key from the same account, and then try again.

      • The bucket owner's account was approved to make UpdateObjectEncryption requests that use any Amazon Web Services KMS key in their organization, but the bucket owner's account isn't part of an organization in Organizations. Make sure that the bucket owner's account and the specified KMS key belong to the same organization, and then try again.

      • The specified Amazon Web Services KMS key must be from the same organization in Organizations as the bucket. Specify a KMS key that belongs to the same organization as the bucket, and then try again.

      • The encryption type for the specified object can’t be updated because that object is protected by S3 Object Lock. If the object has a governance-mode retention period or a legal hold, you must first remove the Object Lock status on the object before you issue your UpdateObjectEncryption request. You can't use the UpdateObjectEncryption operation with objects that have an Object Lock compliance mode retention period applied to them.

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":true @@ -3179,6 +3179,24 @@ "location":"header", "locationName":"x-amz-object-lock-legal-hold" }, + "ObjectLockEventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    The event hold status to apply to the object copy. Set to ON to enable or OFF to disable.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold" + }, + "ObjectLockEventHoldDurationDays":{ + "shape":"ObjectLockEventHoldDurationDays", + "documentation":"

    The event hold duration in days to apply to the object copy. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-days" + }, + "ObjectLockEventHoldDurationYears":{ + "shape":"ObjectLockEventHoldDurationYears", + "documentation":"

    The event hold duration in years to apply to the object copy. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-years" + }, "ExpectedBucketOwner":{ "shape":"AccountId", "documentation":"

    The account ID of the expected destination bucket owner. If the account ID that you provide does not match the actual owner of the destination bucket, the request fails with the HTTP status code 403 Forbidden (access denied).

    ", @@ -3210,7 +3228,7 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The Base64 encoded, 32-bit CRC32 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.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only present if the checksum was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", @@ -3430,7 +3448,7 @@ "members":{ "Location":{ "shape":"Location", - "documentation":"

    A forward slash followed by the name of the bucket.

    ", + "documentation":"

    A forward slash followed by the name of the bucket for all account regional namespace buckets and all global general purpose buckets created in us-east-1. For example, /amzn-s3-demo-bucket. For global general purpose buckets created in other Amazon Web Services Regions, the Location field is the global endpoint URL. For example, http://amzn-s3-demo-bucket.s3.amazonaws.com/.

    ", "location":"header", "locationName":"Location" }, @@ -3774,6 +3792,24 @@ "location":"header", "locationName":"x-amz-object-lock-legal-hold" }, + "ObjectLockEventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    Specifies the event hold status to apply to the uploaded object. Set to ON to enable or OFF to disable.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold" + }, + "ObjectLockEventHoldDurationDays":{ + "shape":"ObjectLockEventHoldDurationDays", + "documentation":"

    Specifies the event hold duration in days to apply to the uploaded object. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-days" + }, + "ObjectLockEventHoldDurationYears":{ + "shape":"ObjectLockEventHoldDurationYears", + "documentation":"

    Specifies the event hold duration in years to apply to the uploaded object. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-years" + }, "ExpectedBucketOwner":{ "shape":"AccountId", "documentation":"

    The account ID of the expected bucket owner. If the account ID that you provide does not match the actual owner of the bucket, the request fails with the HTTP status code 403 Forbidden (access denied).

    ", @@ -3906,6 +3942,10 @@ "Years":{ "shape":"Years", "documentation":"

    The number of years that you want to specify for the default retention period. Must be used with Mode.

    " + }, + "DefaultEventHold":{ + "shape":"EventHoldDuration", + "documentation":"

    The default event hold duration to be applied to new objects placed in the specified bucket. When configured, new objects will automatically have an event hold enabled with this duration.

    " } }, "documentation":"

    The container element for optionally specifying the default Object Lock retention settings for new objects placed in the specified bucket.

    • The DefaultRetention settings require both a mode and a period.

    • The DefaultRetention period can be either Days or Years but you must select one. You cannot specify Days and Years at the same time.

    " @@ -4772,7 +4812,7 @@ "documentation":"

    The error message contains a generic description of the error condition in English. It is intended for a human audience. Simple programs display the message directly to the end user if they encounter an error condition they don't know how or don't care to handle. Sophisticated programs with more exhaustive error handling and proper internationalization are more likely to ignore the error message.

    " } }, - "documentation":"

    Container for all error elements.

    " + "documentation":"

    For information about using the Amazon S3 API—including error handling—see the Amazon S3 Developer Guide.

    Container for all error elements.

    " }, "ErrorCode":{"type":"string"}, "ErrorDetails":{ @@ -4839,7 +4879,8 @@ "s3:ObjectTagging:Delete", "s3:ObjectAnnotation:*", "s3:ObjectAnnotation:Put", - "s3:ObjectAnnotation:Delete" + "s3:ObjectAnnotation:Delete", + "s3:ObjectRetention:Put" ] }, "EventBridgeConfiguration":{ @@ -4847,6 +4888,20 @@ "members":{}, "documentation":"

    A container for specifying the configuration for Amazon EventBridge.

    " }, + "EventHoldDuration":{ + "type":"structure", + "members":{ + "Days":{ + "shape":"Days", + "documentation":"

    The number of days for the event hold duration. The minimum value is 1 and the maximum value is 36,500.

    " + }, + "Years":{ + "shape":"Years", + "documentation":"

    The number of years for the event hold duration. The minimum value is 1 and the maximum value is 100.

    " + } + }, + "documentation":"

    Contains the event hold duration configuration, specified in either days or years.

    " + }, "EventList":{ "type":"list", "member":{"shape":"Event"}, @@ -4889,7 +4944,7 @@ "type":"boolean", "box":true }, - "Expires":{"type":"timestamp"}, + "Expires":{"type":"string"}, "ExposeHeader":{"type":"string"}, "ExposeHeaders":{ "type":"list", @@ -6236,7 +6291,7 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The Base64 encoded, 32-bit CRC32 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.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC32 checksum of the object. This checksum is only present if the checksum 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" }, @@ -6442,6 +6497,24 @@ "documentation":"

    Indicates whether this object has an active legal hold. This field is only returned if you have permission to view an object's legal hold status.

    This functionality is not supported for directory buckets.

    ", "location":"header", "locationName":"x-amz-object-lock-legal-hold" + }, + "ObjectLockEventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    The event hold status for this object. This header is only returned if the requester has the s3:GetObjectRetention permission.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold" + }, + "ObjectLockEventHoldDurationDays":{ + "shape":"ObjectLockEventHoldDurationDays", + "documentation":"

    The event hold duration in days for this object. Only returned when the event hold is enabled.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-days" + }, + "ObjectLockEventHoldDurationYears":{ + "shape":"ObjectLockEventHoldDurationYears", + "documentation":"

    The event hold duration in years for this object. Only returned when the event hold is enabled.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-years" } }, "payload":"Body" @@ -7152,6 +7225,24 @@ "documentation":"

    Specifies whether a legal hold is in effect for this object. This header is only returned if the requester has the s3:GetObjectLegalHold permission. This header is not returned if the specified version of this object has never had a legal hold applied. For more information about S3 Object Lock, see Object Lock.

    This functionality is not supported for directory buckets.

    ", "location":"header", "locationName":"x-amz-object-lock-legal-hold" + }, + "ObjectLockEventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    The event hold status for this object. This header is only returned if the requester has the s3:GetObjectRetention permission.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold" + }, + "ObjectLockEventHoldDurationDays":{ + "shape":"ObjectLockEventHoldDurationDays", + "documentation":"

    The event hold duration in days for this object. Only returned when the event hold is enabled.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-days" + }, + "ObjectLockEventHoldDurationYears":{ + "shape":"ObjectLockEventHoldDurationYears", + "documentation":"

    The event hold duration in years for this object. Only returned when the event hold is enabled.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-years" } } }, @@ -7614,6 +7705,8 @@ "ObjectLockRetainUntilDate", "ObjectLockMode", "ObjectLockLegalHoldStatus", + "ObjectLockEventHoldStatus", + "ObjectLockEventHoldDuration", "IntelligentTieringAccessTier", "BucketKeyStatus", "ChecksumAlgorithm", @@ -9619,6 +9712,15 @@ "type":"boolean", "box":true }, + "ObjectLockEventHold":{ + "type":"string", + "enum":[ + "ON", + "OFF" + ] + }, + "ObjectLockEventHoldDurationDays":{"type":"integer"}, + "ObjectLockEventHoldDurationYears":{"type":"integer"}, "ObjectLockLegalHold":{ "type":"structure", "members":{ @@ -9657,6 +9759,14 @@ "RetainUntilDate":{ "shape":"Date", "documentation":"

    The date on which this Object Lock Retention will expire.

    " + }, + "EventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    The event hold status for the object. Set to ON to enable an event hold or OFF to disable it.

    " + }, + "EventHoldDuration":{ + "shape":"EventHoldDuration", + "documentation":"

    The event hold duration for the object. Specifies how long the object remains protected after the event hold is released.

    " } }, "documentation":"

    A Retention configuration for an object.

    " @@ -9673,7 +9783,7 @@ "members":{ "DefaultRetention":{ "shape":"DefaultRetention", - "documentation":"

    The default Object Lock retention mode and period that you want to apply to new objects placed in the specified bucket. Bucket settings require both a mode and a period. The period can be either Days or Years but you must select one. You cannot specify Days and Years at the same time.

    " + "documentation":"

    The default Object Lock retention settings for new objects in this bucket. You can specify:

    • A default retention period, by using Days or Years.

    • A default event hold duration, by using DefaultEventHold. This setting also uses days or years.

    You can set one or both. You cannot use days and years in the same setting.

    " } }, "documentation":"

    The container element for an Object Lock rule.

    " @@ -9776,7 +9886,9 @@ "SNOW", "EXPRESS_ONEZONE", "FSX_OPENZFS", - "FSX_ONTAP" + "FSX_ONTAP", + "AWS_BACKUP_WARM", + "AWS_BACKUP_LOW_COST_WARM" ] }, "ObjectVersion":{ @@ -11871,6 +11983,24 @@ "location":"header", "locationName":"x-amz-object-lock-legal-hold" }, + "ObjectLockEventHold":{ + "shape":"ObjectLockEventHold", + "documentation":"

    Specifies the event hold status to apply to this object. Set to ON to enable or OFF to disable.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold" + }, + "ObjectLockEventHoldDurationDays":{ + "shape":"ObjectLockEventHoldDurationDays", + "documentation":"

    Specifies the event hold duration in days to apply to this object. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-days" + }, + "ObjectLockEventHoldDurationYears":{ + "shape":"ObjectLockEventHoldDurationYears", + "documentation":"

    Specifies the event hold duration in years to apply to this object. You cannot specify a duration in both days and years.

    This functionality is not supported for directory buckets.

    ", + "location":"header", + "locationName":"x-amz-object-lock-event-hold-duration-years" + }, "ExpectedBucketOwner":{ "shape":"AccountId", "documentation":"

    The account ID of the expected bucket owner. If the account ID that you provide does not match the actual owner of the bucket, the request fails with the HTTP status code 403 Forbidden (access denied).

    ", @@ -13023,6 +13153,7 @@ "enum":[ "AES256", "aws:fsx", + "aws:backup", "aws:kms", "aws:kms:dsse" ] @@ -13221,7 +13352,9 @@ "SNOW", "EXPRESS_ONEZONE", "FSX_OPENZFS", - "FSX_ONTAP" + "FSX_ONTAP", + "AWS_BACKUP_WARM", + "AWS_BACKUP_LOW_COST_WARM" ] }, "StorageClassAnalysis":{ @@ -13448,7 +13581,7 @@ }, "Days":{ "shape":"Days", - "documentation":"

    Indicates the number of days after creation when objects are transitioned to the specified storage class. If the specified storage class is INTELLIGENT_TIERING, GLACIER_IR, GLACIER, or DEEP_ARCHIVE, valid values are 0 or positive integers. If the specified storage class is STANDARD_IA or ONEZONE_IA, valid values are positive integers greater than 30. Be aware that some storage classes have a minimum storage duration and that you're charged for transitioning objects before their minimum storage duration. For more information, see Constraints and considerations for transitions in the Amazon S3 User Guide.

    " + "documentation":"

    Indicates the number of days after creation when objects are transitioned to the specified storage class. The value can be 0 or any positive integer. Be aware that some storage classes have a minimum storage duration and that you're charged for transitioning objects before their minimum storage duration. For more information, see Constraints and considerations for transitions in the Amazon S3 User Guide.

    " }, "StorageClass":{ "shape":"TransitionStorageClass", @@ -14467,7 +14600,7 @@ "box":true } }, - "documentation":"

    ", + "documentation":"

    For information about using the Amazon S3 API—including authentication, signing requests, code examples, and error handling—see the Amazon S3 Developer Guide.

    Welcome to the Amazon S3 API Reference. This guide explains the Amazon Simple Storage Service (Amazon S3) application programming interface (API).

    Welcome to the Amazon S3 API Reference. This guide explains the Amazon Simple Storage Service (Amazon S3) application programming interface (API).

    You can use any toolkit that supports HTTP to use the REST API. You can even use a browser to fetch objects, as long as they are anonymously readable.

    The REST API uses the standard HTTP headers and status codes, so that standard browsers and toolkits work as expected. In some areas, we have added functionality to HTTP (for example, we added headers to support access control). In these cases, we have done our best to add the new functionality in a way that matched the style of standard HTTP usage.

    The current version of the Amazon S3 API is 2006-03-01.

    Amazon S3 supports the REST API.

    Support for SOAP over HTTP is deprecated, but it is still available over HTTPS. However, new Amazon S3 features will not be supported for SOAP. We recommend that you use either this REST API or the Amazon Web Services SDKs.

    ", "clientContextParams":{ "Accelerate":{ "documentation":"Enables this client to use S3 Transfer Acceleration endpoints.", diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/AuthSchemeProviderOverrideTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/AuthSchemeProviderOverrideTest.java new file mode 100644 index 000000000000..447c21641fb1 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/AuthSchemeProviderOverrideTest.java @@ -0,0 +1,150 @@ +/* + * 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; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicInteger; +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.SdkPlugin; +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.regions.Region; +import software.amazon.awssdk.services.s3.auth.scheme.S3AuthSchemeProvider; + +/** + * Verifies that request-level plugin overrides for auth scheme provider and region + * are respected during auth scheme resolution. + */ +class AuthSchemeProviderOverrideTest { + + @Test + void requestPluginOverridesAuthSchemeProvider_isUsed() { + AtomicInteger defaultProviderCallCount = new AtomicInteger(0); + AtomicInteger overrideProviderCallCount = new AtomicInteger(0); + + S3AuthSchemeProvider defaultProvider = params -> { + defaultProviderCallCount.incrementAndGet(); + return S3AuthSchemeProvider.defaultProvider().resolveAuthScheme(params); + }; + + S3AuthSchemeProvider overrideProvider = params -> { + overrideProviderCallCount.incrementAndGet(); + return S3AuthSchemeProvider.defaultProvider().resolveAuthScheme(params); + }; + + S3Client client = S3Client.builder() + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .addPlugin(authSchemeProviderPlugin(defaultProvider)) + .overrideConfiguration(c -> c.addExecutionInterceptor(new AbortInterceptor())) + .build(); + + // Request with plugin that overrides auth scheme provider + assertThatThrownBy(() -> client.getObject(r -> { + r.overrideConfiguration(c -> c.addPlugin(authSchemeProviderPlugin(overrideProvider))); + r.key("key").bucket("bucket"); + })).hasMessageContaining("aborted"); + + // The override provider should have been called, not the default + assertThat(overrideProviderCallCount.get()).isGreaterThan(0); + assertThat(defaultProviderCallCount.get()).isEqualTo(0); + } + + @Test + void noRequestPluginOverride_usesClientProvider() { + AtomicInteger defaultProviderCallCount = new AtomicInteger(0); + + S3AuthSchemeProvider defaultProvider = params -> { + defaultProviderCallCount.incrementAndGet(); + return S3AuthSchemeProvider.defaultProvider().resolveAuthScheme(params); + }; + + S3Client client = S3Client.builder() + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .addPlugin(authSchemeProviderPlugin(defaultProvider)) + .overrideConfiguration(c -> c.addExecutionInterceptor(new AbortInterceptor())) + .build(); + + // Request without override — should use client-level provider + assertThatThrownBy(() -> client.getObject(r -> { + r.key("key").bucket("bucket"); + })).hasMessageContaining("aborted"); + + assertThat(defaultProviderCallCount.get()).isGreaterThan(0); + } + + @Test + void requestPluginOverridesRegion_isUsedInAuthSchemeResolution() { + AtomicReference capturedRegion = new AtomicReference<>(); + + S3AuthSchemeProvider capturingProvider = params -> { + capturedRegion.set(params.region()); + return S3AuthSchemeProvider.defaultProvider().resolveAuthScheme(params); + }; + + S3Client client = S3Client.builder() + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .authSchemeProvider(capturingProvider) + .overrideConfiguration(c -> c.addExecutionInterceptor(new AbortInterceptor())) + .build(); + + // Request with plugin that overrides region to us-west-2 + assertThatThrownBy(() -> client.getObject(r -> { + r.overrideConfiguration(c -> c.addPlugin(regionOverridePlugin(Region.US_WEST_2))); + r.key("key").bucket("bucket"); + })).hasMessageContaining("aborted"); + + // The auth scheme params should have received the overridden region + assertThat(capturedRegion.get()).isEqualTo(Region.US_WEST_2); + } + + private SdkPlugin regionOverridePlugin(Region region) { + return config -> { + S3ServiceClientConfiguration.Builder s3Config = + (S3ServiceClientConfiguration.Builder) config; + s3Config.region(region); + }; + } + + private SdkPlugin authSchemeProviderPlugin(S3AuthSchemeProvider provider) { + return config -> { + S3ServiceClientConfiguration.Builder s3Config = + (S3ServiceClientConfiguration.Builder) config; + s3Config.authSchemeProvider(provider); + }; + } + + /** + * Interceptor that aborts the request before transmission so we don't need a real endpoint. + */ + static class AbortInterceptor implements ExecutionInterceptor { + @Override + public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + throw new RuntimeException("aborted"); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideEndpointResolutionTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideEndpointResolutionTest.java index 013917270961..ab201a8edf77 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideEndpointResolutionTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideEndpointResolutionTest.java @@ -222,6 +222,25 @@ public static Collection testCases() { .setExpectedSigningServiceName("s3") .setExpectedSigningRegion(Region.US_WEST_2)); + // An override that spells out the protocol's own default port must still have the rules-engine-resolved host + // applied. The port ends up in the resolved authority, but getUri() omits it again because it is the standard + // port for the scheme. + cases.add(new TestCase().setCaseName("normal bucket with the default https port spelled out") + .setGetObjectBucketName("bucketname") + .setEndpointUrl("https://beta.example.com:443") + .setClientRegion(Region.US_WEST_2) + .setExpectedEndpoint("https://bucketname.beta.example.com/object") + .setExpectedSigningServiceName("s3") + .setExpectedSigningRegion(Region.US_WEST_2)); + + cases.add(new TestCase().setCaseName("normal bucket with the default http port spelled out") + .setGetObjectBucketName("bucketname") + .setEndpointUrl("http://beta.example.com:80") + .setClientRegion(Region.US_WEST_2) + .setExpectedEndpoint("http://bucketname.beta.example.com/object") + .setExpectedSigningServiceName("s3") + .setExpectedSigningRegion(Region.US_WEST_2)); + cases.add(new TestCase().setCaseName("access point") .setGetObjectBucketName("arn:aws:s3:us-west-2:123456789012:accesspoint:myendpoint") .setEndpointUrl("https://beta.example.com") diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideInterceptorResolutionTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideInterceptorResolutionTest.java new file mode 100644 index 000000000000..286482a219ac --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/EndpointOverrideInterceptorResolutionTest.java @@ -0,0 +1,242 @@ +/* + * 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; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.UncheckedIOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.util.function.UnaryOperator; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.HttpExecuteResponse; +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.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; +import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient; + +/** + * End-to-end coverage of how {@code endpointOverride} interacts with a customer {@link ExecutionInterceptor} that + * modifies the HTTP request in {@code modifyHttpRequest}. + * + *

    S3 is used because its endpoint rules rewrite the host taken + * from an {@code endpointOverride}: virtual-host addressing resolves {@code {Bucket}.{url#authority}}. That makes the + * assertions here able to distinguish "the rules-engine host was applied" from "the interceptor's host was preserved", + * which a service whose rules pass the override through verbatim could not. Additionally, S3 endpoint rules + * modify the path which we also need to test with. + * + *

    The contract being pinned down, as implemented by {@code EndpointResolutionStage}: + *

      + *
    • If no interceptor changed the endpoint, the resolved scheme, host and port are applied.
    • + *
    • If an interceptor changed the host, scheme or port, that change wins and the resolved scheme/host/port are + * not applied — but the resolved path still is.
    • + *
    • An override that spells out the protocol's default port is not a change.
    • + *
    + */ +class EndpointOverrideInterceptorResolutionTest { + + private static final String BUCKET = "bucketname"; + + // The rules engine rewrites the override's authority to "." for virtual-host addressing. + private static final URI OVERRIDE = URI.create("https://beta.example.com"); + private static final String RESOLVED_HOST = BUCKET + ".beta.example.com"; + + @Test + void noInterceptor_appliesResolvedHost() { + SdkHttpRequest wireRequest = sync(OVERRIDE, null); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + assertThat(wireRequest.protocol()).isEqualTo("https"); + assertThat(wireRequest.getUri()).isEqualTo(URI.create("https://" + RESOLVED_HOST)); + } + + @Test + void noInterceptor_overrideSpellsOutDefaultPort_stillAppliesResolvedHost() { + SdkHttpRequest wireRequest = sync(URI.create("https://beta.example.com:443"), null); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + assertThat(wireRequest.port()).isEqualTo(443); + } + + @Test + void noInterceptor_overrideSpellsOutDefaultHttpPort_stillAppliesResolvedHost() { + SdkHttpRequest wireRequest = sync(URI.create("http://beta.example.com:80"), null); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + assertThat(wireRequest.port()).isEqualTo(80); + } + + @Test + void noInterceptor_overrideWithNonDefaultPort_appliesResolvedHostAndKeepsPort() { + SdkHttpRequest wireRequest = sync(URI.create("https://beta.example.com:8443"), null); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + assertThat(wireRequest.port()).isEqualTo(8443); + } + + @Test + void interceptorReturnsRequestUnchanged_appliesResolvedHost() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + } + + @Test + void interceptorAddsHeaderOnly_appliesResolvedHost() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r.toBuilder().putHeader("x-custom", "value").build()); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + assertThat(wireRequest.firstMatchingHeader("x-custom")).hasValue("value"); + } + + @Test + void interceptorRestatesTheSameEndpoint_appliesResolvedHost() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r.toBuilder() + .protocol(r.protocol()) + .host(r.host()) + .port(r.port()) + .build()); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + } + + @Test + void interceptorChangesHost_hostWinsOverResolvedEndpoint() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r.toBuilder().host("interceptor.example.com").build()); + + assertThat(wireRequest.host()).isEqualTo("interceptor.example.com"); + assertThat(wireRequest.protocol()).isEqualTo("https"); + } + + @Test + void interceptorChangesScheme_schemeWinsOverResolvedEndpoint() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r.toBuilder().protocol("http").port(80).build()); + + assertThat(wireRequest.protocol()).isEqualTo("http"); + assertThat(wireRequest.host()).isEqualTo("beta.example.com"); + } + + @Test + void interceptorChangesPort_portWinsOverResolvedEndpoint() { + SdkHttpRequest wireRequest = sync(OVERRIDE, r -> r.toBuilder().port(9999).build()); + + assertThat(wireRequest.port()).isEqualTo(9999); + assertThat(wireRequest.host()).isEqualTo("beta.example.com"); + } + + @Test + void interceptorChangesHost_resolvedPathIsStillApplied() { + // The override carries a path, so the rules engine prefixes it. That path must survive even though the + // interceptor's host suppresses the resolved host. + SdkHttpRequest wireRequest = sync(URI.create("https://beta.example.com/path"), + r -> r.toBuilder().host("interceptor.example.com").build()); + + assertThat(wireRequest.host()).isEqualTo("interceptor.example.com"); + assertThat(wireRequest.encodedPath()).startsWith("/path"); + } + + @Test + void async_overrideSpellsOutDefaultPort_stillAppliesResolvedHost() { + SdkHttpRequest wireRequest = async(URI.create("https://beta.example.com:443"), null); + + assertThat(wireRequest.host()).isEqualTo(RESOLVED_HOST); + } + + @Test + void async_interceptorChangesHost_hostWinsOverResolvedEndpoint() { + SdkHttpRequest wireRequest = async(OVERRIDE, r -> r.toBuilder().host("interceptor.example.com").build()); + + assertThat(wireRequest.host()).isEqualTo("interceptor.example.com"); + } + + // --------------------------------------------------------------------------------------------------------- + + /** Runs a listObjects against a mocked HTTP client and returns the request that reached the wire. */ + private SdkHttpRequest sync(URI endpointOverride, UnaryOperator modifyHttpRequest) { + try (MockSyncHttpClient httpClient = new MockSyncHttpClient()) { + httpClient.stubNextResponse(listObjectsResponse()); + S3Client client = S3Client.builder() + .region(Region.US_WEST_2) + .credentialsProvider(credentials()) + .endpointOverride(endpointOverride) + .httpClient(httpClient) + .overrideConfiguration(c -> c.addExecutionInterceptor( + new EndpointModifyingInterceptor(modifyHttpRequest))) + .build(); + + client.listObjects(r -> r.bucket(BUCKET)); + return httpClient.getLastRequest(); + } + } + + private SdkHttpRequest async(URI endpointOverride, UnaryOperator modifyHttpRequest) { + try (MockAsyncHttpClient httpClient = new MockAsyncHttpClient()) { + httpClient.stubNextResponse(listObjectsResponse()); + S3AsyncClient client = S3AsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(credentials()) + .endpointOverride(endpointOverride) + .httpClient(httpClient) + .overrideConfiguration(c -> c.addExecutionInterceptor( + new EndpointModifyingInterceptor(modifyHttpRequest))) + .build(); + + client.listObjects(r -> r.bucket(BUCKET)).join(); + return httpClient.getLastRequest(); + } + } + + private static HttpExecuteResponse listObjectsResponse() { + try { + return S3MockUtils.mockListObjectsResponse(); + } catch (UnsupportedEncodingException e) { + throw new UncheckedIOException(e); + } + } + + private static StaticCredentialsProvider credentials() { + return StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")); + } + + /** + * A customer-style interceptor. Also asserts that the pre-modify endpoint snapshot is visible here and describes + * the request as it was marshalled, before endpoint resolution ran. + */ + private static final class EndpointModifyingInterceptor implements ExecutionInterceptor { + private final UnaryOperator modifyHttpRequest; + + private EndpointModifyingInterceptor(UnaryOperator modifyHttpRequest) { + this.modifyHttpRequest = modifyHttpRequest; + } + + @Override + public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes attrs) { + assertThat(attrs.getAttribute(SdkInternalExecutionAttribute.HTTP_REQUEST_ENDPOINT_BEFORE_MODIFY)) + .as("the pre-modify endpoint snapshot must be readable from modifyHttpRequest") + .isNotNull() + .satisfies(endpoint -> assertThat(endpoint.host()).isEqualTo(context.httpRequest().host())); + + return modifyHttpRequest == null ? context.httpRequest() + : modifyHttpRequest.apply(context.httpRequest()); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/InvalidRegionTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/InvalidRegionTest.java index 4eef66bf2e22..7831a78c17eb 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/InvalidRegionTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/InvalidRegionTest.java @@ -32,9 +32,7 @@ public void invalidS3UtilitiesRegionAtClientGivesHelpfulMessage() { assertThatThrownBy(() -> utilities.getUrl(r -> r.bucket("foo").key("bar"))) .isInstanceOf(SdkClientException.class) - .hasMessageContaining("US_EAST_1") - .hasMessageContaining("region") - .hasMessageContaining("us-east-1"); + .hasMessageContaining("Invalid region"); } @Test @@ -43,9 +41,7 @@ public void invalidS3UtilitiesRegionAtRequestGivesHelpfulMessage() { assertThatThrownBy(() -> utilities.getUrl(r -> r.bucket("foo").key("bar").region(Region.of("US_WEST_2")))) .isInstanceOf(SdkClientException.class) - .hasMessageContaining("US_WEST_2") - .hasMessageContaining("region") - .hasMessageContaining("us-west-2"); + .hasMessageContaining("Invalid region"); } @Test @@ -77,7 +73,8 @@ public void invalidS3ArnRegionAtRequestGivesHelpfulMessage() { public void invalidS3PresignerRegionAtClientGivesHelpfulMessage() { assertThatThrownBy(() -> S3Presigner.builder().region(Region.of("US_EAST_1")).build()) .isInstanceOf(SdkClientException.class) - .hasMessageContaining("Configured region (US_EAST_1) and tags ([]) resulted in an invalid URI"); + .hasMessageContaining("Configured region (US_EAST_1)") + .hasMessageContaining("invalid URI"); } @Test diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/crt/CrtDownloadErrorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/crt/CrtDownloadErrorTest.java index e7c26f5469ac..2a345298a010 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/crt/CrtDownloadErrorTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/crt/CrtDownloadErrorTest.java @@ -15,27 +15,39 @@ package software.amazon.awssdk.services.s3.crt; +import static com.github.tomakehurst.wiremock.client.WireMock.anyRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; import static com.github.tomakehurst.wiremock.client.WireMock.get; import static com.github.tomakehurst.wiremock.client.WireMock.head; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +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 static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; import com.github.tomakehurst.wiremock.junit5.WireMockTest; import java.net.URI; import java.nio.charset.StandardCharsets; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; 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 org.junit.jupiter.api.Timeout; +import org.junit.jupiter.api.io.TempDir; +import software.amazon.awssdk.core.FileTransformerConfiguration; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.crt.Log; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.S3Exception; @WireMockTest @@ -44,6 +56,8 @@ public class CrtDownloadErrorTest { private static final String BUCKET = "my-bucket"; private static final String KEY = "my-key"; private S3AsyncClient s3; + @TempDir + private Path tempDir; @BeforeAll public static void setUpBeforeAll() { @@ -120,6 +134,60 @@ public void getObject_headObjectOk_getObjectOk_operationSucceeds() { assertThat(objectContent.getBytes(StandardCharsets.UTF_8)).isEqualTo(content); } + @Test + public void getObjectToPath_success_writesFile() throws Exception { + byte[] content = "hello".getBytes(StandardCharsets.UTF_8); + stubSuccessfulDownload(content); + Path destination = tempDir.resolve("download"); + + s3.getObject(r -> r.bucket(BUCKET).key(KEY), destination).join(); + + assertThat(Files.readAllBytes(destination)).isEqualTo(content); + } + + @Test + public void getObjectWithReplaceTransformer_existingFile_replacesFile() throws Exception { + byte[] content = "hello".getBytes(StandardCharsets.UTF_8); + stubSuccessfulDownload(content); + Path destination = tempDir.resolve("download"); + Files.write(destination, "original".getBytes(StandardCharsets.UTF_8)); + + s3.getObject(r -> r.bucket(BUCKET).key(KEY), + AsyncResponseTransformer.toFile( + destination, FileTransformerConfiguration.defaultCreateOrReplaceExisting())).join(); + + assertThat(Files.readAllBytes(destination)).isEqualTo(content); + } + + @Test + public void getObjectToPath_existingFile_failsAsynchronouslyAndPreservesFile() throws Exception { + byte[] content = "hello".getBytes(StandardCharsets.UTF_8); + stubSuccessfulDownload(content); + Path destination = tempDir.resolve("download"); + byte[] originalContent = "original".getBytes(StandardCharsets.UTF_8); + Files.write(destination, originalContent); + + CompletableFuture future = + assertDoesNotThrow(() -> s3.getObject(r -> r.bucket(BUCKET).key(KEY), destination)); + + assertThatThrownBy(future::join) + .hasRootCauseInstanceOf(FileAlreadyExistsException.class) + .hasRootCauseMessage(destination.toString()); + assertThat(Files.readAllBytes(destination)).isEqualTo(originalContent); + verify(exactly(0), anyRequestedFor(anyUrl())); + } + + @Test + public void getObjectToPath_failedDownload_deletesFile() { + String requestPath = String.format("/%s/%s", BUCKET, KEY); + stubFor(head(urlPathEqualTo(requestPath)).willReturn(WireMock.aResponse().withStatus(404))); + Path destination = tempDir.resolve("download"); + + assertThatThrownBy(s3.getObject(r -> r.bucket(BUCKET).key(KEY), destination)::join) + .hasCauseInstanceOf(S3Exception.class); + assertThat(destination).doesNotExist(); + } + @Test public void getObject_headObjectThrows_operationThrows() { String path = String.format("/%s/%s", BUCKET, KEY); @@ -132,4 +200,15 @@ public void getObject_headObjectThrows_operationThrows() { .hasCauseInstanceOf(S3Exception.class) .hasMessageContaining("Status Code: 403"); } + + private void stubSuccessfulDownload(byte[] content) { + String path = String.format("/%s/%s", BUCKET, KEY); + stubFor(head(urlPathEqualTo(path)) + .willReturn(WireMock.aResponse() + .withStatus(200) + .withHeader("ETag", "etag") + .withHeader("Content-Length", Integer.toString(content.length)))); + stubFor(get(urlPathEqualTo(path)) + .willReturn(WireMock.aResponse().withStatus(200).withBody(content))); + } } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactoryTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactoryTest.java new file mode 100644 index 000000000000..6c4dcdd1390e --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/authscheme/DynamicEndpointAuthSchemeFactoryTest.java @@ -0,0 +1,185 @@ +/* + * 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.endpoints.authscheme; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; +import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; +import software.amazon.awssdk.core.exception.SdkClientException; + +/** + * Tests for {@link DynamicEndpointAuthSchemeFactory}. + * + *

    The generated S3 endpoint provider calls this factory as + * {@code DynamicEndpointAuthSchemeFactory.builder().disableDoubleEncoding(..).signingName(..).signingRegion(..).create(name)}, + * where {@code name} is resolved at runtime to either {@code sigv4} or {@code sigv4-s3express}. These tests pin that contract. + */ +class DynamicEndpointAuthSchemeFactoryTest { + + @Test + void create_sigv4_returnsSigV4AuthSchemeWithPropertiesApplied() { + EndpointAuthScheme scheme = DynamicEndpointAuthSchemeFactory.builder() + .disableDoubleEncoding(true) + .signingName("s3") + .signingRegion("us-west-2") + .create("sigv4"); + + assertThat(scheme).isInstanceOf(SigV4AuthScheme.class); + SigV4AuthScheme sigv4 = (SigV4AuthScheme) scheme; + assertThat(sigv4.name()).isEqualTo("sigv4"); + assertThat(sigv4.schemeId()).isEqualTo("aws.auth#sigv4"); + assertThat(sigv4.signingName()).isEqualTo("s3"); + assertThat(sigv4.signingRegion()).isEqualTo("us-west-2"); + assertThat(sigv4.disableDoubleEncoding()).isTrue(); + assertThat(sigv4.isDisableDoubleEncodingSet()).isTrue(); + } + + @Test + void create_s3Express_returnsS3ExpressAuthSchemeWithPropertiesApplied() { + EndpointAuthScheme scheme = DynamicEndpointAuthSchemeFactory.builder() + .disableDoubleEncoding(true) + .signingName("s3express") + .signingRegion("us-west-2") + .create("sigv4-s3express"); + + assertThat(scheme).isInstanceOf(S3ExpressEndpointAuthScheme.class); + S3ExpressEndpointAuthScheme s3Express = (S3ExpressEndpointAuthScheme) scheme; + assertThat(s3Express.name()).isEqualTo("sigv4-s3express"); + assertThat(s3Express.schemeId()).isEqualTo("aws.auth#sigv4-s3express"); + assertThat(s3Express.signingName()).isEqualTo("s3express"); + assertThat(s3Express.signingRegion()).isEqualTo("us-west-2"); + assertThat(s3Express.disableDoubleEncoding()).isTrue(); + assertThat(s3Express.isDisableDoubleEncodingSet()).isTrue(); + } + + /** + * The scheme name is the only thing that varies at runtime; the collected properties must be applied identically to + * whichever type is selected. This mirrors the merged S3 ruleset result, where both branches carry the same properties. + */ + @Test + void create_sameFactoryProperties_appliedIdenticallyToBothSchemes() { + DynamicEndpointAuthSchemeFactory factory = DynamicEndpointAuthSchemeFactory.builder() + .disableDoubleEncoding(false) + .signingName("s3express") + .signingRegion("eu-central-1"); + + SigV4AuthScheme sigv4 = (SigV4AuthScheme) factory.create("sigv4"); + S3ExpressEndpointAuthScheme s3Express = (S3ExpressEndpointAuthScheme) factory.create("sigv4-s3express"); + + assertThat(sigv4.signingName()).isEqualTo(s3Express.signingName()); + assertThat(sigv4.signingRegion()).isEqualTo(s3Express.signingRegion()); + assertThat(sigv4.disableDoubleEncoding()).isEqualTo(s3Express.disableDoubleEncoding()); + assertThat(sigv4.disableDoubleEncoding()).isFalse(); + } + + /** + * Codegen emits properties in ruleset order, which is not guaranteed to match the declaration order here, so every setter + * must be order independent and return the same instance. + */ + @Test + void setters_calledInAnyOrder_returnSameInstanceAndApplyAllProperties() { + DynamicEndpointAuthSchemeFactory factory = DynamicEndpointAuthSchemeFactory.builder(); + + assertThat(factory.signingRegion("us-east-1")).isSameAs(factory); + assertThat(factory.disableDoubleEncoding(true)).isSameAs(factory); + assertThat(factory.signingName("s3")).isSameAs(factory); + + SigV4AuthScheme scheme = (SigV4AuthScheme) factory.create("sigv4"); + assertThat(scheme.signingName()).isEqualTo("s3"); + assertThat(scheme.signingRegion()).isEqualTo("us-east-1"); + assertThat(scheme.disableDoubleEncoding()).isTrue(); + } + + /** + * Unset properties must behave exactly as they do when codegen emits a direct builder call with those properties omitted, + * that is, {@code null} rather than a defaulted value. + */ + @Test + void create_withNoPropertiesSet_leavesPropertiesUnset() { + SigV4AuthScheme sigv4 = (SigV4AuthScheme) DynamicEndpointAuthSchemeFactory.builder().create("sigv4"); + + assertThat(sigv4.signingName()).isNull(); + assertThat(sigv4.signingRegion()).isNull(); + assertThat(sigv4.isDisableDoubleEncodingSet()).isFalse(); + assertThat(sigv4.disableDoubleEncoding()).isFalse(); + + S3ExpressEndpointAuthScheme s3Express = + (S3ExpressEndpointAuthScheme) DynamicEndpointAuthSchemeFactory.builder().create("sigv4-s3express"); + + assertThat(s3Express.signingName()).isNull(); + assertThat(s3Express.signingRegion()).isNull(); + assertThat(s3Express.isDisableDoubleEncodingSet()).isFalse(); + assertThat(s3Express.disableDoubleEncoding()).isFalse(); + } + + @Test + void create_explicitNullDisableDoubleEncoding_leavesPropertyUnset() { + SigV4AuthScheme sigv4 = (SigV4AuthScheme) DynamicEndpointAuthSchemeFactory.builder() + .disableDoubleEncoding(null) + .create("sigv4"); + + assertThat(sigv4.isDisableDoubleEncodingSet()).isFalse(); + assertThat(sigv4.disableDoubleEncoding()).isFalse(); + } + + /** + * Anything other than the two names the S3 ruleset can produce is a programming error and must fail fast with a message + * naming the offending value, rather than silently resolving to the wrong signer. + */ + @ParameterizedTest + @ValueSource(strings = {"sigv4a", "sigv4-s3", "SIGV4", "Sigv4-S3Express", "", " ", "bearer"}) + void create_unsupportedName_throwsSdkClientException(String name) { + assertThatThrownBy(() -> DynamicEndpointAuthSchemeFactory.builder().create(name)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("Unsupported dynamic endpoint auth scheme name") + .hasMessageContaining(name) + .hasMessageContaining("sigv4") + .hasMessageContaining("sigv4-s3express"); + } + + /** + * A null name must surface the same actionable error as any other unsupported value, not a NullPointerException. + */ + @Test + void create_nullName_throwsSdkClientExceptionNotNpe() { + assertThatThrownBy(() -> DynamicEndpointAuthSchemeFactory.builder().create(null)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("Unsupported dynamic endpoint auth scheme name"); + } + + /** + * The factory is reusable: {@code create} must not consume or mutate the collected properties, since a single resolution can + * in principle build more than one scheme. + */ + @Test + void create_calledRepeatedly_returnsEqualButDistinctInstances() { + DynamicEndpointAuthSchemeFactory factory = DynamicEndpointAuthSchemeFactory.builder() + .signingName("s3express") + .signingRegion("us-west-2") + .disableDoubleEncoding(true); + + EndpointAuthScheme first = factory.create("sigv4-s3express"); + EndpointAuthScheme second = factory.create("sigv4-s3express"); + + assertThat(first).isNotSameAs(second); + assertThat(first).isEqualTo(second); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java new file mode 100644 index 000000000000..92bb9c5fdc05 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java @@ -0,0 +1,165 @@ +/* + * 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.endpoints.internal; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.s3.endpoints.S3EndpointParams; +import software.amazon.awssdk.services.s3.jmespath.internal.JmesPathRuntime; +import software.amazon.awssdk.services.s3.model.Delete; +import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest; +import software.amazon.awssdk.services.s3.model.ObjectIdentifier; + +/** + * Verifies that the codegen-lowered {@code operationContextParams} binding for S3 DeleteObjects + * ("Delete.Objects[*].Key") produces the same value as the reflective {@link JmesPathRuntime} evaluation, + * which remains the fallback for unsupported expressions and is used here as the equivalence oracle. + * + *

    The lowered binding is invoked directly via its generated, private + * {@code setOperationContextParams(builder, request)} overload, so the check is isolated to the binding + * itself, independent of the rest of endpoint parameter resolution. + */ +public class OperationContextParamsBindingEquivalenceTest { + + private static List reflective(DeleteObjectsRequest request) { + JmesPathRuntime.Value input = new JmesPathRuntime.Value(request); + return input.field("Delete").field("Objects").wildcard().field("Key").stringValues(); + } + + private static List lowered(DeleteObjectsRequest request) { + try { + Method binding = S3EndpointResolverUtils.class.getDeclaredMethod( + "setOperationContextParams", S3EndpointParams.Builder.class, DeleteObjectsRequest.class); + binding.setAccessible(true); + S3EndpointParams.Builder builder = S3EndpointParams.builder(); + binding.invoke(null, builder, request); + return builder.build().deleteObjectKeys(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private static void assertEquivalent(DeleteObjectsRequest request, List expected) { + List low = lowered(request); + assertEquals(reflective(request), low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + private static ObjectIdentifier oid(String key) { + return ObjectIdentifier.builder().key(key).build(); + } + + private static DeleteObjectsRequest req(ObjectIdentifier... objects) { + return DeleteObjectsRequest.builder() + .bucket("bucket") + .delete(Delete.builder().objects(Arrays.asList(objects)).build()) + .build(); + } + + @Test + public void deleteContainerNull() { + assertEquivalent(DeleteObjectsRequest.builder().bucket("bucket").build(), Collections.emptyList()); + } + + /** + * A null projection prefix yields {@code Collections.emptyList()} from {@code stringValues()}, so the lowered + * binding must not substitute a mutable list: the endpoint params class stores and returns the reference as-is. + */ + @Test + public void deleteContainerNullYieldsSameMutabilityAsReflective() { + DeleteObjectsRequest request = DeleteObjectsRequest.builder().bucket("bucket").build(); + assertThrows(UnsupportedOperationException.class, () -> reflective(request).add("x"), + "oracle assumption: reflective evaluation returns an immutable list for a null prefix"); + assertThrows(UnsupportedOperationException.class, () -> lowered(request).add("x"), + "lowered binding must match the reflective list's mutability for a null prefix"); + } + + @Test + public void objectsEmpty() { + assertEquivalent(DeleteObjectsRequest.builder() + .bucket("bucket") + .delete(Delete.builder().objects(Collections.emptyList()).build()) + .build(), + Collections.emptyList()); + } + + @Test + public void singleKey() { + assertEquivalent(req(oid("k1")), Collections.singletonList("k1")); + } + + @Test + public void multipleKeys() { + assertEquivalent(req(oid("k1"), oid("k2"), oid("k3")), Arrays.asList("k1", "k2", "k3")); + } + + @Test + public void nullLeafKeyDropped() { + assertEquivalent(req(oid("k1"), oid(null), oid("k3")), Arrays.asList("k1", "k3")); + } + + @Test + public void nullListElementDropped() { + List objects = new ArrayList<>(); + objects.add(oid("k1")); + objects.add(null); + objects.add(oid("k2")); + DeleteObjectsRequest request = DeleteObjectsRequest.builder() + .bucket("bucket") + .delete(Delete.builder().objects(objects).build()) + .build(); + assertEquivalent(request, Arrays.asList("k1", "k2")); + } + + /** + * The equivalence assertions above are only meaningful if the generated method is actually lowered: a codegen + * regression that sends this operation back to the reflective path would make every comparison + * oracle-against-itself. The resolver's class file must not reference the reflective runtime. + */ + @Test + public void operationContextParamBindingsDoNotUseReflectiveFallback() throws IOException { + byte[] classBytes = readClassBytes(S3EndpointResolverUtils.class); + assertFalse(new String(classBytes, StandardCharsets.ISO_8859_1).contains("JmesPathRuntime"), + "The generated resolver references JmesPathRuntime, so at least one operation's bindings use the " + + "reflective fallback. If a codegen change caused this, fix the regression. If a model change " + + "added an expression outside the lowering subset, the fallback is working as designed but is a " + + "performance regression for that operation: extend the lowerer or consciously update this test."); + } + + private static byte[] readClassBytes(Class clazz) throws IOException { + try (InputStream in = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) > 0) { + out.write(buffer, 0, read); + } + return out.toByteArray(); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/Expect100ContinueTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/Expect100ContinueTest.java index 20e11e55098c..e312cdf140ff 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/Expect100ContinueTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/Expect100ContinueTest.java @@ -66,7 +66,7 @@ void setup() { @ParameterizedTest(name = "expect 100-continue enabled = {0}") @CsvSource({"true", "false"}) - void sync_alwaysAdds(boolean enabled) { + void sync_crossRegion_honorsExpectContinueEnabled(boolean enabled) { try (S3Client s3 = S3Client.builder() .httpClient(mockSyncHttp) @@ -83,13 +83,13 @@ void sync_alwaysAdds(boolean enabled) { ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(HttpExecuteRequest.class); verify(mockSyncHttp).prepareRequest(requestCaptor.capture()); - assertHasExpect100Continue(requestCaptor.getValue().httpRequest()); + assertExpect100Continue(requestCaptor.getValue().httpRequest(), enabled); } } @ParameterizedTest(name = "expect 100-continue enabled = {0}") @CsvSource({"true", "false"}) - void async_alwaysAdds(boolean enabled) { + void async_crossRegion_honorsExpectContinueEnabled(boolean enabled) { try (S3AsyncClient s3 = S3AsyncClient.builder() .httpClient(mockAsyncHttp) .region(Region.US_WEST_2) @@ -105,12 +105,16 @@ void async_alwaysAdds(boolean enabled) { ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); verify(mockAsyncHttp).execute(requestCaptor.capture()); - assertHasExpect100Continue(requestCaptor.getValue().request()); + assertExpect100Continue(requestCaptor.getValue().request(), enabled); } } - private static void assertHasExpect100Continue(SdkHttpRequest httpRequest) { - assertThat(httpRequest.firstMatchingHeader("Expect")) - .hasValueSatisfying(v -> assertThat(v).isEqualToIgnoringCase("100-continue")); + private static void assertExpect100Continue(SdkHttpRequest httpRequest, boolean expectHeaderPresent) { + if (expectHeaderPresent) { + assertThat(httpRequest.firstMatchingHeader("Expect")) + .hasValueSatisfying(v -> assertThat(v).isEqualToIgnoringCase("100-continue")); + } else { + assertThat(httpRequest.firstMatchingHeader("Expect")).isEmpty(); + } } } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/S3CrossRegionSyncClientTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/S3CrossRegionSyncClientTest.java index fdec8f328aca..f7e78567b1d9 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/S3CrossRegionSyncClientTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crossregion/S3CrossRegionSyncClientTest.java @@ -43,7 +43,6 @@ import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatchers; -import org.mockito.Mock; import org.mockito.Mockito; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClientTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClientTest.java index ca34f9c045ca..06d7412be4f1 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClientTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClientTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import java.nio.file.Path; import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -33,6 +34,7 @@ import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.crt.s3.S3MetaRequestOptions.ResponseFileOption; import software.amazon.awssdk.http.SdkHttpExecutionAttributes; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; import software.amazon.awssdk.identity.spi.IdentityProvider; @@ -41,6 +43,7 @@ import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.endpoints.S3ClientContextParams; import software.amazon.awssdk.services.s3.internal.crossregion.S3CrossRegionAsyncClient; +import software.amazon.awssdk.testutils.RandomTempFile; import software.amazon.awssdk.utils.AttributeMap; import software.amazon.awssdk.utils.MapUtils; @@ -90,6 +93,40 @@ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes } } + @Test + void getObjectWithPath_shouldConfigureResponseFile() { + AtomicReference capturedAttributes = new AtomicReference<>(); + ExecutionInterceptor captor = new ExecutionInterceptor() { + @Override + public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + capturedAttributes.set( + executionAttributes.getAttribute(SdkInternalExecutionAttribute.SDK_HTTP_EXECUTION_ATTRIBUTES)); + throw new RuntimeException("STOP"); + } + }; + + DefaultS3CrtAsyncClient.DefaultS3CrtClientBuilder builder = + (DefaultS3CrtAsyncClient.DefaultS3CrtClientBuilder) S3CrtAsyncClient.builder(); + builder.addExecutionInterceptor(captor); + Path destination = RandomTempFile.randomUncreatedFile().toPath(); + + try (S3AsyncClient client = builder.region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("key", "secret"))) + .build()) { + assertThatThrownBy(() -> client.getObject(r -> r.bucket("bucket").key("key"), destination).join()) + .hasMessageContaining("STOP"); + } + + SdkHttpExecutionAttributes attributes = capturedAttributes.get(); + assertThat(attributes.getAttribute(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_PATH)) + .isEqualTo(destination); + assertThat(attributes.getAttribute(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_OPTION)) + .isEqualTo(ResponseFileOption.CREATE_NEW); + assertThat(attributes.getAttribute(S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_DELETE_ON_FAILURE)) + .isTrue(); + } + @ParameterizedTest @ValueSource(longs = {0, -1L}) void invalidConfig_shouldThrowException(long value) { 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 40702c70ef65..c07e566a6ed3 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 @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -26,6 +27,7 @@ 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.RESPONSE_FILE_DELETE_ON_FAILURE; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_OPTION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_FILE_PATH; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.CRT_CREDENTIALS_PROVIDER_ADAPTER; @@ -34,6 +36,7 @@ import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.USE_S3_EXPRESS_AUTH; import java.net.URI; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.Path; import java.time.Duration; import java.util.HashMap; @@ -52,6 +55,7 @@ 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.CrtRuntimeException; import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; import software.amazon.awssdk.crt.http.HttpProxyEnvironmentVariableSetting; @@ -618,11 +622,43 @@ public void responseFilePathAndOption_shouldPassToCrt() { .putHttpExecutionAttribute(OPERATION_NAME, "GetObject") .putHttpExecutionAttribute(RESPONSE_FILE_PATH, path) .putHttpExecutionAttribute(RESPONSE_FILE_OPTION, S3MetaRequestOptions.ResponseFileOption.CREATE_OR_APPEND) + .putHttpExecutionAttribute(RESPONSE_FILE_DELETE_ON_FAILURE, true) .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); assertThat(actual.getResponseFilePath()).isEqualTo(path); assertThat(actual.getResponseFileOption()).isEqualTo(S3MetaRequestOptions.ResponseFileOption.CREATE_OR_APPEND); + assertThat(actual.getResponseFileDeleteOnFailure()).isTrue(); + } + + @Test + public void responseFileDeleteOnFailureNotSpecified_shouldUseCrtDefault() { + Path path = RandomTempFile.randomUncreatedFile().toPath(); + AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder() + .putHttpExecutionAttribute(OPERATION_NAME, "GetObject") + .putHttpExecutionAttribute(RESPONSE_FILE_PATH, path) + .build(); + + assertThat(makeRequest(asyncExecuteRequest).getResponseFileDeleteOnFailure()).isFalse(); + } + + @Test + public void responseFileAlreadyExists_shouldFailFutureWithFileAlreadyExistsException() { + Path path = RandomTempFile.randomUncreatedFile().toPath(); + CrtRuntimeException crtException = + new CrtRuntimeException("aws_last_error: AWS_ERROR_S3_RECV_FILE_ALREADY_EXISTS(14367), file exists"); + when(s3Client.makeMetaRequest(any(S3MetaRequestOptions.class))).thenThrow(crtException); + AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder() + .putHttpExecutionAttribute(OPERATION_NAME, "GetObject") + .putHttpExecutionAttribute(RESPONSE_FILE_PATH, path) + .putHttpExecutionAttribute(RESPONSE_FILE_OPTION, S3MetaRequestOptions.ResponseFileOption.CREATE_NEW) + .build(); + + CompletableFuture future = assertDoesNotThrow(() -> asyncHttpClient.execute(asyncExecuteRequest)); + + assertThatThrownBy(future::join) + .hasRootCauseInstanceOf(FileAlreadyExistsException.class) + .hasRootCauseMessage(path.toString()); } @Test diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtClientWiremockTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtClientWiremockTest.java index 147ca786703e..494315044597 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtClientWiremockTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtClientWiremockTest.java @@ -37,17 +37,23 @@ import com.github.tomakehurst.wiremock.junit5.WireMockTest; import com.github.tomakehurst.wiremock.stubbing.Scenario; import java.net.URI; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; +import java.util.Optional; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; 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 org.mockito.Mockito; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.crt.CrtResource; @@ -222,6 +228,52 @@ public void toBlockingInputStream_requestFailedMidwayDueToIoError_shouldThrowExc }); } + @Test + public void putObject_requestBodyPublisherErrors_futureCompletesWithOriginalError(WireMockRuntimeInfo wiremock) { + // Match all methods with a 200. WireMock waits for the full request body before responding, so when the body + // errors mid-send the body error (not a server response) is the meta request's terminal event. + stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200))); + IllegalArgumentException bodyError = new IllegalArgumentException("test error"); + + // A small, known content length keeps this a single-part PutObject (avoids the @BeforeEach client's tiny part + // size that would otherwise force a multipart CreateMultipartUpload before the body is ever read). + AsyncRequestBody erroringBody = new AsyncRequestBody() { + @Override + public Optional contentLength() { + return Optional.of(16L); + } + + @Override + public void subscribe(Subscriber subscriber) { + subscriber.onSubscribe(new Subscription() { + @Override + public void request(long n) { + subscriber.onError(bodyError); + } + + @Override + public void cancel() { + } + }); + } + }; + + try (S3AsyncClient singlePartClient = + S3AsyncClient.crtBuilder() + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost:" + wiremock.getHttpPort())) + .credentialsProvider( + StaticCredentialsProvider.create(AwsBasicCredentials.create("key", "secret"))) + .build()) { + // Bounded wait so a regression that swallows the body error (leaving CRT waiting on the declared 16 bytes) + // fails fast instead of hanging to the global surefire timeout. + assertThatThrownBy(() -> singlePartClient.putObject(r -> r.bucket(BUCKET).key(KEY), erroringBody) + .get(5, TimeUnit.SECONDS)) + .hasRootCauseInstanceOf(IllegalArgumentException.class) + .hasRootCauseMessage("test error"); + } + } + @Test void overrideResponseCompletionExecutor_shouldCompleteWithCustomExecutor(WireMockRuntimeInfo wiremock) { diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapterTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapterTest.java index 2d1c2cd7845f..e25d1e7c0bb9 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapterTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtRequestBodyStreamAdapterTest.java @@ -15,14 +15,16 @@ package software.amazon.awssdk.services.s3.internal.crt; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; import io.reactivex.Flowable; import java.io.IOException; +import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -50,7 +52,7 @@ void getRequestData_fillsInputBuffer_publisherBuffersAreSmaller() { SdkHttpContentPublisher requestBody = requestBody(Flowable.fromIterable(data), 42L); - S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody); + S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody, new CompletableFuture<>()); ByteBuffer inputBuffer = ByteBuffer.allocate(inputBufferSize); adapter.sendRequestBody(inputBuffer); @@ -66,7 +68,7 @@ void getRequestData_fillsInputBuffer_limitsOutstandingDemand() { RequestTrackingPublisher requestTrackingPublisher = new RequestTrackingPublisher(); SdkHttpContentPublisher requestBody = requestBody(requestTrackingPublisher, minBytesBuffered); - S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody); + S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody, new CompletableFuture<>()); ByteBuffer inputBuffer = ByteBuffer.allocate(inputBufferSize); adapter.sendRequestBody(inputBuffer); // initiate the subscription, but no bytes available, makes 1 request @@ -105,7 +107,7 @@ public void getRequestData_fillsInputBuffer_publisherBuffersAreLarger() { SdkHttpContentPublisher requestBody = requestBody(Flowable.just(data), 16L); - S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody); + S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody, new CompletableFuture<>()); ByteBuffer inputBuffer = ByteBuffer.allocate(1); @@ -117,27 +119,33 @@ public void getRequestData_fillsInputBuffer_publisherBuffersAreLarger() { } @Test - public void getRequestData_publisherThrows_surfacesException() { + public void sendRequestBody_publisherThrows_failsFutureWithoutThrowing() { Publisher errorPublisher = Flowable.error(new RuntimeException("Something wrong happened")); SdkHttpContentPublisher requestBody = requestBody(errorPublisher, 0L); - S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody); + CompletableFuture executeFuture = new CompletableFuture<>(); + S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody, executeFuture); - assertThatThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))) - .isInstanceOf(RuntimeException.class) - .hasMessageContaining("Something wrong happened"); + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); + + assertThat(executeFuture).hasFailedWithThrowableThat() + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Something wrong happened"); } @Test - public void getRequestData_publisherThrows_wrapsExceptionIfNotRuntimeException() { + public void sendRequestBody_publisherThrowsCheckedException_failsFutureWithWrappedCause() { Publisher errorPublisher = Flowable.error(new IOException("Some I/O error happened")); SdkHttpContentPublisher requestBody = requestBody(errorPublisher, 0L); - S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody); + CompletableFuture executeFuture = new CompletableFuture<>(); + S3CrtRequestBodyStreamAdapter adapter = new S3CrtRequestBodyStreamAdapter(requestBody, executeFuture); + + assertThatNoException().isThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))); - assertThatThrownBy(() -> adapter.sendRequestBody(ByteBuffer.allocate(16))) - .isInstanceOf(RuntimeException.class) - .hasCauseInstanceOf(IOException.class); + assertThat(executeFuture).hasFailedWithThrowableThat() + .isInstanceOf(UncheckedIOException.class) + .hasCauseInstanceOf(IOException.class); } private static class RequestTrackingPublisher implements Publisher { diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapterTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapterTest.java index d8c55f5820cc..c9733cd81096 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapterTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtResponseHandlerAdapterTest.java @@ -42,6 +42,7 @@ import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import software.amazon.awssdk.core.async.DrainingSubscriber; +import software.amazon.awssdk.core.exception.ApiCallAttemptTimeoutException; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.crt.http.HttpHeader; import software.amazon.awssdk.crt.s3.S3FinishedResponseContext; @@ -256,6 +257,44 @@ public void requestFailedWithCause_shouldCompleteFutureExceptionallyWithCause() verify(s3MetaRequest).close(); } + @Test + public void bodyError_completesFutureWithOriginalError_andSuppressesLaterCancelOnError() { + RuntimeException originalError = new RuntimeException("test error"); + + // The body adapter fails the execute future with the original publisher error. + future.completeExceptionally(originalError); + + assertThat(sdkResponseHandler.error).isSameAs(originalError); + assertThatThrownBy(() -> future.join()).hasCause(originalError); + verify(s3MetaRequest).cancel(); + verify(s3MetaRequest).close(); + + // The cancel() above later surfaces as onFinished(AWS_ERROR_S3_CANCELED). It must not re-notify onError. + responseHandlerAdapter.onFinished(stubResponseContext(1, 0, null)); + + assertThat(sdkResponseHandler.error).isSameAs(originalError); + verify(sdkResponseHandler, times(1)).onError(any()); + } + + @Test + public void pipelineForwardedError_completesFutureWithThatError_andSuppressesLaterCancelOnError() { + // A pipeline-forwarded failure (e.g. an API-call-attempt timeout that MakeAsyncHttpRequestStage forwards onto the + // execute future) completes resultFuture exceptionally the same way a body error does. The whenComplete must + // deliver that error to onError exactly once, not the later cancel-derived S3_CANCELED wrapper. + ApiCallAttemptTimeoutException timeout = ApiCallAttemptTimeoutException.create(1000); + + future.completeExceptionally(timeout); + + assertThat(sdkResponseHandler.error).isSameAs(timeout); + assertThatThrownBy(() -> future.join()).hasCause(timeout); + verify(s3MetaRequest).cancel(); + + responseHandlerAdapter.onFinished(stubResponseContext(1, 0, null)); + + assertThat(sdkResponseHandler.error).isSameAs(timeout); + verify(sdkResponseHandler, times(1)).onError(any()); + } + private S3FinishedResponseContext stubResponseContext(int errorCode, int responseStatus, byte[] errorPayload) { Mockito.reset(context); when(context.getErrorCode()).thenReturn(errorCode); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservableTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservableTest.java new file mode 100644 index 000000000000..2d71253b0b98 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3MetaRequestPauseObservableTest.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.internal.crt; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.crt.s3.ResumeToken; + +public class S3MetaRequestPauseObservableTest { + @Test + void pause_notYetSubscribed_returnsNull() { + S3MetaRequestPauseObservable observable = new S3MetaRequestPauseObservable(); + assertThat(observable.pause()).isNull(); + } + + @Test + void pauseAsync_notYetSubscribed_returnsFutureCompletedWithNull() { + S3MetaRequestPauseObservable observable = new S3MetaRequestPauseObservable(); + assertThat(observable.pauseAsync()).isCompletedWithValue(null); + } + + @Test + void pauseAsync_subscribed_delegatesToMetaRequest() { + ResumeToken token = new ResumeToken(new ResumeToken.PutResumeTokenBuilder().withUploadId("id")); + S3MetaRequestWrapper metaRequest = mock(S3MetaRequestWrapper.class); + when(metaRequest.pauseAsync()).thenReturn(CompletableFuture.completedFuture(token)); + + S3MetaRequestPauseObservable observable = new S3MetaRequestPauseObservable(); + observable.subscribe(metaRequest); + + assertThat(observable.pauseAsync()).isCompletedWithValue(token); + } +} 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 3c93a38b635b..e458ce333dae 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 @@ -17,8 +17,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -42,6 +44,8 @@ import software.amazon.awssdk.core.async.CloseableAsyncRequestBody; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.internal.multipart.utils.ControlledSubscription; +import software.amazon.awssdk.services.s3.internal.multipart.utils.ManagedUploadPart; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -261,6 +265,63 @@ void maxInFlightPutObjectParts_shouldLimitConcurrentUploads() { verify(mockSubscription, times(1)).request(1); } + /** + * Regression test for early CompleteMultipartUpload with a missing part under low maxInFlightParts. + */ + @Test + void lastBodyAndOnCompleteDeliveredInsideCompletionCallback_shouldCompleteWithAllParts() { + int maxInFlight = 2; + int totalParts = 5; + long contentSize = totalParts * PART_SIZE; + + MpuRequestContext context = MpuRequestContext.builder() + .request(Pair.of(putObjectRequest, asyncRequestBody)) + .contentLength(contentSize) + .partSize(PART_SIZE) + .uploadId(UPLOAD_ID) + .numPartsCompleted(0L) + .expectedNumParts(totalParts) + .build(); + + ManagedUploadPart recorder = new ManagedUploadPart(); + when(multipartUploadHelper.sendIndividualUploadPartRequest(eq(UPLOAD_ID), any(), any(), any(), any())) + .thenAnswer(recorder); + + KnownContentLengthAsyncRequestBodySubscriber sub = createSubscriber(context, maxInFlight); + ControlledSubscription controlledSubscription = new ControlledSubscription(sub); + sub.onSubscribe(controlledSubscription); // requests maxInFlight upfront + + controlledSubscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 1 starts + controlledSubscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 2 starts + recorder.completePart(1); // frees a slot + controlledSubscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 3 starts + recorder.completePart(2); + controlledSubscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 4 starts + + // Part 3 completes while the final chunk is not buffered yet: its request(1) delivers nothing. + recorder.completePart(3); + + // The producer now queues the final body and the stream-complete signal. They will be delivered + // synchronously inside the next request(1), which happens in part 4's completion callback, + // between its decrementAndGet() (returning the stale 0) and completeMultipartUploadIfFinished. + controlledSubscription.enqueueBodyQuietly(createMockAsyncRequestBody(PART_SIZE)); + controlledSubscription.enqueueStreamCompleteQuietly(); + recorder.completePart(4); + + // verify we haven't called CompleteMultipartUpload yet. + verify(multipartUploadHelper, never()).completeMultipartUpload(any(), any(), any(), any(), anyLong()); + verify(multipartUploadHelper, never()).failRequestsElegantly(any(), any(), any(), any(), any()); + + // Part 5's upload finishes; only now should CompleteMultipartUpload be sent, with all 5 parts. + recorder.completePart(5); + + ArgumentCaptor partsCaptor = ArgumentCaptor.forClass(CompletedPart[].class); + verify(multipartUploadHelper).completeMultipartUpload(eq(returnFuture), eq(UPLOAD_ID), partsCaptor.capture(), + eq(putObjectRequest), eq(contentSize)); + assertThat(partsCaptor.getValue()).hasSize(totalParts).doesNotContainNull(); + verify(multipartUploadHelper, never()).failRequestsElegantly(any(), any(), any(), any(), any()); + } + private MpuRequestContext createDefaultMpuRequestContext() { return MpuRequestContext.builder() .request(Pair.of(putObjectRequest, AsyncRequestBody.fromFile(testFile))) diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtilsTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtilsTest.java index 5fce3aff2144..b88c6cd8a33d 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtilsTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartDownloadUtilsTest.java @@ -19,7 +19,10 @@ import static software.amazon.awssdk.services.s3.multipart.S3MultipartExecutionAttribute.MULTIPART_DOWNLOAD_RESUME_CONTEXT; import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.services.s3.model.ChecksumType; import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; class MultipartDownloadUtilsTest { @@ -60,4 +63,116 @@ void contextWithParts_contextShouldBePresent() { assertThat(MultipartDownloadUtils.multipartDownloadResumeContext(req)).isPresent(); } -} \ No newline at end of file + @Test + void parseContentRange_shouldParseValidAndInvalidRanges() { + long[] result = MultipartDownloadUtils.parseContentRange("bytes 0-1023/2048"); + assertThat(result).isNotNull(); + assertThat(result[0]).isEqualTo(0); + assertThat(result[1]).isEqualTo(1023); + + result = MultipartDownloadUtils.parseContentRange("bytes 1024-2047/2048"); + assertThat(result[0]).isEqualTo(1024); + assertThat(result[1]).isEqualTo(2047); + + assertThat(MultipartDownloadUtils.parseContentRange("invalid")).isNull(); + assertThat(MultipartDownloadUtils.parseContentRange(null)).isNull(); + } + + @Test + void parseContentRangeForTotalSize_shouldParseValidAndInvalidRanges() { + assertThat(MultipartDownloadUtils.parseContentRangeForTotalSize("bytes 0-1023/2048")).contains(2048L); + assertThat(MultipartDownloadUtils.parseContentRangeForTotalSize("bytes 0-0/1")).contains(1L); + + assertThat(MultipartDownloadUtils.parseContentRangeForTotalSize("invalid")).isEmpty(); + assertThat(MultipartDownloadUtils.parseContentRangeForTotalSize(null)).isEmpty(); + } + + @Test + void calculateTotalParts_shouldCalculateCorrectly() { + assertThat(MultipartDownloadUtils.calculateTotalParts(32, 16)).isEqualTo(2); // exact fit + assertThat(MultipartDownloadUtils.calculateTotalParts(33, 16)).isEqualTo(3); // remainder rounds up + assertThat(MultipartDownloadUtils.calculateTotalParts(1, 16)).isEqualTo(1); // smaller than part size + assertThat(MultipartDownloadUtils.calculateTotalParts(16, 16)).isEqualTo(1); // exactly one part + assertThat(MultipartDownloadUtils.calculateTotalParts(0, 16)).isEqualTo(0); // empty object + // 5 GiB / 1 byte = 5_368_709_120 parts (exceeds Integer.MAX_VALUE) + long fiveGiB = 5L * 1024L * 1024L * 1024L; + assertThat(MultipartDownloadUtils.calculateTotalParts(fiveGiB, 1L)).isEqualTo(fiveGiB); + assertThat(MultipartDownloadUtils.calculateTotalParts(Long.MAX_VALUE - 1, 1L)) + .isEqualTo(Long.MAX_VALUE - 1); + assertThat(MultipartDownloadUtils.calculateTotalParts(Long.MAX_VALUE, 2)) + .isEqualTo((Long.MAX_VALUE / 2) + 1); + } + + @Test + void toFullObjectResponse_setsContentLengthAndContentRange() { + GetObjectResponse response = GetObjectResponse.builder() + .contentLength(1024L) + .contentRange("bytes 0-1023/4096") + .eTag("\"abc123\"") + .build(); + response = setHttpResponse(response, 206, "Partial Content"); + + GetObjectResponse result = MultipartDownloadUtils.toFullObjectResponse(response); + + assertThat(result.contentLength()).isEqualTo(4096L); + assertThat(result.contentRange()).isEqualTo("bytes 0-4095/4096"); + assertThat(result.eTag()).isEqualTo("\"abc123\""); + } + + @Test + void toFullObjectResponse_noContentRange_returnsUnchanged() { + GetObjectResponse response = GetObjectResponse.builder() + .contentLength(1024L) + .build(); + response = setHttpResponse(response, 206, "Partial Content"); + + GetObjectResponse result = MultipartDownloadUtils.toFullObjectResponse(response); + + assertThat(result.contentLength()).isEqualTo(1024L); + } + + @Test + void toFullObjectResponse_compositeChecksum_nullsChecksumValues() { + GetObjectResponse response = GetObjectResponse.builder() + .contentLength(8388608L) + .contentRange("bytes 0-8388607/25165824") + .checksumType(ChecksumType.COMPOSITE) + .checksumCRC32("/g/pWA==") + .build(); + response = setHttpResponse(response, 206, "Partial Content"); + + GetObjectResponse result = MultipartDownloadUtils.toFullObjectResponse(response); + + assertThat(result.checksumType()).isEqualTo(ChecksumType.COMPOSITE); + assertThat(result.checksumCRC32()).isNull(); + assertThat(result.checksumCRC32C()).isNull(); + assertThat(result.checksumCRC64NVME()).isNull(); + assertThat(result.checksumSHA1()).isNull(); + assertThat(result.checksumSHA256()).isNull(); + assertThat(result.contentLength()).isEqualTo(25165824L); + } + + @Test + void toFullObjectResponse_fullObjectChecksum_preservesChecksumValues() { + GetObjectResponse response = GetObjectResponse.builder() + .contentLength(8388608L) + .contentRange("bytes 0-8388607/25165824") + .checksumType(ChecksumType.FULL_OBJECT) + .checksumCRC32("abc123") + .build(); + response = setHttpResponse(response, 206, "Partial Content"); + + GetObjectResponse result = MultipartDownloadUtils.toFullObjectResponse(response); + + assertThat(result.checksumType()).isEqualTo(ChecksumType.FULL_OBJECT); + assertThat(result.checksumCRC32()).isEqualTo("abc123"); + } + + private static GetObjectResponse setHttpResponse(GetObjectResponse response, int statusCode, String statusText) { + SdkHttpResponse httpResponse = SdkHttpResponse.builder() + .statusCode(statusCode) + .statusText(statusText) + .build(); + return (GetObjectResponse) response.toBuilder().sdkHttpResponse(httpResponse).build(); + } +} 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 848d7259124b..d92fd69ac3c9 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,13 +15,17 @@ 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; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import java.net.MalformedURLException; +import java.net.URL; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.SplittingTransformerConfiguration; @@ -30,6 +34,8 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; class MultipartS3AsyncClientTest { @@ -64,4 +70,52 @@ void partManuallySpecified_shouldBypassMultipart() { verify(mockTransformer, never()).split(any(SplittingTransformerConfiguration.class)); verify(mockDelegate, times(1)).getObject(any(GetObjectRequest.class), eq(mockTransformer)); } + + @Test + void presignedUrlExtension_rangeSpecified_shouldBypassMultipart() throws MalformedURLException { + S3AsyncClient mockDelegate = mock(S3AsyncClient.class); + AsyncPresignedUrlExtension mockDelegateExtension = mock(AsyncPresignedUrlExtension.class); + AsyncResponseTransformer mockTransformer = mock(AsyncResponseTransformer.class); + PresignedUrlDownloadRequest req = PresignedUrlDownloadRequest.builder() + .presignedUrl(new URL("https://s3.amazonaws.com/bucket/key?signature=abc")) + .range("bytes=0-1023") + .build(); + when(mockDelegate.presignedUrlExtension()).thenReturn(mockDelegateExtension); + S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build(), true); + s3AsyncClient.presignedUrlExtension().getObject(req, mockTransformer); + verify(mockTransformer, never()).split(any(SplittingTransformerConfiguration.class)); + verify(mockDelegateExtension, times(1)).getObject(eq(req), eq(mockTransformer)); + } + + // TODO: Enable this test once PresignedUrlMultipartDownloaderSubscriber is implemented + // // Currently fails because multipart presigned URL download throws UnsupportedOperationException + // @Test + // void presignedUrlExtension_noRange_shouldUseMultipart() throws MalformedURLException { + // S3AsyncClient mockDelegate = mock(S3AsyncClient.class); + // AsyncPresignedUrlExtension mockDelegateExtension = mock(AsyncPresignedUrlExtension.class); + // AsyncResponseTransformer mockTransformer = mock(AsyncResponseTransformer.class); + // AsyncResponseTransformer.SplitResult mockSplitResult = mock(AsyncResponseTransformer.SplitResult.class); + // PresignedUrlDownloadRequest req = PresignedUrlDownloadRequest.builder() + // .presignedUrl(new URL("https://s3.amazonaws.com/bucket/key?signature=abc")) + // .build(); + // when(mockDelegate.presignedUrlExtension()).thenReturn(mockDelegateExtension); + // when(mockTransformer.split(any(SplittingTransformerConfiguration.class))).thenReturn(mockSplitResult); + // when(mockSplitResult.publisher()).thenReturn(mock(software.amazon.awssdk.core.async.SdkPublisher.class)); + // S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build(), true); + // s3AsyncClient.presignedUrlExtension().getObject(req, mockTransformer); + // verify(mockTransformer, times(1)).split(any(SplittingTransformerConfiguration.class)); + // verify(mockDelegateExtension, never()).getObject(any(PresignedUrlDownloadRequest.class), any(AsyncResponseTransformer.class)); + // } + + @Test + void presignedUrlExtension_shouldReturnMultipartExtension() { + S3AsyncClient mockDelegate = mock(S3AsyncClient.class); + AsyncPresignedUrlExtension mockDelegateExtension = mock(AsyncPresignedUrlExtension.class); + when(mockDelegate.presignedUrlExtension()).thenReturn(mockDelegateExtension); + + S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build(), true); + AsyncPresignedUrlExtension extension = s3AsyncClient.presignedUrlExtension(); + + assertThat(extension).isInstanceOf(MultipartAsyncPresignedUrlExtension.class); + } } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTckTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTckTest.java new file mode 100644 index 000000000000..bb05a0833a2e --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTckTest.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.services.s3.internal.multipart; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.net.MalformedURLException; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import org.mockito.Mockito; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.reactivestreams.tck.SubscriberWhiteboxVerification; +import org.reactivestreams.tck.TestEnvironment; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +public class ParallelPresignedUrlMultipartDownloaderSubscriberTckTest + extends SubscriberWhiteboxVerification> { + + private final S3AsyncClient s3mock; + + public ParallelPresignedUrlMultipartDownloaderSubscriberTckTest() { + super(new TestEnvironment()); + this.s3mock = Mockito.mock(S3AsyncClient.class); + AsyncPresignedUrlExtension presignedUrlExtension = Mockito.mock(AsyncPresignedUrlExtension.class); + when(s3mock.presignedUrlExtension()).thenReturn(presignedUrlExtension); + + when(presignedUrlExtension.getObject(any(PresignedUrlDownloadRequest.class), any(AsyncResponseTransformer.class))) + .thenReturn(CompletableFuture.completedFuture( + GetObjectResponse.builder() + .contentRange("bytes 0-8388607/33554432") + .contentLength(8388608L) + .eTag("\"test-etag\"") + .build())); + } + + @Override + public Subscriber> createSubscriber( + WhiteboxSubscriberProbe> probe) { + + return new ParallelPresignedUrlMultipartDownloaderSubscriber( + s3mock, + createTestPresignedUrlRequest(), + 8 * 1024 * 1024L, + new CompletableFuture<>(), + 10 + ) { + @Override + public void onSubscribe(Subscription s) { + super.onSubscribe(s); + probe.registerOnSubscribe(new SubscriberPuppet() { + @Override + public void triggerRequest(long elements) { + s.request(elements); + } + + @Override + public void signalCancel() { + s.cancel(); + } + }); + } + + @Override + public void onNext(AsyncResponseTransformer item) { + super.onNext(item); + probe.registerOnNext(item); + } + + @Override + public void onError(Throwable t) { + super.onError(t); + probe.registerOnError(t); + } + + @Override + public void onComplete() { + super.onComplete(); + probe.registerOnComplete(); + } + }; + } + + @Override + public AsyncResponseTransformer createElement(int element) { + return new AsyncResponseTransformer() { + @Override + public CompletableFuture prepare() { + return new CompletableFuture<>(); + } + + @Override + public void onResponse(GetObjectResponse response) { + } + + @Override + public void onStream(SdkPublisher publisher) { + } + + @Override + public void exceptionOccurred(Throwable error) { + } + }; + } + + private PresignedUrlDownloadRequest createTestPresignedUrlRequest() { + try { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(java.net.URI.create("https://test-bucket.s3.amazonaws.com/test-key").toURL()) + .build(); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTest.java new file mode 100644 index 000000000000..57ace09759f0 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/ParallelPresignedUrlMultipartDownloaderSubscriberTest.java @@ -0,0 +1,430 @@ +/* + * 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 com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.absent; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +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.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.UUID; +import java.util.concurrent.CompletionException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +/** + * Unit tests for {@link ParallelPresignedUrlMultipartDownloaderSubscriber}. + * Tests parallel-specific behavior: single-part detection, concurrent requests, + * and error propagation with in-flight cancellation. + */ +@WireMockTest +class ParallelPresignedUrlMultipartDownloaderSubscriberTest { + + private static final String PRESIGNED_URL_PATH = "/parallel-test"; + private static final byte[] TEST_DATA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456".getBytes(StandardCharsets.UTF_8); // 32 bytes + + private S3AsyncClient s3AsyncClient; + private URL presignedUrl; + private Path tempFile; + + @BeforeEach + void setup(WireMockRuntimeInfo wiremock) throws MalformedURLException { + MultipartConfiguration multipartConfig = MultipartConfiguration.builder() + .minimumPartSizeInBytes(16L) + .build(); + s3AsyncClient = S3AsyncClient.builder() + .endpointOverride(URI.create("http://localhost:" + wiremock.getHttpPort())) + .multipartEnabled(true) + .multipartConfiguration(multipartConfig) + .build(); + presignedUrl = new URL("http://localhost:" + wiremock.getHttpPort() + PRESIGNED_URL_PATH); + } + + @AfterEach + void cleanup() throws IOException { + if (tempFile != null && Files.exists(tempFile)) { + Files.delete(tempFile); + } + } + + @Test + void singlePartObject_shouldCompleteWithoutAdditionalRequests() throws IOException { + byte[] smallData = "0123456789".getBytes(StandardCharsets.UTF_8); + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", String.valueOf(smallData.length)) + .withHeader("Content-Range", "bytes 0-9/10") + .withHeader("ETag", "\"single-part-etag\"") + .withBody(smallData))); + + tempFile = createTempFile(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + GetObjectResponse response = (GetObjectResponse) s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join(); + + assertThat(response.eTag()).isEqualTo("\"single-part-etag\""); + assertThat(Files.readAllBytes(tempFile)).isEqualTo(smallData); + verify(1, getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH))); + } + + @Test + void multiPartObject_shouldDownloadAllPartsConcurrently() throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"multi-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 16-31/32") + .withHeader("ETag", "\"multi-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 16, 32)))); + + tempFile = createTempFile(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join(); + + assertThat(Files.readAllBytes(tempFile)).isEqualTo(TEST_DATA); + } + + @Test + void errorOnSecondPart_shouldCompleteExceptionallyAndNotSendMoreRequests() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/48") + .withHeader("ETag", "\"error-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalError" + + "Simulated failure"))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .isInstanceOf(CompletionException.class); + } + + @Test + void missingContentRangeOnFirstPart_shouldFail() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("ETag", "\"no-range-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("No Content-Range header"); + } + + @Test + void contentRangeMismatchOnSecondPart_shouldFail() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"mismatch-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 9999-10014/32") + .withHeader("ETag", "\"mismatch-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 16, 32)))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("Content-Range mismatch"); + } + + @Test + void onNext_withNullTransformer_shouldThrowNPE() { + ParallelPresignedUrlMultipartDownloaderSubscriber subscriber = + new ParallelPresignedUrlMultipartDownloaderSubscriber( + s3AsyncClient, + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + 16L, + new java.util.concurrent.CompletableFuture<>(), + 10); + + assertThatThrownBy(() -> subscriber.onNext(null)) + .isInstanceOf(NullPointerException.class); + } + + @Test + void multiPartDownload_manyParts_shouldCompleteSuccessfully() throws Exception { + // 13 parts to exceed maxInFlightParts (10) + byte[] data = new byte[208]; // 13 × 16 bytes + Arrays.fill(data, (byte) 'X'); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse().withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/208") + .withHeader("ETag", "\"etag\"") + .withBody(Arrays.copyOfRange(data, 0, 16)))); + + for (int i = 1; i < 13; i++) { + int start = i * 16; + int end = start + 15; + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=" + start + "-" + end)) + .willReturn(aResponse().withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes " + start + "-" + end + "/208") + .withHeader("ETag", "\"etag\"") + .withBody(Arrays.copyOfRange(data, start, end + 1)))); + } + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join(); + + assertThat(Files.readAllBytes(tempFile)).isEqualTo(data); + verify(13, getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH))); + } + + @Test + void emptyObject_416OnFirstRequest_shouldFallbackToNonRangeGet() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=.*")) + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", absent()) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", "0") + .withHeader("ETag", "\"empty-etag\"") + .withBody(new byte[0]))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join(); + + assertThat(tempFile.toFile()).exists(); + assertThat(tempFile.toFile().length()).isEqualTo(0L); + } + + @Test + void multipartObject_416OnSecondRequest_shouldFailWithError() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("416-on-second") + .whenScenarioStateIs("Started") + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16))) + .willSetStateTo("first-done")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("416-on-second") + .whenScenarioStateIs("first-done") + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .isInstanceOf(CompletionException.class); + } + + @Test + void getObject_firstPartContentLengthMismatch_shouldFailWithValidationError() throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "10") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 10)))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .isInstanceOf(CompletionException.class) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("content length validation failed"); + } + + @Test + void getObject_firstPartContentRangeStartByteMismatch_shouldFailWithValidationError() throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 5-20/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .isInstanceOf(CompletionException.class) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("Content-Range mismatch"); + } + + @Test + void getObject_objectMutatedBetweenParts_shouldFailWith412() throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"original-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .withHeader("If-Match", matching("\"original-etag\"")) + .willReturn(aResponse() + .withStatus(412) + .withBody("PreconditionFailed" + + "Object changed"))); + + tempFile = createTempFileUnchecked(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + assertThatThrownBy(() -> s3AsyncClient.presignedUrlExtension() + .getObject(request, AsyncResponseTransformer.toFile(tempFile)) + .join()) + .isInstanceOf(CompletionException.class); + } + + private static Path createTempFile() throws IOException { + Path path = Files.createTempFile("parallel-test-" + UUID.randomUUID(), ".tmp"); + Files.deleteIfExists(path); + return path; + } + + private static Path createTempFileUnchecked() { + try { + return createTempFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelperTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelperTest.java new file mode 100644 index 000000000000..7902916abf97 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlDownloadHelperTest.java @@ -0,0 +1,182 @@ +/* + * 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 java.net.MalformedURLException; +import java.net.URL; +import java.util.Optional; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +class PresignedUrlDownloadHelperTest { + + @Test + void validatePartResponse_validResponse_shouldReturnEmpty() { + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 0-15/32") + .contentLength(16L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, 32L, 2L); + + assertThat(result).isEmpty(); + } + + @Test + void validatePartResponse_missingContentRange_shouldReturnError() { + GetObjectResponse response = GetObjectResponse.builder() + .contentLength(16L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, 32L, 2L); + + assertThat(result).isPresent(); + assertThat(result.get().getMessage()).contains("No Content-Range header"); + } + + @Test + void validatePartResponse_invalidContentLength_shouldReturnError() { + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 0-15/32") + .contentLength(-1L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, 32L, 2L); + + assertThat(result).isPresent(); + assertThat(result.get().getMessage()).contains("Invalid or missing Content-Length"); + } + + @Test + void validatePartResponse_contentRangeMismatch_shouldReturnError() { + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 5-20/32") + .contentLength(16L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, 32L, 2L); + + assertThat(result).isPresent(); + assertThat(result.get().getMessage()).contains("Content-Range mismatch for part 0"); + } + + @Test + void validatePartResponse_contentLengthMismatch_shouldReturnError() { + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 0-15/32") + .contentLength(10L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, 32L, 2L); + + assertThat(result).isPresent(); + assertThat(result.get().getMessage()).contains("content length validation failed"); + } + + @Test + void validatePartResponse_lastPartSmallerSize_shouldPass() { + // 30-byte object, 16-byte parts → part 1 is bytes 16-29 (14 bytes) + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 16-29/30") + .contentLength(14L) + .build(); + + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 1, 16L, 30L, 2L); + + assertThat(result).isEmpty(); + } + + @Test + void validatePartResponse_nullTotalContentLength_shouldStillValidateRange() { + GetObjectResponse response = GetObjectResponse.builder() + .contentRange("bytes 0-15/32") + .contentLength(16L) + .build(); + + // When totalContentLength is null, content-length check is skipped but range check still works + Optional result = PresignedUrlDownloadHelper.validatePartResponse( + response, 0, 16L, null, null); + + assertThat(result).isEmpty(); + } + + @Test + void createRangedGetRequest_firstPart_shouldNotIncludeIfMatch() throws MalformedURLException { + URL url = new URL("https://bucket.s3.amazonaws.com/key?X-Amz-Signature=abc"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build(); + + PresignedUrlDownloadRequest result = PresignedUrlDownloadHelper.createRangedGetRequest( + original, 0, 16L, 32L, "\"etag\""); + + assertThat(result.range()).isEqualTo("bytes=0-15"); + assertThat(result.ifMatch()).isNull(); + assertThat(result.presignedUrl()).isEqualTo(url); + } + + @Test + void createRangedGetRequest_secondPart_shouldIncludeIfMatch() throws MalformedURLException { + URL url = new URL("https://bucket.s3.amazonaws.com/key?X-Amz-Signature=abc"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build(); + + PresignedUrlDownloadRequest result = PresignedUrlDownloadHelper.createRangedGetRequest( + original, 1, 16L, 32L, "\"etag\""); + + assertThat(result.range()).isEqualTo("bytes=16-31"); + assertThat(result.ifMatch()).isEqualTo("\"etag\""); + } + + @Test + void createRangedGetRequest_lastPartClamped_shouldNotExceedTotalSize() throws MalformedURLException { + URL url = new URL("https://bucket.s3.amazonaws.com/key?X-Amz-Signature=abc"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build(); + + // 30-byte object, 16-byte parts → part 1 should be bytes=16-29 (not 16-31) + PresignedUrlDownloadRequest result = PresignedUrlDownloadHelper.createRangedGetRequest( + original, 1, 16L, 30L, "\"etag\""); + + assertThat(result.range()).isEqualTo("bytes=16-29"); + } + + @Test + void createRangedGetRequest_nullTotalContentLength_shouldUseFullPartSize() throws MalformedURLException { + URL url = new URL("https://bucket.s3.amazonaws.com/key?X-Amz-Signature=abc"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build(); + + // First part when total size unknown — uses full part size without clamping + PresignedUrlDownloadRequest result = PresignedUrlDownloadHelper.createRangedGetRequest( + original, 0, 16L, null, null); + + assertThat(result.range()).isEqualTo("bytes=0-15"); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberRetryWiremockTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberRetryWiremockTest.java new file mode 100644 index 000000000000..fe81ea43715b --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberRetryWiremockTest.java @@ -0,0 +1,357 @@ +/* + * 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 com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.moreThan; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import com.github.tomakehurst.wiremock.http.Fault; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.github.tomakehurst.wiremock.stubbing.Scenario; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.UUID; +import java.util.concurrent.CompletionException; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Timeout; +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.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +@WireMockTest +@Timeout(value = 30, unit = TimeUnit.SECONDS) +class PresignedUrlMultipartDownloaderSubscriberRetryWiremockTest { + + private static final String PRESIGNED_URL_PATH = "/presigned-url"; + private static final int PART_SIZE = 16; + private static final byte[] TEST_DATA = "This is exactly a 32 byte string".getBytes(StandardCharsets.UTF_8); + private static final byte[] PART_1_DATA = Arrays.copyOfRange(TEST_DATA, 0, PART_SIZE); + private static final byte[] PART_2_DATA = Arrays.copyOfRange(TEST_DATA, PART_SIZE, TEST_DATA.length); + + private S3AsyncClient s3AsyncClient; + private URL presignedUrl; + private Path tempFile; + + @BeforeEach + void setup(WireMockRuntimeInfo wiremock) throws MalformedURLException { + s3AsyncClient = S3AsyncClient.builder() + .endpointOverride(URI.create(wiremock.getHttpBaseUrl())) + .multipartEnabled(true) + .multipartConfiguration(MultipartConfiguration.builder() + .minimumPartSizeInBytes((long) PART_SIZE) + .build()) + .build(); + presignedUrl = new URL(wiremock.getHttpBaseUrl() + PRESIGNED_URL_PATH); + } + + static Stream transformerTypes() { + return Stream.of( + Arguments.of("toBytes"), + Arguments.of("toFile") + ); + } + + @ParameterizedTest(name = "errorOnFirstPart_nonRetryable_shouldFailImmediately [{0}]") + @MethodSource("transformerTypes") + void errorOnFirstPart_nonRetryable_shouldFailImmediately(String transformerType) throws IOException { + stubError(1, 403, "AccessDeniedAccess denied"); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class) + .hasCauseInstanceOf(S3Exception.class) + .hasMessageContaining("Access denied"); + + verify(exactly(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH))); + } + + @ParameterizedTest(name = "errorOnMiddlePart_nonRetryable_shouldFail [{0}]") + @MethodSource("transformerTypes") + void errorOnMiddlePart_nonRetryable_shouldFail(String transformerType) throws IOException { + stubSuccessPart1(); + stubError(2, 403, "AccessDeniedAccess denied on part 2"); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class); + + verify(exactly(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + verify(exactly(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31"))); + } + + @ParameterizedTest(name = "errorOnFirstPart_retryable_exhaustsRetries_shouldFail [{0}]") + @MethodSource("transformerTypes") + void errorOnFirstPart_retryable_exhaustsRetries_shouldFail(String transformerType) throws IOException { + stubError(1, 500, "InternalErrorServer error"); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class) + .hasCauseInstanceOf(S3Exception.class) + .hasMessageContaining("Server error"); + + verify(moreThan(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH))); + } + + @ParameterizedTest(name = "errorOnMiddlePart_retryable_exhaustsRetries_shouldFail [{0}]") + @MethodSource("transformerTypes") + void errorOnMiddlePart_retryable_exhaustsRetries_shouldFail(String transformerType) throws IOException { + stubSuccessPart1(); + stubError(2, 500, "InternalErrorPermanent failure"); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class); + + verify(exactly(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + verify(moreThan(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31"))); + } + + @ParameterizedTest(name = "ioErrorOnFirstPart_exhaustsRetries_shouldFail [{0}]") + @MethodSource("transformerTypes") + void ioErrorOnFirstPart_exhaustsRetries_shouldFail(String transformerType) throws IOException { + stubIoError(1); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class) + .hasCauseInstanceOf(SdkClientException.class); + + verify(moreThan(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + } + + @ParameterizedTest(name = "errorOnFirstPart_retryable_thenSucceeds [{0}]") + @MethodSource("transformerTypes") + void errorOnFirstPart_retryable_thenSucceeds(String transformerType) throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("retry-first") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalErrorretry")) + .willSetStateTo("retry")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("retry-first") + .whenScenarioStateIs("retry") + .willReturn(successPart1Response()) + .willSetStateTo("part1-done")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .inScenario("retry-first") + .whenScenarioStateIs("part1-done") + .willReturn(successPart2Response())); + + Object result = executeDownload(transformerType).join(); + assertSuccessfulDownload(transformerType, result); + + verify(exactly(2), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + } + + @ParameterizedTest(name = "errorOnMiddlePart_retryable_thenSucceeds [{0}]") + @MethodSource("transformerTypes") + void errorOnMiddlePart_retryable_thenSucceeds(String transformerType) throws IOException { + stubSuccessPart1(); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .inScenario("retry-middle") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalErrorretry")) + .willSetStateTo("retry")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .inScenario("retry-middle") + .whenScenarioStateIs("retry") + .willReturn(successPart2Response())); + + Object result = executeDownload(transformerType).join(); + assertSuccessfulDownload(transformerType, result); + + verify(exactly(1), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + verify(exactly(2), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31"))); + } + + @ParameterizedTest(name = "ioErrorOnFirstPart_thenSucceeds [{0}]") + @MethodSource("transformerTypes") + void ioErrorOnFirstPart_thenSucceeds(String transformerType) throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("io-retry") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER)) + .willSetStateTo("retry")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("io-retry") + .whenScenarioStateIs("retry") + .willReturn(successPart1Response()) + .willSetStateTo("part1-done")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .inScenario("io-retry") + .whenScenarioStateIs("part1-done") + .willReturn(successPart2Response())); + + Object result = executeDownload(transformerType).join(); + assertSuccessfulDownload(transformerType, result); + + verify(exactly(2), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15"))); + } + + @ParameterizedTest(name = "retryableError_thenUrlExpires_shouldFailWithExpiredError [{0}]") + @MethodSource("transformerTypes") + void retryableError_thenUrlExpires_shouldFailWithExpiredError(String transformerType) throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("url-expires") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalErrorServer error")) + .willSetStateTo("expired")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .inScenario("url-expires") + .whenScenarioStateIs("expired") + .willReturn(aResponse() + .withStatus(403) + .withBody("AccessDenied" + + "Request has expired"))); + + assertThatThrownBy(() -> executeDownload(transformerType).join()) + .isInstanceOf(CompletionException.class) + .hasCauseInstanceOf(S3Exception.class) + .hasMessageContaining("Request has expired"); + + verify(exactly(2), getRequestedFor(urlEqualTo(PRESIGNED_URL_PATH))); + } + + + private java.util.concurrent.CompletableFuture executeDownload(String transformerType) throws IOException { + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + if ("toFile".equals(transformerType)) { + tempFile = Files.createTempFile("test-" + UUID.randomUUID(), ".tmp"); + Files.deleteIfExists(tempFile); + return s3AsyncClient.presignedUrlExtension().getObject(request, AsyncResponseTransformer.toFile(tempFile)); + } + return s3AsyncClient.presignedUrlExtension().getObject(request, AsyncResponseTransformer.toBytes()); + } + + @SuppressWarnings("unchecked") + private void assertSuccessfulDownload(String type, Object result) throws IOException { + if ("toBytes".equals(type)) { + assertArrayEquals(TEST_DATA, ((ResponseBytes) result).asByteArray()); + } else { + assertArrayEquals(TEST_DATA, Files.readAllBytes(tempFile)); + } + } + + private void stubSuccessPart1() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(successPart1Response())); + } + + private com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder successPart1Response() { + return aResponse() + .withStatus(206) + .withHeader("Content-Length", String.valueOf(PART_SIZE)) + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"etag\"") + .withBody(PART_1_DATA); + } + + private com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder successPart2Response() { + return aResponse() + .withStatus(206) + .withHeader("Content-Length", String.valueOf(PART_SIZE)) + .withHeader("Content-Range", "bytes 16-31/32") + .withHeader("ETag", "\"etag\"") + .withBody(PART_2_DATA); + } + + private void stubError(int partNumber, int status, String body) { + String rangePattern = partNumber == 1 ? "bytes=0-15" : "bytes=16-31"; + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching(rangePattern)) + .willReturn(aResponse() + .withStatus(status) + .withBody(body))); + } + + private void stubIoError(int partNumber) { + String rangePattern = partNumber == 1 ? "bytes=0-15" : "bytes=16-31"; + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching(rangePattern)) + .willReturn(aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER))); + } + + @AfterEach + void cleanup() { + if (s3AsyncClient != null) { + s3AsyncClient.close(); + } + if (tempFile != null && Files.exists(tempFile)) { + try { + Files.delete(tempFile); + } catch (IOException e) { + } + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberTckTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberTckTest.java new file mode 100644 index 000000000000..3c176d7e635a --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberTckTest.java @@ -0,0 +1,154 @@ +/* + * 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.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.net.MalformedURLException; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import org.mockito.Mockito; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.reactivestreams.tck.SubscriberWhiteboxVerification; +import org.reactivestreams.tck.TestEnvironment; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.AsyncPresignedUrlExtension; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +public class PresignedUrlMultipartDownloaderSubscriberTckTest + extends SubscriberWhiteboxVerification> { + + private S3AsyncClient s3mock; + + public PresignedUrlMultipartDownloaderSubscriberTckTest() { + super(new TestEnvironment()); + this.s3mock = Mockito.mock(S3AsyncClient.class); + } + + @Override + public Subscriber> + createSubscriber(WhiteboxSubscriberProbe> probe) { + AsyncPresignedUrlExtension presignedUrlExtension = Mockito.mock(AsyncPresignedUrlExtension.class); + when(s3mock.presignedUrlExtension()).thenReturn(presignedUrlExtension); + + CompletableFuture firstPartResponse = CompletableFuture.completedFuture( + GetObjectResponse.builder() + .contentRange("bytes 0-8388607/33554432") + .contentLength(8388608L) // 8MB + .eTag("\"test-etag-12345\"") + .build() + ); + + CompletableFuture subsequentPartResponse = CompletableFuture.completedFuture( + GetObjectResponse.builder() + .contentRange("bytes 8388608-16777215/33554432") + .contentLength(8388608L) // 8MB + .eTag("\"test-etag-12345\"") + .build() + ); + + when(presignedUrlExtension.getObject(any(PresignedUrlDownloadRequest.class), any(AsyncResponseTransformer.class))) + .thenReturn(firstPartResponse) + .thenReturn(subsequentPartResponse) + .thenReturn(subsequentPartResponse) + .thenReturn(subsequentPartResponse); + + return new PresignedUrlMultipartDownloaderSubscriber( + s3mock, + createTestPresignedUrlRequest(), + 8 * 1024 * 1024L, + new CompletableFuture<>() + ) { + @Override + public void onError(Throwable throwable) { + super.onError(throwable); + probe.registerOnError(throwable); + } + + @Override + public void onSubscribe(Subscription subscription) { + super.onSubscribe(subscription); + probe.registerOnSubscribe(new SubscriberPuppet() { + @Override + public void triggerRequest(long elements) { + subscription.request(elements); + } + + @Override + public void signalCancel() { + subscription.cancel(); + } + }); + } + + @Override + public void onNext(AsyncResponseTransformer item) { + super.onNext(item); + probe.registerOnNext(item); + } + + @Override + public void onComplete() { + super.onComplete(); + probe.registerOnComplete(); + } + }; + } + + @Override + public AsyncResponseTransformer createElement(int element) { + return new TestAsyncResponseTransformer(); + } + + private PresignedUrlDownloadRequest createTestPresignedUrlRequest() { + try { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(java.net.URI.create("https://test-bucket.s3.amazonaws.com/test-key").toURL()) + .build(); + } catch (MalformedURLException e) { + throw new RuntimeException("Failed to create test URL", e); + } + } + + private static class TestAsyncResponseTransformer implements AsyncResponseTransformer { + private CompletableFuture future; + + @Override + public CompletableFuture prepare() { + this.future = new CompletableFuture<>(); + return this.future; + } + + @Override + public void onResponse(GetObjectResponse response) { + this.future.complete(response); + } + + @Override + public void onStream(SdkPublisher publisher) { + } + + @Override + public void exceptionOccurred(Throwable error) { + future.completeExceptionally(error); + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberWiremockTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberWiremockTest.java new file mode 100644 index 000000000000..ad05af389452 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/PresignedUrlMultipartDownloaderSubscriberWiremockTest.java @@ -0,0 +1,607 @@ +/* + * 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 com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.absent; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +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.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.multipart.MultipartConfiguration; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +@WireMockTest +class PresignedUrlMultipartDownloaderSubscriberWiremockTest { + + private static final String PRESIGNED_URL_PATH = "/presigned-url"; + private static final byte[] TEST_DATA = "This is exactly a 32 byte string".getBytes(StandardCharsets.UTF_8); + + private S3AsyncClient s3AsyncClient; + private String presignedUrlBase; + private URL presignedUrl; + private Path tempFile; + + @BeforeEach + public void setup(WireMockRuntimeInfo wiremock) throws MalformedURLException { + MultipartConfiguration multipartConfig = MultipartConfiguration.builder() + .minimumPartSizeInBytes(16L) + .build(); + s3AsyncClient = S3AsyncClient.builder() + .endpointOverride(URI.create("http://localhost:" + wiremock.getHttpPort())) + .credentialsProvider(software.amazon.awssdk.auth.credentials.StaticCredentialsProvider.create( + software.amazon.awssdk.auth.credentials.AwsBasicCredentials.create("accessKey", "secretKey"))) + .region(software.amazon.awssdk.regions.Region.US_EAST_1) + .multipartEnabled(true) + .multipartConfiguration(multipartConfig) + .build(); + presignedUrlBase = "http://localhost:" + wiremock.getHttpPort(); + presignedUrl = createPresignedUrl(); + } + + static Stream transformerTypes() { + return Stream.of( + Arguments.of("toBytes"), + Arguments.of("toFile") + ); + } + + private CompletableFuture executeDownload(PresignedUrlDownloadRequest request, String transformerType) + throws IOException { + if ("toFile".equals(transformerType)) { + tempFile = createUniqueTempFile(); + return s3AsyncClient.presignedUrlExtension().getObject(request, AsyncResponseTransformer.toFile(tempFile)); + } + return s3AsyncClient.presignedUrlExtension().getObject(request, AsyncResponseTransformer.toBytes()); + } + + @SuppressWarnings("unchecked") + private void assertSuccessfulDownload(String type, Object result) throws IOException { + if ("toBytes".equals(type)) { + assertArrayEquals(TEST_DATA, ((ResponseBytes) result).asByteArray()); + } else { + assertThat(tempFile.toFile()).exists(); + byte[] fileContent = Files.readAllBytes(tempFile); + assertArrayEquals(TEST_DATA, fileContent); + } + } + + @ParameterizedTest(name = "presignedUrlDownload_withMultipartData_shouldReceiveCompleteBody [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withMultipartData_shouldReceiveCompleteBody(String transformerType) throws IOException { + stubSuccessfulPresignedUrlResponse(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + Object result = executeDownload(request, transformerType).join(); + assertSuccessfulDownload(transformerType, result); + } + + @ParameterizedTest(name = "presignedUrlDownload_smallObjectSmallerThanPartSize_shouldSucceed [{0}]") + @MethodSource("transformerTypes") + @SuppressWarnings("unchecked") + void presignedUrlDownload_smallObjectSmallerThanPartSize_shouldSucceed(String transformerType) throws IOException { + byte[] smallData = "0123456789".getBytes(StandardCharsets.UTF_8); + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "10") + .withHeader("Content-Range", "bytes 0-9/10") + .withHeader("ETag", "\"small-etag\"") + .withBody(smallData))); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + Object result = executeDownload(request, transformerType).join(); + if ("toBytes".equals(transformerType)) { + assertArrayEquals(smallData, ((ResponseBytes) result).asByteArray()); + } else { + assertThat(tempFile.toFile()).exists(); + assertArrayEquals(smallData, Files.readAllBytes(tempFile)); + } + } + + @ParameterizedTest(name = "presignedUrlDownload_withRangeHeader_shouldReceivePartialContent [{0}]") + @MethodSource("transformerTypes") + @SuppressWarnings("unchecked") + void presignedUrlDownload_withRangeHeader_shouldReceivePartialContent(String transformerType) throws IOException { + stubSuccessfulRangeResponse(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .range("bytes=0-10") + .build(); + Object result = executeDownload(request, transformerType).join(); + byte[] expectedPartial = Arrays.copyOfRange(TEST_DATA, 0, 11); + if ("toBytes".equals(transformerType)) { + assertArrayEquals(expectedPartial, ((ResponseBytes) result).asByteArray()); + } else { + byte[] fileContent = Files.readAllBytes(tempFile); + assertArrayEquals(expectedPartial, fileContent); + } + } + + @ParameterizedTest(name = "presignedUrlDownload_whenRequestFails_shouldThrowException [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_whenRequestFails_shouldThrowException(String transformerType) { + stubFailedPresignedUrlResponse(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(S3Exception.class); + } + + @ParameterizedTest(name = "presignedUrlDownload_whenFirstRequestFails_shouldThrowException [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_whenFirstRequestFails_shouldThrowException(String transformerType) { + stubInternalServerError(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(S3Exception.class); + } + + @ParameterizedTest(name = "presignedUrlDownload_whenSecondRequestFails_shouldThrowException [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_whenSecondRequestFails_shouldThrowException(String transformerType) { + stubPartialFailureScenario(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(S3Exception.class); + } + + @ParameterizedTest(name = "presignedUrlDownload_whenIOErrorOccurs_shouldThrowException [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_whenIOErrorOccurs_shouldThrowException(String transformerType) { + stubConnectionReset(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasCauseInstanceOf(SdkClientException.class); + } + + @ParameterizedTest(name = "presignedUrlDownload_withMissingContentRange_shouldFailRequest [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withMissingContentRange_shouldFailRequest(String transformerType) { + stubResponseWithMissingContentRange(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("No Content-Range header in response"); + } + + @ParameterizedTest(name = "presignedUrlDownload_withInvalidContentLength_shouldFailRequest [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withInvalidContentLength_shouldFailRequest(String transformerType) { + stubResponseWithInvalidContentLength(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("Invalid or missing Content-Length in response"); + } + + @ParameterizedTest(name = "presignedUrlDownload_withContentRangeMismatch_shouldFailRequest [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withContentRangeMismatch_shouldFailRequest(String transformerType) { + stubResponseWithContentRangeMismatch(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("Content-Range mismatch"); + } + + @ParameterizedTest(name = "presignedUrlDownload_withContentLengthMismatch_shouldFailRequest [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withContentLengthMismatch_shouldFailRequest(String transformerType) { + stubResponseWithContentLengthMismatch(); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(SdkClientException.class); + } + + @Test + void onNext_withNullTransformer_shouldThrowException() { + PresignedUrlMultipartDownloaderSubscriber subscriber = createTestSubscriber(); + + assertThatThrownBy(() -> subscriber.onNext(null)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("onNext must not be called with null asyncResponseTransformer"); + } + + @ParameterizedTest(name = "presignedUrlDownload_emptyObject_shouldFallbackToNonRangeGet [{0}]") + @MethodSource("transformerTypes") + @SuppressWarnings("unchecked") + void presignedUrlDownload_emptyObject_shouldFallbackToNonRangeGet(String transformerType) throws IOException { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=.*")) + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", absent()) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", "0") + .withHeader("ETag", "\"empty-etag\"") + .withBody(new byte[0]))); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + Object result = executeDownload(request, transformerType).join(); + if ("toBytes".equals(transformerType)) { + ResponseBytes bytes = (ResponseBytes) result; + assertThat(bytes.asByteArray()).isEmpty(); + } else { + assertThat(tempFile.toFile()).exists(); + assertThat(Files.size(tempFile)).isEqualTo(0L); + } + } + + @ParameterizedTest(name = "presignedUrlDownload_416OnSecondRequest_shouldFailWithError [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_416OnSecondRequest_shouldFailWithError(String transformerType) { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("416-on-second") + .whenScenarioStateIs("Started") + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16))) + .willSetStateTo("first-done")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("416-on-second") + .whenScenarioStateIs("first-done") + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(S3Exception.class); + } + + @ParameterizedTest(name = "presignedUrlDownload_withRangeHeader_emptyObject_shouldThrow416 [{0}]") + @MethodSource("transformerTypes") + void presignedUrlDownload_withRangeHeader_emptyObject_shouldThrow416(String transformerType) { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .range("bytes=0-1024") + .build(); + assertThatThrownBy(() -> executeDownload(request, transformerType).join()) + .hasRootCauseInstanceOf(S3Exception.class); + } + + /** + * Verifies that custom serial transformers on the presigned URL path correctly trigger + * the empty-object 416 fallback. + */ + @Test + void presignedUrlDownload_emptyObject_customTransformer_fallbackWorks() { + // Range request → 416 (simulates empty object race) + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=.*")) + .willReturn(aResponse() + .withStatus(416) + .withBody("InvalidRange" + + "The requested range is not satisfiable"))); + + // Non-range fallback GET → 200 with empty body (the correct fallback for empty object) + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", absent()) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", "0") + .withBody(""))); + + AsyncResponseTransformer customTransformer = + new AsyncResponseTransformer() { + private CompletableFuture future; + @Override + public CompletableFuture prepare() { + future = new CompletableFuture<>(); + return future; + } + @Override public void onResponse(GetObjectResponse r) { } + @Override public void onStream(SdkPublisher p) { + p.subscribe(new Subscriber() { + @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } + @Override public void onNext(ByteBuffer b) { } + @Override public void onError(Throwable t) { future.completeExceptionally(t); } + @Override public void onComplete() { future.complete("done"); } + }); + } + @Override public void exceptionOccurred(Throwable e) { future.completeExceptionally(e); } + }; + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + // Should succeed: 416 triggers fallback → non-range GET returns 200 + String result = s3AsyncClient.presignedUrlExtension() + .getObject(request, customTransformer) + .join(); + assertThat(result).isEqualTo("done"); + } + + @AfterEach + void cleanup() { + if (tempFile != null && Files.exists(tempFile)) { + try { + Files.delete(tempFile); + } catch (IOException e) { + } + } + } + + private static Path createUniqueTempFile() throws IOException { + String uniqueName = "test-" + UUID.randomUUID().toString(); + Path tempFile = Files.createTempFile(uniqueName, ".tmp"); + Files.deleteIfExists(tempFile); + return tempFile; + } + + private void stubSuccessfulPresignedUrlResponse() { + // Stub for first part (bytes 0-15) + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + // Stub for second part (bytes 16-31) + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 16-31/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 16, 32)))); + } + + private void stubSuccessfulRangeResponse() { + byte[] partialData = Arrays.copyOfRange(TEST_DATA, 0, 11); + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", String.valueOf(partialData.length)) + .withHeader("Content-Range", "bytes 0-10/" + TEST_DATA.length) + .withHeader("ETag", "\"test-etag\"") + .withBody(partialData))); + } + + private void stubFailedPresignedUrlResponse() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(404) + .withBody("NoSuchKeyThe specified key does not exist."))); + } + + private void stubInternalServerError() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalErrorInternal Server Error"))); + } + + private void stubPartialFailureScenario() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("partial-failure") + .whenScenarioStateIs("Started") + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/" + TEST_DATA.length) + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16))) + .willSetStateTo("first-success")); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .inScenario("partial-failure") + .whenScenarioStateIs("first-success") + .willReturn(aResponse() + .withStatus(500) + .withBody("InternalErrorSecond request failed"))); + } + + private void stubConnectionReset() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withFault(com.github.tomakehurst.wiremock.http.Fault.CONNECTION_RESET_BY_PEER))); + } + + private URL createPresignedUrl() throws MalformedURLException { + return new URL(presignedUrlBase + PRESIGNED_URL_PATH); + } + + private PresignedUrlMultipartDownloaderSubscriber createTestSubscriber() { + return new PresignedUrlMultipartDownloaderSubscriber( + s3AsyncClient, + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + 1024L, + new CompletableFuture<>()); + } + + private void stubResponseWithMissingContentRange() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "16") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + } + + private void stubResponseWithInvalidContentLength() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Range", "bytes 0-15/" + TEST_DATA.length) + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + } + + private void stubResponseWithContentRangeMismatch() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 5000-5015/" + TEST_DATA.length) + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + } + + private void stubResponseWithContentLengthMismatch() { + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Type", "application/octet-stream") + .withHeader("Content-Length", "8") + .withHeader("Content-Range", "bytes 0-15/" + TEST_DATA.length) + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 8)))); + } + + @Test + void presignedUrlDownload_customTransformer_hasFullObjectMetadata() { + // Stub two parts: 16 bytes each, total 32 + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=0-15")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 0-15/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 0, 16)))); + + stubFor(get(urlEqualTo(PRESIGNED_URL_PATH)) + .withHeader("Range", matching("bytes=16-31")) + .willReturn(aResponse() + .withStatus(206) + .withHeader("Content-Length", "16") + .withHeader("Content-Range", "bytes 16-31/32") + .withHeader("ETag", "\"test-etag\"") + .withBody(Arrays.copyOfRange(TEST_DATA, 16, 32)))); + + AsyncResponseTransformer customTransformer = + new AsyncResponseTransformer() { + private CompletableFuture future; + private GetObjectResponse response; + + @Override + public CompletableFuture prepare() { + future = new CompletableFuture<>(); + return future; + } + @Override public void onResponse(GetObjectResponse r) { this.response = r; } + @Override public void onStream(SdkPublisher p) { + p.subscribe(new Subscriber() { + @Override public void onSubscribe(Subscription s) { s.request(Long.MAX_VALUE); } + @Override public void onNext(ByteBuffer b) { } + @Override public void onError(Throwable t) { future.completeExceptionally(t); } + @Override public void onComplete() { + future.complete("contentLength=" + response.contentLength() + + "|contentRange=" + response.contentRange()); + } + }); + } + @Override public void exceptionOccurred(Throwable e) { future.completeExceptionally(e); } + }; + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + String result = s3AsyncClient.presignedUrlExtension() + .getObject(request, customTransformer) + .join(); + + assertThat(result).contains("contentLength=32"); + assertThat(result).contains("contentRange=bytes 0-31/32"); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3MultipartClientPutObjectWiremockTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3MultipartClientPutObjectWiremockTest.java index 42bb4f715c80..1771b508dca2 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3MultipartClientPutObjectWiremockTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3MultipartClientPutObjectWiremockTest.java @@ -17,6 +17,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; 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.delete; import static com.github.tomakehurst.wiremock.client.WireMock.lessThanOrExactly; import static com.github.tomakehurst.wiremock.client.WireMock.matching; @@ -39,6 +40,7 @@ import java.io.InputStream; import java.net.URI; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -46,6 +48,7 @@ import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -212,6 +215,44 @@ public void subscribe(Subscriber s) { verify(lessThanOrExactly(2), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(2)))); } + public static Stream inMemoryBodyRetryableErrorTestCase() { + return Stream.of( + Arguments.of("failOfConnectionReset", aResponse().withFault(Fault.CONNECTION_RESET_BY_PEER)), + Arguments.of("failOf500", aResponse().withStatus(500)) + ); + } + + /** + * An in-memory body holds all of its data, so its parts are retryable without the caller opting into + * {@link BufferedSplittableAsyncRequestBody}. + */ + @ParameterizedTest(name = "{0}") + @MethodSource("inMemoryBodyRetryableErrorTestCase") + void mpuWithInMemoryBody_partsFailOfRetryableError_shouldRetry(String description, + ResponseDefinitionBuilder responseDefinitionBuilder) { + stubUploadPartFailsInitialAttemptSucceedsUponRetryCalls(responseDefinitionBuilder); + String firstPartContent = StringUtils.repeat('a', 10); + String secondPartContent = StringUtils.repeat('b', 10); + byte[] payload = (firstPartContent + secondPartContent).getBytes(StandardCharsets.UTF_8); + + s3AsyncClient.putObject(b -> b.bucket(BUCKET).key(KEY), AsyncRequestBody.fromBytes(payload)).join(); + + verify(moreThan(1), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(1)))); + verify(lessThanOrExactly(3), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(1)))); + verify(moreThan(1), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(2)))); + verify(lessThanOrExactly(3), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(2)))); + + // Each part must only ever carry its own slice of the payload, on the initial attempt and on the retry. The + // bodies are aws-chunked encoded, so match on the content rather than comparing the payload exactly. + verify(moreThan(0), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(1))) + .withRequestBody(containing(firstPartContent))); + verify(0, putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(1))) + .withRequestBody(containing(secondPartContent))); + verify(moreThan(0), putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(2))) + .withRequestBody(containing(secondPartContent))); + verify(0, putRequestedFor(anyUrl()).withQueryParam("partNumber", matching(String.valueOf(2))) + .withRequestBody(containing(firstPartContent))); + } private void stubUploadPartFailsInitialAttemptSucceedsUponRetryCalls(ResponseDefinitionBuilder responseDefinitionBuilder) { stubFor(post(anyUrl()).willReturn(aResponse().withStatus(200).withBody(CREATE_MULTIPART_PAYLOAD))); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriberTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriberTest.java index d6cae74afa61..22b5a7019a2b 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriberTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/UnknownContentLengthAsyncRequestBodySubscriberTest.java @@ -18,8 +18,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -32,7 +34,8 @@ import org.reactivestreams.Subscription; import software.amazon.awssdk.core.async.CloseableAsyncRequestBody; import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.internal.multipart.utils.ControlledSubscription; +import software.amazon.awssdk.services.s3.internal.multipart.utils.ManagedUploadPart; import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; @@ -165,6 +168,57 @@ void onComplete_withNoParts_shouldUploadEmptyBody() { verify(multipartUploadHelper).uploadInOneChunk(eq(putObjectRequest), any(), eq(returnFuture)); } + /** + * Regression test for the "Expected: N, Actual: N-1" part-count failure seen with low maxInFlightParts. + */ + @Test + void lastBodyAndOnCompleteDeliveredInsideCompletionCallback_shouldCompleteWithAllParts() { + int maxInFlight = 2; + int numParts = 5; + UnknownContentLengthAsyncRequestBodySubscriber subscriber = createSubscriber(maxInFlight); + + stubSuccessfulCreateMultipartCall(); + when(genericMultipartHelper.determinePartCount(anyLong(), anyLong())) + .thenAnswer(invocation -> (int) Math.ceil(invocation.getArgument(0, Long.class) + / (double) invocation.getArgument(1, Long.class))); + ManagedUploadPart recorder = new ManagedUploadPart(); + when(multipartUploadHelper.sendIndividualUploadPartRequest(any(), any(), any(), any(), any())) + .thenAnswer(recorder); + + ControlledSubscription subscription = new ControlledSubscription(subscriber); + subscriber.onSubscribe(subscription); + + subscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // held as firstRequestBody + subscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // triggers MPU; parts 1, 2 start + recorder.completePart(1); // frees a slot + subscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 3 starts + recorder.completePart(2); + subscription.enqueueBodyAndDeliver(createMockAsyncRequestBody(PART_SIZE)); // part 4 starts + + // Part 3 completes while the final chunk is not buffered yet: its request(1) delivers nothing. + recorder.completePart(3); + + // The producer now queues the final body and the stream-complete signal. They will be delivered + // synchronously inside the next request(1), which happens in part 4's completion callback, + // between its decrementAndGet() (returning the stale 0) and completeMultipartUploadIfFinish. + subscription.enqueueBodyQuietly(createMockAsyncRequestBody(PART_SIZE)); + subscription.enqueueStreamCompleteQuietly(); + recorder.completePart(4); + + // verify we haven't called CompleteMultipartUpload yet. + verify(multipartUploadHelper, never()).failRequestsElegantly(any(), any(), any(), any(), any()); + verify(multipartUploadHelper, never()).completeMultipartUpload(any(), any(), any(), any(), anyLong()); + + // Part 5's upload finishes; only now should CompleteMultipartUpload be sent, with all 5 parts. + recorder.completePart(5); + + ArgumentCaptor partsCaptor = ArgumentCaptor.forClass(CompletedPart[].class); + verify(multipartUploadHelper).completeMultipartUpload(eq(returnFuture), eq(UPLOAD_ID), partsCaptor.capture(), + eq(putObjectRequest), eq(numParts * PART_SIZE)); + assertThat(partsCaptor.getValue()).hasSize(numParts).doesNotContainNull(); + verify(multipartUploadHelper, never()).failRequestsElegantly(any(), any(), any(), any(), any()); + } + private UnknownContentLengthAsyncRequestBodySubscriber createSubscriber(int maxInFlightParts) { return new UnknownContentLengthAsyncRequestBodySubscriber( PART_SIZE, putObjectRequest, returnFuture, diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ControlledSubscription.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ControlledSubscription.java new file mode 100644 index 000000000000..2e4ade734aea --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ControlledSubscription.java @@ -0,0 +1,82 @@ +/* + * 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.utils; + +import java.util.ArrayDeque; +import java.util.Deque; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.core.async.CloseableAsyncRequestBody; + +/** + * A Subscription that mimics {@link software.amazon.awssdk.utils.async.SimplePublisher}: queued signals + * are delivered synchronously on the thread that calls request(), onNext delivery is gated on demand, + * and onComplete is delivered once the queue drains, without needing demand. + */ +public final class ControlledSubscription implements Subscription { + private final Subscriber subscriber; + private final Deque queuedBodies = new ArrayDeque<>(); + private long demand; + private boolean streamComplete; + private boolean onCompleteDelivered; + private boolean draining; + + public ControlledSubscription(Subscriber subscriber) { + this.subscriber = subscriber; + } + + @Override + public void request(long n) { + demand += n; + drain(); + } + + @Override + public void cancel() { + } + + public void enqueueBodyAndDeliver(CloseableAsyncRequestBody body) { + queuedBodies.add(body); + drain(); + } + + public void enqueueBodyQuietly(CloseableAsyncRequestBody body) { + queuedBodies.add(body); + } + + public void enqueueStreamCompleteQuietly() { + streamComplete = true; + } + + private void drain() { + if (draining) { + return; // mirrors SimplePublisher's processingQueue flag: no re-entrant delivery + } + draining = true; + try { + while (demand > 0 && !queuedBodies.isEmpty()) { + demand--; + subscriber.onNext(queuedBodies.poll()); + } + if (streamComplete && queuedBodies.isEmpty() && !onCompleteDelivered) { + onCompleteDelivered = true; + subscriber.onComplete(); + } + } finally { + draining = false; + } + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ManagedUploadPart.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ManagedUploadPart.java new file mode 100644 index 000000000000..4a03b81c8d8e --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/utils/ManagedUploadPart.java @@ -0,0 +1,61 @@ +/* + * 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.utils; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.services.s3.model.CompletedPart; +import software.amazon.awssdk.services.s3.model.UploadPartRequest; +import software.amazon.awssdk.utils.Pair; + +/** + * Records the consumer and pending future of each UploadPart request so a test can complete parts + * the same way MultipartUploadHelper does: consumer.accept(completedPart) followed by future completion. + * + *

    Intended to be used as a Mockito {@link Answer} for + * {@code MultipartUploadHelper#sendIndividualUploadPartRequest}. + */ +public final class ManagedUploadPart implements Answer> { + private final Map> consumers = new HashMap<>(); + private final Map> futures = new HashMap<>(); + + @Override + @SuppressWarnings("unchecked") + public CompletableFuture answer(InvocationOnMock invocation) { + Consumer consumer = invocation.getArgument(1, Consumer.class); + Pair pair = invocation.getArgument(3, Pair.class); + int partNumber = pair.left().partNumber(); + CompletableFuture future = new CompletableFuture<>(); + consumers.put(partNumber, consumer); + futures.put(partNumber, future); + return future; + } + + public void completePart(int partNumber) { + CompletableFuture future = futures.get(partNumber); + assertThat(future).withFailMessage("UploadPart request for part %d was never sent", partNumber).isNotNull(); + CompletedPart part = CompletedPart.builder().partNumber(partNumber).eTag("etag-" + partNumber).build(); + consumers.get(partNumber).accept(part); + future.complete(part); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtensionTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtensionTest.java new file mode 100644 index 000000000000..9fed4335aa5a --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/DefaultAsyncPresignedUrlExtensionTest.java @@ -0,0 +1,438 @@ +/* + * 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.presignedurl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.function.Consumer; +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 software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.awscore.client.config.AwsAdvancedClientOption; +import software.amazon.awssdk.awscore.client.config.AwsClientOption; +import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; +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.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +import software.amazon.awssdk.core.client.handler.AsyncClientHandler; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.HttpExecuteResponse; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.protocols.core.ExceptionMetadata; +import software.amazon.awssdk.protocols.xml.AwsS3ProtocolFactory; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.InvalidObjectStateException; +import software.amazon.awssdk.services.s3.model.NoSuchKeyException; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; +import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; + +/** + * Tests for {@link DefaultAsyncPresignedUrlExtension} using MockAsyncHttpClient to verify HTTP interactions. + */ +class DefaultAsyncPresignedUrlExtensionTest { + + private static final String TEST_CONTENT = "test-content"; + private static final URI DEFAULT_ENDPOINT = URI.create("https://defaultendpoint.com"); + private static final String TEST_URL = "https://test-bucket.s3.us-east-1.amazonaws.com/test-key?" + + "X-Amz-Date=20250707T000000Z&" + + "X-Amz-Signature=test-signature-value&" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host&" + + "X-Amz-Security-Token=test-session-token&" + + "X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20250707%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Expires=86400"; + + private MockAsyncHttpClient mockHttpClient; + private DefaultAsyncPresignedUrlExtension presignedUrlExtension; + private PresignedUrlDownloadRequest testRequest; + private AwsProtocolMetadata protocolMetadata; + private AwsS3ProtocolFactory protocolFactory; + private AsyncClientHandler clientHandler; + + @BeforeEach + void setUp() throws Exception { + mockHttpClient = new MockAsyncHttpClient(); + URL testPresignedUrl = new URL(TEST_URL); + testRequest = PresignedUrlDownloadRequest.builder() + .presignedUrl(testPresignedUrl) + .build(); + + SdkClientConfiguration clientConfiguration = getDefaultSdkConfigs(); + protocolMetadata = AwsProtocolMetadata.builder() + .serviceProtocol(AwsServiceProtocol.REST_XML) + .build(); + protocolFactory = initProtocolFactory(clientConfiguration); + clientHandler = new AwsAsyncClientHandler(clientConfiguration); + + presignedUrlExtension = new DefaultAsyncPresignedUrlExtension( + clientHandler, protocolFactory, clientConfiguration, protocolMetadata); + } + + private static Stream httpResponseTestCases() { + return Stream.of( + Arguments.of( + "Success response", + createSuccessResponse(), + true, + null + ), + Arguments.of( + "404 Not Found response", + createErrorResponse(404, "NoSuchKey", "The specified key does not exist."), + false, + NoSuchKeyException.class + ), + Arguments.of( + "403 Invalid Object State response", + createErrorResponse(403, "InvalidObjectState", "The operation is not valid for the object's storage class."), + false, + InvalidObjectStateException.class + ), + Arguments.of( + "Generic error response", + createErrorResponse(500, "InternalError", "We encountered an internal error. Please try again."), + false, + S3Exception.class + ) + ); + } + + private static Stream requestConfigurationTestCases() { + return Stream.of( + Arguments.of( + "Basic request", + (Consumer) builder -> + builder.presignedUrl(createTestUrl()), + null + ), + Arguments.of( + "Request with range header", + (Consumer) builder -> + builder.presignedUrl(createTestUrl()).range("bytes=0-1024"), + "bytes=0-1024" + ) + ); + } + + private static Stream additionalTestCases() { + return Stream.of( + Arguments.of("Custom transformer test", "CUSTOM_TRANSFORMER"), + Arguments.of("Metrics collection test", "METRICS_COLLECTION") + ); + } + + private static Stream invalidUrlTestCases() { + return Stream.of( + Arguments.of("Invalid URL format", "not-a-url"), + Arguments.of("Empty HTTP URL", "http://"), + Arguments.of("Empty HTTPS URL", "https://"), + Arguments.of("Empty string", "") + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("httpResponseTestCases") + void given_AsyncPresignedUrlExtension_when_GetObjectWithDifferentHttpResponses_then_ShouldHandleSuccessAndErrorsCorrectly( + String testName, + HttpExecuteResponse response, + boolean expectSuccess, + Class expectedExceptionType) { + + mockHttpClient.stubNextResponse(response); + + if (expectSuccess) { + assertSuccessfulGetObject(testRequest); + } else { + CompletableFuture> future = + presignedUrlExtension.getObject(testRequest, AsyncResponseTransformer.toBytes()); + + assertThatThrownBy(future::join) + .hasCauseInstanceOf(expectedExceptionType); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("requestConfigurationTestCases") + void given_AsyncPresignedUrlExtension_when_GetObjectWithDifferentRequestConfigurations_then_ShouldSetCorrectHeaders( + String testName, + Consumer requestCustomizer, + String expectedRangeHeader) throws ExecutionException, InterruptedException { + + mockHttpClient.stubNextResponse(createSuccessResponse()); + + PresignedUrlDownloadRequest.Builder builder = PresignedUrlDownloadRequest.builder(); + requestCustomizer.accept(builder); + PresignedUrlDownloadRequest request = builder.build(); + + CompletableFuture> future = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + ResponseBytes result = future.get(); + + assertThat(result).isNotNull(); + assertThat(result.asUtf8String()).isEqualTo(TEST_CONTENT); + + SdkHttpRequest lastRequest = mockHttpClient.getLastRequest(); + assertThat(lastRequest.method()).isEqualTo(SdkHttpMethod.GET); + + if (expectedRangeHeader != null) { + assertThat(lastRequest.firstMatchingHeader("Range")) + .isPresent() + .contains(expectedRangeHeader); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("additionalTestCases") + void given_AsyncPresignedUrlExtension_when_ExecutingDifferentScenarios_then_ShouldBehaveCorrectly( + String testName, String testType) throws Exception { + + switch (testType) { + case "CUSTOM_TRANSFORMER": + mockHttpClient.stubNextResponse(createSuccessResponse()); + CompletableFuture> future = + presignedUrlExtension.getObject(testRequest, AsyncResponseTransformer.toBytes()); + ResponseBytes result = future.get(); + assertThat(result.asUtf8String()).isEqualTo(TEST_CONTENT); + break; + + case "METRICS_COLLECTION": + MetricPublisher mockPublisher = mock(MetricPublisher.class); + SdkClientConfiguration clientConfigWithMetrics = getDefaultSdkConfigs().toBuilder() + .option(SdkClientOption.METRIC_PUBLISHERS, Collections.singletonList(mockPublisher)) + .build(); + DefaultAsyncPresignedUrlExtension extensionWithMetrics = new DefaultAsyncPresignedUrlExtension( + clientHandler, protocolFactory, clientConfigWithMetrics, protocolMetadata); + mockHttpClient.stubNextResponse(createSuccessResponse()); + CompletableFuture> metricsFuture = + extensionWithMetrics.getObject(testRequest, AsyncResponseTransformer.toBytes()); + metricsFuture.get(); + + verify(mockPublisher, atLeastOnce()).publish(any(MetricCollection.class)); + ArgumentCaptor metricsCaptor = ArgumentCaptor.forClass(MetricCollection.class); + verify(mockPublisher).publish(metricsCaptor.capture()); + MetricCollection capturedMetrics = metricsCaptor.getValue(); + assertThat(capturedMetrics.metricValues(CoreMetric.SERVICE_ID)).contains("S3"); + assertThat(capturedMetrics.metricValues(CoreMetric.OPERATION_NAME)).contains("PresignedUrlDownload"); + break; + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("invalidUrlTestCases") + void given_AsyncPresignedUrlExtension_when_GetObjectWithInvalidUrl_then_ShouldThrowException( + String testName, String invalidUrlString) { + assertThatThrownBy(() -> { + URL invalidUrl = new URL(invalidUrlString); + PresignedUrlDownloadRequest invalidRequest = PresignedUrlDownloadRequest.builder() + .presignedUrl(invalidUrl) + .build(); + presignedUrlExtension.getObject(invalidRequest, AsyncResponseTransformer.toBytes()).join(); + }).satisfiesAnyOf( + ex -> assertThat(ex).isInstanceOf(java.net.MalformedURLException.class), + ex -> assertThat(ex).isInstanceOf(SdkClientException.class), + ex -> assertThat(ex).isInstanceOf(java.util.concurrent.CompletionException.class) + .extracting(Throwable::getCause) + .isInstanceOf(SdkClientException.class) + ); + } + + private SdkClientConfiguration getDefaultSdkConfigs() { + return SdkClientConfiguration.builder() + .option(SdkClientOption.ASYNC_HTTP_CLIENT, mockHttpClient) + .option(SdkClientOption.ADDITIONAL_HTTP_HEADERS, Collections.emptyMap()) + .option(SdkClientOption.EXECUTION_INTERCEPTORS, Collections.emptyList()) + .option(SdkClientOption.RETRY_STRATEGY, AwsRetryStrategy.doNotRetry()) + .option(SdkAdvancedClientOption.USER_AGENT_PREFIX, "") + .option(SdkAdvancedClientOption.USER_AGENT_SUFFIX, "") + .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false) + .option(AwsClientOption.CREDENTIALS_IDENTITY_PROVIDER, AnonymousCredentialsProvider.create()) + .option(AwsClientOption.AWS_REGION, Region.US_EAST_2) + .option(AwsClientOption.SIGNING_REGION, Region.US_EAST_2) + .option(AwsClientOption.SERVICE_SIGNING_NAME, Region.AP_EAST_2.toString()) + .option(AwsAdvancedClientOption.ENABLE_DEFAULT_REGION_DETECTION, false) + .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, Executors.newScheduledThreadPool(1)) + .option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR, Runnable::run) + .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + software.amazon.awssdk.core.ClientEndpointProvider.forEndpointOverride(DEFAULT_ENDPOINT)) + .build(); + } + + private AwsS3ProtocolFactory initProtocolFactory(SdkClientConfiguration configuration) { + return AwsS3ProtocolFactory.builder() + .registerModeledException( + ExceptionMetadata.builder().errorCode("NoSuchKey") + .exceptionBuilderSupplier(NoSuchKeyException::builder) + .httpStatusCode(404).build()) + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidObjectState") + .exceptionBuilderSupplier(InvalidObjectStateException::builder) + .httpStatusCode(403).build()) + .clientConfiguration(configuration) + .defaultServiceExceptionSupplier(S3Exception::builder) + .build(); + } + + private static URL createTestUrl() { + try { + return new URL(TEST_URL); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void assertSuccessfulGetObject(PresignedUrlDownloadRequest request) { + try { + CompletableFuture> future = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + ResponseBytes result = future.get(); + + assertThat(result).isNotNull(); + assertThat(result.asUtf8String()).isEqualTo(TEST_CONTENT); + + SdkHttpRequest lastRequest = mockHttpClient.getLastRequest(); + assertThat(lastRequest.method()).isEqualTo(SdkHttpMethod.GET); + assertThat(lastRequest.getUri().toString()).contains("test-bucket.s3.us-east-1.amazonaws.com/test-key"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("checksumValidationTestCases") + void getObject_withChecksumHeaderInResponse_shouldDownloadSuccessfully( + String testName, + HttpExecuteResponse response, + String testUrl, + boolean expectSuccess) throws Exception { + + mockHttpClient.stubNextResponse(response); + + URL presignedUrl = new URL(testUrl); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + CompletableFuture> future = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes result = future.get(); + assertThat(result).isNotNull(); + assertThat(result.asUtf8String()).isEqualTo(TEST_CONTENT); + } + + private static Stream checksumValidationTestCases() { + // CRC32 of "test-content" = 0x6B59FCDE → base64 = a1n83g== + String correctCrc32 = "a1n83g=="; + String urlWithChecksumSigned = "https://test-bucket.s3.us-east-1.amazonaws.com/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-Date=20250707T000000Z&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=test-signature&" + + "X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20250707%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Expires=600"; + + return Stream.of( + Arguments.of( + "With checksum in response - should succeed", + createResponseWithChecksum("x-amz-checksum-crc32", correctCrc32), + urlWithChecksumSigned, + true + ), + Arguments.of( + "No checksum header in response - should succeed without validation", + createSuccessResponse(), + TEST_URL, + true + ) + ); + } + + private static HttpExecuteResponse createResponseWithChecksum(String checksumHeader, String checksumValue) { + SdkHttpFullResponse httpResponse = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("Content-Length", "12") + .putHeader("ETag", "\"test-etag\"") + .putHeader("Content-Type", "text/plain") + .putHeader(checksumHeader, checksumValue) + .build(); + return HttpExecuteResponse.builder() + .response(httpResponse) + .responseBody(AbortableInputStream.create( + new ByteArrayInputStream(TEST_CONTENT.getBytes(StandardCharsets.UTF_8)))) + .build(); + } + + private static HttpExecuteResponse createSuccessResponse() { + SdkHttpFullResponse httpResponse = SdkHttpFullResponse.builder() + .statusCode(200) + .putHeader("Content-Length", "12") + .putHeader("ETag", "\"test-etag\"") + .putHeader("Content-Type", "text/plain") + .build(); + return HttpExecuteResponse.builder() + .response(httpResponse) + .responseBody(AbortableInputStream.create( + new ByteArrayInputStream(TEST_CONTENT.getBytes(StandardCharsets.UTF_8)))) + .build(); + } + + private static HttpExecuteResponse createErrorResponse(int statusCode, String errorCode, String errorMessage) { + String errorContent = String.format( + "%s%s", + errorCode, errorMessage); + SdkHttpFullResponse httpResponse = SdkHttpFullResponse.builder() + .statusCode(statusCode) + .putHeader("x-amz-request-id", "test-request-id") + .putHeader("x-amz-id-2", "test-extended-request-id") + .build(); + return HttpExecuteResponse.builder() + .response(httpResponse) + .responseBody(AbortableInputStream.create( + new ByteArrayInputStream(errorContent.getBytes(StandardCharsets.UTF_8)))) + .build(); + } +} \ No newline at end of file diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlChecksumValidationWiremockTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlChecksumValidationWiremockTest.java new file mode 100644 index 000000000000..fc2a7a26cf97 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlChecksumValidationWiremockTest.java @@ -0,0 +1,216 @@ +/* + * 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.presignedurl; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import java.net.URL; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.checksums.ChecksumValidation; +import software.amazon.awssdk.core.exception.SdkClientException; +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.regions.Region; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +/** + * WireMock test verifying checksum validation behavior for presigned URL downloads. + */ +@WireMockTest +class PresignedUrlChecksumValidationWiremockTest { + + private static final String BODY = "test-content-for-checksum"; + private static final String CORRECT_CRC32 = "HUUjuQ=="; // CRC32 of "test-content-for-checksum" + private static final String INCORRECT_CRC32 = "AAAAAAAA=="; + + private S3AsyncClient s3Client; + private final AtomicReference checksumValidationStatus = new AtomicReference<>(); + + @BeforeEach + void setUp(WireMockRuntimeInfo wmInfo) { + checksumValidationStatus.set(null); + s3Client = S3AsyncClient.builder() + .endpointOverride(java.net.URI.create(wmInfo.getHttpBaseUrl())) + .region(Region.US_EAST_1) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .forcePathStyle(true) + .overrideConfiguration(c -> c.addExecutionInterceptor(new ExecutionInterceptor() { + @Override + public void afterExecution(Context.AfterExecution context, ExecutionAttributes attrs) { + checksumValidationStatus.set( + attrs.getAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION)); + } + })) + .build(); + } + + @AfterEach + void tearDown() { + if (s3Client != null) { + s3Client.close(); + } + } + + @Test + void getObject_withMatchingChecksum_shouldSucceed(WireMockRuntimeInfo wmInfo) throws Exception { + stubFor(get(urlPathEqualTo("/test-key")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", String.valueOf(BODY.length())) + .withHeader("x-amz-checksum-crc32", CORRECT_CRC32) + .withHeader("x-amz-checksum-type", "FULL_OBJECT") + .withBody(BODY))); + + URL presignedUrl = new URL(wmInfo.getHttpBaseUrl() + "/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=fake&" + + "X-Amz-Expires=600"); + + ResponseBytes result = s3Client.presignedUrlExtension() + .getObject( + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + AsyncResponseTransformer.toBytes()) + .join(); + + assertThat(result.asUtf8String()).isEqualTo(BODY); + assertThat(checksumValidationStatus.get()) + .isEqualTo(ChecksumValidation.VALIDATED); + } + + @Test + void getObject_withMismatchingChecksum_shouldThrow(WireMockRuntimeInfo wmInfo) throws Exception { + stubFor(get(urlPathEqualTo("/test-key")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", String.valueOf(BODY.length())) + .withHeader("x-amz-checksum-crc32", INCORRECT_CRC32) + .withHeader("x-amz-checksum-type", "FULL_OBJECT") + .withBody(BODY))); + + URL presignedUrl = new URL(wmInfo.getHttpBaseUrl() + "/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=fake&" + + "X-Amz-Expires=600"); + + CompletableFuture> future = s3Client.presignedUrlExtension() + .getObject( + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + AsyncResponseTransformer.toBytes()); + + assertThatThrownBy(future::join) + .hasCauseInstanceOf(SdkClientException.class) + .hasMessageContaining("checksum"); + } + + @Test + void getObject_withNoChecksumHeader_shouldSucceedWithoutValidation(WireMockRuntimeInfo wmInfo) throws Exception { + stubFor(get(urlPathEqualTo("/test-key")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", String.valueOf(BODY.length())) + .withBody(BODY))); + + URL presignedUrl = new URL(wmInfo.getHttpBaseUrl() + "/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host&" + + "X-Amz-Signature=fake&" + + "X-Amz-Expires=600"); + + ResponseBytes result = s3Client.presignedUrlExtension() + .getObject( + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + AsyncResponseTransformer.toBytes()) + .join(); + + assertThat(result.asUtf8String()).isEqualTo(BODY); + assertThat(checksumValidationStatus.get()).isNull(); + } + + @Test + void getObject_withChecksumModeButNoChecksumInResponse_shouldSetAlgorithmNotFound(WireMockRuntimeInfo wmInfo) + throws Exception { + // URL has checksum mode signed, but S3 response has no checksum header (e.g., ranged GET on single-PUT) + stubFor(get(urlPathEqualTo("/test-key")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", String.valueOf(BODY.length())) + .withBody(BODY))); + + URL presignedUrl = new URL(wmInfo.getHttpBaseUrl() + "/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=fake&" + + "X-Amz-Expires=600"); + + ResponseBytes result = s3Client.presignedUrlExtension() + .getObject( + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + AsyncResponseTransformer.toBytes()) + .join(); + + assertThat(result.asUtf8String()).isEqualTo(BODY); + assertThat(checksumValidationStatus.get()) + .isEqualTo(ChecksumValidation.CHECKSUM_ALGORITHM_NOT_FOUND); + } + + @Test + void getObject_withCompositeChecksum_shouldSkipValidationAndSucceed(WireMockRuntimeInfo wmInfo) throws Exception { + stubFor(get(urlPathEqualTo("/test-key")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Length", String.valueOf(BODY.length())) + .withHeader("x-amz-checksum-crc32", "i0T6cA==-3") + .withHeader("x-amz-checksum-type", "COMPOSITE") + .withBody(BODY))); + + URL presignedUrl = new URL(wmInfo.getHttpBaseUrl() + "/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=fake&" + + "X-Amz-Expires=600"); + + ResponseBytes result = s3Client.presignedUrlExtension() + .getObject( + PresignedUrlDownloadRequest.builder().presignedUrl(presignedUrl).build(), + AsyncResponseTransformer.toBytes()) + .join(); + + assertThat(result.asUtf8String()).isEqualTo(BODY); + assertThat(checksumValidationStatus.get()) + .isEqualTo(ChecksumValidation.FORCE_SKIP); + + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshallerTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshallerTest.java new file mode 100644 index 000000000000..900b40940c19 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/PresignedUrlDownloadRequestMarshallerTest.java @@ -0,0 +1,309 @@ +/* + * 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.presignedurl; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.concurrent.CompletionException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; +import org.junit.jupiter.params.provider.ValueSource; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpMethod; +import software.amazon.awssdk.protocols.core.OperationInfo; +import software.amazon.awssdk.protocols.core.ProtocolMarshaller; +import software.amazon.awssdk.protocols.xml.AwsXmlProtocolFactory; +import software.amazon.awssdk.services.s3.internal.presignedurl.model.PresignedUrlDownloadRequestWrapper; + +class PresignedUrlDownloadRequestMarshallerTest { + + private PresignedUrlDownloadRequestMarshaller marshaller; + private AwsXmlProtocolFactory mockProtocolFactory; + private ProtocolMarshaller mockProtocolMarshaller; + private URL testUrl; + + @BeforeEach + void setUp() throws Exception { + mockProtocolFactory = mock(AwsXmlProtocolFactory.class); + mockProtocolMarshaller = mock(ProtocolMarshaller.class); + when(mockProtocolFactory.createProtocolMarshaller(any(OperationInfo.class))) + .thenReturn(mockProtocolMarshaller); + marshaller = new PresignedUrlDownloadRequestMarshaller(mockProtocolFactory); + + testUrl = new URL("https://test-bucket.s3.us-east-1.amazonaws.com/test-key?" + + "X-Amz-Date=20231215T000000Z&" + + "X-Amz-Signature=example-signature&" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host&" + + "X-Amz-Security-Token=xxx&" + + "X-Amz-Credential=EXAMPLE12345678901234%2F20231215%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Expires=3600"); + } + + @Test + void marshall_withBasicRequest_shouldCreateCorrectHttpRequest() throws Exception { + // Setup the mock marshaller to return a properly configured request + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(testUrl) + .build(); + SdkHttpFullRequest result = marshaller.marshall(request); + + // Verify HTTP method and URI components + assertThat(result.method()).isEqualTo(SdkHttpMethod.GET); + assertThat(result.getUri()) + .satisfies(uri -> { + assertThat(uri.getScheme()).isEqualTo("https"); + assertThat(uri.getHost()).isEqualTo("test-bucket.s3.us-east-1.amazonaws.com"); + assertThat(uri.getPath()).isEqualTo("/test-key"); + }); + + // Verify query parameters are preserved + assertThat(result.getUri().getQuery()) + .contains("X-Amz-Date=20231215T000000Z") + .contains("X-Amz-Signature=example-signature") + .contains("X-Amz-Algorithm=AWS4-HMAC-SHA256") + .contains("X-Amz-SignedHeaders=host") + .contains("X-Amz-Security-Token=xxx") + .contains("X-Amz-Credential=EXAMPLE12345678901234") + .contains("X-Amz-Expires=3600"); + + assertThat(result.headers()).doesNotContainKey("Range"); + } + + @ParameterizedTest + @ValueSource(strings = { + "bytes=0-100", // First 101 bytes + "bytes=100-", // From byte 100 to end + "bytes=-100", // Last 100 bytes + "bytes=0-0", // Single byte + "bytes=100-200" // Specific range + }) + void marshall_withValidRangeFormats_shouldAddRangeHeader(String rangeValue) throws Exception { + // Setup the mock marshaller to return a request with the Range header already set + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .putHeader("Range", rangeValue) // Add the Range header to the mock response + .build(); + + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(testUrl) + .range(rangeValue) + .build(); + + SdkHttpFullRequest result = marshaller.marshall(request); + + // Verify the Range header is preserved + assertThat(result.headers()) + .containsKey("Range") + .satisfies(headers -> assertThat(headers.get("Range")).contains(rangeValue)); + } + + @ParameterizedTest + @NullAndEmptySource + void marshall_withNullOrEmptyRange_shouldNotAddRangeHeader(String rangeValue) throws Exception { + // Setup the mock marshaller to return a properly configured request + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(testUrl) + .range(rangeValue) + .build(); + SdkHttpFullRequest result = marshaller.marshall(request); + + assertThat(result.headers()).doesNotContainKey("Range"); + } + + @Test + void marshall_withNullRequest_shouldThrowException() { + assertThatThrownBy(() -> marshaller.marshall(null)) + .isInstanceOf(NullPointerException.class) + .hasMessageContaining("presignedUrlDownloadRequestWrapper must not be null"); + } + + @Test + void marshall_withChecksumModeInSignedHeaders_shouldAddChecksumHeader() throws Exception { + URL urlWithChecksum = new URL("https://test-bucket.s3.us-east-1.amazonaws.com/test-key?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-SignedHeaders=host%3Bx-amz-checksum-mode&" + + "X-Amz-Signature=abc123&" + + "X-Amz-Expires=600"); + + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(urlWithChecksum) + .build(); + SdkHttpFullRequest result = marshaller.marshall(request); + + assertThat(result.headers()).containsKey("x-amz-checksum-mode"); + assertThat(result.firstMatchingHeader("x-amz-checksum-mode")).hasValue("ENABLED"); + } + + @Test + void marshall_withoutChecksumModeInSignedHeaders_shouldNotAddChecksumHeader() throws Exception { + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(testUrl) + .build(); + SdkHttpFullRequest result = marshaller.marshall(request); + + assertThat(result.headers()).doesNotContainKey("x-amz-checksum-mode"); + } + + @Test + void marshall_withNoQueryString_shouldNotAddChecksumHeader() throws Exception { + URL urlNoQuery = new URL("https://test-bucket.s3.us-east-1.amazonaws.com/test-key"); + + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(urlNoQuery) + .build(); + SdkHttpFullRequest result = marshaller.marshall(request); + + assertThat(result.headers()).doesNotContainKey("x-amz-checksum-mode"); + } + + @Test + void marshall_withMalformedUrl_shouldThrowSdkClientException() throws Exception { + // Setup the mock marshaller to return a properly configured request + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + URL malformedUrl = new URL("https", "test-bucket.s3.us-east-1.amazonaws.com", -1, "/test key with spaces"); + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(malformedUrl) + .build(); + + assertThatThrownBy(() -> marshaller.marshall(request)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("Unable to marshall pre-signed URL Request"); + } + + @Test + void marshall_withMalformedUrl_shouldNotLeakPresignedUrlInExceptionMessage() throws Exception { + SdkHttpFullRequest baseRequest = SdkHttpFullRequest.builder() + .method(SdkHttpMethod.GET) + .protocol("https") + .host("example.com") + .build(); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))) + .thenReturn(baseRequest); + + URL malformedUrl = new URL("https", "test-bucket.s3.us-east-1.amazonaws.com", -1, + "/my key.txt?X-Amz-Signature=deadbeef&X-Amz-Security-Token=TOKEN"); + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(malformedUrl) + .build(); + + assertThatThrownBy(() -> marshaller.marshall(request)) + .isInstanceOf(SdkClientException.class) + .hasMessage("Unable to marshall pre-signed URL Request for " + + "https://test-bucket.s3.us-east-1.amazonaws.com/my key.txt?*** Sensitive Data Redacted ***: " + + "Illegal character in path at index 49") + .satisfies(e -> assertThat(e.toString()).doesNotContain("X-Amz-Signature", "deadbeef", "TOKEN")) + .satisfies(e -> assertThat(String.valueOf(new CompletionException(e))) + .doesNotContain("X-Amz-Signature", "deadbeef", "TOKEN")) + .satisfies(e -> assertThat(stackTraceOf(e)).doesNotContain("X-Amz-Signature", "deadbeef", "TOKEN")) + .satisfies(e -> assertThat(e.getCause()) + .isInstanceOf(URISyntaxException.class) + .hasMessage("Illegal character in path at index 49: " + + "https://test-bucket.s3.us-east-1.amazonaws.com/my key.txt?*** Sensitive Data Redacted ***")) + .satisfies(e -> assertThat(e.getCause().getStackTrace()[0].getClassName()).startsWith("java.net.")); + } + + @Test + void marshall_whenProtocolMarshallerFails_shouldReplaceCauseWithItsTypeAndRedactedUrl() { + IllegalStateException failure = new IllegalStateException("failed for " + testUrl); + when(mockProtocolMarshaller.marshall(any(PresignedUrlDownloadRequestWrapper.class))).thenThrow(failure); + + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(testUrl) + .build(); + + assertThatThrownBy(() -> marshaller.marshall(request)) + .isInstanceOf(SdkClientException.class) + .hasMessage("Unable to marshall pre-signed URL Request for " + + "https://test-bucket.s3.us-east-1.amazonaws.com/test-key?*** Sensitive Data Redacted ***: " + + "java.lang.IllegalStateException") + .satisfies(e -> assertThat(stackTraceOf(e)) + .doesNotContain("X-Amz-Signature", "example-signature", "X-Amz-Security-Token", "X-Amz-Credential")) + .satisfies(e -> assertThat(e.getCause()) + .isInstanceOf(SdkClientException.class) + .hasMessage("java.lang.IllegalStateException for " + + "https://test-bucket.s3.us-east-1.amazonaws.com/test-key?*** Sensitive Data Redacted ***")) + .satisfies(e -> assertThat(e.getCause().getStackTrace()).isEqualTo(failure.getStackTrace())); + } + + private static String stackTraceOf(Throwable throwable) { + StringWriter writer = new StringWriter(); + throwable.printStackTrace(new PrintWriter(writer, true)); + return writer.toString(); + } +} \ No newline at end of file diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapperTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapperTest.java new file mode 100644 index 000000000000..8b301a332199 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/presignedurl/model/PresignedUrlDownloadRequestWrapperTest.java @@ -0,0 +1,118 @@ +/* + * 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.presignedurl.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URL; +import java.util.List; +import java.util.Map; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.protocol.MarshallLocation; + + +class PresignedUrlDownloadRequestWrapperTest { + @Test + void equalsAndHashCode_shouldFollowContract() { + EqualsVerifier.forClass(PresignedUrlDownloadRequestWrapper.class) + .withRedefinedSuperclass() + .verify(); + } + + @Test + void basicProperties_shouldWork() throws Exception { + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(new URL("https://example.com")) + .range("bytes=0-100") + .ifMatch("\"etag-123\"") + .build(); + + assertThat(request.url()).isEqualTo(new URL("https://example.com")); + assertThat(request.range()).isEqualTo("bytes=0-100"); + assertThat(request.ifMatch()).isEqualTo("\"etag-123\""); + } + + @Test + void sdkFields_shouldReturnExpectedFields() throws Exception { + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(new URL("https://example.com")) + .range("bytes=0-100") + .build(); + + List> fields = request.sdkFields(); + + assertThat(fields).hasSize(2); + assertThat(fields).extracting(SdkField::memberName) + .containsExactlyInAnyOrder("Range", "IfMatch"); + assertThat(fields).allMatch(field -> field.location() == MarshallLocation.HEADER); + SdkField rangeField = fields.stream() + .filter(f -> "Range".equals(f.memberName())) + .findFirst() + .orElseThrow(() -> new AssertionError("Range field not found")); + Object rangeValue = rangeField.getValueOrDefault(request); + assertThat(rangeValue).isNotNull(); + assertThat(rangeValue).isEqualTo("bytes=0-100"); + } + + @Test + void sdkFieldNameToField_shouldReturnExpectedMapping() throws Exception { + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(new URL("https://example.com")) + .build(); + + Map> fieldMap = request.sdkFieldNameToField(); + + assertThat(fieldMap) + .hasSize(2) + .containsKeys("Range", "IfMatch"); + assertThat(fieldMap.get("Range").memberName()).isEqualTo("Range"); + assertThat(fieldMap.get("IfMatch").memberName()).isEqualTo("IfMatch"); + } + + @Test + void rangeField_shouldMarshalCorrectly() throws Exception { + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(new URL("https://example.com")) + .range("bytes=0-1023") + .build(); + + SdkField rangeField = request.sdkFields().stream() + .filter(f -> "Range".equals(f.memberName())) + .findFirst() + .orElseThrow(() -> new AssertionError("Range field not found")); + Object extractedValue = rangeField.getValueOrDefault(request); + + assertThat(extractedValue).isEqualTo("bytes=0-1023"); + } + + @Test + void ifMatchField_shouldMarshalCorrectly() throws Exception { + PresignedUrlDownloadRequestWrapper request = PresignedUrlDownloadRequestWrapper.builder() + .url(new URL("https://example.com")) + .ifMatch("\"etag-value\"") + .build(); + + SdkField ifMatchField = request.sdkFields().stream() + .filter(f -> "IfMatch".equals(f.memberName())) + .findFirst() + .orElseThrow(() -> new AssertionError("IfMatch field not found")); + Object extractedValue = ifMatchField.getValueOrDefault(request); + + assertThat(extractedValue).isEqualTo("\"etag-value\""); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtilsTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtilsTest.java index 53d84f42ad66..ca358c8605f5 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtilsTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/s3express/S3ExpressUtilsTest.java @@ -22,8 +22,10 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; import org.junit.jupiter.api.Test; import software.amazon.awssdk.services.s3.model.GetObjectRequest; @@ -58,54 +60,114 @@ void isS3ExpressBucket_noBucketField_returnsFalse() { } /** - * Validates that the S3Express bucket suffix used in {@link S3ExpressUtils#isS3ExpressBucket} matches the suffix - * defined in the endpoint ruleset. + * Validates that the S3Express bucket suffix used in {@link S3ExpressUtils#isS3ExpressBucket} is one the endpoint + * model tests for, and that the model tests for it the same way: as the trailing characters of the bucket name. + * + *

    The model compares several trailing substrings of the bucket name ({@code --x-s3}, {@code --xa-s3}, and a + * bare {@code --}), so this looks for the S3Express one among them rather than expecting a single such condition. */ @Test - void isS3ExpressBucket_suffixMatchesEndpointRuleset() throws IOException { - String rulesetSuffix = extractBucketSuffixFromRuleset(); - assertThat(rulesetSuffix).isEqualTo("--x-s3"); + void isS3ExpressBucket_suffixMatchesEndpointModel() throws IOException { + String suffix = "--x-s3"; + Map modelSuffixChecks = trailingBucketSuffixChecks(); + + assertThat(modelSuffixChecks) + .as("the endpoint model should compare a trailing substring of the bucket name against '%s'", suffix) + .containsKey(suffix); + assertThat(modelSuffixChecks.get(suffix)) + .as("the model compares the trailing characters of the bucket name against '%s', so it must compare " + + "exactly %s of them", suffix, suffix.length()) + .isEqualTo(suffix.length()); + GetObjectRequest request = GetObjectRequest.builder() - .bucket("test-bucket" + rulesetSuffix) + .bucket("test-bucket" + suffix) .key("key") .build(); assertThat(S3ExpressUtils.isS3ExpressBucket(request)) - .as("isS3ExpressBucket should recognize the suffix '%s' from the endpoint ruleset", rulesetSuffix) + .as("isS3ExpressBucket should recognize the suffix '%s' from the endpoint model", suffix) .isTrue(); } /** - * Parses the endpoint-rule-set.json and extracts the S3Express bucket suffix. + * Parses endpoint-bdd-1.json and returns every suffix the model compares the end of the bucket name against, + * mapped to the number of trailing characters it compares. */ - private String extractBucketSuffixFromRuleset() throws IOException { - Path rulesetPath = Paths.get("src/main/resources/codegen-resources/endpoint-rule-set.json"); - assertThat(rulesetPath.toFile()).as("endpoint-rule-set.json should exist").exists(); - JsonNode root = MAPPER.readTree(rulesetPath.toFile()); - List suffixes = new ArrayList<>(); - findBucketSuffixValues(root, suffixes); - assertThat(suffixes) - .as("Expected exactly one bucketSuffix stringEquals check in the endpoint ruleset") - .hasSize(1); - return suffixes.get(0); + private Map trailingBucketSuffixChecks() throws IOException { + Path modelPath = Paths.get("src/main/resources/codegen-resources/endpoint-bdd-1.json"); + assertThat(modelPath.toFile()).as("endpoint-bdd-1.json should exist").exists(); + + JsonNode conditions = MAPPER.readTree(modelPath.toFile()).path("conditions"); + assertThat(conditions.isArray()).as("the endpoint BDD model should declare a conditions array").isTrue(); + + Map checks = new LinkedHashMap<>(); + for (JsonNode condition : conditions) { + bucketSuffixCheck(condition).ifPresent(check -> checks.putIfAbsent(check.suffix, check.substringLength)); + } + assertThat(checks) + .as("the endpoint BDD model should compare the end of the bucket name against at least one suffix") + .isNotEmpty(); + return checks; } - private void findBucketSuffixValues(JsonNode node, List results) { - if (node.isObject() && "stringEquals".equals(node.path("fn").asText(null))) { + /** + * Matches {@code stringEquals(, "")}. The BDD model inlines that substring + * into the condition; the rules model it replaced bound it to a named {@code bucketSuffix} variable first, so this + * matches on the shape of the comparison rather than on a variable name. + */ + private Optional bucketSuffixCheck(JsonNode condition) { + if (!"stringEquals".equals(condition.path("fn").asText(null))) { + return Optional.empty(); + } + JsonNode argv = condition.path("argv"); + if (!argv.isArray() || argv.size() != 2) { + return Optional.empty(); + } + for (int i = 0; i < 2; i++) { + JsonNode literal = argv.get(i); + if (!literal.isTextual()) { + continue; + } + OptionalInt substringLength = trailingBucketSubstringLength(argv.get(1 - i)); + if (substringLength.isPresent()) { + return Optional.of(new BucketSuffixCheck(literal.asText(), substringLength.getAsInt())); + } + } + return Optional.empty(); + } + + /** + * Returns the length of the trailing substring of {@code Bucket} this expression takes, if it takes one: + * {@code substring(Bucket, start, stop, true)}, where the trailing {@code true} means "counting from the end". The + * call may be wrapped, in the S3 model by a {@code coalesce} that defaults to an empty string. + */ + private OptionalInt trailingBucketSubstringLength(JsonNode node) { + if ("substring".equals(node.path("fn").asText(null))) { JsonNode argv = node.path("argv"); - if (argv.isArray() && argv.size() == 2) { - for (int i = 0; i < 2; i++) { - JsonNode arg = argv.get(i); - JsonNode other = argv.get(1 - i); - if (arg.isObject() && "bucketSuffix".equals(arg.path("ref").asText(null)) - && other.isTextual()) { - results.add(other.asText()); - return; - } - } + if (argv.isArray() && argv.size() == 4 + && "Bucket".equals(argv.get(0).path("ref").asText(null)) + && argv.get(3).asBoolean(false)) { + return OptionalInt.of(argv.get(2).asInt() - argv.get(1).asInt()); } } for (JsonNode child : node) { - findBucketSuffixValues(child, results); + OptionalInt substringLength = trailingBucketSubstringLength(child); + if (substringLength.isPresent()) { + return substringLength; + } + } + return OptionalInt.empty(); + } + + /** + * The suffix the endpoint model compares the bucket name against, and the number of trailing characters it compares. + */ + private static final class BucketSuffixCheck { + private final String suffix; + private final int substringLength; + + private BucketSuffixCheck(String suffix, int substringLength) { + this.suffix = suffix; + this.substringLength = substringLength; } } } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTest.java new file mode 100644 index 000000000000..1b99c9bde491 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/AsyncPresignedUrlExtensionTest.java @@ -0,0 +1,522 @@ +/* + * 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.presignedurl; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.exactly; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +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 java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import com.github.tomakehurst.wiremock.http.Fault; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.github.tomakehurst.wiremock.stubbing.Scenario; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.presignedurl.model.PresignedUrlDownloadRequest; + +@WireMockTest +public class AsyncPresignedUrlExtensionTest { + + private S3AsyncClient s3AsyncClient; + private AsyncPresignedUrlExtension presignedUrlExtension; + + @TempDir + Path tempDir; + + @BeforeEach + void setup(WireMockRuntimeInfo wireMockRuntimeInfo) { + s3AsyncClient = S3AsyncClient.builder() + .endpointOverride(URI.create(wireMockRuntimeInfo.getHttpBaseUrl())) + .build(); + presignedUrlExtension = s3AsyncClient.presignedUrlExtension(); + } + + @AfterEach + void cleanup() { + if (s3AsyncClient != null) { + s3AsyncClient.close(); + } + } + + @Nested + class BasicFunctionality { + @Test + void givenS3AsyncClient_whenPresignedUrlExtensionRequested_thenReturnsNonNullInstance() { + assertThat(presignedUrlExtension).isNotNull(); + } + + @Test + void givenValidPresignedUrl_whenGetObjectCalled_thenReturnsExpectedContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "Hello world"; + String testETag = "\"d6eb32081c822ed572b70567826d9d9d\""; + String presignedUrlPath = "/presigned-test-object"; + + stubSuccessResponse(presignedUrlPath, testContent, testETag); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes response = result.get(); + assertSuccessfulResponse(response, testContent, testETag); + } + + @Test + void givenValidPresignedUrl_whenGetObjectWithConsumerBuilderCalled_thenReturnsExpectedContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "Hello consumer"; + String testETag = "\"c1234567890abcdef1234567890abcdef\""; + String presignedUrlPath = "/presigned-test-consumer"; + + stubSuccessResponse(presignedUrlPath, testContent, testETag); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + + CompletableFuture> result = + presignedUrlExtension.getObject( + request -> request.presignedUrl(presignedUrl), + AsyncResponseTransformer.toBytes() + ); + + ResponseBytes response = result.get(); + assertSuccessfulResponse(response, testContent, testETag); + } + + @Test + void givenEmptyFile_whenGetObjectCalled_thenReturnsEmptyContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = ""; + String testETag = "\"empty-file-etag\""; + String presignedUrlPath = "/empty-file-memory"; + + // Using custom stubbing for empty file to include Content-Length header + stubFor(get(urlEqualTo(presignedUrlPath)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", testETag) + .withHeader("Content-Length", "0") + .withBody(testContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.asByteArray()).isEmpty(); + assertThat(response.response().eTag()).isEqualTo(testETag); + } + + @Test + void givenRangeRequest_whenGetObjectCalled_thenReturnsPartialContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String expectedContent = "Hello"; + String contentRange = "bytes 0-4/11"; + String range = "bytes=0-4"; + String testETag = "\"d6eb32081c822ed572b70567826d9d9d\""; + String presignedUrlPath = "/presigned-test-range"; + + // Custom stubbing for range request with 206 status + stubFor(get(urlEqualTo(presignedUrlPath)) + .willReturn(aResponse() + .withStatus(206) + .withHeader("ETag", testETag) + .withHeader("Content-Range", contentRange) + .withBody(expectedContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .range(range) + .build(); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.asUtf8String()).isEqualTo(expectedContent); + } + } + + @Nested + class FileDownloads { + @Test + void givenValidPresignedUrl_whenGetObjectToFileCalled_thenDownloadsFileWithExpectedContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "File content for download"; + String testETag = generateRandomETag(); + String presignedUrlPath = "/presigned-test-file"; + + stubSuccessResponse(presignedUrlPath, testContent, testETag); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + Path downloadFile = tempDir.resolve("download-" + UUID.randomUUID() + ".txt"); + + CompletableFuture result = + presignedUrlExtension.getObject(request, downloadFile); + + GetObjectResponse response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.eTag()).isEqualTo(testETag); + + String fileContent = new String(Files.readAllBytes(downloadFile), StandardCharsets.UTF_8); + assertThat(fileContent).isEqualTo(testContent); + } + + @Test + void givenValidPresignedUrl_whenGetObjectToFileWithConsumerBuilderCalled_thenDownloadsFileWithExpectedContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "File content for consumer download"; + String testETag = generateRandomETag(); + String presignedUrlPath = "/presigned-test-consumer-file"; + + stubSuccessResponse(presignedUrlPath, testContent, testETag); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + Path downloadFile = tempDir.resolve("consumer-download-" + UUID.randomUUID() + ".txt"); + + CompletableFuture result = + presignedUrlExtension.getObject( + request -> request.presignedUrl(presignedUrl), + downloadFile + ); + + GetObjectResponse response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.eTag()).isEqualTo(testETag); + + String fileContent = new String(Files.readAllBytes(downloadFile), StandardCharsets.UTF_8); + assertThat(fileContent).isEqualTo(testContent); + } + + @Test + void givenEmptyFile_whenGetObjectToFileCalled_thenDownloadsEmptyFile(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = ""; + String testETag = "\"empty-file-etag\""; + String presignedUrlPath = "/empty-file"; + + // Custom stubbing for empty file to include Content-Length header + stubFor(get(urlEqualTo(presignedUrlPath)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", testETag) + .withHeader("Content-Length", "0") + .withBody(testContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + Path downloadFile = tempDir.resolve("empty-file-" + UUID.randomUUID() + ".txt"); + CompletableFuture result = presignedUrlExtension.getObject(request, downloadFile); + + GetObjectResponse response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.eTag()).isEqualTo(testETag); + assertThat(Files.size(downloadFile)).isEqualTo(0); + } + + @Test + void givenLargeFile_whenGetObjectCalled_thenDownloadsCompleteContent(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + int contentSize = 1024 * 1024 + 512 * 1024; // 1.5MB + byte[] largeContent = new byte[contentSize]; + new Random().nextBytes(largeContent); + + String testETag = "\"large-file-etag\""; + String presignedUrlPath = "/large-file"; + + // Custom stubbing for large file with Content-Length header + stubFor(get(urlEqualTo(presignedUrlPath)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", testETag) + .withHeader("Content-Length", String.valueOf(contentSize)) + .withBody(largeContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + Path downloadFile = tempDir.resolve("large-file-" + UUID.randomUUID() + ".bin"); + CompletableFuture result = presignedUrlExtension.getObject(request, downloadFile); + + GetObjectResponse response = result.get(); + assertThat(response).isNotNull(); + assertThat(response.eTag()).isEqualTo(testETag); + + assertThat(Files.size(downloadFile)).isEqualTo(contentSize); + + byte[] downloadedContent = Files.readAllBytes(downloadFile); + assertThat(downloadedContent).isEqualTo(largeContent); + } + } + + @Nested + class RetryBehavior { + @Test + void givenNetworkError_whenGetObjectCalled_thenRetriesAndEventuallySucceeds(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "Success after network error"; + String testETag = "\"network-retry-etag\""; + String presignedUrlPath = "/network-error-retry"; + String scenarioName = "network-error-scenario"; + + stubFor(get(urlEqualTo(presignedUrlPath)) + .inScenario(scenarioName) + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse() + .withFault(Fault.CONNECTION_RESET_BY_PEER)) + .willSetStateTo("after-network-error")); + + stubFor(get(urlEqualTo(presignedUrlPath)) + .inScenario(scenarioName) + .whenScenarioStateIs("after-network-error") + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", testETag) + .withBody(testContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes response = result.get(); + assertSuccessfulResponse(response, testContent, testETag); + + verify(exactly(2), getRequestedFor(urlEqualTo(presignedUrlPath))); + } + + @Test + void givenTemporaryFailure_whenGetObjectCalled_thenRetriesAndSucceeds(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String testContent = "Success after retry"; + String testETag = "\"retry-success-etag\""; + String presignedUrlPath = "/retry-test"; + String scenarioName = "retry-scenario"; + + stubFor(get(urlEqualTo(presignedUrlPath)) + .inScenario(scenarioName) + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(aResponse() + .withStatus(503) + .withBody("Service Unavailable")) + .willSetStateTo("retry")); + + stubFor(get(urlEqualTo(presignedUrlPath)) + .inScenario(scenarioName) + .whenScenarioStateIs("retry") + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", testETag) + .withBody(testContent))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + ResponseBytes response = result.get(); + assertSuccessfulResponse(response, testContent, testETag); + + verify(exactly(2), getRequestedFor(urlEqualTo(presignedUrlPath))); + } + } + + @Nested + class ErrorScenarios { + @Test + void givenMalformedResponse_whenGetObjectCalled_thenCompletableFutureCompletesExceptionally(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + String presignedUrlPath = "/malformed-response"; + stubFor(get(urlEqualTo(presignedUrlPath)) + .willReturn(aResponse() + .withFault(Fault.CONNECTION_RESET_BY_PEER))); + + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, presignedUrlPath); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + try { + result.get(); + throw new AssertionError("Expected exception was not thrown"); + } catch (ExecutionException e) { + assertThat(e.getCause()).isInstanceOf(SdkClientException.class); + } + } + + @Test + void givenNotFoundError_whenGetObjectCalled_thenCompletableFutureCompletesExceptionally(WireMockRuntimeInfo wireMockRuntimeInfo) { + String urlPath = "/nonexistent-key"; + + stubFor(get(urlEqualTo(urlPath)) + .willReturn(aResponse() + .withStatus(404) + .withBody("NoSuchKey"))); + + URL presignedUrl; + try { + presignedUrl = new URL(wireMockRuntimeInfo.getHttpBaseUrl() + urlPath); + } catch (Exception e) { + throw new RuntimeException(e); + } + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + assertThatThrownBy(() -> result.get()) + .isInstanceOf(ExecutionException.class); + } + + @Test + void givenAccessDeniedError_whenGetObjectCalled_thenCompletableFutureCompletesExceptionally(WireMockRuntimeInfo wireMockRuntimeInfo) { + String urlPath = "/forbidden-key"; + + stubFor(get(urlEqualTo(urlPath)) + .willReturn(aResponse() + .withStatus(403) + .withBody("AccessDenied"))); + + URL presignedUrl; + try { + presignedUrl = new URL(wireMockRuntimeInfo.getHttpBaseUrl() + urlPath); + } catch (Exception e) { + throw new RuntimeException(e); + } + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + + CompletableFuture> result = + presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes()); + + assertThatThrownBy(() -> result.get()) + .isInstanceOf(ExecutionException.class); + } + } + + @Nested + class ConcurrentOperations { + @Test + void givenMultipleRequests_whenGetObjectCalledConcurrently_thenAllDownloadsComplete(WireMockRuntimeInfo wireMockRuntimeInfo) throws Exception { + int concurrentRequests = 5; + List contents = new ArrayList<>(); + List eTags = new ArrayList<>(); + List paths = new ArrayList<>(); + + for (int i = 0; i < concurrentRequests; i++) { + String content = "Content for concurrent download " + i; + String eTag = "\"concurrent-etag-" + i + "\""; + String path = "/concurrent-" + i; + + contents.add(content); + eTags.add(eTag); + paths.add(path); + + stubSuccessResponse(path, content, eTag); + } + + List>> futures = new ArrayList<>(); + for (int i = 0; i < concurrentRequests; i++) { + URL presignedUrl = createPresignedUrl(wireMockRuntimeInfo, paths.get(i)); + PresignedUrlDownloadRequest request = createRequest(presignedUrl); + + futures.add(presignedUrlExtension.getObject(request, AsyncResponseTransformer.toBytes())); + } + + CompletableFuture allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + allFutures.get(); + + for (int i = 0; i < concurrentRequests; i++) { + ResponseBytes response = futures.get(i).get(); + assertSuccessfulResponse(response, contents.get(i), eTags.get(i)); + } + } + } + + // Helper methods + private URL createPresignedUrl(WireMockRuntimeInfo wireMockRuntimeInfo, String path) { + try { + return new URL(wireMockRuntimeInfo.getHttpBaseUrl() + path); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private PresignedUrlDownloadRequest createRequest(URL presignedUrl) { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(presignedUrl) + .build(); + } + + private String generateRandomETag() { + return "\"" + UUID.randomUUID().toString().replace("-", "") + "\""; + } + + private void stubSuccessResponse(String path, String content, String eTag) { + stubFor(get(urlEqualTo(path)) + .willReturn(aResponse() + .withStatus(200) + .withHeader("ETag", eTag) + .withBody(content))); + } + + private void stubErrorResponse(String path, int statusCode, String body) { + stubFor(get(urlEqualTo(path)) + .willReturn(aResponse() + .withStatus(statusCode) + .withBody(body))); + } + + private void assertSuccessfulResponse(ResponseBytes response, String expectedContent, String expectedETag) { + assertThat(response).isNotNull(); + assertThat(response.asUtf8String()).isEqualTo(expectedContent); + assertThat(response.response().eTag()).isEqualTo(expectedETag); + } + +} \ No newline at end of file diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequestTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequestTest.java new file mode 100644 index 000000000000..1dba6cbf28b4 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/presignedurl/model/PresignedUrlDownloadRequestTest.java @@ -0,0 +1,153 @@ +/* + * 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.presignedurl.model; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URL; +import nl.jqno.equalsverifier.EqualsVerifier; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class PresignedUrlDownloadRequestTest { + + @Test + void equalsAndHashCode_shouldFollowContract() { + EqualsVerifier.forClass(PresignedUrlDownloadRequest.class) + .verify(); + } + + @Test + void builder_shouldCreateRequestWithAllFields() throws Exception { + URL url = new URL("https://example.com"); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .range("bytes=0-100") + .build(); + + assertThat(request.presignedUrl()).isEqualTo(url); + assertThat(request.range()).isEqualTo("bytes=0-100"); + } + + @Test + void builder_shouldCreateRequestWithOnlyRequiredFields() throws Exception { + URL url = new URL("https://example.com"); + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build(); + + assertThat(request.presignedUrl()).isEqualTo(url); + assertThat(request.range()).isNull(); + } + + @Test + void toBuilder_shouldCreateBuilderFromExistingRequest() throws Exception { + URL url = new URL("https://example.com"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .range("bytes=0-100") + .build(); + + PresignedUrlDownloadRequest copy = original.toBuilder().build(); + + assertThat(copy.presignedUrl()).isEqualTo(original.presignedUrl()); + assertThat(copy.range()).isEqualTo(original.range()); + } + + @Test + void toBuilder_shouldAllowModification() throws Exception { + URL url1 = new URL("https://example.com"); + URL url2 = new URL("https://other.com"); + PresignedUrlDownloadRequest original = PresignedUrlDownloadRequest.builder() + .presignedUrl(url1) + .range("bytes=0-100") + .build(); + + PresignedUrlDownloadRequest modified = original.toBuilder() + .presignedUrl(url2) + .range("bytes=200-300") + .build(); + + assertThat(modified.presignedUrl()).isEqualTo(url2); + assertThat(modified.range()).isEqualTo("bytes=200-300"); + // Original unchanged + assertThat(original.presignedUrl()).isEqualTo(url1); + assertThat(original.range()).isEqualTo("bytes=0-100"); + } + + @Test + void toString_redactsPresignedUrlQueryString() throws Exception { + URL url = new URL("https://bucket.s3.us-east-1.amazonaws.com/dir/key.txt?" + + "X-Amz-Algorithm=AWS4-HMAC-SHA256&" + + "X-Amz-Credential=AKIAEXAMPLE%2F20240101%2Fus-east-1%2Fs3%2Faws4_request&" + + "X-Amz-Date=20240101T000000Z&" + + "X-Amz-Expires=604800&" + + "X-Amz-Security-Token=SESSIONTOKENEXAMPLE&" + + "X-Amz-SignedHeaders=host&" + + "X-Amz-Signature=deadbeefdeadbeef"); + + PresignedUrlDownloadRequest request = PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .range("bytes=0-100") + .ifMatch("etag") + .build(); + + String result = request.toString(); + + assertThat(result) + .isNotNull() + .isNotEmpty() + .doesNotContain("X-Amz-Signature") + .doesNotContain("deadbeef") + .doesNotContain("X-Amz-Credential") + .doesNotContain("AKIAEXAMPLE") + .doesNotContain("X-Amz-Security-Token") + .doesNotContain("SESSIONTOKENEXAMPLE") + .doesNotContain(url.getQuery()) + .contains("https://bucket.s3.us-east-1.amazonaws.com/dir/key.txt") + .contains("*** Sensitive Data Redacted ***") + .contains("bytes=0-100") + .contains("etag"); + } + + @ParameterizedTest + @CsvSource(delimiter = '|', value = { + "https://example.com/key | https://example.com/key", + "https://example.com | https://example.com", + "https://host:8443/key?X-Amz-Signature=abc | https://host:8443/key?*** Sensitive Data Redacted ***", + "https://***@host/key?X-Amz-Signature=abc#frag| https://host/key?*** Sensitive Data Redacted ***", + "https://host/key#X-Amz-Signature=abc | https://host/key", + "https://host/key? | https://host/key?*** Sensitive Data Redacted ***" + }) + void toString_rendersUrlWithoutQueryString(String url, String expectedUrlRendering) throws Exception { + assertThat(toStringOf(new URL(url))) + .isEqualTo("PresignedUrlDownloadRequest(PresignedUrl=" + expectedUrlRendering + ")"); + } + + @Test + void serializableBuilderClass_shouldReturnCorrectClass() { + assertThat(PresignedUrlDownloadRequest.serializableBuilderClass()) + .isEqualTo(PresignedUrlDownloadRequest.BuilderImpl.class); + } + + private String toStringOf(URL url) { + return PresignedUrlDownloadRequest.builder() + .presignedUrl(url) + .build() + .toString(); + } +} diff --git a/services/s3control/pom.xml b/services/s3control/pom.xml index d814988abf33..ef642d4ea703 100644 --- a/services/s3control/pom.xml +++ b/services/s3control/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3control AWS Java SDK :: Services :: Amazon S3 Control diff --git a/services/s3control/src/main/resources/codegen-resources/customization.config b/services/s3control/src/main/resources/codegen-resources/customization.config index 195563e9149e..44fa62c92b76 100644 --- a/services/s3control/src/main/resources/codegen-resources/customization.config +++ b/services/s3control/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { - "enableGenerateCompiledEndpointRules": true, "serviceConfig": { "className": "S3ControlConfiguration", "hasDualstackProperty": true, diff --git a/services/s3control/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3control/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b932851a98e5 --- /dev/null +++ b/services/s3control/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,1710 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "AccountId": { + "required": false, + "documentation": "The Account ID used to send the request. This is an optional parameter that will be set automatically for operations that require it.", + "type": "string" + }, + "RequiresAccountId": { + "required": false, + "documentation": "Internal parameter for operations that require account id host prefix.", + "type": "boolean" + }, + "OutpostId": { + "required": false, + "documentation": "The Outpost ID. Some operations have an optional OutpostId which should be used in endpoint construction.", + "type": "string" + }, + "Bucket": { + "required": false, + "documentation": "The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.", + "type": "string" + }, + "AccessPointName": { + "required": false, + "documentation": "The S3 AccessPointName used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 AccessPoint.", + "type": "string" + }, + "UseArnRegion": { + "builtIn": "AWS::S3Control::UseArnRegion", + "required": false, + "documentation": "When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN's region when constructing the endpoint instead of the client's configured region.", + "type": "boolean" + }, + "ResourceArn": { + "required": false, + "documentation": "The resource ARN included in the request. Only set on TagResource, UntagResourceand ListTagsForResource", + "type": "string" + }, + "UseS3ExpressControlEndpoint": { + "required": false, + "documentation": "Internal parameter to indicate whether S3Express operation should use control plane, (ex. ListDirectoryAccessPoints)", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "partitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "OutpostId" + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "OutpostId" + }, + false + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "ResourceArn" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "ResourceArn" + } + ], + "assign": "resourceArn" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "resourceArn" + }, + "service" + ] + }, + "s3express" + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "resourceArn" + }, + "region" + ] + } + ], + "assign": "arnPartition_ssa_3" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arnPartition_ssa_3" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseS3ExpressControlEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "parseURL", + "argv": [ + { + "ref": "Endpoint" + } + ], + "assign": "url" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccessPointName" + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 0, + 7, + true + ] + }, + "" + ] + }, + "--xa-s3" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 7, + 15, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 15, + 17, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 7, + 16, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "snow" + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "AccessPointName" + } + ], + "assign": "accessPointArn" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_1" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Bucket" + } + ] + }, + { + "fn": "aws.parseArn", + "argv": [ + { + "ref": "Bucket" + } + ], + "assign": "bucketArn" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[0]" + ], + "assign": "arnType_ssa_2" + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_2" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "service" + ] + }, + "s3-outposts" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[1]" + ], + "assign": "outpostId_ssa_2" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 16, + 18, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "arnType_ssa_1" + }, + "" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "service" + ] + }, + "s3-outposts" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "resourceId[1]" + ], + "assign": "outpostId_ssa_1" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountId" + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "AccountId" + }, + false + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "RequiresAccountId" + }, + false + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountId" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "accountId" + ] + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "Region" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "AccountId" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "UseArnRegion" + }, + true + ] + }, + true + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_2" + }, + false + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "region" + ] + } + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + } + ], + "assign": "arnPartition_ssa_2" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arnPartition_ssa_2" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "region" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + "" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "outpostId_ssa_1" + }, + false + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "region" + ] + } + ], + "assign": "arnPartition_ssa_1" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "arnPartition_ssa_1" + }, + "name" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "partitionResult" + }, + "name" + ] + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "region" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "accountId" + ] + }, + "" + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "accountId" + ] + }, + false + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 7, + 20, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 20, + 22, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 7, + 21, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 21, + 23, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "resourceId[2]" + ], + "assign": "outpostType_ssa_1" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "accessPointArn" + }, + "resourceId[3]" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "outpostType_ssa_1" + }, + "accesspoint" + ] + }, + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 7, + 27, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "fn": "substring", + "argv": [ + { + "ref": "AccessPointName" + }, + 27, + 29, + true + ] + }, + "" + ] + }, + "--" + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[2]" + ], + "assign": "outpostType_ssa_2" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "bucketArn" + }, + "resourceId[3]" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "outpostType_ssa_2" + }, + "bucket" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "resourceArn" + }, + "region" + ] + } + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "error": "AccountId is required but not set", + "type": "error" + }, + { + "conditions": [], + "error": "AccountId must only contain a-z, A-Z, 0-9 and `-`.", + "type": "error" + }, + { + "conditions": [], + "error": "OutpostId must only contain a-z, A-Z, 0-9 and `-`.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: DualStack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{Region}.{partitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{Region}.{partitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid region: region was not a valid DNS name.", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: region from ARN `{resourceArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", + "type": "error" + }, + { + "conditions": [], + "error": "S3Express does not support Dual-stack.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3express", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition_ssa_3#name}`", + "type": "error" + }, + { + "conditions": [], + "error": "Unrecognized S3Express Access Point name format.", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Snow does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "S3 Snow does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid configuration: region from ARN `{accessPointArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: the accountId specified in the ARN (`{accessPointArn#accountId}`) does not match the parameter (`{AccountId}`)", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{accessPointArn#region}.{arnPartition_ssa_1#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{accessPointArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{accessPointArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_1}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{accessPointArn#region}.{arnPartition_ssa_1#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{accessPointArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{accessPointArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_1}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{accessPointArn#region}.{arnPartition_ssa_1#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{accessPointArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{accessPointArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_1}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{accessPointArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{accessPointArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_1}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{accessPointArn#region}.{arnPartition_ssa_1#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{accessPointArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{accessPointArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_1}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Expected an outpost type `accesspoint`, found `{outpostType_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: expected an access point name", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected a 4-component resource", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointArn#accountId}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: missing account ID", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid region in ARN: `{accessPointArn#region}` (invalid DNS name)", + "type": "error" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition_ssa_1#name}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`., found: `{outpostId_ssa_1}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The Outpost Id was not set", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: No ARN type specified", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: the accountId specified in the ARN (`{bucketArn#accountId}`) does not match the parameter (`{AccountId}`)", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{bucketArn#region}.{arnPartition_ssa_2#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{bucketArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_2}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{bucketArn#region}.{arnPartition_ssa_2#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{bucketArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_2}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{bucketArn#region}.{arnPartition_ssa_2#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{bucketArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_2}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{bucketArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_2}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{bucketArn#region}.{arnPartition_ssa_2#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3-outposts", + "signingRegion": "{bucketArn#region}" + } + ] + }, + "headers": { + "x-amz-account-id": [ + "{bucketArn#accountId}" + ], + "x-amz-outpost-id": [ + "{outpostId_ssa_2}" + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid ARN: Expected an outpost type `bucket`, found `{outpostType_ssa_2}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: expected a bucket name", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", + "type": "error" + }, + { + "conditions": [], + "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition_ssa_2#name}`", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`., found: `{outpostId_ssa_2}`", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{AccountId}.{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "{url#scheme}://{url#authority}{url#path}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.s3-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.s3-control-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-control-fips.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.s3-control.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-control.dualstack.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{AccountId}.s3-control.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-control.{Region}.{partitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "disableDoubleEncoding": true, + "name": "sigv4", + "signingName": "s3", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Region must be set", + "type": "error" + } + ], + "root": 2, + "nodeCount": 428, + "nodes": "/////wAAAAH/////AAAAAAAAAAMF9eE+AAAAAQAAABsAAAAEAAAACwAAAAUAAAAGAAAADAAAABcAAAAGAAAADwAAAAcAAAAIAAAAFQAAABEAAAAIAAAAFwAAAAkF9eE+AAAAGAAAAAoF9eE+AAAAGQAAAAsF9eEmAAAAGgX14SYAAAAMAAAAGwAAAA0F9eEmAAAAHAAAAA4F9eElAAAAJwX14TMAAAAPAAAAKAAAABAF9eEzAAAAKgX14TMF9eEnAAAAFgAAABIF9eEmAAAAHgX14SYAAAATAAAAHwAAABQF9eEmAAAAIAAAABUF9eElAAAAJwX14SQAAAAWAAAAKQX14SQAAAFOAAAADwAAABgAAAAZAAAAFQAAAYQAAAAZAAAAFwAAABoF9eE+AAAAGAAAAX8F9eE+AAAAAgAAANYAAAAcAAAABAAAAMkAAAAdAAAABgAAAB4AAAAhAAAABwAAAB8AAAAhAAAACAAAACAAAAAhAAAACQAAAMIAAAAhAAAACwAAAE0AAAAiAAAADAAAACQAAAAjAAAADQAAAKkAAABQAAAADQX14Q0AAAAlAAAADwAAACYAAAAoAAAAEAX14Q0AAAAnAAAAFQAAADwAAAAoAAAAFwAAACkAAAC8AAAAGAAAACoAAAC8AAAAGQAAACsF9eEmAAAAGgX14SYAAAAsAAAAGwAAAC0F9eEmAAAAHAAAAC4F9eElAAAAIQAAAC8AAAAwAAAAJgAAADAAAAEpAAAAJwAAADMAAAAxAAAAKAAAADIF9eEzAAAAKgAAADQF9eEnAAAAKAAAADQF9eEzAAAAKwAAADUF9eEzAAAALAAAADYF9eEyAAAALQAAADcF9eExAAAALgX14SEAAAA4AAAALwAAADkF9eEwAAAAPwAAADoF9eEfAAAAQAAAADsF9eEvAAAAQQX14SsF9eEuAAAAFgAAAD0F9eEmAAAAHgX14SYAAAA+AAAAHwAAAD8F9eEmAAAAIAAAAEAF9eElAAAAIQAAAEEAAABCAAAAJAAAAEIAAAFEAAAAJwAAAEQAAABDAAAAKQAAAEQAAAFOAAAAMAAAAEUF9eEkAAAAMQAAAEYF9eEkAAAAMgAAAEcF9eEjAAAAMwAAAEgF9eEiAAAANAX14SEAAABJAAAANQAAAEoF9eEgAAAAOgAAAEsF9eEfAAAAOwAAAEwF9eEeAAAAPAX14RoF9eEdAAAADAAAALUAAABOAAAADQAAAKgAAABPAAAADgAAAH4AAABQAAAADwAAAFEAAABTAAAAEAAAAKsAAABSAAAAFQAAAG0AAABTAAAAFwAAAFQAAABVAAAAGAAAAFsAAABVAAAAIQAAAFcAAABWAAAAIwAAAXsAAABZAAAAIgAAAFgAAAF9AAAAIwAAAFoAAABZAAAAJQX14T0F9eELAAAAJQX14TwF9eELAAAAGQAAAFwF9eEmAAAAGgX14SYAAABdAAAAGwAAAF4F9eEmAAAAHAAAAF8F9eElAAAAIQAAAGAAAABhAAAAJgAAAGEAAAEpAAAAJwAAAGQAAABiAAAAKAAAAGMF9eEzAAAAKgAAAGUF9eEnAAAAKAAAAGUF9eEzAAAAKwAAAGYF9eEzAAAALAAAAGcF9eEyAAAALQAAAGgF9eExAAAALgX14SEAAABpAAAALwAAAGoF9eEwAAAAPwAAAGsF9eEfAAAAQAAAAGwF9eEvAAAAQQX14S0F9eEuAAAAFgAAAG4F9eEmAAAAHgX14SYAAABvAAAAHwAAAHAF9eEmAAAAIAAAAHEF9eElAAAAIQAAAHIAAABzAAAAJAAAAHMAAAFEAAAAJwAAAHUAAAB0AAAAKQAAAHUAAAFOAAAAMAAAAHYF9eEkAAAAMQAAAHcF9eEkAAAAMgAAAHgF9eEjAAAAMwAAAHkF9eEiAAAANAX14SEAAAB6AAAANQAAAHsF9eEgAAAAOgAAAHwF9eEfAAAAOwAAAH0F9eEeAAAAPAX14RwF9eEdAAAADwAAAIAAAAB/AAAAFAX14RUAAACDAAAAEAX14Q4AAACBAAAAFAX14RUAAACCAAAAFQAAAJcAAACDAAAAFwAAAIQAAAEdAAAAGAAAAIUAAAEdAAAAGQAAAIYF9eEmAAAAGgX14SYAAACHAAAAGwAAAIgF9eEmAAAAHAAAAIkF9eElAAAAIQAAAIoAAACLAAAAJgAAAIsAAAEpAAAAJwAAAI4AAACMAAAAKAAAAI0F9eEzAAAAKgAAAI8F9eEnAAAAKAAAAI8F9eEzAAAAKwAAAJAF9eEzAAAALAAAAJEF9eEyAAAALQAAAJIF9eExAAAALgX14SEAAACTAAAALwAAAJQF9eEwAAAAPwAAAJUF9eEfAAAAQAAAAJYF9eEvAAAAQQX14SwF9eEuAAAAFgAAAJgF9eEmAAAAHgX14SYAAACZAAAAHwAAAJoF9eEmAAAAIAAAAJsF9eElAAAAIQAAAJwAAACdAAAAJAAAAJ0AAAFEAAAAJwAAAJ8AAACeAAAAKQAAAJ8AAAFOAAAAMAAAAKAF9eEkAAAAMQAAAKEF9eEkAAAAMgAAAKIF9eEjAAAAMwAAAKMF9eEiAAAANAX14SEAAACkAAAANQAAAKUF9eEgAAAAOgAAAKYF9eEfAAAAOwAAAKcF9eEeAAAAPAX14RsF9eEdAAAADgX14Q4AAACpAAAADwAAAKoF9eEQAAAAEAAAAKsF9eEQAAAAEQAAAKwAAACtAAAAEgX14RAAAACtAAAAEwAAAK4AAACvAAAAHQX14RAAAACvAAAANgAAALAAAACxAAAANwX14RAAAACxAAAAOAAAALIAAACzAAAAOQX14RAAAACzAAAAPQAAALQF9eESAAAAPgX14RAF9eESAAAADQX14QUAAAC2AAAADgAAAXIAAAC3AAAADwAAALgAAAC6AAAAEAX14QUAAAC5AAAAFQAAAYQAAAC6AAAAFwAAALsAAAC8AAAAGAAAAX8AAAC8AAAAIQAAAL4AAAC9AAAAIwAAAXsAAADAAAAAIgAAAL8AAAF9AAAAIwAAAMEAAADAAAAAJQX14TsF9eELAAAAJQX14ToF9eELAAAACgAAAMMF9eERAAAACwAAAMUAAADEAAAADAAAAYwAAADHAAAADAAAAZQAAADGAAAADgAAAZIAAADHAAAAJwX14RAAAADIAAAAQgX14RAF9eEMAAAABQAAAMoAAAGXAAAACwAAANAAAADLAAAADAAAAMwAAADSAAAAIQAAAM4AAADNAAAAIwX14QIAAADPAAAAIgAAAM8F9eEDAAAAJQX14QkF9eELAAAADAAAAaoAAADRAAAADgAAAaYAAADSAAAAIQAAANQAAADTAAAAIwX14QIAAADVAAAAIgAAANUF9eEDAAAAJQX14QoF9eELAAAAAwX14QEAAADXAAAABAAAAZYAAADYAAAABgAAANkAAADcAAAABwAAANoAAADcAAAACAAAANsAAADcAAAACQAAAYkAAADcAAAACwAAAQgAAADdAAAADAAAAN8AAADeAAAADQAAAVkAAAELAAAADQX14Q0AAADgAAAADwAAAOEAAADjAAAAEAX14Q0AAADiAAAAFQAAAPcAAADjAAAAFwAAAOQAAAFsAAAAGAAAAOUAAAFsAAAAGQAAAOYF9eEmAAAAGgX14SYAAADnAAAAGwAAAOgF9eEmAAAAHAAAAOkF9eElAAAAIQAAAOoAAADrAAAAJgAAAOsAAAEpAAAAJwAAAO4AAADsAAAAKAAAAO0F9eEzAAAAKgAAAO8F9eEnAAAAKAAAAO8F9eEzAAAAKwAAAPAF9eEzAAAALAAAAPEF9eEyAAAALQAAAPIF9eExAAAALgX14SEAAADzAAAALwAAAPQF9eEwAAAAPwAAAPUF9eEfAAAAQAAAAPYF9eEvAAAAQQX14SkF9eEuAAAAFgAAAPgF9eEmAAAAHgX14SYAAAD5AAAAHwAAAPoF9eEmAAAAIAAAAPsF9eElAAAAIQAAAPwAAAD9AAAAJAAAAP0AAAFEAAAAJwAAAP8AAAD+AAAAKQAAAP8AAAFOAAAAMAAAAQAF9eEkAAAAMQAAAQEF9eEkAAAAMgAAAQIF9eEjAAAAMwAAAQMF9eEiAAAANAX14SEAAAEEAAAANQAAAQUF9eEgAAAAOgAAAQYF9eEfAAAAOwAAAQcF9eEeAAAAPAX14RgF9eEdAAAADAAAAWUAAAEJAAAADQAAAVgAAAEKAAAADgAAARYAAAELAAAADwAAAQwAAAEOAAAAEAAAAVsAAAENAAAAFQAAAT4AAAEOAAAAFwAAAQ8AAAEQAAAAGAAAASMAAAEQAAAAIQAAARIAAAERAAAAIwAAAXsAAAEUAAAAIgAAARMAAAF9AAAAIwAAARUAAAEUAAAAJQX14TkF9eELAAAAJQX14TgF9eELAAAADwAAARgAAAEXAAAAFAX14RQAAAEbAAAAEAX14Q4AAAEZAAAAFAX14RQAAAEaAAAAFQAAAT4AAAEbAAAAFwAAARwAAAEdAAAAGAAAASMAAAEdAAAAIQAAAR8AAAEeAAAAIwAAAXsAAAEhAAAAIgAAASAAAAF9AAAAIwAAASIAAAEhAAAAJQX14TUF9eELAAAAJQX14TQF9eELAAAAGQAAASQF9eEmAAAAGgX14SYAAAElAAAAGwAAASYF9eEmAAAAHAAAAScF9eElAAAAIQAAASgAAAEyAAAAJgAAATIAAAEpAAAAJwAAASwAAAEqAAAAKAAAASsF9eEzAAAAKgAAAS0F9eEnAAAAKAAAAS0F9eEzAAAAKwAAAS4F9eEzAAAALAAAAS8F9eEyAAAALQAAATAF9eExAAAALgX14SEAAAExAAAALwX14SgF9eEwAAAAJwAAATUAAAEzAAAAKAAAATQF9eEzAAAAKgAAATYF9eEnAAAAKAAAATYF9eEzAAAAKwAAATcF9eEzAAAALAAAATgF9eEyAAAALQAAATkF9eExAAAALgX14SEAAAE6AAAALwAAATsF9eEwAAAAPwAAATwF9eEfAAAAQAAAAT0F9eEvAAAAQQX14SoF9eEuAAAAFgAAAT8F9eEmAAAAHgX14SYAAAFAAAAAHwAAAUEF9eEmAAAAIAAAAUIF9eElAAAAIQAAAUMAAAFMAAAAJAAAAUwAAAFEAAAAJwAAAUYAAAFFAAAAKQAAAUYAAAFOAAAAMAAAAUcF9eEkAAAAMQAAAUgF9eEkAAAAMgAAAUkF9eEjAAAAMwAAAUoF9eEiAAAANAX14SEAAAFLAAAANQX14RcF9eEgAAAAJwAAAU8AAAFNAAAAKQAAAU8AAAFOAAAAMAX14RYF9eEkAAAAMAAAAVAF9eEkAAAAMQAAAVEF9eEkAAAAMgAAAVIF9eEjAAAAMwAAAVMF9eEiAAAANAX14SEAAAFUAAAANQAAAVUF9eEgAAAAOgAAAVYF9eEfAAAAOwAAAVcF9eEeAAAAPAX14RkF9eEdAAAADgX14Q4AAAFZAAAADwAAAVoF9eEPAAAAEAAAAVsF9eEPAAAAEQAAAVwAAAFdAAAAEgX14Q8AAAFdAAAAEwAAAV4AAAFfAAAAHQX14Q8AAAFfAAAANgAAAWAAAAFhAAAANwX14Q8AAAFhAAAAOAAAAWIAAAFjAAAAOQX14Q8AAAFjAAAAPQAAAWQF9eESAAAAPgX14Q8F9eESAAAADQX14QUAAAFmAAAADgAAAXIAAAFnAAAADwAAAWgAAAFqAAAAEAX14QUAAAFpAAAAFQAAAYQAAAFqAAAAFwAAAWsAAAFsAAAAGAAAAX8AAAFsAAAAIQAAAW4AAAFtAAAAIwAAAXsAAAFwAAAAIgAAAW8AAAF9AAAAIwAAAXEAAAFwAAAAJQX14TcF9eELAAAAJQX14TYF9eELAAAADwAAAXQAAAFzAAAAFAX14RMAAAF3AAAAEAX14QUAAAF1AAAAFAX14RMAAAF2AAAAFQAAAYQAAAF3AAAAFwAAAXgAAAF5AAAAGAAAAX8AAAF5AAAAIQAAAXwAAAF6AAAAIwAAAXsAAAF+AAAAJQX14QIF9eELAAAAIgAAAX4AAAF9AAAAJQX14QMF9eELAAAAJQX14QUF9eELAAAAGQAAAYAF9eEmAAAAGgX14SYAAAGBAAAAGwAAAYIF9eEmAAAAHAAAAYMF9eElAAAAKAX14QUF9eEzAAAAFgAAAYUF9eEmAAAAHgX14SYAAAGGAAAAHwAAAYcF9eEmAAAAIAAAAYgF9eElAAAAMAX14QUF9eEkAAAACgAAAYoF9eERAAAACwAAAY4AAAGLAAAADAAAAYwAAAGQAAAAJwX14Q0AAAGNAAAAQgX14Q0F9eEMAAAADAAAAZQAAAGPAAAADgAAAZIAAAGQAAAAJwX14Q8AAAGRAAAAQgX14Q8F9eEMAAAAJwX14Q4AAAGTAAAAQgX14Q4F9eEMAAAAJwX14QUAAAGVAAAAQgX14QUF9eEMAAAABQAAAZoAAAGXAAAAIQAAAZkAAAGYAAAAIwX14QIF9eEEAAAAIgX14QQF9eEDAAAACwAAAaAAAAGbAAAADAAAAZwAAAGiAAAAIQAAAZ4AAAGdAAAAIwX14QIAAAGfAAAAIgAAAZ8F9eEDAAAAJQX14QcF9eELAAAADAAAAaoAAAGhAAAADgAAAaYAAAGiAAAAIQAAAaQAAAGjAAAAIwX14QIAAAGlAAAAIgAAAaUF9eEDAAAAJQX14QgF9eELAAAAIQAAAagAAAGnAAAAIwX14QIAAAGpAAAAIgAAAakF9eEDAAAAJQX14QYF9eELAAAAIQAAAawAAAGrAAAAIwX14QIF9eEFAAAAIgX14QUF9eED" +} \ No newline at end of file diff --git a/services/s3control/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3control/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 38aaf2be68cc..000000000000 --- a/services/s3control/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,3380 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "AccountId": { - "required": false, - "documentation": "The Account ID used to send the request. This is an optional parameter that will be set automatically for operations that require it.", - "type": "string" - }, - "RequiresAccountId": { - "required": false, - "documentation": "Internal parameter for operations that require account id host prefix.", - "type": "boolean" - }, - "OutpostId": { - "required": false, - "documentation": "The Outpost ID. Some operations have an optional OutpostId which should be used in endpoint construction.", - "type": "string" - }, - "Bucket": { - "required": false, - "documentation": "The S3 bucket used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 bucket.", - "type": "string" - }, - "AccessPointName": { - "required": false, - "documentation": "The S3 AccessPointName used to send the request. This is an optional parameter that will be set automatically for operations that are scoped to an S3 AccessPoint.", - "type": "string" - }, - "UseArnRegion": { - "builtIn": "AWS::S3Control::UseArnRegion", - "required": false, - "documentation": "When an Access Point ARN is provided and this flag is enabled, the SDK MUST use the ARN's region when constructing the endpoint instead of the client's configured region.", - "type": "boolean" - }, - "ResourceArn": { - "required": false, - "documentation": "The resource ARN included in the request. Only set on TagResource, UntagResourceand ListTagsForResource", - "type": "string" - }, - "UseS3ExpressControlEndpoint": { - "required": false, - "documentation": "Internal parameter to indicate whether S3Express operation should use control plane, (ex. ListDirectoryAccessPoints)", - "type": "boolean" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "error": "Partition does not support FIPS", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "OutpostId" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ] - } - ], - "error": "AccountId is required but not set", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "AccountId" - }, - false - ] - } - ] - } - ], - "error": "AccountId must only contain a-z, A-Z, 0-9 and `-`.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "OutpostId" - }, - false - ] - } - ] - } - ], - "error": "OutpostId must only contain a-z, A-Z, 0-9 and `-`.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{Region}.{partitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts.{Region}.{partitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "ResourceArn" - } - ] - }, - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "ResourceArn" - } - ], - "assign": "resourceArn" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "resourceArn" - }, - "service" - ] - }, - "s3express" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "resourceArn" - }, - "region" - ] - } - ], - "assign": "arnPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arnPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "resourceArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{resourceArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3Express does not support Dual-stack.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccessPointName" - } - ] - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 0, - 7, - true - ], - "assign": "accessPointSuffix" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "accessPointSuffix" - }, - "--xa-s3" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3Express does not support Dual-stack.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 7, - 15, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 15, - 17, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 7, - 16, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 16, - 18, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 7, - 20, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 20, - 22, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 7, - 21, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 21, - 23, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 7, - 27, - true - ], - "assign": "s3expressAvailabilityZoneId" - }, - { - "fn": "substring", - "argv": [ - { - "ref": "AccessPointName" - }, - 27, - 29, - true - ], - "assign": "s3expressAvailabilityZoneDelim" - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "s3expressAvailabilityZoneDelim" - }, - "--" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Unrecognized S3Express Access Point name format.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseS3ExpressControlEndpoint" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3Express does not support Dual-stack.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3express-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3express-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3express", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "snow" - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "S3 Snow does not support DualStack", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "S3 Snow does not support FIPS", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccessPointName" - } - ] - }, - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "AccessPointName" - } - ], - "assign": "accessPointArn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "service" - ] - }, - "s3-outposts" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "resourceId[1]" - ], - "assign": "outpostId" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "outpostId" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{accessPointArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "region" - ] - } - ], - "assign": "arnPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arnPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "region" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "accountId" - ] - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "AccountId" - }, - "{accessPointArn#accountId}" - ] - } - ] - } - ], - "error": "Invalid ARN: the accountId specified in the ARN (`{accessPointArn#accountId}`) does not match the parameter (`{AccountId}`)", - "type": "error" - }, - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "resourceId[2]" - ], - "assign": "outpostType" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "accessPointArn" - }, - "resourceId[3]" - ], - "assign": "accessPointName" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "outpostType" - }, - "accesspoint" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{accessPointArn#region}.{arnPartition#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{accessPointArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{accessPointArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{accessPointArn#region}.{arnPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{accessPointArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{accessPointArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts.{accessPointArn#region}.{arnPartition#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{accessPointArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{accessPointArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{accessPointArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{accessPointArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts.{accessPointArn#region}.{arnPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{accessPointArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{accessPointArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Expected an outpost type `accesspoint`, found `{outpostType}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: expected an access point name", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected a 4-component resource", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{accessPointArn#accountId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: missing account ID", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region in ARN: `{accessPointArn#region}` (invalid DNS name)", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`., found: `{outpostId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The Outpost Id was not set", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Bucket" - } - ] - }, - { - "fn": "aws.parseArn", - "argv": [ - { - "ref": "Bucket" - } - ], - "assign": "bucketArn" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[0]" - ], - "assign": "arnType" - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "arnType" - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "service" - ] - }, - "s3-outposts" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[1]" - ], - "assign": "outpostId" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "outpostId" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "UseArnRegion" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseArnRegion" - }, - false - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - "{Region}" - ] - } - ] - } - ], - "error": "Invalid configuration: region from ARN `{bucketArn#region}` does not match client region `{Region}` and UseArnRegion is `false`", - "type": "error" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - } - ], - "assign": "arnPartition" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "arnPartition" - }, - "name" - ] - }, - { - "fn": "getAttr", - "argv": [ - { - "ref": "partitionResult" - }, - "name" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "region" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - "" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "accountId" - ] - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "AccountId" - }, - "{bucketArn#accountId}" - ] - } - ] - } - ], - "error": "Invalid ARN: the accountId specified in the ARN (`{bucketArn#accountId}`) does not match the parameter (`{AccountId}`)", - "type": "error" - }, - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[2]" - ], - "assign": "outpostType" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "bucketArn" - }, - "resourceId[3]" - ], - "assign": "bucketName" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "outpostType" - }, - "bucket" - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{bucketArn#region}.{arnPartition#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{bucketArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts-fips.{bucketArn#region}.{arnPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{bucketArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-outposts.{bucketArn#region}.{arnPartition#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{bucketArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{bucketArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts.{bucketArn#region}.{arnPartition#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3-outposts", - "signingRegion": "{bucketArn#region}" - } - ] - }, - "headers": { - "x-amz-account-id": [ - "{bucketArn#accountId}" - ], - "x-amz-outpost-id": [ - "{outpostId}" - ] - } - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected an outpost type `bucket`, found `{outpostType}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: expected a bucket name", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: Expected a 4-component resource", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The account id may only contain a-z, A-Z, 0-9 and `-`. Found: `{bucketArn#accountId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: missing account ID", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region in ARN: `{bucketArn#region}` (invalid DNS name)", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Client was configured for partition `{partitionResult#name}` but ARN has `{arnPartition#name}`", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The outpost Id must only contain a-z, A-Z, 0-9 and `-`., found: `{outpostId}`", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: The Outpost Id was not set", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid ARN: No ARN type specified", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "partitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "Region" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ] - } - ], - "error": "AccountId is required but not set", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "AccountId" - }, - false - ] - } - ] - } - ], - "error": "AccountId must only contain a-z, A-Z, 0-9 and `-`.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - }, - { - "fn": "parseURL", - "argv": [ - { - "ref": "Endpoint" - } - ], - "assign": "url" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: DualStack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ], - "endpoint": { - "url": "{url#scheme}://{AccountId}.{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "{url#scheme}://{url#authority}{url#path}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ], - "endpoint": { - "url": "https://{AccountId}.s3-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-control-fips.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ], - "endpoint": { - "url": "https://{AccountId}.s3-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-control-fips.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ], - "endpoint": { - "url": "https://{AccountId}.s3-control.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3-control.dualstack.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "RequiresAccountId" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "RequiresAccountId" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "AccountId" - } - ] - } - ], - "endpoint": { - "url": "https://{AccountId}.s3-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://s3-control.{Region}.{partitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "disableDoubleEncoding": true, - "name": "sigv4", - "signingName": "s3", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid region: region was not a valid DNS name.", - "type": "error" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Region must be set", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/s3control/src/main/resources/codegen-resources/service-2.json b/services/s3control/src/main/resources/codegen-resources/service-2.json index 518c3013e7ea..deae615f6465 100644 --- a/services/s3control/src/main/resources/codegen-resources/service-2.json +++ b/services/s3control/src/main/resources/codegen-resources/service-2.json @@ -7723,6 +7723,13 @@ "max":128, "min":4 }, + "S3AnnotationDirective":{ + "type":"string", + "enum":[ + "COPY", + "EXCLUDE" + ] + }, "S3BucketArnString":{ "type":"string", "max":128, @@ -7831,6 +7838,10 @@ "shape":"S3MetadataDirective", "documentation":"

    " }, + "AnnotationDirective":{ + "shape":"S3AnnotationDirective", + "documentation":"

    Specifies whether the Batch Operations copy job copies object annotations from the source object or skips them. If this property isn't specified, COPY is the default behavior.

    Valid Values: COPY | EXCLUDE

    This functionality is not supported by directory buckets.

    " + }, "ModifiedSinceConstraint":{ "shape":"TimeStamp", "documentation":"

    " @@ -7886,6 +7897,14 @@ "ChecksumAlgorithm":{ "shape":"S3ChecksumAlgorithm", "documentation":"

    Indicates the algorithm that you want Amazon S3 to use to create the checksum. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ObjectLockEventHold":{ + "shape":"S3ObjectLockEventHold", + "documentation":"

    The event hold status to be applied to all objects in the Batch Operations copy job. Set to ON to enable an event hold or OFF to disable it.

    This functionality is not supported by directory buckets.

    " + }, + "ObjectLockEventHoldDuration":{ + "shape":"S3ObjectLockEventHoldDuration", + "documentation":"

    The event hold duration to be applied to all objects in the Batch Operations copy job. The duration specifies how long the object remains protected after the event hold is released.

    This functionality is not supported by directory buckets.

    " } }, "documentation":"

    Contains the configuration parameters for a PUT Copy object operation. S3 Batch Operations passes every object to the underlying CopyObject API operation. For more information about the parameters for this operation, see CopyObject.

    " @@ -7986,7 +8005,7 @@ "members":{ "ExpectedBucketOwner":{ "shape":"AccountId", - "documentation":"

    The Amazon Web Services account ID that owns the bucket the generated manifest is written to. If provided the generated manifest bucket's owner Amazon Web Services account ID must match this value, else the job fails.

    " + "documentation":"

    The Amazon Web Services account ID that owns the source bucket specified in SourceBucket. If provided, the manifest source bucket owner's Amazon Web Services account ID must match this value, else the job fails.

    " }, "SourceBucket":{ "shape":"S3BucketArnString", @@ -8050,6 +8069,41 @@ "REPLACE" ] }, + "S3ObjectLockEventHold":{ + "type":"string", + "enum":[ + "ON", + "OFF" + ] + }, + "S3ObjectLockEventHoldDuration":{ + "type":"structure", + "members":{ + "Days":{ + "shape":"S3ObjectLockEventHoldDurationDays", + "documentation":"

    The number of days for the event hold duration. The minimum value is 1 and the maximum value is 36,500.

    ", + "box":true + }, + "Years":{ + "shape":"S3ObjectLockEventHoldDurationYears", + "documentation":"

    The number of years for the event hold duration. The minimum value is 1 and the maximum value is 100.

    ", + "box":true + } + }, + "documentation":"

    Contains the duration configuration for an event hold, specified in either days or years.

    " + }, + "S3ObjectLockEventHoldDurationDays":{ + "type":"integer", + "box":true, + "max":36500, + "min":1 + }, + "S3ObjectLockEventHoldDurationYears":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, "S3ObjectLockLegalHold":{ "type":"structure", "required":["Status"], @@ -8075,6 +8129,41 @@ "GOVERNANCE" ] }, + "S3ObjectLockRetentionEventHold":{ + "type":"string", + "enum":[ + "ON", + "OFF" + ] + }, + "S3ObjectLockRetentionEventHoldDuration":{ + "type":"structure", + "members":{ + "Days":{ + "shape":"S3ObjectLockRetentionEventHoldDurationDays", + "documentation":"

    The number of days for the event hold duration. The minimum value is 1 and the maximum value is 36,500.

    ", + "box":true + }, + "Years":{ + "shape":"S3ObjectLockRetentionEventHoldDurationYears", + "documentation":"

    The number of years for the event hold duration. The minimum value is 1 and the maximum value is 100.

    ", + "box":true + } + }, + "documentation":"

    Contains the duration configuration for an event hold, specified in either days or years.

    " + }, + "S3ObjectLockRetentionEventHoldDurationDays":{ + "type":"integer", + "box":true, + "max":36500, + "min":1 + }, + "S3ObjectLockRetentionEventHoldDurationYears":{ + "type":"integer", + "box":true, + "max":100, + "min":1 + }, "S3ObjectLockRetentionMode":{ "type":"string", "enum":[ @@ -8203,6 +8292,14 @@ "Mode":{ "shape":"S3ObjectLockRetentionMode", "documentation":"

    The Object Lock retention mode to be applied to all objects in the Batch Operations job.

    " + }, + "EventHold":{ + "shape":"S3ObjectLockRetentionEventHold", + "documentation":"

    The event hold status to be applied to all objects in the Batch Operations job. Set to ON to enable an event hold or OFF to disable it.

    " + }, + "EventHoldDuration":{ + "shape":"S3ObjectLockRetentionEventHoldDuration", + "documentation":"

    The event hold duration to be applied to all objects in the Batch Operations job. The duration specifies how long the object remains protected after the event hold is released.

    " } }, "documentation":"

    Contains the S3 Object Lock retention mode to be applied to all objects in the S3 Batch Operations job. If you don't provide Mode and RetainUntilDate data types in your operation, you will remove the retention from your objects. For more information, see Using S3 Object Lock retention with S3 Batch Operations in the Amazon S3 User Guide.

    " @@ -8444,7 +8541,7 @@ }, "MinStorageBytesPercentage":{ "shape":"MinStorageBytesPercentage", - "documentation":"

    The minimum number of storage bytes percentage whose metrics will be selected.

    You must choose a value greater than or equal to 1.0.

    " + "documentation":"

    The minimum percentage of total bucket storage that a prefix must hold for its metrics to be included.

    " } }, "documentation":"

    " diff --git a/services/s3files/pom.xml b/services/s3files/pom.xml index 9f0a0849b98a..27671000ba51 100644 --- a/services/s3files/pom.xml +++ b/services/s3files/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3files AWS Java SDK :: Services :: S3 Files diff --git a/services/s3files/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3files/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e6672c1de983 --- /dev/null +++ b/services/s3files/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3files-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3files.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/s3files/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3files/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a905c657bc5c..000000000000 --- a/services/s3files/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3files-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3files.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/s3outposts/pom.xml b/services/s3outposts/pom.xml index 8cd451ad7d81..6f67f8efd522 100644 --- a/services/s3outposts/pom.xml +++ b/services/s3outposts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3outposts AWS Java SDK :: Services :: S3 Outposts diff --git a/services/s3outposts/src/main/resources/codegen-resources/customization.config b/services/s3outposts/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/s3outposts/src/main/resources/codegen-resources/customization.config +++ b/services/s3outposts/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/s3outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..00c9c7652d28 --- /dev/null +++ b/services/s3outposts/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3-outposts.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/s3outposts/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3outposts/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 510709c84777..000000000000 --- a/services/s3outposts/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3-outposts.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/s3tables/pom.xml b/services/s3tables/pom.xml index 5b11a844167b..63f6e5deac97 100644 --- a/services/s3tables/pom.xml +++ b/services/s3tables/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3tables AWS Java SDK :: Services :: S3 Tables diff --git a/services/s3tables/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3tables/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5496b7c6a3bd --- /dev/null +++ b/services/s3tables/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3tables-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3tables-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3tables.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3tables.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/s3tables/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3tables/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 90e6c88439c7..000000000000 --- a/services/s3tables/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3tables-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3tables-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3tables.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://s3tables.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/s3vectors/pom.xml b/services/s3vectors/pom.xml index f373672159db..e87271915c4b 100644 --- a/services/s3vectors/pom.xml +++ b/services/s3vectors/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT s3vectors AWS Java SDK :: Services :: S3 Vectors diff --git a/services/s3vectors/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/s3vectors/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..5bbe7701e809 --- /dev/null +++ b/services/s3vectors/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3vectors-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://s3vectors.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/s3vectors/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/s3vectors/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index eb1bdf8f1733..000000000000 --- a/services/s3vectors/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://s3vectors-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://s3vectors.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sagemaker/pom.xml b/services/sagemaker/pom.xml index 2ee9816c9b01..c9022d9f3ce4 100644 --- a/services/sagemaker/pom.xml +++ b/services/sagemaker/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 sagemaker diff --git a/services/sagemaker/src/main/resources/codegen-resources/customization.config b/services/sagemaker/src/main/resources/codegen-resources/customization.config index 5d63887a8f3e..bcf7d119479b 100644 --- a/services/sagemaker/src/main/resources/codegen-resources/customization.config +++ b/services/sagemaker/src/main/resources/codegen-resources/customization.config @@ -20,6 +20,5 @@ "TrialComponentParameterValue": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/sagemaker/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemaker/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2afcd85a9ada --- /dev/null +++ b/services/sagemaker/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,227 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api-fips.sagemaker.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAwAAAAJAAAABgAAAAoF9eEIAAAABwX14QYAAAALAAAACAX14QYF9eEHAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemaker/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemaker/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c252a1bea3ab..000000000000 --- a/services/sagemaker/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://api-fips.sagemaker.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://api-fips.sagemaker.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://api.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://api.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemaker/src/main/resources/codegen-resources/service-2.json b/services/sagemaker/src/main/resources/codegen-resources/service-2.json index 6b4103b31ced..4e24b6c39e5e 100644 --- a/services/sagemaker/src/main/resources/codegen-resources/service-2.json +++ b/services/sagemaker/src/main/resources/codegen-resources/service-2.json @@ -54,6 +54,20 @@ ], "documentation":"

    Associates a trial component with a trial. A trial component can be associated with multiple trials. To disassociate a trial component from a trial, call the DisassociateTrialComponent API.

    " }, + "AttachClusterNodeNetworkInterface":{ + "name":"AttachClusterNodeNetworkInterface", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"AttachClusterNodeNetworkInterfaceRequest"}, + "output":{"shape":"AttachClusterNodeNetworkInterfaceResponse"}, + "errors":[ + {"shape":"ResourceNotFound"}, + {"shape":"ResourceLimitExceeded"} + ], + "documentation":"

    Attaches an elastic network interface (ENI) to a node in a HyperPod cluster.

    To use this operation, you must have the sagemaker:AttachClusterNodeNetworkInterface permission.

    " + }, "AttachClusterNodeVolume":{ "name":"AttachClusterNodeVolume", "http":{ @@ -5003,6 +5017,76 @@ } }, "shapes":{ + "AIAdapterId":{ + "type":"string", + "documentation":"

    A unique identifier for a LoRA adapter within a recommendation job request. The ID must start and end with an alphanumeric character, can contain hyphens between alphanumeric characters, and can be up to 63 characters long. This ID is used as the inference component name when the adapter is deployed.

    ", + "max":63, + "min":1, + "pattern":"[a-zA-Z0-9](-*[a-zA-Z0-9])*" + }, + "AIAdapterModelPackageEntry":{ + "type":"structure", + "required":[ + "AdapterId", + "ModelPackageArn" + ], + "members":{ + "AdapterId":{ + "shape":"AIAdapterId", + "documentation":"

    A unique identifier for the adapter. This ID is used as the inference component name when the adapter is deployed. The ID must start and end with an alphanumeric character, can contain hyphens between alphanumeric characters, and can be up to 63 characters long.

    " + }, + "ModelPackageArn":{ + "shape":"ModelPackageArn", + "documentation":"

    The Amazon Resource Name (ARN) of the model package that contains the LoRA adapter artifacts.

    " + } + }, + "documentation":"

    A LoRA adapter entry identified by a model package ARN.

    " + }, + "AIAdapterModelPackageEntryList":{ + "type":"list", + "member":{"shape":"AIAdapterModelPackageEntry"}, + "max":10, + "min":1 + }, + "AIAdapterS3Entry":{ + "type":"structure", + "required":[ + "AdapterId", + "S3Uri" + ], + "members":{ + "AdapterId":{ + "shape":"AIAdapterId", + "documentation":"

    A unique identifier for the adapter. This ID is used as the inference component name when the adapter is deployed. The ID must start and end with an alphanumeric character, can contain hyphens between alphanumeric characters, and can be up to 63 characters long.

    " + }, + "S3Uri":{ + "shape":"S3Uri", + "documentation":"

    The Amazon S3 URI of the directory that contains the LoRA adapter artifacts in PEFT format.

    " + } + }, + "documentation":"

    A LoRA adapter entry identified by an Amazon S3 URI.

    " + }, + "AIAdapterS3EntryList":{ + "type":"list", + "member":{"shape":"AIAdapterS3Entry"}, + "max":10, + "min":1 + }, + "AIAdapterSource":{ + "type":"structure", + "members":{ + "ModelPackageArns":{ + "shape":"AIAdapterModelPackageEntryList", + "documentation":"

    A list of LoRA adapters identified by their model package ARNs. Use this when your adapters were produced by a SageMaker AI fine-tuning workflow that registers model packages.

    " + }, + "S3Uris":{ + "shape":"AIAdapterS3EntryList", + "documentation":"

    A list of LoRA adapters identified by their Amazon S3 URIs. Use this when your adapters are stored as raw artifacts in Amazon S3.

    " + } + }, + "documentation":"

    The source of LoRA adapters for an AI recommendation job. This is a union type — specify exactly one of the members.

    ", + "union":true + }, "AIBenchmarkEndpoint":{ "type":"structure", "required":["Identifier"], @@ -5307,10 +5391,32 @@ "ExpectedPerformance":{ "shape":"ExpectedPerformanceList", "documentation":"

    The expected performance metrics for this recommendation.

    " + }, + "AdapterDetails":{ + "shape":"AIRecommendationAdapterDetails", + "documentation":"

    The LoRA adapter details for this recommendation. This field contains both the model package ARNs and Amazon S3 URIs for each adapter, regardless of which form was originally supplied. This field is absent when the job was created without LoRA adapters.

    " } }, "documentation":"

    An optimization recommendation generated by an AI recommendation job.

    " }, + "AIRecommendationAdapterDetails":{ + "type":"structure", + "required":[ + "ModelPackageArns", + "S3Uris" + ], + "members":{ + "ModelPackageArns":{ + "shape":"AIAdapterModelPackageEntryList", + "documentation":"

    The list of LoRA adapters with their model package ARNs.

    " + }, + "S3Uris":{ + "shape":"AIAdapterS3EntryList", + "documentation":"

    The list of LoRA adapters with their Amazon S3 URIs.

    " + } + }, + "documentation":"

    The per-recommendation LoRA adapter details. Contains both the model package ARNs and Amazon S3 URIs for each adapter, regardless of which form was originally supplied in the request. When you supply only Amazon S3 URIs, Amazon SageMaker AI creates model packages on your behalf.

    " + }, "AIRecommendationAllowOptimization":{ "type":"boolean", "box":true @@ -5374,6 +5480,10 @@ "EnvironmentVariables":{ "shape":"EnvironmentMap", "documentation":"

    The environment variables for the deployment.

    " + }, + "MinCpuMemoryRequiredInMb":{ + "shape":"AIRecommendationMinCpuMemoryRequiredInMb", + "documentation":"

    The minimum host (CPU) memory, in MiB, to reserve for each model copy when deploying the recommendation as an Inference Component. This value maps to the Inference Component's ComputeResourceRequirements$MinMemoryRequiredInMb field.

    " } }, "documentation":"

    The deployment configuration for a recommendation.

    " @@ -5466,6 +5576,12 @@ "ml.g6e.16xlarge", "ml.g6e.24xlarge", "ml.g6e.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge", "ml.g7e.2xlarge", "ml.g7e.4xlarge", "ml.g7e.8xlarge", @@ -5554,6 +5670,11 @@ "cost" ] }, + "AIRecommendationMinCpuMemoryRequiredInMb":{ + "type":"integer", + "box":true, + "min":1 + }, "AIRecommendationModelDetails":{ "type":"structure", "members":{ @@ -6691,6 +6812,12 @@ "ml.r6id.24xlarge", "ml.r6id.32xlarge", "ml.p5.4xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge", "ml.g7e.2xlarge", "ml.g7e.4xlarge", "ml.g7e.8xlarge", @@ -6781,6 +6908,12 @@ "Canvas" ] }, + "ApplicationArn":{ + "type":"string", + "max":128, + "min":1, + "pattern":"arn:aws[a-z\\-]*:sso::[0-9]{12}:application/(sso)?ins-[a-zA-Z0-9.-]{16}/apl-[a-zA-Z0-9.-]{16}" + }, "ApprovalDescription":{ "type":"string", "max":1024, @@ -7181,6 +7314,55 @@ "min":1, "pattern":"[a-zA-Z0-9._-]+" }, + "AttachClusterNodeNetworkInterfaceRequest":{ + "type":"structure", + "required":[ + "ClusterName", + "NodeId", + "NetworkInterfaceId" + ], + "members":{ + "ClusterName":{ + "shape":"ClusterNameOrArn", + "documentation":"

    The name or Amazon Resource Name (ARN) of the SageMaker HyperPod cluster that contains the target node.

    " + }, + "NodeId":{ + "shape":"ClusterNodeId", + "documentation":"

    The unique identifier of the cluster node to which you want to attach the network interface. The node must belong to your specified HyperPod cluster and cannot be part of a Restricted Instance Group (RIG).

    " + }, + "NetworkInterfaceId":{ + "shape":"ClusterNetworkInterfaceId", + "documentation":"

    The unique identifier of the elastic network interface (ENI) to attach.

    " + } + } + }, + "AttachClusterNodeNetworkInterfaceResponse":{ + "type":"structure", + "required":[ + "ClusterArn", + "NodeId", + "NetworkInterfaceId", + "AttachmentId" + ], + "members":{ + "ClusterArn":{ + "shape":"ClusterArn", + "documentation":"

    The Amazon Resource Name (ARN) of your SageMaker HyperPod cluster where the network interface attachment operation was performed.

    " + }, + "NodeId":{ + "shape":"ClusterNodeId", + "documentation":"

    The unique identifier of the cluster node where your network interface was attached.

    " + }, + "NetworkInterfaceId":{ + "shape":"ClusterNetworkInterfaceId", + "documentation":"

    The unique identifier of the elastic network interface (ENI) that was attached.

    " + }, + "AttachmentId":{ + "shape":"ClusterNetworkInterfaceAttachmentId", + "documentation":"

    The unique identifier of the network interface attachment. Use this value to reference or detach the network interface later.

    " + } + } + }, "AttachClusterNodeVolumeRequest":{ "type":"structure", "required":[ @@ -9966,7 +10148,7 @@ "members":{ "PatchingStrategy":{ "shape":"ClusterPatchingStrategy", - "documentation":"

    The strategy for applying patches to instances in the group.

    " + "documentation":"

    The strategy for applying patches to instances in the group.

    • WhenIdle: Cordons all instances and patches each instance as it becomes idle (no running jobs). Each instance is uncordoned immediately after patching and becomes available for new jobs. If instances do not become idle, they remain on the previous AMI version. You can then use UpdateClusterSoftware with the desired ImageReleaseVersion to manually update the remaining instances.

    • WhenAllIdle: Cordons all instances and waits for all to become idle before patching. All instances are uncordoned after patching completes. If not all instances become idle, no patching occurs and all instances remain on the previous AMI version.

    " }, "PatchSchedule":{ "shape":"ClusterPatchSchedule", @@ -9984,7 +10166,7 @@ "members":{ "PatchingStrategy":{ "shape":"ClusterPatchingStrategy", - "documentation":"

    The strategy used for applying patches to instances in the group.

    " + "documentation":"

    The strategy used for applying patches to instances in the group.

    • WhenIdle: Cordons all instances and patches each instance as it becomes idle (no running jobs). Each instance is uncordoned immediately after patching and becomes available for new jobs. If instances do not become idle, they remain on the previous AMI version. You can then use UpdateClusterSoftware with the desired ImageReleaseVersion to manually update the remaining instances.

    • WhenAllIdle: Cordons all instances and waits for all to become idle before patching. All instances are uncordoned after patching completes. If not all instances become idle, no patching occurs and all instances remain on the previous AMI version.

    " }, "CurrentPatchSchedule":{ "shape":"ClusterPatchScheduleDetails", @@ -10532,7 +10714,7 @@ }, "ImageId":{ "shape":"ImageId", - "documentation":"

    When configuring your HyperPod cluster, you can specify an image ID using one of the following options:

    • HyperPodPublicAmiId: Use a HyperPod public AMI

    • CustomAmiId: Use your custom AMI

    • default: Use the default latest system image

    If you choose to use a custom AMI (CustomAmiId), ensure it meets the following requirements:

    • Encryption: The custom AMI must be unencrypted.

    • Ownership: The custom AMI must be owned by the same Amazon Web Services account that is creating the HyperPod cluster.

    • Volume support: Only the primary AMI snapshot volume is supported; additional AMI volumes are not supported.

    When updating the instance group's AMI through the UpdateClusterSoftware operation, if an instance group uses a custom AMI, you must provide an ImageId or use the default as input. Note that if you don't specify an instance group in your UpdateClusterSoftware request, then all of the instance groups are patched with the specified image.

    " + "documentation":"

    When configuring your HyperPod cluster, you can specify an image ID using one of the following options:

    • HyperPodPublicAmiId: Use a HyperPod public AMI

    • CustomAmiId: Use your custom AMI

    • default: Use the default latest system image. For clusters with continuous scaling node provisioning mode, new instance groups inherit the AMI from the earliest existing instance group

    If you choose to use a custom AMI (CustomAmiId), ensure it meets the following requirements:

    • Encryption: The custom AMI must be unencrypted.

    • Ownership: The custom AMI must be owned by the same Amazon Web Services account that is creating the HyperPod cluster.

    • Volume support: Only the primary AMI snapshot volume is supported; additional AMI volumes are not supported.

    When updating the instance group's AMI through the UpdateClusterSoftware operation, if an instance group uses a custom AMI, you must provide an ImageId or use the default as input. Note that if you don't specify an instance group in your UpdateClusterSoftware request, then all of the instance groups are patched with the specified image.

    " }, "AutoPatchConfig":{ "shape":"ClusterAutoPatchConfig", @@ -10795,7 +10977,91 @@ "ml.g7e.12xlarge", "ml.g7e.24xlarge", "ml.g7e.48xlarge", - "ml.p6-b300.48xlarge" + "ml.p6-b300.48xlarge", + "ml.g4dn.xlarge", + "ml.g4dn.2xlarge", + "ml.g4dn.4xlarge", + "ml.g4dn.8xlarge", + "ml.g4dn.12xlarge", + "ml.g4dn.16xlarge", + "ml.c6g.medium", + "ml.c6g.large", + "ml.c6g.xlarge", + "ml.c6g.2xlarge", + "ml.c6g.4xlarge", + "ml.c6g.8xlarge", + "ml.c6g.12xlarge", + "ml.c6g.16xlarge", + "ml.c7g.medium", + "ml.c7g.large", + "ml.c7g.xlarge", + "ml.c7g.2xlarge", + "ml.c7g.4xlarge", + "ml.c7g.8xlarge", + "ml.c7g.12xlarge", + "ml.c7g.16xlarge", + "ml.c8g.medium", + "ml.c8g.large", + "ml.c8g.xlarge", + "ml.c8g.2xlarge", + "ml.c8g.4xlarge", + "ml.c8g.8xlarge", + "ml.c8g.12xlarge", + "ml.c8g.16xlarge", + "ml.c8g.24xlarge", + "ml.c8g.48xlarge", + "ml.c6a.large", + "ml.c6a.xlarge", + "ml.c6a.2xlarge", + "ml.c6a.4xlarge", + "ml.c6a.8xlarge", + "ml.c6a.12xlarge", + "ml.c6a.16xlarge", + "ml.c6a.24xlarge", + "ml.c6a.32xlarge", + "ml.c6a.48xlarge", + "ml.m6a.large", + "ml.m6a.xlarge", + "ml.m6a.2xlarge", + "ml.m6a.4xlarge", + "ml.m6a.8xlarge", + "ml.m6a.12xlarge", + "ml.m6a.16xlarge", + "ml.m6a.24xlarge", + "ml.m6a.32xlarge", + "ml.m6a.48xlarge", + "ml.m6g.medium", + "ml.m6g.large", + "ml.m6g.xlarge", + "ml.m6g.2xlarge", + "ml.m6g.4xlarge", + "ml.m6g.8xlarge", + "ml.m6g.12xlarge", + "ml.m6g.16xlarge", + "ml.m7g.medium", + "ml.m7g.large", + "ml.m7g.xlarge", + "ml.m7g.2xlarge", + "ml.m7g.4xlarge", + "ml.m7g.8xlarge", + "ml.m7g.12xlarge", + "ml.m7g.16xlarge", + "ml.m8g.medium", + "ml.m8g.large", + "ml.m8g.xlarge", + "ml.m8g.2xlarge", + "ml.m8g.4xlarge", + "ml.m8g.8xlarge", + "ml.m8g.12xlarge", + "ml.m8g.16xlarge", + "ml.m8g.24xlarge", + "ml.m8g.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge" ] }, "ClusterInstanceTypeDetail":{ @@ -11030,6 +11296,12 @@ }, "documentation":"

    The network interface configuration for a Amazon SageMaker HyperPod cluster instance group.

    " }, + "ClusterNetworkInterfaceAttachmentId":{ + "type":"string", + "max":28, + "min":1, + "pattern":"eni-attach-[0-9a-f]{8}(?:[0-9a-f]{9})?" + }, "ClusterNetworkInterfaceDetails":{ "type":"structure", "members":{ @@ -11040,6 +11312,12 @@ }, "documentation":"

    The network interface configuration details for a Amazon SageMaker HyperPod cluster instance group.

    " }, + "ClusterNetworkInterfaceId":{ + "type":"string", + "max":21, + "min":1, + "pattern":"eni-[0-9a-f]{8}(?:[0-9a-f]{9})?" + }, "ClusterNodeDetails":{ "type":"structure", "members":{ @@ -12629,6 +12907,10 @@ "shape":"AIRecommendationComputeSpec", "documentation":"

    The compute resource specification for the recommendation job. You can specify up to 3 instance types to consider, and optionally provide capacity reservation configuration.

    " }, + "AdapterSource":{ + "shape":"AIAdapterSource", + "documentation":"

    The LoRA adapter source for the recommendation job. Specify either a list of model package ARNs or Amazon S3 URIs for your LoRA adapters. When this parameter is absent, the recommendation job runs without LoRA adapter support.

    " + }, "Tags":{ "shape":"TagList", "documentation":"

    The metadata that you apply to Amazon Web Services resources to help you categorize and organize them.

    " @@ -14441,6 +14723,10 @@ "shape":"RoleArn", "documentation":"

    The Amazon Resource Name (ARN) for an IAM role in your account that the MLflow App uses to access the artifact store in Amazon S3. The role should have the AmazonS3FullAccess permission.

    " }, + "KmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The ID of the Amazon Web Services KMS key used to encrypt the data at rest associated with the MLflow App. If you don't specify a value, the MLflow App is not encrypted with a customer-managed key.

    " + }, "ModelRegistrationMode":{ "shape":"ModelRegistrationMode", "documentation":"

    Whether to enable or disable automatic registration of new MLflow models to the SageMaker Model Registry. To enable automatic model registration, set this value to AutoModelRegistrationEnabled. To disable automatic model registration, set this value to AutoModelRegistrationDisabled. If not specified, AutomaticModelRegistration defaults to AutoModelRegistrationDisabled.

    " @@ -15168,6 +15454,10 @@ "VpcConfig":{ "shape":"OptimizationVpcConfig", "documentation":"

    A VPC in Amazon VPC that your optimized model has access to.

    " + }, + "TrainingPlanArns":{ + "shape":"OptimizationJobTrainingPlanArns", + "documentation":"

    The Amazon Resource Name (ARN) of the training plan to use for this optimization job.

    When you use reserved capacity from a training plan, the optimization job runs on that reserved capacity instead of on-demand capacity. If you omit this field, the job uses on-demand capacity. You can specify at most one training plan.

    For more information about how to reserve GPU capacity for your optimization jobs using Amazon SageMaker Training Plans, see Reserve capacity with training plans.

    " } } }, @@ -15246,9 +15536,13 @@ "shape":"PartnerAppConfig", "documentation":"

    Configuration settings for the SageMaker Partner AI App.

    " }, + "IdcConfig":{ + "shape":"IdcConfigInput", + "documentation":"

    Specifies the Amazon Web Services IAM Identity Center configuration for the SageMaker Partner AI App. Specify this parameter when AuthType is IDC. Apps that use IAM authorization don't use this parameter.

    " + }, "AuthType":{ "shape":"PartnerAppAuthType", - "documentation":"

    The authorization type that users use to access the SageMaker Partner AI App.

    " + "documentation":"

    The authorization type that users use to access the SageMaker Partner AI App. Valid values:

    • IAM: Users access the SageMaker Partner AI App with their Amazon Web Services IAM identity.

    • IDC: Users access the SageMaker Partner AI App with their Amazon Web Services IAM Identity Center identity. Specify the Identity Center instance to use in IdcConfig.

    " }, "EnableIamSessionBasedIdentity":{ "shape":"Boolean", @@ -16658,7 +16952,7 @@ "DeepHealthChecks":{ "type":"list", "member":{"shape":"DeepHealthCheckType"}, - "max":2, + "max":3, "min":1 }, "DefaultDomainIdList":{ @@ -17980,6 +18274,10 @@ "shape":"AIRecommendationComputeSpec", "documentation":"

    The compute resource specification for the recommendation job.

    " }, + "AdapterSource":{ + "shape":"AIAdapterSource", + "documentation":"

    The LoRA adapter source that you specified when you created the recommendation job. This field is absent when you created the job without LoRA adapters.

    " + }, "CreationTime":{ "shape":"Timestamp", "documentation":"

    A timestamp that indicates when the recommendation job was created.

    " @@ -20950,6 +21248,10 @@ "shape":"RoleArn", "documentation":"

    The Amazon Resource Name (ARN) for an IAM role in your account that the MLflow App uses to access the artifact store in Amazon S3.

    " }, + "KmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The ID of the Amazon Web Services KMS key used to encrypt the data at rest associated with the MLflow App. This field is absent if the MLflow App is not encrypted with a customer-managed key.

    " + }, "Status":{ "shape":"MlflowAppStatus", "documentation":"

    The current creation status of the described MLflow App.

    " @@ -21944,6 +22246,10 @@ "VpcConfig":{ "shape":"OptimizationVpcConfig", "documentation":"

    A VPC in Amazon VPC that your optimized model has access to.

    " + }, + "TrainingPlanArns":{ + "shape":"OptimizationJobTrainingPlanArns", + "documentation":"

    The Amazon Resource Name (ARN) of the training plan associated with this optimization job. This field appears only when you specified a training plan when you created the job. Optimization jobs that use on-demand capacity don't return this field.

    " } } }, @@ -22019,7 +22325,7 @@ }, "AuthType":{ "shape":"PartnerAppAuthType", - "documentation":"

    The authorization type that users use to access the SageMaker Partner AI App.

    " + "documentation":"

    The authorization type that users use to access the SageMaker Partner AI App. Valid values:

    • IAM: Users access the SageMaker Partner AI App with their Amazon Web Services IAM identity.

    • IDC: Users access the SageMaker Partner AI App with their Amazon Web Services IAM Identity Center identity.

    " }, "EnableIamSessionBasedIdentity":{ "shape":"Boolean", @@ -22042,6 +22348,10 @@ "AvailableUpgrade":{ "shape":"AvailableUpgrade", "documentation":"

    A map of available minor version upgrades for the SageMaker Partner AI App. The key is the semantic version number, and the value is a list of release notes for that version. A null value indicates no upgrades are available.

    " + }, + "IdcConfig":{ + "shape":"IdcConfigOutput", + "documentation":"

    Contains the Amazon Web Services IAM Identity Center configuration for the SageMaker Partner AI App, including the Identity Center instance and the Identity Center application that SageMaker creates for the app. The service returns this field for apps that use IDC authorization.

    " } } }, @@ -26475,6 +26785,107 @@ "min":0, "pattern":".*" }, + "HubContent":{ + "type":"structure", + "required":[ + "HubContentName", + "HubContentArn", + "HubContentVersion", + "HubContentType", + "DocumentSchemaVersion", + "HubName", + "HubArn", + "HubContentStatus", + "CreationTime" + ], + "members":{ + "HubContentName":{ + "shape":"HubContentName", + "documentation":"

    The name of the hub content.

    " + }, + "HubContentArn":{ + "shape":"HubContentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the hub content.

    " + }, + "HubContentVersion":{ + "shape":"HubContentVersion", + "documentation":"

    The version of the hub content.

    " + }, + "HubContentType":{ + "shape":"HubContentType", + "documentation":"

    The type of hub content.

    " + }, + "DocumentSchemaVersion":{ + "shape":"DocumentSchemaVersion", + "documentation":"

    The document schema version for the hub content.

    " + }, + "HubName":{ + "shape":"HubName", + "documentation":"

    The name of the hub that contains the content.

    " + }, + "HubArn":{ + "shape":"HubArn", + "documentation":"

    The Amazon Resource Name (ARN) of the hub that contains the content.

    " + }, + "HubContentDisplayName":{ + "shape":"HubContentDisplayName", + "documentation":"

    The display name of the hub content.

    " + }, + "HubContentDescription":{ + "shape":"HubContentDescription", + "documentation":"

    A description of the hub content.

    " + }, + "HubContentMarkdown":{ + "shape":"HubContentMarkdown", + "documentation":"

    A string that provides a description of the hub content. This string can include links, tables, and standard markdown formatting.

    " + }, + "HubContentDocument":{ + "shape":"HubContentDocument", + "documentation":"

    The hub content document that describes information about the hub content such as type, associated containers, scripts, and more.

    " + }, + "SageMakerPublicHubContentArn":{ + "shape":"SageMakerPublicHubContentArn", + "documentation":"

    The Amazon Resource Name (ARN) of the public hub content.

    " + }, + "ReferenceMinVersion":{ + "shape":"ReferenceMinVersion", + "documentation":"

    The minimum version of the hub content.

    " + }, + "SupportStatus":{ + "shape":"HubContentSupportStatus", + "documentation":"

    The support status of the hub content.

    " + }, + "HubContentSearchKeywords":{ + "shape":"HubContentSearchKeywordList", + "documentation":"

    The searchable keywords for the hub content.

    " + }, + "HubContentDependencies":{ + "shape":"HubContentDependencyList", + "documentation":"

    The location of any dependencies that the hub content has, such as scripts, model artifacts, datasets, or notebooks.

    " + }, + "HubContentStatus":{ + "shape":"HubContentStatus", + "documentation":"

    The status of the hub content.

    " + }, + "FailureReason":{ + "shape":"FailureReason", + "documentation":"

    The failure reason if importing hub content failed.

    " + }, + "CreationTime":{ + "shape":"Timestamp", + "documentation":"

    The date and time that hub content was created.

    " + }, + "LastModifiedTime":{ + "shape":"Timestamp", + "documentation":"

    The last modified time of the hub content.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    Any tags associated with the hub content.

    " + } + }, + "documentation":"

    Contains information about a hub content resource, including its name, version, type, associated documents, dependencies, and status, as returned by a search result.

    " + }, "HubContentArn":{ "type":"string", "max":255, @@ -27664,6 +28075,32 @@ }, "documentation":"

    Use this parameter to specify a supported global condition key that is added to the IAM policy.

    " }, + "IdcConfigInput":{ + "type":"structure", + "required":["InstanceArn"], + "members":{ + "InstanceArn":{ + "shape":"InstanceArn", + "documentation":"

    The ARN of the Amazon Web Services IAM Identity Center instance that the SageMaker Partner AI App uses to authenticate users.

    " + } + }, + "documentation":"

    Specifies the Amazon Web Services IAM Identity Center configuration to use for a SageMaker Partner AI App that uses IDC authorization.

    " + }, + "IdcConfigOutput":{ + "type":"structure", + "required":["InstanceArn"], + "members":{ + "InstanceArn":{ + "shape":"InstanceArn", + "documentation":"

    The ARN of the Amazon Web Services IAM Identity Center instance that the SageMaker Partner AI App uses to authenticate users.

    " + }, + "ApplicationArn":{ + "shape":"ApplicationArn", + "documentation":"

    The ARN of the Amazon Web Services IAM Identity Center application that SageMaker creates for the SageMaker Partner AI App.

    " + } + }, + "documentation":"

    Contains the Amazon Web Services IAM Identity Center configuration of a SageMaker Partner AI App that uses IDC authorization.

    " + }, "IdempotencyToken":{ "type":"string", "max":128, @@ -28969,6 +29406,12 @@ "member":{"shape":"TrainingInputMode"}, "min":1 }, + "InstanceArn":{ + "type":"string", + "max":128, + "min":1, + "pattern":"arn:aws[a-z\\-]*:sso:::instance/(sso)?ins-[a-zA-Z0-9.-]{16}" + }, "InstanceCount":{ "type":"integer", "box":true, @@ -29231,6 +29674,33 @@ "member":{"shape":"InstancePoolSummary"}, "min":1 }, + "InstancePreference":{ + "type":"structure", + "required":["InstanceType"], + "members":{ + "InstanceType":{ + "shape":"TrainingInstanceType", + "documentation":"

    The ML compute instance type. An instance type can appear only once in an InstancePreferences list.

    " + }, + "InstanceCount":{ + "shape":"TrainingInstanceCount", + "documentation":"

    The number of instances to launch if this instance type is selected. Specify the instance count for the training job in one of the following two ways:

    1. Per preference – Set InstanceCount on every preference in the InstancePreferences list and don't set ResourceConfig$InstanceCount. Use this when each instance type needs a different number of instances to deliver equivalent compute.

    2. One count for the job – Set ResourceConfig$InstanceCount and omit it from every preference. SageMaker applies this to all instance types in the list.

    For example, in a list of five preferences, either all five specify InstanceCount or none of them do. SageMaker rejects requests that set InstanceCount on only some preferences, that set it both per preference and in ResourceConfig, or that omit it in both places.

    ", + "box":true + }, + "TrainingPlanArns":{ + "shape":"TrainingPlanArnList", + "documentation":"

    The Amazon Resource Name (ARN) of a training plan to use if this instance type is selected. The plan's instance type must match InstanceType. A preference with a training plan uses that plan's reserved capacity; a preference without one uses on-demand capacity. Per-preference TrainingPlanArns is mutually exclusive with the job-level TrainingPlanArn in ResourceConfig.

    " + } + }, + "documentation":"

    A candidate instance type preference in an InstancePreferences list.

    " + }, + "InstancePreferenceList":{ + "type":"list", + "member":{"shape":"InstancePreference"}, + "documentation":"

    Ordered list of candidate instance types, in priority order.

    ", + "max":5, + "min":1 + }, "InstanceRequirementsEniConfiguration":{ "type":"structure", "members":{ @@ -29425,6 +29895,12 @@ "ml.g6.16xlarge", "ml.g6.24xlarge", "ml.g6.48xlarge", + "ml.g7e.2xlarge", + "ml.g7e.4xlarge", + "ml.g7e.8xlarge", + "ml.g7e.12xlarge", + "ml.g7e.24xlarge", + "ml.g7e.48xlarge", "ml.p5.4xlarge", "ml.p5en.48xlarge", "ml.g6e.xlarge", @@ -35305,7 +35781,7 @@ "documentation":"

    Maximum job scheduler pending time in seconds.

    ", "box":true, "max":2419200, - "min":7200 + "min":1800 }, "MaxPercentageOfInputDatasetLabeled":{ "type":"integer", @@ -38628,7 +39104,9 @@ "Stopped", "Failed", "Deleting", - "Updating" + "Updating", + "PendingMaintenance", + "InMaintenance" ] }, "NotebookInstanceSummary":{ @@ -38931,7 +39409,7 @@ "OnStartDeepHealthChecks":{ "type":"list", "member":{"shape":"DeepHealthCheckType"}, - "max":2, + "max":3, "min":1 }, "OnlineStoreConfig":{ @@ -38952,7 +39430,7 @@ }, "StorageType":{ "shape":"StorageType", - "documentation":"

    Option for different tiers of low latency storage for real-time data retrieval.

    • Standard: A managed low latency data store for feature groups.

    • InMemory: A managed data store for feature groups that supports very low latency retrieval.

    " + "documentation":"

    Option for different tiers of low latency storage for real-time data retrieval.

    • Standard: A managed low latency data store for feature groups.

    • Standard_V2: A managed low latency data store for feature groups that supports partial updates to individual features using the UpdateRecord operation. Choose this storage type at feature group creation time if your use case requires updating specific feature values without rewriting the entire record.

    • InMemory: A managed data store for feature groups that supports very low latency retrieval.

    " } }, "documentation":"

    Use this to specify the Amazon Web Services Key Management Service (KMS) Key ID, or KMSKeyId, for at rest data encryption. You can turn OnlineStore on or off by specifying the EnableOnlineStore flag at General Assembly.

    The default value is False.

    " @@ -38963,6 +39441,10 @@ "TtlDuration":{ "shape":"TtlDuration", "documentation":"

    Time to live duration, where the record is hard deleted after the expiration time is reached; ExpiresAt = EventTime + TtlDuration. For information on HardDelete, see the DeleteRecord API in the Amazon SageMaker API Reference guide.

    " + }, + "StorageType":{ + "shape":"StorageType", + "documentation":"

    The online store storage type to migrate the feature group to. Use this parameter to migrate an existing feature group from Standard to Standard_V2 storage format, enabling support for the UpdateRecord operation. Migration is a one-way operation and cannot be reversed.

    " } }, "documentation":"

    Updates the feature group online store configuration.

    " @@ -39081,7 +39563,20 @@ "ml.inf2.48xlarge", "ml.trn1.2xlarge", "ml.trn1.32xlarge", - "ml.trn1n.32xlarge" + "ml.trn1n.32xlarge", + "ml.p6-b200.48xlarge", + "ml.g7e.2xlarge", + "ml.g7e.4xlarge", + "ml.g7e.8xlarge", + "ml.g7e.12xlarge", + "ml.g7e.24xlarge", + "ml.g7e.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge" ] }, "OptimizationJobEnvironmentVariables":{ @@ -39212,6 +39707,13 @@ }, "documentation":"

    Summarizes an optimization job by providing some of its key properties.

    " }, + "OptimizationJobTrainingPlanArns":{ + "type":"list", + "member":{"shape":"TrainingPlanArn"}, + "documentation":"

    Amazon Resource Names (ARNs) of the training plans whose reserved capacity backs the optimization job. Bounded to a single plan for now; the list shape allows widening to multiple plans in the future without a breaking scalar-to-list change.

    ", + "max":1, + "min":0 + }, "OptimizationModelAcceptEula":{"type":"boolean"}, "OptimizationModelAccessConfig":{ "type":"structure", @@ -39579,7 +40081,10 @@ }, "PartnerAppAuthType":{ "type":"string", - "enum":["IAM"] + "enum":[ + "IAM", + "IDC" + ] }, "PartnerAppConfig":{ "type":"structure", @@ -40401,6 +40906,32 @@ "LowerPriority" ] }, + "PrefixAwareRoutingConcurrencyThreshold":{ + "type":"integer", + "box":true, + "max":1024, + "min":1 + }, + "PrefixAwareRoutingConfig":{ + "type":"structure", + "members":{ + "PrefixLength":{ + "shape":"PrefixAwareRoutingPrefixLength", + "documentation":"

    The maximum length of the prefix used for routing decisions. Required when RoutingStrategy is PREFIX_AWARE.

    • For the SageMaker Runtime InvokeEndpoint and InvokeEndpointWithResponseStream APIs, this value specifies the number of bytes from the beginning of the request body.

    • For OpenAI-compatible API, this value specifies the number of characters from the text content of the messages array.

    The endpoint routes requests that share the same prefix to the same instance. Set this value to cover shared content (such as system prompts) plus enough unique content to distribute workloads across instances.

    " + }, + "ConcurrencyThreshold":{ + "shape":"PrefixAwareRoutingConcurrencyThreshold", + "documentation":"

    The maximum number of in-flight requests on the target instance before the endpoint routes to another instance. Required when RoutingStrategy is PREFIX_AWARE. When in-flight requests on the prefix-selected instance reach this threshold, the endpoint routes the request to an instance with more available capacity.

    " + } + }, + "documentation":"

    The configuration for prefix-aware routing on a SageMaker real-time inference endpoint. Specify PrefixLength and ConcurrencyThreshold to control routing behavior.

    " + }, + "PrefixAwareRoutingPrefixLength":{ + "type":"integer", + "box":true, + "max":65536, + "min":1024 + }, "PresignedDomainUrl":{"type":"string"}, "PresignedUrlAccessConfig":{ "type":"structure", @@ -40461,11 +40992,7 @@ }, "ProcessingClusterConfig":{ "type":"structure", - "required":[ - "InstanceCount", - "InstanceType", - "VolumeSizeInGB" - ], + "required":["VolumeSizeInGB"], "members":{ "InstanceCount":{ "shape":"ProcessingInstanceCount", @@ -40482,6 +41009,18 @@ "VolumeKmsKeyId":{ "shape":"KmsKeyId", "documentation":"

    The Amazon Web Services Key Management Service (Amazon Web Services KMS) key that Amazon SageMaker uses to encrypt data on the storage volume attached to the ML compute instance(s) that run the processing job.

    Certain Nitro-based instances include local storage, dependent on the instance type. Local storage volumes are encrypted using a hardware module on the instance. You can't request a VolumeKmsKeyId when using an instance type with local storage.

    For a list of instance types that support local instance storage, see Instance Store Volumes.

    For more information about local instance storage encryption, see SSD Instance Store Volumes.

    " + }, + "InstancePreferences":{ + "shape":"ProcessingInstancePreferenceList", + "documentation":"

    An ordered list of ML compute instance types for the processing job, in priority order. Amazon SageMaker launches the job on the first instance type in the list that has available capacity. If capacity is insufficient, Amazon SageMaker evaluates the next instance type in the list. Exactly one instance type is selected for the job.

    InstancePreferences is mutually exclusive with InstanceType.

    " + }, + "SelectedInstanceType":{ + "shape":"ProcessingInstanceType", + "documentation":"

    The instance type that Amazon SageMaker selected for the job from InstancePreferences. Returned by DescribeProcessingJob after an instance type is selected. This field is read-only and isn't accepted in CreateProcessingJob requests.

    " + }, + "SelectedInstanceCount":{ + "shape":"ProcessingInstanceCount", + "documentation":"

    The number of instances of SelectedInstanceType that the job launched with. The job is billed for this instance type and count. Returned by DescribeProcessingJob after an instance type is selected. This field is read-only and isn't accepted in CreateProcessingJob requests.

    " } }, "documentation":"

    Configuration for the cluster used to run a processing job.

    " @@ -40552,6 +41091,28 @@ "max":100, "min":1 }, + "ProcessingInstancePreference":{ + "type":"structure", + "required":["InstanceType"], + "members":{ + "InstanceType":{ + "shape":"ProcessingInstanceType", + "documentation":"

    The ML compute instance type. An instance type can appear only once in an InstancePreferences list.

    " + }, + "InstanceCount":{ + "shape":"ProcessingInstanceCount", + "documentation":"

    The number of instances to launch if this instance type is selected. Specify the instance count for the processing job in one of the following two ways:

    1. Per preference – Set InstanceCount on every preference in the InstancePreferences list and don't set ProcessingClusterConfig$InstanceCount. Use this when each instance type needs a different number of instances to deliver equivalent compute.

    2. One count for the job – Set ProcessingClusterConfig$InstanceCount and omit it from every preference. Amazon SageMaker applies this to all instance types in the list.

    For example, in a list of five preferences, either all five specify InstanceCount or none of them do. Amazon SageMaker rejects requests that set InstanceCount on only some preferences, that set it both per preference and in ProcessingClusterConfig, or that omit it in both places.

    " + } + }, + "documentation":"

    A candidate instance type preference in a processing InstancePreferences list.

    " + }, + "ProcessingInstancePreferenceList":{ + "type":"list", + "member":{"shape":"ProcessingInstancePreference"}, + "documentation":"

    Ordered list of candidate instance types, in priority order.

    ", + "max":5, + "min":1 + }, "ProcessingInstanceType":{ "type":"string", "enum":[ @@ -40681,7 +41242,54 @@ "ml.g7e.8xlarge", "ml.g7e.12xlarge", "ml.g7e.24xlarge", - "ml.g7e.48xlarge" + "ml.g7e.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge", + "ml.r6i.large", + "ml.r6i.xlarge", + "ml.r6i.2xlarge", + "ml.r6i.4xlarge", + "ml.r6i.8xlarge", + "ml.r6i.12xlarge", + "ml.r6i.16xlarge", + "ml.r6i.24xlarge", + "ml.r6i.32xlarge", + "ml.m8i.large", + "ml.m8i.xlarge", + "ml.m8i.2xlarge", + "ml.m8i.4xlarge", + "ml.m8i.8xlarge", + "ml.m8i.12xlarge", + "ml.m8i.16xlarge", + "ml.m8i.24xlarge", + "ml.m8i.32xlarge", + "ml.m8i.48xlarge", + "ml.m8i.96xlarge", + "ml.c8i.xlarge", + "ml.c8i.2xlarge", + "ml.c8i.4xlarge", + "ml.c8i.8xlarge", + "ml.c8i.12xlarge", + "ml.c8i.16xlarge", + "ml.c8i.24xlarge", + "ml.c8i.32xlarge", + "ml.c8i.48xlarge", + "ml.c8i.96xlarge", + "ml.r8i.large", + "ml.r8i.xlarge", + "ml.r8i.2xlarge", + "ml.r8i.4xlarge", + "ml.r8i.8xlarge", + "ml.r8i.12xlarge", + "ml.r8i.16xlarge", + "ml.r8i.24xlarge", + "ml.r8i.32xlarge", + "ml.r8i.48xlarge", + "ml.r8i.96xlarge" ] }, "ProcessingJob":{ @@ -41335,6 +41943,12 @@ "ml.g7e.12xlarge", "ml.g7e.24xlarge", "ml.g7e.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge", "ml.p4d.24xlarge", "ml.c7g.large", "ml.c7g.xlarge", @@ -41533,7 +42147,11 @@ "members":{ "RoutingStrategy":{ "shape":"RoutingStrategy", - "documentation":"

    Sets how the endpoint routes incoming traffic:

    • LEAST_OUTSTANDING_REQUESTS: The endpoint routes requests to the specific instances that have more capacity to process them.

    • RANDOM: The endpoint routes each request to a randomly chosen instance.

    " + "documentation":"

    Sets how the endpoint routes incoming traffic:

    • LEAST_OUTSTANDING_REQUESTS: The endpoint routes requests to the specific instances that have more capacity to process them.

    • RANDOM: The endpoint routes each request to a randomly chosen instance.

    • PREFIX_AWARE: The endpoint routes requests that share the same prompt prefix to the same instance. When the number of in-flight requests on the selected instance reaches the configured threshold, the endpoint routes the request to an instance with more available capacity.

    " + }, + "PrefixAwareRoutingConfig":{ + "shape":"PrefixAwareRoutingConfig", + "documentation":"

    The configuration for prefix-aware routing. Specify this parameter only when you set RoutingStrategy to PREFIX_AWARE.

    " } }, "documentation":"

    Settings that control how the endpoint routes incoming traffic to the instances that the endpoint hosts.

    " @@ -43313,6 +43931,19 @@ "InstancePlacementConfig":{ "shape":"InstancePlacementConfig", "documentation":"

    Configuration for how training job instances are placed and allocated within UltraServers. Only applicable for UltraServer capacity.

    " + }, + "InstancePreferences":{ + "shape":"InstancePreferenceList", + "documentation":"

    An ordered list of ML compute instance types for the training job, in priority order. SageMaker launches the training job on the first instance type in the list that has available capacity. If capacity is insufficient, SageMaker evaluates the next instance type in the preferred list. Exactly one instance type is selected for the job.

    InstancePreferences is mutually exclusive with InstanceType, InstanceGroups, InstancePlacementConfig, and EnableManagedSpotTraining, and supports only Flexible Training Plans (FTP) and On-Demand capacity.

    " + }, + "SelectedInstanceType":{ + "shape":"TrainingInstanceType", + "documentation":"

    The instance type that SageMaker selected for the job from the provided InstancePreferences. The job is billed for this instance type and count. Returned by DescribeTrainingJob after an instance type is selected. This field is read-only and isn't accepted in CreateTrainingJob requests.

    " + }, + "SelectedInstanceCount":{ + "shape":"TrainingInstanceCount", + "documentation":"

    The number of instances of SelectedInstanceType that the training job launched with. The job is billed for this instance type and count. Returned by DescribeTrainingJob after an instance type is selected. This field is read-only and isn't accepted in CreateTrainingJob requests.

    ", + "box":true } }, "documentation":"

    Describes the resources, including machine learning (ML) compute instances and ML storage volumes, to use for model training.

    " @@ -43479,7 +44110,8 @@ "HyperParameterTuningJob", "ModelCard", "PipelineVersion", - "Job" + "Job", + "HubContent" ] }, "ResponseMIMEType":{ @@ -43634,7 +44266,8 @@ "type":"string", "enum":[ "LEAST_OUTSTANDING_REQUESTS", - "RANDOM" + "RANDOM", + "PREFIX_AWARE" ] }, "RuleConfigurationName":{ @@ -44115,6 +44748,10 @@ "Job":{ "shape":"Job", "documentation":"

    The properties of a job.

    " + }, + "HubContent":{ + "shape":"HubContent", + "documentation":"

    The properties of a hub content resource.

    " } }, "documentation":"

    A single resource returned as part of the Search API response.

    " @@ -44410,6 +45047,12 @@ } } }, + "SequenceLength":{ + "type":"string", + "max":50, + "min":1, + "pattern":"\\d+K" + }, "ServerlessJobBaseModelArn":{ "type":"string", "documentation":"

    ServerlessJobConfig relevant fields

    ", @@ -44452,6 +45095,10 @@ "EvaluatorArn":{ "shape":"EvaluatorArn", "documentation":"

    The evaluator Amazon Resource Name (ARN) used as reward function or reward prompt.

    " + }, + "SequenceLength":{ + "shape":"SequenceLength", + "documentation":"

    The maximum sequence length, in tokens, that the customization job supports. SageMaker uses this value to select a training configuration for the base model that you specify. The parameter supports the following values:

    • 1K

    • 2K

    • 4K

    • 8K

    • 16K

    • 32K

    • 64K

    • 128K

    If you don't specify a value, SageMaker selects a training configuration based on the other values that you specify. The selection is not restricted to a particular sequence length.

    " } }, "documentation":"

    The configuration for the serverless training job.

    " @@ -45662,7 +46309,7 @@ }, "MaxPendingTimeInSeconds":{ "shape":"MaxPendingTimeInSeconds", - "documentation":"

    The maximum length of time, in seconds, that a training or compilation job can be pending before it is stopped.

    When working with training jobs that use capacity from training plans, not all Pending job states count against the MaxPendingTimeInSeconds limit. The following scenarios do not increment the MaxPendingTimeInSeconds counter:

    • The plan is in a Scheduled state: Jobs queued (in Pending status) before a plan's start date (waiting for scheduled start time)

    • Between capacity reservations: Jobs temporarily back to Pending status between two capacity reservation periods

    MaxPendingTimeInSeconds only increments when jobs are actively waiting for capacity in an Active plan.

    " + "documentation":"

    The maximum length of time, in seconds, that a training or compilation job can be pending before it is stopped.

    When working with training jobs that use capacity from training plans, not all Pending job states count against the MaxPendingTimeInSeconds limit. The following scenarios do not increment the MaxPendingTimeInSeconds counter:

    • The plan is in a Scheduled state: Jobs queued (in Pending status) before a plan's start date (waiting for scheduled start time)

    • Between capacity reservations: Jobs temporarily back to Pending status between two capacity reservation periods

    MaxPendingTimeInSeconds only increments when jobs are actively waiting for capacity in an Active plan.

    • MaxPendingTimeInSeconds takes effect only for jobs that request accelerated computing instance types, such as instances in the ml.p, ml.g, and ml.trn families. It has no effect on jobs that request CPU-only instance types.

    • If the job specifies InstancePreferences, MaxPendingTimeInSeconds bounds the total time SageMaker spends working through your list of instance types. It is not applied per instance type preference, and takes effect only when the list includes at least one accelerated computing instance type.

    " } }, "documentation":"

    Specifies a limit to how long a job can run. When the job reaches the time limit, SageMaker ends the job. Use this API to cap costs.

    To stop a training job, SageMaker sends the algorithm the SIGTERM signal, which delays job termination for 120 seconds. Algorithms can use this 120-second window to save the model artifacts, so the results of training are not lost.

    The training algorithms provided by SageMaker automatically save the intermediate results of a model training job when possible. This attempt to save artifacts is only a best effort case as model might not be in a state from which it can be saved. For example, if training has just started, the model might not be ready to save. When saved, this intermediate data is a valid model artifact. You can use it to create a model with CreateModel.

    The Neural Topic Model (NTM) currently does not support saving intermediate model artifacts. When training NTMs, make sure that the maximum runtime is sufficient for the training job to complete.

    " @@ -45671,6 +46318,7 @@ "type":"string", "enum":[ "Standard", + "Standard_V2", "InMemory" ] }, @@ -46892,7 +47540,54 @@ "ml.g7e.8xlarge", "ml.g7e.12xlarge", "ml.g7e.24xlarge", - "ml.g7e.48xlarge" + "ml.g7e.48xlarge", + "ml.g7.2xlarge", + "ml.g7.4xlarge", + "ml.g7.8xlarge", + "ml.g7.12xlarge", + "ml.g7.24xlarge", + "ml.g7.48xlarge", + "ml.r6i.large", + "ml.r6i.xlarge", + "ml.r6i.2xlarge", + "ml.r6i.4xlarge", + "ml.r6i.8xlarge", + "ml.r6i.12xlarge", + "ml.r6i.16xlarge", + "ml.r6i.24xlarge", + "ml.r6i.32xlarge", + "ml.m8i.large", + "ml.m8i.xlarge", + "ml.m8i.2xlarge", + "ml.m8i.4xlarge", + "ml.m8i.8xlarge", + "ml.m8i.12xlarge", + "ml.m8i.16xlarge", + "ml.m8i.24xlarge", + "ml.m8i.32xlarge", + "ml.m8i.48xlarge", + "ml.m8i.96xlarge", + "ml.c8i.xlarge", + "ml.c8i.2xlarge", + "ml.c8i.4xlarge", + "ml.c8i.8xlarge", + "ml.c8i.12xlarge", + "ml.c8i.16xlarge", + "ml.c8i.24xlarge", + "ml.c8i.32xlarge", + "ml.c8i.48xlarge", + "ml.c8i.96xlarge", + "ml.r8i.large", + "ml.r8i.xlarge", + "ml.r8i.2xlarge", + "ml.r8i.4xlarge", + "ml.r8i.8xlarge", + "ml.r8i.12xlarge", + "ml.r8i.16xlarge", + "ml.r8i.24xlarge", + "ml.r8i.32xlarge", + "ml.r8i.48xlarge", + "ml.r8i.96xlarge" ] }, "TrainingInstanceTypes":{ @@ -47233,6 +47928,13 @@ "min":50, "pattern":"arn:aws[a-z\\-]*:sagemaker:[a-z0-9\\-]*:[0-9]{12}:training-plan/.*" }, + "TrainingPlanArnList":{ + "type":"list", + "member":{"shape":"TrainingPlanArn"}, + "documentation":"

    Training plan ARNs for a single instance preference.

    ", + "max":1, + "min":1 + }, "TrainingPlanArns":{ "type":"list", "member":{"shape":"TrainingPlanArn"} @@ -47836,7 +48538,15 @@ "ml.g6.12xlarge", "ml.g6.16xlarge", "ml.g6.24xlarge", - "ml.g6.48xlarge" + "ml.g6.48xlarge", + "ml.g6e.xlarge", + "ml.g6e.2xlarge", + "ml.g6e.4xlarge", + "ml.g6e.8xlarge", + "ml.g6e.12xlarge", + "ml.g6e.16xlarge", + "ml.g6e.24xlarge", + "ml.g6e.48xlarge" ] }, "TransformInstanceTypes":{ @@ -50199,6 +50909,14 @@ "shape":"PartnerAppConfig", "documentation":"

    Configuration settings for the SageMaker Partner AI App.

    " }, + "IdcConfig":{ + "shape":"IdcConfigInput", + "documentation":"

    Specifies the Amazon Web Services IAM Identity Center configuration for the SageMaker Partner AI App. Specify this parameter when AuthType is IDC. Apps that use IAM authorization don't use this parameter.

    " + }, + "AuthType":{ + "shape":"PartnerAppAuthType", + "documentation":"

    The authorization type that users use to access the SageMaker Partner AI App. Use this parameter to migrate an existing SageMaker Partner AI App from IAM authorization to IDC authorization. Valid values:

    • IAM: Users access the SageMaker Partner AI App with their Amazon Web Services IAM identity.

    • IDC: Users access the SageMaker Partner AI App with their Amazon Web Services IAM Identity Center identity. Specify the Identity Center instance to use in IdcConfig.

    " + }, "EnableIamSessionBasedIdentity":{ "shape":"Boolean", "documentation":"

    When set to TRUE, the SageMaker Partner AI App sets the Amazon Web Services IAM session name or the authenticated IAM user as the identity of the SageMaker Partner AI App user.

    ", diff --git a/services/sagemakera2iruntime/pom.xml b/services/sagemakera2iruntime/pom.xml index 4263f24b300d..6ffd07d9b4dc 100644 --- a/services/sagemakera2iruntime/pom.xml +++ b/services/sagemakera2iruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakera2iruntime AWS Java SDK :: Services :: SageMaker A2I Runtime diff --git a/services/sagemakera2iruntime/src/main/resources/codegen-resources/customization.config b/services/sagemakera2iruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakera2iruntime/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakera2iruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e5aaa883744e --- /dev/null +++ b/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://a2i-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://a2i-runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://a2i-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://a2i-runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b92705e321b9..000000000000 --- a/services/sagemakera2iruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://a2i-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://a2i-runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://a2i-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://a2i-runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemakeredge/pom.xml b/services/sagemakeredge/pom.xml index e04333bb607f..e4249a3a2c35 100644 --- a/services/sagemakeredge/pom.xml +++ b/services/sagemakeredge/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakeredge AWS Java SDK :: Services :: Sagemaker Edge diff --git a/services/sagemakeredge/src/main/resources/codegen-resources/customization.config b/services/sagemakeredge/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakeredge/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakeredge/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e278fee8fa6a --- /dev/null +++ b/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://edge.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://edge.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://edge.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://edge.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index abdd05d2bc68..000000000000 --- a/services/sagemakeredge/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://edge.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://edge.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://edge.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://edge.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemakerfeaturestoreruntime/pom.xml b/services/sagemakerfeaturestoreruntime/pom.xml index 12294aa2bde3..0edbff1e81c3 100644 --- a/services/sagemakerfeaturestoreruntime/pom.xml +++ b/services/sagemakerfeaturestoreruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakerfeaturestoreruntime AWS Java SDK :: Services :: Sage Maker Feature Store Runtime diff --git a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/customization.config b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b30ac541a5e2 --- /dev/null +++ b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://featurestore-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://featurestore-runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://featurestore-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://featurestore-runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 36583d92fe7b..000000000000 --- a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://featurestore-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://featurestore-runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://featurestore-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://featurestore-runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/service-2.json b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/service-2.json index 9819e70f9813..82a5de2b5ee6 100644 --- a/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/service-2.json +++ b/services/sagemakerfeaturestoreruntime/src/main/resources/codegen-resources/service-2.json @@ -111,6 +111,23 @@ {"shape":"AccessForbidden"} ], "documentation":"

    The PutRecord API is used to ingest a list of Records into your feature group.

    If a new record’s EventTime is greater, the new record is written to both the OnlineStore and OfflineStore. Otherwise, the record is a historic record and it is written only to the OfflineStore.

    You can specify the ingestion to be applied to the OnlineStore, OfflineStore, or both by using the TargetStores request parameter.

    You can set the ingested record to expire at a given time to live (TTL) duration after the record’s event time, ExpiresAt = EventTime + TtlDuration, by specifying the TtlDuration parameter. A record level TtlDuration is set when specifying the TtlDuration parameter using the PutRecord API call. If the input TtlDuration is null or unspecified, TtlDuration is set to the default feature group level TtlDuration. A record level TtlDuration supersedes the group level TtlDuration.

    " + }, + "UpdateRecord":{ + "name":"UpdateRecord", + "http":{ + "method":"POST", + "requestUri":"/FeatureGroup/{FeatureGroupName}/Record" + }, + "input":{"shape":"UpdateRecordRequest"}, + "errors":[ + {"shape":"ValidationError"}, + {"shape":"InternalFailure"}, + {"shape":"ServiceUnavailable"}, + {"shape":"AccessForbidden"}, + {"shape":"ResourceNotFound"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates one or more feature values for an existing record in the specified feature group. Features that you do not include in the request remain unchanged. You can update up to 100 features per call.

    This operation is available only for feature groups that use the Standard_V2 or InMemory online store type.

    The record must already exist. If the record does not exist or has been soft-deleted, the operation returns a ResourceNotFound error. To create a record, use PutRecord.

    If you provide an EventTime that is older than the record's current EventTime, the service rejects the update with a ConflictException. If the EventTime is equal to or newer than the current value, the service applies the update. If you omit EventTime, the service keeps the record's existing EventTime and applies the update.

    If you specify a TtlDuration, you must also provide an EventTime in the request. Otherwise, the operation returns a ValidationError.

    " } }, "shapes":{ @@ -345,6 +362,16 @@ } }, "Boolean":{"type":"boolean"}, + "ConflictException":{ + "type":"structure", + "members":{ + "Message":{"shape":"Message"} + }, + "documentation":"

    The service rejected the update because the provided EventTime is older than the record's current EventTime. To persist the update, retrieve the record's latest EventTime and resubmit the request with an EventTime that is equal to or newer than the current value.

    ", + "error":{"httpStatusCode":409}, + "exception":true, + "synthetic":true + }, "DeleteRecordRequest":{ "type":"structure", "required":[ @@ -662,6 +689,38 @@ "member":{"shape":"BatchGetRecordIdentifier"}, "min":0 }, + "UpdateRecordRequest":{ + "type":"structure", + "required":[ + "FeatureGroupName", + "RecordIdentifierValueAsString", + "Features" + ], + "members":{ + "FeatureGroupName":{ + "shape":"FeatureGroupNameOrArn", + "documentation":"

    The identifier for the feature group that contains the record to update. You can specify one of the following:

    • The feature group name.

    • The feature group Amazon Resource Name (ARN).

    ", + "location":"uri", + "locationName":"FeatureGroupName" + }, + "RecordIdentifierValueAsString":{ + "shape":"ValueAsString", + "documentation":"

    The value that uniquely identifies the record in the feature group. This must match the value defined by the feature group's record identifier feature.

    " + }, + "Features":{ + "shape":"Record", + "documentation":"

    The feature values to write to the record.

    " + }, + "TargetStores":{ + "shape":"TargetStores", + "documentation":"

    The target stores for the record update. By default, Amazon SageMaker Feature Store updates the record in all stores associated with the FeatureGroup.

    " + }, + "TtlDuration":{ + "shape":"TtlDuration", + "documentation":"

    The time-to-live (TTL) duration for the record. Amazon SageMaker Feature Store deletes the record when EventTime + TtlDuration elapses. If you omit this parameter, the record's existing TTL setting remains unchanged. For information about HardDelete, see the DeleteRecord operation in the Amazon SageMaker API Reference.

    " + } + } + }, "ValidationError":{ "type":"structure", "members":{ diff --git a/services/sagemakergeospatial/pom.xml b/services/sagemakergeospatial/pom.xml index a9ac96a8e194..8bf8ef34f373 100644 --- a/services/sagemakergeospatial/pom.xml +++ b/services/sagemakergeospatial/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakergeospatial AWS Java SDK :: Services :: Sage Maker Geospatial diff --git a/services/sagemakergeospatial/src/main/resources/codegen-resources/customization.config b/services/sagemakergeospatial/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakergeospatial/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakergeospatial/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e2097e8d304a --- /dev/null +++ b/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sagemaker-geospatial-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sagemaker-geospatial-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sagemaker-geospatial.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sagemaker-geospatial.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 9c03b6b79cc3..000000000000 --- a/services/sagemakergeospatial/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sagemaker-geospatial-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sagemaker-geospatial-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sagemaker-geospatial.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sagemaker-geospatial.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sagemakerjobruntime/pom.xml b/services/sagemakerjobruntime/pom.xml index 36e461062650..62f2c4221495 100644 --- a/services/sagemakerjobruntime/pom.xml +++ b/services/sagemakerjobruntime/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakerjobruntime AWS Java SDK :: Services :: Sagemaker Job Runtime diff --git a/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9bd49d6725e6 --- /dev/null +++ b/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://job-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://job-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QQF9eEDAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0921df94ed5b..000000000000 --- a/services/sagemakerjobruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,239 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://job-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://job-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://job-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://job-runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://job-runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sagemakermetrics/pom.xml b/services/sagemakermetrics/pom.xml index 050361e92b4c..895ef7c96e8c 100644 --- a/services/sagemakermetrics/pom.xml +++ b/services/sagemakermetrics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakermetrics AWS Java SDK :: Services :: Sage Maker Metrics diff --git a/services/sagemakermetrics/src/main/resources/codegen-resources/customization.config b/services/sagemakermetrics/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakermetrics/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakermetrics/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..163545493211 --- /dev/null +++ b/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metrics.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metrics-fips.sagemaker.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metrics.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metrics.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://metrics.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 51374a503a99..000000000000 --- a/services/sagemakermetrics/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://metrics.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://metrics-fips.sagemaker.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://metrics.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://metrics.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://metrics.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemakerruntime/pom.xml b/services/sagemakerruntime/pom.xml index 15763ceefc0c..d43c3b07d8bf 100644 --- a/services/sagemakerruntime/pom.xml +++ b/services/sagemakerruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakerruntime AWS Java SDK :: Services :: SageMaker Runtime diff --git a/services/sagemakerruntime/src/main/resources/codegen-resources/customization.config b/services/sagemakerruntime/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sagemakerruntime/src/main/resources/codegen-resources/customization.config +++ b/services/sagemakerruntime/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3d6f88b45308 --- /dev/null +++ b/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,236 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-fips.sagemaker.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7455b869c586..000000000000 --- a/services/sagemakerruntime/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,364 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sagemakerruntime/src/main/resources/codegen-resources/service-2.json b/services/sagemakerruntime/src/main/resources/codegen-resources/service-2.json index cc6cc95c808b..e1f5199fb439 100644 --- a/services/sagemakerruntime/src/main/resources/codegen-resources/service-2.json +++ b/services/sagemakerruntime/src/main/resources/codegen-resources/service-2.json @@ -329,6 +329,12 @@ "documentation":"

    Creates a stateful session or identifies an existing one. You can do one of the following:

    • Create a stateful session by specifying the value NEW_SESSION.

    • Send your request to an existing stateful session by specifying the ID of that session.

    With a stateful session, you can send multiple requests to a stateful model. When you create a session with a stateful model, the model must create the session ID and set the expiration time. The model must also provide that information in the response to your request. You can get the ID and timestamp from the NewSessionId response parameter. For any subsequent request where you specify that session ID, SageMaker AI routes the request to the same instance that supports the session.

    ", "location":"header", "locationName":"X-Amzn-SageMaker-Session-Id" + }, + "PrefixAwareId":{ + "shape":"PrefixAwareIdHeader", + "documentation":"

    An optional, stable identifier that serves as a routing hint for prefix-aware routing. The service routes requests with the same prefix and the same identifier to the same instance. If requests from different applications might have the same prompt prefix, set a different identifier for each application to differentiate their routing decisions.

    Applies only to endpoints configured with a RoutingStrategy of PREFIX_AWARE.

    ", + "location":"header", + "locationName":"X-Amzn-SageMaker-Prefix-Aware-Id" } }, "payload":"Body" @@ -438,6 +444,12 @@ "documentation":"

    The ID of a stateful session to handle your request.

    You can't create a stateful session by using the InvokeEndpointWithResponseStream action. Instead, you can create one by using the InvokeEndpoint action. In your request, you specify NEW_SESSION for the SessionId request parameter. The response to that request provides the session ID for the NewSessionId response parameter.

    ", "location":"header", "locationName":"X-Amzn-SageMaker-Session-Id" + }, + "PrefixAwareId":{ + "shape":"PrefixAwareIdHeader", + "documentation":"

    An optional, stable identifier that serves as a routing hint for prefix-aware routing. The service routes requests with the same prefix and the same identifier to the same instance. If requests from different applications might have the same prompt prefix, set a different identifier for each application to differentiate their routing decisions.

    Applies only to endpoints configured with a RoutingStrategy of PREFIX_AWARE.

    ", + "location":"header", + "locationName":"X-Amzn-SageMaker-Prefix-Aware-Id" } }, "payload":"Body" @@ -538,6 +550,12 @@ "documentation":"

    A wrapper for pieces of the payload that's returned in response to a streaming inference request. A streaming inference response consists of one or more payload parts.

    ", "event":true }, + "PrefixAwareIdHeader":{ + "type":"string", + "max":64, + "min":1, + "pattern":"\\A\\S[\\p{Print}]*\\z" + }, "RequestTTLSecondsHeader":{ "type":"integer", "max":21600, diff --git a/services/sagemakerruntimehttp2/pom.xml b/services/sagemakerruntimehttp2/pom.xml index 3fcb68a60871..646734d7f176 100644 --- a/services/sagemakerruntimehttp2/pom.xml +++ b/services/sagemakerruntimehttp2/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sagemakerruntimehttp2 AWS Java SDK :: Services :: Sage Maker Runtime HTTP2 diff --git a/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..28dd31c1d998 --- /dev/null +++ b/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,329 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 23, + "nodes": "/////wAAAAH/////AAAAAAAAABYAAAADAAAAAQAAAAQF9eEPAAAAAgAAAAUF9eEPAAAAAwAAABMAAAAGAAAABAAAABMAAAAHAAAABQAAABMAAAAIAAAABgAAABMAAAAJAAAABwAAABMAAAAKAAAACAAAABMAAAALAAAACQAAABMAAAAMAAAACgAAAA8AAAANAAAADAAAAA4F9eEOAAAADQX14QwF9eENAAAACwAAABEAAAAQAAAADAX14QkF9eELAAAADAAAABIF9eEKAAAADQX14QgF9eEJAAAACgAAABUAAAAUAAAADAX14QUF9eEEAAAADAX14QcF9eEGAAAACgX14QEAAAAXAAAADAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 22432095e492..000000000000 --- a/services/sagemakerruntimehttp2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,1548 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://runtime-fips.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}:8443", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://runtime.sagemaker.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/savingsplans/pom.xml b/services/savingsplans/pom.xml index 1eb41aaeb9ad..86c3496cb556 100644 --- a/services/savingsplans/pom.xml +++ b/services/savingsplans/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT savingsplans AWS Java SDK :: Services :: Savingsplans diff --git a/services/savingsplans/src/main/resources/codegen-resources/customization.config b/services/savingsplans/src/main/resources/codegen-resources/customization.config index d7ed49e2a984..c07d1f98a7e6 100644 --- a/services/savingsplans/src/main/resources/codegen-resources/customization.config +++ b/services/savingsplans/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "customServiceMetadata": { "contentType": "application/json" - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/savingsplans/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/savingsplans/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..69bc0c42664a --- /dev/null +++ b/services/savingsplans/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,237 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans.global.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "savingsplans", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "savingsplans", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://savingsplans.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAYAAAAEAAAAAwX14Q0AAAAFAAAABQX14QEF9eENAAAAAgAAAAcF9eENAAAAAwAAAAwAAAAIAAAABAAAAAsAAAAJAAAABQAAAAoF9eEMAAAABwX14QIF9eEDAAAABQX14QEF9eEHAAAABQAAAA4AAAANAAAABgX14QoF9eELAAAABgAAAA8F9eEJAAAABwX14QgF9eEJAAAAAwX14QQAAAARAAAABQX14QUF9eEG" +} \ No newline at end of file diff --git a/services/savingsplans/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/savingsplans/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 36ee2cc3b3d1..000000000000 --- a/services/savingsplans/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,527 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://savingsplans.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "savingsplans", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://savingsplans.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ] - } - ], - "endpoint": { - "url": "https://savingsplans.global.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "savingsplans", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://savingsplans.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "savingsplans", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://savingsplans-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://savingsplans-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://savingsplans.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://savingsplans.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/scheduler/pom.xml b/services/scheduler/pom.xml index b4ea5d028bfd..113c60406511 100644 --- a/services/scheduler/pom.xml +++ b/services/scheduler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT scheduler AWS Java SDK :: Services :: Scheduler diff --git a/services/scheduler/src/main/resources/codegen-resources/customization.config b/services/scheduler/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/scheduler/src/main/resources/codegen-resources/customization.config +++ b/services/scheduler/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/scheduler/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/scheduler/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4aa5366f9aa7 --- /dev/null +++ b/services/scheduler/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scheduler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scheduler-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scheduler.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scheduler.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/scheduler/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/scheduler/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index beb22f2a846a..000000000000 --- a/services/scheduler/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scheduler-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scheduler-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scheduler.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scheduler.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/schemas/pom.xml b/services/schemas/pom.xml index c8db613581de..e534b049004b 100644 --- a/services/schemas/pom.xml +++ b/services/schemas/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT schemas AWS Java SDK :: Services :: Schemas diff --git a/services/schemas/src/main/resources/codegen-resources/customization.config b/services/schemas/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/schemas/src/main/resources/codegen-resources/customization.config +++ b/services/schemas/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/schemas/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/schemas/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a2972681b48b --- /dev/null +++ b/services/schemas/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://schemas-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://schemas-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://schemas.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://schemas.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/schemas/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/schemas/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6f143f13b4ee..000000000000 --- a/services/schemas/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://schemas-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://schemas-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://schemas.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://schemas.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/secretsmanager/pom.xml b/services/secretsmanager/pom.xml index 6e83494351a4..ed1e86520772 100644 --- a/services/secretsmanager/pom.xml +++ b/services/secretsmanager/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT secretsmanager AWS Java SDK :: Services :: AWS Secrets Manager diff --git a/services/secretsmanager/src/main/resources/codegen-resources/customization.config b/services/secretsmanager/src/main/resources/codegen-resources/customization.config index 55141f588dc7..23b6cfba9fda 100644 --- a/services/secretsmanager/src/main/resources/codegen-resources/customization.config +++ b/services/secretsmanager/src/main/resources/codegen-resources/customization.config @@ -2,6 +2,5 @@ "verifiedSimpleMethods": [ "getRandomPassword", "listSecrets" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/secretsmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/secretsmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9a9376c604ca --- /dev/null +++ b/services/secretsmanager/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,260 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager-fips.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager.{Region}.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://secretsmanager.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAsAAAAGAAAABAAAAAcF9eENAAAABQAAAAgF9eEMAAAABwX14QkAAAAJAAAACAX14QoAAAAKAAAACQX14QkF9eELAAAABAAAAA0AAAAMAAAABgX14QcF9eEIAAAABQAAAA4F9eEGAAAABgAAAA8F9eEGAAAABwX14QQAAAAQAAAACQX14QQF9eEFAAAAAwX14QEAAAASAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/secretsmanager/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/secretsmanager/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 78514ea2c136..000000000000 --- a/services/secretsmanager/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,439 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://secretsmanager-fips.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://secretsmanager-fips.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://secretsmanager-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://secretsmanager-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://secretsmanager.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://secretsmanager.{Region}.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://secretsmanager.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://secretsmanager.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://secretsmanager.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/securityagent/pom.xml b/services/securityagent/pom.xml index acf03a9691b5..96fb5224498e 100644 --- a/services/securityagent/pom.xml +++ b/services/securityagent/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT securityagent AWS Java SDK :: Services :: Security Agent diff --git a/services/securityagent/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/securityagent/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..29544aefc902 --- /dev/null +++ b/services/securityagent/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityagent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityagent.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/securityagent/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/securityagent/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1a8728f1e4a2..000000000000 --- a/services/securityagent/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://securityagent-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://securityagent.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/securityagent/src/main/resources/codegen-resources/service-2.json b/services/securityagent/src/main/resources/codegen-resources/service-2.json index b058cb33312c..d47595639a48 100644 --- a/services/securityagent/src/main/resources/codegen-resources/service-2.json +++ b/services/securityagent/src/main/resources/codegen-resources/service-2.json @@ -1342,6 +1342,14 @@ "description":{ "shape":"String", "documentation":"

    A description of the actor.

    " + }, + "enableEmailMfa":{ + "shape":"Boolean", + "documentation":"

    Whether email-based MFA is enabled for this actor.

    " + }, + "mfaForwardingAddress":{ + "shape":"SensitiveEmailAddress", + "documentation":"

    Server-generated email forwarding address for receiving MFA codes.

    " } }, "documentation":"

    Represents an actor used during penetration testing. An actor defines a user or entity that interacts with the target application, including authentication credentials and target URIs.

    " @@ -1643,6 +1651,10 @@ "integratedRepositories":{ "shape":"IntegratedRepositoryList", "documentation":"

    The list of integrated repositories associated with the pentest.

    " + }, + "trustedCaCertificates":{ + "shape":"TrustedCaCertificateList", + "documentation":"

    The trust anchors used to validate target endpoint TLS certificates. Provide these for endpoints served by a private or internal certificate authority (CA), an intermediate CA, or a self-signed certificate.

    " } }, "documentation":"

    The collection of assets used in a pentest configuration, including endpoints, actors, documents, source code repositories, and integrated repositories.

    " @@ -2556,6 +2568,32 @@ "type":"boolean", "box":true }, + "CaCertificatePem":{ + "type":"string", + "documentation":"

    A PEM-encoded X.509 certificate.

    ", + "max":8192, + "min":1, + "sensitive":true + }, + "CaCertificateSource":{ + "type":"structure", + "members":{ + "inlinePem":{ + "shape":"CaCertificatePem", + "documentation":"

    A PEM-encoded X.509 certificate supplied inline.

    " + }, + "artifactId":{ + "shape":"String", + "documentation":"

    The artifact ID of an uploaded certificate file.

    " + }, + "s3Location":{ + "shape":"String", + "documentation":"

    The Amazon S3 location URI of a customer-staged certificate.

    " + } + }, + "documentation":"

    The source of a trusted CA certificate. Exactly one member must be set.

    ", + "union":true + }, "Category":{ "type":"structure", "members":{ @@ -2728,6 +2766,10 @@ "shape":"ValidationMode", "documentation":"

    The validation mode for the code review. Valid values are SIMULATED and DISABLED.

    " }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for jobs started from this code review. If a job reaches the configured limit, it is gracefully stopped. If not set, jobs run to completion with no budget cap.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the code review was created, in UTC format.

    " @@ -2803,6 +2845,10 @@ "shape":"CodeRemediationStrategy", "documentation":"

    The code remediation strategy for the code review job.

    " }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for this code review job. If the cumulative task hours reach this limit, the job is gracefully stopped.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the code review job was created, in UTC format.

    " @@ -3326,6 +3372,10 @@ "validationMode":{ "shape":"ValidationMode", "documentation":"

    The validation mode for the code review. Valid values are SIMULATED and DISABLED.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for jobs started from this code review. Must be a positive number. If not set, jobs run to completion with no budget cap.

    " } }, "documentation":"

    Input for creating a new code review.

    " @@ -3373,6 +3423,10 @@ "validationMode":{ "shape":"ValidationMode", "documentation":"

    The validation mode for the code review.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours configured for jobs started from this code review. Null if no budget cap is set.

    " } }, "documentation":"

    Output for the CreateCodeReview operation.

    " @@ -3504,6 +3558,10 @@ "disableManagedSkills":{ "shape":"SkillTypeList", "documentation":"

    A list of managed skills to disable for this pentest. Valid values include FINDING_PERSONALIZATION and LOGIN_OPTIMIZATION.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for jobs started from this pentest. Must be a positive number. If not set, jobs run to completion with no budget cap.

    " } }, "documentation":"

    Input for creating a new pentest.

    " @@ -4481,6 +4539,10 @@ "PRIVATE_VPC" ] }, + "Double":{ + "type":"double", + "box":true + }, "Endpoint":{ "type":"structure", "members":{ @@ -4639,6 +4701,14 @@ "shape":"String", "documentation":"

    The rationale provided by the alignment agent explaining how the finding was adjusted based on customer preferences.

    " }, + "revalidationJobIds":{ + "shape":"StringList", + "documentation":"

    The list of pentest job identifiers for revalidation jobs that retested this finding.

    " + }, + "originalFindingId":{ + "shape":"String", + "documentation":"

    The identifier of the original finding that this revalidation finding was produced from.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the finding was created, in UTC format.

    " @@ -5278,6 +5348,10 @@ "providerResourceId":{ "shape":"String", "documentation":"

    The provider-specific resource identifier for the repository.

    " + }, + "branch":{ + "shape":"String", + "documentation":"

    An optional override for the repository branch.

    " } }, "documentation":"

    Represents a code repository that is integrated with the service through a third-party provider.

    " @@ -5460,6 +5534,14 @@ "COMPLETED" ] }, + "JobType":{ + "type":"string", + "documentation":"

    The type of pentest job execution.

    ", + "enum":[ + "FULL", + "REVALIDATION" + ] + }, "KmsKeyId":{ "type":"string", "documentation":"

    Identifier of a KMS key. Can be a key ID, key ARN, alias name, or alias ARN.

    " @@ -6583,6 +6665,10 @@ "shape":"SkillTypeList", "documentation":"

    A list of managed skills to disable for this pentest. Valid values include FINDING_PERSONALIZATION and LOGIN_OPTIMIZATION.

    " }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for jobs started from this pentest. If a job reaches the configured limit, it is gracefully stopped. If not set, jobs run to completion with no budget cap.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the pentest was created, in UTC format.

    " @@ -6681,6 +6767,10 @@ "shape":"IntegratedRepositoryList", "documentation":"

    The list of integrated repositories associated with the pentest job.

    " }, + "trustedCaCertificates":{ + "shape":"TrustedCaCertificateList", + "documentation":"

    The trust anchors used to validate target endpoint TLS certificates during the pentest job.

    " + }, "codeRemediationStrategy":{ "shape":"CodeRemediationStrategy", "documentation":"

    The code remediation strategy for the pentest job.

    " @@ -6693,6 +6783,18 @@ "shape":"SkillTypeList", "documentation":"

    A list of managed skills disabled for this pentest job. Valid values include FINDING_PERSONALIZATION and LOGIN_OPTIMIZATION.

    " }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours allowed for this pentest job. If the cumulative task hours reach this limit, the job is gracefully stopped.

    " + }, + "jobType":{ + "shape":"JobType", + "documentation":"

    The type of the pentest job. Valid values are FULL and REVALIDATION.

    " + }, + "selectedFindingIds":{ + "shape":"StringList", + "documentation":"

    The list of finding identifiers selected for revalidation. Present only when jobType is REVALIDATION.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the pentest job was created, in UTC format.

    " @@ -7305,6 +7407,10 @@ "type":"string", "documentation":"

    Sensitive email address.

    " }, + "SensitiveEmailAddress":{ + "type":"string", + "sensitive":true + }, "ServiceManagedInput":{ "type":"structure", "required":[ @@ -7501,6 +7607,14 @@ "pentestId":{ "shape":"String", "documentation":"

    The unique identifier of the pentest to start a job for.

    " + }, + "jobType":{ + "shape":"JobType", + "documentation":"

    The type of pentest job to start. Valid values are FULL and REVALIDATION. When set to REVALIDATION, the selectedFindingIds parameter is required.

    " + }, + "selectedFindingIds":{ + "shape":"StringList", + "documentation":"

    The list of finding identifiers to revalidate. Required when jobType is REVALIDATION. Each finding must belong to the same agent space and pentest.

    " } }, "documentation":"

    Input for starting the execution of a pentest.

    " @@ -7929,6 +8043,10 @@ "shape":"LogLocation", "documentation":"

    The location of the task execution logs.

    " }, + "taskHours":{ + "shape":"Double", + "documentation":"

    The number of active work hours consumed by the task during execution.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the task was created, in UTC format.

    " @@ -7991,6 +8109,10 @@ "shape":"TaskExecutionStatus", "documentation":"

    The current execution status of the task.

    " }, + "taskHours":{ + "shape":"Double", + "documentation":"

    The number of active work hours consumed by the task during execution.

    " + }, "createdAt":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The date and time the task was created, in UTC format.

    " @@ -8563,6 +8685,22 @@ }, "exception":true }, + "TrustedCaCertificate":{ + "type":"structure", + "required":["source"], + "members":{ + "source":{ + "shape":"CaCertificateSource", + "documentation":"

    The source that AWS Security Agent reads the certificate from.

    " + } + }, + "documentation":"

    A trust anchor used when validating a target endpoint's TLS certificate.

    ", + "sensitive":true + }, + "TrustedCaCertificateList":{ + "type":"list", + "member":{"shape":"TrustedCaCertificate"} + }, "UntagResourceInput":{ "type":"structure", "required":[ @@ -8729,6 +8867,10 @@ "validationMode":{ "shape":"ValidationMode", "documentation":"

    The updated validation mode for the code review. Valid values are SIMULATED and DISABLED.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The updated maximum number of billable task hours allowed for jobs started from this code review.

    " } }, "documentation":"

    Input for updating an existing code review.

    " @@ -8776,6 +8918,10 @@ "validationMode":{ "shape":"ValidationMode", "documentation":"

    The validation mode for the code review.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The maximum number of billable task hours configured for jobs started from this code review. Null if no budget cap is set.

    " } }, "documentation":"

    Output for the UpdateCodeReview operation.

    " @@ -8915,6 +9061,10 @@ "disableManagedSkills":{ "shape":"SkillTypeList", "documentation":"

    The updated list of managed skills to disable for this pentest. Valid values include FINDING_PERSONALIZATION and LOGIN_OPTIMIZATION.

    " + }, + "maxTaskHours":{ + "shape":"Double", + "documentation":"

    The updated maximum number of billable task hours allowed for jobs started from this pentest.

    " } }, "documentation":"

    Input for updating an existing pentest.

    " diff --git a/services/securityhub/pom.xml b/services/securityhub/pom.xml index b2ee263ac4e2..037cc74706a7 100644 --- a/services/securityhub/pom.xml +++ b/services/securityhub/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT securityhub AWS Java SDK :: Services :: SecurityHub diff --git a/services/securityhub/src/main/resources/codegen-resources/customization.config b/services/securityhub/src/main/resources/codegen-resources/customization.config index fdcbc9df329a..d0e45589b9cf 100644 --- a/services/securityhub/src/main/resources/codegen-resources/customization.config +++ b/services/securityhub/src/main/resources/codegen-resources/customization.config @@ -12,6 +12,5 @@ "excludedSimpleMethods": [ "getEnabledStandards", "getInsights" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/securityhub/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/securityhub/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b7310422aa89 --- /dev/null +++ b/services/securityhub/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityhub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityhub-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityhub.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securityhub.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/securityhub/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/securityhub/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index bfbc3fc6775b..000000000000 --- a/services/securityhub/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securityhub-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securityhub-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securityhub.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://securityhub.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/securityhub/src/main/resources/codegen-resources/paginators-1.json b/services/securityhub/src/main/resources/codegen-resources/paginators-1.json index 7b22906c0a95..1aa2999952bd 100644 --- a/services/securityhub/src/main/resources/codegen-resources/paginators-1.json +++ b/services/securityhub/src/main/resources/codegen-resources/paginators-1.json @@ -114,6 +114,12 @@ "limit_key": "MaxResults", "result_key": "FindingAggregators" }, + "ListFreeTrialStatusesV2": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "AccountFreeTrialStatuses" + }, "ListInvitations": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/securityhub/src/main/resources/codegen-resources/service-2.json b/services/securityhub/src/main/resources/codegen-resources/service-2.json index 8705fdf7df8a..f47aeff83c6d 100644 --- a/services/securityhub/src/main/resources/codegen-resources/service-2.json +++ b/services/securityhub/src/main/resources/codegen-resources/service-2.json @@ -359,7 +359,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Creates a cloud service provider management (CSPM) connector in Security Hub CSPM. A connector establishes a connection between Security Hub CSPM and a third-party cloud provider, enabling Security Hub CSPM to ingest security findings and resource data from the connected environment.

    " + "documentation":"

    Creates a connector to a third-party cloud provider in Security Hub CSPM. A connector establishes a connection between Security Hub CSPM and a third-party cloud provider, enabling Security Hub CSPM to ingest security findings and resource data from the connected environment.

    " }, "CreateConnectorV2":{ "name":"CreateConnectorV2", @@ -1380,7 +1380,7 @@ {"shape":"OrganizationalUnitNotFoundException"}, {"shape":"OrganizationNotFoundException"} ], - "documentation":"

    Retrieves statistical information about Amazon Web Services resources and their associated security findings.

    You can use the Scopes parameter to define the data boundary for the query. Currently, Scopes supports AwsOrganizations, which lets you aggregate resources from your entire organization or from specific organizational units. Only the delegated administrator account can use Scopes.

    " + "documentation":"

    Retrieves statistical information about Amazon Web Services resources and their associated security findings.

    You can use the Scopes parameter to define the data boundary for the query. Currently, Scopes supports AwsOrganizations, which lets you aggregate resources from your entire organization or from specific organizational units. Only the delegated administrator account can use Scopes.

    If you set GroupByField to ResourceSubCategory, ResourceInfo.AIDetails.HostResourceType, or ResourceInfo.AIDetails.CanonicalId, you must include a ResourceCategory string filter with comparison set to EQUALS and value AI/ML in the corresponding ResourceGroupByRule.

    " }, "GetResourcesTrendsV2":{ "name":"GetResourcesTrendsV2", @@ -1416,7 +1416,7 @@ {"shape":"OrganizationalUnitNotFoundException"}, {"shape":"OrganizationNotFoundException"} ], - "documentation":"

    Returns a list of resources.

    You can use the Scopes parameter to define the data boundary for the query. Currently, Scopes supports AwsOrganizations, which lets you retrieve resources from your entire organization or from specific organizational units. Only the delegated administrator account can use Scopes.

    You can use the Filters parameter to refine results based on resource attributes. You can use Scopes and Filters independently or together. When both are provided, Scopes narrows the data set first, and then Filters refines results within that scoped data set.

    " + "documentation":"

    Returns a list of resources.

    You can use the Scopes parameter to define the data boundary for the query. Currently, Scopes supports AwsOrganizations, which lets you retrieve resources from your entire organization or from specific organizational units. Only the delegated administrator account can use Scopes.

    You can use the Filters parameter to refine results based on resource attributes. You can use Scopes and Filters independently or together. When both are provided, Scopes narrows the data set first, and then Filters refines results within that scoped data set.

    For AI/ML resources, the response includes the ResourceSubCategory field. For self-hosted AI resources and their host resources, the response also includes ResourceInfo with AI-specific details. Self-hosted AI resources use a ResourceType with the SelfHosted::AI:: prefix, such as SelfHosted::AI::Model, SelfHosted::AI::Agent, SelfHosted::AI::InferenceEndpoint, and SelfHosted::AI::ExternalEndpoint.

    If you filter by ResourceSubCategory, you must also include a ResourceCategory string filter with comparison set to EQUALS and value AI/ML in the same request.

    " }, "GetSecurityControlDefinition":{ "name":"GetSecurityControlDefinition", @@ -1608,6 +1608,23 @@ ], "documentation":"

    If cross-Region aggregation is enabled, then ListFindingAggregators returns the Amazon Resource Name (ARN) of the finding aggregator. You can run this operation from any Amazon Web Services Region.

    " }, + "ListFreeTrialStatusesV2":{ + "name":"ListFreeTrialStatusesV2", + "http":{ + "method":"POST", + "requestUri":"/freetrial/statusv2/list" + }, + "input":{"shape":"ListFreeTrialStatusesV2Request"}, + "output":{"shape":"ListFreeTrialStatusesV2Response"}, + "errors":[ + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists the free trial status of Security Hub features. A delegated Security Hub administrator can list the status for accounts in its organization. Any other account can list the status only for itself. Free trial status remains available after a feature is disabled.

    " + }, "ListInvitations":{ "name":"ListInvitations", "http":{ @@ -2025,6 +2042,56 @@ } }, "shapes":{ + "AIDetails":{ + "type":"structure", + "members":{ + "HostResourceGuid":{ + "shape":"NonEmptyString", + "documentation":"

    The identifier of the host resource that hosts the self-hosted AI resource. Present only on self-hosted AI resources.

    " + }, + "HostResourceType":{ + "shape":"NonEmptyString", + "documentation":"

    The ResourceType of the host resource that hosts the self-hosted AI resource, such as AWS::EC2::Instance. Present only on self-hosted AI resources.

    " + }, + "CanonicalId":{ + "shape":"NonEmptyString", + "documentation":"

    The canonical identifier for the AI resource, independent of where it is deployed. Multiple occurrences of the same resource on different hosts share the same CanonicalId. For model resources, the value follows the format model/<purl>, such as model/pkg:huggingface/meta-llama/llama-3-8b. Present only on self-hosted AI resources.

    " + }, + "SelfHostedAIModelResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory Model detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIAgentResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory Agent detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIModelServingResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory ModelServing detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIExternalEndpointResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory ExternalEndpoint detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIDevelopmentResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory Development detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIAgentFrameworkResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory AgentFramework detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedAIAgentToolsAndIdentityResourceCount":{ + "shape":"Integer", + "documentation":"

    The number of self-hosted AI resources of ResourceSubCategory AgentToolsAndIdentity detected on the host resource. Present only on host resources.

    " + }, + "SelfHostedTotalAIResourceCount":{ + "shape":"Integer", + "documentation":"

    The total number of all self-hosted AI resources detected on the host resource. Present only on host resources.

    " + } + }, + "documentation":"

    Contains information about self-hosted AI resources and their host resources. The fields that are present depend on the role of the resource.

    On a self-hosted AI resource (a resource with a SelfHosted::AI:: resource type, such as SelfHosted::AI::Model or SelfHosted::AI::Agent), the HostResourceGuid and HostResourceType fields link the resource to its host. The CanonicalId field identifies what the resource is, enabling aggregation of identical resources across multiple hosts.

    On a host resource (such as an Amazon EC2 instance), the SelfHostedAI*ResourceCount fields contain the count for each ResourceSubCategory and the total count of self-hosted AI resources detected on the host.

    " + }, "AcceptAdministratorInvitationRequest":{ "type":"structure", "required":[ @@ -2098,6 +2165,34 @@ "max":50, "min":1 }, + "AccountFreeTrialStatus":{ + "type":"structure", + "required":[ + "AccountId", + "EvaluatedAt", + "FreeTrialStatuses" + ], + "members":{ + "AccountId":{ + "shape":"FreeTrialAccountId", + "documentation":"

    The Amazon Web Services account identifier that the free trial statuses apply to.

    " + }, + "EvaluatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time at which Security Hub evaluated the free trial statuses for this account. Every status in FreeTrialStatuses reflects this point in time.

    " + }, + "FreeTrialStatuses":{ + "shape":"FreeTrialStatusList", + "documentation":"

    An array of free trial statuses, one for each feature that has a free trial period for the account. The array is empty if the account has no free trial to report.

    " + } + }, + "documentation":"

    The free trial status of each Security Hub feature for an account.

    " + }, + "AccountFreeTrialStatusList":{ + "type":"list", + "member":{"shape":"AccountFreeTrialStatus"}, + "max":100 + }, "AccountId":{"type":"string"}, "AccountIdList":{ "type":"list", @@ -16278,7 +16373,7 @@ "members":{ "AWSConfigConnectorArn":{ "shape":"NonEmptyString", - "documentation":"

    The ARN of the AWS Config connector used to establish the connection to Azure.

    " + "documentation":"

    The ARN of the multi-cloud configuration connector used to establish the connection to Azure.

    " }, "ScopeConfiguration":{ "shape":"AzureScopeConfiguration", @@ -16301,7 +16396,7 @@ "members":{ "AWSConfigConnectorArn":{ "shape":"NonEmptyString", - "documentation":"

    The ARN of the AWS Config connector used to establish the connection to Azure.

    " + "documentation":"

    The ARN of the multi-cloud configuration connector used to establish the connection to Azure.

    " }, "ScopeConfiguration":{ "shape":"AzureScopeConfiguration", @@ -18700,6 +18795,13 @@ "type":"structure", "members":{} }, + "DiscoveryType":{ + "type":"string", + "enum":[ + "Managed", + "SelfHosted" + ] + }, "DnsRequestAction":{ "type":"structure", "members":{ @@ -19252,6 +19354,69 @@ "type":"list", "member":{"shape":"FirewallPolicyStatelessRuleGroupReferencesDetails"} }, + "FreeTrialAccountId":{ + "type":"string", + "pattern":"^[0-9]{12}$" + }, + "FreeTrialAccountIdList":{ + "type":"list", + "member":{"shape":"FreeTrialAccountId"}, + "max":50, + "min":1 + }, + "FreeTrialStatus":{ + "type":"structure", + "required":[ + "FeatureType", + "Status", + "StartedAt", + "ExpiresAt" + ], + "members":{ + "FeatureType":{ + "shape":"FreeTrialType", + "documentation":"

    The feature that the free trial period applies to. Valid values:

    • SECURITY_HUB_V2 specifies Security Hub.

    • SECURITY_HUB_V2_MULTI_CLOUD_AZURE specifies Security Hub coverage for Microsoft Azure resources.

    " + }, + "Status":{ + "shape":"FreeTrialStatusValue", + "documentation":"

    Whether the free trial period is currently active. Valid values:

    • ACTIVE specifies that the free trial period is ongoing.

    • INACTIVE specifies that the free trial period has ended, or that it never started.

    To determine whether a trial has expired, compare ExpiresAt to the current time.

    " + }, + "StartedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time at which the free trial period began.

    " + }, + "ExpiresAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time at which the free trial period ends.

    " + } + }, + "documentation":"

    The free trial period for a Security Hub feature, and whether the trial is currently active.

    " + }, + "FreeTrialStatusList":{ + "type":"list", + "member":{"shape":"FreeTrialStatus"}, + "max":50 + }, + "FreeTrialStatusValue":{ + "type":"string", + "enum":[ + "ACTIVE", + "INACTIVE" + ] + }, + "FreeTrialStatusValueList":{ + "type":"list", + "member":{"shape":"FreeTrialStatusValue"}, + "max":10, + "min":1 + }, + "FreeTrialType":{ + "type":"string", + "enum":[ + "SECURITY_HUB_V2", + "SECURITY_HUB_V2_MULTI_CLOUD_AZURE" + ] + }, "GenerateRecommendedPolicyV2Request":{ "type":"structure", "required":["MetadataUid"], @@ -21072,6 +21237,41 @@ } } }, + "ListFreeTrialStatusesV2Request":{ + "type":"structure", + "members":{ + "AccountIds":{ + "shape":"FreeTrialAccountIdList", + "documentation":"

    The Amazon Web Services account identifiers to list free trial status for. You can specify accounts other than your own only if you are a delegated Security Hub administrator.

    " + }, + "Statuses":{ + "shape":"FreeTrialStatusValueList", + "documentation":"

    The free trial statuses to filter the results by. Valid values:

    • ACTIVE returns only features with an ongoing free trial period.

    • INACTIVE returns only features whose free trial period has ended, or that never started.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return. If you don't specify a value, Security Hub returns up to 100 results.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token to request the next page of results.

    " + } + } + }, + "ListFreeTrialStatusesV2Response":{ + "type":"structure", + "required":["AccountFreeTrialStatuses"], + "members":{ + "AccountFreeTrialStatuses":{ + "shape":"AccountFreeTrialStatusList", + "documentation":"

    An array of free trial statuses, one for each account in scope.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token to use to request the next page of results. If there are no additional results, this value is null.

    " + } + } + }, "ListInvitationsRequest":{ "type":"structure", "members":{ @@ -23285,7 +23485,11 @@ "ResourceCategory", "ResourceType", "ResourceName", - "FindingsSummary.FindingType" + "FindingsSummary.FindingType", + "ResourceSubCategory", + "DiscoveryType", + "ResourceInfo.AIDetails.HostResourceType", + "ResourceInfo.AIDetails.CanonicalId" ] }, "ResourceGroupByRule":{ @@ -23317,6 +23521,16 @@ "error":{"httpStatusCode":400}, "exception":true }, + "ResourceInfo":{ + "type":"structure", + "members":{ + "AIDetails":{ + "shape":"AIDetails", + "documentation":"

    Details that are specific to self-hosted AI resources and their host resources.

    " + } + }, + "documentation":"

    Additional details about a resource that are specific to its category. For AI/ML resources and their host resources, this structure contains AIDetails.

    " + }, "ResourceList":{ "type":"list", "member":{"shape":"Resource"} @@ -23447,6 +23661,18 @@ "ResourceConfig":{ "shape":"ResourceConfig", "documentation":"

    The configuration details of a resource.

    " + }, + "ResourceSubCategory":{ + "shape":"ResourceSubCategory", + "documentation":"

    The AI/ML sub-grouping of the resource. Present only when ResourceCategory is AI/ML.

    " + }, + "DiscoveryType":{ + "shape":"DiscoveryType", + "documentation":"

    Specifies how the resource was discovered. If the value is Managed, the resource is natively provided by a cloud service provider. If the value is SelfHosted, the resource is hosted on customer-managed infrastructure, such as a compute instance or container image.

    " + }, + "ResourceInfo":{ + "shape":"ResourceInfo", + "documentation":"

    Additional resource-type-specific details. For self-hosted AI resources and their host resources, contains an AIDetails structure.

    " } }, "documentation":"

    Provides comprehensive details about an Amazon Web Services resource and its associated security findings.

    " @@ -23499,6 +23725,22 @@ }, "documentation":"

    A comprehensive distribution of security findings by severity level for Amazon Web Services resources.

    " }, + "ResourceSubCategory":{ + "type":"string", + "enum":[ + "Model", + "ModelServing", + "Agent", + "AgentFramework", + "AgentToolsAndIdentity", + "SafetyAndGuardrail", + "KnowledgeAndData", + "OrchestrationAndPipeline", + "ExternalEndpoint", + "Development", + "Other" + ] + }, "ResourceTag":{ "type":"structure", "required":[ @@ -23636,7 +23878,15 @@ "FindingsSummary.Severities.Medium", "FindingsSummary.Severities.Low", "FindingsSummary.Severities.Informational", - "FindingsSummary.Severities.Unknown" + "FindingsSummary.Severities.Unknown", + "ResourceInfo.AIDetails.SelfHostedAIModelResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIAgentResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIModelServingResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIExternalEndpointResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIDevelopmentResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIAgentFrameworkResourceCount", + "ResourceInfo.AIDetails.SelfHostedAIAgentToolsAndIdentityResourceCount", + "ResourceInfo.AIDetails.SelfHostedTotalAIResourceCount" ] }, "ResourcesNumberFilter":{ @@ -23671,7 +23921,12 @@ "ResourceType", "ResourceName", "FindingsSummary.FindingType", - "FindingsSummary.ProductName" + "FindingsSummary.ProductName", + "ResourceSubCategory", + "DiscoveryType", + "ResourceInfo.AIDetails.HostResourceGuid", + "ResourceInfo.AIDetails.HostResourceType", + "ResourceInfo.AIDetails.CanonicalId" ] }, "ResourcesStringFilter":{ diff --git a/services/securityir/pom.xml b/services/securityir/pom.xml index 8d5d8ce78fc5..00c6c9802dcf 100644 --- a/services/securityir/pom.xml +++ b/services/securityir/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT securityir AWS Java SDK :: Services :: Security IR diff --git a/services/securityir/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/securityir/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e7ca1def7cd5 --- /dev/null +++ b/services/securityir/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://security-ir-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://security-ir.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/securityir/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/securityir/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2a1d11d8f2ed..000000000000 --- a/services/securityir/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://security-ir-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://security-ir.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/securitylake/pom.xml b/services/securitylake/pom.xml index 605fab5470b6..34e2f4d691e6 100644 --- a/services/securitylake/pom.xml +++ b/services/securitylake/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT securitylake AWS Java SDK :: Services :: Security Lake diff --git a/services/securitylake/src/main/resources/codegen-resources/customization.config b/services/securitylake/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/securitylake/src/main/resources/codegen-resources/customization.config +++ b/services/securitylake/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/securitylake/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/securitylake/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..77e344299021 --- /dev/null +++ b/services/securitylake/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securitylake-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securitylake-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securitylake.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://securitylake.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/securitylake/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/securitylake/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6a02dbe1f29b..000000000000 --- a/services/securitylake/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securitylake-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securitylake-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securitylake.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://securitylake.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/serverlessapplicationrepository/pom.xml b/services/serverlessapplicationrepository/pom.xml index 62fef9f4d548..296a2ad35963 100644 --- a/services/serverlessapplicationrepository/pom.xml +++ b/services/serverlessapplicationrepository/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 serverlessapplicationrepository diff --git a/services/serverlessapplicationrepository/src/main/resources/codegen-resources/customization.config b/services/serverlessapplicationrepository/src/main/resources/codegen-resources/customization.config index f75675b7698b..fe8bc698abde 100644 --- a/services/serverlessapplicationrepository/src/main/resources/codegen-resources/customization.config +++ b/services/serverlessapplicationrepository/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ ], "verifiedSimpleMethods": [ "listApplications" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..def44ad52292 --- /dev/null +++ b/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://serverlessrepo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://serverlessrepo.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://serverlessrepo-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://serverlessrepo.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://serverlessrepo.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 86da821df8d7..000000000000 --- a/services/serverlessapplicationrepository/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://serverlessrepo-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://serverlessrepo.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://serverlessrepo-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://serverlessrepo.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://serverlessrepo.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/servicecatalog/pom.xml b/services/servicecatalog/pom.xml index 908e696b1780..218999493d8f 100644 --- a/services/servicecatalog/pom.xml +++ b/services/servicecatalog/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT servicecatalog AWS Java SDK :: Services :: AWS Service Catalog diff --git a/services/servicecatalog/src/main/resources/codegen-resources/customization.config b/services/servicecatalog/src/main/resources/codegen-resources/customization.config index 7f77782fc298..0d56acb0896e 100644 --- a/services/servicecatalog/src/main/resources/codegen-resources/customization.config +++ b/services/servicecatalog/src/main/resources/codegen-resources/customization.config @@ -11,6 +11,5 @@ "listTagOptions", "searchProvisionedProducts", "getAWSOrganizationsAccessStatus" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/servicecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/servicecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c8366bd27e00 --- /dev/null +++ b/services/servicecatalog/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/servicecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/servicecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3c45049a7f93..000000000000 --- a/services/servicecatalog/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/servicecatalogappregistry/pom.xml b/services/servicecatalogappregistry/pom.xml index daf7789196b6..0f801aadb736 100644 --- a/services/servicecatalogappregistry/pom.xml +++ b/services/servicecatalogappregistry/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT servicecatalogappregistry AWS Java SDK :: Services :: Service Catalog App Registry diff --git a/services/servicecatalogappregistry/src/main/resources/codegen-resources/customization.config b/services/servicecatalogappregistry/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/servicecatalogappregistry/src/main/resources/codegen-resources/customization.config +++ b/services/servicecatalogappregistry/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4cb35f07d849 --- /dev/null +++ b/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-appregistry-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-appregistry.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-appregistry-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-appregistry.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicecatalog-appregistry.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d21f652b5830..000000000000 --- a/services/servicecatalogappregistry/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-appregistry-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://servicecatalog-appregistry.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-appregistry-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-appregistry.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicecatalog-appregistry.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/servicediscovery/pom.xml b/services/servicediscovery/pom.xml index 35b9f82d34fd..1d3813c238b2 100644 --- a/services/servicediscovery/pom.xml +++ b/services/servicediscovery/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 servicediscovery diff --git a/services/servicediscovery/src/main/resources/codegen-resources/customization.config b/services/servicediscovery/src/main/resources/codegen-resources/customization.config index e62d340b16a3..5315549520de 100644 --- a/services/servicediscovery/src/main/resources/codegen-resources/customization.config +++ b/services/servicediscovery/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ "listOperations", "listServices" ], - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/servicediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/servicediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7e2e89994eae --- /dev/null +++ b/services/servicediscovery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicediscovery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicediscovery-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicediscovery.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicediscovery.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/servicediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/servicediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8fa166a55eb6..000000000000 --- a/services/servicediscovery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,389 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicediscovery-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicediscovery-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://servicediscovery.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-cn", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://servicediscovery.{Region}.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://servicediscovery.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicediscovery.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicediscovery.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/servicediscovery/src/main/resources/codegen-resources/endpoint-tests.json b/services/servicediscovery/src/main/resources/codegen-resources/endpoint-tests.json index 1d0971efc015..aa4711fbe019 100644 --- a/services/servicediscovery/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/servicediscovery/src/main/resources/codegen-resources/endpoint-tests.json @@ -1,458 +1,283 @@ { "testCases": [ { - "documentation": "For region af-south-1 with FIPS disabled and DualStack disabled", + "documentation": "For custom endpoint with region not set and fips disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.af-south-1.amazonaws.com" - } - }, - "params": { - "Region": "af-south-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-east-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.ap-east-1.amazonaws.com" - } - }, - "params": { - "Region": "ap-east-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-northeast-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.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://servicediscovery.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://servicediscovery.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://servicediscovery.ap-southeast-1.amazonaws.com" + "url": "https://example.com" } }, "params": { - "Region": "ap-southeast-1", - "UseFIPS": false, - "UseDualStack": false + "Endpoint": "https://example.com", + "UseFIPS": false } }, { - "documentation": "For region ap-southeast-2 with FIPS disabled and DualStack disabled", + "documentation": "For custom endpoint with fips enabled", "expect": { - "endpoint": { - "url": "https://servicediscovery.ap-southeast-2.amazonaws.com" - } + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" }, "params": { - "Region": "ap-southeast-2", - "UseFIPS": false, - "UseDualStack": false + "Endpoint": "https://example.com", + "UseFIPS": true } }, { - "documentation": "For region ca-central-1 with FIPS disabled and DualStack disabled", + "documentation": "For custom endpoint with fips disabled and dualstack enabled", "expect": { - "endpoint": { - "url": "https://servicediscovery.ca-central-1.amazonaws.com" - } + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" }, "params": { - "Region": "ca-central-1", + "Endpoint": "https://example.com", "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region ca-central-1 with FIPS enabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.ca-central-1.amazonaws.com" + "url": "https://servicediscovery-fips.us-east-1.api.aws" } }, "params": { - "Region": "ca-central-1", + "Region": "us-east-1", "UseFIPS": true, - "UseDualStack": false - } - }, - { - "documentation": "For region eu-central-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.eu-central-1.amazonaws.com" - } - }, - "params": { - "Region": "eu-central-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region eu-north-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.eu-north-1.amazonaws.com" - } - }, - "params": { - "Region": "eu-north-1", - "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region eu-south-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.eu-south-1.amazonaws.com" + "url": "https://servicediscovery-fips.us-east-1.amazonaws.com" } }, "params": { - "Region": "eu-south-1", - "UseFIPS": false, + "Region": "us-east-1", + "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region eu-west-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery.eu-west-1.amazonaws.com" + "url": "https://servicediscovery.us-east-1.api.aws" } }, "params": { - "Region": "eu-west-1", + "Region": "us-east-1", "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region eu-west-2 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.eu-west-2.amazonaws.com" + "url": "https://servicediscovery.us-east-1.amazonaws.com" } }, "params": { - "Region": "eu-west-2", + "Region": "us-east-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region eu-west-3 with FIPS disabled and DualStack disabled", + "documentation": "For region cn-northwest-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery.eu-west-3.amazonaws.com" + "url": "https://servicediscovery-fips.cn-northwest-1.api.amazonwebservices.com.cn" } }, "params": { - "Region": "eu-west-3", - "UseFIPS": false, - "UseDualStack": false + "Region": "cn-northwest-1", + "UseFIPS": true, + "UseDualStack": true } }, { - "documentation": "For region me-south-1 with FIPS disabled and DualStack disabled", + "documentation": "For region cn-northwest-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.me-south-1.amazonaws.com" + "url": "https://servicediscovery-fips.cn-northwest-1.amazonaws.com.cn" } }, "params": { - "Region": "me-south-1", - "UseFIPS": false, + "Region": "cn-northwest-1", + "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region sa-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery.sa-east-1.amazonaws.com" + "url": "https://servicediscovery.cn-northwest-1.api.amazonwebservices.com.cn" } }, "params": { - "Region": "sa-east-1", + "Region": "cn-northwest-1", "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-east-1.amazonaws.com" + "url": "https://servicediscovery.cn-northwest-1.amazonaws.com.cn" } }, "params": { - "Region": "us-east-1", + "Region": "cn-northwest-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", + "documentation": "For region eusc-de-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.us-east-1.amazonaws.com" + "url": "https://servicediscovery-fips.eusc-de-east-1.amazonaws.eu" } }, "params": { - "Region": "us-east-1", + "Region": "eusc-de-east-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region us-east-2 with FIPS disabled and DualStack disabled", + "documentation": "For region eusc-de-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-east-2.amazonaws.com" + "url": "https://servicediscovery.eusc-de-east-1.amazonaws.eu" } }, "params": { - "Region": "us-east-2", + "Region": "eusc-de-east-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-east-2 with FIPS enabled and DualStack disabled", + "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.us-east-2.amazonaws.com" + "url": "https://servicediscovery-fips.us-iso-east-1.c2s.ic.gov" } }, "params": { - "Region": "us-east-2", + "Region": "us-iso-east-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region us-west-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-west-1.amazonaws.com" + "url": "https://servicediscovery.us-iso-east-1.c2s.ic.gov" } }, "params": { - "Region": "us-west-1", + "Region": "us-iso-east-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-west-1 with FIPS enabled and DualStack disabled", + "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.us-west-1.amazonaws.com" + "url": "https://servicediscovery-fips.us-isob-east-1.sc2s.sgov.gov" } }, "params": { - "Region": "us-west-1", + "Region": "us-isob-east-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region us-west-2 with FIPS disabled and DualStack disabled", + "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-west-2.amazonaws.com" + "url": "https://servicediscovery.us-isob-east-1.sc2s.sgov.gov" } }, "params": { - "Region": "us-west-2", + "Region": "us-isob-east-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-west-2 with FIPS enabled and DualStack disabled", + "documentation": "For region eu-isoe-west-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.us-west-2.amazonaws.com" + "url": "https://servicediscovery-fips.eu-isoe-west-1.cloud.adc-e.uk" } }, "params": { - "Region": "us-west-2", + "Region": "eu-isoe-west-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery-fips.us-east-1.api.aws" - } - }, - "params": { - "Region": "us-east-1", - "UseFIPS": true, - "UseDualStack": true - } - }, - { - "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.us-east-1.amazonaws.com" - } - }, - "params": { - "Region": "us-east-1", - "UseFIPS": false, - "UseDualStack": true - } - }, - { - "documentation": "For region cn-north-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.cn-north-1.amazonaws.com.cn" - } - }, - "params": { - "Region": "cn-north-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region cn-northwest-1 with FIPS disabled and DualStack disabled", + "documentation": "For region eu-isoe-west-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.cn-northwest-1.amazonaws.com.cn" + "url": "https://servicediscovery.eu-isoe-west-1.cloud.adc-e.uk" } }, "params": { - "Region": "cn-northwest-1", + "Region": "eu-isoe-west-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region cn-north-1 with FIPS enabled and DualStack enabled", + "documentation": "For region us-isof-south-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.cn-north-1.api.amazonwebservices.com.cn" + "url": "https://servicediscovery-fips.us-isof-south-1.csp.hci.ic.gov" } }, "params": { - "Region": "cn-north-1", - "UseFIPS": true, - "UseDualStack": true - } - }, - { - "documentation": "For region cn-north-1 with FIPS enabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery-fips.cn-north-1.amazonaws.com.cn" - } - }, - "params": { - "Region": "cn-north-1", + "Region": "us-isof-south-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region cn-north-1 with FIPS disabled and DualStack enabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.cn-north-1.amazonaws.com.cn" - } - }, - "params": { - "Region": "cn-north-1", - "UseFIPS": false, - "UseDualStack": true - } - }, - { - "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-isof-south-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-gov-east-1.amazonaws.com" + "url": "https://servicediscovery.us-isof-south-1.csp.hci.ic.gov" } }, "params": { - "Region": "us-gov-east-1", + "Region": "us-isof-south-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack disabled", + "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery-fips.us-gov-east-1.amazonaws.com" - } - }, - "params": { - "Region": "us-gov-east-1", - "UseFIPS": true, - "UseDualStack": false - } - }, - { - "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.us-gov-west-1.amazonaws.com" + "url": "https://servicediscovery-fips.us-gov-west-1.api.aws" } }, "params": { "Region": "us-gov-west-1", - "UseFIPS": false, - "UseDualStack": false + "UseFIPS": true, + "UseDualStack": true } }, { @@ -469,134 +294,31 @@ } }, { - "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack enabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery-fips.us-gov-east-1.api.aws" - } - }, - "params": { - "Region": "us-gov-east-1", - "UseFIPS": true, - "UseDualStack": true - } - }, - { - "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack enabled", + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-gov-east-1.amazonaws.com" + "url": "https://servicediscovery.us-gov-west-1.api.aws" } }, "params": { - "Region": "us-gov-east-1", + "Region": "us-gov-west-1", "UseFIPS": false, "UseDualStack": true } }, { - "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery-fips.us-iso-east-1.c2s.ic.gov" - } - }, - "params": { - "Region": "us-iso-east-1", - "UseFIPS": true, - "UseDualStack": false - } - }, - { - "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery.us-iso-east-1.c2s.ic.gov" - } - }, - "params": { - "Region": "us-iso-east-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://servicediscovery-fips.us-isob-east-1.sc2s.sgov.gov" - } - }, - "params": { - "Region": "us-isob-east-1", - "UseFIPS": true, - "UseDualStack": false - } - }, - { - "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://servicediscovery.us-isob-east-1.sc2s.sgov.gov" + "url": "https://servicediscovery.us-gov-west-1.amazonaws.com" } }, "params": { - "Region": "us-isob-east-1", + "Region": "us-gov-west-1", "UseFIPS": false, "UseDualStack": false } }, - { - "documentation": "For custom endpoint with region set and fips disabled and dualstack disabled", - "expect": { - "endpoint": { - "url": "https://example.com" - } - }, - "params": { - "Region": "us-east-1", - "UseFIPS": false, - "UseDualStack": false, - "Endpoint": "https://example.com" - } - }, - { - "documentation": "For custom endpoint with region not set and fips disabled and dualstack disabled", - "expect": { - "endpoint": { - "url": "https://example.com" - } - }, - "params": { - "UseFIPS": false, - "UseDualStack": false, - "Endpoint": "https://example.com" - } - }, - { - "documentation": "For custom endpoint with fips enabled and dualstack disabled", - "expect": { - "error": "Invalid Configuration: FIPS and custom endpoint are not supported" - }, - "params": { - "Region": "us-east-1", - "UseFIPS": true, - "UseDualStack": false, - "Endpoint": "https://example.com" - } - }, - { - "documentation": "For custom endpoint with fips disabled and dualstack enabled", - "expect": { - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" - }, - "params": { - "Region": "us-east-1", - "UseFIPS": false, - "UseDualStack": true, - "Endpoint": "https://example.com" - } - }, { "documentation": "Missing region", "expect": { diff --git a/services/servicequotas/pom.xml b/services/servicequotas/pom.xml index c67459fad1cb..f054301d2e3f 100644 --- a/services/servicequotas/pom.xml +++ b/services/servicequotas/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT servicequotas AWS Java SDK :: Services :: Service Quotas diff --git a/services/servicequotas/src/main/resources/codegen-resources/customization.config b/services/servicequotas/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/servicequotas/src/main/resources/codegen-resources/customization.config +++ b/services/servicequotas/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/servicequotas/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/servicequotas/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..8804ee5ec58e --- /dev/null +++ b/services/servicequotas/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicequotas-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicequotas.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicequotas-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicequotas.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://servicequotas.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/servicequotas/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/servicequotas/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c565f41095c8..000000000000 --- a/services/servicequotas/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicequotas-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://servicequotas.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicequotas-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://servicequotas.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://servicequotas.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/servicequotas/src/main/resources/codegen-resources/service-2.json b/services/servicequotas/src/main/resources/codegen-resources/service-2.json index 83e2365aeaaf..43f031db27f2 100644 --- a/services/servicequotas/src/main/resources/codegen-resources/service-2.json +++ b/services/servicequotas/src/main/resources/codegen-resources/service-2.json @@ -162,6 +162,7 @@ {"shape":"NoSuchResourceException"}, {"shape":"IllegalArgumentException"}, {"shape":"AccessDeniedException"}, + {"shape":"InvalidPaginationTokenException"}, {"shape":"ServiceException"} ], "documentation":"

    Retrieves the quota utilization report for your Amazon Web Services account. This operation returns paginated results showing your quota usage across all Amazon Web Services services, sorted by utilization percentage in descending order (highest utilization first).

    You must first initiate a report using the StartQuotaUtilizationReport operation. The report generation process is asynchronous and may take several seconds to complete. Poll this operation periodically to check the status and retrieve results when the report is ready.

    Each report contains up to 1,000 quota records per page. Use the NextToken parameter to retrieve additional pages of results. Reports are automatically deleted after 15 minutes.

    " @@ -513,6 +514,14 @@ "documentation":"

    You do not have sufficient permission to perform this action.

    ", "exception":true }, + "AdjustableAtLevelEnum":{ + "type":"string", + "enum":[ + "ACCOUNT", + "PER_RESOURCE", + "ALL" + ] + }, "AmazonResourceName":{ "type":"string", "max":1011, @@ -1294,6 +1303,10 @@ "ContextId":{ "shape":"QuotaContextId", "documentation":"

    Specifies the resource, or resources, to which the quota applies. The value for this field is either an Amazon Resource Name (ARN) or *. If the value is an ARN, the quota value applies to that resource. If the value is *, then the quota value applies to all resources listed in the ContextScopeType field. The quota value applies to all resources for which you haven’t previously applied a quota value, and any new resources you create in your Amazon Web Services account.

    " + }, + "AdjustableAtLevel":{ + "shape":"AdjustableAtLevelEnum", + "documentation":"

    Specifies the level at which you can request an increase for this quota:

    • ACCOUNT – You can request an increase only at the account level.

    • PER_RESOURCE – You can request an increase only for an individual resource.

    • ALL – You can request an increase at either the account level or for an individual resource.

    " } }, "documentation":"

    A structure that describes the context for a resource-level quota. For resource-level quotas, such as Instances per OpenSearch Service Domain, you can apply the quota value at the resource-level for each OpenSearch Service Domain in your Amazon Web Services account. Together the attributes of this structure help you understand how the quota is implemented by Amazon Web Services and how you can manage it. For quotas such as Amazon OpenSearch Service Domains which can be managed at the account-level for each Amazon Web Services Region, the QuotaContext field is absent. See the attribute descriptions below to further understand how to use them.

    " diff --git a/services/ses/pom.xml b/services/ses/pom.xml index 2781aaf5bc1c..9afdbea2e805 100644 --- a/services/ses/pom.xml +++ b/services/ses/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ses AWS Java SDK :: Services :: Amazon SES diff --git a/services/ses/src/main/resources/codegen-resources/customization.config b/services/ses/src/main/resources/codegen-resources/customization.config index 0de5557533d5..00c337b5260d 100644 --- a/services/ses/src/main/resources/codegen-resources/customization.config +++ b/services/ses/src/main/resources/codegen-resources/customization.config @@ -15,8 +15,6 @@ ], "excludedSimpleMethods": [ "updateAccountSendingEnabled" - ], - - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ses/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ses/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..36f42a218754 --- /dev/null +++ b/services/ses/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ses/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ses/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7386f6b5cc61..000000000000 --- a/services/ses/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sesv2/pom.xml b/services/sesv2/pom.xml index 10bd6467a12f..18559184212b 100644 --- a/services/sesv2/pom.xml +++ b/services/sesv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sesv2 AWS Java SDK :: Services :: SESv2 diff --git a/services/sesv2/src/main/resources/codegen-resources/customization.config b/services/sesv2/src/main/resources/codegen-resources/customization.config index 3388694e6427..7ad0bbabcc1f 100644 --- a/services/sesv2/src/main/resources/codegen-resources/customization.config +++ b/services/sesv2/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "enableEndpointAuthSchemeParams": true } diff --git a/services/sesv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sesv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b22f512d6f10 --- /dev/null +++ b/services/sesv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,332 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "EndpointId": { + "required": false, + "documentation": "Operation parameter for EndpointId", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "EndpointId" + } + ] + }, + { + "fn": "isValidHostLabel", + "argv": [ + { + "ref": "EndpointId" + }, + true + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "ses", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoints.email.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "ses", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoints.email.us-gov.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "ses", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoints.email.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "ses", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{EndpointId}.endpoints.email.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingName": "ses", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS is not supported with multi-region endpoints", + "type": "error" + }, + { + "conditions": [], + "error": "EndpointId must be a valid host label", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 23, + "nodes": "/////wAAAAH/////AAAAAAAAAAMAAAAEAAAAAQAAAAUAAAAEAAAABAAAAA4F9eESAAAAAgAAABAAAAAGAAAABAAAAA4AAAAHAAAABQAAAAoAAAAIAAAABgAAAAkF9eERAAAABwX14RAF9eEDAAAABgAAAAwAAAALAAAACQX14Q4F9eEPAAAABwAAAA0F9eENAAAACQX14QwF9eENAAAABQX14QkAAAAPAAAABgX14QoF9eELAAAAAwAAABEF9eEIAAAABAAAABcAAAASAAAABQX14QcAAAATAAAABgAAABUAAAAUAAAACAX14QQF9eEGAAAABwAAABYF9eEDAAAACAX14QIF9eEFAAAABQX14QcF9eEB" +} \ No newline at end of file diff --git a/services/sesv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sesv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0697cd288213..000000000000 --- a/services/sesv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,504 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "EndpointId": { - "required": false, - "documentation": "Operation parameter for EndpointId", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "EndpointId" - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isValidHostLabel", - "argv": [ - { - "ref": "EndpointId" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "ses", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://{EndpointId}.endpoints.email.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "ses", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://{EndpointId}.endpoints.email.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingName": "ses", - "signingRegionSet": [ - "*" - ] - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: FIPS is not supported with multi-region endpoints", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "EndpointId must be a valid host label", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://email.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sesv2/src/main/resources/codegen-resources/endpoint-tests.json b/services/sesv2/src/main/resources/codegen-resources/endpoint-tests.json index 4e5aad9c0dcb..0cb0dc684ce8 100644 --- a/services/sesv2/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/sesv2/src/main/resources/codegen-resources/endpoint-tests.json @@ -696,6 +696,219 @@ "Region": "us-east-1", "Endpoint": "https://example.com" } + }, + { + "documentation": "Gov IPv4 only: us-gov-west-1 primary, dualstack and FIPS disabled", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.us-gov.amazonaws.com" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": false, + "Region": "us-gov-west-1" + } + }, + { + "documentation": "Gov IPv4 only: us-gov-east-1, dualstack and FIPS disabled (proves both gov regions resolve identically)", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.us-gov.amazonaws.com" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": false, + "Region": "us-gov-east-1" + } + }, + { + "documentation": "Gov dualstack: us-gov-west-1, dualstack enabled, FIPS disabled (no global. prefix; api.aws not global.api.aws)", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.us-gov.api.aws" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": true, + "UseFIPS": false, + "Region": "us-gov-west-1" + } + }, + { + "documentation": "Gov FIPS: us-gov-west-1, FIPS enabled, dualstack disabled — FIPS not supported with multi-region endpoints", + "expect": { + "error": "Invalid Configuration: FIPS is not supported with multi-region endpoints" + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": true, + "Region": "us-gov-west-1" + } + }, + { + "documentation": "Gov FIPS+dualstack: us-gov-west-1, both FIPS and dualstack enabled — FIPS check precedes dualstack branch selection", + "expect": { + "error": "Invalid Configuration: FIPS is not supported with multi-region endpoints" + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": true, + "UseFIPS": true, + "Region": "us-gov-west-1" + } + }, + { + "documentation": "Gov custom SDK endpoint: us-gov-west-1, EndpointId set, custom Endpoint — passes through unchanged with SigV4a", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://example.com" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": false, + "Region": "us-gov-west-1", + "Endpoint": "https://example.com" + } + }, + { + "documentation": "China IPv4 regression: cn-north-1, dualstack disabled — endpoint uses aws-cn dnsSuffix (amazonaws.com.cn)", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.amazonaws.com.cn" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": false, + "Region": "cn-north-1" + } + }, + { + "documentation": "China dualstack regression: cn-north-1, dualstack enabled — uses global. prefix with aws-cn dualStackDnsSuffix (api.amazonwebservices.com.cn)", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.global.api.amazonwebservices.com.cn" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": true, + "UseFIPS": false, + "Region": "cn-north-1" + } + }, + { + "documentation": "Gov custom SDK endpoint with FIPS: FIPS guard sits above the SDK passthrough, so error wins", + "expect": { + "error": "Invalid Configuration: FIPS is not supported with multi-region endpoints" + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": false, + "UseFIPS": true, + "Region": "us-gov-west-1", + "Endpoint": "https://example.com" + } + }, + { + "documentation": "Gov dualstack OSU (us-gov-east-1) matches PDT dualstack output (us-gov.api.aws, no global. prefix)", + "expect": { + "endpoint": { + "properties": { + "authSchemes": [ + { + "signingName": "ses", + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + } + ] + }, + "url": "https://abc123.456def.endpoints.email.us-gov.api.aws" + } + }, + "params": { + "EndpointId": "abc123.456def", + "UseDualStack": true, + "UseFIPS": false, + "Region": "us-gov-east-1" + } } ], "version": "1.0" diff --git a/services/sesv2/src/main/resources/codegen-resources/paginators-1.json b/services/sesv2/src/main/resources/codegen-resources/paginators-1.json index 7162a3a06d77..825816ba3ae7 100644 --- a/services/sesv2/src/main/resources/codegen-resources/paginators-1.json +++ b/services/sesv2/src/main/resources/codegen-resources/paginators-1.json @@ -45,6 +45,12 @@ "output_token": "NextToken", "limit_key": "PageSize" }, + "ListEmailIdentityCertificates": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "PageSize", + "result_key": "Certificates" + }, "ListEmailTemplates": { "input_token": "NextToken", "output_token": "NextToken", 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 5419ffd9c724..8c6485c7d681 100644 --- a/services/sesv2/src/main/resources/codegen-resources/service-2.json +++ b/services/sesv2/src/main/resources/codegen-resources/service-2.json @@ -15,6 +15,22 @@ "auth":["aws.auth#sigv4"] }, "operations":{ + "AssociateEmailIdentityCertificate":{ + "name":"AssociateEmailIdentityCertificate", + "http":{ + "method":"POST", + "requestUri":"/v2/email/identity/certificates" + }, + "input":{"shape":"AssociateEmailIdentityCertificateRequest"}, + "output":{"shape":"AssociateEmailIdentityCertificateResponse"}, + "errors":[ + {"shape":"NotFoundException"}, + {"shape":"AlreadyExistsException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"BadRequestException"} + ], + "documentation":"

    Associates an S/MIME certificate with an email identity. After the certificate is active, Amazon SES API v2 can add an S/MIME signature to messages that you send from the associated address when signing is enabled on the configuration set used to send the message.

    The certificate is an X.509 certificate that you manage in Certificate Manager (ACM). You identify it by its Amazon Resource Name (ARN).

    • If the email identity is a domain, you must specify a FromAddress that belongs to that domain or one of its subdomains. The certificate applies to messages sent from that address.

    • If the email identity is an email address, FromAddress is optional. If you specify it, it must exactly match the email identity.

    When the association is created, the certificate begins provisioning and its status is PROVISIONING. The status changes to ACTIVE when the certificate is ready to use for signing. Each email address can have only one certificate association. If an association already exists for the address, this operation returns an error, unless the existing association is in the DEPROVISIONING state.

    " + }, "BatchGetMetricData":{ "name":"BatchGetMetricData", "http":{ @@ -264,7 +280,7 @@ {"shape":"AlreadyExistsException"}, {"shape":"BadRequestException"} ], - "documentation":"

    Creates a multi-region endpoint (global-endpoint).

    The primary region is going to be the AWS-Region where the operation is executed. The secondary region has to be provided in request's parameters. From the data flow standpoint there is no difference between primary and secondary regions - sending traffic will be split equally between the two. The primary region is the region where the resource has been created and where it can be managed.

    " + "documentation":"

    Creates a multi-region endpoint (global-endpoint).

    The primary region is going to be the AWS-Region where the operation is executed. The secondary region has to be provided in request's parameters. From the data flow standpoint there is no difference between primary and secondary regions - sending traffic is divided between the two. The primary region is the region where the resource has been created and where it can be managed.

    " }, "CreateTenant":{ "name":"CreateTenant", @@ -498,6 +514,21 @@ ], "documentation":"

    Delete an association between a tenant and a resource.

    When you delete a tenant-resource association, the resource itself is not deleted, only its association with the specific tenant is removed. After removal, the resource will no longer be available for use with that tenant's email sending operations.

    " }, + "DisassociateEmailIdentityCertificate":{ + "name":"DisassociateEmailIdentityCertificate", + "http":{ + "method":"POST", + "requestUri":"/v2/email/identity/certificates/delete" + }, + "input":{"shape":"DisassociateEmailIdentityCertificateRequest"}, + "output":{"shape":"DisassociateEmailIdentityCertificateResponse"}, + "errors":[ + {"shape":"NotFoundException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"BadRequestException"} + ], + "documentation":"

    Removes the association between an S/MIME certificate and an email identity. After the association is removed, Amazon SES API v2 stops adding an S/MIME signature to messages sent from that address.

    If the email identity is a domain, specify the FromAddress whose certificate association you want to remove.

    This operation is idempotent. If the specified email identity exists but there's no matching certificate association, the operation succeeds without making any changes. Amazon SES API v2 returns a NotFoundException only when the specified email identity doesn't exist.

    " + }, "GetAccount":{ "name":"GetAccount", "http":{ @@ -986,6 +1017,21 @@ ], "documentation":"

    Returns a list of all of the email identities that are associated with your Amazon Web Services account. An identity can be either an email address or a domain. This operation returns identities that are verified as well as those that aren't. This operation returns identities that are associated with Amazon SES and Amazon Pinpoint.

    " }, + "ListEmailIdentityCertificates":{ + "name":"ListEmailIdentityCertificates", + "http":{ + "method":"POST", + "requestUri":"/v2/email/identity/certificates/list" + }, + "input":{"shape":"ListEmailIdentityCertificatesRequest"}, + "output":{"shape":"ListEmailIdentityCertificatesResponse"}, + "errors":[ + {"shape":"NotFoundException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"BadRequestException"} + ], + "documentation":"

    Lists the S/MIME certificates that are associated with the specified email identity. The results include certificates in all states, such as PROVISIONING, ACTIVE, INACTIVE, DEPROVISIONING, and FAILED.

    If a certificate has passed its expiration time, it's returned with a status of FAILED.

    We recommend using pagination to ensure that the operation returns quickly and successfully. When there are more results than fit in a single response, the response includes a NextToken value that you use in a subsequent call to retrieve the next set of results.

    " + }, "ListEmailTemplates":{ "name":"ListEmailTemplates", "http":{ @@ -1175,6 +1221,21 @@ ], "documentation":"

    Update your Amazon SES account details.

    " }, + "PutAccountPricingAttributes":{ + "name":"PutAccountPricingAttributes", + "http":{ + "method":"PUT", + "requestUri":"/v2/email/account/pricing-attributes" + }, + "input":{"shape":"PutAccountPricingAttributesRequest"}, + "output":{"shape":"PutAccountPricingAttributesResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Set the pricing plan for your Amazon SES account.

    " + }, "PutAccountSendingAttributes":{ "name":"PutAccountSendingAttributes", "http":{ @@ -1598,6 +1659,21 @@ ], "documentation":"

    Remove one or more tags (keys and values) from a specified resource.

    " }, + "UpdateConfigurationSet":{ + "name":"UpdateConfigurationSet", + "http":{ + "method":"POST", + "requestUri":"/v2/email/update-configuration-sets" + }, + "input":{"shape":"UpdateConfigurationSetRequest"}, + "output":{"shape":"UpdateConfigurationSetResponse"}, + "errors":[ + {"shape":"NotFoundException"}, + {"shape":"TooManyRequestsException"}, + {"shape":"BadRequestException"} + ], + "documentation":"

    Updates an existing configuration set.

    This operation performs a partial update. Only the attributes that you include in the request are updated; any omitted attribute is left unchanged.

    " + }, "UpdateConfigurationSetEventDestination":{ "name":"UpdateConfigurationSetEventDestination", "http":{ @@ -1801,6 +1877,33 @@ }, "documentation":"

    Used to associate a configuration set with a MailManager archive.

    " }, + "AssociateEmailIdentityCertificateRequest":{ + "type":"structure", + "required":[ + "EmailIdentity", + "CertificateArn" + ], + "members":{ + "EmailIdentity":{ + "shape":"Identity", + "documentation":"

    The email identity, either an email address or a domain, to associate the certificate with.

    " + }, + "FromAddress":{ + "shape":"EmailAddress", + "documentation":"

    The email address that the certificate applies to. This value is required when the email identity is a domain, and the address must belong to that domain or one of its subdomains. When the email identity is an email address, this value is optional. If you specify it, it must exactly match the email identity.

    " + }, + "CertificateArn":{ + "shape":"CertificateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Certificate Manager (ACM) certificate to associate with the email identity.

    " + } + }, + "documentation":"

    A request to associate an S/MIME certificate with an email identity.

    " + }, + "AssociateEmailIdentityCertificateResponse":{ + "type":"structure", + "members":{}, + "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " + }, "Attachment":{ "type":"structure", "required":[ @@ -2139,6 +2242,12 @@ "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " }, "CaseId":{"type":"string"}, + "CertificateArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:[\\w+=/,.@-]+:[\\w+=/,.@-]+:[\\w+=/,.@-]*:[0-9]+:certificate/[\\w+=,.@-]+" + }, "Charset":{"type":"string"}, "CloudWatchDestination":{ "type":"structure", @@ -2202,6 +2311,16 @@ "exception":true, "fault":true }, + "ConfigurationOverrides":{ + "type":"structure", + "members":{ + "Tracking":{ + "shape":"TrackingConfigurationOverrides", + "documentation":"

    An object that overrides the open and click tracking settings that would otherwise apply to the message.

    " + } + }, + "documentation":"

    An object that overrides settings for a single email sending request. An override applies only to the message or messages in the request that contains it. It doesn't change your account-level settings, and it doesn't change the configuration set that the request uses.

    A setting that you don't override keeps the value that would otherwise apply to the message. Depending on the setting, that value comes from the configuration set that the message uses, from your account-level settings, or from the Amazon SES default.

    " + }, "ConfigurationSetName":{ "type":"string", "documentation":"

    The name of a configuration set.

    Configuration sets are groups of rules that you can apply to the emails you send. You apply a configuration set to an email by including a reference to the configuration set in the headers of the email. When you apply a configuration set to an email, all of the rules in that configuration set are applied to the email.

    " @@ -2375,6 +2494,10 @@ "ArchivingOptions":{ "shape":"ArchivingOptions", "documentation":"

    An object that defines the MailManager archiving options for emails that you send using the configuration set.

    " + }, + "MessageSecurityOptions":{ + "shape":"MessageSecurityOptions", + "documentation":"

    The message security options to apply to the configuration set, such as the signing scheme used for messages that you send with the configuration set.

    " } }, "documentation":"

    A request to create a configuration set.

    " @@ -2964,6 +3087,11 @@ "type":"string", "documentation":"

    The default value of the dimension that is published to Amazon CloudWatch if you don't provide the value of the dimension when you send an email. This value has to meet the following criteria:

    • It can only contain ASCII letters (a–z, A–Z), numbers (0–9), underscores (_), or dashes (-).

    • It can contain no more than 255 characters.

    " }, + "DefaultSigningScheme":{ + "type":"structure", + "members":{}, + "documentation":"

    Specifies the default signing scheme, in which Amazon SES API v2 doesn't apply S/MIME signing to messages sent with the configuration set.

    " + }, "DeleteConfigurationSetEventDestinationRequest":{ "type":"structure", "required":[ @@ -3371,6 +3499,26 @@ "max":3, "min":1 }, + "DisassociateEmailIdentityCertificateRequest":{ + "type":"structure", + "required":["EmailIdentity"], + "members":{ + "EmailIdentity":{ + "shape":"Identity", + "documentation":"

    The email identity whose certificate association you want to remove.

    " + }, + "FromAddress":{ + "shape":"EmailAddress", + "documentation":"

    The email address whose certificate association you want to remove. This value is required when the email identity is a domain. When the email identity is an email address, this value is optional.

    " + } + }, + "documentation":"

    A request to remove the association between an S/MIME certificate and an email identity.

    " + }, + "DisassociateEmailIdentityCertificateResponse":{ + "type":"structure", + "members":{}, + "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " + }, "DisplayName":{"type":"string"}, "DkimAttributes":{ "type":"structure", @@ -3393,7 +3541,7 @@ }, "SigningAttributesOrigin":{ "shape":"DkimSigningAttributesOrigin", - "documentation":"

    A string that indicates how DKIM was configured for the identity. These are the possible values:

    • AWS_SES – Indicates that DKIM was configured for the identity by using Easy DKIM.

    • EXTERNAL – Indicates that DKIM was configured for the identity by using Bring Your Own DKIM (BYODKIM).

    • AWS_SES_AF_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Africa (Cape Town) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_NORTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Stockholm) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Mumbai) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Hyderabad) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Paris) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (London) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Milan) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Ireland) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Osaka) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Seoul) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Middle East (UAE) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Middle East (Bahrain) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Tokyo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_IL_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Israel (Tel Aviv) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_SA_EAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in South America (São Paulo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Canada (Central) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Canada (Calgary) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Singapore) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Sydney) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Jakarta) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_5 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Malaysia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Frankfurt) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Zurich) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US East (N. Virginia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US East (Ohio) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US West (N. California) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US West (Oregon) region using Deterministic Easy-DKIM (DEED).

    " + "documentation":"

    A string that indicates how DKIM was configured for the identity. These are the possible values:

    • AWS_SES – Indicates that DKIM was configured for the identity by using Easy DKIM.

    • EXTERNAL – Indicates that DKIM was configured for the identity by using Bring Your Own DKIM (BYODKIM).

    • AWS_SES_AF_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Africa (Cape Town) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_NORTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Stockholm) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Mumbai) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Hyderabad) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Paris) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (London) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Milan) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Ireland) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Osaka) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Seoul) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Middle East (UAE) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_SOUTH_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Middle East (Bahrain) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Tokyo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_IL_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Israel (Tel Aviv) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_SA_EAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in South America (São Paulo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Canada (Central) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Canada (Calgary) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Singapore) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Sydney) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_3 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Jakarta) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_5 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Asia Pacific (Malaysia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Frankfurt) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in Europe (Zurich) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US East (N. Virginia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US East (Ohio) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US West (N. California) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_2 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in US West (Oregon) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_GOV_EAST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in AWS GovCloud (US-East) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_GOV_WEST_1 – Indicates that DKIM was configured for the identity by replicating signing attributes from a parent identity in AWS GovCloud (US-West) region using Deterministic Easy-DKIM (DEED).

    " }, "NextSigningKeyLength":{ "shape":"DkimSigningKeyLength", @@ -3427,7 +3575,7 @@ }, "DomainSigningAttributesOrigin":{ "shape":"DkimSigningAttributesOrigin", - "documentation":"

    The attribute to use for configuring DKIM for the identity depends on the operation:

    1. For PutEmailIdentityDkimSigningAttributes:

    2. For CreateEmailIdentity when replicating a parent identity's DKIM configuration:

      • Allowed values: All values except AWS_SES and EXTERNAL

    • AWS_SES – Configure DKIM for the identity by using Easy DKIM.

    • EXTERNAL – Configure DKIM for the identity by using Bring Your Own DKIM (BYODKIM).

    • AWS_SES_AF_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Africa (Cape Town) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_NORTH_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Stockholm) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Mumbai) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Hyderabad) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_3 – Configure DKIM for the identity by replicating from a parent identity in Europe (Paris) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_2 – Configure DKIM for the identity by replicating from a parent identity in Europe (London) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Milan) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Ireland) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_3 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Osaka) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Seoul) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Middle East (UAE) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Middle East (Bahrain) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Tokyo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_IL_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Israel (Tel Aviv) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_SA_EAST_1 – Configure DKIM for the identity by replicating from a parent identity in South America (São Paulo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Canada (Central) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in Canada (Calgary) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Singapore) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Sydney) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_3 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Jakarta) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_5 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Malaysia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Frankfurt) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_2 – Configure DKIM for the identity by replicating from a parent identity in Europe (Zurich) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_1 – Configure DKIM for the identity by replicating from a parent identity in US East (N. Virginia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_2 – Configure DKIM for the identity by replicating from a parent identity in US East (Ohio) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in US West (N. California) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_2 – Configure DKIM for the identity by replicating from a parent identity in US West (Oregon) region using Deterministic Easy-DKIM (DEED).

    " + "documentation":"

    The attribute to use for configuring DKIM for the identity depends on the operation:

    1. For PutEmailIdentityDkimSigningAttributes:

    2. For CreateEmailIdentity when replicating a parent identity's DKIM configuration:

      • Allowed values: All values except AWS_SES and EXTERNAL

    • AWS_SES – Configure DKIM for the identity by using Easy DKIM.

    • EXTERNAL – Configure DKIM for the identity by using Bring Your Own DKIM (BYODKIM).

    • AWS_SES_AF_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Africa (Cape Town) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_NORTH_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Stockholm) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Mumbai) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTH_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Hyderabad) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_3 – Configure DKIM for the identity by replicating from a parent identity in Europe (Paris) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_2 – Configure DKIM for the identity by replicating from a parent identity in Europe (London) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Milan) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Ireland) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_3 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Osaka) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Seoul) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Middle East (UAE) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_ME_SOUTH_1 – Configure DKIM for the identity by replicating from a parent identity in Middle East (Bahrain) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_NORTHEAST_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Tokyo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_IL_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Israel (Tel Aviv) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_SA_EAST_1 – Configure DKIM for the identity by replicating from a parent identity in South America (São Paulo) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Canada (Central) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_CA_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in Canada (Calgary) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_1 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Singapore) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_2 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Sydney) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_3 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Jakarta) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_AP_SOUTHEAST_5 – Configure DKIM for the identity by replicating from a parent identity in Asia Pacific (Malaysia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_1 – Configure DKIM for the identity by replicating from a parent identity in Europe (Frankfurt) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_EU_CENTRAL_2 – Configure DKIM for the identity by replicating from a parent identity in Europe (Zurich) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_1 – Configure DKIM for the identity by replicating from a parent identity in US East (N. Virginia) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_EAST_2 – Configure DKIM for the identity by replicating from a parent identity in US East (Ohio) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in US West (N. California) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_WEST_2 – Configure DKIM for the identity by replicating from a parent identity in US West (Oregon) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_GOV_EAST_1 – Configure DKIM for the identity by replicating from a parent identity in AWS GovCloud (US-East) region using Deterministic Easy-DKIM (DEED).

    • AWS_SES_US_GOV_WEST_1 – Configure DKIM for the identity by replicating from a parent identity in AWS GovCloud (US-West) region using Deterministic Easy-DKIM (DEED).

    " } }, "documentation":"

    An object that contains configuration for Bring Your Own DKIM (BYODKIM), or, for Easy DKIM

    " @@ -3463,7 +3611,9 @@ "AWS_SES_AP_SOUTH_2", "AWS_SES_EU_CENTRAL_2", "AWS_SES_AP_SOUTHEAST_5", - "AWS_SES_CA_WEST_1" + "AWS_SES_CA_WEST_1", + "AWS_SES_US_GOV_EAST_1", + "AWS_SES_US_GOV_WEST_1" ] }, "DkimSigningKeyLength":{ @@ -4107,6 +4257,10 @@ "VdmAttributes":{ "shape":"VdmAttributes", "documentation":"

    The VDM attributes that apply to your Amazon SES account.

    " + }, + "PricingAttributes":{ + "shape":"PricingAttributes", + "documentation":"

    The pricing attributes that apply to your Amazon SES account, including the currently active pricing plan and any scheduled change.

    " } }, "documentation":"

    A list of details about the email-sending capabilities of your Amazon SES account in the current Amazon Web Services Region.

    " @@ -4209,6 +4363,10 @@ "ArchivingOptions":{ "shape":"ArchivingOptions", "documentation":"

    An object that defines the MailManager archive where sent emails are archived that you send using the configuration set.

    " + }, + "MessageSecurityOptions":{ + "shape":"MessageSecurityOptions", + "documentation":"

    The message security options that are applied to the configuration set, such as the signing scheme used for messages that you send with the configuration set.

    " } }, "documentation":"

    Information about a configuration set.

    " @@ -5037,6 +5195,43 @@ "type":"string", "min":1 }, + "IdentityCertificate":{ + "type":"structure", + "members":{ + "FromAddress":{ + "shape":"EmailAddress", + "documentation":"

    The email address that the certificate applies to.

    " + }, + "Status":{ + "shape":"IdentityCertificateStatus", + "documentation":"

    The status of the certificate association. A status of ACTIVE indicates that the certificate is ready to use for signing.

    " + }, + "CertificateArn":{ + "shape":"CertificateArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Certificate Manager (ACM) certificate that's associated with the email identity.

    " + }, + "CertificateExpiryTime":{ + "shape":"Timestamp", + "documentation":"

    The timestamp after which the certificate is no longer valid.

    " + } + }, + "documentation":"

    An object that contains information about an S/MIME certificate that's associated with an email identity.

    " + }, + "IdentityCertificateList":{ + "type":"list", + "member":{"shape":"IdentityCertificate"} + }, + "IdentityCertificateStatus":{ + "type":"string", + "documentation":"

    The status of an S/MIME certificate that's associated with an email identity. The status can be one of the following values:

    • PROVISIONING – The certificate association was created and the certificate is being prepared for use.

    • ACTIVE – The certificate is ready to use for signing.

    • INACTIVE – The certificate is no longer used for signing.

    • DEPROVISIONING – The certificate association is being cleaned up.

    • FAILED – The certificate couldn't be prepared for use, or the certificate has expired.

    ", + "enum":[ + "PROVISIONING", + "INACTIVE", + "DEPROVISIONING", + "ACTIVE", + "FAILED" + ] + }, "IdentityInfo":{ "type":"structure", "members":{ @@ -5588,6 +5783,39 @@ }, "documentation":"

    A list of all of the identities that you've attempted to verify, regardless of whether or not those identities were successfully verified.

    " }, + "ListEmailIdentityCertificatesRequest":{ + "type":"structure", + "required":["EmailIdentity"], + "members":{ + "EmailIdentity":{ + "shape":"Identity", + "documentation":"

    The email identity whose certificate associations you want to list.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    A token returned from a previous call to ListEmailIdentityCertificates to indicate the position in the list of certificates.

    " + }, + "PageSize":{ + "shape":"MaxItems", + "documentation":"

    The number of results to show in a single call to ListEmailIdentityCertificates. If the number of results is larger than the number you specified in this parameter, then the response includes a NextToken element, which you can use to obtain additional results.

    " + } + }, + "documentation":"

    A request to list the S/MIME certificates that are associated with an email identity.

    " + }, + "ListEmailIdentityCertificatesResponse":{ + "type":"structure", + "members":{ + "Certificates":{ + "shape":"IdentityCertificateList", + "documentation":"

    An array that contains the certificate associations for the email identity. Each entry includes the from address, the certificate's status, its Amazon Resource Name (ARN), and its expiry time.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    A token that indicates that there are additional certificates to list. To view additional certificates, issue another request to ListEmailIdentityCertificates, and pass this token in the NextToken parameter.

    " + } + }, + "documentation":"

    Information about the S/MIME certificates that are associated with an email identity.

    " + }, "ListEmailTemplatesRequest":{ "type":"structure", "members":{ @@ -6196,7 +6424,7 @@ }, "MaxResults":{ "shape":"MessageInsightsExportMaxResults", - "documentation":"

    The maximum number of results.

    " + "documentation":"

    The maximum number of results.

    If you don't specify MaxResults, the export returns a maximum of 1,000 results.

    " } }, "documentation":"

    An object that contains filters applied when performing the Message Insights export.

    " @@ -6225,6 +6453,10 @@ "shape":"IspFilterList", "documentation":"

    The recipient's ISP (e.g., Gmail, Yahoo, etc.).

    " }, + "TenantName":{ + "shape":"TenantNameFilterList", + "documentation":"

    The name of the tenant used when sending the message.

    " + }, "LastDeliveryEvent":{ "shape":"LastDeliveryEventList", "documentation":"

    The last delivery-related event for the email, where the ordering is as follows: SEND < BOUNCE < DELIVERY < COMPLAINT.

    " @@ -6243,6 +6475,16 @@ "error":{"httpStatusCode":400}, "exception":true }, + "MessageSecurityOptions":{ + "type":"structure", + "members":{ + "SigningScheme":{ + "shape":"SigningScheme", + "documentation":"

    The signing scheme that Amazon SES API v2 applies to messages sent with the configuration set.

    " + } + }, + "documentation":"

    An object that defines the message-level security options that apply to messages that you send using the configuration set. Currently, these options determine whether Amazon SES API v2 adds an S/MIME signature to your messages and, if so, the format of that signature.

    " + }, "MessageTag":{ "type":"structure", "required":[ @@ -6344,11 +6586,12 @@ }, "MetricDimensionName":{ "type":"string", - "documentation":"

    The BatchGetMetricDataQuery dimension name. This can be one of the following:

    • EMAIL_IDENTITY – The email identity used when sending messages.

    • CONFIGURATION_SET – The configuration set used when sending messages (if one was used).

    • ISP – The recipient ISP (e.g. Gmail, Yahoo, etc.).

    ", + "documentation":"

    The BatchGetMetricDataQuery dimension name. This can be one of the following:

    • EMAIL_IDENTITY – The email identity used when sending messages.

    • CONFIGURATION_SET – The configuration set used when sending messages (if one was used).

    • ISP – The recipient ISP (e.g. Gmail, Yahoo, etc.).

    • TENANT_NAME – The name of the tenant used when sending messages (if one was used).

    ", "enum":[ "EMAIL_IDENTITY", "CONFIGURATION_SET", - "ISP" + "ISP", + "TENANT_NAME" ] }, "MetricDimensionValue":{ @@ -6530,6 +6773,30 @@ "type":"string", "documentation":"

    The name of a dedicated IP pool.

    " }, + "PricingAttributes":{ + "type":"structure", + "members":{ + "CurrentPlan":{ + "shape":"PricingPlan", + "documentation":"

    The pricing plan that is currently active on your Amazon SES account.

    " + }, + "NextPlan":{ + "shape":"PricingPlan", + "documentation":"

    The pricing plan that will become active at the start of the next monthly cycle, if a scheduled change has been requested. This field is empty when no scheduled change is pending.

    " + } + }, + "documentation":"

    The pricing attributes that apply to your Amazon SES account, including the currently active pricing plan and any scheduled change.

    " + }, + "PricingPlan":{ + "type":"string", + "documentation":"

    Identifies an Amazon SES pricing plan. See PutAccountPricingAttributesRequest$Plan for the list of supported values and their meanings.

    ", + "enum":[ + "NONE", + "ESSENTIALS", + "PRO", + "ENTERPRISE" + ] + }, "PrimaryNameServer":{"type":"string"}, "PrivateKey":{ "type":"string", @@ -6593,6 +6860,22 @@ "members":{}, "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " }, + "PutAccountPricingAttributesRequest":{ + "type":"structure", + "required":["Plan"], + "members":{ + "Plan":{ + "shape":"PricingPlan", + "documentation":"

    The pricing plan to apply to your Amazon SES account. For details about each plan, see Amazon SES Pricing. Can be one of the following:

    • NONE

    • ESSENTIALS

    • PRO

    • ENTERPRISE

    " + } + }, + "documentation":"

    A request to set the pricing plan for your Amazon SES account.

    " + }, + "PutAccountPricingAttributesResponse":{ + "type":"structure", + "members":{}, + "documentation":"

    An HTTP 200 response if the request succeeds, or an error response if the request fails.

    " + }, "PutAccountSendingAttributesRequest":{ "type":"structure", "members":{ @@ -7495,6 +7778,10 @@ "TenantName":{ "shape":"TenantName", "documentation":"

    The name of the tenant through which this bulk email will be sent.

    The email sending operation will only succeed if all referenced resources (identities, configuration sets, and templates) are associated with this tenant.

    " + }, + "ConfigurationOverrides":{ + "shape":"ConfigurationOverrides", + "documentation":"

    An object that overrides, for the messages in this request only, settings that would otherwise apply to them. The overrides apply to every message in the request. Each setting that you don't override keeps the value that already applies.

    " } }, "documentation":"

    Represents a request to send email messages to multiple destinations using Amazon SES. For more information, see the Amazon SES Developer Guide.

    " @@ -7594,6 +7881,10 @@ "ListManagementOptions":{ "shape":"ListManagementOptions", "documentation":"

    An object used to specify a list or topic to which an email belongs, which will be used when a contact chooses to unsubscribe.

    " + }, + "ConfigurationOverrides":{ + "shape":"ConfigurationOverrides", + "documentation":"

    An object that overrides, for this message only, settings that would otherwise apply to it. Each setting that you don't override keeps the value that already applies.

    " } }, "documentation":"

    Represents a request to send a single formatted email using Amazon SES. For more information, see the Amazon SES Developer Guide.

    " @@ -7658,6 +7949,36 @@ }, "SentLast24Hours":{"type":"double"}, "SerialNumber":{"type":"long"}, + "SignatureFormat":{ + "type":"string", + "documentation":"

    The format of the S/MIME signature that's applied to a message. The following value is supported:

    • DETACHED – The signature is carried in a separate MIME part alongside the signed content.

    ", + "enum":["DETACHED"] + }, + "SigningScheme":{ + "type":"structure", + "members":{ + "DefaultScheme":{ + "shape":"DefaultSigningScheme", + "documentation":"

    Use the default signing behavior. When you select this option, Amazon SES API v2 doesn't add an S/MIME signature to messages sent with the configuration set.

    " + }, + "SmimeScheme":{ + "shape":"SmimeSigningScheme", + "documentation":"

    Sign messages sent with the configuration set using S/MIME. For signing to apply, the email identity used to send a message must have an active S/MIME certificate association.

    " + } + }, + "documentation":"

    Specifies the signing scheme to apply to messages sent with a configuration set. This is a union type, so you specify exactly one of its members.

    ", + "union":true + }, + "SmimeSigningScheme":{ + "type":"structure", + "members":{ + "SignatureFormat":{ + "shape":"SignatureFormat", + "documentation":"

    The format of the S/MIME signature that Amazon SES API v2 applies to messages.

    " + } + }, + "documentation":"

    Specifies that Amazon SES API v2 signs messages sent with the configuration set using S/MIME.

    " + }, "SnsDestination":{ "type":"structure", "required":["TopicArn"], @@ -8059,6 +8380,11 @@ "documentation":"

    The name of a tenant. The name can contain up to 64 alphanumeric characters, including letters, numbers, hyphens (-) and underscores (_) only.

    ", "min":1 }, + "TenantNameFilterList":{ + "type":"list", + "member":{"shape":"TenantName"}, + "max":5 + }, "TenantResource":{ "type":"structure", "members":{ @@ -8211,6 +8537,20 @@ "type":"list", "member":{"shape":"Topic"} }, + "TrackingConfigurationOverrides":{ + "type":"structure", + "members":{ + "OpenTrackingEnabled":{ + "shape":"FeatureStatus", + "documentation":"

    Specifies whether Amazon SES tracks when the recipient opens this message. Can be one of the following:

    • ENABLED – Amazon SES tracks opens for this message, even when your account-level and configuration set settings don't enable open tracking.

    • DISABLED – Amazon SES doesn't track opens for this message, even when your account-level or configuration set settings enable open tracking. Amazon SES doesn't add the tracking image to the message.

    If you don't specify this value, Amazon SES uses the open tracking setting that would otherwise apply to the message.

    " + }, + "ClickTrackingEnabled":{ + "shape":"FeatureStatus", + "documentation":"

    Specifies whether Amazon SES tracks when the recipient clicks a link in this message. Can be one of the following:

    • ENABLED – Amazon SES tracks clicks for this message, even when your account-level and configuration set settings don't enable click tracking.

    • DISABLED – Amazon SES doesn't track clicks for this message, even when your account-level or configuration set settings enable click tracking. Amazon SES doesn't rewrite the links in the message.

    If you don't specify this value, Amazon SES uses the click tracking setting that would otherwise apply to the message.

    Enabling open or click tracking with an override doesn't create an event destination. Amazon SES records the resulting open and click events in VDM, where you can review them using VDM metrics and Message Insights. To also receive these events at a destination that you own, the configuration set that the message uses must have an event destination that publishes open and click events.

    " + } + }, + "documentation":"

    An object that overrides, for a single email sending request, the engagement tracking settings that would otherwise apply. Use these overrides to turn open tracking or click tracking on or off for an individual message, for example to suppress tracking in a transactional message that you send from an account or a configuration set that has tracking enabled.

    Without an override, engagement tracking is determined by your account-level EngagementMetrics setting, which you configure using the PutAccountVdmAttributes operation, by the EngagementMetrics setting of the configuration set that the message uses, which you configure using the PutConfigurationSetVdmOptions operation, and by whether that configuration set has an event destination whose MatchingEventTypes include the OPEN or CLICK event types.

    For more information about tracking open and click events, see the Amazon SES Developer Guide.

    " + }, "TrackingOptions":{ "type":"structure", "required":["CustomRedirectDomain"], @@ -8284,6 +8624,26 @@ "members":{}, "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " }, + "UpdateConfigurationSetRequest":{ + "type":"structure", + "required":["ConfigurationSetName"], + "members":{ + "ConfigurationSetName":{ + "shape":"ConfigurationSetName", + "documentation":"

    The name of the configuration set to update.

    " + }, + "MessageSecurityOptions":{ + "shape":"MessageSecurityOptions", + "documentation":"

    The security options that apply to the MIME message itself for messages sent with the configuration set.

    " + } + }, + "documentation":"

    A request to update the configuration of an existing configuration set.

    " + }, + "UpdateConfigurationSetResponse":{ + "type":"structure", + "members":{}, + "documentation":"

    An HTTP 200 response if the request succeeds, or an error message if the request fails.

    " + }, "UpdateContactListRequest":{ "type":"structure", "required":["ContactListName"], diff --git a/services/sfn/pom.xml b/services/sfn/pom.xml index 0ca3a61ffb7d..200ceec6eec8 100644 --- a/services/sfn/pom.xml +++ b/services/sfn/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sfn AWS Java SDK :: Services :: AWS Step Functions diff --git a/services/sfn/src/main/resources/codegen-resources/customization.config b/services/sfn/src/main/resources/codegen-resources/customization.config index 0df33f6080a1..99b2a1a03599 100644 --- a/services/sfn/src/main/resources/codegen-resources/customization.config +++ b/services/sfn/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ "listStateMachines" ], "serviceSpecificHttpConfig": "software.amazon.awssdk.services.sfn.internal.SfnHttpConfigurationOptions", - "generateEndpointClientTests": true, - "enableGenerateCompiledEndpointRules": true + "generateEndpointClientTests": true } diff --git a/services/sfn/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sfn/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4974947a8794 --- /dev/null +++ b/services/sfn/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://states.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://states-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://states-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://states.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAkAAAAGAAAABAAAAAcF9eEEAAAABwX14QUAAAAIAAAACAX14QkF9eEKAAAABAAAAAwAAAAKAAAABQX14QQAAAALAAAABgX14QcF9eEIAAAABgAAAA0F9eEGAAAACAX14QUF9eEGAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sfn/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sfn/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7401e2ee4065..000000000000 --- a/services/sfn/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,424 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://states.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://states-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://states-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://states-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://states.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://states.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sfn/src/main/resources/codegen-resources/service-2.json b/services/sfn/src/main/resources/codegen-resources/service-2.json index 44ba50c5ffe9..677d15bee42c 100644 --- a/services/sfn/src/main/resources/codegen-resources/service-2.json +++ b/services/sfn/src/main/resources/codegen-resources/service-2.json @@ -250,7 +250,7 @@ {"shape":"KmsInvalidStateException"}, {"shape":"KmsThrottlingException"} ], - "documentation":"

    Used by workers to retrieve a task (with the specified activity ARN) which has been scheduled for execution by a running state machine. This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available (i.e. an execution of a task of this type is needed.) The maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll returns a taskToken with a null string.

    This API action isn't logged in CloudTrail.

    Workers should set their client side socket timeout to at least 65 seconds (5 seconds higher than the maximum time the service may hold the poll request).

    Polling with GetActivityTask can cause latency in some implementations. See Avoid Latency When Polling for Activity Tasks in the Step Functions Developer Guide.

    " + "documentation":"

    Used by workers to retrieve a task (with the specified activity ARN) which has been scheduled for execution by a running state machine. This initiates a long poll, where the service holds the HTTP connection open and responds as soon as a task becomes available (i.e. an execution of a task of this type is needed.) The maximum time the service holds on to the request before responding is 60 seconds. If no task is available within 60 seconds, the poll returns a taskToken with a null string.

    Workers should set their client side socket timeout to at least 65 seconds (5 seconds higher than the maximum time the service may hold the poll request).

    Polling with GetActivityTask can cause latency in some implementations. See Avoid Latency When Polling for Activity Tasks in the Step Functions Developer Guide.

    " }, "GetExecutionHistory":{ "name":"GetExecutionHistory", @@ -299,7 +299,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFound"} ], - "documentation":"

    Lists all executions of a state machine or a Map Run. You can list all executions related to a state machine by specifying a state machine Amazon Resource Name (ARN), or those related to a Map Run by specifying a Map Run ARN. Using this API action, you can also list all redriven executions.

    You can also provide a state machine alias ARN or version ARN to list the executions associated with a specific alias or version.

    Results are sorted by time, with the most recent execution first.

    If nextToken is returned, there are more results available. The value of nextToken is a unique pagination token for each page. Make the call again using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours. Using an expired pagination token will return an HTTP 400 InvalidToken error.

    This operation is eventually consistent. The results are best effort and may not reflect very recent updates and changes.

    This API action is not supported by EXPRESS state machines.

    " + "documentation":"

    Lists all executions of a state machine or a Map Run. You can list all executions related to a state machine by specifying a state machine Amazon Resource Name (ARN), or those related to a Map Run by specifying a Map Run ARN. Using this API action, you can also list all redriven executions.

    You can also provide a state machine alias ARN or version ARN to list the executions associated with a specific alias or version.

    Results are sorted by time, with the most recent execution first. Running executions are sorted by their startDate or redriveDate, and other executions are sorted by their stopDate.

    If nextToken is returned, there are more results available. The value of nextToken is a unique pagination token for each page. Make the call again using the returned token to retrieve the next page. Keep all other arguments unchanged. Each pagination token expires after 24 hours. Using an expired pagination token will return an HTTP 400 InvalidToken error.

    This operation is eventually consistent. The results are best effort and may not reflect very recent updates and changes.

    This API action is not supported by EXPRESS state machines. However, you may list EXPRESS children started by a map run using the mapRunArn parameter.

    " }, "ListMapRuns":{ "name":"ListMapRuns", @@ -485,7 +485,7 @@ {"shape":"KmsInvalidStateException"}, {"shape":"KmsThrottlingException"} ], - "documentation":"

    Starts a state machine execution.

    A qualified state machine ARN can either refer to a Distributed Map state defined within a state machine, a version ARN, or an alias ARN.

    The following are some examples of qualified and unqualified state machine ARNs:

    • The following qualified state machine ARN refers to a Distributed Map state with a label mapStateLabel in a state machine named myStateMachine.

      arn:partition:states:region:account-id:stateMachine:myStateMachine/mapStateLabel

      If you provide a qualified state machine ARN that refers to a Distributed Map state, the request fails with ValidationException.

    • The following qualified state machine ARN refers to an alias named PROD.

      arn:<partition>:states:<region>:<account-id>:stateMachine:<myStateMachine:PROD>

      If you provide a qualified state machine ARN that refers to a version ARN or an alias ARN, the request starts execution for that version or alias.

    • The following unqualified state machine ARN refers to a state machine named myStateMachine.

      arn:<partition>:states:<region>:<account-id>:stateMachine:<myStateMachine>

    If you start an execution with an unqualified state machine ARN, Step Functions uses the latest revision of the state machine for the execution.

    To start executions of a state machine version, call StartExecution and provide the version ARN or the ARN of an alias that points to the version.

    StartExecution is idempotent for STANDARD workflows. For a STANDARD workflow, if you call StartExecution with the same name and input as a running execution, the call succeeds and return the same response as the original request. If the execution is closed or if the input is different, it returns a 400 ExecutionAlreadyExists error. You can reuse names after 90 days.

    StartExecution isn't idempotent for EXPRESS workflows.

    ", + "documentation":"

    Starts a state machine execution.

    A qualified state machine ARN can either refer to a Distributed Map state defined within a state machine, a version ARN, or an alias ARN.

    The following are some examples of qualified and unqualified state machine ARNs:

    • The following qualified state machine ARN refers to a Distributed Map state with a label mapStateLabel in a state machine named myStateMachine.

      arn:partition:states:region:account-id:stateMachine:myStateMachine/mapStateLabel

      If you provide a qualified state machine ARN that refers to a Distributed Map state, the request fails with ValidationException.

    • The following qualified state machine ARN refers to an alias named PROD.

      arn:<partition>:states:<region>:<account-id>:stateMachine:<myStateMachine:PROD>

      If you provide a qualified state machine ARN that refers to a version ARN or an alias ARN, the request starts execution for that version or alias.

    • The following unqualified state machine ARN refers to a state machine named myStateMachine.

      arn:<partition>:states:<region>:<account-id>:stateMachine:<myStateMachine>

    If you start an execution with an unqualified state machine ARN, Step Functions uses the latest revision of the state machine for the execution.

    To start executions of a state machine version, call StartExecution and provide the version ARN or the ARN of an alias that points to the version.

    StartExecution is idempotent for STANDARD workflows. For a STANDARD workflow, if you call StartExecution with the same name and input as a running execution, the call succeeds and return the same response as the original request. If the execution is closed or if the input is different, it returns a 400 ExecutionAlreadyExists error. You can reuse the name 90 days after it closes.

    StartExecution isn't idempotent for EXPRESS workflows.

    ", "idempotent":true }, "StartSyncExecution":{ @@ -507,7 +507,7 @@ {"shape":"KmsInvalidStateException"}, {"shape":"KmsThrottlingException"} ], - "documentation":"

    Starts a Synchronous Express state machine execution. StartSyncExecution is not available for STANDARD workflows.

    StartSyncExecution will return a 200 OK response, even if your execution fails, because the status code in the API response doesn't reflect function errors. Error codes are reserved for errors that prevent your execution from running, such as permissions errors, limit errors, or issues with your state machine code and configuration.

    This API action isn't logged in CloudTrail.

    ", + "documentation":"

    Starts a Synchronous Express state machine execution. StartSyncExecution is not available for STANDARD workflows.

    StartSyncExecution will return a 200 OK response, even if your execution fails, because the status code in the API response doesn't reflect function errors. Error codes are reserved for errors that prevent your execution from running, such as permissions errors, limit errors, or issues with your state machine code and configuration.

    ", "endpoint":{"hostPrefix":"sync-"} }, "StopExecution":{ @@ -900,7 +900,7 @@ "members":{ "name":{ "shape":"Name", - "documentation":"

    The name of the activity to create. This name must be unique for your Amazon Web Services account and region for 90 days. For more information, see Limits Related to State Machine Executions in the Step Functions Developer Guide.

    A name must not contain:

    • white space

    • brackets < > { } [ ]

    • wildcard characters ? *

    • special characters \" # % \\ ^ | ~ ` $ & , ; : /

    • control characters (U+0000-001F, U+007F-009F, U+FFFE-FFFF)

    • surrogates (U+D800-DFFF)

    • invalid characters ( U+10FFFF)

    To enable logging with CloudWatch Logs, the name should only contain 0-9, A-Z, a-z, - and _.

    " + "documentation":"

    The name of the activity to create. This name must be unique for your Amazon Web Services account and region.

    A name must not contain:

    • white space

    • brackets < > { } [ ]

    • wildcard characters ? *

    • special characters \" # % \\ ^ | ~ ` $ & , ; : /

    • control characters (U+0000-001F, U+007F-009F, U+FFFE-FFFF)

    • surrogates (U+D800-DFFF)

    • invalid characters ( U+10FFFF)

    To enable logging with CloudWatch Logs, the name should only contain 0-9, A-Z, a-z, - and _.

    " }, "tags":{ "shape":"TagList", @@ -3242,7 +3242,7 @@ }, "name":{ "shape":"Name", - "documentation":"

    Optional name of the execution. This name must be unique for your Amazon Web Services account, Region, and state machine for 90 days. For more information, see Limits Related to State Machine Executions in the Step Functions Developer Guide.

    If you don't provide a name for the execution, Step Functions automatically generates a universally unique identifier (UUID) as the execution name.

    A name must not contain:

    • white space

    • brackets < > { } [ ]

    • wildcard characters ? *

    • special characters \" # % \\ ^ | ~ ` $ & , ; : /

    • control characters (U+0000-001F, U+007F-009F, U+FFFE-FFFF)

    • surrogates (U+D800-DFFF)

    • invalid characters ( U+10FFFF)

    To enable logging with CloudWatch Logs, the name should only contain 0-9, A-Z, a-z, - and _.

    " + "documentation":"

    Optional name of the execution. For STANDARD workflows, this name must be unique for your Amazon Web Services account, region, and state machine. If a previous execution with the same name exists, you can reuse the name 90 days after it closes. For EXPRESS workflows, execution names can be reused immediately. For more information, see Limits Related to State Machine Executions in the Step Functions Developer Guide.

    If you don't provide a name for the execution, Step Functions automatically generates a universally unique identifier (UUID) as the execution name.

    A name must not contain:

    • white space

    • brackets < > { } [ ]

    • wildcard characters ? *

    • special characters \" # % \\ ^ | ~ ` $ & , ; : /

    • control characters (U+0000-001F, U+007F-009F, U+FFFE-FFFF)

    • surrogates (U+D800-DFFF)

    • invalid characters ( U+10FFFF)

    To enable logging with CloudWatch Logs, the name should only contain 0-9, A-Z, a-z, - and _.

    " }, "input":{ "shape":"SensitiveData", diff --git a/services/shield/pom.xml b/services/shield/pom.xml index 6cf0e91df947..ac123c37a5cb 100644 --- a/services/shield/pom.xml +++ b/services/shield/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT shield AWS Java SDK :: Services :: AWS Shield diff --git a/services/shield/src/main/resources/codegen-resources/customization.config b/services/shield/src/main/resources/codegen-resources/customization.config index 7746e3896c44..7d2323feedfa 100644 --- a/services/shield/src/main/resources/codegen-resources/customization.config +++ b/services/shield/src/main/resources/codegen-resources/customization.config @@ -16,6 +16,5 @@ ], "deprecatedOperations": [ "DeleteSubscription" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/shield/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/shield/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..7ef05ec0fcd4 --- /dev/null +++ b/services/shield/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,237 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "shield", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield-fips.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "shield", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://shield.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABgX14QQF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAKAAAABgX14QUAAAALAAAABwX14QgF9eEJAAAABQAAAA0F9eEHAAAABwX14QYF9eEHAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/shield/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/shield/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b73865a387d6..000000000000 --- a/services/shield/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,416 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://shield.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "shield", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://shield-fips.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "shield", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://shield-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://shield-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://shield.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://shield.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/signer/pom.xml b/services/signer/pom.xml index 1b17ec93deed..fc7ab608bfae 100644 --- a/services/signer/pom.xml +++ b/services/signer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT signer AWS Java SDK :: Services :: Signer diff --git a/services/signer/src/main/resources/codegen-resources/customization.config b/services/signer/src/main/resources/codegen-resources/customization.config index 5c2bd87be192..6e174ea988f2 100644 --- a/services/signer/src/main/resources/codegen-resources/customization.config +++ b/services/signer/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "listSigningJobs", "listSigningPlatforms", "listSigningProfiles" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/signer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/signer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e3d1e51c4d19 --- /dev/null +++ b/services/signer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/signer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/signer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c3e9e6ee175d..000000000000 --- a/services/signer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signer-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signer.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://signer.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/signerdata/pom.xml b/services/signerdata/pom.xml index c4b3312cc954..b6be89639874 100644 --- a/services/signerdata/pom.xml +++ b/services/signerdata/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT signerdata AWS Java SDK :: Services :: Signer Data diff --git a/services/signerdata/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/signerdata/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..494d1a13f0a3 --- /dev/null +++ b/services/signerdata/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,120 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint.", + "type": "boolean" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-signer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-signer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-signer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://data-signer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAX14QEAAAADAAAAAQAAAAQF9eEAAAAAAgAAAAYAAAAFAAAAAwX14QQF9eEFAAAAAwX14QIF9eED" +} \ No newline at end of file diff --git a/services/signerdata/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/signerdata/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 80a5200ad3b5..000000000000 --- a/services/signerdata/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "required": true, - "type": "String", - "builtIn": "AWS::Region", - "documentation": "The AWS region used to dispatch the request." - }, - "UseFIPS": { - "required": true, - "type": "Boolean", - "builtIn": "AWS::UseFIPS", - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint." - }, - "UseDualStack": { - "required": true, - "type": "Boolean", - "builtIn": "AWS::UseDualStack", - "default": false, - "documentation": "When true, use the dual-stack endpoint." - }, - "Endpoint": { - "required": false, - "type": "String", - "builtIn": "SDK::Endpoint", - "documentation": "Override the endpoint used to send this request." - } - }, - "rules": [ - { - "type": "endpoint", - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "endpoint": { - "url": { - "ref": "Endpoint" - } - } - }, - { - "type": "tree", - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "type": "endpoint", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://data-signer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}" - } - }, - { - "type": "endpoint", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://data-signer-fips.{Region}.{PartitionResult#dnsSuffix}" - } - }, - { - "type": "endpoint", - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://data-signer.{Region}.{PartitionResult#dualStackDnsSuffix}" - } - }, - { - "type": "endpoint", - "conditions": [], - "endpoint": { - "url": "https://data-signer.{Region}.{PartitionResult#dnsSuffix}" - } - } - ] - } - ] -} \ No newline at end of file diff --git a/services/signin/pom.xml b/services/signin/pom.xml index fba91d57795c..9f32f6ebd759 100644 --- a/services/signin/pom.xml +++ b/services/signin/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT signin AWS Java SDK :: Services :: Signin diff --git a/services/signin/src/main/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactory.java b/services/signin/src/main/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactory.java index ae5fa97e8589..b5b12f84d1cf 100644 --- a/services/signin/src/main/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactory.java +++ b/services/signin/src/main/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactory.java @@ -16,13 +16,17 @@ package software.amazon.awssdk.services.signin.auth; import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; import software.amazon.awssdk.auth.credentials.AwsCredentials; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.ProfileCredentialsProviderFactory; import software.amazon.awssdk.auth.credentials.ProfileProviderCredentialsContext; import software.amazon.awssdk.profiles.Profile; +import software.amazon.awssdk.profiles.ProfileFile; import software.amazon.awssdk.profiles.ProfileProperty; import software.amazon.awssdk.services.signin.SigninClient; +import software.amazon.awssdk.services.signin.SigninClientBuilder; import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.SdkAutoCloseable; @@ -42,6 +46,23 @@ public AwsCredentialsProvider create(ProfileProviderCredentialsContext profilePr return new LoginProfileCredentialsProvider(profileProviderCredentialsContext); } + /** + * Create the {@link SigninClient} used to refresh the login session, configured from the profile that requested these + * credentials. + */ + @SdkTestInternalApi + static SigninClient signinClient(ProfileProviderCredentialsContext credentialsContext) { + SigninClientBuilder builder = SigninClient.builder() + .credentialsProvider(AnonymousCredentialsProvider.create()); + ProfileFile profileFile = credentialsContext.profileFile(); + if (profileFile != null) { + builder.overrideConfiguration(c -> c.defaultProfileFile(profileFile) + .defaultProfileName(credentialsContext.profile().name())); + } + + return builder.build(); + } + private static class LoginProfileCredentialsProvider implements AwsCredentialsProvider, SdkAutoCloseable { private final LoginCredentialsProvider credentialsProvider; private final SigninClient signinClient; @@ -51,7 +72,7 @@ private LoginProfileCredentialsProvider(ProfileProviderCredentialsContext creden String loginSession = profile.property(ProfileProperty.LOGIN_SESSION) .orElseThrow(() -> new IllegalArgumentException("login_session property is required")); - this.signinClient = SigninClient.create(); + this.signinClient = signinClient(credentialsContext); this.credentialsProvider = LoginCredentialsProvider .builder() .loginSession(loginSession) diff --git a/services/signin/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/signin/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f927f6f95f48 --- /dev/null +++ b/services/signin/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,529 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "IsControlPlane": { + "required": false, + "documentation": "Indicates if the operation targets the control plane endpoint", + "type": "boolean" + }, + "IsOAuthEndpoint": { + "required": false, + "documentation": "Indicates if the operation targets the OAuth token endpoint", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "IsControlPlane" + }, + false + ] + }, + true + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "coalesce", + "argv": [ + { + "ref": "IsOAuthEndpoint" + }, + false + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-f" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-e" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-eusc" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://signin.{Region}.api.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "signin", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin.{Region}.api.amazonwebservices.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "signin", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "signin", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS endpoints are not supported for OAuth operations. Disable FIPS or use a non-OAuth operation.", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.oauth.signin.aws", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "signin", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.aws.amazon.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.amazonaws.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.amazonaws-us-gov.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.c2shome.ic.gov", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.sc2shome.sgov.gov", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.csphome.hci.ic.gov", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.csphome.adc-e.uk", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.amazonaws-eusc.eu", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin-fips.amazonaws-us-gov.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin-fips.amazonaws-us-gov.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://{Region}.signin.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://signin.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 40, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAgAAACQAAAAEAAAABAAAAAUF9eEbAAAABgX14QQF9eEbAAAAAQAAAB0AAAAHAAAAAgAAACQAAAAIAAAAAwAAAAkAAAAfAAAABAAAABYAAAAKAAAABQAAABMAAAALAAAABwAAABUAAAAMAAAACAX14QcAAAANAAAACgX14QgAAAAOAAAADAX14QkAAAAPAAAADQX14QoAAAAQAAAADgX14QsAAAARAAAADwX14QwAAAASAAAAEAX14Q0F9eEQAAAABgX14QUAAAAUAAAABwAAABUF9eEGAAAAEQX14RgF9eEZAAAABgX14QQAAAAXAAAABwAAABsAAAAYAAAACQX14Q4AAAAZAAAACgX14Q8AAAAaAAAACwX14RYF9eEXAAAACwAAABwF9eEVAAAAEQX14RQF9eEVAAAAAgAAACMAAAAeAAAAAwAAACcAAAAfAAAABAAAACAF9eEbAAAABgX14QQAAAAhAAAABwX14RsAAAAiAAAACQX14Q4F9eEbAAAAAwAAACcAAAAkAAAABAAAACYAAAAlAAAABwX14RIF9eETAAAABgX14QQF9eERAAAABQX14QEAAAAoAAAACAX14QIF9eED" +} \ No newline at end of file diff --git a/services/signin/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/signin/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 545bb9c3a661..000000000000 --- a/services/signin/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,1492 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "IsControlPlane": { - "required": false, - "documentation": "Indicates if the operation targets the control plane endpoint", - "type": "boolean" - }, - "IsOAuthEndpoint": { - "required": false, - "documentation": "Indicates if the operation targets the OAuth token endpoint", - "type": "boolean" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "IsControlPlane" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "IsControlPlane" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://signin.{Region}.api.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "signin", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "endpoint": { - "url": "https://signin.{Region}.api.amazonwebservices.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "signin", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://signin.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "signin", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "IsOAuthEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "IsOAuthEndpoint" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "FIPS endpoints are not supported for OAuth operations. Disable FIPS or use a non-OAuth operation.", - "type": "error" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "IsOAuthEndpoint" - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "IsOAuthEndpoint" - }, - true - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://{Region}.oauth.signin.aws", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "signin", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.aws.amazon.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.amazonaws.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.amazonaws-us-gov.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.c2shome.ic.gov", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.sc2shome.sgov.gov", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-f" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.csphome.hci.ic.gov", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-e" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.csphome.adc-e.uk", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-eusc" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.amazonaws-eusc.eu", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://signin-fips.amazonaws-us-gov.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin-fips.amazonaws-us-gov.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "endpoint": { - "url": "https://{Region}.signin.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.aws.amazon.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.amazonaws.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://{Region}.signin.amazonaws-us-gov.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signin-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signin-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://signin.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://signin.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/signin/src/test/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactoryTest.java b/services/signin/src/test/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactoryTest.java index c27be1270a7c..7c6dbce0cfe3 100644 --- a/services/signin/src/test/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactoryTest.java +++ b/services/signin/src/test/java/software/amazon/awssdk/services/signin/auth/LoginProfileCredentialsProviderFactoryTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static software.amazon.awssdk.services.signin.auth.internal.DpopTestUtils.VALID_TEST_PEM; +import java.net.URI; import java.nio.file.Path; import java.time.Instant; import java.util.Optional; @@ -33,12 +34,16 @@ import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; import software.amazon.awssdk.auth.credentials.ProfileProviderCredentialsContext; import software.amazon.awssdk.auth.credentials.internal.ProfileCredentialsUtils; +import software.amazon.awssdk.core.SdkSystemSetting; import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.signin.SigninClient; import software.amazon.awssdk.services.signin.internal.AccessTokenManager; import software.amazon.awssdk.services.signin.internal.LoginAccessToken; import software.amazon.awssdk.services.signin.internal.LoginCacheDirectorySystemSetting; import software.amazon.awssdk.services.signin.internal.OnDiskTokenManager; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; import software.amazon.awssdk.utils.StringInputStream; public class LoginProfileCredentialsProviderFactoryTest { @@ -47,17 +52,20 @@ public class LoginProfileCredentialsProviderFactoryTest { @TempDir Path tempDir; + private final EnvironmentVariableHelper environmentVariables = new EnvironmentVariableHelper(); + private AccessTokenManager tokenManager; @BeforeEach public void setup() { - System.setProperty(new LoginCacheDirectorySystemSetting().property(), tempDir.toString()); + environmentVariables.set(new LoginCacheDirectorySystemSetting(), tempDir.toString()); + environmentVariables.remove(SdkSystemSetting.AWS_REGION); tokenManager = OnDiskTokenManager.create(tempDir, LOGIN_SESSION_ID); } @AfterEach public void teardown() { - System.clearProperty(new LoginCacheDirectorySystemSetting().property()); + environmentVariables.reset(); } @Test @@ -67,15 +75,10 @@ public void create_returnsLoginCredentialsFromProfile() { tokenManager.storeToken(token); ProfileFile profileFile = configFile("[profile foo]\n" + + "region=us-east-1\n" + "login_session=" + LOGIN_SESSION_ID + "\n"); - AwsCredentialsProvider provider = new LoginProfileCredentialsProviderFactory().create( - ProfileProviderCredentialsContext - .builder() - .profile(profileFile.profile("foo").get()) - .profileFile(profileFile) - .build() - ); + AwsCredentialsProvider provider = new LoginProfileCredentialsProviderFactory().create(context(profileFile, "foo")); // validate the creds are from cached token file stored above AwsCredentials credentials = provider.resolveCredentials(); @@ -100,6 +103,7 @@ public void profileCredentialsUtils_returnsLoginCredentialsFromProfile() { tokenManager.storeToken(token); ProfileFile profileFile = configFile("[profile foo]\n" + + "region=us-east-1\n" + "login_session=" + LOGIN_SESSION_ID + "\n"); ProfileCredentialsUtils profileCredentialsUtils = new ProfileCredentialsUtils( @@ -122,6 +126,79 @@ public void profileCredentialsUtils_returnsLoginCredentialsFromProfile() { assertEquals(expectedCredSource, resolvedCredentials.providerName().get()); } + @Test + public void signinClient_resolvesRegionFromContextProfile() { + ProfileFile profileFile = configFile("[default]\n" + + "region=us-east-1\n" + + "\n" + + "[profile foo]\n" + + "region=eu-west-2\n" + + "login_session=" + LOGIN_SESSION_ID + "\n"); + + try (SigninClient client = LoginProfileCredentialsProviderFactory.signinClient(context(profileFile, "foo"))) { + assertEquals(Region.EU_WEST_2, client.serviceClientConfiguration().region()); + } + } + + /** + * The profile is applied as the client's default profile, so it drives every setting the client loads from a profile, not + * just the region. + */ + @Test + public void signinClient_resolvesNonRegionSettingsFromContextProfile() { + ProfileFile profileFile = configFile("[default]\n" + + "region=us-east-1\n" + + "\n" + + "[profile foo]\n" + + "region=us-east-1\n" + + "endpoint_url=https://signin.example.com\n" + + "login_session=" + LOGIN_SESSION_ID + "\n"); + + try (SigninClient client = LoginProfileCredentialsProviderFactory.signinClient(context(profileFile, "foo"))) { + assertEquals(URI.create("https://signin.example.com"), + client.serviceClientConfiguration().endpointOverride().orElse(null)); + } + } + + @Test + public void signinClient_whenProfileFileMissingFromContext_fallsBackToDefaultConfiguration() { + ProfileFile profileFile = configFile("[profile foo]\n" + + "region=eu-west-2\n" + + "login_session=" + LOGIN_SESSION_ID + "\n"); + + ProfileProviderCredentialsContext context = ProfileProviderCredentialsContext + .builder() + .profile(profileFile.profile("foo").get()) + .build(); + + environmentVariables.set(SdkSystemSetting.AWS_REGION, "us-east-1"); + try (SigninClient client = LoginProfileCredentialsProviderFactory.signinClient(context)) { + assertEquals(Region.US_EAST_1, client.serviceClientConfiguration().region()); + } + } + + /** + * Region has higher-priority sources than the profile, and the profile override should not change that. + */ + @Test + public void signinClient_whenRegionSetInSystemSettings_takesPriorityOverContextProfile() { + ProfileFile profileFile = configFile("[profile foo]\n" + + "region=eu-west-2\n" + + "login_session=" + LOGIN_SESSION_ID + "\n"); + + environmentVariables.set(SdkSystemSetting.AWS_REGION, "us-east-1"); + try (SigninClient client = LoginProfileCredentialsProviderFactory.signinClient(context(profileFile, "foo"))) { + assertEquals(Region.US_EAST_1, client.serviceClientConfiguration().region()); + } + } + + private static ProfileProviderCredentialsContext context(ProfileFile profileFile, String profileName) { + return ProfileProviderCredentialsContext.builder() + .profile(profileFile.profile(profileName).get()) + .profileFile(profileFile) + .build(); + } + private static ProfileFile configFile(String configFile) { return ProfileFile.builder() .content(new StringInputStream(configFile)) diff --git a/services/simpledbv2/pom.xml b/services/simpledbv2/pom.xml index c56813e1c478..8e6c8abc3740 100644 --- a/services/simpledbv2/pom.xml +++ b/services/simpledbv2/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT simpledbv2 AWS Java SDK :: Services :: Simple DB V2 diff --git a/services/simpledbv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/simpledbv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4c6e0f90dfe7 --- /dev/null +++ b/services/simpledbv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,206 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sdb.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sdb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sdb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sdb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sdb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAkAAAAGAAAABQAAAAgAAAAHAAAABwX14QQF9eELAAAABgX14QkF9eEKAAAABAAAAAsAAAAKAAAABQX14QYF9eEIAAAABQAAAAwF9eEHAAAABgX14QUF9eEGAAAAAwX14QEAAAAOAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/simpledbv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/simpledbv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7979ff9afd86..000000000000 --- a/services/simpledbv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,381 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://sdb.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sdb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sdb-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sdb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sdb.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/snowball/pom.xml b/services/snowball/pom.xml index 7518a1eb326e..c45b449fa134 100644 --- a/services/snowball/pom.xml +++ b/services/snowball/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT snowball AWS Java SDK :: Services :: Amazon Snowball diff --git a/services/snowball/src/main/resources/codegen-resources/customization.config b/services/snowball/src/main/resources/codegen-resources/customization.config index 54b6acdf321e..a19b2b5e7261 100644 --- a/services/snowball/src/main/resources/codegen-resources/customization.config +++ b/services/snowball/src/main/resources/codegen-resources/customization.config @@ -19,6 +19,5 @@ }, "excludedSimpleMethods": [ "createJob" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/snowball/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/snowball/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..614ee24b6846 --- /dev/null +++ b/services/snowball/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snowball-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snowball-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snowball.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snowball.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/snowball/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/snowball/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8b9bd8181b73..000000000000 --- a/services/snowball/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snowball-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snowball-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snowball.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://snowball.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/snowdevicemanagement/pom.xml b/services/snowdevicemanagement/pom.xml index f7819fb916ec..5e13b1331bb0 100644 --- a/services/snowdevicemanagement/pom.xml +++ b/services/snowdevicemanagement/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT snowdevicemanagement AWS Java SDK :: Services :: Snow Device Management diff --git a/services/snowdevicemanagement/src/main/resources/codegen-resources/customization.config b/services/snowdevicemanagement/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/snowdevicemanagement/src/main/resources/codegen-resources/customization.config +++ b/services/snowdevicemanagement/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..fcd6c7ce5622 --- /dev/null +++ b/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snow-device-management-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snow-device-management-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snow-device-management.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://snow-device-management.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a4ab87673fb1..000000000000 --- a/services/snowdevicemanagement/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snow-device-management-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snow-device-management-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://snow-device-management.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://snow-device-management.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sns/pom.xml b/services/sns/pom.xml index 7b0a29c53fb4..3e4df47f41d2 100644 --- a/services/sns/pom.xml +++ b/services/sns/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sns AWS Java SDK :: Services :: Amazon SNS diff --git a/services/sns/src/main/resources/codegen-resources/customization.config b/services/sns/src/main/resources/codegen-resources/customization.config index fa152e531c44..253f4995da35 100644 --- a/services/sns/src/main/resources/codegen-resources/customization.config +++ b/services/sns/src/main/resources/codegen-resources/customization.config @@ -19,8 +19,6 @@ } ] } - }, - - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/sns/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sns/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..d09fb59f7e50 --- /dev/null +++ b/services/sns/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,224 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-gov-west-1" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns.us-gov-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns.us-gov-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sns.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAJAAAABgAAAAoF9eEJAAAABwX14QYAAAALAAAACAX14QcF9eEIAAAABQAAAA0F9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sns/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sns/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 93c066d30cdf..000000000000 --- a/services/sns/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,352 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sns-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-east-1" - ] - } - ], - "endpoint": { - "url": "https://sns.us-gov-east-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-gov-west-1" - ] - } - ], - "endpoint": { - "url": "https://sns.us-gov-west-1.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sns-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sns.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sns.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sns/src/main/resources/codegen-resources/service-2.json b/services/sns/src/main/resources/codegen-resources/service-2.json index 3ea8b6184006..d39e5cd873d0 100644 --- a/services/sns/src/main/resources/codegen-resources/service-2.json +++ b/services/sns/src/main/resources/codegen-resources/service-2.json @@ -238,7 +238,7 @@ {"shape":"AuthorizationErrorException"}, {"shape":"InvalidSecurityException"} ], - "documentation":"

    Retrieves the specified inline DataProtectionPolicy document that is stored in the specified Amazon SNS topic.

    " + "documentation":"

    Amazon SNS message data protection is no longer available to new customers. For more information and guidance on alternatives, see Amazon SNS message data protection availability change.

    Retrieves the specified inline DataProtectionPolicy document that is stored in the specified Amazon SNS topic.

    " }, "GetEndpointAttributes":{ "name":"GetEndpointAttributes", @@ -607,7 +607,7 @@ {"shape":"InvalidSecurityException"}, {"shape":"ValidationException"} ], - "documentation":"

    Publishes up to 10 messages to the specified topic in a single batch. This is a batch version of the Publish API. If you try to send more than 10 messages in a single batch request, you will receive a TooManyEntriesInBatchRequest exception.

    For FIFO topics, multiple messages within a single batch are published in the order they are sent, and messages are deduplicated within the batch and across batches for five minutes.

    The result of publishing each message is reported individually in the response. Because the batch request can result in a combination of successful and unsuccessful actions, you should check for batch errors even when the call returns an HTTP status code of 200.

    The maximum allowed individual message size and the maximum total payload size (the sum of the individual lengths of all of the batched messages) are both 256 KB (262,144 bytes).

    The PublishBatch API can send up to 10 messages at a time. If you attempt to send more than 10 messages in one request, you will encounter a TooManyEntriesInBatchRequest exception. In such cases, split your messages into multiple requests, each containing no more than 10 messages.

    Some actions take lists of parameters. These lists are specified using the param.n notation. Values of n are integers starting from 1. For example, a parameter list with two elements looks like this:

    &AttributeName.1=first

    &AttributeName.2=second

    If you send a batch message to a topic, Amazon SNS publishes the batch message to each endpoint that is subscribed to the topic. The format of the batch message depends on the notification protocol for each subscribed endpoint.

    When a messageId is returned, the batch message is saved, and Amazon SNS immediately delivers the message to subscribers.

    " + "documentation":"

    Publishes up to 10 messages to the specified topic in a single batch. This is a batch version of the Publish API. If you try to send more than 10 messages in a single batch request, you will receive a TooManyEntriesInBatchRequest exception.

    For FIFO topics, multiple messages within a single batch are published in the order they are sent, and messages are deduplicated within the batch and across batches for five minutes.

    The result of publishing each message is reported individually in the response. Because the batch request can result in a combination of successful and unsuccessful actions, you should check for batch errors even when the call returns an HTTP status code of 200.

    By default, the maximum allowed individual message size and the maximum total payload size (the sum of the individual lengths of all of the batched messages) are both 256 KiB (262,144 bytes). To publish larger batches, set the topic's MaximumMessageSize attribute, which supports values up to 1 MiB (1,048,576 bytes). The combined size of all messages in the batch, including each message's body and attributes, must not exceed the topic's MaximumMessageSize.

    For more information, see Large message payloads in the Amazon SNS Developer Guide.

    The PublishBatch API can send up to 10 messages at a time. If you attempt to send more than 10 messages in one request, you will encounter a TooManyEntriesInBatchRequest exception. In such cases, split your messages into multiple requests, each containing no more than 10 messages.

    Some actions take lists of parameters. These lists are specified using the param.n notation. Values of n are integers starting from 1. For example, a parameter list with two elements looks like this:

    &AttributeName.1=first

    &AttributeName.2=second

    If you send a batch message to a topic, Amazon SNS publishes the batch message to each endpoint that is subscribed to the topic. The format of the batch message depends on the notification protocol for each subscribed endpoint.

    When a messageId is returned, the batch message is saved, and Amazon SNS immediately delivers the message to subscribers.

    " }, "PutDataProtectionPolicy":{ "name":"PutDataProtectionPolicy", @@ -623,7 +623,7 @@ {"shape":"AuthorizationErrorException"}, {"shape":"InvalidSecurityException"} ], - "documentation":"

    Adds or updates an inline policy document that is stored in the specified Amazon SNS topic.

    " + "documentation":"

    Amazon SNS message data protection is no longer available to new customers. For more information and guidance on alternatives, see Amazon SNS message data protection availability change.

    Adds or updates an inline policy document that is stored in the specified Amazon SNS topic.

    " }, "RemovePermission":{ "name":"RemovePermission", @@ -1098,7 +1098,7 @@ }, "Attributes":{ "shape":"TopicAttributesMap", - "documentation":"

    A map of attributes with their corresponding values.

    The following lists names, descriptions, and values of the special request parameters that the CreateTopic action uses:

    • DeliveryPolicy – The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints.

    • DisplayName – The display name to use for a topic with SMS subscriptions.

    • Policy – The policy that defines who can access your topic. By default, only the topic owner can publish or subscribe to the topic.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    • HTTP

      • HTTPSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

    • Amazon Data Firehose

      • FirehoseSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

    • Lambda

      • LambdaSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

    • Platform application endpoint

      • ApplicationSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to a platform application endpoint.

      • ApplicationSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      In addition to being able to configure topic attributes for message delivery status of notification messages sent to Amazon SNS application endpoints, you can also configure application attributes for the delivery status of push notification messages sent to push notification services.

      For example, For more information, see Using Amazon SNS Application Attributes for Message Delivery Status.

    • Amazon SQS

      • SQSSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

    The <ENDPOINT>SuccessFeedbackRoleArn and <ENDPOINT>FailureFeedbackRoleArn attributes are used to give Amazon SNS write access to use CloudWatch Logs on your behalf. The <ENDPOINT>SuccessFeedbackSampleRate attribute is for specifying the sample rate percentage (0-100) of successfully delivered messages. After you configure the <ENDPOINT>FailureFeedbackRoleArn attribute, then all failed message deliveries generate CloudWatch Logs.

    The following attribute applies only to server-side encryption:

    • KmsMasterKeyId – The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    The following attributes apply only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoThroughputScope – Enables higher throughput for your FIFO topic by adjusting the scope of deduplication. This attribute has two possible values:

      • Topic – The scope of message deduplication is across the entire topic. This is the default value and maintains existing behavior, with a maximum throughput of 3000 messages per second or 20MB per second, whichever comes first.

      • MessageGroup – The scope of deduplication is within each individual message group, which enables higher throughput per topic subject to regional quotas. For more information on quotas or to request an increase, see Amazon SNS service quotas in the Amazon Web Services General Reference.

    " + "documentation":"

    A map of attributes with their corresponding values.

    The following lists names, descriptions, and values of the special request parameters that the CreateTopic action uses:

    • DeliveryPolicy – The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints.

    • DisplayName – The display name to use for a topic with SMS, email, and email-json subscriptions. For email and email-json subscriptions, the display name is used as the sender name for regular notification messages. Subscription confirmation and unsubscribe confirmation emails always use \"Amazon Web Services Notifications\" as the sender name.

    • MaximumMessageSize – The maximum size, in bytes, of a message that can be published to the topic. Valid values are 1024 to 1048576 (1 MiB). The default is 262144 (256 KiB).

      A topic with a MaximumMessageSize above 256 KiB must have 100 or fewer subscriptions, and each subscription must be an Amazon SQS, Amazon Data Firehose, or Lambda subscription.

    • Policy – The policy that defines who can access your topic. By default, only the topic owner can publish or subscribe to the topic.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    • HTTP

      • HTTPSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

    • Amazon Data Firehose

      • FirehoseSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

    • Lambda

      • LambdaSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

    • Platform application endpoint

      • ApplicationSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to a platform application endpoint.

      • ApplicationSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      In addition to being able to configure topic attributes for message delivery status of notification messages sent to Amazon SNS application endpoints, you can also configure application attributes for the delivery status of push notification messages sent to push notification services.

      For example, For more information, see Using Amazon SNS Application Attributes for Message Delivery Status.

    • Amazon SQS

      • SQSSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

    The <ENDPOINT>SuccessFeedbackRoleArn and <ENDPOINT>FailureFeedbackRoleArn attributes are used to give Amazon SNS write access to use CloudWatch Logs on your behalf. The <ENDPOINT>SuccessFeedbackSampleRate attribute is for specifying the sample rate percentage (0-100) of successfully delivered messages. After you configure the <ENDPOINT>FailureFeedbackRoleArn attribute, then all failed message deliveries generate CloudWatch Logs.

    The following attribute applies only to server-side encryption:

    • KmsMasterKeyId – The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    The following attributes apply only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoThroughputScope – Enables higher throughput for your FIFO topic by adjusting the scope of deduplication. This attribute has two possible values:

      • Topic – The scope of message deduplication is across the entire topic. This is the default value and maintains existing behavior, with a maximum throughput of 3000 messages per second or 20MB per second, whichever comes first.

      • MessageGroup – The scope of deduplication is within each individual message group, which enables higher throughput per topic subject to regional quotas. For more information on quotas or to request an increase, see Amazon SNS service quotas in the Amazon Web Services General Reference.

    " }, "Tags":{ "shape":"TagList", @@ -1106,7 +1106,7 @@ }, "DataProtectionPolicy":{ "shape":"attributeValue", - "documentation":"

    The body of the policy document you want to use for this topic.

    You can only add one policy per topic.

    The policy must be in JSON string format.

    Length Constraints: Maximum length of 30,720.

    " + "documentation":"

    Amazon SNS message data protection is no longer available to new customers. For more information and guidance on alternatives, see Amazon SNS message data protection availability change.

    The body of the policy document you want to use for this topic.

    You can only add one policy per topic.

    The policy must be in JSON string format.

    Length Constraints: Maximum length of 30,720.

    " } }, "documentation":"

    Input for CreateTopic action.

    " @@ -1359,7 +1359,7 @@ "members":{ "Attributes":{ "shape":"TopicAttributesMap", - "documentation":"

    A map of the topic's attributes. Attributes in this map include the following:

    • DeliveryPolicy – The JSON serialization of the topic's delivery policy.

    • DisplayName – The human-readable name used in the From field for notifications to email and email-json endpoints.

    • EffectiveDeliveryPolicy – The JSON serialization of the effective delivery policy, taking system defaults into account.

    • Owner – The Amazon Web Services account ID of the topic's owner.

    • Policy – The JSON serialization of the topic's access control policy.

    • SignatureVersion – The signature version corresponds to the hashing algorithm used while creating the signature of the notifications, subscription confirmations, or unsubscribe confirmation messages sent by Amazon SNS.

      • By default, SignatureVersion is set to 1. The signature is a Base64-encoded SHA1withRSA signature.

      • When you set SignatureVersion to 2. Amazon SNS uses a Base64-encoded SHA256withRSA signature.

        If the API response does not include the SignatureVersion attribute, it means that the SignatureVersion for the topic has value 1.

    • SubscriptionsConfirmed – The number of confirmed subscriptions for the topic.

    • SubscriptionsDeleted – The number of deleted subscriptions for the topic.

    • SubscriptionsPending – The number of subscriptions pending confirmation for the topic.

    • TopicArn – The topic's ARN.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    The following attribute applies only to server-side-encryption:

    • KmsMasterKeyId - The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    The following attributes apply only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • BeginningArchiveTime – The earliest starting point at which a message in the topic’s archive can be replayed from. This point in time is based on the configured message retention period set by the topic’s message archiving policy.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoTopic – When this is set to true, a FIFO topic is created.

    " + "documentation":"

    A map of the topic's attributes. Attributes in this map include the following:

    • DeliveryPolicy – The JSON serialization of the topic's delivery policy.

    • DisplayName – The human-readable name used in the From field for notifications to email and email-json endpoints. For subscription confirmation and unsubscribe confirmation emails, the sender name is always \"Amazon Web Services Notifications\" regardless of this attribute.

    • EffectiveDeliveryPolicy – The JSON serialization of the effective delivery policy, taking system defaults into account.

    • MaximumMessageSize – The maximum size, in bytes, of a message that can be published to the topic. Amazon SNS returns this attribute only if you explicitly set it. If Amazon SNS doesn't return it, the topic uses the default of 262144 (256 KiB).

    • Owner – The Amazon Web Services account ID of the topic's owner.

    • Policy – The JSON serialization of the topic's access control policy.

    • SignatureVersion – The signature version corresponds to the hashing algorithm used while creating the signature of the notifications, subscription confirmations, or unsubscribe confirmation messages sent by Amazon SNS.

      • By default, SignatureVersion is set to 1. The signature is a Base64-encoded SHA1withRSA signature.

      • When you set SignatureVersion to 2. Amazon SNS uses a Base64-encoded SHA256withRSA signature.

        If the API response does not include the SignatureVersion attribute, it means that the SignatureVersion for the topic has value 1.

    • SubscriptionsConfirmed – The number of confirmed subscriptions for the topic.

    • SubscriptionsDeleted – The number of deleted subscriptions for the topic.

    • SubscriptionsPending – The number of subscriptions pending confirmation for the topic.

    • TopicArn – The topic's ARN.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    The following attribute applies only to server-side-encryption:

    • KmsMasterKeyId - The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    The following attributes apply only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • BeginningArchiveTime – The earliest starting point at which a message in the topic’s archive can be replayed from. This point in time is based on the configured message retention period set by the topic’s message archiving policy.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoTopic – When this is set to true, a FIFO topic is created.

    " } }, "documentation":"

    Response for GetTopicAttributes action.

    " @@ -1828,7 +1828,7 @@ "documentation":"

    Binary type attributes can store any binary data, for example, compressed data, encrypted data, or images.

    " } }, - "documentation":"

    The user-specified message attribute value. For string data types, the value attribute has the same restrictions on the content as the message body. For more information, see Publish.

    Name, type, and value must not be empty or null. In addition, the message body should not be empty or null. All parts of the message attribute, including name, type, and value, are included in the message size restriction, which is currently 256 KB (262,144 bytes). For more information, see Amazon SNS message attributes and Publishing to a mobile phone in the Amazon SNS Developer Guide.

    " + "documentation":"

    The user-specified message attribute value. For string data types, the value attribute has the same restrictions on the content as the message body. For more information, see Publish.

    Name, type, and value must not be empty or null. In addition, the message body should not be empty or null. All parts of the message attribute, including name, type, and value, are included in the message size restriction, which is 256 KiB (262,144 bytes) by default and is determined by the topic's MaximumMessageSize attribute. For more information, see Large message payloads, Amazon SNS message attributes and Publishing to a mobile phone in the Amazon SNS Developer Guide.

    " }, "NotFoundException":{ "type":"structure", @@ -2084,7 +2084,7 @@ }, "Message":{ "shape":"message", - "documentation":"

    The message you want to send.

    If you are publishing to a topic and you want to send the same message to all transport protocols, include the text of the message as a String value. If you want to send different messages for each transport protocol, set the value of the MessageStructure parameter to json and use a JSON object for the Message parameter.

    Constraints:

    • With the exception of SMS, messages must be UTF-8 encoded strings and at most 256 KB in size (262,144 bytes, not 262,144 characters).

    • For SMS, each message can contain up to 140 characters. This character limit depends on the encoding schema. For example, an SMS message can contain 160 GSM characters, 140 ASCII characters, or 70 UCS-2 characters.

      If you publish a message that exceeds this size limit, Amazon SNS sends the message as multiple messages, each fitting within the size limit. Messages aren't truncated mid-word but are cut off at whole-word boundaries.

      The total size limit for a single SMS Publish action is 1,600 characters.

    JSON-specific constraints:

    • Keys in the JSON object that correspond to supported transport protocols must have simple JSON string values.

    • The values will be parsed (unescaped) before they are used in outgoing messages.

    • Outbound notifications are JSON encoded (meaning that the characters will be reescaped for sending).

    • Values have a minimum length of 0 (the empty string, \"\", is allowed).

    • Values have a maximum length bounded by the overall message size (so, including multiple protocols may limit message sizes).

    • Non-string values will cause the key to be ignored.

    • Keys that do not correspond to supported transport protocols are ignored.

    • Duplicate keys are not allowed.

    • Failure to parse or validate any key or value in the message will cause the Publish call to return an error (no partial delivery).

    " + "documentation":"

    The message you want to send.

    If you are publishing to a topic and you want to send the same message to all transport protocols, include the text of the message as a String value. If you want to send different messages for each transport protocol, set the value of the MessageStructure parameter to json and use a JSON object for the Message parameter.

    Constraints:

    • With the exception of SMS, messages must be UTF-8 encoded strings. By default, a message can be at most 256 KiB in size (262,144 bytes, not 262,144 characters).

      When you publish to a topic, the maximum size is determined by the topic's MaximumMessageSize attribute, which supports values up to 1 MiB (1,048,576 bytes). Amazon SNS validates the combined size of the message body and message attributes against this value and returns an InvalidParameter error if the limit is exceeded.

      For more information, see Large message payloads in the Amazon SNS Developer Guide.

    • For SMS, each message can contain up to 140 characters. This character limit depends on the encoding schema. For example, an SMS message can contain 160 GSM characters, 140 ASCII characters, or 70 UCS-2 characters.

      If you publish a message that exceeds this size limit, Amazon SNS sends the message as multiple messages, each fitting within the size limit. Messages aren't truncated mid-word but are cut off at whole-word boundaries.

      The total size limit for a single SMS Publish action is 1,600 characters.

    JSON-specific constraints:

    • Keys in the JSON object that correspond to supported transport protocols must have simple JSON string values.

    • The values will be parsed (unescaped) before they are used in outgoing messages.

    • Outbound notifications are JSON encoded (meaning that the characters will be reescaped for sending).

    • Values have a minimum length of 0 (the empty string, \"\", is allowed).

    • Values have a maximum length bounded by the overall message size (so, including multiple protocols may limit message sizes).

    • Non-string values will cause the key to be ignored.

    • Keys that do not correspond to supported transport protocols are ignored.

    • Duplicate keys are not allowed.

    • Failure to parse or validate any key or value in the message will cause the Publish call to return an error (no partial delivery).

    " }, "Subject":{ "shape":"subject", @@ -2306,7 +2306,7 @@ }, "AttributeName":{ "shape":"attributeName", - "documentation":"

    A map of attributes with their corresponding values.

    The following lists the names, descriptions, and values of the special request parameters that the SetTopicAttributes action uses:

    • DeliveryPolicy – The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints.

    • DisplayName – The display name to use for a topic with SMS subscriptions.

    • Policy – The policy that defines who can access your topic. By default, only the topic owner can publish or subscribe to the topic.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    • HTTP

      • HTTPSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

    • Amazon Data Firehose

      • FirehoseSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

    • Lambda

      • LambdaSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

    • Platform application endpoint

      • ApplicationSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      In addition to being able to configure topic attributes for message delivery status of notification messages sent to Amazon SNS application endpoints, you can also configure application attributes for the delivery status of push notification messages sent to push notification services.

      For example, For more information, see Using Amazon SNS Application Attributes for Message Delivery Status.

    • Amazon SQS

      • SQSSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

    The <ENDPOINT>SuccessFeedbackRoleArn and <ENDPOINT>FailureFeedbackRoleArn attributes are used to give Amazon SNS write access to use CloudWatch Logs on your behalf. The <ENDPOINT>SuccessFeedbackSampleRate attribute is for specifying the sample rate percentage (0-100) of successfully delivered messages. After you configure the <ENDPOINT>FailureFeedbackRoleArn attribute, then all failed message deliveries generate CloudWatch Logs.

    The following attribute applies only to server-side-encryption:

    • KmsMasterKeyId – The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    • SignatureVersion – The signature version corresponds to the hashing algorithm used while creating the signature of the notifications, subscription confirmations, or unsubscribe confirmation messages sent by Amazon SNS. By default, SignatureVersion is set to 1.

    The following attribute applies only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoThroughputScope – Enables higher throughput for your FIFO topic by adjusting the scope of deduplication. This attribute has two possible values:

      • Topic – The scope of message deduplication is across the entire topic. This is the default value and maintains existing behavior, with a maximum throughput of 3000 messages per second or 20MB per second, whichever comes first.

      • MessageGroup – The scope of deduplication is within each individual message group, which enables higher throughput per topic subject to regional quotas. For more information on quotas or to request an increase, see Amazon SNS service quotas in the Amazon Web Services General Reference.

    " + "documentation":"

    A map of attributes with their corresponding values.

    The following lists the names, descriptions, and values of the special request parameters that the SetTopicAttributes action uses:

    • DeliveryPolicy – The policy that defines how Amazon SNS retries failed deliveries to HTTP/S endpoints.

    • DisplayName – The display name to use for a topic with SMS, email, and email-json subscriptions. For email and email-json subscriptions, the display name is used as the sender name for regular notification messages. Subscription confirmation and unsubscribe confirmation emails always use \"Amazon Web Services Notifications\" as the sender name.

    • MaximumMessageSize – The maximum size, in bytes, of a message that can be published to the topic. Valid values are 1024 to 1048576 (1 MiB). The default is 262144 (256 KiB).

      A topic with a MaximumMessageSize above 256 KiB must have 100 or fewer subscriptions, and each subscription must be an Amazon SQS, Amazon Data Firehose, or Lambda subscription.

      You can increase or decrease this value at any time. If the topic doesn't meet these requirements when you set a value above 256 KiB, Amazon SNS returns an InvalidParameter error. For more information, see Large message payloads in the Amazon SNS Developer Guide.

    • Policy – The policy that defines who can access your topic. By default, only the topic owner can publish or subscribe to the topic.

    • TracingConfig – Tracing mode of an Amazon SNS topic. By default TracingConfig is set to PassThrough, and the topic passes through the tracing header it receives from an Amazon SNS publisher to its subscriptions. If set to Active, Amazon SNS will vend X-Ray segment data to topic owner account if the sampled flag in the tracing header is true. This is only supported on standard topics.

    • HTTP

      • HTTPSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an HTTP endpoint.

      • HTTPFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an HTTP endpoint.

    • Amazon Data Firehose

      • FirehoseSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

      • FirehoseFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon Data Firehose endpoint.

    • Lambda

      • LambdaSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Lambda endpoint.

      • LambdaFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Lambda endpoint.

    • Platform application endpoint

      • ApplicationSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an platform application endpoint.

      • ApplicationFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an platform application endpoint.

      In addition to being able to configure topic attributes for message delivery status of notification messages sent to Amazon SNS application endpoints, you can also configure application attributes for the delivery status of push notification messages sent to push notification services.

      For example, For more information, see Using Amazon SNS Application Attributes for Message Delivery Status.

    • Amazon SQS

      • SQSSuccessFeedbackRoleArn – Indicates successful message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSSuccessFeedbackSampleRate – Indicates percentage of successful messages to sample for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

      • SQSFailureFeedbackRoleArn – Indicates failed message delivery status for an Amazon SNS topic that is subscribed to an Amazon SQS endpoint.

    The <ENDPOINT>SuccessFeedbackRoleArn and <ENDPOINT>FailureFeedbackRoleArn attributes are used to give Amazon SNS write access to use CloudWatch Logs on your behalf. The <ENDPOINT>SuccessFeedbackSampleRate attribute is for specifying the sample rate percentage (0-100) of successfully delivered messages. After you configure the <ENDPOINT>FailureFeedbackRoleArn attribute, then all failed message deliveries generate CloudWatch Logs.

    The following attribute applies only to server-side-encryption:

    • KmsMasterKeyId – The ID of an Amazon Web Services managed customer master key (CMK) for Amazon SNS or a custom CMK. For more information, see Key Terms. For more examples, see KeyId in the Key Management Service API Reference.

    • SignatureVersion – The signature version corresponds to the hashing algorithm used while creating the signature of the notifications, subscription confirmations, or unsubscribe confirmation messages sent by Amazon SNS. By default, SignatureVersion is set to 1.

    The following attribute applies only to FIFO topics:

    • ArchivePolicy – The policy that sets the retention period for messages stored in the message archive of an Amazon SNS FIFO topic.

    • ContentBasedDeduplication – Enables content-based deduplication for FIFO topics.

      • By default, ContentBasedDeduplication is set to false. If you create a FIFO topic and this attribute is false, you must specify a value for the MessageDeduplicationId parameter for the Publish action.

      • When you set ContentBasedDeduplication to true, Amazon SNS uses a SHA-256 hash to generate the MessageDeduplicationId using the body of the message (but not the attributes of the message).

        (Optional) To override the generated value, you can specify a value for the MessageDeduplicationId parameter for the Publish action.

    • FifoThroughputScope – Enables higher throughput for your FIFO topic by adjusting the scope of deduplication. This attribute has two possible values:

      • Topic – The scope of message deduplication is across the entire topic. This is the default value and maintains existing behavior, with a maximum throughput of 3000 messages per second or 20MB per second, whichever comes first.

      • MessageGroup – The scope of deduplication is within each individual message group, which enables higher throughput per topic subject to regional quotas. For more information on quotas or to request an increase, see Amazon SNS service quotas in the Amazon Web Services General Reference.

    " }, "AttributeValue":{ "shape":"attributeValue", diff --git a/services/socialmessaging/pom.xml b/services/socialmessaging/pom.xml index df1a9808b591..19268f866cf7 100644 --- a/services/socialmessaging/pom.xml +++ b/services/socialmessaging/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT socialmessaging AWS Java SDK :: Services :: Social Messaging diff --git a/services/socialmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/socialmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..84ce419f517c --- /dev/null +++ b/services/socialmessaging/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://social-messaging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://social-messaging-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://social-messaging.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://social-messaging.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/socialmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/socialmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index aaa153ce50b1..000000000000 --- a/services/socialmessaging/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://social-messaging-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://social-messaging-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://social-messaging.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://social-messaging.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/socialmessaging/src/main/resources/codegen-resources/service-2.json b/services/socialmessaging/src/main/resources/codegen-resources/service-2.json index 86ca15f94ca6..7a01700289e1 100644 --- a/services/socialmessaging/src/main/resources/codegen-resources/service-2.json +++ b/services/socialmessaging/src/main/resources/codegen-resources/service-2.json @@ -32,6 +32,28 @@ ], "documentation":"

    This is only used through the Amazon Web Services console during sign-up to associate your WhatsApp Business Account to your Amazon Web Services account.

    " }, + "CreateWhatsAppDataset":{ + "name":"CreateWhatsAppDataset", + "http":{ + "method":"POST", + "requestUri":"/v1/whatsapp/waba/dataset", + "responseCode":200 + }, + "input":{"shape":"CreateWhatsAppDatasetInput"}, + "output":{"shape":"CreateWhatsAppDatasetOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParametersException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Creates a Meta Conversions API dataset for a WhatsApp Business Account.

    ", + "idempotent":true + }, "CreateWhatsAppFlow":{ "name":"CreateWhatsAppFlow", "http":{ @@ -265,6 +287,49 @@ "documentation":"

    Retrieve the WABA account id and phone number details of a WhatsApp business account phone number.

    ", "readonly":true }, + "GetWhatsAppBusinessPublicKey":{ + "name":"GetWhatsAppBusinessPublicKey", + "http":{ + "method":"GET", + "requestUri":"/v1/whatsapp/business-public-key", + "responseCode":200 + }, + "input":{"shape":"GetWhatsAppBusinessPublicKeyInput"}, + "output":{"shape":"GetWhatsAppBusinessPublicKeyOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParametersException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Retrieves the business public key for a phone number and its signature status.

    ", + "readonly":true + }, + "GetWhatsAppCallPermission":{ + "name":"GetWhatsAppCallPermission", + "http":{ + "method":"POST", + "requestUri":"/v1/whatsapp/call/permission/get", + "responseCode":200 + }, + "input":{"shape":"GetWhatsAppCallPermissionInput"}, + "output":{"shape":"GetWhatsAppCallPermissionOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParametersException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Retrieves the current calling permission for a WhatsApp end user, along with the calling actions the business is allowed to take with that user. Provide the destination phone number or the business-scoped user ID to identify the end user.

    " + }, "GetWhatsAppFlow":{ "name":"GetWhatsAppFlow", "http":{ @@ -540,6 +605,71 @@ "documentation":"

    Add an event destination to log event data from WhatsApp for a WhatsApp Business Account (WABA). A WABA can only have one event destination at a time. All resources associated with the WABA use the same event destination.

    ", "idempotent":true }, + "PutWhatsAppBusinessPublicKey":{ + "name":"PutWhatsAppBusinessPublicKey", + "http":{ + "method":"PUT", + "requestUri":"/v1/whatsapp/business-public-key", + "responseCode":200 + }, + "input":{"shape":"PutWhatsAppBusinessPublicKeyInput"}, + "output":{"shape":"PutWhatsAppBusinessPublicKeyOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"InvalidParametersException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Sets the business public key used to encrypt the data exchanged with the endpoint of a data exchange Flow.

    ", + "idempotent":true + }, + "SendWhatsAppCallEvent":{ + "name":"SendWhatsAppCallEvent", + "http":{ + "method":"POST", + "requestUri":"/v1/whatsapp/call/event", + "responseCode":200 + }, + "input":{"shape":"SendWhatsAppCallEventInput"}, + "output":{"shape":"SendWhatsAppCallEventOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParametersException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Sends a WhatsApp calling event, such as connecting or terminating a call, for a business phone number. This operation passes the event through to Meta. To use this operation, the origination phone number must belong to a WhatsApp Business Account that is linked to your Amazon Web Services account.

    " + }, + "SendWhatsAppConversionEvent":{ + "name":"SendWhatsAppConversionEvent", + "http":{ + "method":"POST", + "requestUri":"/v1/whatsapp/waba/dataset/events", + "responseCode":200 + }, + "input":{"shape":"SendWhatsAppConversionEventInput"}, + "output":{"shape":"SendWhatsAppConversionEventOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParametersException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Sends a conversion event to Meta's Conversions API for the specified WhatsApp Business Account dataset.

    " + }, "SendWhatsAppMessage":{ "name":"SendWhatsAppMessage", "http":{ @@ -596,6 +726,28 @@ ], "documentation":"

    Removes the specified tags from a resource.

    " }, + "UpdateLinkedWhatsAppBusinessAccountPhoneNumber":{ + "name":"UpdateLinkedWhatsAppBusinessAccountPhoneNumber", + "http":{ + "method":"PUT", + "requestUri":"/v1/whatsapp/waba/phone", + "responseCode":200 + }, + "input":{"shape":"UpdateLinkedWhatsAppBusinessAccountPhoneNumberInput"}, + "output":{"shape":"UpdateLinkedWhatsAppBusinessAccountPhoneNumberOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InvalidParametersException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"AccessDeniedByMetaException"}, + {"shape":"ThrottledRequestException"}, + {"shape":"InternalServiceException"}, + {"shape":"DependencyException"} + ], + "documentation":"

    Updates the calling settings for a linked WhatsApp business phone number, such as whether calling is enabled and the hours during which the business accepts calls.

    ", + "idempotent":true + }, "UpdateWhatsAppFlow":{ "name":"UpdateWhatsAppFlow", "http":{ @@ -747,6 +899,16 @@ "type":"boolean", "box":true }, + "BusinessPublicKeyPem":{ + "type":"string", + "max":8192, + "min":1 + }, + "BusinessPublicKeySignatureStatus":{ + "type":"string", + "max":20, + "min":1 + }, "ButtonType":{ "type":"string", "max":25, @@ -756,6 +918,38 @@ "type":"integer", "box":true }, + "ConflictException":{ + "type":"structure", + "members":{ + "message":{"shape":"ErrorMessage"} + }, + "documentation":"

    Your request has conflicting operations. This can occur if you're trying to perform more than one operation on the same resource at the same time.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, + "exception":true + }, + "CreateWhatsAppDatasetInput":{ + "type":"structure", + "required":["id"], + "members":{ + "id":{ + "shape":"LinkedWhatsAppBusinessAccountId", + "documentation":"

    The ID of the WhatsApp Business Account to create a dataset for, formatted as waba-01234567890123456789012345678901.

    " + } + } + }, + "CreateWhatsAppDatasetOutput":{ + "type":"structure", + "required":["datasetId"], + "members":{ + "datasetId":{ + "shape":"WhatsAppDatasetId", + "documentation":"

    The Meta-generated dataset ID, a numeric string of 10 to 20 digits.

    " + } + } + }, "CreateWhatsAppFlowInput":{ "type":"structure", "required":[ @@ -787,6 +981,10 @@ "cloneFlowId":{ "shape":"MetaFlowId", "documentation":"

    The ID of an existing Flow within the same WhatsApp Business Account to clone.

    " + }, + "endpointUri":{ + "shape":"MetaFlowEndpointUri", + "documentation":"

    The HTTPS endpoint that Meta calls for a data exchange Flow.

    " } } }, @@ -1099,6 +1297,70 @@ "linkedWhatsAppBusinessAccountId":{ "shape":"LinkedWhatsAppBusinessAccountId", "documentation":"

    The WABA identifier linked to the phone number, formatted as waba-01234567890123456789012345678901.

    " + }, + "callSettings":{ + "shape":"WhatsAppCallSettings", + "documentation":"

    The calling settings configured for the phone number. This value is absent when calling is not configured.

    " + } + } + }, + "GetWhatsAppBusinessPublicKeyInput":{ + "type":"structure", + "required":["originationPhoneNumberId"], + "members":{ + "originationPhoneNumberId":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the phone number whose business public key to retrieve.

    ", + "location":"querystring", + "locationName":"originationPhoneNumberId" + } + } + }, + "GetWhatsAppBusinessPublicKeyOutput":{ + "type":"structure", + "members":{ + "businessPublicKey":{ + "shape":"BusinessPublicKeyPem", + "documentation":"

    The stored PEM-encoded 2048-bit RSA public key.

    " + }, + "businessPublicKeySignatureStatus":{ + "shape":"BusinessPublicKeySignatureStatus", + "documentation":"

    The signature status of the stored business public key. Valid values are VALID and MISMATCH.

    " + } + } + }, + "GetWhatsAppCallPermissionInput":{ + "type":"structure", + "required":["originationPhoneNumberId"], + "members":{ + "originationPhoneNumberId":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the business phone number for which to retrieve the calling permission. The phone number identifiers are formatted as phone-number-id-01234567890123456789012345678901.

    " + }, + "destinationPhoneNumber":{ + "shape":"WhatsAppDestinationPhoneNumber", + "documentation":"

    The end user's phone number, in E.164 format, for which to retrieve the calling permission.

    " + }, + "endUserBsuid":{ + "shape":"WhatsAppBusinessScopedUserId", + "documentation":"

    The business-scoped user identifier (BSUID) of the end user for which to retrieve the calling permission.

    " + } + } + }, + "GetWhatsAppCallPermissionOutput":{ + "type":"structure", + "required":[ + "permission", + "actions" + ], + "members":{ + "permission":{ + "shape":"WhatsAppCallPermission", + "documentation":"

    The current calling permission state for the end user.

    " + }, + "actions":{ + "shape":"WhatsAppCallPermissionActionList", + "documentation":"

    The calling actions the business can take with the end user, and any limits that apply to each action.

    " } } }, @@ -1161,7 +1423,7 @@ }, "endpointUri":{ "shape":"MetaFlowEndpointUri", - "documentation":"

    The endpoint URI for data exchange Flows, if configured.

    " + "documentation":"

    The HTTPS endpoint that Meta calls for a data exchange Flow.

    " }, "preview":{ "shape":"MetaFlowPreviewInfo", @@ -1311,6 +1573,11 @@ "key":{"shape":"String"}, "value":{"shape":"String"} }, + "IanaTimezone":{ + "type":"string", + "max":100, + "min":1 + }, "Integer":{ "type":"integer", "box":true @@ -1338,10 +1605,21 @@ }, "exception":true }, + "Iso8601Duration":{ + "type":"string", + "max":20, + "min":1 + }, "IsoCountryCode":{ "type":"string", "pattern":"[A-Z]{2}" }, + "KmsKeyArn":{ + "type":"string", + "max":256, + "min":1, + "pattern":"arn:aws[a-z-]*:kms:[a-z0-9-]+:[0-9]{12}:(key/.+|alias/.+)" + }, "LibraryTemplateBodyInputs":{ "type":"structure", "members":{ @@ -1494,6 +1772,10 @@ "shape":"WhatsAppBusinessAccountMarketingMessagesOnboardingStatus", "documentation":"

    The onboarding status for the Marketing Messages API. This value is fetched from Meta and indicates whether the WhatsApp Business Account is onboarded for Meta's Marketing Messages API.

    " }, + "datasetId":{ + "shape":"WhatsAppDatasetId", + "documentation":"

    The Meta Conversions API dataset ID associated with this WhatsApp Business Account. This value is a numeric string of 10 to 20 digits. This field is not present when no dataset has been created for this account.

    " + }, "phoneNumbers":{ "shape":"WhatsAppPhoneNumberSummaryList", "documentation":"

    The phone numbers associated with the Linked WhatsApp Business Account.

    " @@ -1578,6 +1860,10 @@ "marketingMessagesOnboardingStatus":{ "shape":"WhatsAppBusinessAccountMarketingMessagesOnboardingStatus", "documentation":"

    The onboarding status for the Marketing Messages API. This value is fetched from Meta and indicates whether the WhatsApp Business Account is onboarded for Meta's Marketing Messages API.

    " + }, + "datasetId":{ + "shape":"WhatsAppDatasetId", + "documentation":"

    The Meta Conversions API dataset ID associated with this WhatsApp Business Account. This value is a numeric string of 10 to 20 digits. This field is not present when no dataset has been created for this account.

    " } }, "documentation":"

    The details of a linked WhatsApp Business Account.

    " @@ -2416,6 +2702,28 @@ "type":"structure", "members":{} }, + "PutWhatsAppBusinessPublicKeyInput":{ + "type":"structure", + "required":["originationPhoneNumberId"], + "members":{ + "originationPhoneNumberId":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the phone number to associate with the business public key.

    " + }, + "businessPublicKey":{ + "shape":"BusinessPublicKeyPem", + "documentation":"

    The PEM-encoded 2048-bit RSA public key to set. Mutually exclusive with kmsKeyArn.

    " + }, + "kmsKeyArn":{ + "shape":"KmsKeyArn", + "documentation":"

    The ARN of a customer managed asymmetric RSA key in Amazon Web Services KMS. Mutually exclusive with businessPublicKey.

    " + } + } + }, + "PutWhatsAppBusinessPublicKeyOutput":{ + "type":"structure", + "members":{} + }, "RegistrationStatus":{ "type":"string", "enum":[ @@ -2494,6 +2802,70 @@ "min":1, "pattern":"https://(.*)s3(.*).amazonaws.com/(.*)" }, + "SendWhatsAppCallEventInput":{ + "type":"structure", + "required":[ + "originationPhoneNumberId", + "metaApiVersion", + "callEvent" + ], + "members":{ + "originationPhoneNumberId":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the origination phone number for the call. The phone number identifiers are formatted as phone-number-id-01234567890123456789012345678901. Use GetLinkedWhatsAppBusinessAccount to find a phone number's ID.

    " + }, + "metaApiVersion":{ + "shape":"String", + "documentation":"

    The version of the Meta Graph API to use for the request.

    " + }, + "callEvent":{ + "shape":"WhatsAppCallEventBlob", + "documentation":"

    The call event payload to send, as a JSON blob in the format defined by the Meta calling API.

    " + } + } + }, + "SendWhatsAppCallEventOutput":{ + "type":"structure", + "required":["callId"], + "members":{ + "callId":{ + "shape":"String", + "documentation":"

    The unique identifier that Meta assigns to the call.

    " + } + } + }, + "SendWhatsAppConversionEventInput":{ + "type":"structure", + "required":[ + "id", + "datasetId", + "eventData" + ], + "members":{ + "id":{ + "shape":"LinkedWhatsAppBusinessAccountId", + "documentation":"

    The ID of the WhatsApp Business Account associated with the dataset, formatted as waba-01234567890123456789012345678901.

    " + }, + "datasetId":{ + "shape":"WhatsAppDatasetId", + "documentation":"

    The Meta-generated dataset ID to send the event to.

    " + }, + "eventData":{ + "shape":"WhatsAppConversionEventBlob", + "documentation":"

    The raw Meta Conversions API event payload as a JSON blob. See Meta's server event parameters for the supported format.

    " + } + } + }, + "SendWhatsAppConversionEventOutput":{ + "type":"structure", + "required":["requestId"], + "members":{ + "requestId":{ + "shape":"String", + "documentation":"

    The unique identifier for the conversion event request.

    " + } + } + }, "SendWhatsAppMessageInput":{ "type":"structure", "required":[ @@ -2653,6 +3025,7 @@ "exception":true, "retryable":{"throttling":false} }, + "Timestamp":{"type":"timestamp"}, "TwoFactorPin":{ "type":"string", "max":6, @@ -2685,6 +3058,35 @@ } } }, + "UpdateLinkedWhatsAppBusinessAccountPhoneNumberInput":{ + "type":"structure", + "required":[ + "id", + "callSettings" + ], + "members":{ + "id":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the phone number to update. The phone number identifiers are formatted as phone-number-id-01234567890123456789012345678901.

    ", + "location":"querystring", + "locationName":"id" + }, + "callSettings":{ + "shape":"WhatsAppCallSettings", + "documentation":"

    The calling settings to apply to the phone number.

    " + } + } + }, + "UpdateLinkedWhatsAppBusinessAccountPhoneNumberOutput":{ + "type":"structure", + "required":["phoneNumberId"], + "members":{ + "phoneNumberId":{ + "shape":"WhatsAppPhoneNumberId", + "documentation":"

    The unique identifier of the phone number that was updated.

    " + } + } + }, "UpdateWhatsAppFlowAssetsInput":{ "type":"structure", "required":[ @@ -2738,6 +3140,14 @@ "categories":{ "shape":"MetaFlowCategoryList", "documentation":"

    The updated categories for the Flow.

    " + }, + "endpointUri":{ + "shape":"MetaFlowEndpointUri", + "documentation":"

    The updated HTTPS endpoint for a data exchange Flow.

    " + }, + "metaAppId":{ + "shape":"MetaFlowApplicationId", + "documentation":"

    The ID of the Meta application to attach to the Flow.

    " } } }, @@ -2888,11 +3298,234 @@ "max":200, "min":0 }, + "WhatsAppBusinessScopedUserId":{ + "type":"string", + "max":100, + "min":1, + "sensitive":true + }, + "WhatsAppCallEventBlob":{ + "type":"blob", + "max":2048000, + "min":1, + "sensitive":true + }, + "WhatsAppCallHours":{ + "type":"structure", + "required":[ + "enabled", + "timezone", + "weeklyOperatingHours" + ], + "members":{ + "enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether call hours are enforced. When disabled, the business accepts calls at any time.

    " + }, + "timezone":{ + "shape":"IanaTimezone", + "documentation":"

    The IANA time zone in which the operating hours are interpreted, such as America/New_York.

    " + }, + "weeklyOperatingHours":{ + "shape":"WhatsAppWeeklyOperatingHoursList", + "documentation":"

    The weekly schedule of hours during which the business accepts calls.

    " + }, + "holidaySchedule":{ + "shape":"WhatsAppHolidayScheduleList", + "documentation":"

    Date-specific overrides to the weekly operating hours, such as holidays.

    " + } + }, + "documentation":"

    The operating hours during which a business phone number accepts WhatsApp calls, including the time zone, weekly schedule, and any holiday overrides.

    " + }, + "WhatsAppCallIconVisibility":{ + "type":"string", + "max":50, + "min":1 + }, + "WhatsAppCallPermission":{ + "type":"structure", + "required":["status"], + "members":{ + "status":{ + "shape":"WhatsAppCallPermissionStatus", + "documentation":"

    The permission status for the end user.

    " + }, + "expirationTime":{ + "shape":"Timestamp", + "documentation":"

    The time when a temporary permission expires. This value is absent for permanent permissions and when there is no permission.

    " + } + }, + "documentation":"

    The current calling permission state for a business phone number and a specific WhatsApp end user.

    " + }, + "WhatsAppCallPermissionAction":{ + "type":"structure", + "required":[ + "actionName", + "canPerformAction", + "limits" + ], + "members":{ + "actionName":{ + "shape":"WhatsAppCallPermissionActionName", + "documentation":"

    The name of the calling action.

    " + }, + "canPerformAction":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the business can currently perform the action.

    " + }, + "limits":{ + "shape":"WhatsAppCallPermissionLimitList", + "documentation":"

    The time-bound limits that apply to the action.

    " + } + }, + "documentation":"

    Describes a single calling action the business can take with an end user, including whether the action is currently allowed and any limits that apply to it. Returned as an item in the actions list from GetWhatsAppCallPermission.

    " + }, + "WhatsAppCallPermissionActionList":{ + "type":"list", + "member":{"shape":"WhatsAppCallPermissionAction"} + }, + "WhatsAppCallPermissionActionName":{ + "type":"string", + "max":50, + "min":1 + }, + "WhatsAppCallPermissionLimit":{ + "type":"structure", + "required":[ + "timePeriod", + "maxAllowed", + "currentUsage" + ], + "members":{ + "timePeriod":{ + "shape":"Iso8601Duration", + "documentation":"

    The time period over which the limit applies, as an ISO 8601 duration.

    " + }, + "maxAllowed":{ + "shape":"Integer", + "documentation":"

    The maximum number of times the action is allowed within the time period.

    " + }, + "currentUsage":{ + "shape":"Integer", + "documentation":"

    The number of times the action has been used within the current time period.

    " + }, + "limitExpirationTime":{ + "shape":"Timestamp", + "documentation":"

    The time when the limit resets. This value is present only when the current usage has reached the maximum allowed.

    " + } + }, + "documentation":"

    A time-bound restriction on a calling action, such as the number of calls allowed within a time period.

    " + }, + "WhatsAppCallPermissionLimitList":{ + "type":"list", + "member":{"shape":"WhatsAppCallPermissionLimit"}, + "max":10, + "min":0 + }, + "WhatsAppCallPermissionStatus":{ + "type":"string", + "max":50, + "min":1 + }, + "WhatsAppCallSettings":{ + "type":"structure", + "required":["callEnabled"], + "members":{ + "callEnabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether calling is enabled for the phone number.

    " + }, + "callHours":{ + "shape":"WhatsAppCallHours", + "documentation":"

    The hours during which the business accepts calls on the phone number.

    " + }, + "callIconVisibility":{ + "shape":"WhatsAppCallIconVisibility", + "documentation":"

    The visibility setting for the call icon shown to end users in WhatsApp.

    " + }, + "callbackPermissionStatus":{ + "shape":"WhatsAppCallbackPermissionStatus", + "documentation":"

    The callback permission status for the phone number.

    " + } + }, + "documentation":"

    The calling configuration for a WhatsApp business phone number.

    " + }, + "WhatsAppCallbackPermissionStatus":{ + "type":"string", + "max":50, + "min":1 + }, + "WhatsAppConversionEventBlob":{ + "type":"blob", + "max":1024000, + "min":1, + "sensitive":true + }, + "WhatsAppDatasetId":{ + "type":"string", + "max":20, + "min":10, + "pattern":"[0-9]+" + }, + "WhatsAppDate":{ + "type":"string", + "max":10, + "min":10, + "pattern":"[0-9]{4}-[0-9]{2}-[0-9]{2}" + }, + "WhatsAppDayOfWeek":{ + "type":"string", + "enum":[ + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", + "SUNDAY" + ] + }, + "WhatsAppDestinationPhoneNumber":{ + "type":"string", + "max":20, + "min":1, + "pattern":"\\+[1-9]\\d{1,14}", + "sensitive":true + }, "WhatsAppDisplayPhoneNumber":{ "type":"string", "max":20, "min":0 }, + "WhatsAppHolidayScheduleEntry":{ + "type":"structure", + "required":[ + "date", + "startTime", + "endTime" + ], + "members":{ + "date":{ + "shape":"WhatsAppDate", + "documentation":"

    The date that the override applies to, in ISO 8601 format (YYYY-MM-DD).

    " + }, + "startTime":{ + "shape":"WhatsAppTimeOfDay", + "documentation":"

    The time of day when the business begins accepting calls on the override date.

    " + }, + "endTime":{ + "shape":"WhatsAppTimeOfDay", + "documentation":"

    The time of day when the business stops accepting calls on the override date.

    " + } + }, + "documentation":"

    A date-specific override to the weekly operating hours, such as a holiday.

    " + }, + "WhatsAppHolidayScheduleList":{ + "type":"list", + "member":{"shape":"WhatsAppHolidayScheduleEntry"}, + "max":20, + "min":0 + }, "WhatsAppMediaId":{ "type":"string", "max":100, @@ -3093,6 +3726,65 @@ }, "documentation":"

    Contains the results of WhatsAppSignupCallback.

    " }, + "WhatsAppTimeOfDay":{ + "type":"structure", + "required":[ + "hours", + "minutes" + ], + "members":{ + "hours":{ + "shape":"WhatsAppTimeOfDayHoursInteger", + "documentation":"

    The hour of the day, from 0 to 23.

    " + }, + "minutes":{ + "shape":"WhatsAppTimeOfDayMinutesInteger", + "documentation":"

    The minute of the hour, from 0 to 59.

    " + } + }, + "documentation":"

    A time of day, expressed as an hour and minute.

    " + }, + "WhatsAppTimeOfDayHoursInteger":{ + "type":"integer", + "box":true, + "max":23, + "min":0 + }, + "WhatsAppTimeOfDayMinutesInteger":{ + "type":"integer", + "box":true, + "max":59, + "min":0 + }, + "WhatsAppWeeklyOperatingHoursEntry":{ + "type":"structure", + "required":[ + "dayOfWeek", + "openTime", + "closeTime" + ], + "members":{ + "dayOfWeek":{ + "shape":"WhatsAppDayOfWeek", + "documentation":"

    The day of the week that the entry applies to.

    " + }, + "openTime":{ + "shape":"WhatsAppTimeOfDay", + "documentation":"

    The time of day when the business begins accepting calls.

    " + }, + "closeTime":{ + "shape":"WhatsAppTimeOfDay", + "documentation":"

    The time of day when the business stops accepting calls.

    " + } + }, + "documentation":"

    A single entry in a weekly calling schedule, defining the open and close times for one day of the week.

    " + }, + "WhatsAppWeeklyOperatingHoursList":{ + "type":"list", + "member":{"shape":"WhatsAppWeeklyOperatingHoursEntry"}, + "max":14, + "min":0 + }, "ZeroTapTermsAccepted":{ "type":"boolean", "box":true diff --git a/services/sqs/pom.xml b/services/sqs/pom.xml index 290039487197..391f30219fc8 100644 --- a/services/sqs/pom.xml +++ b/services/sqs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sqs AWS Java SDK :: Services :: Amazon SQS diff --git a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.java b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.java index d8d54f718a59..14f7756a7d8d 100644 --- a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.java +++ b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/batchmanager/SqsAsyncBatchManager.java @@ -148,6 +148,13 @@ default CompletableFuture receiveMessage( return receiveMessage(ReceiveMessageRequest.builder().applyMutation(request).build()); } + /** + * Closes the batch manager and releases its resources. Buffered requests are first flushed to the service, then + * this method blocks for up to a bounded timeout waiting for the in-flight batch sends to complete so their + * callers receive the real service result. Requests still outstanding when the timeout expires are cancelled. + */ + @Override + void close(); interface Builder { diff --git a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManager.java b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManager.java index 08300d485249..f3b0fbb264d5 100644 --- a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManager.java +++ b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManager.java @@ -18,9 +18,18 @@ import static software.amazon.awssdk.services.sqs.internal.batchmanager.ResponseBatchConfiguration.MAX_SEND_MESSAGE_PAYLOAD_SIZE_BYTES; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.services.sqs.SqsAsyncClient; import software.amazon.awssdk.services.sqs.batchmanager.BatchOverrideConfiguration; import software.amazon.awssdk.services.sqs.batchmanager.SqsAsyncBatchManager; @@ -32,10 +41,13 @@ import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse; import software.amazon.awssdk.services.sqs.model.SendMessageRequest; import software.amazon.awssdk.services.sqs.model.SendMessageResponse; +import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Validate; @SdkInternalApi public final class DefaultSqsAsyncBatchManager implements SqsAsyncBatchManager { + private static final Logger log = Logger.loggerFor(DefaultSqsAsyncBatchManager.class); + private final SqsAsyncClient client; private final SendMessageBatchManager sendMessageBatchManager; @@ -46,6 +58,10 @@ public final class DefaultSqsAsyncBatchManager implements SqsAsyncBatchManager { private final ReceiveMessageBatchManager receiveMessageBatchManager; + private final List> requestBatchManagers; + + private final AtomicBoolean closed = new AtomicBoolean(false); + private DefaultSqsAsyncBatchManager(DefaultBuilder builder) { this.client = Validate.notNull(builder.client, "client cannot be null"); ScheduledExecutorService scheduledExecutor = Validate.notNull(builder.scheduledExecutor, @@ -54,6 +70,7 @@ private DefaultSqsAsyncBatchManager(DefaultBuilder builder) { new SendMessageBatchManager( RequestBatchConfiguration.builder(builder.overrideConfiguration) .maxBatchBytesSize(MAX_SEND_MESSAGE_PAYLOAD_SIZE_BYTES) + .shutdownTimeout(builder.shutdownTimeout) .build(), scheduledExecutor, client @@ -61,18 +78,27 @@ private DefaultSqsAsyncBatchManager(DefaultBuilder builder) { this.deleteMessageBatchManager = new DeleteMessageBatchManager( - RequestBatchConfiguration.builder(builder.overrideConfiguration).build(), + RequestBatchConfiguration.builder(builder.overrideConfiguration) + .shutdownTimeout(builder.shutdownTimeout) + .build(), scheduledExecutor, client ); this.changeMessageVisibilityBatchManager = new ChangeMessageVisibilityBatchManager( - RequestBatchConfiguration.builder(builder.overrideConfiguration).build(), + RequestBatchConfiguration.builder(builder.overrideConfiguration) + .shutdownTimeout(builder.shutdownTimeout) + .build(), scheduledExecutor, client ); + requestBatchManagers = new ArrayList<>(3); + requestBatchManagers.add(sendMessageBatchManager); + requestBatchManagers.add(deleteMessageBatchManager); + requestBatchManagers.add(changeMessageVisibilityBatchManager); + this.receiveMessageBatchManager = new ReceiveMessageBatchManager(client, scheduledExecutor, @@ -105,20 +131,49 @@ public static SqsAsyncBatchManager.Builder builder() { @Override public void close() { - sendMessageBatchManager.close(); - deleteMessageBatchManager.close(); - changeMessageVisibilityBatchManager.close(); + if (!closed.compareAndSet(false, true)) { + return; + } + + List> futures = + requestBatchManagers.stream().map(requestBatchManager -> requestBatchManager.closeAndDispatch()) + .collect(Collectors.toList()); + + awaitQuietly(CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])), + sendMessageBatchManager.shutdownTimeout()); + + requestBatchManagers.forEach(requestBatchManager -> requestBatchManager.cancelPending()); receiveMessageBatchManager.close(); } + private static void awaitQuietly(CompletableFuture pending, Duration timeout) { + try { + pending.get(timeout.toMillis(), TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (TimeoutException e) { + log.debug(() -> "Timed out waiting for in-flight batch sends to complete during close; " + + "cancelling outstanding requests."); + } catch (ExecutionException e) { + // A send failed; its caller future is already settled with the failure. Nothing to do here. + } + } + public static final class DefaultBuilder implements SqsAsyncBatchManager.Builder { private SqsAsyncClient client; private BatchOverrideConfiguration overrideConfiguration; private ScheduledExecutorService scheduledExecutor; + private Duration shutdownTimeout; private DefaultBuilder() { } + @SdkTestInternalApi + DefaultBuilder shutdownTimeout(Duration shutdownTimeout) { + this.shutdownTimeout = shutdownTimeout; + return this; + } + @Override public SqsAsyncBatchManager.Builder overrideConfiguration(BatchOverrideConfiguration overrideConfiguration) { this.overrideConfiguration = overrideConfiguration; diff --git a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchConfiguration.java b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchConfiguration.java index 08cd1c0818ce..d6d7583baad0 100644 --- a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchConfiguration.java +++ b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchConfiguration.java @@ -28,11 +28,18 @@ public final class RequestBatchConfiguration { public static final int DEFAULT_MAX_BUFFER_SIZE = 500; public static final Duration DEFAULT_MAX_BATCH_OPEN_IN_MS = Duration.ofMillis(200); + /** + * Time {@code close()} waits for in-flight batch sends to complete so their callers receive real results before + * outstanding requests are cancelled. + */ + public static final Duration DEFAULT_SHUTDOWN_TIMEOUT = Duration.ofSeconds(5); + private final Integer maxBatchItems; private final Integer maxBatchKeys; private final Integer maxBufferSize; private final Duration sendRequestFrequency; private final Integer maxBatchBytesSize; + private final Duration shutdownTimeout; private RequestBatchConfiguration(Builder builder) { @@ -43,6 +50,8 @@ private RequestBatchConfiguration(Builder builder) { builder.sendRequestFrequency : DEFAULT_MAX_BATCH_OPEN_IN_MS; this.maxBatchBytesSize = builder.maxBatchBytesSize != null ? builder.maxBatchBytesSize : DEFAULT_MAX_BATCH_BYTES_SIZE; + this.shutdownTimeout = builder.shutdownTimeout != null ? + builder.shutdownTimeout : DEFAULT_SHUTDOWN_TIMEOUT; } @@ -80,6 +89,10 @@ public int maxBatchBytesSize() { return maxBatchBytesSize; } + public Duration shutdownTimeout() { + return shutdownTimeout; + } + public static final class Builder { private Integer maxBatchItems; @@ -87,6 +100,7 @@ public static final class Builder { private Integer maxBufferSize; private Duration sendRequestFrequency; private Integer maxBatchBytesSize; + private Duration shutdownTimeout; private Builder() { } @@ -116,6 +130,11 @@ public Builder maxBatchBytesSize(Integer maxBatchBytesSize) { return this; } + public Builder shutdownTimeout(Duration shutdownTimeout) { + this.shutdownTimeout = shutdownTimeout; + return this; + } + public RequestBatchConfiguration build() { return new RequestBatchConfiguration(this); } diff --git a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchManager.java b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchManager.java index dd1de65cd2c9..0bbaaba1d9f7 100644 --- a/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchManager.java +++ b/services/sqs/src/main/java/software/amazon/awssdk/services/sqs/internal/batchmanager/RequestBatchManager.java @@ -26,6 +26,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; @@ -36,7 +37,6 @@ @SdkInternalApi public abstract class RequestBatchManager { - // abm stands for Automatic Batching Manager public static final Consumer USER_AGENT_APPLIER = b -> b.addApiName(ApiName.builder().version("abm").name("hll").build()); @@ -45,10 +45,12 @@ public abstract class RequestBatchManager { private final int maxBatchItems; private final Duration sendRequestFrequency; + private final Duration shutdownTimeout; private final BatchingMap requestsAndResponsesMaps; private final ScheduledExecutorService scheduledExecutor; private final Set> pendingBatchResponses ; private final Set> pendingResponses ; + private final AtomicBoolean closed = new AtomicBoolean(false); protected RequestBatchManager(RequestBatchConfiguration overrideConfiguration, @@ -56,6 +58,7 @@ protected RequestBatchManager(RequestBatchConfiguration overrideConfiguration, batchConfiguration = overrideConfiguration; this.maxBatchItems = batchConfiguration.maxBatchItems(); this.sendRequestFrequency = batchConfiguration.sendRequestFrequency(); + this.shutdownTimeout = batchConfiguration.shutdownTimeout(); this.scheduledExecutor = Validate.notNull(scheduledExecutor, "Null scheduledExecutor"); pendingBatchResponses = ConcurrentHashMap.newKeySet(); pendingResponses = ConcurrentHashMap.newKeySet(); @@ -65,6 +68,10 @@ protected RequestBatchManager(RequestBatchConfiguration overrideConfiguration, public CompletableFuture batchRequest(RequestT request) { CompletableFuture response = new CompletableFuture<>(); + if (closed.get()) { + response.completeExceptionally(new IllegalStateException("The client has been shut down.")); + return response; + } pendingResponses.add(response); response.whenComplete((r, t) -> pendingResponses.remove(response)); @@ -160,20 +167,45 @@ private void performScheduledFlush(String batchKey) { } } - public void close() { + /** + * Phase 1 of shutdown, non-blocking. Marks the manager closed, dispatches every buffered batch (each exactly + * once), and returns a future that completes when all in-flight sends dispatched here have completed, so the + * caller can wait on it. Does not block and does not cancel; a second call is a no-op that returns an + * already-completed future. + */ + protected CompletableFuture closeAndDispatch() { + if (!closed.compareAndSet(false, true)) { + return CompletableFuture.completedFuture(null); + } + drainBuffers(); + List> snapshot = new ArrayList<>(pendingResponses); + return CompletableFuture.allOf(snapshot.toArray(new CompletableFuture[0])); + } + + /** + * Phase 2 of shutdown. Cancels any requests still pending after the timeout, surfacing + * {@link java.util.concurrent.CancellationException} to their callers, and releases the buffers. Idempotent. + */ + protected void cancelPending() { + pendingResponses.forEach(future -> future.cancel(true)); + pendingBatchResponses.forEach(future -> future.cancel(true)); + requestsAndResponsesMaps.clear(); + } + + protected Duration shutdownTimeout() { + return shutdownTimeout; + } + + private void drainBuffers() { requestsAndResponsesMaps.forEach((batchKey, batchBuffer) -> { requestsAndResponsesMaps.cancelScheduledFlush(batchKey); - Map> - extractedEntries = requestsAndResponsesMaps.extractBatchIfReady(batchKey); - + Map> extractedEntries = + requestsAndResponsesMaps.extractEntriesForScheduledFlush(batchKey, maxBatchItems); while (!extractedEntries.isEmpty()) { flushBuffer(batchKey, extractedEntries); + extractedEntries = requestsAndResponsesMaps.extractEntriesForScheduledFlush(batchKey, maxBatchItems); } - }); - pendingBatchResponses.forEach(future -> future.cancel(true)); - pendingResponses.forEach(future -> future.cancel(true)); - requestsAndResponsesMaps.clear(); } } \ No newline at end of file diff --git a/services/sqs/src/main/resources/codegen-resources/customization.config b/services/sqs/src/main/resources/codegen-resources/customization.config index 1e0dd0cada26..44848a1e3b7a 100644 --- a/services/sqs/src/main/resources/codegen-resources/customization.config +++ b/services/sqs/src/main/resources/codegen-resources/customization.config @@ -11,6 +11,5 @@ "type": "boolean" } }, - "enableGenerateCompiledEndpointRules": true, "batchManagerSupported": true } diff --git a/services/sqs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sqs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c85760070b54 --- /dev/null +++ b/services/sqs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sqs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sqs.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sqs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sqs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sqs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sqs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sqs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a8e2f9752871..000000000000 --- a/services/sqs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sqs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://sqs.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sqs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sqs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sqs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/batchmanager/RequestBatchManagerTest.java b/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/batchmanager/RequestBatchManagerTest.java index c82984bbecd1..b7d1e3f928f7 100644 --- a/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/batchmanager/RequestBatchManagerTest.java +++ b/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/batchmanager/RequestBatchManagerTest.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; @@ -152,54 +151,6 @@ void batchRequest_WithNetworkError_throwsException() throws Exception { assertThrows(ExecutionException.class, () -> response.get(1, TimeUnit.SECONDS)); } - @Test - void close_FlushesAllBatches() throws Exception { - String request1 = "testRequest:0"; - String batchKey = "testRequest"; - String request2 = "testRequest:1"; - CompletableFuture batchResponseFuture = CompletableFuture.completedFuture(batchedResponse(2, - "testResponse")); - - when(mockClient.sendBatchAsync(any(), eq(batchKey))).thenReturn(batchResponseFuture); - - SampleBatchManager batchManager= - new SampleBatchManager(BatchOverrideConfiguration.builder().maxBatchSize(2).sendRequestFrequency(Duration.ofHours(1)).build(), scheduledExecutor, mockClient); - - CompletableFuture response1 = batchManager.batchRequest(request1); - CompletableFuture response2 = batchManager.batchRequest(request2); - // Even though the mock returns results immediately, since this is asynchronous execution, the test environment may take - // additional time due to the Scheduled Executors execution on that machine. - Thread.sleep(200); - batchManager.close(); - - assertEquals("testResponse0", response1.get(1, TimeUnit.SECONDS)); - - assertEquals("testResponse1", response2.get(1, TimeUnit.SECONDS)); - } - - - @Test - void batchRequest_ClosedWhenWaitingForResponse() throws Exception { - String request = "testRequest:1"; - String batchKey = "testRequest"; - CompletableFuture batchResponseFuture = new CompletableFuture<>(); - - // Simulate successful response with delay - scheduledExecutor.schedule(() -> batchResponseFuture.complete(batchedResponse(1, "testResponse")), - 10, TimeUnit.HOURS); - - when(mockClient.sendBatchAsync(any(), eq(batchKey))).thenReturn(batchResponseFuture); - - SampleBatchManager batchManager = - new SampleBatchManager(BatchOverrideConfiguration.builder().maxBatchSize(1).build(), scheduledExecutor, mockClient); - CompletableFuture response = batchManager.batchRequest(request); - - batchManager.close(); - assertThrows(CancellationException.class, () -> response.join()); - - } - - @Test void batchRequest_MoreThanBufferSize_Fails() throws Exception { final int MAX_QUEUES_THRESHOLD = 10000; diff --git a/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManagerTest.java b/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManagerTest.java new file mode 100644 index 000000000000..7d558d41b5e2 --- /dev/null +++ b/services/sqs/src/test/java/software/amazon/awssdk/services/sqs/internal/batchmanager/DefaultSqsAsyncBatchManagerTest.java @@ -0,0 +1,201 @@ +/* + * 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.sqs.internal.batchmanager; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.time.Duration; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import software.amazon.awssdk.services.sqs.SqsAsyncClient; +import software.amazon.awssdk.services.sqs.batchmanager.BatchOverrideConfiguration; +import software.amazon.awssdk.services.sqs.batchmanager.SqsAsyncBatchManager; +import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityBatchRequest; +import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityBatchResponse; +import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest; +import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchResponse; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; +import software.amazon.awssdk.services.sqs.model.SendMessageBatchResultEntry; +import software.amazon.awssdk.services.sqs.model.SendMessageResponse; + +/** + * Close/shutdown behavior of the real {@link DefaultSqsAsyncBatchManager} (and, through it, the real write batch + * managers), driven over a mock {@link SqsAsyncClient} whose batch-send futures the test controls. Lives in the + * internal package to reach the package-private {@link DefaultSqsAsyncBatchManager.DefaultBuilder#shutdownTimeout} + * test seam so a short timeout can be injected. + */ +class DefaultSqsAsyncBatchManagerTest { + + private static final String QUEUE_URL = "https://sqs.us-east-1.amazonaws.com/123456789012/q"; + + private ScheduledExecutorService executor; + + @BeforeEach + void setUp() { + executor = Executors.newScheduledThreadPool(2); + } + + @AfterEach + void tearDown() { + executor.shutdownNow(); + } + + private SqsAsyncBatchManager batchManager(SqsAsyncClient client, int maxBatchSize, Duration sendFrequency, + Duration shutdownTimeout) { + DefaultSqsAsyncBatchManager.DefaultBuilder builder = + (DefaultSqsAsyncBatchManager.DefaultBuilder) DefaultSqsAsyncBatchManager.builder(); + builder.client(client); + builder.scheduledExecutor(executor); + builder.overrideConfiguration(BatchOverrideConfiguration.builder() + .maxBatchSize(maxBatchSize) + .sendRequestFrequency(sendFrequency) + .build()); + builder.shutdownTimeout(shutdownTimeout); + return builder.build(); + } + + @Test + @Timeout(20) + void close_boundsShutdownToOneSharedTimeout_notPerManager() { + Duration timeout = Duration.ofMillis(400); + SqsAsyncClient client = mock(SqsAsyncClient.class); + when(client.sendMessageBatch(any(SendMessageBatchRequest.class))) + .thenReturn(new CompletableFuture()); + when(client.deleteMessageBatch(any(DeleteMessageBatchRequest.class))) + .thenReturn(new CompletableFuture()); + when(client.changeMessageVisibilityBatch(any(ChangeMessageVisibilityBatchRequest.class))) + .thenReturn(new CompletableFuture()); + + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), timeout); + batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m")); + batchManager.deleteMessage(r -> r.queueUrl(QUEUE_URL).receiptHandle("rh")); + batchManager.changeMessageVisibility(r -> r.queueUrl(QUEUE_URL).receiptHandle("rh").visibilityTimeout(30)); + + long start = System.nanoTime(); + batchManager.close(); + long closeMillis = (System.nanoTime() - start) / 1_000_000; + + assertThat(closeMillis).as("close() should wait about one timeout").isGreaterThanOrEqualTo(300); + assertThat(closeMillis) + .as("close() must be bounded by ONE shared timeout, not one per manager (3x would be ~%d ms)", + 3 * timeout.toMillis()) + .isLessThan(2 * timeout.toMillis()); + } + + @Test + @Timeout(20) + void close_flushesBufferedPartialBatchExactlyOnce() { + SqsAsyncClient client = mock(SqsAsyncClient.class); + when(client.sendMessageBatch(any(SendMessageBatchRequest.class))) + .thenReturn(new CompletableFuture()); + + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), Duration.ofMillis(300)); + for (int i = 0; i < 5; i++) { + int n = i; + batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m" + n)); + } + + batchManager.close(); + + verify(client, times(1)).sendMessageBatch(any(SendMessageBatchRequest.class)); + } + + @Test + @Timeout(20) + void close_flushesFullThenResidualPartialBatch_eachExactlyOnce() { + SqsAsyncClient client = mock(SqsAsyncClient.class); + when(client.sendMessageBatch(any(SendMessageBatchRequest.class))) + .thenReturn(new CompletableFuture()); + + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), Duration.ofMillis(300)); + for (int i = 0; i < 15; i++) { + int n = i; + batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m" + n)); + } + + batchManager.close(); + + // 10 auto-flush a full batch during sendMessage, the residual 5 are drained on close: two sends, each once. + verify(client, times(2)).sendMessageBatch(any(SendMessageBatchRequest.class)); + } + + @Test + @Timeout(20) + void close_completesCallerWithRealResult_whenSendCompletesWithinTimeout() throws Exception { + SqsAsyncClient client = mock(SqsAsyncClient.class); + CompletableFuture sendFuture = new CompletableFuture<>(); + when(client.sendMessageBatch(any(SendMessageBatchRequest.class))).thenReturn(sendFuture); + + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), Duration.ofSeconds(2)); + CompletableFuture response = batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m")); + executor.schedule(() -> sendFuture.complete( + SendMessageBatchResponse.builder() + .successful(SendMessageBatchResultEntry.builder() + .id("0") + .messageId("msg-0") + .md5OfMessageBody("d41d8cd98f00b204e9800998ecf8427e") + .build()) + .build()), + 100, TimeUnit.MILLISECONDS); + + batchManager.close(); + + assertThat(response.get(1, TimeUnit.SECONDS).messageId()).isEqualTo("msg-0"); + } + + @Test + @Timeout(20) + void close_cancelsStragglerSend_thatDoesNotCompleteWithinTimeout() { + SqsAsyncClient client = mock(SqsAsyncClient.class); + when(client.sendMessageBatch(any(SendMessageBatchRequest.class))) + .thenReturn(new CompletableFuture()); + + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), Duration.ofMillis(300)); + CompletableFuture response = batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m")); + + batchManager.close(); + + assertThatThrownBy(response::join).isInstanceOf(CancellationException.class); + } + + @Test + @Timeout(20) + void sendMessageAfterClose_completesExceptionallyWithIllegalStateException() { + SqsAsyncClient client = mock(SqsAsyncClient.class); + SqsAsyncBatchManager batchManager = batchManager(client, 10, Duration.ofHours(1), Duration.ofMillis(1)); + + batchManager.close(); + batchManager.close(); // idempotent: second close is a no-op + + CompletableFuture response = batchManager.sendMessage(r -> r.queueUrl(QUEUE_URL).messageBody("m")); + + assertThatThrownBy(() -> response.get(1, TimeUnit.SECONDS)).hasCauseInstanceOf(IllegalStateException.class); + } +} diff --git a/services/ssm/pom.xml b/services/ssm/pom.xml index 3098b5e1021f..72701a3220d3 100644 --- a/services/ssm/pom.xml +++ b/services/ssm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssm AWS Java SDK :: Services :: AWS Simple Systems Management (SSM) diff --git a/services/ssm/src/main/resources/codegen-resources/customization.config b/services/ssm/src/main/resources/codegen-resources/customization.config index 926c0be479ff..00fcb960d059 100644 --- a/services/ssm/src/main/resources/codegen-resources/customization.config +++ b/services/ssm/src/main/resources/codegen-resources/customization.config @@ -25,6 +25,5 @@ "describeAssociation", "listComplianceItems", "describeMaintenanceWindowSchedule" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/ssm/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssm/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b11a0725961f --- /dev/null +++ b/services/ssm/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssm/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssm/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c0a4306be9b3..000000000000 --- a/services/ssm/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://ssm.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ssm-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ssm.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ssm/src/main/resources/codegen-resources/service-2.json b/services/ssm/src/main/resources/codegen-resources/service-2.json index 80c1d9e3eb30..0256474f55b5 100644 --- a/services/ssm/src/main/resources/codegen-resources/service-2.json +++ b/services/ssm/src/main/resources/codegen-resources/service-2.json @@ -3575,6 +3575,10 @@ "shape":"String", "documentation":"

    A message describing why an execution has failed, if the status is set to Failed.

    " }, + "WarningMessage":{ + "shape":"String", + "documentation":"

    A message that describes a non-critical issue that occurred during the automation execution.

    " + }, "Mode":{ "shape":"ExecutionMode", "documentation":"

    The automation execution mode.

    " @@ -3744,7 +3748,7 @@ "documentation":"

    The name of the parameter used as the target resource for the rate-controlled execution. Required if you specify targets.

    " }, "Targets":{ - "shape":"Targets", + "shape":"AutomationTargets", "documentation":"

    Information about the resources that would be included in the actual runbook execution, if it were to be run. Both Targets and TargetMaps can't be specified together.

    " }, "TargetMaps":{ @@ -3827,7 +3831,11 @@ }, "FailureMessage":{ "shape":"String", - "documentation":"

    The list of execution outputs as defined in the Automation runbook.

    " + "documentation":"

    A message that describes a failure that occurred during the automation execution.

    " + }, + "WarningMessage":{ + "shape":"String", + "documentation":"

    A message that describes a non-critical issue that occurred during the automation execution.

    " }, "TargetParameterName":{ "shape":"AutomationParameterKey", @@ -4001,6 +4009,12 @@ "max":50, "min":1 }, + "AutomationTargets":{ + "type":"list", + "member":{"shape":"Target"}, + "max":1, + "min":0 + }, "AutomationType":{ "type":"string", "enum":[ @@ -16879,7 +16893,7 @@ "documentation":"

    The name of the parameter used as the target resource for the rate-controlled execution. Required if you specify targets.

    " }, "Targets":{ - "shape":"Targets", + "shape":"AutomationTargets", "documentation":"

    A key-value mapping to target resources. Required if you specify TargetParameterName.

    If both this parameter and the TargetLocation:Targets parameter are supplied, TargetLocation:Targets takes precedence.

    " }, "TargetMaps":{ @@ -17129,6 +17143,10 @@ "shape":"String", "documentation":"

    If a step failed, this message explains why the execution failed.

    " }, + "WarningMessage":{ + "shape":"String", + "documentation":"

    A message that describes a non-critical issue that occurred during the step execution. Present only if the step status includes a warning.

    " + }, "FailureDetails":{ "shape":"FailureDetails", "documentation":"

    Information about the Automation failure.

    " @@ -17390,7 +17408,7 @@ "documentation":"

    Amazon Web Services accounts or organizational units to exclude as expanded targets.

    " }, "Targets":{ - "shape":"Targets", + "shape":"AutomationTargets", "documentation":"

    A list of key-value mappings to target resources. If you specify values for this data type, you must also specify a value for TargetParameterName.

    This Targets parameter takes precedence over the StartAutomationExecution:Targets parameter if both are supplied.

    " }, "TargetsMaxConcurrency":{ diff --git a/services/ssmcontacts/pom.xml b/services/ssmcontacts/pom.xml index f13cfc5867e4..6fd28a4bb8fe 100644 --- a/services/ssmcontacts/pom.xml +++ b/services/ssmcontacts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssmcontacts AWS Java SDK :: Services :: SSM Contacts diff --git a/services/ssmcontacts/src/main/resources/codegen-resources/customization.config b/services/ssmcontacts/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ssmcontacts/src/main/resources/codegen-resources/customization.config +++ b/services/ssmcontacts/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1b05c4af536e --- /dev/null +++ b/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-contacts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-contacts-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-contacts.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-contacts.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 558698268f02..000000000000 --- a/services/ssmcontacts/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-contacts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-contacts-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-contacts.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ssm-contacts.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ssmguiconnect/pom.xml b/services/ssmguiconnect/pom.xml index 0b5d0ed1695e..8bf4dceac71a 100644 --- a/services/ssmguiconnect/pom.xml +++ b/services/ssmguiconnect/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssmguiconnect AWS Java SDK :: Services :: SSM Gui Connect diff --git a/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..2dd9d46c772c --- /dev/null +++ b/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-guiconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-guiconnect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-guiconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-guiconnect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 064adfd633ca..000000000000 --- a/services/ssmguiconnect/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-guiconnect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-guiconnect-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-guiconnect.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-guiconnect.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/ssmincidents/pom.xml b/services/ssmincidents/pom.xml index 7773085f9079..ba7ffd2159bb 100644 --- a/services/ssmincidents/pom.xml +++ b/services/ssmincidents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssmincidents AWS Java SDK :: Services :: SSM Incidents diff --git a/services/ssmincidents/src/main/resources/codegen-resources/customization.config b/services/ssmincidents/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ssmincidents/src/main/resources/codegen-resources/customization.config +++ b/services/ssmincidents/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ssmincidents/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssmincidents/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..282e32e35d94 --- /dev/null +++ b/services/ssmincidents/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-incidents-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-incidents-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-incidents.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-incidents.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssmincidents/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssmincidents/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b0147dbfd8a4..000000000000 --- a/services/ssmincidents/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-incidents-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-incidents-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-incidents.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ssm-incidents.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ssmquicksetup/pom.xml b/services/ssmquicksetup/pom.xml index 6cfc04c4bf41..dd1acbc43898 100644 --- a/services/ssmquicksetup/pom.xml +++ b/services/ssmquicksetup/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssmquicksetup AWS Java SDK :: Services :: SSM Quick Setup diff --git a/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..091ce75818ed --- /dev/null +++ b/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-quicksetup-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-quicksetup-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-quicksetup.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-quicksetup.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 506ad9b90bd3..000000000000 --- a/services/ssmquicksetup/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-quicksetup-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-quicksetup-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-quicksetup.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-quicksetup.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/ssmsap/pom.xml b/services/ssmsap/pom.xml index b991e547e70d..a050d1ba21c7 100644 --- a/services/ssmsap/pom.xml +++ b/services/ssmsap/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssmsap AWS Java SDK :: Services :: Ssm Sap diff --git a/services/ssmsap/src/main/resources/codegen-resources/customization.config b/services/ssmsap/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ssmsap/src/main/resources/codegen-resources/customization.config +++ b/services/ssmsap/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ssmsap/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssmsap/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..53347745cc86 --- /dev/null +++ b/services/ssmsap/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-sap-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-sap-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-sap.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ssm-sap.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssmsap/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssmsap/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 274cbba6fc8a..000000000000 --- a/services/ssmsap/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-sap-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-sap-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-sap.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://ssm-sap.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sso/pom.xml b/services/sso/pom.xml index c270050b2a5e..e1bc14edf12a 100644 --- a/services/sso/pom.xml +++ b/services/sso/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sso AWS Java SDK :: Services :: SSO diff --git a/services/sso/src/main/resources/codegen-resources/customization.config b/services/sso/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/sso/src/main/resources/codegen-resources/customization.config +++ b/services/sso/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/sso/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sso/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..495365eabf4a --- /dev/null +++ b/services/sso/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://portal.sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://portal.sso.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://portal.sso-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://portal.sso.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://portal.sso.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/sso/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sso/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5e6a59db7d56..000000000000 --- a/services/sso/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://portal.sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://portal.sso.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://portal.sso-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://portal.sso.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://portal.sso.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ssoadmin/pom.xml b/services/ssoadmin/pom.xml index 914252e48f97..5359d86caf89 100644 --- a/services/ssoadmin/pom.xml +++ b/services/ssoadmin/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssoadmin AWS Java SDK :: Services :: SSO Admin diff --git a/services/ssoadmin/src/main/resources/codegen-resources/customization.config b/services/ssoadmin/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/ssoadmin/src/main/resources/codegen-resources/customization.config +++ b/services/ssoadmin/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/ssoadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssoadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1db8b41b2947 --- /dev/null +++ b/services/ssoadmin/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sso.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sso-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sso.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sso.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssoadmin/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssoadmin/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d66c5e58261c..000000000000 --- a/services/ssoadmin/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sso-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://sso.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sso-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sso.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sso.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/ssoadmin/src/main/resources/codegen-resources/service-2.json b/services/ssoadmin/src/main/resources/codegen-resources/service-2.json index ae2b0bd97364..ed338c4a2f5c 100644 --- a/services/ssoadmin/src/main/resources/codegen-resources/service-2.json +++ b/services/ssoadmin/src/main/resources/codegen-resources/service-2.json @@ -1357,7 +1357,7 @@ {"shape":"ValidationException"}, {"shape":"ConflictException"} ], - "documentation":"

    Update the details for the instance of IAM Identity Center that is owned by the Amazon Web Services account.

    " + "documentation":"

    Update the details for the instance of IAM Identity Center that is owned by the Amazon Web Services account.

    In a single UpdateInstance request, you can perform only one of the following operations:

    • Update the encryption configuration of the instance by specifying EncryptionConfiguration.

    • Enable permission sets for the instance by specifying PermissionSetsEnabled.

    A request that specifies both EncryptionConfiguration and PermissionSetsEnabled returns a ValidationException. To perform both operations, call UpdateInstance separately for each. The two calls can be made in parallel.

    " }, "UpdateInstanceAccessControlAttributeConfiguration":{ "name":"UpdateInstanceAccessControlAttributeConfiguration", @@ -1949,6 +1949,10 @@ "max":10, "min":1 }, + "Boolean":{ + "type":"boolean", + "box":true + }, "ClaimAttributePath":{ "type":"string", "max":255, @@ -2729,6 +2733,10 @@ "shape":"Id", "documentation":"

    The identifier of the identity store that is connected to the instance of IAM Identity Center.

    " }, + "IdentityStoreArn":{ + "shape":"InstanceIdentityStoreArn", + "documentation":"

    The ARN of the identity store that is connected to the instance of IAM Identity Center.

    " + }, "OwnerAccountId":{ "shape":"AccountId", "documentation":"

    The identifier of the Amazon Web Services account for which the instance was created.

    " @@ -2749,9 +2757,21 @@ "shape":"Reason", "documentation":"

    Provides additional context about the current status of the IAM Identity Center instance. This field is particularly useful when an instance is in a non-ACTIVE state, such as CREATE_FAILED. When an instance fails to create or update, this field contains information about the cause, which may include issues with KMS key configuration, permission problems with the specified KMS key, or service-related errors.

    " }, + "PrimaryRegion":{ + "shape":"RegionName", + "documentation":"

    The primary Region where the IAM Identity Center instance was originally enabled. The primary Region cannot be removed.

    " + }, + "Regions":{ + "shape":"RegionMetadataList", + "documentation":"

    The list of Regions enabled in the IAM Identity Center instance, including Regions with ACTIVE, ADDING, or REMOVING status.

    " + }, "EncryptionConfigurationDetails":{ "shape":"EncryptionConfigurationDetails", "documentation":"

    Contains the encryption configuration for your IAM Identity Center instance, including the encryption status, KMS key type, and KMS key ARN.

    " + }, + "PermissionSetsEnabled":{ + "shape":"Boolean", + "documentation":"

    Indicates whether permission sets are enabled for this Identity Center instance.

    " } } }, @@ -3280,6 +3300,12 @@ "min":10, "pattern":"arn:aws(-[a-z]{1,5}){0,3}:sso:::instance/(sso)?ins-[a-zA-Z0-9-.]{16}" }, + "InstanceIdentityStoreArn":{ + "type":"string", + "max":93, + "min":62, + "pattern":"arn:aws(-[a-z]{1,5}){0,3}:identitystore::\\d{12}:identitystore/(d-[0-9a-f]{10}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})" + }, "InstanceList":{ "type":"list", "member":{"shape":"InstanceMetadata"}, @@ -3297,6 +3323,10 @@ "shape":"Id", "documentation":"

    The identifier of the identity store that is connected to the Identity Center instance.

    " }, + "IdentityStoreArn":{ + "shape":"InstanceIdentityStoreArn", + "documentation":"

    The ARN of the identity store that is connected to the Identity Center instance.

    " + }, "OwnerAccountId":{ "shape":"AccountId", "documentation":"

    The Amazon Web Services account ID number of the owner of the Identity Center instance.

    " @@ -5115,6 +5145,10 @@ "EncryptionConfiguration":{ "shape":"EncryptionConfiguration", "documentation":"

    Specifies the encryption configuration for your IAM Identity Center instance. You can use this to configure customer managed KMS keys or Amazon Web Services owned KMS keys for encrypting your instance data.

    " + }, + "PermissionSetsEnabled":{ + "shape":"Boolean", + "documentation":"

    Enables permission sets for this Identity Center instance. The only accepted value is true . After permission sets are enabled, they cannot be disabled.

    You can't set EncryptionConfiguration and PermissionSetsEnabled in the same request. To configure both, make two separate UpdateInstance calls. These calls can be made in parallel.

    " } } }, diff --git a/services/ssooidc/pom.xml b/services/ssooidc/pom.xml index 5d1973b13cd0..a0507a5f35a1 100644 --- a/services/ssooidc/pom.xml +++ b/services/ssooidc/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ssooidc AWS Java SDK :: Services :: SSO OIDC diff --git a/services/ssooidc/src/main/java/software/amazon/awssdk/services/ssooidc/SsoOidcTokenProvider.java b/services/ssooidc/src/main/java/software/amazon/awssdk/services/ssooidc/SsoOidcTokenProvider.java index c5c1501ee395..222a42ce9bd8 100644 --- a/services/ssooidc/src/main/java/software/amazon/awssdk/services/ssooidc/SsoOidcTokenProvider.java +++ b/services/ssooidc/src/main/java/software/amazon/awssdk/services/ssooidc/SsoOidcTokenProvider.java @@ -116,29 +116,29 @@ public interface Builder { Builder sessionName(String sessionName); /** - * * Client to fetch token from SSO OIDC service. */ Builder ssoOidcClient(SsoOidcClient ssoOidcClient); /** - * Configure the amount of time, relative to Sso-Oidc token , that the cached tokens in refresher are considered + * Configure the amount of time, relative to SSO OIDC token expiration, that the cached tokens in refresher are considered * stale and should no longer be used. * - *

    By default, this is 5 minute.

    + *

    By default, this is 1 minute.

    */ Builder staleTime(Duration onDiskStaleDuration); /** + * Configure the amount of time, relative to SSO OIDC token expiration, that the cached tokens in refresher are considered + * close to stale and should be prefetched from the service. * - * Configure the amount of time, relative to Sso-Oidc token , that the cached tokens in refresher are considered - * prefetched from service.. + *

    By default, this is 5 minutes.

    */ Builder prefetchTime(Duration prefetchTime); /** * Configure whether the provider should fetch tokens asynchronously in the background. If this is true, - * threads are less likely to block when token are loaded, but additional resources are used to maintain + * threads are less likely to block when tokens are loaded, but additional resources are used to maintain * the provider. * *

    By default, this is disabled.

    diff --git a/services/ssooidc/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/ssooidc/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ef453c9e9147 --- /dev/null +++ b/services/ssooidc/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,212 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oidc.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://oidc.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 14, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/ssooidc/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/ssooidc/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 63e78264e018..000000000000 --- a/services/ssooidc/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oidc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://oidc.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://oidc-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://oidc.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://oidc.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/storagegateway/pom.xml b/services/storagegateway/pom.xml index 132ad50f7143..4eb5535277cd 100644 --- a/services/storagegateway/pom.xml +++ b/services/storagegateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT storagegateway AWS Java SDK :: Services :: AWS Storage Gateway diff --git a/services/storagegateway/src/main/resources/codegen-resources/customization.config b/services/storagegateway/src/main/resources/codegen-resources/customization.config index 2383d1862b10..d354924e1729 100644 --- a/services/storagegateway/src/main/resources/codegen-resources/customization.config +++ b/services/storagegateway/src/main/resources/codegen-resources/customization.config @@ -17,6 +17,5 @@ "error" ] } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/storagegateway/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/storagegateway/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b0f610f5f249 --- /dev/null +++ b/services/storagegateway/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://storagegateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://storagegateway-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://storagegateway.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://storagegateway.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/storagegateway/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/storagegateway/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 320e93cff71e..000000000000 --- a/services/storagegateway/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://storagegateway-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://storagegateway-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://storagegateway.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://storagegateway.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sts/pom.xml b/services/sts/pom.xml index eb9ec8b27837..287df0aa0be4 100644 --- a/services/sts/pom.xml +++ b/services/sts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sts AWS Java SDK :: Services :: AWS STS diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsGetFederationTokenCredentialsProvider.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsGetFederationTokenCredentialsProvider.java index 7fb6a33e9cba..e096d66eceb3 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsGetFederationTokenCredentialsProvider.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/auth/StsGetFederationTokenCredentialsProvider.java @@ -25,7 +25,7 @@ import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.services.sts.StsClient; -import software.amazon.awssdk.services.sts.endpoints.internal.Arn; +import software.amazon.awssdk.services.sts.endpoints.internal.RuleArn; import software.amazon.awssdk.services.sts.model.FederatedUser; import software.amazon.awssdk.services.sts.model.GetFederationTokenRequest; import software.amazon.awssdk.services.sts.model.GetFederationTokenResponse; @@ -89,9 +89,11 @@ private String accountIdFromArn(FederatedUser federatedUser) { if (federatedUser == null) { return null; } - return Arn.parse(federatedUser.arn()) - .map(Arn::accountId) - .orElse(null); + RuleArn arn = RuleArn.parse(federatedUser.arn()); + if (arn == null) { + return null; + } + return arn.accountId(); } @Override diff --git a/services/sts/src/main/java/software/amazon/awssdk/services/sts/internal/StsAuthUtils.java b/services/sts/src/main/java/software/amazon/awssdk/services/sts/internal/StsAuthUtils.java index e854495e0124..fb84fbb2f1cf 100644 --- a/services/sts/src/main/java/software/amazon/awssdk/services/sts/internal/StsAuthUtils.java +++ b/services/sts/src/main/java/software/amazon/awssdk/services/sts/internal/StsAuthUtils.java @@ -17,7 +17,7 @@ import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; -import software.amazon.awssdk.services.sts.endpoints.internal.Arn; +import software.amazon.awssdk.services.sts.endpoints.internal.RuleArn; import software.amazon.awssdk.services.sts.model.AssumedRoleUser; import software.amazon.awssdk.services.sts.model.Credentials; @@ -31,9 +31,11 @@ public static String accountIdFromArn(AssumedRoleUser assumedRoleUser) { if (assumedRoleUser == null) { return null; } - return Arn.parse(assumedRoleUser.arn()) - .map(Arn::accountId) - .orElse(null); + RuleArn arn = RuleArn.parse(assumedRoleUser.arn()); + if (arn == null) { + return null; + } + return arn.accountId(); } public static AwsSessionCredentials fromStsCredentials(Credentials credentials, String provider) { diff --git a/services/sts/src/main/resources/codegen-resources/customization.config b/services/sts/src/main/resources/codegen-resources/customization.config index 26879092eaa6..320740074fe5 100644 --- a/services/sts/src/main/resources/codegen-resources/customization.config +++ b/services/sts/src/main/resources/codegen-resources/customization.config @@ -21,6 +21,5 @@ "UseGlobalEndpoint with legacy region `us-west-2`": "V2 does not support setting UseGlobalEndpoint. It's regional only/by default" }, - "enableGenerateCompiledEndpointRules": true, "customRetryStrategy" : "software.amazon.awssdk.services.sts.internal.StsRetryStrategy" } diff --git a/services/sts/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sts/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..bed3b99c63af --- /dev/null +++ b/services/sts/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,406 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "UseGlobalEndpoint": { + "builtIn": "AWS::STS::UseGlobalEndpoint", + "required": true, + "default": false, + "documentation": "Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.", + "type": "boolean" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "aws-global" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseGlobalEndpoint" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "eu-central-1" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ap-south-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "eu-north-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "eu-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "eu-west-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "eu-west-3" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "sa-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ca-central-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ap-southeast-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ap-northeast-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "ap-southeast-2" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "endpoint": { + "url": "https://sts.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "sts", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts.{Region}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "sts", + "signingRegion": "{Region}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sts.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 31, + "nodes": "/////wAAAAH/////AAAAAAAAAB4AAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAABkAAAAGAAAABAAAABgAAAAHAAAABQX14QEAAAAIAAAABgAAAAkF9eENAAAABwX14QEAAAAKAAAACgX14QEAAAALAAAACwX14QEAAAAMAAAADAX14QEAAAANAAAADQX14QEAAAAOAAAADgX14QEAAAAPAAAADwX14QEAAAAQAAAAEAX14QEAAAARAAAAEQX14QEAAAASAAAAEgX14QEAAAATAAAAEwX14QEAAAAUAAAAFAX14QEAAAAVAAAAFQX14QEAAAAWAAAAFgX14QEAAAAXAAAAFwX14QEF9eECAAAACAX14QsF9eEMAAAABAAAABwAAAAaAAAACQAAABsF9eEKAAAAGAX14QgF9eEJAAAACAAAAB0F9eEHAAAACQX14QYF9eEHAAAAAwX14QMAAAAfAAAABAX14QQF9eEF" +} \ No newline at end of file diff --git a/services/sts/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sts/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 3c5902ab840c..000000000000 --- a/services/sts/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,886 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "UseGlobalEndpoint": { - "builtIn": "AWS::STS::UseGlobalEndpoint", - "required": true, - "default": false, - "documentation": "Whether the global endpoint should be used, rather then the regional endpoint for us-east-1.", - "type": "boolean" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseGlobalEndpoint" - }, - true - ] - }, - { - "fn": "not", - "argv": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ] - }, - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - }, - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ap-northeast-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ap-south-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ap-southeast-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ap-southeast-2" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "ca-central-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "eu-central-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "eu-north-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "eu-west-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "eu-west-2" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "eu-west-3" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "sa-east-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-east-2" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-1" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "us-west-2" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sts.{Region}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "{Region}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sts-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://sts.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sts-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://sts.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "aws-global" - ] - } - ], - "endpoint": { - "url": "https://sts.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "sts", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sts.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/sts/src/main/resources/codegen-resources/service-2.json b/services/sts/src/main/resources/codegen-resources/service-2.json index c63be78c58ff..ecdcb1848c76 100644 --- a/services/sts/src/main/resources/codegen-resources/service-2.json +++ b/services/sts/src/main/resources/codegen-resources/service-2.json @@ -211,7 +211,7 @@ {"shape":"OutboundWebIdentityFederationDisabledException"}, {"shape":"JWTPayloadSizeExceededException"} ], - "documentation":"

    Returns a signed JSON Web Token (JWT) that represents the calling Amazon Web Services identity. The returned JWT can be used to authenticate with external services that support OIDC discovery. The token is signed by Amazon Web Services STS and can be publicly verified using the verification keys published at the issuer's JWKS endpoint.

    " + "documentation":"

    Returns a signed JSON Web Token (JWT) that represents the calling Amazon Web Services identity. The returned JWT can be used to authenticate with external services that support OIDC discovery. The token is signed by Amazon Web Services STS and can be publicly verified using the verification keys published at the issuer's JWKS endpoint.

    The GetWebIdentityToken API is not available on the STS Global endpoint.

    " } }, "shapes":{ @@ -269,7 +269,8 @@ "ProvidedContexts":{ "shape":"ProvidedContextsListType", "documentation":"

    A list of previously acquired trusted context assertions in the format of a JSON array. The trusted context assertion is signed and encrypted by Amazon Web Services STS.

    The following is an example of a ProvidedContext value that includes a single trusted context assertion and the ARN of the context provider from which the trusted context assertion was generated.

    [{\"ProviderArn\":\"arn:aws:iam::aws:contextProvider/IdentityCenter\",\"ContextAssertion\":\"trusted-context-assertion\"}]

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "AssumeRoleResponse":{ @@ -285,12 +286,17 @@ }, "PackedPolicySize":{ "shape":"nonNegativeIntegerType", - "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    " + "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. Replaced by SessionTokenUtilization.", + "deprecatedSince":"2026-06-17" }, "SourceIdentity":{ "shape":"sourceIdentityType", "documentation":"

    The source identity specified by the principal that is calling the AssumeRole operation.

    You can require users to specify a source identity when they assume a role. You do this by using the sts:SourceIdentity condition key in a role trust policy. You can use source identity information in CloudTrail logs to determine who took actions with a role. You can use the aws:SourceIdentity condition key to further control access to Amazon Web Services resources based on the value of source identity. For more information about using source identity, see Monitor and control actions taken with assumed roles in the IAM User Guide.

    The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    " - } + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} }, "documentation":"

    Contains the response to a successful AssumeRole request, including temporary Amazon Web Services credentials that can be used to make Amazon Web Services requests.

    " }, @@ -325,7 +331,8 @@ "DurationSeconds":{ "shape":"roleDurationSecondsType", "documentation":"

    The duration, in seconds, of the role session. Your role session lasts for the duration that you specify for the DurationSeconds parameter, or until the time specified in the SAML authentication response's SessionNotOnOrAfter value, whichever is shorter. You can provide a DurationSeconds value from 900 seconds (15 minutes) up to the maximum session duration setting for the role. This setting can have a value from 1 hour to 12 hours. If you specify a value higher than this setting, the operation fails. For example, if you specify a session duration of 12 hours, but your administrator set the maximum session duration to 6 hours, your operation fails. To learn how to view the maximum value for your role, see View the Maximum Session Duration Setting for a Role in the IAM User Guide.

    By default, the value is set to 3600 seconds.

    The DurationSeconds parameter is separate from the duration of a console session that you might request using the returned credentials. The request to the federation endpoint for a console sign-in token takes a SessionDuration parameter that specifies the maximum length of the console session. For more information, see Creating a URL that Enables Federated Users to Access the Amazon Web Services Management Console in the IAM User Guide.

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "AssumeRoleWithSAMLResponse":{ @@ -341,7 +348,10 @@ }, "PackedPolicySize":{ "shape":"nonNegativeIntegerType", - "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    " + "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. Replaced by SessionTokenUtilization.", + "deprecatedSince":"2026-06-17" }, "Subject":{ "shape":"Subject", @@ -366,7 +376,9 @@ "SourceIdentity":{ "shape":"sourceIdentityType", "documentation":"

    The value in the SourceIdentity attribute in the SAML assertion. The source identity value persists across chained role sessions.

    You can require users to set a source identity value when they assume a role. You do this by using the sts:SourceIdentity condition key in a role trust policy. That way, actions that are taken with the role are associated with that user. After the source identity is set, the value cannot be changed. It is present in the request for all actions that are taken by the role and persists across chained role sessions. You can configure your SAML identity provider to use an attribute associated with your users, like user name or email, as the source identity when calling AssumeRoleWithSAML. You do this by adding an attribute to the SAML assertion. For more information about using source identity, see Monitor and control actions taken with assumed roles in the IAM User Guide.

    The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    " - } + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} }, "documentation":"

    Contains the response to a successful AssumeRoleWithSAML request, including temporary Amazon Web Services credentials that can be used to make Amazon Web Services requests.

    " }, @@ -405,7 +417,8 @@ "DurationSeconds":{ "shape":"roleDurationSecondsType", "documentation":"

    The duration, in seconds, of the role session. The value can range from 900 seconds (15 minutes) up to the maximum session duration setting for the role. This setting can have a value from 1 hour to 12 hours. If you specify a value higher than this setting, the operation fails. For example, if you specify a session duration of 12 hours, but your administrator set the maximum session duration to 6 hours, your operation fails. To learn how to view the maximum value for your role, see View the Maximum Session Duration Setting for a Role in the IAM User Guide.

    By default, the value is set to 3600 seconds.

    The DurationSeconds parameter is separate from the duration of a console session that you might request using the returned credentials. The request to the federation endpoint for a console sign-in token takes a SessionDuration parameter that specifies the maximum length of the console session. For more information, see Creating a URL that Enables Federated Users to Access the Amazon Web Services Management Console in the IAM User Guide.

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "AssumeRoleWithWebIdentityResponse":{ @@ -425,7 +438,10 @@ }, "PackedPolicySize":{ "shape":"nonNegativeIntegerType", - "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    " + "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. Replaced by SessionTokenUtilization.", + "deprecatedSince":"2026-06-17" }, "Provider":{ "shape":"Issuer", @@ -438,7 +454,9 @@ "SourceIdentity":{ "shape":"sourceIdentityType", "documentation":"

    The value of the source identity that is returned in the JSON web token (JWT) from the identity provider.

    You can require users to set a source identity value when they assume a role. You do this by using the sts:SourceIdentity condition key in a role trust policy. That way, actions that are taken with the role are associated with that user. After the source identity is set, the value cannot be changed. It is present in the request for all actions that are taken by the role and persists across chained role sessions. You can configure your identity provider to use an attribute associated with your users, like user name or email, as the source identity when calling AssumeRoleWithWebIdentity. You do this by adding a claim to the JSON web token. To learn more about OIDC tokens and claims, see Using Tokens with User Pools in the Amazon Cognito Developer Guide. For more information about using source identity, see Monitor and control actions taken with assumed roles in the IAM User Guide.

    The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    " - } + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} }, "documentation":"

    Contains the response to a successful AssumeRoleWithWebIdentity request, including temporary Amazon Web Services credentials that can be used to make Amazon Web Services requests.

    " }, @@ -460,7 +478,8 @@ "DurationSeconds":{ "shape":"RootDurationSecondsType", "documentation":"

    The duration, in seconds, of the privileged session. The value can range from 0 seconds up to the maximum session duration of 900 seconds (15 minutes). If you specify a value higher than this setting, the operation fails.

    By default, the value is set to 900 seconds.

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "AssumeRootResponse":{ @@ -473,7 +492,9 @@ "SourceIdentity":{ "shape":"sourceIdentityType", "documentation":"

    The source identity specified by the principal that is calling the AssumeRoot operation.

    You can use the aws:SourceIdentity condition key to control access based on the value of source identity. For more information about using source identity, see Monitor and control actions taken with assumed roles in the IAM User Guide.

    The regex used to validate this parameter is a string of characters consisting of upper- and lower-case alphanumeric characters with no spaces. You can also include underscores or any of the following characters: =,.@-

    " - } + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} } }, "AssumedRoleUser":{ @@ -644,7 +665,10 @@ "Credentials":{"shape":"Credentials"}, "PackedPolicySize":{ "shape":"nonNegativeIntegerType", - "documentation":"

    The percentage of the maximum policy size that is used by the session policy. The policy size is calculated as the sum of all the session policies and permission boundaries attached to the session. If the packed size exceeds 100%, the request fails.

    " + "documentation":"

    The percentage of the maximum policy size that is used by the session policy. The policy size is calculated as the sum of all the session policies and permission boundaries attached to the session. If the packed size exceeds 100%, the request fails.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. This field is not populated for GetDelegatedAccessToken.", + "deprecatedSince":"2026-06-17" }, "AssumedPrincipal":{ "shape":"arnType", @@ -675,7 +699,8 @@ "Tags":{ "shape":"tagListType", "documentation":"

    A list of session tags. Each session tag consists of a key name and an associated value. For more information about session tags, see Passing Session Tags in STS in the IAM User Guide.

    This parameter is optional. You can pass up to 50 session tags. The plaintext session tag keys can’t exceed 128 characters and the values can’t exceed 256 characters. For these and additional limits, see IAM and STS Character Limits in the IAM User Guide.

    An Amazon Web Services conversion compresses the passed inline session policy, managed policy ARNs, and session tags into a packed binary format that has a separate limit. Your request can fail for this limit even if your plaintext meets the other requirements. The PackedPolicySize response element indicates by percentage how close the policies and tags for your request are to the upper size limit.

    You can pass a session tag with the same key as a tag that is already attached to the user you are federating. When you do, session tags override a user tag with the same key.

    Tag key–value pairs are not case sensitive, but case is preserved. This means that you cannot have separate Department and department tag keys. Assume that the role has the Department=Marketing tag and you pass the department=engineering session tag. Department and department are not saved as separate tags, and the session tag passed in the request takes precedence over the role tag.

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "GetFederationTokenResponse":{ @@ -691,8 +716,13 @@ }, "PackedPolicySize":{ "shape":"nonNegativeIntegerType", - "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    " - } + "documentation":"

    A percentage value that indicates the packed size of the session policies and session tags combined passed in the request. The request fails if the packed size is greater than 100 percent, which means the policies and tags exceeded the allowed space.

    ", + "deprecated":true, + "deprecatedMessage":"Deprecated. Replaced by SessionTokenUtilization.", + "deprecatedSince":"2026-06-17" + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} }, "documentation":"

    Contains the response to a successful GetFederationToken request, including temporary Amazon Web Services credentials that can be used to make Amazon Web Services requests.

    " }, @@ -710,7 +740,8 @@ "TokenCode":{ "shape":"tokenCodeType", "documentation":"

    The value provided by the MFA device, if MFA is required. If any policy requires the IAM user to submit an MFA code, specify this value. If MFA authentication is required, the user must provide a code when requesting a set of temporary security credentials. A user who fails to provide the code receives an \"access denied\" response when requesting resources that require MFA authentication.

    The format for this parameter, as described by its regex pattern, is a sequence of six numeric digits.

    " - } + }, + "MinimumSessionTokenSize":{"shape":"minimumSessionTokenSizeType"} } }, "GetSessionTokenResponse":{ @@ -719,7 +750,9 @@ "Credentials":{ "shape":"Credentials", "documentation":"

    The temporary security credentials, which include an access key ID, a secret access key, and a security (or session) token.

    The size of the security token that STS API operations return is not fixed. We strongly recommend that you make no assumptions about the maximum size.

    " - } + }, + "SessionTokenUtilization":{"shape":"sessionTokenUtilizationType"}, + "SessionTokenSize":{"shape":"sessionTokenSizeType"} }, "documentation":"

    Contains the response to a successful GetSessionToken request, including temporary Amazon Web Services credentials that can be used to make Amazon Web Services requests.

    " }, @@ -1030,6 +1063,12 @@ }, "jwtPayloadSizeExceededException":{"type":"string"}, "malformedPolicyDocumentMessage":{"type":"string"}, + "minimumSessionTokenSizeType":{ + "type":"integer", + "documentation":"The minimum size, in bytes, of the session token that STS issues for the request. STS increases the session token to at least this size, regardless of its actual content. The value must not exceed 4,096 bytes. When set to 0 or not specified, the session token size is unchanged.", + "max":4096, + "min":0 + }, "nonNegativeIntegerType":{ "type":"integer", "min":0 @@ -1065,6 +1104,16 @@ "min":1, "pattern":"[\\u0009\\u000A\\u000D\\u0020-\\u00FF]+" }, + "sessionTokenSizeType":{ + "type":"integer", + "documentation":"The size, in bytes, of the session token returned in the Credentials for this response.", + "min":0 + }, + "sessionTokenUtilizationType":{ + "type":"integer", + "documentation":"The percentage (0-100) of the maximum allowed session token size that the returned session token consumes.", + "min":0 + }, "sourceIdentityType":{ "type":"string", "max":64, @@ -1147,5 +1196,5 @@ "sensitive":true } }, - "documentation":"Security Token Service

    Security Token Service (STS) enables you to request temporary, limited-privilege credentials for users. This guide provides descriptions of the STS API. For more information about using this service, see Temporary Security Credentials.

    " + "documentation":"Security Token Service

    Amazon Web Services provides Security Token Service (STS) as a web service that enables you to request temporary, limited-privilege credentials for users. This guide describes the STS API. For more information, see Temporary Security Credentials in the IAM User Guide.

    As an alternative to using the API, you can use one of the Amazon Web Services SDKs, which consist of libraries and sample code for various programming languages and platforms such as Java, Ruby, .NET, iOS, Android, and others. The SDKs provide a convenient way to create programmatic access to STS. For example, the SDKs can cryptographically sign requests, manage errors, and retry requests automatically. For information about the Amazon Web Services SDKs, see Tools to Build on Amazon Web Services.

    For information about setting up signatures and authorization through the API, see Signing Amazon Web Services API Requests in the Amazon Web Services General Reference. For general information about the Query API, see Making Query Requests in the IAM User Guide. For information about using security tokens with other Amazon Web Services products, see Amazon Web Services Services That Work with IAM in the IAM User Guide.

    For information about STS endpoints, see STS Regions and endpoints in the IAM User Guide. For information about logging STS API calls, see Logging IAM and STS API calls with CloudTrail in the IAM User Guide.

    " } diff --git a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProviderTestBase.java b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProviderTestBase.java index 8c054aa97e1a..e7bce1105295 100644 --- a/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProviderTestBase.java +++ b/services/sts/src/test/java/software/amazon/awssdk/services/sts/auth/StsCredentialsProviderTestBase.java @@ -29,7 +29,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import software.amazon.awssdk.auth.credentials.AwsSessionCredentials; import software.amazon.awssdk.services.sts.StsClient; -import software.amazon.awssdk.services.sts.endpoints.internal.Arn; import software.amazon.awssdk.services.sts.model.Credentials; /** diff --git a/services/supplychain/pom.xml b/services/supplychain/pom.xml index 0c9d7f1e21a7..cc9bf9c37243 100644 --- a/services/supplychain/pom.xml +++ b/services/supplychain/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT supplychain AWS Java SDK :: Services :: Supply Chain diff --git a/services/supplychain/src/main/resources/codegen-resources/customization.config b/services/supplychain/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/supplychain/src/main/resources/codegen-resources/customization.config +++ b/services/supplychain/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/supplychain/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/supplychain/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a802df12875a --- /dev/null +++ b/services/supplychain/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scn-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scn-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scn.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://scn.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/supplychain/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/supplychain/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5e8568a08de1..000000000000 --- a/services/supplychain/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scn-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scn-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scn.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://scn.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/support/pom.xml b/services/support/pom.xml index 4b6c8e7252f2..264eb11c8651 100644 --- a/services/support/pom.xml +++ b/services/support/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT support AWS Java SDK :: Services :: AWS Support diff --git a/services/support/src/main/resources/codegen-resources/customization.config b/services/support/src/main/resources/codegen-resources/customization.config index 8376e307ce94..14581b7ee319 100644 --- a/services/support/src/main/resources/codegen-resources/customization.config +++ b/services/support/src/main/resources/codegen-resources/customization.config @@ -4,6 +4,5 @@ "describeSeverityLevels", "describeCases", "describeServices" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/support/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/support/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..83e52b6f5186 --- /dev/null +++ b/services/support/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,348 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-cn" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-iso-b" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "support", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.cn-north-1.amazonaws.com.cn", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "support", + "signingRegion": "cn-north-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.us-gov-west-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "support", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.us-iso-east-1.c2s.ic.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "support", + "signingRegion": "us-iso-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.us-isob-east-1.sc2s.sgov.gov", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "support", + "signingRegion": "us-isob-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://support.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 19, + "nodes": "/////wAAAAH/////AAAAAAAAABIAAAADAAAAAQAAAAQF9eEQAAAAAgAAAAUF9eEQAAAAAwAAAA0AAAAGAAAABAAAAAwAAAAHAAAABQX14QQAAAAIAAAABwX14QUAAAAJAAAACAX14QYAAAAKAAAACgX14QcAAAALAAAACwX14QgF9eEPAAAABgX14Q0F9eEOAAAABAAAABAAAAAOAAAACAX14QYAAAAPAAAACQX14QsF9eEMAAAABgAAABEF9eEKAAAACQX14QkF9eEKAAAAAwX14QEAAAATAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/support/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/support/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8eb7596ecc4a..000000000000 --- a/services/support/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,620 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.us-east-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-cn" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.cn-north-1.amazonaws.com.cn", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "cn-north-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.us-gov-west-1.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.us-iso-east-1.c2s.ic.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "us-iso-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-iso-b" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://support.us-isob-east-1.sc2s.sgov.gov", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "support", - "signingRegion": "us-isob-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://support-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://support-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://support.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://support.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/support/src/main/resources/codegen-resources/service-2.json b/services/support/src/main/resources/codegen-resources/service-2.json index 2dce9a7e0faf..69aa2f7407be 100644 --- a/services/support/src/main/resources/codegen-resources/service-2.json +++ b/services/support/src/main/resources/codegen-resources/service-2.json @@ -27,9 +27,10 @@ {"shape":"AttachmentSetIdNotFound"}, {"shape":"AttachmentSetExpired"}, {"shape":"AttachmentSetSizeLimitExceeded"}, - {"shape":"AttachmentLimitExceeded"} + {"shape":"AttachmentLimitExceeded"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Adds one or more attachments to an attachment set.

    An attachment set is a temporary container for attachments that you add to a case or case communication. The set is available for 1 hour after it's created. The expiryTime returned in the response is when the set expires.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Adds one or more attachments to an attachment set.

    An attachment set is a temporary container for attachments that you add to a case or case communication. The set is available for 1 hour after it's created. The expiryTime returned in the response is when the set expires.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "AddCommunicationToCase":{ "name":"AddCommunicationToCase", @@ -43,9 +44,25 @@ {"shape":"InternalServerError"}, {"shape":"CaseIdNotFound"}, {"shape":"AttachmentSetIdNotFound"}, - {"shape":"AttachmentSetExpired"} + {"shape":"AttachmentSetExpired"}, + {"shape":"DryRunOperationException"} + ], + "documentation":"

    Adds additional customer communication to a Amazon Web Services Support case. Use the caseId parameter to identify the case to which to add communication. To list a set of email addresses to copy on the communication, use the ccEmailAddresses parameter. The communicationBody value contains the text of the communication.

    To attach files larger than 5 MB to the communication, use the uploadIds parameter.

    Amazon Web Services Support automatically redacts sensitive information from support cases to protect your data. The following information is replaced with [REDACTED_BY_Amazon Web Services] and is not stored:

    • Amazon Web Services secret keys - The complete key is replaced. Example: [REDACTED_BY_Amazon Web Services]

    • Private keys - The complete key is replaced. Example: [REDACTED_BY_Amazon Web Services]

    • Credit card numbers - The number is redacted, but the last 4 digits remain. Example: [REDACTED_BY_Amazon Web Services]-7016

    This sensitive information is never required by Amazon Web Services Support.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + }, + "CompleteAttachmentUpload":{ + "name":"CompleteAttachmentUpload", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CompleteAttachmentUploadRequest"}, + "output":{"shape":"CompleteAttachmentUploadResponse"}, + "errors":[ + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"}, + {"shape":"UploadIdNotFound"} ], - "documentation":"

    Adds additional customer communication to an Amazon Web Services Support case. Use the caseId parameter to identify the case to which to add communication. You can list a set of email addresses to copy on the communication by using the ccEmailAddresses parameter. The communicationBody value contains the text of the communication.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Completes an attachment upload that was started with GetAttachmentUploadLinks. After you upload a part of the file to its presigned Amazon S3 URL, call CompleteAttachmentUpload with the partIndex and eTag of that part. You can include one part per call, or multiple parts in a single call. After CompleteAttachmentUpload has been called for every part of the file, the service processes the upload asynchronously. The attachment-ready status might not be reflected immediately. Use DescribeAttachmentUploadStatus to poll for the uploadStatus to become attachment-ready before passing the uploadId to CreateCase or AddCommunicationToCase.

    " }, "CreateCase":{ "name":"CreateCase", @@ -59,9 +76,10 @@ {"shape":"InternalServerError"}, {"shape":"CaseCreationLimitExceeded"}, {"shape":"AttachmentSetIdNotFound"}, - {"shape":"AttachmentSetExpired"} + {"shape":"AttachmentSetExpired"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Creates a case in the Amazon Web Services Support Center. This operation is similar to how you create a case in the Amazon Web Services Support Center Create Case page.

    The Amazon Web Services Support API doesn't support requesting service limit increases. You can submit a service limit increase in the following ways:

    A successful CreateCase request returns an Amazon Web Services Support case number. You can use the DescribeCases operation and specify the case number to get existing Amazon Web Services Support cases. After you create a case, use the AddCommunicationToCase operation to add additional communication or attachments to an existing case.

    The caseId is separate from the displayId that appears in the Amazon Web Services Support Center. Use the DescribeCases operation to get the displayId.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Creates a case in the Amazon Web Services Support Center. This operation is similar to how you create a case in the Amazon Web Services Support Center Create Case page.

    The Amazon Web Services Support API doesn't support requesting service limit increases. You can submit a service limit increase in the following ways:

    Amazon Web Services Support automatically redacts sensitive information from support cases to protect your data. The following information is replaced with [REDACTED_BY_Amazon Web Services] and is not stored:

    • Amazon Web Services secret keys - The complete key is replaced. Example: [REDACTED_BY_Amazon Web Services]

    • Private keys - The complete key is replaced. Example: [REDACTED_BY_Amazon Web Services]

    • Credit card numbers - The number is redacted, but the last 4 digits remain. Example: [REDACTED_BY_Amazon Web Services]-7016

    This sensitive information is never required by Amazon Web Services Support.

    A successful CreateCase request returns a Amazon Web Services Support case number. You can use the DescribeCases operation and specify the case number to get existing Amazon Web Services Support cases. After you create a case, use the AddCommunicationToCase operation to add additional communication or attachments to an existing case.

    The caseId is separate from the displayId that appears in the Amazon Web Services Support Center. Use the DescribeCases operation to get the displayId.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeAttachment":{ "name":"DescribeAttachment", @@ -74,9 +92,25 @@ "errors":[ {"shape":"InternalServerError"}, {"shape":"DescribeAttachmentLimitExceeded"}, - {"shape":"AttachmentIdNotFound"} + {"shape":"AttachmentIdNotFound"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns the attachment that has the specified ID. Attachments can include screenshots, error logs, or other files that describe your issue. Attachment IDs are generated by the case management system when you add an attachment to a case or case communication. Attachment IDs are returned in the AttachmentDetails objects that are returned by the DescribeCommunications operation.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns the attachment that has the specified ID. Attachments can include screenshots, error logs, or other files that describe your issue. Attachment IDs are generated by the case management system when you add an attachment to a case or case communication. Attachment IDs are returned in the AttachmentDetails objects that are returned by the DescribeCommunications operation.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    DescribeAttachment can't return attachments larger than 5 MB. If the specified attachmentId refers to an attachment larger than 5 MB, the request fails with InvalidParameterValueException.

    To download an attachment of any size, including attachments larger than 5 MB, use GetAttachmentDownloadLink. GetAttachmentDownloadLink returns an Amazon S3 presigned URL that you can use to download the attachment directly.

    " + }, + "DescribeAttachmentUploadStatus":{ + "name":"DescribeAttachmentUploadStatus", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DescribeAttachmentUploadStatusRequest"}, + "output":{"shape":"DescribeAttachmentUploadStatusResponse"}, + "errors":[ + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"}, + {"shape":"UploadIdNotFound"} + ], + "documentation":"

    Returns the current status, file name, and progress of a multipart attachment upload that was started with GetAttachmentUploadLinks. Use this operation to track where an upload is in the workflow. While parts are still being uploaded and reported through CompleteAttachmentUpload, the uploadStatus is attachment-not-ready and uploadProgress reports the total number of parts and how many have been completed so far. After every part has been reported and the service finishes processing the upload asynchronously, the uploadStatus becomes attachment-ready and the uploadId can be attached to a case through CreateCase or AddCommunicationToCase.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeCases":{ "name":"DescribeCases", @@ -88,9 +122,10 @@ "output":{"shape":"DescribeCasesResponse"}, "errors":[ {"shape":"InternalServerError"}, - {"shape":"CaseIdNotFound"} + {"shape":"CaseIdNotFound"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns a list of cases that you specify by passing one or more case IDs. You can use the afterTime and beforeTime parameters to filter the cases by date. You can set values for the includeResolvedCases and includeCommunications parameters to specify how much information to return.

    The response returns the following in JSON format:

    • One or more CaseDetails data types.

    • One or more nextToken values, which specify where to paginate the returned records represented by the CaseDetails objects.

    Case data is available for 12 months after creation. If a case was created more than 12 months ago, a request might return an error.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns a list of cases that you specify by passing one or more case IDs. You can use the afterTime and beforeTime parameters to filter the cases by date. You can set values for the includeResolvedCases and includeCommunications parameters to specify how much information to return.

    The response returns the following in JSON format:

    • One or more CaseDetails data types.

    • One or more nextToken values, which specify where to paginate the returned records represented by the CaseDetails objects.

    Case data is available for 24 months after creation. If a case was created more than 24 months ago, a request might return an error.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    Each Communication returned by this operation includes attachment information in two fields:

    • attachmentSet: returns only attachments that are 5 MB or smaller. Attachments larger than 5 MB are not included in this field.

    • attachments: returns all attachments regardless of size.

    Amazon Web Services recommends that you use the attachments field and download each attachment with GetAttachmentDownloadLink, which supports attachments of any size. The attachmentSet field and DescribeAttachment return only attachments that are 5 MB or smaller.

    " }, "DescribeCommunications":{ "name":"DescribeCommunications", @@ -102,9 +137,10 @@ "output":{"shape":"DescribeCommunicationsResponse"}, "errors":[ {"shape":"InternalServerError"}, - {"shape":"CaseIdNotFound"} + {"shape":"CaseIdNotFound"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns communications and attachments for one or more support cases. Use the afterTime and beforeTime parameters to filter by date. You can use the caseId parameter to restrict the results to a specific case.

    Case data is available for 12 months after creation. If a case was created more than 12 months ago, a request for data might cause an error.

    You can use the maxResults and nextToken parameters to control the pagination of the results. Set maxResults to the number of cases that you want to display on each page, and use nextToken to specify the resumption of pagination.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns communications and attachments for one or more support cases. Use the afterTime and beforeTime parameters to filter by date. You can use the caseId parameter to restrict the results to a specific case.

    Case data is available for 24 months after creation. If a case was created more than 24 months ago, a request for data might cause an error.

    You can use the maxResults and nextToken parameters to control the pagination of the results. Set maxResults to the number of cases that you want to display on each page, and use nextToken to specify the resumption of pagination.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    Each Communication returned by this operation includes attachment information in two fields:

    • attachmentSet: returns only attachments that are 5 MB or smaller. Attachments larger than 5 MB are not included in this field.

    • attachments: returns all attachments regardless of size.

    Amazon Web Services recommends that you use the attachments field and download each attachment with GetAttachmentDownloadLink, which supports attachments of any size. The attachmentSet field and DescribeAttachment return only attachments that are 5 MB or smaller.

    " }, "DescribeCreateCaseOptions":{ "name":"DescribeCreateCaseOptions", @@ -116,9 +152,10 @@ "output":{"shape":"DescribeCreateCaseOptionsResponse"}, "errors":[ {"shape":"InternalServerError"}, - {"shape":"ThrottlingException"} + {"shape":"ThrottlingException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns a list of CreateCaseOption types along with the corresponding supported hours and language availability. You can specify the language categoryCode, issueType and serviceCode used to retrieve the CreateCaseOptions.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns a list of CreateCaseOption types along with the corresponding supported hours and language availability. You can specify the language categoryCode, issueType and serviceCode used to retrieve the CreateCaseOptions.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeServices":{ "name":"DescribeServices", @@ -129,9 +166,10 @@ "input":{"shape":"DescribeServicesRequest"}, "output":{"shape":"DescribeServicesResponse"}, "errors":[ - {"shape":"InternalServerError"} + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns the current list of Amazon Web Services services and a list of service categories for each service. You then use service names and categories in your CreateCase requests. Each Amazon Web Services service has its own set of categories.

    The service codes and category codes correspond to the values that appear in the Service and Category lists on the Amazon Web Services Support Center Create Case page. The values in those fields don't necessarily match the service codes and categories returned by the DescribeServices operation. Always use the service codes and categories that the DescribeServices operation returns, so that you have the most recent set of service and category codes.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns the current list of Amazon Web Services services and a list of service categories for each service. You then use service names and categories in your CreateCase requests. Each Amazon Web Services service has its own set of categories.

    The service codes and category codes correspond to the values that appear in the Service and Category lists on the Amazon Web Services Support Center Create Case page. The values in those fields don't necessarily match the service codes and categories returned by the DescribeServices operation. Always use the service codes and categories that the DescribeServices operation returns, so that you have the most recent set of service and category codes.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeSeverityLevels":{ "name":"DescribeSeverityLevels", @@ -142,9 +180,10 @@ "input":{"shape":"DescribeSeverityLevelsRequest"}, "output":{"shape":"DescribeSeverityLevelsResponse"}, "errors":[ - {"shape":"InternalServerError"} + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns the list of severity levels that you can assign to a support case. The severity level for a case is also a field in the CaseDetails data type that you include for a CreateCase request.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns the list of severity levels that you can assign to a support case. The severity level for a case is also a field in the CaseDetails data type that you include for a CreateCase request.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeSupportedLanguages":{ "name":"DescribeSupportedLanguages", @@ -156,9 +195,10 @@ "output":{"shape":"DescribeSupportedLanguagesResponse"}, "errors":[ {"shape":"InternalServerError"}, - {"shape":"ThrottlingException"} + {"shape":"ThrottlingException"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Returns a list of supported languages for a specified categoryCode, issueType and serviceCode. The returned supported languages will include a ISO 639-1 code for the language, and the language display name.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Returns a list of supported languages for a specified categoryCode, issueType and serviceCode. The returned supported languages will include a ISO 639-1 code for the language, and the language display name.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "DescribeTrustedAdvisorCheckRefreshStatuses":{ "name":"DescribeTrustedAdvisorCheckRefreshStatuses", @@ -172,7 +212,7 @@ {"shape":"InternalServerError"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the refresh status of the Trusted Advisor checks that have the specified check IDs. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    Some checks are refreshed automatically, and you can't return their refresh statuses by using the DescribeTrustedAdvisorCheckRefreshStatuses operation. If you call this operation for these checks, you might see an InvalidParameterValue error.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"

    Returns the refresh status of the Trusted Advisor checks that have the specified check IDs. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    Some checks are refreshed automatically, and you can't return their refresh statuses by using the DescribeTrustedAdvisorCheckRefreshStatuses operation. If you call this operation for these checks, you might see an InvalidParameterValue error.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " }, "DescribeTrustedAdvisorCheckResult":{ "name":"DescribeTrustedAdvisorCheckResult", @@ -186,7 +226,7 @@ {"shape":"InternalServerError"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the results of the Trusted Advisor check that has the specified check ID. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    The response contains a TrustedAdvisorCheckResult object, which contains these three objects:

    In addition, the response contains these fields:

    • status - The alert status of the check can be ok (green), warning (yellow), error (red), or not_available.

    • timestamp - The time of the last refresh of the check.

    • checkId - The unique identifier for the check.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"

    Returns the results of the Trusted Advisor check that has the specified check ID. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    The response contains a TrustedAdvisorCheckResult object, which contains these three objects:

    In addition, the response contains these fields:

    • status - The alert status of the check can be ok (green), warning (yellow), error (red), or not_available.

    • timestamp - The time of the last refresh of the check.

    • checkId - The unique identifier for the check.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " }, "DescribeTrustedAdvisorCheckSummaries":{ "name":"DescribeTrustedAdvisorCheckSummaries", @@ -200,7 +240,7 @@ {"shape":"InternalServerError"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns the results for the Trusted Advisor check summaries for the check IDs that you specified. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    The response contains an array of TrustedAdvisorCheckSummary objects.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"

    Returns the results for the Trusted Advisor check summaries for the check IDs that you specified. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    The response contains an array of TrustedAdvisorCheckSummary objects.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    Understanding the Trusted Advisor Resources processed value

    The Resources processed value, resourcesProcessed, usually shows both flagged resources (those with warnings or errors) and resources in good standing (ok status resources). However, some checks report flagged resources only. To understand what a specific check reports, review the detailed check information in the Trusted Advisor check reference. If you see a Green criterion listed in the Alert criteria, then the check reports all resources. If there's no Green criterion listed in the Alert criteria, then the check reports only flagged resources. For example, the Amazon EC2 Reserved Instance optimization check (cX3c2R1chu) doesn't list a Green criterion in the Alert criteria. So, this check only reports flagged resources.

    " }, "DescribeTrustedAdvisorChecks":{ "name":"DescribeTrustedAdvisorChecks", @@ -214,7 +254,37 @@ {"shape":"InternalServerError"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Returns information about all available Trusted Advisor checks, including the name, ID, category, description, and metadata. You must specify a language code.

    The response contains a TrustedAdvisorCheckDescription object for each check. You must set the Amazon Web Services Region to us-east-1.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    • The names and descriptions for Trusted Advisor checks are subject to change. We recommend that you specify the check ID in your code to uniquely identify a check.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"

    Returns information about all available Trusted Advisor checks, including the name, ID, category, description, and metadata. You must specify a language code.

    The response contains a TrustedAdvisorCheckDescription object for each check. You must set the Amazon Web Services Region to us-east-1.

    • You must have a Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    • The names and descriptions for Trusted Advisor checks are subject to change. We recommend that you specify the check ID in your code to uniquely identify a check.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + }, + "GetAttachmentDownloadLink":{ + "name":"GetAttachmentDownloadLink", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAttachmentDownloadLinkRequest"}, + "output":{"shape":"GetAttachmentDownloadLinkResponse"}, + "errors":[ + {"shape":"AttachmentIdNotFound"}, + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"} + ], + "documentation":"

    Returns a presigned download URL for an attachment that is associated with a case communication. The download link works for an attachment of any size, including attachments added through AddAttachmentsToSet and attachments uploaded through GetAttachmentUploadLinks. The download URL is time-limited and expires at the date and time indicated in the downloadUrl response field. Download the attachment from the URL before it expires.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + }, + "GetAttachmentUploadLinks":{ + "name":"GetAttachmentUploadLinks", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetAttachmentUploadLinksRequest"}, + "output":{"shape":"GetAttachmentUploadLinksResponse"}, + "errors":[ + {"shape":"InternalServerError"}, + {"shape":"DryRunOperationException"}, + {"shape":"UploadIdNotFound"} + ], + "documentation":"

    Returns one or more presigned upload URLs for uploading a large file attachment to a support case by using a multipart upload workflow. The maximum file size that you can upload with this workflow is 150 MB, and parts can be up to 100 MB each. Initiate a new upload by providing fileName and fileSizeBytes; the response returns a unique uploadId, the part size, the total number of parts, and a list of presigned upload URLs for the requested range of parts. A maximum of 10 upload URLs are returned per call. To retrieve more upload URLs for an upload that's already in progress, call GetAttachmentUploadLinks again with the existing uploadId and a new uploadRange.

    Upload each part to its presigned URL by using HTTP PUT and capture the ETag from the response. After you upload all parts, call CompleteAttachmentUpload with the uploadId and the list of part indexes and ETags to finalize the upload. You can then attach the upload to a case by passing the uploadId in the uploadIds parameter of CreateCase or AddCommunicationToCase. To monitor progress before completion, call DescribeAttachmentUploadStatus.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " }, "RefreshTrustedAdvisorCheck":{ "name":"RefreshTrustedAdvisorCheck", @@ -227,7 +297,7 @@ "errors":[ {"shape":"InternalServerError"} ], - "documentation":"

    Refreshes the Trusted Advisor check that you specify using the check ID. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    Some checks are refreshed automatically. If you call the RefreshTrustedAdvisorCheck operation to refresh them, you might see the InvalidParameterValue error.

    The response contains a TrustedAdvisorCheckRefreshStatus object.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"

    Refreshes the Trusted Advisor check that you specify using the check ID. You can get the check IDs by calling the DescribeTrustedAdvisorChecks operation.

    Some checks are refreshed automatically. If you call the RefreshTrustedAdvisorCheck operation to refresh them, you might see the InvalidParameterValue error.

    The response contains a TrustedAdvisorCheckRefreshStatus object.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    To call the Trusted Advisor operations in the Amazon Web Services Support API, you must use the US East (N. Virginia) endpoint. Currently, the US West (Oregon) and Europe (Ireland) endpoints don't support the Trusted Advisor operations. For more information, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " }, "ResolveCase":{ "name":"ResolveCase", @@ -239,9 +309,10 @@ "output":{"shape":"ResolveCaseResponse"}, "errors":[ {"shape":"InternalServerError"}, - {"shape":"CaseIdNotFound"} + {"shape":"CaseIdNotFound"}, + {"shape":"DryRunOperationException"} ], - "documentation":"

    Resolves a support case. This operation takes a caseId and returns the initial and final state of the case.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " + "documentation":"

    Resolves a support case. This operation takes a caseId and returns the initial and final state of the case.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    " } }, "shapes":{ @@ -256,6 +327,10 @@ "attachments":{ "shape":"Attachments", "documentation":"

    One or more attachments to add to the set. You can add up to three attachments per set. The size limit is 5 MB per attachment.

    In the Attachment object, use the data parameter to specify the contents of the attachment file. In the previous request syntax, the value for data appear as blob, which is represented as a base64-encoded string. The value for fileName is the name of the attachment, such as troubleshoot-screenshot.png.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually adding the attachments. When set to true, the request is validated but no attachments are stored, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -279,7 +354,7 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " }, "communicationBody":{ "shape":"CommunicationBody", @@ -291,7 +366,15 @@ }, "attachmentSetId":{ "shape":"AttachmentSetId", - "documentation":"

    The ID of a set of one or more attachments for the communication to add to the case. Create the set by calling AddAttachmentsToSet

    " + "documentation":"

    The ID of a set of one or more attachments for the communication to add to the case. Create the set by calling AddAttachmentsToSet. Each attachment in the set must be 5 MB or smaller. To attach files larger than 5 MB, use uploadIds.

    " + }, + "uploadIds":{ + "shape":"UploadIds", + "documentation":"

    A list of upload IDs that identify attachments to add to the case. Each uploadId is returned by the GetAttachmentUploadLinks operation. The upload must reach the attachment-ready state by calling CompleteAttachmentUpload before it can be passed here. Use uploadIds to attach files of any supported size, including files larger than 5 MB.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually adding the communication to the case. When set to true, the request is validated but the communication isn't added, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -418,7 +501,7 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " }, "displayId":{ "shape":"DisplayId", @@ -462,10 +545,10 @@ }, "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " } }, - "documentation":"

    A JSON-formatted object that contains the metadata for a support case. It is contained in the response from a DescribeCases request. CaseDetails contains the following fields:

    • caseId - The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47.

    • categoryCode - The category of problem for the support case. Corresponds to the CategoryCode values returned by a call to DescribeServices.

    • displayId - The identifier for the case on pages in the Amazon Web Services Support Center.

    • language - The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    • nextToken - A resumption point for pagination.

    • recentCommunications - One or more Communication objects. Fields of these objects are attachments, body, caseId, submittedBy, and timeCreated.

    • serviceCode - The identifier for the Amazon Web Services service that corresponds to the service code defined in the call to DescribeServices.

    • severityCode - The severity code assigned to the case. Contains one of the values returned by the call to DescribeSeverityLevels. The possible values are: low, normal, high, urgent, and critical.

    • status - The status of the case in the Amazon Web Services Support Center. Valid values:

      • all-open

      • customer-action-completed

      • opened

      • pending-customer-action

      • reopened

      • resolved

      • unassigned

      • work-in-progress

    • subject - The subject line of the case.

    • submittedBy - The email address of the account that submitted the case.

    • timeCreated - The time the case was created, in ISO-8601 format.

    " + "documentation":"

    A JSON-formatted object that contains the metadata for a support case. It is contained in the response from a DescribeCases request. CaseDetails contains the following fields:

    • caseId - The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47.

    • categoryCode - The category of problem for the support case. Corresponds to the CategoryCode values returned by a call to DescribeServices.

    • displayId - The identifier for the case on pages in the Amazon Web Services Support Center.

    • language - The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    • nextToken - A resumption point for pagination.

    • recentCommunications - One or more Communication objects. Fields of these objects are attachments, body, caseId, submittedBy, and timeCreated.

    • serviceCode - The identifier for the Amazon Web Services service that corresponds to the service code defined in the call to DescribeServices.

    • severityCode - The severity code assigned to the case. Contains one of the values returned by the call to DescribeSeverityLevels. The possible values are: low, normal, high, urgent, and critical.

    • status - The status of the case in the Amazon Web Services Support Center. Valid values:

      • all-open

      • customer-action-completed

      • opened

      • pending-customer-action

      • reopened

      • resolved

      • unassigned

      • work-in-progress

    • subject - The subject line of the case.

    • submittedBy - The email address of the account that submitted the case.

    • timeCreated - The time the case was created, in ISO-8601 format.

    " }, "CaseId":{"type":"string"}, "CaseIdList":{ @@ -523,7 +606,7 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " }, "body":{ "shape":"ValidatedCommunicationBody", @@ -537,9 +620,13 @@ "shape":"TimeCreated", "documentation":"

    The time the communication was created.

    " }, + "attachments":{ + "shape":"AttachmentSet", + "documentation":"

    Information about all attachments on the case communication. This includes attachments added through AddAttachmentsToSet and attachments uploaded through GetAttachmentUploadLinks.

    Use this field to enumerate every attachment on the communication. To download an attachment listed in this field, use GetAttachmentDownloadLink. GetAttachmentDownloadLink returns a presigned URL that works for attachments of any size.

    " + }, "attachmentSet":{ "shape":"AttachmentSet", - "documentation":"

    Information about the attachments to the case communication.

    " + "documentation":"

    Information about the attachments to the case communication that are 5 MB or smaller. This field doesn't include attachments larger than 5 MB. To enumerate every attachment on the communication, including attachments larger than 5 MB, use the attachments field instead.

    " } }, "documentation":"

    A communication associated with a support case. The communication consists of the case ID, the message body, attachment information, the submitter of the communication, and the date and time of the communication.

    " @@ -577,6 +664,61 @@ "max":100, "min":1 }, + "CompleteAttachmentUploadRequest":{ + "type":"structure", + "required":[ + "uploadId", + "completedUploads" + ], + "members":{ + "uploadId":{ + "shape":"UploadId", + "documentation":"

    The identifier associated with the upload to complete.

    " + }, + "completedUploads":{ + "shape":"CompletedUploadList", + "documentation":"

    The list of parts being reported as completed in this call. Each entry must contain the partIndex of an uploaded part and the ETag returned by Amazon S3 when that part was uploaded.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually completing the upload. When set to true, the request is validated but the upload isn't finalized, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " + } + } + }, + "CompleteAttachmentUploadResponse":{ + "type":"structure", + "required":["uploadStatus"], + "members":{ + "uploadStatus":{ + "shape":"UploadStatus", + "documentation":"

    The status of the multipart upload after the operation finalizes the attachment. Valid values: attachment-ready, attachment-not-ready, and failed.

    " + } + } + }, + "CompletedUpload":{ + "type":"structure", + "required":[ + "partIndex", + "eTag" + ], + "members":{ + "partIndex":{ + "shape":"FieldIntegerValue", + "documentation":"

    The index of the uploaded part. This is the same partIndex value returned for the corresponding entry in the uploadUrls field of the GetAttachmentUploadLinks response.

    " + }, + "eTag":{ + "shape":"ETag", + "documentation":"

    The ETag returned in the response headers when the part was uploaded to Amazon S3. The ETag value identifies the part contents.

    " + } + }, + "documentation":"

    Identifies a single uploaded part of a multipart attachment upload. Pass a list of CompletedUpload objects to CompleteAttachmentUpload to finalize the upload.

    " + }, + "CompletedUploadList":{ + "type":"list", + "member":{"shape":"CompletedUpload"} + }, + "CoralAvailabilityThrottledResource":{"type":"string"}, + "CoralAvailabilityThrottlingReason":{"type":"string"}, "CreateCaseRequest":{ "type":"structure", "required":[ @@ -610,7 +752,7 @@ }, "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " }, "issueType":{ "shape":"IssueType", @@ -618,7 +760,15 @@ }, "attachmentSetId":{ "shape":"AttachmentSetId", - "documentation":"

    The ID of a set of one or more attachments for the case. Create the set by using the AddAttachmentsToSet operation.

    " + "documentation":"

    The ID of a set of one or more attachments for the case. Create the set by using the AddAttachmentsToSet operation. Each attachment in the set must be 5 MB or smaller. To attach files larger than 5 MB, use uploadIds.

    " + }, + "uploadIds":{ + "shape":"UploadIds", + "documentation":"

    A list of upload IDs that identify attachments to add to the case. Each uploadId is returned by the GetAttachmentUploadLinks operation. The upload must reach the attachment-ready state by calling CompleteAttachmentUpload before it can be passed here. Use uploadIds to attach files of any supported size, including files larger than 5 MB.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually creating the case. When set to true, the request is validated but no case is created, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -627,7 +777,7 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string in the following format: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string in the following format: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " } }, "documentation":"

    The support case ID returned by a successful completion of the CreateCase operation.

    " @@ -668,7 +818,11 @@ "members":{ "attachmentId":{ "shape":"AttachmentId", - "documentation":"

    The ID of the attachment to return. Attachment IDs are returned by the DescribeCommunications operation.

    " + "documentation":"

    The ID of the attachment to return. Attachment IDs are returned by the DescribeCommunications operation.

    If the specified attachment is larger than 5 MB, this operation returns InvalidParameterValueException. To download attachments larger than 5 MB, use GetAttachmentDownloadLink.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually retrieving the attachment. When set to true, the request is validated but no attachment content is returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -682,6 +836,41 @@ }, "documentation":"

    The content and file name of the attachment returned by the DescribeAttachment operation.

    " }, + "DescribeAttachmentUploadStatusRequest":{ + "type":"structure", + "required":["uploadId"], + "members":{ + "uploadId":{ + "shape":"UploadId", + "documentation":"

    The unique identifier for the upload. The uploadId is returned by GetAttachmentUploadLinks when you initiate the upload.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning upload status. When set to true, the request is validated but no status is returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " + } + } + }, + "DescribeAttachmentUploadStatusResponse":{ + "type":"structure", + "required":[ + "uploadStatus", + "fileName" + ], + "members":{ + "uploadStatus":{ + "shape":"UploadStatus", + "documentation":"

    The current status of the multipart upload. Valid values: attachment-ready, attachment-not-ready, and failed.

    " + }, + "fileName":{ + "shape":"FileName", + "documentation":"

    The name of the file being uploaded, including the file extension.

    " + }, + "uploadProgress":{ + "shape":"UploadProgress", + "documentation":"

    The progress of the multipart upload, including the total number of parts and the number of parts that have been successfully uploaded.

    " + } + } + }, "DescribeCasesRequest":{ "type":"structure", "members":{ @@ -695,11 +884,11 @@ }, "afterTime":{ "shape":"AfterTime", - "documentation":"

    The start date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

    " + "documentation":"

    The start date for a filtered date search on support case communications. Case communications are available for 24 months after creation.

    " }, "beforeTime":{ "shape":"BeforeTime", - "documentation":"

    The end date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

    " + "documentation":"

    The end date for a filtered date search on support case communications. Case communications are available for 24 months after creation.

    " }, "includeResolvedCases":{ "shape":"IncludeResolvedCases", @@ -715,11 +904,15 @@ }, "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " }, "includeCommunications":{ "shape":"IncludeCommunications", "documentation":"

    Specifies whether to include communications in the DescribeCases response. By default, communications are included.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning case data. When set to true, the request is validated but no cases are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -743,15 +936,15 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " }, "beforeTime":{ "shape":"BeforeTime", - "documentation":"

    The end date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

    " + "documentation":"

    The end date for a filtered date search on support case communications. Case communications are available for 24 months after creation.

    " }, "afterTime":{ "shape":"AfterTime", - "documentation":"

    The start date for a filtered date search on support case communications. Case communications are available for 12 months after creation.

    " + "documentation":"

    The start date for a filtered date search on support case communications. Case communications are available for 24 months after creation.

    " }, "nextToken":{ "shape":"NextToken", @@ -760,6 +953,10 @@ "maxResults":{ "shape":"MaxResults", "documentation":"

    The maximum number of results to return before paginating.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning communications. When set to true, the request is validated but no communications are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -796,11 +993,15 @@ }, "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " }, "categoryCode":{ "shape":"CategoryCode", "documentation":"

    The category of problem for the support case. You also use the DescribeServices operation to get the category code for a service. Each Amazon Web Services service defines its own set of category codes.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning case option data. When set to true, the request is validated but no options are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -826,7 +1027,11 @@ }, "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning the list of services. When set to true, the request is validated but no services are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -845,7 +1050,11 @@ "members":{ "language":{ "shape":"Language", - "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") and Korean (“ko”). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + "documentation":"

    The language in which Amazon Web Services Support handles the case. Amazon Web Services Support currently supports Chinese (“zh”), English (\"en\"), Japanese (\"ja\") , Chinese (\"zh\"), Spanish (\"es\"), Portuguese (\"pt\"), French (\"fr\"), Korean (“ko”), and Turkish (\"tr\"). You must specify the ISO 639-1 code for the language parameter if you want support in that language.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning severity levels. When set to true, the request is validated but no severity levels are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -878,6 +1087,10 @@ "categoryCode":{ "shape":"ValidatedCategoryCode", "documentation":"

    The category of problem for the support case. You also use the DescribeServices operation to get the category code for a service. Each Amazon Web Services service defines its own set of category codes.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning supported languages. When set to true, the request is validated but no languages are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -981,12 +1194,147 @@ "Display":{"type":"string"}, "DisplayId":{"type":"string"}, "Double":{"type":"double"}, + "DownloadUrl":{ + "type":"structure", + "required":[ + "url", + "expiryDate" + ], + "members":{ + "url":{ + "shape":"HttpsUrl", + "documentation":"

    The presigned HTTPS URL that you can use to download the attachment. Download URLs are served from downloadv1.attachments.support.{region}.amazonaws.com. The downloadv1 prefix is subject to change.

    " + }, + "expiryDate":{ + "shape":"ValidatedDateTime", + "documentation":"

    The date and time, in ISO-8601 format, when the presigned URL expires. Download the attachment before this time.

    " + } + }, + "documentation":"

    A presigned URL for downloading an attachment, along with the date and time the URL expires. Returned by GetAttachmentDownloadLink.

    " + }, + "DryRunOperationException":{ + "type":"structure", + "members":{ + "message":{"shape":"ErrorMessage"} + }, + "documentation":"

    The request was valid, but the operation wasn't performed because dryRun was set to true.

    ", + "exception":true + }, + "ETag":{ + "type":"string", + "max":256, + "min":1 + }, + "EndIndex":{ + "type":"integer", + "min":2 + }, "EndTime":{"type":"string"}, "ErrorMessage":{"type":"string"}, "ExpiryTime":{"type":"string"}, + "FieldIntegerValue":{"type":"integer"}, "FileName":{"type":"string"}, + "FileSize":{ + "type":"long", + "max":157286400, + "min":1 + }, + "GetAttachmentDownloadLinkRequest":{ + "type":"structure", + "required":["attachmentId"], + "members":{ + "attachmentId":{ + "shape":"AttachmentId", + "documentation":"

    The unique identifier of the attachment for which to retrieve a download link. Attachment IDs are returned in the AttachmentDetails objects in the attachments field of a Communication returned by DescribeCommunications or DescribeCases.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually returning a download link. When set to true, the request is validated but no URL is returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " + } + } + }, + "GetAttachmentDownloadLinkResponse":{ + "type":"structure", + "required":[ + "fileName", + "downloadUrl" + ], + "members":{ + "fileName":{ + "shape":"FileName", + "documentation":"

    The name of the attachment file, including the file extension.

    " + }, + "downloadUrl":{ + "shape":"DownloadUrl", + "documentation":"

    The presigned download URL and the date and time the URL expires.

    " + } + } + }, + "GetAttachmentUploadLinksRequest":{ + "type":"structure", + "required":["fileName"], + "members":{ + "fileName":{ + "shape":"FileName", + "documentation":"

    The name of the file to upload, including the file extension. This value is required when you initiate a new upload.

    " + }, + "fileSizeBytes":{ + "shape":"FileSize", + "documentation":"

    The total size of the file in bytes. The service uses this value to calculate the total number of parts and the size of each part. Required when you initiate a new upload (when uploadId isn't provided). Valid range: 1 to 157,286,400 bytes (approximately 150 MB).

    " + }, + "uploadId":{ + "shape":"UploadId", + "documentation":"

    The unique identifier of an in-progress multipart upload, returned by a previous call to GetAttachmentUploadLinks. Specify uploadId to retrieve additional presigned upload URLs for an upload that has already been initiated. Required when fileSizeBytes isn't provided. Length: 1 to 2,048 characters.

    " + }, + "uploadRange":{ + "shape":"UploadRange", + "documentation":"

    The range of part indexes for which to return presigned upload URLs. Use this parameter to page through the upload URLs for a large file across multiple calls. If you omit this parameter, the service determines the range to return.

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually generating upload URLs. When set to true, the request is validated but no URLs are returned, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " + } + } + }, + "GetAttachmentUploadLinksResponse":{ + "type":"structure", + "required":[ + "uploadId", + "partSizeBytes", + "totalParts", + "uploadUrls" + ], + "members":{ + "uploadId":{ + "shape":"UploadId", + "documentation":"

    The unique identifier for the multipart upload. Use this value in subsequent calls to GetAttachmentUploadLinks, DescribeAttachmentUploadStatus, and CompleteAttachmentUpload, and to attach the upload to a case through the uploadIds parameter on CreateCase or AddCommunicationToCase.

    " + }, + "partSizeBytes":{ + "shape":"PartSizeBytes", + "documentation":"

    The size, in bytes, of each part. Split the file into parts of this size before you upload them to the presigned URLs. For an upload with n total parts, parts 1 through n - 1 are exactly this size; the last part may be smaller. Maximum: 104,857,600 bytes (approximately 100 MB).

    " + }, + "totalParts":{ + "shape":"Integer", + "documentation":"

    The total number of parts that the file is split into. Upload one part to each presigned URL.

    " + }, + "nextIndex":{ + "shape":"Integer", + "documentation":"

    The next part index to request presigned URLs for. If all upload URLs for the file have been returned, this field is null. Use this value as the startIndex in uploadRange on a subsequent call to GetAttachmentUploadLinks to retrieve the next batch of upload URLs.

    " + }, + "uploadUrls":{ + "shape":"UploadUrlList", + "documentation":"

    The list of presigned upload URLs for the requested range of parts. The list contains at most 10 URLs per call. Upload each part to its corresponding URL by using HTTP PUT before the URL expires.

    " + } + } + }, + "HttpsUrl":{ + "type":"string", + "min":8, + "pattern":"^https://[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]\\.[a-zA-Z]{2,}(/.*)?$" + }, "IncludeCommunications":{"type":"boolean"}, "IncludeResolvedCases":{"type":"boolean"}, + "Integer":{"type":"integer"}, "InternalServerError":{ "type":"structure", "members":{ @@ -1008,6 +1356,12 @@ "min":10 }, "NextToken":{"type":"string"}, + "NullableBooleanType":{"type":"boolean"}, + "PartSizeBytes":{ + "type":"long", + "max":104857600, + "min":1 + }, "RecentCaseCommunications":{ "type":"structure", "members":{ @@ -1049,7 +1403,11 @@ "members":{ "caseId":{ "shape":"CaseId", - "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-2013-c4c1d2bf33c5cf47

    " + "documentation":"

    The support case ID requested or returned in the call. The case ID is an alphanumeric string formatted as shown in this example: case-12345678910-exen-2025-c4c1d2bf33c5cf47

    " + }, + "dryRun":{ + "shape":"NullableBooleanType", + "documentation":"

    Specifies whether to validate the request without actually resolving the case. When set to true, the request is validated but the case isn't resolved, and the operation returns a DryRunOperationException. When omitted or set to false, the request runs normally.

    " } } }, @@ -1119,6 +1477,10 @@ "type":"list", "member":{"shape":"SeverityLevel"} }, + "StartIndex":{ + "type":"integer", + "min":1 + }, "StartTime":{"type":"string"}, "Status":{"type":"string"}, "String":{"type":"string"}, @@ -1173,12 +1535,34 @@ "ThrottlingException":{ "type":"structure", "members":{ - "message":{"shape":"AvailabilityErrorMessage"} + "message":{"shape":"AvailabilityErrorMessage"}, + "throttlingReasons":{ + "shape":"ThrottlingReasonList", + "documentation":"

    A list of one or more reasons that the request was throttled.

    " + } }, "documentation":"

    You have exceeded the maximum allowed TPS (Transactions Per Second) for the operations.

    ", "exception":true, "synthetic":true }, + "ThrottlingReason":{ + "type":"structure", + "members":{ + "reason":{ + "shape":"CoralAvailabilityThrottlingReason", + "documentation":"

    The reason that the request was throttled.

    " + }, + "resource":{ + "shape":"CoralAvailabilityThrottledResource", + "documentation":"

    The resource that caused the request to be throttled.

    " + } + }, + "documentation":"

    Information about why a request was throttled.

    " + }, + "ThrottlingReasonList":{ + "type":"list", + "member":{"shape":"ThrottlingReason"} + }, "TimeCreated":{"type":"string"}, "TrustedAdvisorCategorySpecificSummary":{ "type":"structure", @@ -1409,6 +1793,89 @@ "documentation":"

    Details about Amazon Web Services resources that were analyzed in a call to Trusted Advisor DescribeTrustedAdvisorCheckSummaries.

    " }, "Type":{"type":"string"}, + "UploadId":{ + "type":"string", + "max":2048, + "min":1 + }, + "UploadIdNotFound":{ + "type":"structure", + "members":{ + "message":{"shape":"ErrorMessage"} + }, + "documentation":"

    The specified uploadId couldn't be located.

    ", + "exception":true + }, + "UploadIds":{ + "type":"list", + "member":{"shape":"UploadId"}, + "max":10, + "min":0 + }, + "UploadProgress":{ + "type":"structure", + "members":{ + "totalParts":{ + "shape":"FieldIntegerValue", + "documentation":"

    The total number of parts that the file is split into.

    " + }, + "completedPartsCount":{ + "shape":"FieldIntegerValue", + "documentation":"

    The number of parts that have been successfully uploaded.

    " + } + }, + "documentation":"

    The progress of a multipart attachment upload, returned by DescribeAttachmentUploadStatus.

    " + }, + "UploadRange":{ + "type":"structure", + "required":["startIndex"], + "members":{ + "startIndex":{ + "shape":"StartIndex", + "documentation":"

    The starting part index of the range, inclusive. Part indexes start at 1.

    " + }, + "endIndex":{ + "shape":"EndIndex", + "documentation":"

    The ending part index of the range, exclusive. The range is half-open: startIndex is inclusive and endIndex is exclusive. For example, a range with startIndex of 1 and endIndex of 4 requests URLs for parts 1, 2, and 3. The range size (endIndex - startIndex) must not exceed 10. If you omit endIndex, the service defaults to startIndex + 10, capped by the total number of parts.

    " + } + }, + "documentation":"

    The range of part indexes for which to return presigned upload URLs from GetAttachmentUploadLinks.

    " + }, + "UploadStatus":{ + "type":"string", + "enum":[ + "attachment-ready", + "attachment-not-ready", + "failed" + ] + }, + "UploadUrl":{ + "type":"structure", + "required":[ + "url", + "partIndex", + "expiryDate" + ], + "members":{ + "url":{ + "shape":"HttpsUrl", + "documentation":"

    The presigned HTTPS URL that you use to upload a single part with HTTP PUT. Upload URLs are served from uploadv1.attachments.support.{region}.amazonaws.com. The uploadv1 prefix is subject to change.

    " + }, + "partIndex":{ + "shape":"Integer", + "documentation":"

    The index of the part that this URL uploads.

    " + }, + "expiryDate":{ + "shape":"ValidatedDateTime", + "documentation":"

    The date and time, in ISO-8601 format, when the presigned URL expires. Upload the part before this time.

    " + } + }, + "documentation":"

    A presigned URL for uploading a single part of a multipart attachment upload, along with the part index and the date and time the URL expires. Returned by GetAttachmentUploadLinks.

    " + }, + "UploadUrlList":{ + "type":"list", + "member":{"shape":"UploadUrl"} + }, "ValidatedCategoryCode":{ "type":"string", "max":100, @@ -1440,5 +1907,5 @@ "min":0 } }, - "documentation":"Amazon Web Services Support

    The Amazon Web Services Support API Reference is intended for programmers who need detailed information about the Amazon Web Services Support operations and data types. You can use the API to manage your support cases programmatically. The Amazon Web Services Support API uses HTTP methods that return results in JSON format.

    • You must have a Business, Enterprise On-Ramp, or Enterprise Support plan to use the Amazon Web Services Support API.

    • If you call the Amazon Web Services Support API from an account that doesn't have a Business, Enterprise On-Ramp, or Enterprise Support plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    You can also use the Amazon Web Services Support API to access features for Trusted Advisor. You can return a list of checks and their descriptions, get check results, specify checks to refresh, and get the refresh status of checks.

    You can manage your support cases with the following Amazon Web Services Support API operations:

    You can also use the Amazon Web Services Support API to call the Trusted Advisor operations. For more information, see Trusted Advisor in the Amazon Web Services Support User Guide.

    For authentication of requests, Amazon Web Services Support uses Signature Version 4 Signing Process.

    For more information about this service and the endpoints to use, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " + "documentation":"Amazon Web Services Support

    The Amazon Web Services Support API Reference is intended for programmers who need detailed information about the Amazon Web Services Support operations and data types. You can use the API to manage your support cases programmatically. The Amazon Web Services Support API uses HTTP methods that return results in JSON format.

    • You must have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan to use the Amazon Web Services Support API. If you're in an Amazon Web Services Region that doesn't offer one of these Amazon Web Services Support plans, or if you haven't transitioned to one of these plans, you can use the Amazon Web Services Support API with a Business, Enterprise On-Ramp, or Enterprise Support plan.

    • If you call the Amazon Web Services Support API from an account that doesn't have an Amazon Web Services Business Support+, Amazon Web Services Enterprise Support, or Amazon Web Services Unified Operations plan, the SubscriptionRequiredException error message appears. For information about changing your support plan, see Amazon Web Services Support.

    You can also use the Amazon Web Services Support API to access features for Trusted Advisor. You can return a list of checks and their descriptions, get check results, specify checks to refresh, and get the refresh status of checks.

    You can manage your support cases with the following Amazon Web Services Support API operations:

    You can also use the Amazon Web Services Support API to call the Trusted Advisor operations. For more information, see Trusted Advisor in the Amazon Web Services Support User Guide.

    For authentication of requests, Amazon Web Services Support uses Signature Version 4 Signing Process.

    For more information about this service and the endpoints to use, see About the Amazon Web Services Support API in the Amazon Web Services Support User Guide.

    " } diff --git a/services/supportapp/pom.xml b/services/supportapp/pom.xml index e529db0de879..c51a977684f9 100644 --- a/services/supportapp/pom.xml +++ b/services/supportapp/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT supportapp AWS Java SDK :: Services :: Support App diff --git a/services/supportapp/src/main/resources/codegen-resources/customization.config b/services/supportapp/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/supportapp/src/main/resources/codegen-resources/customization.config +++ b/services/supportapp/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/supportapp/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/supportapp/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..97c5a1f257a3 --- /dev/null +++ b/services/supportapp/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportapp-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportapp-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportapp.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportapp.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/supportapp/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/supportapp/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b01313f14d3a..000000000000 --- a/services/supportapp/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://supportapp-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://supportapp-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://supportapp.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://supportapp.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/supportauthz/pom.xml b/services/supportauthz/pom.xml index 68599369876f..4252cb7bb627 100644 --- a/services/supportauthz/pom.xml +++ b/services/supportauthz/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT supportauthz AWS Java SDK :: Services :: Support AuthZ diff --git a/services/supportauthz/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/supportauthz/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..cd7ceeafa95d --- /dev/null +++ b/services/supportauthz/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportauthz-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://supportauthz.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/supportauthz/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/supportauthz/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b92f4c796eed..000000000000 --- a/services/supportauthz/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://supportauthz-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://supportauthz.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sustainability/pom.xml b/services/sustainability/pom.xml index 2bd4c5fc7891..56f3de152f80 100644 --- a/services/sustainability/pom.xml +++ b/services/sustainability/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT sustainability AWS Java SDK :: Services :: Sustainability diff --git a/services/sustainability/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/sustainability/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f0c869a9b85a --- /dev/null +++ b/services/sustainability/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,238 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://api.sustainability.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sustainability.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sustainability-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "us-gov-west-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sustainability-fips.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://sustainability.global.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4a", + "signingRegionSet": [ + "*" + ] + }, + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 9, + "nodes": "/////wAAAAH/////AAAAAAAAAAkAAAADAAAAAQAAAAQF9eEIAAAAAgAAAAUF9eEIAAAAAwAAAAgAAAAGAAAABAX14QMAAAAHAAAABQX14QQF9eEHAAAABQX14QUF9eEGAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/sustainability/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/sustainability/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 38c1ed79e230..000000000000 --- a/services/sustainability/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://api.sustainability.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - } - ], - "endpoint": { - "url": "https://sustainability.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://sustainability-fips.us-gov.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "us-gov-west-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://sustainability-fips.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://sustainability.global.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4a", - "signingRegionSet": [ - "*" - ] - }, - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/sustainability/src/main/resources/codegen-resources/paginators-1.json b/services/sustainability/src/main/resources/codegen-resources/paginators-1.json index c3de2178cfc3..41156c58148b 100644 --- a/services/sustainability/src/main/resources/codegen-resources/paginators-1.json +++ b/services/sustainability/src/main/resources/codegen-resources/paginators-1.json @@ -11,6 +11,18 @@ "output_token": "NextToken", "limit_key": "MaxResults", "result_key": "Results" + }, + "GetEstimatedWaterAllocation": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Results" + }, + "GetEstimatedWaterAllocationDimensionValues": { + "input_token": "NextToken", + "output_token": "NextToken", + "limit_key": "MaxResults", + "result_key": "Results" } } } diff --git a/services/sustainability/src/main/resources/codegen-resources/service-2.json b/services/sustainability/src/main/resources/codegen-resources/service-2.json index f52831e1e8ab..12af3061338c 100644 --- a/services/sustainability/src/main/resources/codegen-resources/service-2.json +++ b/services/sustainability/src/main/resources/codegen-resources/service-2.json @@ -51,6 +51,42 @@ ], "documentation":"

    Returns the possible dimension values available for a customer's account. We recommend using pagination to ensure that the operation returns quickly and successfully.

    ", "readonly":true + }, + "GetEstimatedWaterAllocation":{ + "name":"GetEstimatedWaterAllocation", + "http":{ + "method":"POST", + "requestUri":"/v1/estimated-water-allocation", + "responseCode":200 + }, + "input":{"shape":"GetEstimatedWaterAllocationRequest"}, + "output":{"shape":"GetEstimatedWaterAllocationResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns estimated water allocation values based on customer grouping and filtering parameters. We recommend using pagination to ensure that the operation returns quickly and successfully.

    ", + "readonly":true + }, + "GetEstimatedWaterAllocationDimensionValues":{ + "name":"GetEstimatedWaterAllocationDimensionValues", + "http":{ + "method":"POST", + "requestUri":"/v1/estimated-water-allocation-dimension-values", + "responseCode":200 + }, + "input":{"shape":"GetEstimatedWaterAllocationDimensionValuesRequest"}, + "output":{"shape":"GetEstimatedWaterAllocationDimensionValuesResponse"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"AccessDeniedException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns the possible dimension values available for a customer's account. We recommend using pagination to ensure that the operation returns quickly and successfully.

    ", + "readonly":true } }, "shapes":{ @@ -72,7 +108,7 @@ }, "Dimension":{ "type":"string", - "documentation":"

    Specifies the dimensions available for grouping and filtering emissions data.

    ", + "documentation":"

    Specifies the dimensions available for grouping and filtering environmental impact data.

    ", "enum":[ "USAGE_ACCOUNT_ID", "REGION", @@ -91,7 +127,7 @@ "documentation":"

    The dimension type that categorizes this entry.

    " }, "Value":{ - "shape":"String", + "shape":"DimensionValue", "documentation":"

    The value for the specified dimension. Valid values vary based on the dimension type (e.g., us-east-1 for the REGION dimension, AmazonEC2 for the SERVICE dimension).

    " } }, @@ -110,14 +146,19 @@ "key":{"shape":"Dimension"}, "value":{"shape":"DimensionValueList"} }, + "DimensionValue":{ + "type":"string", + "max":256, + "min":0 + }, "DimensionValueList":{ "type":"list", - "member":{"shape":"String"} + "member":{"shape":"DimensionValue"} }, "DimensionsMap":{ "type":"map", "key":{"shape":"Dimension"}, - "value":{"shape":"String"} + "value":{"shape":"DimensionValue"} }, "Double":{ "type":"double", @@ -200,15 +241,47 @@ "type":"list", "member":{"shape":"EstimatedCarbonEmissions"} }, + "EstimatedWaterAllocation":{ + "type":"structure", + "required":[ + "TimePeriod", + "DimensionsValues", + "ModelVersion", + "AllocationValues" + ], + "members":{ + "TimePeriod":{ + "shape":"TimePeriod", + "documentation":"

    The reporting period for water allocation values.

    " + }, + "DimensionsValues":{ + "shape":"DimensionsMap", + "documentation":"

    The dimensions used to group water allocation values.

    " + }, + "ModelVersion":{ + "shape":"ModelVersion", + "documentation":"

    The semantic version-formatted string that indicates the methodology version used to calculate the water allocation values.

    The AWS Sustainability service reflects the most recent model version for every month. You will not see two entries for the same month with different ModelVersion values.

    " + }, + "AllocationValues":{ + "shape":"WaterAllocationMap", + "documentation":"

    The allocation values for the requested water allocation types.

    " + } + }, + "documentation":"

    Contains estimated water allocation data for a specific time period and dimension grouping.

    " + }, + "EstimatedWaterAllocationList":{ + "type":"list", + "member":{"shape":"EstimatedWaterAllocation"} + }, "FilterExpression":{ "type":"structure", "members":{ "Dimensions":{ "shape":"DimensionListMap", - "documentation":"

    Filters emission values by specific dimension values.

    " + "documentation":"

    Filters environmental impact values by specific dimension values.

    " } }, - "documentation":"

    Filters emission values by specific dimension values.

    " + "documentation":"

    Filters environmental impact values by specific dimension values.

    " }, "GetEstimatedCarbonEmissionsDimensionValuesRequest":{ "type":"structure", @@ -219,7 +292,7 @@ "members":{ "TimePeriod":{ "shape":"TimePeriod", - "documentation":"

    The date range for fetching the dimension values.

    " + "documentation":"

    The date range for fetching the dimension values. The range must include the start date of a month for that month's dimensions to be included in the response.

    " }, "Dimensions":{ "shape":"DimensionList", @@ -227,7 +300,7 @@ }, "MaxResults":{ "shape":"MaxResults", - "documentation":"

    The maximum number of results to return in a single call. Default is 40.

    " + "documentation":"

    The maximum number of results to return in a single call. Default is 1000.

    " }, "NextToken":{ "shape":"NextToken", @@ -254,7 +327,7 @@ "members":{ "TimePeriod":{ "shape":"TimePeriod", - "documentation":"

    The date range for fetching estimated carbon emissions.

    " + "documentation":"

    The date range for fetching estimated carbon emissions. The range must include the start date of a month for that month's data to be included in the response.

    " }, "GroupBy":{ "shape":"DimensionList", @@ -262,7 +335,7 @@ }, "FilterBy":{ "shape":"FilterExpression", - "documentation":"

    The criteria for filtering estimated carbon emissions.

    " + "documentation":"

    The criteria for filtering estimated carbon emissions. To determine which dimensions are available to be filtered by, you can first call GetEstimatedCarbonEmissionsDimensionValues

    " }, "EmissionsTypes":{ "shape":"EmissionsTypeList", @@ -270,7 +343,7 @@ }, "Granularity":{ "shape":"TimeGranularity", - "documentation":"

    The time granularity for the results. If absent, uses MONTHLY time granularity.

    " + "documentation":"

    The time granularity for the results. If absent, uses MONTHLY time granularity. The smallest supported granularity for carbon emissions is MONTHLY.

    If requesting partial time periods, data will be returned based on the smallest supported granularity. For example, requesting 2025-04-01T00:00:00Z to 2026-04-01T00:00:00Z with YEARLY_CALENDAR granularity will return the last 9 months for 2025 and the first 3 months of 2026.

    " }, "GranularityConfiguration":{ "shape":"GranularityConfiguration", @@ -278,7 +351,7 @@ }, "MaxResults":{ "shape":"MaxResults", - "documentation":"

    The maximum number of results to return in a single call. Default is 40.

    " + "documentation":"

    The maximum number of results to return in a single call. Default is 1000.

    " }, "NextToken":{ "shape":"NextToken", @@ -300,6 +373,93 @@ } } }, + "GetEstimatedWaterAllocationDimensionValuesRequest":{ + "type":"structure", + "required":[ + "TimePeriod", + "Dimensions" + ], + "members":{ + "TimePeriod":{ + "shape":"TimePeriod", + "documentation":"

    The date range for fetching the dimension values. The range must include the start date of a year for that year's data to be included in the response.

    " + }, + "Dimensions":{ + "shape":"DimensionList", + "documentation":"

    The dimensions available for grouping estimated water allocation.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Default is 1000.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token specifying which page of results to return in the response. If no token is provided, the default page is the first page.

    " + } + } + }, + "GetEstimatedWaterAllocationDimensionValuesResponse":{ + "type":"structure", + "required":["Results"], + "members":{ + "Results":{ + "shape":"DimensionEntryList", + "documentation":"

    The list of possible dimensions over which the allocation data is aggregated.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token indicating there are additional pages available. You can use the token in a following request to fetch the next set of results.

    " + } + } + }, + "GetEstimatedWaterAllocationRequest":{ + "type":"structure", + "required":["TimePeriod"], + "members":{ + "TimePeriod":{ + "shape":"TimePeriod", + "documentation":"

    The date range for fetching estimated water allocation. The range must include the start date of a year for that year's data to be included in the response.

    " + }, + "GroupBy":{ + "shape":"DimensionList", + "documentation":"

    The dimensions available for grouping estimated water allocation.

    " + }, + "FilterBy":{ + "shape":"FilterExpression", + "documentation":"

    The criteria for filtering estimated water allocation. To determine which dimensions are available to be filtered by, you can first call GetEstimatedWaterAllocationDimensionValues

    " + }, + "AllocationTypes":{ + "shape":"WaterAllocationTypeList", + "documentation":"

    The allocation types to include in the results. If absent, returns TOTAL_WATER_WITHDRAWALS allocation types.

    " + }, + "Granularity":{ + "shape":"TimeGranularity", + "documentation":"

    The time granularity for the results. Only YEARLY_CALENDAR time granularity is currently supported for water allocation. Defaults to YEARLY_CALENDAR if absent.

    If requesting partial time periods, data will be returned based on the smallest supported granularity. For example, requesting 2025-04-01T00:00:00Z to 2026-04-01T00:00:00Z with YEARLY_CALENDAR will return all the data for 2026 only.

    " + }, + "MaxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of results to return in a single call. Default is 1000.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token specifying which page of results to return in the response. If no token is provided, the default page is the first page.

    " + } + } + }, + "GetEstimatedWaterAllocationResponse":{ + "type":"structure", + "required":["Results"], + "members":{ + "Results":{ + "shape":"EstimatedWaterAllocationList", + "documentation":"

    The result of the requested inputs.

    " + }, + "NextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token indicating there are additional pages available. You can use the token in a following request to fetch the next set of results.

    " + } + } + }, "GranularityConfiguration":{ "type":"structure", "members":{ @@ -366,7 +526,7 @@ }, "TimeGranularity":{ "type":"string", - "documentation":"

    Specifies the time period over which emissions data is aggregated.

    ", + "documentation":"

    Specifies the time period over which environmental impact data is aggregated.

    ", "enum":[ "YEARLY_CALENDAR", "YEARLY_FISCAL", @@ -412,7 +572,44 @@ "senderFault":true }, "exception":true + }, + "WaterAllocation":{ + "type":"structure", + "required":[ + "Value", + "Unit" + ], + "members":{ + "Value":{ + "shape":"Double", + "documentation":"

    The numeric value of the allocation quantity.

    " + }, + "Unit":{ + "shape":"WaterAllocationUnit", + "documentation":"

    The unit of measurement for the allocation value.

    " + } + }, + "documentation":"

    Represents a water allocation quantity with its value and unit of measurement.

    " + }, + "WaterAllocationMap":{ + "type":"map", + "key":{"shape":"WaterAllocationType"}, + "value":{"shape":"WaterAllocation"} + }, + "WaterAllocationType":{ + "type":"string", + "documentation":"

    Specifies the types of water allocation calculations available.

    ", + "enum":["TOTAL_WATER_WITHDRAWALS"] + }, + "WaterAllocationTypeList":{ + "type":"list", + "member":{"shape":"WaterAllocationType"} + }, + "WaterAllocationUnit":{ + "type":"string", + "documentation":"

    Specifies the unit of measurement for allocation.

    ", + "enum":["m3"] } }, - "documentation":"

    The AWS Sustainability service provides programmatic access to estimated carbon emissions data for your Amazon Web Services usage. Use the AWS Sustainability service to retrieve, analyze, and track the carbon footprint of your cloud infrastructure over time.

    With the AWS Sustainability service, you can:

    • Retrieve estimated carbon emissions for your Amazon Web Services usage across different time periods

    • Group emissions data by dimensions such as account, region, and service

    • Filter emissions data to focus on specific accounts, regions, or services

    • Access multiple emissions calculation methodologies including Location-based Method (LBM) and Market-based Method (MBM)

    • Aggregate emissions data at various time granularities including monthly, quarterly, and yearly periods

    The API supports pagination for efficient data retrieval and provides dimension values to help you understand the available grouping and filtering options for your account.

    All emissions values are calculated using methodologies aligned with the Greenhouse Gas (GHG) Protocol and are provided in metric tons of carbon dioxide-equivalent (MTCO2e).

    " + "documentation":"

    The AWS Sustainability service provides programmatic access to estimated environmental impact data for your Amazon Web Services usage. Use the AWS Sustainability service to retrieve, analyze, and track the environmental impact of your cloud infrastructure over time.

    With the AWS Sustainability service, you can:

    • Retrieve estimated carbon emissions and water allocation for your Amazon Web Services usage across different time periods

    • Group environmental impact data by dimensions such as account, region, and service

    • Filter environmental impact data to focus on specific accounts, regions, or services

    • Access multiple carbon emissions calculation methodologies including Location-based Method (LBM) and Market-based Method (MBM)

    • Aggregate environmental impact data at various time granularities including monthly, quarterly, and yearly periods

    The API supports pagination for efficient data retrieval and provides dimension values to help you understand the available grouping and filtering options for your account.

    " } diff --git a/services/swf/pom.xml b/services/swf/pom.xml index eb5a2e4bf45f..8b8769a6729e 100644 --- a/services/swf/pom.xml +++ b/services/swf/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT swf AWS Java SDK :: Services :: Amazon SWF diff --git a/services/swf/src/main/resources/codegen-resources/customization.config b/services/swf/src/main/resources/codegen-resources/customization.config index 704ac68ddeb8..f2b99d866f9c 100644 --- a/services/swf/src/main/resources/codegen-resources/customization.config +++ b/services/swf/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "serviceSpecificHttpConfig": "software.amazon.awssdk.services.swf.internal.SwfHttpConfigurationOptions", - "enableGenerateCompiledEndpointRules": true + "serviceSpecificHttpConfig": "software.amazon.awssdk.services.swf.internal.SwfHttpConfigurationOptions" } diff --git a/services/swf/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/swf/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..01d56824f9a1 --- /dev/null +++ b/services/swf/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,203 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://swf.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://swf-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://swf-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://swf.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAkAAAAGAAAABAAAAAcF9eEEAAAABQX14QUAAAAIAAAABwX14QkF9eEKAAAABAAAAAwAAAAKAAAABQX14QQAAAALAAAABgX14QcF9eEIAAAABgAAAA0F9eEGAAAABwX14QUF9eEGAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/swf/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/swf/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ec0b6bb2afe7..000000000000 --- a/services/swf/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,430 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://swf.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "endpoint": { - "url": "https://swf-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://swf-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://swf-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://swf.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://swf.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/synthetics/pom.xml b/services/synthetics/pom.xml index f31e817e6fdf..db9e5ed6df8a 100644 --- a/services/synthetics/pom.xml +++ b/services/synthetics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT synthetics AWS Java SDK :: Services :: Synthetics diff --git a/services/synthetics/src/main/resources/codegen-resources/customization.config b/services/synthetics/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/synthetics/src/main/resources/codegen-resources/customization.config +++ b/services/synthetics/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/synthetics/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/synthetics/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a3eb5292be3f --- /dev/null +++ b/services/synthetics/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://synthetics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://synthetics-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://synthetics.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://synthetics.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/synthetics/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/synthetics/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7e1183625a1d..000000000000 --- a/services/synthetics/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://synthetics-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://synthetics-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://synthetics.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://synthetics.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/taxsettings/pom.xml b/services/taxsettings/pom.xml index f43a3b06a7c1..3ce2be3a243b 100644 --- a/services/taxsettings/pom.xml +++ b/services/taxsettings/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT taxsettings AWS Java SDK :: Services :: Tax Settings diff --git a/services/taxsettings/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/taxsettings/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4a826b16d8ea --- /dev/null +++ b/services/taxsettings/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,216 @@ +{ + "version": "1.1", + "parameters": { + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tax-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tax-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tax.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tax.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{PartitionResult#implicitGlobalRegion}" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/taxsettings/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/taxsettings/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e85db5be6294..000000000000 --- a/services/taxsettings/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tax-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tax-fips.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tax.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dualStackDnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://tax.{PartitionResult#implicitGlobalRegion}.{PartitionResult#dnsSuffix}", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingRegion": "{PartitionResult#implicitGlobalRegion}" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/taxsettings/src/main/resources/codegen-resources/service-2.json b/services/taxsettings/src/main/resources/codegen-resources/service-2.json index 482bc01e4f23..b58e8733c018 100644 --- a/services/taxsettings/src/main/resources/codegen-resources/service-2.json +++ b/services/taxsettings/src/main/resources/codegen-resources/service-2.json @@ -60,7 +60,7 @@ {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Adds or updates tax registration for multiple accounts in batch. This can be used to add or update tax registrations for up to five accounts in one batch. You can't set a TRN if there's a pending TRN. You'll need to delete the pending TRN first.

    To call this API operation for specific countries, see the following country-specific requirements.

    Bangladesh

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Brazil

    • You must complete the tax registration process in the Payment preferences page in the Billing and Cost Management console. After your TRN and billing address are verified, you can call this API operation.

    • For Amazon Web Services accounts created through Organizations, you can call this API operation when you don't have a billing address.

    Georgia

    • The valid personType values are Physical Person and Business.

    Indonesia

    • PutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022.

    • BatchPutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022, through our third-party partner PT Achilles Advanced Management (OnlinePajak).

    • You must specify the taxRegistrationNumberType in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    • If you specify decisionNumber, you must specify the ppnExceptionDesignationCode in the indonesiaAdditionalInfo field of the additionalTaxInformation object. If the taxRegistrationNumberType is set to NPWP or NITKU, valid values for ppnExceptionDesignationCode are either 01, 02, 03, 07, or 08.

      For other taxRegistrationNumberType values, ppnExceptionDesignationCode must be either 01, 07, or 08.

    • If ppnExceptionDesignationCode is 07 or 08, you must specify the decisionNumber in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    Kenya

    • You must specify the personType in the kenyaAdditionalInfo field of the additionalTaxInformation object.

    • If the personType is Physical Person, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Malaysia

    • The sector valid values are Business and Individual.

    • RegistrationType valid values are NRIC for individual, and TIN and sales and service tax (SST) for Business.

    • For individual, you can specify the taxInformationNumber in MalaysiaAdditionalInfo with NRIC type, and a valid MyKad or NRIC number.

    • For business, you must specify a businessRegistrationNumber in MalaysiaAdditionalInfo with a TIN type and tax identification number.

    • For business resellers, you must specify a businessRegistrationNumber and taxInformationNumber in MalaysiaAdditionalInfo with a sales and service tax (SST) type and a valid SST number.

    • For business resellers with service codes, you must specify businessRegistrationNumber, taxInformationNumber, and distinct serviceTaxCodes in MalaysiaAdditionalInfo with a SST type and valid sales and service tax (SST) number. By using this API operation, Amazon Web Services registers your self-declaration that you’re an authorized business reseller registered with the Royal Malaysia Customs Department (RMCD), and have a valid SST number.

    • Amazon Web Services reserves the right to seek additional information and/or take other actions to support your self-declaration as appropriate.

    • Amazon Web Services is currently registered under the following service tax codes. You must include at least one of the service tax codes in the service tax code strings to declare yourself as an authorized registered business reseller.

      Taxable service and service tax codes:

      Consultancy - 9907061674

      Training or coaching service - 9907071685

      IT service - 9907101676

      Digital services and electronic medium - 9907121690

    Mexico

    • You must provide a Constancia de Situación fiscal (CSF) document in the verificationDetails field.

    • You do not need to provide address and legal name. These will be populated based on your tax registration number.

    Nepal

    • The sector valid values are Business and Individual.

    Saudi Arabia

    • For address, you must specify addressLine3.

    South Korea

    • You must specify the certifiedEmailId and legalName in the TaxRegistrationEntry object. Use Korean characters for legalName.

    • You must specify the businessRepresentativeName, itemOfBusiness, and lineOfBusiness in the southKoreaAdditionalInfo field of the additionalTaxInformation object. Use Korean characters for these fields.

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    • For the address object, use Korean characters for addressLine1, addressLine2 city, postalCode, and stateOrRegion.

    Spain

    • You must specify the registrationType in the spainAdditionalInfo field of the additionalTaxInformation object.

    • If the registrationType is Local, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Turkey

    • You must specify the sector in the taxRegistrationEntry object.

    • If your sector is Business, Individual, or Government:

      • Specify the taxOffice. If your sector is Individual, don't enter this value.

      • (Optional) Specify the kepEmailId. If your sector is Individual, don't enter this value.

      • Note: In the Tax Settings page of the Billing console, Government appears as Public institutions

    • If your sector is Business and you're subject to KDV tax, you must specify your industry in the industries field.

    • For address, you must specify districtOrCounty.

    Ukraine

    • The sector valid values are Business and Individual.

    Philippines

    • You can optionally specify the isVatRegistered in the philippinesAdditionalInfo field of the additionalTaxInformation object to indicate your VAT registration status with the Bureau of Internal Revenue (BIR).

    Belgium

    • You can optionally specify the peppolId in the belgiumAdditionalInfo field of the additionalTaxInformation object.

    Chile

    • You can optionally specify the documentType and businessActivity in the chileAdditionalInfo field of the additionalTaxInformation object.

    France

    • You must specify the sirenNumber in the franceAdditionalInfo field of the additionalTaxInformation object.

    Poland

    • You can optionally specify the taxRegistrationNumberType in the polandAdditionalInfo field of the additionalTaxInformation object. Valid values are EUTaxRegistrationNumber, LocalTaxRegistrationNumber, or LocalRegistrationNumber.

    " + "documentation":"

    Adds or updates tax registration for multiple accounts in batch. This can be used to add or update tax registrations for up to five accounts in one batch. You can't set a TRN if there's a pending TRN. You'll need to delete the pending TRN first.

    To call this API operation for specific countries, see the following country-specific requirements.

    Bangladesh

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Brazil

    • You must complete the tax registration process in the Payment preferences page in the Billing and Cost Management console. After your TRN and billing address are verified, you can call this API operation.

    • For Amazon Web Services accounts created through Organizations, you can call this API operation when you don't have a billing address.

    Georgia

    • The valid personType values are Physical Person and Business.

    Indonesia

    • PutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022.

    • BatchPutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022, through our third-party partner PT Achilles Advanced Management (OnlinePajak).

    • You must specify the taxRegistrationNumberType in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    • If you specify decisionNumber, you must specify the ppnExceptionDesignationCode in the indonesiaAdditionalInfo field of the additionalTaxInformation object. If the taxRegistrationNumberType is set to NPWP or NITKU, valid values for ppnExceptionDesignationCode are either 01, 02, 03, 07, or 08.

      For other taxRegistrationNumberType values, ppnExceptionDesignationCode must be either 01, 07, or 08.

    • If ppnExceptionDesignationCode is 07 or 08, you must specify the decisionNumber in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    Kenya

    • You must specify the personType in the kenyaAdditionalInfo field of the additionalTaxInformation object.

    • If the personType is Physical Person, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Malaysia

    • The sector valid values are Business and Individual.

    • RegistrationType valid values are NRIC for individual, and TIN and sales and service tax (SST) for Business.

    • For individual, you can specify the taxInformationNumber in MalaysiaAdditionalInfo with NRIC type, and a valid MyKad or NRIC number.

    • For business, you must specify a businessRegistrationNumber in MalaysiaAdditionalInfo with a TIN type and tax identification number.

    • For business resellers, you must specify a businessRegistrationNumber and taxInformationNumber in MalaysiaAdditionalInfo with a sales and service tax (SST) type and a valid SST number.

    • For business resellers with service codes, you must specify businessRegistrationNumber, taxInformationNumber, and distinct serviceTaxCodes in MalaysiaAdditionalInfo with a SST type and valid sales and service tax (SST) number. By using this API operation, Amazon Web Services registers your self-declaration that you’re an authorized business reseller registered with the Royal Malaysia Customs Department (RMCD), and have a valid SST number.

    • Amazon Web Services reserves the right to seek additional information and/or take other actions to support your self-declaration as appropriate.

    • Amazon Web Services is currently registered under the following service tax codes. You must include at least one of the service tax codes in the service tax code strings to declare yourself as an authorized registered business reseller.

      Taxable service and service tax codes:

      Consultancy - 9907061674

      Training or coaching service - 9907071685

      IT service - 9907101676

      Digital services and electronic medium - 9907121690

    Mexico

    • You must provide a Constancia de Situación fiscal (CSF) document in the verificationDetails field.

    • You do not need to provide address and legal name. These will be populated based on your tax registration number.

    Nepal

    • The sector valid values are Business and Individual.

    Saudi Arabia

    • For address, you must specify addressLine3.

    South Korea

    • You must specify the certifiedEmailId and legalName in the TaxRegistrationEntry object. Use Korean characters for legalName.

    • You must specify the businessRepresentativeName, itemOfBusiness, and lineOfBusiness in the southKoreaAdditionalInfo field of the additionalTaxInformation object. Use Korean characters for these fields.

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    • For the address object, use Korean characters for addressLine1, addressLine2 city, postalCode, and stateOrRegion.

    Spain

    • You must specify the registrationType in the spainAdditionalInfo field of the additionalTaxInformation object.

    • If the registrationType is Local, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Turkey

    • You must specify the sector in the taxRegistrationEntry object.

    • If your sector is Business, Individual, or Government:

      • Specify the taxOffice. If your sector is Individual, don't enter this value.

      • (Optional) Specify the kepEmailId. If your sector is Individual, don't enter this value.

      • Note: In the Tax Settings page of the Billing console, Government appears as Public institutions

    • If your sector is Business and you're subject to KDV tax, you must specify your industry in the industries field.

    • For address, you must specify districtOrCounty.

    Ukraine

    • The sector valid values are Business and Individual.

    Philippines

    • You can optionally specify the isVatRegistered in the philippinesAdditionalInfo field of the additionalTaxInformation object to indicate your VAT registration status with the Bureau of Internal Revenue (BIR).

    Belgium

    • You can optionally specify the peppolId in the belgiumAdditionalInfo field of the additionalTaxInformation object.

    Chile

    • You can optionally specify the documentType and businessActivity in the chileAdditionalInfo field of the additionalTaxInformation object.

    France

    • You must specify the sirenNumber in the franceAdditionalInfo field of the additionalTaxInformation object.

    • You can optionally specify the eInvoiceRoutingCode in the franceAdditionalInfo field of the additionalTaxInformation object.

    Monaco

    • You must specify the businessNumber in the monacoAdditionalInfo field of the additionalTaxInformation object.

    Poland

    • You can optionally specify the taxRegistrationNumberType in the polandAdditionalInfo field of the additionalTaxInformation object. Valid values are EUTaxRegistrationNumber, LocalTaxRegistrationNumber, or LocalRegistrationNumber.

    " }, "DeleteSupplementalTaxRegistration":{ "name":"DeleteSupplementalTaxRegistration", @@ -280,7 +280,7 @@ {"shape":"ValidationException"}, {"shape":"InternalServerException"} ], - "documentation":"

    Adds or updates tax registration for a single account. You can't set a TRN if there's a pending TRN. You'll need to delete the pending TRN first.

    To call this API operation for specific countries, see the following country-specific requirements.

    Bangladesh

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Brazil

    • You must complete the tax registration process in the Payment preferences page in the Billing and Cost Management console. After your TRN and billing address are verified, you can call this API operation.

    • For Amazon Web Services accounts created through Organizations, you can call this API operation when you don't have a billing address.

    Georgia

    • The valid personType values are Physical Person and Business.

    Indonesia

    • PutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022.

    • BatchPutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022, through our third-party partner PT Achilles Advanced Management (OnlinePajak).

    • You must specify the taxRegistrationNumberType in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    • If you specify decisionNumber, you must specify the ppnExceptionDesignationCode in the indonesiaAdditionalInfo field of the additionalTaxInformation object. If the taxRegistrationNumberType is set to NPWP or NITKU, valid values for ppnExceptionDesignationCode are either 01, 02, 03, 07, or 08.

      For other taxRegistrationNumberType values, ppnExceptionDesignationCode must be either 01, 07, or 08.

    • If ppnExceptionDesignationCode is 07 or 08, you must specify the decisionNumber in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    Kenya

    • You must specify the personType in the kenyaAdditionalInfo field of the additionalTaxInformation object.

    • If the personType is Physical Person, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Malaysia

    • The sector valid values are Business and Individual.

    • RegistrationType valid values are NRIC for individual, and TIN and sales and service tax (SST) for Business.

    • For individual, you can specify the taxInformationNumber in MalaysiaAdditionalInfo with NRIC type, and a valid MyKad or NRIC number.

    • For business, you must specify a businessRegistrationNumber in MalaysiaAdditionalInfo with a TIN type and tax identification number.

    • For business resellers, you must specify a businessRegistrationNumber and taxInformationNumber in MalaysiaAdditionalInfo with a sales and service tax (SST) type and a valid SST number.

    • For business resellers with service codes, you must specify businessRegistrationNumber, taxInformationNumber, and distinct serviceTaxCodes in MalaysiaAdditionalInfo with a SST type and valid sales and service tax (SST) number. By using this API operation, Amazon Web Services registers your self-declaration that you’re an authorized business reseller registered with the Royal Malaysia Customs Department (RMCD), and have a valid SST number.

    • Amazon Web Services reserves the right to seek additional information and/or take other actions to support your self-declaration as appropriate.

    • Amazon Web Services is currently registered under the following service tax codes. You must include at least one of the service tax codes in the service tax code strings to declare yourself as an authorized registered business reseller.

      Taxable service and service tax codes:

      Consultancy - 9907061674

      Training or coaching service - 9907071685

      IT service - 9907101676

      Digital services and electronic medium - 9907121690

    Mexico

    • You must provide a Constancia de Situación fiscal (CSF) document in the verificationDetails field.

    • You do not need to provide address and legal name. These will be populated based on your tax registration number.

    Nepal

    • The sector valid values are Business and Individual.

    Saudi Arabia

    • For address, you must specify addressLine3.

    South Korea

    • You must specify the certifiedEmailId and legalName in the TaxRegistrationEntry object. Use Korean characters for legalName.

    • You must specify the businessRepresentativeName, itemOfBusiness, and lineOfBusiness in the southKoreaAdditionalInfo field of the additionalTaxInformation object. Use Korean characters for these fields.

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    • For the address object, use Korean characters for addressLine1, addressLine2 city, postalCode, and stateOrRegion.

    Spain

    • You must specify the registrationType in the spainAdditionalInfo field of the additionalTaxInformation object.

    • If the registrationType is Local, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Turkey

    • You must specify the sector in the taxRegistrationEntry object.

    • If your sector is Business, Individual, or Government:

      • Specify the taxOffice. If your sector is Individual, don't enter this value.

      • (Optional) Specify the kepEmailId. If your sector is Individual, don't enter this value.

      • Note: In the Tax Settings page of the Billing console, Government appears as Public institutions

    • If your sector is Business and you're subject to KDV tax, you must specify your industry in the industries field.

    • For address, you must specify districtOrCounty.

    Ukraine

    • The sector valid values are Business and Individual.

    Philippines

    • You can optionally specify the isVatRegistered in the philippinesAdditionalInfo field of the additionalTaxInformation object to indicate your VAT registration status with the Bureau of Internal Revenue (BIR).

    Belgium

    • You can optionally specify the peppolId in the belgiumAdditionalInfo field of the additionalTaxInformation object.

    Chile

    • You can optionally specify the documentType and businessActivity in the chileAdditionalInfo field of the additionalTaxInformation object.

    France

    • You must specify the sirenNumber in the franceAdditionalInfo field of the additionalTaxInformation object.

    Poland

    • You can optionally specify the taxRegistrationNumberType in the polandAdditionalInfo field of the additionalTaxInformation object. Valid values are EUTaxRegistrationNumber, LocalTaxRegistrationNumber, or LocalRegistrationNumber.

    " + "documentation":"

    Adds or updates tax registration for a single account. You can't set a TRN if there's a pending TRN. You'll need to delete the pending TRN first.

    To call this API operation for specific countries, see the following country-specific requirements.

    Bangladesh

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Brazil

    • You must complete the tax registration process in the Payment preferences page in the Billing and Cost Management console. After your TRN and billing address are verified, you can call this API operation.

    • For Amazon Web Services accounts created through Organizations, you can call this API operation when you don't have a billing address.

    Georgia

    • The valid personType values are Physical Person and Business.

    Indonesia

    • PutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022.

    • BatchPutTaxRegistration: The use of this operation to submit tax information is subject to the Amazon Web Services service terms. By submitting, you’re providing consent for Amazon Web Services to validate NIK, NPWP, and NITKU data, provided by you with the Directorate General of Taxes of Indonesia in accordance with the Minister of Finance Regulation (PMK) Number 112/PMK.03/2022, through our third-party partner PT Achilles Advanced Management (OnlinePajak).

    • You must specify the taxRegistrationNumberType in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    • If you specify decisionNumber, you must specify the ppnExceptionDesignationCode in the indonesiaAdditionalInfo field of the additionalTaxInformation object. If the taxRegistrationNumberType is set to NPWP or NITKU, valid values for ppnExceptionDesignationCode are either 01, 02, 03, 07, or 08.

      For other taxRegistrationNumberType values, ppnExceptionDesignationCode must be either 01, 07, or 08.

    • If ppnExceptionDesignationCode is 07 or 08, you must specify the decisionNumber in the indonesiaAdditionalInfo field of the additionalTaxInformation object.

    Kenya

    • You must specify the personType in the kenyaAdditionalInfo field of the additionalTaxInformation object.

    • If the personType is Physical Person, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Malaysia

    • The sector valid values are Business and Individual.

    • RegistrationType valid values are NRIC for individual, and TIN and sales and service tax (SST) for Business.

    • For individual, you can specify the taxInformationNumber in MalaysiaAdditionalInfo with NRIC type, and a valid MyKad or NRIC number.

    • For business, you must specify a businessRegistrationNumber in MalaysiaAdditionalInfo with a TIN type and tax identification number.

    • For business resellers, you must specify a businessRegistrationNumber and taxInformationNumber in MalaysiaAdditionalInfo with a sales and service tax (SST) type and a valid SST number.

    • For business resellers with service codes, you must specify businessRegistrationNumber, taxInformationNumber, and distinct serviceTaxCodes in MalaysiaAdditionalInfo with a SST type and valid sales and service tax (SST) number. By using this API operation, Amazon Web Services registers your self-declaration that you’re an authorized business reseller registered with the Royal Malaysia Customs Department (RMCD), and have a valid SST number.

    • Amazon Web Services reserves the right to seek additional information and/or take other actions to support your self-declaration as appropriate.

    • Amazon Web Services is currently registered under the following service tax codes. You must include at least one of the service tax codes in the service tax code strings to declare yourself as an authorized registered business reseller.

      Taxable service and service tax codes:

      Consultancy - 9907061674

      Training or coaching service - 9907071685

      IT service - 9907101676

      Digital services and electronic medium - 9907121690

    Mexico

    • You must provide a Constancia de Situación fiscal (CSF) document in the verificationDetails field.

    • You do not need to provide address and legal name. These will be populated based on your tax registration number.

    Nepal

    • The sector valid values are Business and Individual.

    Saudi Arabia

    • For address, you must specify addressLine3.

    South Korea

    • You must specify the certifiedEmailId and legalName in the TaxRegistrationEntry object. Use Korean characters for legalName.

    • You must specify the businessRepresentativeName, itemOfBusiness, and lineOfBusiness in the southKoreaAdditionalInfo field of the additionalTaxInformation object. Use Korean characters for these fields.

    • You must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    • For the address object, use Korean characters for addressLine1, addressLine2 city, postalCode, and stateOrRegion.

    Spain

    • You must specify the registrationType in the spainAdditionalInfo field of the additionalTaxInformation object.

    • If the registrationType is Local, you must specify the tax registration certificate document in the taxRegistrationDocuments field of the VerificationDetails object.

    Turkey

    • You must specify the sector in the taxRegistrationEntry object.

    • If your sector is Business, Individual, or Government:

      • Specify the taxOffice. If your sector is Individual, don't enter this value.

      • (Optional) Specify the kepEmailId. If your sector is Individual, don't enter this value.

      • Note: In the Tax Settings page of the Billing console, Government appears as Public institutions

    • If your sector is Business and you're subject to KDV tax, you must specify your industry in the industries field.

    • For address, you must specify districtOrCounty.

    Ukraine

    • The sector valid values are Business and Individual.

    Philippines

    • You can optionally specify the isVatRegistered in the philippinesAdditionalInfo field of the additionalTaxInformation object to indicate your VAT registration status with the Bureau of Internal Revenue (BIR).

    Belgium

    • You can optionally specify the peppolId in the belgiumAdditionalInfo field of the additionalTaxInformation object.

    Chile

    • You can optionally specify the documentType and businessActivity in the chileAdditionalInfo field of the additionalTaxInformation object.

    France

    • You must specify the sirenNumber in the franceAdditionalInfo field of the additionalTaxInformation object.

    • You can optionally specify the eInvoiceRoutingCode in the franceAdditionalInfo field of the additionalTaxInformation object.

    Monaco

    • You must specify the businessNumber in the monacoAdditionalInfo field of the additionalTaxInformation object.

    Poland

    • You can optionally specify the taxRegistrationNumberType in the polandAdditionalInfo field of the additionalTaxInformation object. Valid values are EUTaxRegistrationNumber, LocalTaxRegistrationNumber, or LocalRegistrationNumber.

    " } }, "shapes":{ @@ -456,6 +456,10 @@ "franceAdditionalInfo":{ "shape":"FranceAdditionalInfo", "documentation":"

    Additional tax information to specify for a TRN in France.

    " + }, + "monacoAdditionalInfo":{ + "shape":"MonacoAdditionalInfo", + "documentation":"

    Additional tax information to specify for a TRN in Monaco.

    " } }, "documentation":"

    Additional tax information associated with your tax registration number (TRN). Depending on the TRN for a specific country, you might need to specify this information when you set your TRN.

    You can only specify one of the following parameters and the value can't be empty.

    The parameter that you specify must match the country for the TRN, if available. For example, if you set a TRN in Canada for specific provinces, you must also specify the canadaAdditionalInfo parameter.

    " @@ -562,6 +566,10 @@ "franceAdditionalInfo":{ "shape":"FranceAdditionalInfo", "documentation":"

    Additional tax information associated with your TRN in France.

    " + }, + "monacoAdditionalInfo":{ + "shape":"MonacoAdditionalInfo", + "documentation":"

    Additional tax information associated with your TRN in Monaco.

    " } }, "documentation":"

    Additional tax information associated with your TRN. The Tax Settings API returns country-specific information in the response when any additional information is present with your TRN for the following countries.

    " @@ -847,6 +855,10 @@ }, "documentation":"

    Additional tax information associated with your TRN in Brazil.

    " }, + "BusinessNumber":{ + "type":"string", + "pattern":"[a-zA-Z0-9]{1,12}" + }, "BusinessRegistrationNumber":{ "type":"string", "pattern":"([0-9]{12}|LL[0-9]{5})" @@ -925,7 +937,7 @@ }, "businessActivity":{ "shape":"GenericString", - "documentation":"

    The business activity of the taxpayer in Chile.

    " + "documentation":"

    The business activity code of the taxpayer in Chile. This must be the activity code shown on your SII (Servicio de Impuestos Internos) tax profile. For the list of valid activity codes, see SII activity codes.

    " } }, "documentation":"

    Additional tax information associated with your TRN in Chile.

    " @@ -1161,6 +1173,10 @@ "sirenNumber":{ "shape":"SirenNumber", "documentation":"

    The SIREN number for the company in France. Must be a 9-digit number.

    " + }, + "eInvoiceRoutingCode":{ + "shape":"String", + "documentation":"

    The routing code used for electronic invoicing (e-invoicing) for the company in France.

    " } }, "documentation":"

    Additional tax information associated with your TRN in France.

    " @@ -1575,6 +1591,17 @@ "max":1000, "min":1 }, + "MonacoAdditionalInfo":{ + "type":"structure", + "required":["businessNumber"], + "members":{ + "businessNumber":{ + "shape":"BusinessNumber", + "documentation":"

    The business number for the company in Monaco. Can be up to 12 alphanumeric characters.

    " + } + }, + "documentation":"

    Additional tax information associated with your TRN in Monaco.

    " + }, "PaginationTokenString":{ "type":"string", "max":2000, @@ -1914,6 +1941,7 @@ "min":1, "pattern":"(?!\\s*$)[\\s\\S]+" }, + "String":{"type":"string"}, "SupplementalTaxRegistration":{ "type":"structure", "required":[ diff --git a/services/textract/pom.xml b/services/textract/pom.xml index 43b8cfc2a1c5..867ef26fc4d2 100644 --- a/services/textract/pom.xml +++ b/services/textract/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT textract AWS Java SDK :: Services :: Textract diff --git a/services/textract/src/main/resources/codegen-resources/customization.config b/services/textract/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/textract/src/main/resources/codegen-resources/customization.config +++ b/services/textract/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/textract/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/textract/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..822580fc8105 --- /dev/null +++ b/services/textract/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://textract-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://textract-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://textract.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://textract.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/textract/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/textract/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8587b691f4c9..000000000000 --- a/services/textract/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://textract-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://textract-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://textract.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://textract.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/textract/src/main/resources/codegen-resources/service-2.json b/services/textract/src/main/resources/codegen-resources/service-2.json index 25a818647866..bbe2144634ac 100644 --- a/services/textract/src/main/resources/codegen-resources/service-2.json +++ b/services/textract/src/main/resources/codegen-resources/service-2.json @@ -746,7 +746,7 @@ }, "HumanLoopConfig":{ "shape":"HumanLoopConfig", - "documentation":"

    Sets the configuration for the human in the loop workflow for analyzing documents.

    " + "documentation":"

    Sets the configuration for the human in the loop workflow for analyzing documents.

    Amazon Textract uses Amazon Augmented AI (A2I) to run the human review workflows that you specify in HumanLoopConfig. A2I entered maintenance mode in July 2026 and no longer accepts new customers. If your account is not an existing A2I customer, requests fail with an InvalidParameterException. For more information, see AWS service availability. If you're an existing A2I customer but receive this error, contact AWS Support and request assistance from the A2I team.

    " }, "QueriesConfig":{ "shape":"QueriesConfig", @@ -850,7 +850,7 @@ "BadDocumentException":{ "type":"structure", "members":{}, - "documentation":"

    Amazon Textract isn't able to read the document. For more information on the document limits in Amazon Textract, see limits.

    ", + "documentation":"

    Amazon Textract isn't able to read the document. For more information on the document limits in Amazon Textract, see Hard limits.

    ", "exception":true }, "Block":{ @@ -1441,7 +1441,7 @@ }, "RotationAngle":{ "shape":"Angle", - "documentation":"

    Provides a numerical value corresponding to the rotation of the text.

    " + "documentation":"

    Provides a numerical value corresponding to the rotation of the WORD block. Possible values are 0, 90, 180, and 270.

    " } }, "documentation":"

    Information about where the following items are located on a document page: detected page, text, key-value pairs, tables, table cells, and selection elements.

    " @@ -1842,7 +1842,7 @@ "documentation":"

    Sets attributes of the input data.

    " } }, - "documentation":"

    Sets up the human review workflow the document will be sent to if one of the conditions is met. You can also set certain attributes of the image before review.

    " + "documentation":"

    Sets up the human review workflow the document will be sent to if one of the conditions is met. You can also set certain attributes of the image before review.

    Amazon Textract uses Amazon Augmented AI (A2I) to run the human review workflows that you specify in HumanLoopConfig. A2I entered maintenance mode in July 2026 and no longer accepts new customers. If your account is not an existing A2I customer, requests fail with an InvalidParameterException. For more information, see AWS service availability. If you're an existing A2I customer but receive this error, contact AWS Support and request assistance from the A2I team.

    " }, "HumanLoopDataAttributes":{ "type":"structure", diff --git a/services/timestreaminfluxdb/pom.xml b/services/timestreaminfluxdb/pom.xml index 08c734a04f73..ae9fb8fc1ce6 100644 --- a/services/timestreaminfluxdb/pom.xml +++ b/services/timestreaminfluxdb/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT timestreaminfluxdb AWS Java SDK :: Services :: Timestream Influx DB diff --git a/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0f242772b0a5 --- /dev/null +++ b/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-influxdb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-influxdb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-influxdb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-influxdb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index e20fcba8a527..000000000000 --- a/services/timestreaminfluxdb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://timestream-influxdb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://timestream-influxdb-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://timestream-influxdb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://timestream-influxdb.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/timestreaminfluxdb/src/main/resources/codegen-resources/paginators-1.json b/services/timestreaminfluxdb/src/main/resources/codegen-resources/paginators-1.json index 8e843c672f89..1c714f34ab1f 100644 --- a/services/timestreaminfluxdb/src/main/resources/codegen-resources/paginators-1.json +++ b/services/timestreaminfluxdb/src/main/resources/codegen-resources/paginators-1.json @@ -1,5 +1,11 @@ { "pagination": { + "ListDbBackups": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, "ListDbClusters": { "input_token": "nextToken", "output_token": "nextToken", diff --git a/services/timestreaminfluxdb/src/main/resources/codegen-resources/service-2.json b/services/timestreaminfluxdb/src/main/resources/codegen-resources/service-2.json index f030f2654c29..f94af72c296c 100644 --- a/services/timestreaminfluxdb/src/main/resources/codegen-resources/service-2.json +++ b/services/timestreaminfluxdb/src/main/resources/codegen-resources/service-2.json @@ -15,6 +15,26 @@ "uid":"timestream-influxdb-2023-01-27" }, "operations":{ + "CreateDbBackup":{ + "name":"CreateDbBackup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"CreateDbBackupInput"}, + "output":{"shape":"CreateDbBackupOutput"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a new on-demand backup of a Timestream for InfluxDB resource.

    ", + "idempotent":true + }, "CreateDbCluster":{ "name":"CreateDbCluster", "http":{ @@ -75,6 +95,25 @@ "documentation":"

    Creates a new Timestream for InfluxDB DB parameter group to associate with DB instances.

    ", "idempotent":true }, + "DeleteDbBackup":{ + "name":"DeleteDbBackup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"DeleteDbBackupInput"}, + "output":{"shape":"DeleteDbBackupOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes a Timestream for InfluxDB backup.

    ", + "idempotent":true + }, "DeleteDbCluster":{ "name":"DeleteDbCluster", "http":{ @@ -113,6 +152,23 @@ "documentation":"

    Deletes a Timestream for InfluxDB DB instance.

    ", "idempotent":true }, + "GetDbBackup":{ + "name":"GetDbBackup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"GetDbBackupInput"}, + "output":{"shape":"GetDbBackupOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns information about a specific Timestream for InfluxDB backup.

    " + }, "GetDbCluster":{ "name":"GetDbCluster", "http":{ @@ -164,6 +220,23 @@ ], "documentation":"

    Returns a Timestream for InfluxDB DB parameter group.

    " }, + "ListDbBackups":{ + "name":"ListDbBackups", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListDbBackupsInput"}, + "output":{"shape":"ListDbBackupsOutput"}, + "errors":[ + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Returns a list of Timestream for InfluxDB backups.

    " + }, "ListDbClusters":{ "name":"ListDbClusters", "http":{ @@ -283,6 +356,26 @@ "documentation":"

    Reboots a Timestream for InfluxDB instance.

    ", "idempotent":true }, + "RestoreFromDbBackup":{ + "name":"RestoreFromDbBackup", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"RestoreFromDbBackupInput"}, + "output":{"shape":"RestoreFromDbBackupOutput"}, + "errors":[ + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ValidationException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Restores a Timestream for InfluxDB resource from a backup. By default, a new resource is created. You can optionally restore to the same resource using the REPLACE_EXISTING restore mode.

    ", + "idempotent":true + }, "TagResource":{ "name":"TagResource", "http":{ @@ -369,7 +462,30 @@ "type":"string", "max":1011, "min":1, - "pattern":"arn:aws[a-z\\-]*:timestream\\-influxdb:[a-z0-9\\-]+:[0-9]{12}:(db\\-instance|db\\-cluster|db\\-parameter\\-group)/[a-zA-Z0-9]{3,64}" + "pattern":"arn:aws[a-z\\-]*:timestream\\-influxdb:[a-z0-9\\-]+:[0-9]{12}:(db\\-instance|db\\-cluster|db\\-parameter\\-group|db\\-backup)/[a-zA-Z0-9]{3,64}" + }, + "AutomatedBackupRetentionDays":{ + "type":"integer", + "box":true, + "max":365, + "min":1 + }, + "AutomatedDbBackupType":{ + "type":"string", + "enum":[ + "HOURLY", + "DAILY", + "WEEKLY", + "MONTHLY", + "CUSTOM_SCHEDULE", + "CONTINUOUS" + ] + }, + "AwsCronSchedule":{ + "type":"string", + "max":256, + "min":9, + "pattern":"cron\\(\\S+ \\S+ \\S+ \\S+ \\S+ \\S+\\)" }, "Boolean":{ "type":"boolean", @@ -416,7 +532,9 @@ "UPDATING_INSTANCE_TYPE", "REBOOTING", "REBOOT_FAILED", - "PARTIALLY_AVAILABLE" + "PARTIALLY_AVAILABLE", + "RESTORING", + "RESTORE_FAILED" ] }, "ConflictException":{ @@ -440,6 +558,140 @@ "documentation":"

    The request conflicts with an existing resource in Timestream for InfluxDB.

    ", "exception":true }, + "CreateDbBackupInput":{ + "type":"structure", + "required":[ + "name", + "dbResourceId" + ], + "members":{ + "name":{ + "shape":"DbBackupName", + "documentation":"

    The name of the backup. Must be unique within the account and region.

    " + }, + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The id of the DB instance or DB cluster to back up.

    " + }, + "retentionDays":{ + "shape":"RetentionDays", + "documentation":"

    The number of days to retain the backup. Valid values are 1 to 3650.

    " + }, + "tags":{ + "shape":"RequestTagMap", + "documentation":"

    A list of key-value pairs to associate with the backup.

    " + } + } + }, + "CreateDbBackupOutput":{ + "type":"structure", + "required":[ + "id", + "arn" + ], + "members":{ + "id":{ + "shape":"DbBackupId", + "documentation":"

    Service-generated unique identifier of the backup.

    " + }, + "name":{ + "shape":"DbBackupName", + "documentation":"

    The customer-provided name of the backup.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup.

    " + }, + "status":{ + "shape":"DbBackupStatus", + "documentation":"

    The current status of the backup.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The time when the backup was created.

    " + }, + "expiresAfter":{ + "shape":"Date", + "documentation":"

    The date after which the backup will be automatically deleted.

    " + }, + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the DB resource that the backup was created from.

    " + }, + "type":{ + "shape":"DbBackupType", + "documentation":"

    The type of backup.

    " + }, + "engineType":{ + "shape":"EngineType", + "documentation":"

    The engine type of the resource that the backup was created from.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    The deployment type of the resource that the backup was created from.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the resource at the time of backup.

    " + }, + "clusterConfiguration":{ + "shape":"ClusterConfiguration", + "documentation":"

    The cluster configuration of the resource at the time of backup.

    " + }, + "dbParameterGroupId":{ + "shape":"DbParameterGroupId", + "documentation":"

    The identifier of the DB parameter group associated with the backup.

    " + }, + "dbInstanceType":{ + "shape":"DbInstanceType", + "documentation":"

    The DB instance type of the resource at the time of backup.

    " + }, + "logDeliveryConfiguration":{ + "shape":"LogDeliveryConfiguration", + "documentation":"

    The log delivery configuration of the resource at the time of backup.

    " + }, + "failoverMode":{ + "shape":"FailoverMode", + "documentation":"

    The failover mode of the resource at the time of backup.

    " + }, + "dbStorageType":{ + "shape":"DbStorageType", + "documentation":"

    The storage type of the resource at the time of backup.

    " + }, + "allocatedStorage":{ + "shape":"AllocatedStorage", + "documentation":"

    The allocated storage of the resource at the time of backup, in GiB.

    " + }, + "vpcSubnetIds":{ + "shape":"VpcSubnetIdList", + "documentation":"

    The VPC subnet IDs associated with the resource at the time of backup.

    " + }, + "vpcSecurityGroupIds":{ + "shape":"VpcSecurityGroupIdList", + "documentation":"

    The VPC security group IDs associated with the resource at the time of backup.

    " + }, + "publiclyAccessible":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the resource was publicly accessible at the time of backup.

    " + }, + "port":{ + "shape":"Integer", + "documentation":"

    The port number of the resource at the time of backup.

    " + }, + "networkType":{ + "shape":"NetworkType", + "documentation":"

    The network type of the resource at the time of backup.

    " + }, + "influxAuthParametersSecretArn":{ + "shape":"String", + "documentation":"

    The ARN of the Secrets Manager secret containing the InfluxDB auth parameters.

    " + }, + "maintenanceSchedule":{ + "shape":"MaintenanceSchedule", + "documentation":"

    The maintenance schedule of the resource at the time of backup.

    " + } + } + }, "CreateDbClusterInput":{ "type":"structure", "required":[ @@ -521,6 +773,14 @@ "shape":"MaintenanceSchedule", "documentation":"

    Specifies the maintenance schedule for the DB cluster, including the preferred maintenance window and timezone.

    " }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationInputList", + "documentation":"

    A list of backup configurations to enable automated backups for the DB cluster.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key identifier to use for encryption of the DB cluster. Can be a key ID, key ARN, alias name, or alias ARN.

    " + }, "tags":{ "shape":"RequestTagMap", "documentation":"

    A list of key-value pairs to associate with the DB instance.

    " @@ -622,6 +882,14 @@ "networkType":{ "shape":"NetworkType", "documentation":"

    Specifies whether the networkType of the Timestream for InfluxDB instance is IPV4, which can communicate over IPv4 protocol only, or DUAL, which can communicate over both IPv4 and IPv6 protocols.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationInputList", + "documentation":"

    A list of backup configurations to enable automated backups for the DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key identifier to use for encryption of the DB instance. Can be a key ID, key ARN, alias name, or alias ARN.

    " } } }, @@ -733,6 +1001,14 @@ "nextMaintenanceTime":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The timestamp of the next scheduled maintenance operation on the DB instance.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations for the DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the DB instance.

    " } } }, @@ -800,6 +1076,171 @@ "multi-thread-alt" ] }, + "Date":{ + "type":"string", + "documentation":"

    A calendar date in YYYY-MM-DD format.

    ", + "pattern":"\\d{4}-\\d{2}-\\d{2}" + }, + "DbBackupConfiguration":{ + "type":"structure", + "required":[ + "type", + "retentionDays", + "enabled" + ], + "members":{ + "type":{ + "shape":"AutomatedDbBackupType", + "documentation":"

    The type of automated backup schedule. Valid values are HOURLY, DAILY, WEEKLY, MONTHLY, CUSTOM_SCHEDULE, and CONTINUOUS.

    " + }, + "retentionDays":{ + "shape":"AutomatedBackupRetentionDays", + "documentation":"

    The number of days to retain automated backups. Valid values are 1 to 365.

    " + }, + "enabled":{ + "shape":"Boolean", + "documentation":"

    Specifies whether this backup configuration is enabled.

    " + }, + "customSchedule":{ + "shape":"AwsCronSchedule", + "documentation":"

    A custom cron schedule expression for the backup. Required when type is CUSTOM_SCHEDULE.

    " + } + }, + "documentation":"

    Specifies the configuration for an automated backup schedule.

    " + }, + "DbBackupConfigurationInputList":{ + "type":"list", + "member":{"shape":"DbBackupConfiguration"}, + "max":4, + "min":1 + }, + "DbBackupConfigurationOutput":{ + "type":"structure", + "required":[ + "type", + "retentionDays", + "enabled" + ], + "members":{ + "type":{ + "shape":"AutomatedDbBackupType", + "documentation":"

    The type of automated backup schedule.

    " + }, + "retentionDays":{ + "shape":"AutomatedBackupRetentionDays", + "documentation":"

    The number of days automated backups are retained.

    " + }, + "enabled":{ + "shape":"Boolean", + "documentation":"

    Indicates whether this backup configuration is enabled.

    " + }, + "customSchedule":{ + "shape":"AwsCronSchedule", + "documentation":"

    The custom cron schedule expression for the backup, if applicable.

    " + }, + "nextAutomatedBackupTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The next scheduled time for an automated backup to be taken.

    " + } + }, + "documentation":"

    Contains the configuration and status for an automated backup schedule.

    " + }, + "DbBackupConfigurationOutputList":{ + "type":"list", + "member":{"shape":"DbBackupConfigurationOutput"} + }, + "DbBackupId":{ + "type":"string", + "max":64, + "min":3, + "pattern":"[a-zA-Z0-9]+" + }, + "DbBackupName":{ + "type":"string", + "max":40, + "min":3, + "pattern":"[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*" + }, + "DbBackupStatus":{ + "type":"string", + "enum":[ + "IN_PROGRESS", + "COMPLETED", + "FAILED", + "DELETING", + "DELETED" + ] + }, + "DbBackupSummary":{ + "type":"structure", + "required":[ + "id", + "arn" + ], + "members":{ + "id":{ + "shape":"DbBackupId", + "documentation":"

    Service-generated unique identifier of the backup.

    " + }, + "name":{ + "shape":"DbBackupName", + "documentation":"

    The customer-provided name of the backup.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup.

    " + }, + "status":{ + "shape":"DbBackupStatus", + "documentation":"

    The status of the backup. Valid values are IN_PROGRESS, COMPLETED, FAILED, DELETING, and DELETED.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The time when the backup was created.

    " + }, + "expiresAfter":{ + "shape":"Date", + "documentation":"

    The date after which the backup will be automatically deleted.

    " + }, + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the DB resource that the backup was created from.

    " + }, + "type":{ + "shape":"DbBackupType", + "documentation":"

    The type of backup. Valid values are HOURLY, DAILY, WEEKLY, MONTHLY, CUSTOM_SCHEDULE, ON_DEMAND, and CONTINUOUS.

    " + }, + "engineType":{ + "shape":"EngineType", + "documentation":"

    The engine type of the resource that the backup was created from.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    The deployment type of the resource that the backup was created from.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the resource at the time of backup.

    " + } + }, + "documentation":"

    Contains a summary of a Timestream for InfluxDB backup.

    " + }, + "DbBackupSummaryList":{ + "type":"list", + "member":{"shape":"DbBackupSummary"} + }, + "DbBackupType":{ + "type":"string", + "enum":[ + "HOURLY", + "DAILY", + "WEEKLY", + "MONTHLY", + "CUSTOM_SCHEDULE", + "ON_DEMAND", + "CONTINUOUS" + ] + }, "DbClusterId":{ "type":"string", "max":64, @@ -1067,32 +1508,163 @@ "shape":"DbParameterGroupId", "documentation":"

    A service-generated unique identifier.

    " }, - "name":{ - "shape":"DbParameterGroupName", - "documentation":"

    This customer-supplied name uniquely identifies the parameter group.

    " + "name":{ + "shape":"DbParameterGroupName", + "documentation":"

    This customer-supplied name uniquely identifies the parameter group.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the DB parameter group.

    " + }, + "description":{ + "shape":"String", + "documentation":"

    A description of the DB parameter group.

    " + } + }, + "documentation":"

    Contains a summary of a DB parameter group.

    " + }, + "DbParameterGroupSummaryList":{ + "type":"list", + "member":{"shape":"DbParameterGroupSummary"} + }, + "DbResourceId":{ + "type":"string", + "max":64, + "min":3, + "pattern":"[a-zA-Z0-9]+" + }, + "DbResourceName":{ + "type":"string", + "max":40, + "min":3, + "pattern":"[a-zA-Z][a-zA-Z0-9]*(-[a-zA-Z0-9]+)*" + }, + "DbStorageType":{ + "type":"string", + "enum":[ + "InfluxIOIncludedT1", + "InfluxIOIncludedT2", + "InfluxIOIncludedT3" + ] + }, + "DeleteDbBackupInput":{ + "type":"structure", + "required":["identifier"], + "members":{ + "identifier":{ + "shape":"DbBackupId", + "documentation":"

    The identifier of the backup to delete.

    " + } + } + }, + "DeleteDbBackupOutput":{ + "type":"structure", + "required":[ + "id", + "arn" + ], + "members":{ + "id":{ + "shape":"DbBackupId", + "documentation":"

    Service-generated unique identifier of the deleted backup.

    " + }, + "name":{ + "shape":"DbBackupName", + "documentation":"

    The customer-provided name of the deleted backup.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the deleted backup.

    " + }, + "status":{ + "shape":"DbBackupStatus", + "documentation":"

    The current status of the backup.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The time when the backup was created.

    " + }, + "expiresAfter":{ + "shape":"Date", + "documentation":"

    The date after which the backup was set to be automatically deleted.

    " + }, + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the DB resource that the backup was created from.

    " + }, + "type":{ + "shape":"DbBackupType", + "documentation":"

    The type of backup.

    " + }, + "engineType":{ + "shape":"EngineType", + "documentation":"

    The engine type of the resource that the backup was created from.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    The deployment type of the resource that the backup was created from.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the resource at the time of backup.

    " + }, + "clusterConfiguration":{ + "shape":"ClusterConfiguration", + "documentation":"

    The cluster configuration of the resource at the time of backup.

    " + }, + "dbParameterGroupId":{ + "shape":"DbParameterGroupId", + "documentation":"

    The identifier of the DB parameter group associated with the backup.

    " + }, + "dbInstanceType":{ + "shape":"DbInstanceType", + "documentation":"

    The DB instance type of the resource at the time of backup.

    " + }, + "logDeliveryConfiguration":{ + "shape":"LogDeliveryConfiguration", + "documentation":"

    The log delivery configuration of the resource at the time of backup.

    " + }, + "failoverMode":{ + "shape":"FailoverMode", + "documentation":"

    The failover mode of the resource at the time of backup.

    " }, - "arn":{ - "shape":"Arn", - "documentation":"

    The Amazon Resource Name (ARN) of the DB parameter group.

    " + "dbStorageType":{ + "shape":"DbStorageType", + "documentation":"

    The storage type of the resource at the time of backup.

    " }, - "description":{ + "allocatedStorage":{ + "shape":"AllocatedStorage", + "documentation":"

    The allocated storage of the resource at the time of backup, in GiB.

    " + }, + "vpcSubnetIds":{ + "shape":"VpcSubnetIdList", + "documentation":"

    The VPC subnet IDs associated with the resource at the time of backup.

    " + }, + "vpcSecurityGroupIds":{ + "shape":"VpcSecurityGroupIdList", + "documentation":"

    The VPC security group IDs associated with the resource at the time of backup.

    " + }, + "publiclyAccessible":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the resource was publicly accessible at the time of backup.

    " + }, + "port":{ + "shape":"Integer", + "documentation":"

    The port number of the resource at the time of backup.

    " + }, + "networkType":{ + "shape":"NetworkType", + "documentation":"

    The network type of the resource at the time of backup.

    " + }, + "influxAuthParametersSecretArn":{ "shape":"String", - "documentation":"

    A description of the DB parameter group.

    " + "documentation":"

    The ARN of the Secrets Manager secret containing the InfluxDB auth parameters.

    " + }, + "maintenanceSchedule":{ + "shape":"MaintenanceSchedule", + "documentation":"

    The maintenance schedule of the resource at the time of backup.

    " } - }, - "documentation":"

    Contains a summary of a DB parameter group.

    " - }, - "DbParameterGroupSummaryList":{ - "type":"list", - "member":{"shape":"DbParameterGroupSummary"} - }, - "DbStorageType":{ - "type":"string", - "enum":[ - "InfluxIOIncludedT1", - "InfluxIOIncludedT2", - "InfluxIOIncludedT3" - ] + } }, "DeleteDbClusterInput":{ "type":"structure", @@ -1101,6 +1673,10 @@ "dbClusterId":{ "shape":"DbClusterId", "documentation":"

    Service-generated unique identifier of the DB cluster.

    " + }, + "retainAutomatedBackups":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to retain automated backups after the DB cluster is deleted. If set to true, automated backups are not deleted and can be restored later.

    " } } }, @@ -1120,6 +1696,10 @@ "identifier":{ "shape":"DbInstanceIdentifier", "documentation":"

    The id of the DB instance.

    " + }, + "retainAutomatedBackups":{ + "shape":"Boolean", + "documentation":"

    Specifies whether to retain automated backups after the DB instance is deleted. If set to true, automated backups are not deleted and can be restored later.

    " } } }, @@ -1231,6 +1811,14 @@ "nextMaintenanceTime":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The timestamp of the next scheduled maintenance operation on the DB instance.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations that were associated with the deleted DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN that was used for encryption of the deleted DB instance.

    " } } }, @@ -1289,6 +1877,125 @@ "NO_FAILOVER" ] }, + "GetDbBackupInput":{ + "type":"structure", + "required":["identifier"], + "members":{ + "identifier":{ + "shape":"DbBackupId", + "documentation":"

    The identifier of the backup to retrieve information for.

    " + } + } + }, + "GetDbBackupOutput":{ + "type":"structure", + "required":[ + "id", + "arn" + ], + "members":{ + "id":{ + "shape":"DbBackupId", + "documentation":"

    Service-generated unique identifier of the backup.

    " + }, + "name":{ + "shape":"DbBackupName", + "documentation":"

    The customer-provided name of the backup.

    " + }, + "arn":{ + "shape":"Arn", + "documentation":"

    The Amazon Resource Name (ARN) of the backup.

    " + }, + "status":{ + "shape":"DbBackupStatus", + "documentation":"

    The current status of the backup.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The time when the backup was created.

    " + }, + "expiresAfter":{ + "shape":"Date", + "documentation":"

    The date after which the backup will be automatically deleted.

    " + }, + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the DB resource that the backup was created from.

    " + }, + "type":{ + "shape":"DbBackupType", + "documentation":"

    The type of backup.

    " + }, + "engineType":{ + "shape":"EngineType", + "documentation":"

    The engine type of the resource that the backup was created from.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    The deployment type of the resource that the backup was created from.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the resource at the time of backup.

    " + }, + "clusterConfiguration":{ + "shape":"ClusterConfiguration", + "documentation":"

    The cluster configuration of the resource at the time of backup.

    " + }, + "dbParameterGroupId":{ + "shape":"DbParameterGroupId", + "documentation":"

    The identifier of the DB parameter group associated with the backup.

    " + }, + "dbInstanceType":{ + "shape":"DbInstanceType", + "documentation":"

    The DB instance type of the resource at the time of backup.

    " + }, + "logDeliveryConfiguration":{ + "shape":"LogDeliveryConfiguration", + "documentation":"

    The log delivery configuration of the resource at the time of backup.

    " + }, + "failoverMode":{ + "shape":"FailoverMode", + "documentation":"

    The failover mode of the resource at the time of backup.

    " + }, + "dbStorageType":{ + "shape":"DbStorageType", + "documentation":"

    The storage type of the resource at the time of backup.

    " + }, + "allocatedStorage":{ + "shape":"AllocatedStorage", + "documentation":"

    The allocated storage of the resource at the time of backup, in GiB.

    " + }, + "vpcSubnetIds":{ + "shape":"VpcSubnetIdList", + "documentation":"

    The VPC subnet IDs associated with the resource at the time of backup.

    " + }, + "vpcSecurityGroupIds":{ + "shape":"VpcSecurityGroupIdList", + "documentation":"

    The VPC security group IDs associated with the resource at the time of backup.

    " + }, + "publiclyAccessible":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the resource was publicly accessible at the time of backup.

    " + }, + "port":{ + "shape":"Integer", + "documentation":"

    The port number of the resource at the time of backup.

    " + }, + "networkType":{ + "shape":"NetworkType", + "documentation":"

    The network type of the resource at the time of backup.

    " + }, + "influxAuthParametersSecretArn":{ + "shape":"String", + "documentation":"

    The ARN of the Secrets Manager secret containing the InfluxDB auth parameters.

    " + }, + "maintenanceSchedule":{ + "shape":"MaintenanceSchedule", + "documentation":"

    The maintenance schedule of the resource at the time of backup.

    " + } + } + }, "GetDbClusterInput":{ "type":"structure", "required":["dbClusterId"], @@ -1367,6 +2074,10 @@ "shape":"DbParameterGroupIdentifier", "documentation":"

    The ID of the DB parameter group assigned to your DB cluster.

    " }, + "effectiveDbParameterGroupIdentifier":{ + "shape":"DbParameterGroupIdentifier", + "documentation":"

    The ID of the DB parameter group actually applied to your DB cluster. When the service applies optimized defaults, it creates a service-managed DB parameter group and this field reflects that group, while dbParameterGroupIdentifier reflects the customer-provided DB parameter group. When no service-managed DB parameter group is applied, this value matches dbParameterGroupIdentifier.

    " + }, "logDeliveryConfiguration":{ "shape":"LogDeliveryConfiguration", "documentation":"

    Configuration for sending InfluxDB engine logs to send to specified S3 bucket.

    " @@ -1402,6 +2113,14 @@ "clusterConfiguration":{ "shape":"ClusterConfiguration", "documentation":"

    Configuration for node modes in the DbCluster.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations for the DB cluster.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the DB cluster.

    " } } }, @@ -1523,6 +2242,14 @@ "nextMaintenanceTime":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The timestamp of the next scheduled maintenance operation on the DB instance.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations for the DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the DB instance.

    " } } }, @@ -1642,7 +2369,7 @@ }, "queryMaxMemoryBytes":{ "shape":"InfluxDBv2ParametersQueryMaxMemoryBytesLong", - "documentation":"

    Maximum number of queries allowed in execution queue. When queue limit is reached, new queries are rejected. Setting to 0 allows an unlimited number of queries in the queue.

    Default: 0

    " + "documentation":"

    Maximum total bytes of memory allowed for all running queries. When this limit is reached, new queries are rejected. Setting to 0 allows unlimited memory usage.

    Default: 0

    " }, "queryMemoryBytes":{ "shape":"InfluxDBv2ParametersQueryMemoryBytesLong", @@ -1975,6 +2702,14 @@ "hardDeleteDefaultDuration":{ "shape":"Duration", "documentation":"

    Sets the default duration for hard deletion of data.

    Default: 90d

    " + }, + "pluginRepositoryUrl":{ + "shape":"String", + "documentation":"

    Specifies the URL of the repository that InfluxDB downloads plugins from.

    " + }, + "pluginRepositorySecretArn":{ + "shape":"PluginRepositorySecretArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Secrets Manager secret that holds your repository access token.

    " } }, "documentation":"

    All the customer-modifiable InfluxDB v3 Core parameters in Timestream for InfluxDB.

    " @@ -2254,6 +2989,14 @@ "shape":"Duration", "documentation":"

    Sets the default duration for hard deletion of data.

    Default: 90d

    " }, + "pluginRepositoryUrl":{ + "shape":"String", + "documentation":"

    Specifies the URL of the repository that InfluxDB downloads plugins from.

    " + }, + "pluginRepositorySecretArn":{ + "shape":"PluginRepositorySecretArn", + "documentation":"

    The Amazon Resource Name (ARN) of the Secrets Manager secret that holds your repository access token.

    " + }, "ingestQueryInstances":{ "shape":"InfluxDBv3EnterpriseParametersIngestQueryInstancesInteger", "documentation":"

    Specifies number of instances in the DbCluster which can both ingest and query.

    " @@ -2481,6 +3224,43 @@ "fault":true, "retryable":{"throttling":false} }, + "KmsKeyId":{ + "type":"string", + "max":2048, + "min":1, + "pattern":"[a-zA-Z0-9:/_\\-]+" + }, + "ListDbBackupsInput":{ + "type":"structure", + "members":{ + "dbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the DB instance or DB cluster to list backups for. If not specified, returns all backups in the account and region.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    The pagination token. To resume pagination, provide the nextToken value as an argument of a subsequent API invocation.

    " + }, + "maxResults":{ + "shape":"MaxResults", + "documentation":"

    The maximum number of items to return in the output. If the total number of items available is more than the value specified, a nextToken is provided in the output. To resume pagination, provide the nextToken value as an argument of a subsequent API invocation.

    " + } + } + }, + "ListDbBackupsOutput":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"DbBackupSummaryList", + "documentation":"

    A list of Timestream for InfluxDB backup summaries.

    " + }, + "nextToken":{ + "shape":"NextToken", + "documentation":"

    Token from a previous call of the operation. When this value is provided, the service returns results from where the previous response left off.

    " + } + } + }, "ListDbClustersInput":{ "type":"structure", "members":{ @@ -2736,6 +3516,12 @@ "min":2, "pattern":"(?:100|[1-9]?[0-9])%" }, + "PluginRepositorySecretArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:(aws|aws-cn|aws-us-gov):secretsmanager:[a-z0-9\\-]+:[0-9]{12}:secret:[a-zA-Z0-9/_+=.@\\-]+" + }, "Port":{ "type":"integer", "box":true, @@ -2889,6 +3675,14 @@ "nextMaintenanceTime":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The timestamp of the next scheduled maintenance operation on the DB instance.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations for the DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the DB instance.

    " } } }, @@ -2899,6 +3693,14 @@ "max":200, "min":1 }, + "ResourceDeploymentType":{ + "type":"string", + "enum":[ + "SINGLE_AZ", + "WITH_MULTIAZ_STANDBY", + "MULTI_NODE_READ_REPLICAS" + ] + }, "ResourceNotFoundException":{ "type":"structure", "required":[ @@ -2920,6 +3722,13 @@ "documentation":"

    The requested resource was not found or does not exist.

    ", "exception":true }, + "ResourceType":{ + "type":"string", + "enum":[ + "DB_INSTANCE", + "DB_CLUSTER" + ] + }, "ResponseTagMap":{ "type":"map", "key":{"shape":"TagKey"}, @@ -2927,6 +3736,117 @@ "max":200, "min":0 }, + "RestoreFromDbBackupInput":{ + "type":"structure", + "required":[ + "name", + "dbBackupId" + ], + "members":{ + "name":{ + "shape":"DbResourceName", + "documentation":"

    The name of the new resource to create from the restore. If restoring to an existing resource, the name must match the existing resource name.

    " + }, + "dbBackupId":{ + "shape":"DbBackupId", + "documentation":"

    The identifier of the backup to restore from.

    " + }, + "restoreToTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The point in time to restore to, for continuous backups. Must be within the backup's retention window.

    " + }, + "restoreMode":{ + "shape":"RestoreMode", + "documentation":"

    Specifies whether to restore to a new resource or replace the existing resource. Valid values are NEW_RESOURCE (default) and REPLACE_EXISTING.

    " + }, + "vpcSubnetIds":{ + "shape":"VpcSubnetIdList", + "documentation":"

    A list of VPC subnet IDs for the restored resource. If not specified, the restored resource uses the same subnets as the backup.

    " + }, + "vpcSecurityGroupIds":{ + "shape":"VpcSecurityGroupIdList", + "documentation":"

    A list of VPC security group IDs for the restored resource. If not specified, the restored resource uses the same security groups as the backup.

    " + }, + "publiclyAccessible":{ + "shape":"Boolean", + "documentation":"

    Specifies whether the restored resource is publicly accessible.

    " + }, + "logDeliveryConfiguration":{ + "shape":"LogDeliveryConfiguration", + "documentation":"

    Configuration for sending InfluxDB engine logs to the specified S3 bucket for the restored resource.

    " + }, + "maintenanceSchedule":{ + "shape":"MaintenanceSchedule", + "documentation":"

    The maintenance schedule for the restored resource.

    " + }, + "tags":{ + "shape":"RequestTagMap", + "documentation":"

    A list of key-value pairs to associate with the restored resource.

    " + }, + "port":{ + "shape":"Port", + "documentation":"

    The port number on which the restored InfluxDB resource accepts connections.

    " + }, + "networkType":{ + "shape":"NetworkType", + "documentation":"

    Specifies the network type of the restored resource. Valid values are IPV4 and DUAL.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    Specifies the deployment type of the restored resource. Valid values are SINGLE_AZ, WITH_MULTIAZ_STANDBY, and MULTI_NODE_READ_REPLICAS.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationInputList", + "documentation":"

    A list of backup configurations to apply to the restored resource.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key identifier to use for encryption of the restored resource. Can be a key ID, key ARN, alias name, or alias ARN.

    " + } + } + }, + "RestoreFromDbBackupOutput":{ + "type":"structure", + "members":{ + "restoredDbResourceId":{ + "shape":"DbResourceId", + "documentation":"

    The identifier of the restored DB resource.

    " + }, + "restoreStatus":{ + "shape":"RestoreStatus", + "documentation":"

    The status of the restore operation.

    " + }, + "resourceType":{ + "shape":"ResourceType", + "documentation":"

    The type of the restored resource. Valid values are DB_INSTANCE and DB_CLUSTER.

    " + }, + "engineType":{ + "shape":"EngineType", + "documentation":"

    The engine type of the restored resource.

    " + }, + "deploymentType":{ + "shape":"ResourceDeploymentType", + "documentation":"

    The deployment type of the restored resource.

    " + } + } + }, + "RestoreMode":{ + "type":"string", + "enum":[ + "NEW_RESOURCE", + "REPLACE_EXISTING" + ] + }, + "RestoreStatus":{ + "type":"string", + "enum":["RESTORING"] + }, + "RetentionDays":{ + "type":"integer", + "box":true, + "max":3650, + "min":1 + }, "S3Configuration":{ "type":"structure", "required":[ @@ -2974,7 +3894,9 @@ "UPDATING_INSTANCE_TYPE", "MAINTENANCE", "REBOOTING", - "REBOOT_FAILED" + "REBOOT_FAILED", + "RESTORING", + "RESTORE_FAILED" ] }, "String":{"type":"string"}, @@ -3085,6 +4007,10 @@ "maintenanceSchedule":{ "shape":"MaintenanceSchedule", "documentation":"

    Specifies the maintenance schedule for the DB cluster, including the preferred maintenance window and timezone.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationInputList", + "documentation":"

    A list of backup configurations to update for the DB cluster.

    " } } }, @@ -3136,6 +4062,10 @@ "maintenanceSchedule":{ "shape":"MaintenanceSchedule", "documentation":"

    Specifies the maintenance schedule for the DB instance, including the preferred maintenance window and timezone.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationInputList", + "documentation":"

    A list of backup configurations to update for the DB instance.

    " } } }, @@ -3247,6 +4177,14 @@ "nextMaintenanceTime":{ "shape":"SyntheticTimestamp_date_time", "documentation":"

    The timestamp of the next scheduled maintenance operation on the DB instance.

    " + }, + "dbBackupConfigurations":{ + "shape":"DbBackupConfigurationOutputList", + "documentation":"

    The backup configurations for the DB instance.

    " + }, + "kmsKeyId":{ + "shape":"KmsKeyId", + "documentation":"

    The Amazon Web Services KMS key ARN used for encryption of the DB instance.

    " } } }, diff --git a/services/timestreamquery/pom.xml b/services/timestreamquery/pom.xml index 719f627e0cc8..e2befeab5c91 100644 --- a/services/timestreamquery/pom.xml +++ b/services/timestreamquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT timestreamquery AWS Java SDK :: Services :: Timestream Query diff --git a/services/timestreamquery/src/main/resources/codegen-resources/customization.config b/services/timestreamquery/src/main/resources/codegen-resources/customization.config index 75948b49c354..3cee03d437e0 100644 --- a/services/timestreamquery/src/main/resources/codegen-resources/customization.config +++ b/services/timestreamquery/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,4 @@ { - "allowEndpointOverrideForEndpointDiscoveryRequiredOperations": true, - - "enableGenerateCompiledEndpointRules": true + "allowEndpointOverrideForEndpointDiscoveryRequiredOperations": true } diff --git a/services/timestreamquery/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/timestreamquery/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6dd5dec9ce55 --- /dev/null +++ b/services/timestreamquery/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,245 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-query-fips.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-query.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.timestream-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.timestream.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.timestream-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.timestream.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://query.timestream.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAoAAAAGAAAABAAAAAcF9eENAAAABgAAAAgF9eEMAAAABwX14QUAAAAJAAAACAX14QUF9eELAAAABAAAAA0AAAALAAAABQAAAAwF9eEKAAAACAX14QgF9eEJAAAABQAAAA4F9eEHAAAABgAAAA8F9eEHAAAABwX14QQAAAAQAAAACAX14QUF9eEGAAAAAwX14QEAAAASAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/timestreamquery/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/timestreamquery/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index a0469a6666cd..000000000000 --- a/services/timestreamquery/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,439 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-query-fips.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-query.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://query.timestream-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://query.timestream.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://query.timestream-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-query.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-query.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://query.timestream.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://query.timestream.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/timestreamwrite/pom.xml b/services/timestreamwrite/pom.xml index a5b5a2acae1e..06a077d4c2b7 100644 --- a/services/timestreamwrite/pom.xml +++ b/services/timestreamwrite/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT timestreamwrite AWS Java SDK :: Services :: Timestream Write diff --git a/services/timestreamwrite/src/main/resources/codegen-resources/customization.config b/services/timestreamwrite/src/main/resources/codegen-resources/customization.config index bca9c08d17ec..f5001ab47fc6 100644 --- a/services/timestreamwrite/src/main/resources/codegen-resources/customization.config +++ b/services/timestreamwrite/src/main/resources/codegen-resources/customization.config @@ -1,4 +1,3 @@ { - "allowEndpointOverrideForEndpointDiscoveryRequiredOperations": true, - "enableGenerateCompiledEndpointRules": true + "allowEndpointOverrideForEndpointDiscoveryRequiredOperations": true } diff --git a/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a6b3bb6c3cd9 --- /dev/null +++ b/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,245 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-ingest-fips.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://timestream-ingest.{Region}.api.aws", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ingest.timestream-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ingest.timestream.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ingest.timestream-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ingest.timestream.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://ingest.timestream.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 18, + "nodes": "/////wAAAAH/////AAAAAAAAABEAAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAoAAAAGAAAABAAAAAcF9eENAAAABgAAAAgF9eEMAAAABwX14QUAAAAJAAAACAX14QUF9eELAAAABAAAAA0AAAALAAAABQAAAAwF9eEKAAAACAX14QgF9eEJAAAABQAAAA4F9eEHAAAABgAAAA8F9eEHAAAABwX14QQAAAAQAAAACAX14QUF9eEGAAAAAwX14QEAAAASAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 6f0d2f7c3a1f..000000000000 --- a/services/timestreamwrite/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,439 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-ingest-fips.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-ingest.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ingest.timestream-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://ingest.timestream.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ingest.timestream-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-ingest.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - "aws-us-gov", - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - } - ] - } - ], - "endpoint": { - "url": "https://timestream-ingest.{Region}.api.aws", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ingest.timestream.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://ingest.timestream.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/tnb/pom.xml b/services/tnb/pom.xml index 90d10d5d37cf..371ab044eaac 100644 --- a/services/tnb/pom.xml +++ b/services/tnb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT tnb AWS Java SDK :: Services :: Tnb diff --git a/services/tnb/src/main/resources/codegen-resources/customization.config b/services/tnb/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/tnb/src/main/resources/codegen-resources/customization.config +++ b/services/tnb/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/tnb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/tnb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c094d11bd312 --- /dev/null +++ b/services/tnb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tnb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tnb-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tnb.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://tnb.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/tnb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/tnb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 5ce23f51b9de..000000000000 --- a/services/tnb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tnb-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tnb-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tnb.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://tnb.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/transcribe/pom.xml b/services/transcribe/pom.xml index 42c7b847b0b1..86716cae2a35 100644 --- a/services/transcribe/pom.xml +++ b/services/transcribe/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT transcribe AWS Java SDK :: Services :: Transcribe diff --git a/services/transcribe/src/main/resources/codegen-resources/customization.config b/services/transcribe/src/main/resources/codegen-resources/customization.config index 7d4a6e0d6c5b..ff06be57a475 100644 --- a/services/transcribe/src/main/resources/codegen-resources/customization.config +++ b/services/transcribe/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "verifiedSimpleMethods" : [ "listTranscriptionJobs", "listVocabularies" diff --git a/services/transcribe/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/transcribe/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..6d7e6fd33e4b --- /dev/null +++ b/services/transcribe/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,263 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "cn-north-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "cn-northwest-1" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribe-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://fips.transcribe.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribe-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribe.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cn.transcribe.cn-north-1.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://cn.transcribe.cn-northwest-1.amazonaws.com.cn", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribe.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 17, + "nodes": "/////wAAAAH/////AAAAAAAAABAAAAADAAAAAQAAAAQF9eEOAAAAAgAAAAUF9eEOAAAAAwAAAAoAAAAGAAAABQAAAAkAAAAHAAAABwX14QsAAAAIAAAACAX14QwF9eENAAAABgX14QkF9eEKAAAABAAAAAwAAAALAAAABQX14QUF9eEIAAAABQAAAA8AAAANAAAACQX14QYAAAAOAAAACgX14QYF9eEHAAAABgX14QQF9eEFAAAAAwX14QEAAAARAAAABQX14QIF9eED" +} \ No newline at end of file diff --git a/services/transcribe/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/transcribe/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 4d612ce99fdb..000000000000 --- a/services/transcribe/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,402 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transcribe-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - } - ], - "endpoint": { - "url": "https://fips.transcribe.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws-us-gov" - ] - } - ], - "endpoint": { - "url": "https://fips.transcribe.{Region}.amazonaws.com", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://transcribe-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transcribe.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "cn-north-1" - ] - } - ], - "endpoint": { - "url": "https://cn.transcribe.cn-north-1.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "ref": "Region" - }, - "cn-northwest-1" - ] - } - ], - "endpoint": { - "url": "https://cn.transcribe.cn-northwest-1.amazonaws.com.cn", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://transcribe.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/transcribe/src/main/resources/codegen-resources/service-2.json b/services/transcribe/src/main/resources/codegen-resources/service-2.json index 92882754bd50..eb19bab28b5e 100644 --- a/services/transcribe/src/main/resources/codegen-resources/service-2.json +++ b/services/transcribe/src/main/resources/codegen-resources/service-2.json @@ -637,6 +637,23 @@ ], "documentation":"

    Updates the specified Call Analytics category with new rules. Note that the UpdateCallAnalyticsCategory operation overwrites all existing rules contained in the specified category. You cannot append additional rules onto an existing category.

    To create a new category, see .

    " }, + "UpdateLanguageModel":{ + "name":"UpdateLanguageModel", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UpdateLanguageModelRequest"}, + "output":{"shape":"UpdateLanguageModelResponse"}, + "errors":[ + {"shape":"BadRequestException"}, + {"shape":"LimitExceededException"}, + {"shape":"InternalFailureException"}, + {"shape":"NotFoundException"}, + {"shape":"ConflictException"} + ], + "documentation":"

    Updates the encryption configuration for an existing custom language model. You can use this operation to change the KMS key used to encrypt your model artifacts. The model artifacts are re-encrypted in place. No model training is required.

    Your custom language model must not be in the IN_PROGRESS state when you call this operation. You cannot submit another update while a previous update is in progress. Use to check the current state of your model.

    Your custom language model remains available for transcription jobs while the update is being processed.

    " + }, "UpdateMedicalVocabulary":{ "name":"UpdateMedicalVocabulary", "http":{ @@ -669,7 +686,7 @@ {"shape":"NotFoundException"}, {"shape":"ConflictException"} ], - "documentation":"

    Updates an existing custom vocabulary with new values. This operation overwrites all existing information with your new values; you cannot append new terms onto an existing custom vocabulary.

    " + "documentation":"

    Updates an existing custom vocabulary with new values. This operation overwrites all existing information with your new values; you cannot append new terms onto an existing custom vocabulary.

    Your custom vocabulary must be in a terminal state (READY or FAILED) before you can update it. You must include either Phrases or VocabularyFileUri in your request.

    " }, "UpdateVocabularyFilter":{ "name":"UpdateVocabularyFilter", @@ -683,9 +700,10 @@ {"shape":"BadRequestException"}, {"shape":"LimitExceededException"}, {"shape":"InternalFailureException"}, - {"shape":"NotFoundException"} + {"shape":"NotFoundException"}, + {"shape":"ConflictException"} ], - "documentation":"

    Updates an existing custom vocabulary filter with a new list of words. The new list you provide overwrites all previous entries; you cannot append new terms onto an existing custom vocabulary filter.

    " + "documentation":"

    Updates an existing custom vocabulary filter with a new list of words. The new list you provide overwrites all previous entries; you cannot append new terms onto an existing custom vocabulary filter.

    You must include either Words or VocabularyFilterFileUri in your request.

    " } }, "shapes":{ @@ -1109,6 +1127,10 @@ "shape":"InputDataConfig", "documentation":"

    Contains the Amazon S3 location of the training data you want to use to create a new custom language model, and permissions to access this location.

    When using InputDataConfig, you must include these sub-parameters: S3Uri, which is the Amazon S3 location of your training data, and DataAccessRoleArn, which is the Amazon Resource Name (ARN) of the role that has permission to access your specified Amazon S3 location. You can optionally include TuningDataS3Uri, which is the Amazon S3 location of your tuning data. If you specify different Amazon S3 locations for training and tuning data, the ARN you use must have permissions to access both locations.

    " }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the encryption configuration for your custom language model. Your model artifacts are encrypted with the specified KMS key or with an AWS-owned key if a key is not supplied.

    " + }, "Tags":{ "shape":"TagList", "documentation":"

    Adds one or more custom tags, each in the form of a key:value pair, to a new custom language model at the time you create this new model.

    To learn more about using tags with Amazon Transcribe, refer to Tagging resources.

    " @@ -1220,7 +1242,11 @@ }, "DataAccessRoleArn":{ "shape":"DataAccessRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary filter). If the role that you specify doesn’t have the appropriate permissions to access the specified Amazon S3 location, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary filter). If you include EncryptionConfiguration in your request, this role must also have permissions to access the specified KMS key. If the role that you specify doesn’t have the appropriate permissions, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the encryption configuration for your custom vocabulary filter. Your vocabulary filter artifacts are encrypted with the specified KMS key or with an AWS-owned key if a key is not supplied.

    " } } }, @@ -1270,7 +1296,11 @@ }, "DataAccessRoleArn":{ "shape":"DataAccessRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary). If the role that you specify doesn’t have the appropriate permissions to access the specified Amazon S3 location, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary). If you include EncryptionConfiguration in your request, this role must also have permissions to access the specified KMS key. If the role that you specify doesn’t have the appropriate permissions, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the encryption configuration for your custom vocabulary. Your vocabulary artifacts are encrypted with the specified KMS key or with an AWS-owned key if a key is not supplied.

    " } } }, @@ -1424,6 +1454,21 @@ } }, "DurationInSeconds":{"type":"float"}, + "EncryptionConfiguration":{ + "type":"structure", + "required":["KMSKey"], + "members":{ + "KMSEncryptionContext":{ + "shape":"KMSEncryptionContextMap", + "documentation":"

    A map of plain text, non-secret key:value pairs, known as encryption context pairs, that provide an added layer of security for your data. For more information, see KMS encryption context.

    " + }, + "KMSKey":{ + "shape":"KMSKeyId", + "documentation":"

    The Amazon Resource Name (ARN) of the KMS key you want to use to encrypt your resource artifacts. Only full KMS key ARN format is supported.

    KMS key ARNs have the format arn:partition:kms:region:account:key/key-id. For example: arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab.

    For more information, see KMS key ARNs.

    " + } + }, + "documentation":"Encryption configuration for the invocation" + }, "FailureReason":{"type":"string"}, "GetCallAnalyticsCategoryRequest":{ "type":"structure", @@ -1587,6 +1632,14 @@ "DownloadUri":{ "shape":"Uri", "documentation":"

    The Amazon S3 location where the custom vocabulary filter is stored; use this URI to view or download the custom vocabulary filter.

    " + }, + "DataAccessRoleArn":{ + "shape":"DataAccessRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role used to access the Amazon S3 bucket that contains your input files and, if applicable, the KMS key specified in EncryptionConfiguration.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The encryption configuration used for your custom vocabulary filter.

    " } } }, @@ -1626,6 +1679,14 @@ "DownloadUri":{ "shape":"Uri", "documentation":"

    The Amazon S3 location where the custom vocabulary is stored; use this URI to view or download the custom vocabulary.

    " + }, + "DataAccessRoleArn":{ + "shape":"DataAccessRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of the IAM role used to access the Amazon S3 bucket that contains your input files and, if applicable, the KMS key specified in EncryptionConfiguration.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The encryption configuration used for your custom vocabulary.

    " } } }, @@ -1710,8 +1771,8 @@ }, "KMSEncryptionContextMap":{ "type":"map", - "key":{"shape":"NonEmptyString"}, - "value":{"shape":"NonEmptyString"}, + "key":{"shape":"PrintableNonEmptyString"}, + "value":{"shape":"PrintableNonEmptyString"}, "max":10, "min":1 }, @@ -1924,6 +1985,10 @@ "InputDataConfig":{ "shape":"InputDataConfig", "documentation":"

    The Amazon S3 location of the input files used to train and tune your custom language model, in addition to the data access role ARN (Amazon Resource Name) that has permissions to access these data.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    The encryption configuration used for your custom language model.

    " } }, "documentation":"

    Provides information about a custom language model, including:

    • The base model name

    • When the model was created

    • The location of the files used to train the model

    • When the model was last modified

    • The name you chose for the model

    • The model's language

    • The model's processing state

    • Any available upgrades for the base model

    " @@ -2852,15 +2917,39 @@ "NAME", "PHONE", "SSN", + "DATE_TIME", + "PASSPORT_NUMBER", + "DRIVER_ID", + "URL", + "AGE", + "USERNAME", + "PASSWORD", + "AWS_ACCESS_KEY", + "AWS_SECRET_KEY", + "IP_ADDRESS", + "MAC_ADDRESS", + "LICENSE_PLATE", + "VEHICLE_IDENTIFICATION_NUMBER", + "US_INDIVIDUAL_TAX_IDENTIFICATION_NUMBER", + "CA_HEALTH_NUMBER", + "CA_SOCIAL_INSURANCE_NUMBER", + "INTERNATIONAL_BANK_ACCOUNT_NUMBER", + "SWIFT_CODE", "ALL" ] }, "PiiEntityTypes":{ "type":"list", "member":{"shape":"PiiEntityType"}, - "max":11, + "max":29, "min":0 }, + "PrintableNonEmptyString":{ + "type":"string", + "max":2000, + "min":1, + "pattern":"^[\\x20-\\x7E]+$" + }, "Pronouns":{ "type":"string", "enum":[ @@ -3759,6 +3848,41 @@ } } }, + "UpdateLanguageModelRequest":{ + "type":"structure", + "required":["ModelName"], + "members":{ + "ModelName":{ + "shape":"ModelName", + "documentation":"

    The name of the custom language model you want to update. Model names are case sensitive.

    " + }, + "DataAccessRoleArn":{ + "shape":"DataAccessRoleArn", + "documentation":"

    The Amazon Resource Name (ARN) of an IAM role. If you include EncryptionConfiguration in your request, this role must have permissions to access the specified KMS key. If the role that you specify doesn't have the appropriate permissions, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the new encryption configuration for your custom language model. The model artifacts are re-encrypted in place using the specified KMS key or with an AWS-owned key if a key is not supplied.

    " + } + } + }, + "UpdateLanguageModelResponse":{ + "type":"structure", + "members":{ + "ModelName":{ + "shape":"ModelName", + "documentation":"

    The name of the custom language model that was updated.

    " + }, + "ModelStatus":{ + "shape":"ModelStatus", + "documentation":"

    The status of the specified custom language model.

    " + }, + "LastModifiedTime":{ + "shape":"DateTime", + "documentation":"

    The date and time the specified custom language model was last modified.

    " + } + } + }, "UpdateMedicalVocabularyRequest":{ "type":"structure", "required":[ @@ -3820,7 +3944,11 @@ }, "DataAccessRoleArn":{ "shape":"DataAccessRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary filter). If the role that you specify doesn’t have the appropriate permissions to access the specified Amazon S3 location, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary filter). If you include EncryptionConfiguration in your request, this role must also have permissions to access the specified KMS key. If the role that you specify doesn’t have the appropriate permissions, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the new encryption configuration for your custom vocabulary filter. The vocabulary filter artifacts are re-encrypted in place using the specified KMS key or with an AWS-owned key if a key is not supplied.

    " } } }, @@ -3866,7 +3994,11 @@ }, "DataAccessRoleArn":{ "shape":"DataAccessRoleArn", - "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary). If the role that you specify doesn’t have the appropriate permissions to access the specified Amazon S3 location, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + "documentation":"

    The Amazon Resource Name (ARN) of an IAM role that has permissions to access the Amazon S3 bucket that contains your input files (in this case, your custom vocabulary). If you include EncryptionConfiguration in your request, this role must also have permissions to access the specified KMS key. If the role that you specify doesn’t have the appropriate permissions, your request fails.

    IAM role ARNs have the format arn:partition:iam::account:role/role-name-with-path. For example: arn:aws:iam::111122223333:role/Admin.

    For more information, see IAM ARNs.

    " + }, + "EncryptionConfiguration":{ + "shape":"EncryptionConfiguration", + "documentation":"

    Specifies the new encryption configuration for your custom vocabulary. The vocabulary artifacts are re-encrypted in place using the specified KMS key or with an AWS-owned key if a key is not supplied.

    " } } }, diff --git a/services/transcribestreaming/pom.xml b/services/transcribestreaming/pom.xml index 317edfaebab2..0d067fad4422 100644 --- a/services/transcribestreaming/pom.xml +++ b/services/transcribestreaming/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT transcribestreaming AWS Java SDK :: Services :: AWS Transcribe Streaming diff --git a/services/transcribestreaming/src/main/resources/codegen-resources/customization.config b/services/transcribestreaming/src/main/resources/codegen-resources/customization.config index 93624870594f..fde78a855326 100644 --- a/services/transcribestreaming/src/main/resources/codegen-resources/customization.config +++ b/services/transcribestreaming/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,4 @@ { - "enableGenerateCompiledEndpointRules": true, "serviceSpecificHttpConfig": "software.amazon.awssdk.services.transcribestreaming.internal.DefaultHttpConfigurationOptions", "skipSyncClientGeneration": true, "useLegacyEventGenerationScheme": { diff --git a/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..1c4c9846da5a --- /dev/null +++ b/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribestreaming-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribestreaming-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribestreaming.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transcribestreaming.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 983eec1ec984..000000000000 --- a/services/transcribestreaming/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transcribestreaming-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transcribestreaming-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transcribestreaming.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://transcribestreaming.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/transcribestreaming/src/main/resources/codegen-resources/service-2.json b/services/transcribestreaming/src/main/resources/codegen-resources/service-2.json index 9288096e5bae..2b6f32622adc 100644 --- a/services/transcribestreaming/src/main/resources/codegen-resources/service-2.json +++ b/services/transcribestreaming/src/main/resources/codegen-resources/service-2.json @@ -715,7 +715,7 @@ "members":{ "Message":{"shape":"String"} }, - "documentation":"

    Your client has exceeded one of the Amazon Transcribe limits. This is typically the audio length limit. Break your audio stream into smaller chunks and try your request again.

    ", + "documentation":"

    Your client has exceeded one of the Amazon Transcribe limits, typically the concurrent stream service quota. This error can also occur if a stream exceeds the maximum session duration. In rare cases, this error can also occur if you increase your number of concurrent streams too quickly. Reduce your number of concurrent streams and try your request again using an exponential backoff strategy.

    ", "error":{"httpStatusCode":429}, "exception":true }, @@ -730,7 +730,10 @@ "enum":[ "pcm", "ogg-opus", - "flac" + "flac", + "g711-alaw", + "g711-ulaw", + "g729" ] }, "MediaSampleRateHertz":{ @@ -2115,6 +2118,12 @@ "documentation":"

    Specify the time window, in minutes, during which your transcription session can be resumed, measured from the stream start time. This optional parameter accepts integer values from 1 to 300 (5 hours).

    For example, if your stream starts at 1 PM and you specify a SessionResumeWindow of 30 minutes, you can reconnect to the session as many times as you want until 1:30 PM.

    ", "location":"header", "locationName":"x-amzn-transcribe-session-resume-window" + }, + "TranscriptFormat":{ + "shape":"TranscriptFormat", + "documentation":"

    Specify how numbers, dates, and other alphanumeric entities are rendered in your transcription results.

    • WRITTEN renders these entities in their standard written form (for example, $50, 10:30 AM, and 101).

    • SPOKEN renders these entities as words, exactly as they were spoken (for example, fifty dollars, ten thirty a m, and one oh one).

    If you don't specify a value, Amazon Transcribe uses WRITTEN by default.

    ", + "location":"header", + "locationName":"x-amzn-transcribe-transcript-format" } }, "payload":"AudioStream" @@ -2269,6 +2278,12 @@ "documentation":"

    Provides the session resume window, in minutes, that you specified in your request.

    ", "location":"header", "locationName":"x-amzn-transcribe-session-resume-window" + }, + "TranscriptFormat":{ + "shape":"TranscriptFormat", + "documentation":"

    Provides the transcript format that you specified in your request.

    ", + "location":"header", + "locationName":"x-amzn-transcribe-transcript-format" } }, "payload":"TranscriptResultStream" @@ -2317,6 +2332,13 @@ "documentation":"

    The TranscriptEvent associated with a TranscriptResultStream.

    Contains a set of transcription results from one or more audio segments, along with additional information per your request parameters.

    ", "event":true }, + "TranscriptFormat":{ + "type":"string", + "enum":[ + "spoken", + "written" + ] + }, "TranscriptResultStream":{ "type":"structure", "members":{ @@ -2330,7 +2352,7 @@ }, "LimitExceededException":{ "shape":"LimitExceededException", - "documentation":"

    Your client has exceeded one of the Amazon Transcribe limits. This is typically the audio length limit. Break your audio stream into smaller chunks and try your request again.

    " + "documentation":"

    Your client has exceeded one of the Amazon Transcribe limits, typically the concurrent stream service quota. This error can also occur if a stream exceeds the maximum session duration. In rare cases, this error can also occur if you increase your number of concurrent streams too quickly. Reduce your number of concurrent streams and try your request again using an exponential backoff strategy.

    " }, "InternalFailureException":{ "shape":"InternalFailureException", diff --git a/services/transfer/pom.xml b/services/transfer/pom.xml index 38bc8b2141a5..b831846978f0 100644 --- a/services/transfer/pom.xml +++ b/services/transfer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT transfer AWS Java SDK :: Services :: Transfer diff --git a/services/transfer/src/main/resources/codegen-resources/customization.config b/services/transfer/src/main/resources/codegen-resources/customization.config index 74e0cba3a8db..6634ed4039cc 100644 --- a/services/transfer/src/main/resources/codegen-resources/customization.config +++ b/services/transfer/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listServers" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/transfer/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/transfer/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..9995696d904d --- /dev/null +++ b/services/transfer/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transfer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transfer-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transfer.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://transfer.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/transfer/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/transfer/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b9f931114adc..000000000000 --- a/services/transfer/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transfer-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transfer-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://transfer.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://transfer.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/transfer/src/main/resources/codegen-resources/service-2.json b/services/transfer/src/main/resources/codegen-resources/service-2.json index fc66ecc09a2b..3ada544275a9 100644 --- a/services/transfer/src/main/resources/codegen-resources/service-2.json +++ b/services/transfer/src/main/resources/codegen-resources/service-2.json @@ -4922,6 +4922,10 @@ "As2Transports":{ "shape":"As2Transports", "documentation":"

    Indicates the transport method for the AS2 messages. Currently, only HTTP is supported.

    " + }, + "ProxyConfig":{ + "shape":"ProxyConfig", + "documentation":"

    The configuration for PROXY protocol version 2 (PPv2) support on the Transfer Family server. For more information, see Working with Network Load Balancers.

    " } }, "documentation":"

    The protocol settings that are configured for your server.

    " @@ -4932,6 +4936,23 @@ "max":4, "min":1 }, + "ProxyConfig":{ + "type":"structure", + "members":{ + "SftpMode":{ + "shape":"ProxyMode", + "documentation":"

    Specifies whether the Transfer Family server requires or ignores a PPv2 header containing the original client IP address on incoming SFTP connections. If you don't specify a value, the default is NONE

    • NONE: the server reads and ignores any PPv2 header on incoming SFTP connections. This is the default value. Use this value when your SFTP server is not behind an NLB, or when you do not need to preserve client source IP addresses through an NLB.

    • PROXY_PROTOCOL_V2_ENFORCED: the server requires a valid PPv2 header on every incoming SFTP connection. When a valid header is present, the server applies it and uses the client IP address from the header. If a connection arrives without a PPv2 header, the server refuses the connection and logs an error to Amazon CloudWatch Logs indicating that the expected PPv2 header was missing. Use this value when your SFTP server is behind an NLB with PPv2 enabled on the target group.

      When you enable PROXY_PROTOCOL_V2_ENFORCED, the server trusts the source IP address in the PPv2 header. You must configure security groups on your server's VPC endpoint to restrict inbound traffic to only the NLB's private IP addresses. For the full requirements, see Working with Network Load Balancers.

    " + } + }, + "documentation":"

    Contains configuration for PROXY protocol version 2 (PPv2) support on an Transfer Family server. When enabled, Transfer Family reads the added PPv2 header from incoming connections to extract the original client IP address. This address is then available in Amazon CloudWatch Logs entries and is passed to custom identity providers during authentication, enabling IP-based access policies. For more information, see Working with Network Load Balancers.

    " + }, + "ProxyMode":{ + "type":"string", + "enum":[ + "NONE", + "PROXY_PROTOCOL_V2_ENFORCED" + ] + }, "Resource":{"type":"string"}, "ResourceExistsException":{ "type":"structure", @@ -5089,6 +5110,17 @@ "max":2048, "min":1 }, + "SecretVersionStage":{ + "type":"string", + "max":256, + "min":1 + }, + "SecretVersionStageList":{ + "type":"list", + "member":{"shape":"SecretVersionStage"}, + "max":2, + "min":1 + }, "SecurityGroupId":{ "type":"string", "max":20, @@ -5241,6 +5273,10 @@ "MaxConcurrentConnections":{ "shape":"MaxConcurrentConnections", "documentation":"

    Specify the number of concurrent connections that your connector creates to the remote server. The default value is 1. The maximum values is 5.

    If you are using the Amazon Web Services Management Console, the default value is 5.

    This parameter specifies the number of active connections that your connector can establish with the remote server at the same time. Increasing this value can enhance connector performance when transferring large file batches by enabling parallel operations.

    " + }, + "OrderedUserSecretVersionStages":{ + "shape":"SecretVersionStageList", + "documentation":"

    An ordered list of Amazon Web Services Secrets Manager version stages (staging labels, such as AWSCURRENT and AWSPREVIOUS) for the secret identified by UserSecretId. When establishing a connection, the connector attempts to retrieve the SFTP user's credentials from each version stage in the order listed, and uses the first version it can successfully retrieve. This lets you rotate the user secret without interrupting connector operations.

    " } }, "documentation":"

    Contains the details for an SFTP connector object. The connector object is used for transferring files to and from a partner's SFTP server.

    " @@ -6558,5 +6594,5 @@ "min":0 } }, - "documentation":"

    Transfer Family is a fully managed service that enables the transfer of files over the File Transfer Protocol (FTP), File Transfer Protocol over SSL (FTPS), or Secure Shell (SSH) File Transfer Protocol (SFTP) directly into and out of Amazon Simple Storage Service (Amazon S3) or Amazon EFS. Additionally, you can use Applicability Statement 2 (AS2) to transfer files into and out of Amazon S3. Amazon Web Services helps you seamlessly migrate your file transfer workflows to Transfer Family by integrating with existing authentication systems, and providing DNS routing with Amazon Route 53 so nothing changes for your customers and partners, or their applications. With your data in Amazon S3, you can use it with Amazon Web Services services for processing, analytics, machine learning, and archiving. Getting started with Transfer Family is easy since there is no infrastructure to buy and set up.

    " + "documentation":"

    Transfer Family offers fully managed support for the transfer of files over SFTP, AS2, FTPS, FTP, and web browser-based transfers directly into and out of Amazon Web Services storage services.

    File transfer protocols are used in data exchange workflows across different industries such as financial services, healthcare, advertising, and retail, among others. Transfer Family simplifies the migration of file transfer workflows to Amazon Web Services.

    To use the Transfer Family service, you instantiate a server in the Amazon Web Services Region of your choice. You can create the server, list available servers, and update and delete servers. The server is the entity that requests file operations from Transfer Family. Servers have a number of important properties. The server is a named instance as identified by a system assigned ServerId identifier. You can optionally assign a hostname, or even a custom hostname to a server. The service bills for any instantiated servers (even ones OFFLINE), and for the amount of data transferred.

    Users must be known to the server that requests file operations. A user as identified by their username is assigned to a server. Usernames are used to authenticate requests. A server can have only one authentication method: AWS_DIRECTORY_SERVICE, SERVICE_MANAGED, AWS_LAMBDA, or API_GATEWAY.

    Transfer Family also supports web applications that provide browser-based file transfer capabilities. Web applications can be configured with VPC endpoints to enable secure, private connectivity within your Virtual Private Cloud (VPC). This allows you to control network access and route traffic through your VPC infrastructure while maintaining the managed benefits of Transfer Family.

    This API interface reference for Transfer Family contains documentation for a programming interface that you can use to manage Transfer Family. The reference structure is as follows:

    • For the alphabetical list of API actions, see .

    • For the alphabetical list of data types, see .

    • For a list of common query parameters, see CommonParameters.

    • For descriptions of the error codes, see CommonErrors.

    Rather than actually running a command, you can use the --generate-cli-skeleton parameter with any API call to generate and display a parameter template. You can then use the generated template to customize and use as input on a later command. For details, see Generate and use a parameter skeleton file.

    " } diff --git a/services/translate/pom.xml b/services/translate/pom.xml index 6878f1637908..57ca96fd0dd9 100644 --- a/services/translate/pom.xml +++ b/services/translate/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 translate diff --git a/services/translate/src/main/resources/codegen-resources/customization.config b/services/translate/src/main/resources/codegen-resources/customization.config index f927886f4077..9cdac486bf17 100644 --- a/services/translate/src/main/resources/codegen-resources/customization.config +++ b/services/translate/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listTerminologies" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/translate/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/translate/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..a6e1d92bea81 --- /dev/null +++ b/services/translate/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://translate-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://translate-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://translate.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://translate.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/translate/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/translate/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7c118583df74..000000000000 --- a/services/translate/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://translate-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://translate-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://translate.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://translate.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/trustedadvisor/pom.xml b/services/trustedadvisor/pom.xml index 1dd2143f1086..5126e9e4cd92 100644 --- a/services/trustedadvisor/pom.xml +++ b/services/trustedadvisor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT trustedadvisor AWS Java SDK :: Services :: Trusted Advisor diff --git a/services/trustedadvisor/src/main/resources/codegen-resources/customization.config b/services/trustedadvisor/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/trustedadvisor/src/main/resources/codegen-resources/customization.config +++ b/services/trustedadvisor/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..71dbf1b8fa11 --- /dev/null +++ b/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://trustedadvisor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://trustedadvisor-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://trustedadvisor.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://trustedadvisor.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1a95d4361f7a..000000000000 --- a/services/trustedadvisor/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://trustedadvisor-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://trustedadvisor-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://trustedadvisor.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://trustedadvisor.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/trustedadvisor/src/main/resources/codegen-resources/paginators-1.json b/services/trustedadvisor/src/main/resources/codegen-resources/paginators-1.json index 0ac4c7b0e358..f21fde7718e7 100644 --- a/services/trustedadvisor/src/main/resources/codegen-resources/paginators-1.json +++ b/services/trustedadvisor/src/main/resources/codegen-resources/paginators-1.json @@ -35,6 +35,12 @@ "output_token": "nextToken", "limit_key": "maxResults", "result_key": "recommendationSummaries" + }, + "ListRecommendationsForResource": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "recommendationForResourceSummaries" } } } diff --git a/services/trustedadvisor/src/main/resources/codegen-resources/service-2.json b/services/trustedadvisor/src/main/resources/codegen-resources/service-2.json index f6aad2ee884e..56e948995697 100644 --- a/services/trustedadvisor/src/main/resources/codegen-resources/service-2.json +++ b/services/trustedadvisor/src/main/resources/codegen-resources/service-2.json @@ -181,6 +181,24 @@ "documentation":"

    List a filterable set of Recommendations. This API provides global recommendations, eliminating the need to call the API in each AWS Region.

    ", "readonly":true }, + "ListRecommendationsForResource":{ + "name":"ListRecommendationsForResource", + "http":{ + "method":"GET", + "requestUri":"/v1/recommendations-for-resource/{awsResourceArn}", + "responseCode":200 + }, + "input":{"shape":"ListRecommendationsForResourceRequest"}, + "output":{"shape":"ListRecommendationsForResourceResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    List all Trusted Advisor recommendations for a given AWS resource ARN.

    ", + "readonly":true + }, "UpdateOrganizationRecommendationLifecycle":{ "name":"UpdateOrganizationRecommendationLifecycle", "http":{ @@ -294,6 +312,12 @@ "type":"list", "member":{"shape":"AccountRecommendationLifecycleSummary"} }, + "AwsResourceArn":{ + "type":"string", + "max":2048, + "min":20, + "pattern":"arn:aws(-\\w+)*:[\\w\\d-]+:([\\w\\d-]*)?:[\\w\\d_-]*([:/].+)*" + }, "BatchUpdateRecommendationResourceExclusionRequest":{ "type":"structure", "required":["recommendationResourceExclusions"], @@ -374,6 +398,22 @@ "metadata":{ "shape":"StringMap", "documentation":"

    The column headings for the metadata returned in the resource

    " + }, + "resourceArnQueryable":{ + "shape":"Boolean", + "documentation":"

    Indicates whether this check is supported by the ListRecommendationsForResource API.

    " + }, + "awsResourceTypes":{ + "shape":"StringList", + "documentation":"

    The AWS resource types that this check evaluates (for example, AWS::EC2::Instance).

    " + }, + "checkGranularity":{ + "shape":"String", + "documentation":"

    The granularity level at which the check operates: resource, account, or account_region.

    " + }, + "recommendationId":{ + "shape":"String", + "documentation":"

    The recommendation identifier associated with the check.

    " } }, "documentation":"

    A summary of an AWS Trusted Advisor Check

    " @@ -848,6 +888,84 @@ "max":10000, "min":4 }, + "ListRecommendationsForResourceRequest":{ + "type":"structure", + "required":["awsResourceArn"], + "members":{ + "nextToken":{ + "shape":"ListRecommendationsForResourceRequestNextTokenString", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "maxResults":{ + "shape":"ListRecommendationsForResourceRequestMaxResultsInteger", + "documentation":"

    The maximum number of results to return per page

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "awsResourceArn":{ + "shape":"AwsResourceArn", + "documentation":"

    The ARN of the AWS resource to query recommendations for

    ", + "location":"uri", + "locationName":"awsResourceArn" + }, + "pillar":{ + "shape":"RecommendationPillar", + "documentation":"

    The pillar that the recommendation belongs to

    ", + "location":"querystring", + "locationName":"pillar" + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the Recommendation Resource

    ", + "location":"querystring", + "locationName":"status" + }, + "checkArn":{ + "shape":"CheckArn", + "documentation":"

    The AWS Trusted Advisor Check ARN that relates to the Recommendation

    ", + "location":"querystring", + "locationName":"checkArn" + }, + "language":{ + "shape":"RecommendationLanguage", + "documentation":"

    The ISO 639-1 code for the language that you want your recommendations to appear in.

    ", + "location":"querystring", + "locationName":"language" + } + } + }, + "ListRecommendationsForResourceRequestMaxResultsInteger":{ + "type":"integer", + "box":true, + "max":600, + "min":1 + }, + "ListRecommendationsForResourceRequestNextTokenString":{ + "type":"string", + "max":10000, + "min":4 + }, + "ListRecommendationsForResourceResponse":{ + "type":"structure", + "required":["recommendationForResourceSummaries"], + "members":{ + "nextToken":{ + "shape":"ListRecommendationsForResourceResponseNextTokenString", + "documentation":"

    The token for the next set of results. Use the value returned in the previous response in the next request to retrieve the next set of results.

    " + }, + "recommendationForResourceSummaries":{ + "shape":"RecommendationForResourceSummaryList", + "documentation":"

    List of Trusted Advisor recommendations associated with the given AWS resource

    " + } + } + }, + "ListRecommendationsForResourceResponseNextTokenString":{ + "type":"string", + "max":10000, + "min":4 + }, "ListRecommendationsRequest":{ "type":"structure", "members":{ @@ -1334,6 +1452,58 @@ }, "documentation":"

    Cost optimizing aggregates for a Recommendation

    " }, + "RecommendationForResourceSummary":{ + "type":"structure", + "required":[ + "checkArn", + "recommendationArn", + "awsResourceArn", + "status", + "lastUpdatedAt", + "exclusionStatus", + "metadata", + "pillars" + ], + "members":{ + "checkArn":{ + "shape":"CheckArn", + "documentation":"

    The Check ARN

    " + }, + "recommendationArn":{ + "shape":"AccountRecommendationArn", + "documentation":"

    The Recommendation ARN

    " + }, + "awsResourceArn":{ + "shape":"AwsResourceArn", + "documentation":"

    The AWS Resource ARN

    " + }, + "status":{ + "shape":"ResourceStatus", + "documentation":"

    The current status of the recommendation

    " + }, + "lastUpdatedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    When the recommendation was last updated

    " + }, + "exclusionStatus":{ + "shape":"ExclusionStatus", + "documentation":"

    The exclusion status of the recommendation

    " + }, + "metadata":{ + "shape":"StringMap", + "documentation":"

    Metadata associated with the recommendation

    " + }, + "pillars":{ + "shape":"RecommendationPillarList", + "documentation":"

    The Pillars that the Recommendation is optimizing

    " + } + }, + "documentation":"

    Summary of a Recommendation for a specific AWS Resource

    " + }, + "RecommendationForResourceSummaryList":{ + "type":"list", + "member":{"shape":"RecommendationForResourceSummary"} + }, "RecommendationLanguage":{ "type":"string", "enum":[ @@ -1651,6 +1821,10 @@ "enum":["no_data_ok"] }, "String":{"type":"string"}, + "StringList":{ + "type":"list", + "member":{"shape":"String"} + }, "StringMap":{ "type":"map", "key":{"shape":"String"}, diff --git a/services/uxc/pom.xml b/services/uxc/pom.xml index e73a8a3a36e5..34ef01bcfdc0 100644 --- a/services/uxc/pom.xml +++ b/services/uxc/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT uxc AWS Java SDK :: Services :: Uxc diff --git a/services/uxc/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/uxc/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b3384ba5f721 --- /dev/null +++ b/services/uxc/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://uxc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://uxc.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/uxc/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/uxc/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7be4f909805e..000000000000 --- a/services/uxc/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://uxc-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://uxc.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/verifiedpermissions/pom.xml b/services/verifiedpermissions/pom.xml index d11f69db2b00..3fc6bfac5784 100644 --- a/services/verifiedpermissions/pom.xml +++ b/services/verifiedpermissions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT verifiedpermissions AWS Java SDK :: Services :: Verified Permissions diff --git a/services/verifiedpermissions/src/main/resources/codegen-resources/customization.config b/services/verifiedpermissions/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/verifiedpermissions/src/main/resources/codegen-resources/customization.config +++ b/services/verifiedpermissions/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..f69b855c32bc --- /dev/null +++ b/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://verifiedpermissions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://verifiedpermissions-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://verifiedpermissions.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://verifiedpermissions.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 7aa322e3abc9..000000000000 --- a/services/verifiedpermissions/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://verifiedpermissions-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://verifiedpermissions-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://verifiedpermissions.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://verifiedpermissions.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/voiceid/pom.xml b/services/voiceid/pom.xml index c1b77857464e..7a4fbe3710ee 100644 --- a/services/voiceid/pom.xml +++ b/services/voiceid/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT voiceid AWS Java SDK :: Services :: Voice ID diff --git a/services/voiceid/src/main/resources/codegen-resources/customization.config b/services/voiceid/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/voiceid/src/main/resources/codegen-resources/customization.config +++ b/services/voiceid/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/voiceid/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/voiceid/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..05282845ef83 --- /dev/null +++ b/services/voiceid/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voiceid-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voiceid-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voiceid.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://voiceid.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/voiceid/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/voiceid/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2409dc5414da..000000000000 --- a/services/voiceid/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voiceid-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voiceid-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://voiceid.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://voiceid.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/vpclattice/pom.xml b/services/vpclattice/pom.xml index 2326204fa7dc..0d4dcaca4aea 100644 --- a/services/vpclattice/pom.xml +++ b/services/vpclattice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT vpclattice AWS Java SDK :: Services :: VPC Lattice diff --git a/services/vpclattice/src/main/resources/codegen-resources/customization.config b/services/vpclattice/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/vpclattice/src/main/resources/codegen-resources/customization.config +++ b/services/vpclattice/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/vpclattice/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/vpclattice/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..3131c2fb1001 --- /dev/null +++ b/services/vpclattice/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://vpc-lattice-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://vpc-lattice-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://vpc-lattice.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://vpc-lattice.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/vpclattice/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/vpclattice/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d01675059e49..000000000000 --- a/services/vpclattice/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://vpc-lattice-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://vpc-lattice-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://vpc-lattice.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://vpc-lattice.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/vpclattice/src/main/resources/codegen-resources/service-2.json b/services/vpclattice/src/main/resources/codegen-resources/service-2.json index 648afc148b50..a54305bc2386 100644 --- a/services/vpclattice/src/main/resources/codegen-resources/service-2.json +++ b/services/vpclattice/src/main/resources/codegen-resources/service-2.json @@ -1609,6 +1609,27 @@ "min":0, "pattern":"(arn(:[a-z0-9]+([.-][a-z0-9]+)*){2}(:([a-z0-9]+([.-][a-z0-9]+)*)?){2}:certificate/[0-9a-z-]+)?" }, + "CidrRange":{ + "type":"string", + "max":50, + "min":1 + }, + "CidrRangeList":{ + "type":"list", + "member":{"shape":"CidrRange"}, + "max":10, + "min":1 + }, + "CidrResource":{ + "type":"structure", + "members":{ + "cidrRanges":{ + "shape":"CidrRangeList", + "documentation":"

    The CIDR ranges of the network segment, for example, 10.0.0.0/16.

    " + } + }, + "documentation":"

    Describes a CIDR resource, which represents a network segment as one or more CIDR ranges.

    " + }, "ClientToken":{ "type":"string", "max":64, @@ -1798,19 +1819,19 @@ }, "type":{ "shape":"ResourceConfigurationType", - "documentation":"

    The type of resource configuration. A resource configuration can be one of the following types:

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    " + "documentation":"

    The type of resource configuration. A resource configuration can be one of the following types:

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    • CIDR - A network segment, expressed as a range of IP addresses (a CIDR block). Use this type to share a portion of your network rather than an individual resource. A consumer accesses the resources within the CIDR range through a Tunnel VPC endpoint. You can't add a CIDR resource configuration to a service network. A CIDR resource configuration must be associated with a resource gateway whose DNS resolution is set to IN_VPC.

    " }, "portRanges":{ "shape":"PortRangeList", - "documentation":"

    (SINGLE, GROUP, CHILD) The TCP port ranges that a consumer can use to access a resource configuration (for example: 1-65535). You can separate port ranges using commas (for example: 1,2,22-30).

    " + "documentation":"

    (SINGLE, GROUP, CHILD, CIDR) The port ranges that a consumer can use to access a resource configuration (for example: 1-65535). You can separate port ranges using commas (for example: 1,2,22-30). To resolve DNS through a CIDR resource configuration, include port 53 in the port ranges.

    " }, "protocol":{ "shape":"ProtocolType", - "documentation":"

    (SINGLE, GROUP) The protocol accepted by the resource configuration.

    " + "documentation":"

    (SINGLE, GROUP, CIDR) The protocol accepted by the resource configuration. The default is TCP. TCP_UDP is supported only for CIDR resource configurations; specify it for a CIDR resource configuration to allow DNS resolution, which uses UDP.

    " }, "resourceGatewayIdentifier":{ "shape":"ResourceGatewayIdentifier", - "documentation":"

    (SINGLE, GROUP, ARN) The ID or ARN of the resource gateway used to connect to the resource configuration. For a child resource configuration, this value is inherited from the parent resource configuration.

    " + "documentation":"

    (SINGLE, GROUP, ARN, CIDR) The ID or ARN of the resource gateway used to connect to the resource configuration. For a child resource configuration, this value is inherited from the parent resource configuration. For a CIDR resource configuration, the associated resource gateway must have its DNS resolution set to IN_VPC so that DNS queries resolve in the context of your VPC.

    " }, "resourceConfigurationGroupIdentifier":{ "shape":"ResourceConfigurationIdentifier", @@ -1818,7 +1839,7 @@ }, "resourceConfigurationDefinition":{ "shape":"ResourceConfigurationDefinition", - "documentation":"

    Identifies the resource configuration in one of the following ways:

    • Amazon Resource Name (ARN) - Supported resource-types that are provisioned by Amazon Web Services services, such as RDS databases, can be identified by their ARN.

    • Domain name - Any domain name that is publicly resolvable.

    • IP address - For IPv4 and IPv6, only IP addresses in the VPC are supported.

    " + "documentation":"

    Identifies the resource configuration in one of the following ways:

    • Amazon Resource Name (ARN) - Supported resource-types that are provisioned by Amazon Web Services services, such as RDS databases, can be identified by their ARN.

    • Domain name - Any domain name that is publicly resolvable.

    • IP address - For IPv4 and IPv6, only IP addresses in the VPC are supported.

    • CIDR range - For a resource configuration of type CIDR, specify a cidrResource with one or more cidrRanges (for example, 10.0.0.0/16) that cover the IP addresses of the resources you want to make accessible. You can specify up to 10 ranges, using IPv4, IPv6, or both, and each range must include a prefix length. To represent your entire network, specify 0.0.0.0/0 (IPv4) or ::/0 (IPv6) as the only range. You can't use reserved ranges such as 169.254.0.0/16, 100.64.0.0/10, 224.0.0.0/4, fe80::/10, or ff00::/8.

    " }, "allowAssociationToShareableServiceNetwork":{ "shape":"Boolean", @@ -1872,7 +1893,7 @@ }, "type":{ "shape":"ResourceConfigurationType", - "documentation":"

    The type of resource configuration. A resource configuration can be one of the following types:

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    " + "documentation":"

    The type of resource configuration. A resource configuration can be one of the following types:

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    • CIDR - A network segment, expressed as a range of IP addresses (a CIDR block). A consumer accesses the resources within the CIDR range through a Tunnel VPC endpoint. A CIDR resource configuration must be associated with a resource gateway whose DNS resolution is set to IN_VPC.

    " }, "portRanges":{ "shape":"PortRangeList", @@ -1955,7 +1976,7 @@ }, "resourceConfigDnsResolution":{ "shape":"ResourceConfigDnsResolution", - "documentation":"

    Indicates how DNS is resolved for resource configurations associated to this resource gateway. ResourceConfigDnsResolution is set at creation time and cannot be changed.

    • IN_VPC - DNS resolution occurs privately within the resource gateway's VPC. DNS queries for resources behind this resource gateway resolve using the DNS resolvers defined in the VPC's DHCP option sets. Use this when your resource domain names are hosted in private Route 53 hosted zones or on-premises DNS servers reachable from the VPC.

    • PUBLIC - DNS resolution occurs against public DNS resolvers. DNS queries for resources behind this resource gateway resolve using standard public DNS. Use this when your resource domain names are publicly resolvable.

    " + "documentation":"

    Indicates how DNS is resolved for resource configurations associated with this resource gateway. This value is set when you create the resource gateway and can't be changed afterward. The default is PUBLIC.

    • IN_VPC - DNS resolution occurs privately within the resource gateway's VPC. DNS queries for resources behind this resource gateway resolve using the DNS resolvers defined in the VPC's DHCP option sets. Use this when your resource domain names are hosted in private Route 53 hosted zones or on-premises DNS servers reachable from the VPC. A CIDR resource configuration requires a resource gateway that uses IN_VPC, and an IN_VPC resource gateway can't be used for ARN resource configurations, so a single resource gateway can't serve both ARN and CIDR resource configurations.

    • PUBLIC - DNS resolution occurs against public DNS resolvers. DNS queries for resources behind this resource gateway resolve using standard public DNS. Use this when your resource domain names are publicly resolvable.

    " }, "tags":{ "shape":"TagMap", @@ -2268,7 +2289,7 @@ "idempotencyToken":true }, "serviceNetworkIdentifier":{ - "shape":"ServiceNetworkIdentifier", + "shape":"ServiceNetworkIdentifierWithoutRegex", "documentation":"

    The ID or ARN of the service network. You must use an ARN if the resources are in different accounts.

    " }, "vpcIdentifier":{ @@ -3254,7 +3275,7 @@ }, "resourceGatewayId":{ "shape":"ResourceGatewayId", - "documentation":"

    The ID of the resource gateway used to connect to the resource configuration in a given VPC. You can specify the resource gateway identifier only for resource configurations with type SINGLE, GROUP, or ARN.

    " + "documentation":"

    The ID of the resource gateway used to connect to the resource configuration in a given VPC. You can specify the resource gateway identifier only for resource configurations with type SINGLE, GROUP, ARN, or CIDR.

    " }, "resourceConfigurationGroupId":{ "shape":"ResourceConfigurationId", @@ -3262,7 +3283,7 @@ }, "type":{ "shape":"ResourceConfigurationType", - "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    " + "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    • CIDR - A network segment (a range of IP addresses) accessed through a Tunnel VPC endpoint.

    " }, "allowAssociationToShareableServiceNetwork":{ "shape":"Boolean", @@ -3570,7 +3591,7 @@ }, "privateDnsEntry":{ "shape":"DnsEntry", - "documentation":"

    The private DNS entry for the service.

    " + "documentation":"

    The private DNS entry for the service. This entry includes only the domain name.

    " }, "privateDnsEnabled":{ "shape":"Boolean", @@ -4934,6 +4955,37 @@ "documentation":"

    Describes a path match type. Each rule can include only one of the following types of paths.

    ", "union":true }, + "PayerResponsibilityEntry":{ + "type":"structure", + "members":{ + "scope":{ + "shape":"PayerResponsibilityScope", + "documentation":"

    The category of charges that this entry applies to. ResourceGatewayCharges covers the resource gateway's data processing charge.

    " + }, + "payerResponsibilityType":{ + "shape":"PayerResponsibilityPayer", + "documentation":"

    The account that pays this category of charges. VpcEndpointAccount owns the VPC endpoint. ResourceGatewayAccount owns the resource gateway.

    " + } + }, + "documentation":"

    Specifies which account pays for a category of charges on a VPC endpoint association.

    " + }, + "PayerResponsibilityList":{ + "type":"list", + "member":{"shape":"PayerResponsibilityEntry"}, + "max":10, + "min":1 + }, + "PayerResponsibilityPayer":{ + "type":"string", + "enum":[ + "VpcEndpointAccount", + "ResourceGatewayAccount" + ] + }, + "PayerResponsibilityScope":{ + "type":"string", + "enum":["ResourceGatewayCharges"] + }, "PolicyString":{ "type":"string", "max":10000, @@ -4978,7 +5030,10 @@ }, "ProtocolType":{ "type":"string", - "enum":["TCP"] + "enum":[ + "TCP", + "TCP_UDP" + ] }, "PutAuthPolicyRequest":{ "type":"structure", @@ -5106,6 +5161,10 @@ "arnResource":{ "shape":"ArnResource", "documentation":"

    The Amazon Resource Name (ARN) of the resource.

    " + }, + "cidrResource":{ + "shape":"CidrResource", + "documentation":"

    The network segment for a resource configuration of type CIDR, specified as one or more CIDR ranges (cidrRanges). Resources whose IP addresses fall within these ranges are reachable through a Tunnel VPC endpoint.

    " } }, "documentation":"

    Describes a resource configuration.

    ", @@ -5174,7 +5233,7 @@ }, "type":{ "shape":"ResourceConfigurationType", - "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    " + "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources. You must create a group resource configuration before you create a child resource configuration.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    • CIDR - A network segment (a range of IP addresses) accessed through a Tunnel VPC endpoint.

    " }, "status":{ "shape":"ResourceConfigurationStatus", @@ -5217,7 +5276,8 @@ "GROUP", "CHILD", "SINGLE", - "ARN" + "ARN", + "CIDR" ] }, "ResourceEndpointAssociationArn":{ @@ -5280,6 +5340,10 @@ "createdAt":{ "shape":"Timestamp", "documentation":"

    The date and time that the VPC endpoint association was created, in ISO-8601 format.

    " + }, + "payerResponsibility":{ + "shape":"PayerResponsibilityList", + "documentation":"

    Who pays for each category of charges on the VPC endpoint association.

    " } }, "documentation":"

    Summary information about a VPC endpoint association.

    " @@ -5823,7 +5887,7 @@ }, "privateDnsEntry":{ "shape":"DnsEntry", - "documentation":"

    The private DNS entry for the service.

    " + "documentation":"

    The private DNS entry for the service. This entry includes only the domain name.

    " }, "isManagedAssociation":{ "shape":"Boolean", @@ -6750,7 +6814,7 @@ }, "type":{ "shape":"ResourceConfigurationType", - "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    " + "documentation":"

    The type of resource configuration.

    • SINGLE - A single resource.

    • GROUP - A group of resources.

    • CHILD - A single resource that is part of a group resource configuration.

    • ARN - An Amazon Web Services resource.

    • CIDR - A network segment (a range of IP addresses) accessed through a Tunnel VPC endpoint.

    " }, "portRanges":{ "shape":"PortRangeList", @@ -6948,10 +7012,7 @@ }, "UpdateServiceNetworkVpcAssociationRequest":{ "type":"structure", - "required":[ - "serviceNetworkVpcAssociationIdentifier", - "securityGroupIds" - ], + "required":["serviceNetworkVpcAssociationIdentifier"], "members":{ "serviceNetworkVpcAssociationIdentifier":{ "shape":"ServiceNetworkVpcAssociationIdentifier", @@ -6962,6 +7023,14 @@ "securityGroupIds":{ "shape":"UpdateServiceNetworkVpcAssociationRequestSecurityGroupIdsList", "documentation":"

    The IDs of the security groups.

    " + }, + "privateDnsEnabled":{ + "shape":"Boolean", + "documentation":"

    Indicates if private DNS is enabled for the VPC association.

    " + }, + "dnsOptions":{ + "shape":"DnsOptions", + "documentation":"

    DNS options for the service network VPC association.

    " } } }, @@ -6993,6 +7062,14 @@ "securityGroupIds":{ "shape":"SecurityGroupList", "documentation":"

    The IDs of the security groups.

    " + }, + "privateDnsEnabled":{ + "shape":"Boolean", + "documentation":"

    Indicates if private DNS is enabled for the VPC association.

    " + }, + "dnsOptions":{ + "shape":"DnsOptions", + "documentation":"

    DNS options for the service network VPC association.

    " } } }, diff --git a/services/waf/pom.xml b/services/waf/pom.xml index 2e6db5d29f1c..31cfaafc8ea1 100644 --- a/services/waf/pom.xml +++ b/services/waf/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT waf AWS Java SDK :: Services :: AWS WAF diff --git a/services/waf/src/it/java/software/amazon/awssdk/services/waf/WafIntegrationTest.java b/services/waf/src/it/java/software/amazon/awssdk/services/waf/WafIntegrationTest.java deleted file mode 100644 index fcf279ecfc9b..000000000000 --- a/services/waf/src/it/java/software/amazon/awssdk/services/waf/WafIntegrationTest.java +++ /dev/null @@ -1,172 +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.waf; - -import java.io.IOException; -import java.time.Duration; -import java.util.List; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import software.amazon.awssdk.core.retry.backoff.FixedDelayBackoffStrategy; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.waf.model.ChangeAction; -import software.amazon.awssdk.services.waf.model.CreateIpSetRequest; -import software.amazon.awssdk.services.waf.model.CreateIpSetResponse; -import software.amazon.awssdk.services.waf.model.GetChangeTokenRequest; -import software.amazon.awssdk.services.waf.model.GetChangeTokenResponse; -import software.amazon.awssdk.services.waf.model.GetIpSetRequest; -import software.amazon.awssdk.services.waf.model.GetIpSetResponse; -import software.amazon.awssdk.services.waf.model.IPSet; -import software.amazon.awssdk.services.waf.model.IPSetDescriptor; -import software.amazon.awssdk.services.waf.model.IPSetDescriptorType; -import software.amazon.awssdk.services.waf.model.IPSetUpdate; -import software.amazon.awssdk.services.waf.model.ListIpSetsRequest; -import software.amazon.awssdk.services.waf.model.ListIpSetsResponse; -import software.amazon.awssdk.services.waf.model.UpdateIpSetRequest; -import software.amazon.awssdk.services.waf.model.WafNonEmptyEntityException; -import software.amazon.awssdk.testutils.Waiter; -import software.amazon.awssdk.testutils.service.AwsTestBase; - -public class WafIntegrationTest extends AwsTestBase { - - private static final String IP_SET_NAME = "java-sdk-ipset-" + System.currentTimeMillis(); - private static final String IP_ADDRESS_RANGE = "192.0.2.0/24"; - private static WafClient client = null; - private static String ipSetId = null; - - @BeforeClass - public static void setup() throws IOException { - FixedDelayBackoffStrategy fixedBackoffStrategy = FixedDelayBackoffStrategy.create(Duration.ofSeconds(30)); - setUpCredentials(); - client = WafClient.builder() - .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) - .region(Region.AWS_GLOBAL) - .overrideConfiguration(cfg -> cfg.retryPolicy(r -> r.backoffStrategy(fixedBackoffStrategy))) - .build(); - } - - @AfterClass - public static void tearDown() throws IOException { - if (client != null) { - - deleteIpSet(); - } - } - - private static void deleteIpSet() { - if (ipSetId != null) { - Waiter.run(() -> client.deleteIPSet(r -> r.ipSetId(ipSetId).changeToken(newChangeToken()))) - .ignoringException(WafNonEmptyEntityException.class) - .orFailAfter(Duration.ofMinutes(2)); - } - } - - private static String newChangeToken() { - - GetChangeTokenResponse result = client.getChangeToken(GetChangeTokenRequest.builder().build()); - return result.changeToken(); - - } - - @Test - public void testOperations() throws InterruptedException { - - ipSetId = testCreateIpSet(); - testGetIpSet(); - testUpdateIpSet(); - } - - private String testCreateIpSet() { - final String changeToken = newChangeToken(); - CreateIpSetResponse createResult = client.createIPSet(CreateIpSetRequest.builder() - .changeToken(changeToken) - .name(IP_SET_NAME).build()); - - Assert.assertEquals(changeToken, createResult.changeToken()); - - final IPSet ipSet = createResult.ipSet(); - Assert.assertNotNull(ipSet); - Assert.assertEquals(IP_SET_NAME, ipSet.name()); - Assert.assertTrue(ipSet.ipSetDescriptors().isEmpty()); - Assert.assertNotNull(ipSet.ipSetId()); - - return ipSet.ipSetId(); - } - - private void testGetIpSet() { - GetIpSetResponse getResult = client.getIPSet(GetIpSetRequest.builder() - .ipSetId(ipSetId) - .build()); - IPSet ipSet = getResult.ipSet(); - Assert.assertNotNull(ipSet); - Assert.assertEquals(IP_SET_NAME, ipSet.name()); - Assert.assertTrue(ipSet.ipSetDescriptors().isEmpty()); - Assert.assertNotNull(ipSet.ipSetId()); - Assert.assertEquals(ipSetId, ipSet.ipSetId()); - - ListIpSetsResponse listResult = client.listIPSets(ListIpSetsRequest.builder() - .limit(1) - .build()); - Assert.assertNotNull(listResult.ipSets()); - Assert.assertFalse(listResult.ipSets().isEmpty()); - } - - private void testUpdateIpSet() { - final IPSetDescriptor ipSetDescriptor = IPSetDescriptor.builder() - .type(IPSetDescriptorType.IPV4) - .value(IP_ADDRESS_RANGE) - .build(); - final IPSetUpdate ipToInsert = IPSetUpdate.builder() - .ipSetDescriptor(ipSetDescriptor) - .action(ChangeAction.INSERT) - .build(); - - - client.updateIPSet(UpdateIpSetRequest.builder() - .ipSetId(ipSetId) - .changeToken(newChangeToken()) - .updates(ipToInsert).build()); - GetIpSetResponse getResult = client.getIPSet(GetIpSetRequest.builder() - .ipSetId(ipSetId).build()); - - IPSet ipSet = getResult.ipSet(); - Assert.assertNotNull(ipSet); - Assert.assertEquals(IP_SET_NAME, ipSet.name()); - Assert.assertNotNull(ipSet.ipSetId()); - Assert.assertEquals(ipSetId, ipSet.ipSetId()); - - List actualList = ipSet.ipSetDescriptors(); - - Assert.assertFalse(actualList.isEmpty()); - Assert.assertEquals(1, actualList.size()); - IPSetDescriptor actualIpSetDescriptor = actualList.get(0); - Assert.assertEquals(ipSetDescriptor.type(), actualIpSetDescriptor.type()); - Assert.assertEquals(ipSetDescriptor.value(), actualIpSetDescriptor.value()); - - final IPSetUpdate ipToDelete = IPSetUpdate.builder() - .ipSetDescriptor(ipSetDescriptor) - .action(ChangeAction.DELETE) - .build(); - - client.updateIPSet(UpdateIpSetRequest.builder() - .ipSetId(ipSetId) - .changeToken(newChangeToken()) - .updates(ipToDelete) - .build()); - } -} diff --git a/services/waf/src/main/resources/codegen-resources/customization.config b/services/waf/src/main/resources/codegen-resources/customization.config index c2457f7c37ab..0db3279e44b0 100644 --- a/services/waf/src/main/resources/codegen-resources/customization.config +++ b/services/waf/src/main/resources/codegen-resources/customization.config @@ -1,5 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true - } diff --git a/services/waf/src/main/resources/codegen-resources/waf/endpoint-bdd-1.json b/services/waf/src/main/resources/codegen-resources/waf/endpoint-bdd-1.json new file mode 100644 index 000000000000..d4dda5c40bfe --- /dev/null +++ b/services/waf/src/main/resources/codegen-resources/waf/endpoint-bdd-1.json @@ -0,0 +1,237 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws" + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "waf", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-fips.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingName": "waf", + "signingRegion": "us-east-1" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 15, + "nodes": "/////wAAAAH/////AAAAAAAAAA4AAAADAAAAAQAAAAQF9eENAAAAAgAAAAUF9eENAAAAAwAAAAkAAAAGAAAABAAAAAgAAAAHAAAABgX14QQF9eEMAAAABQX14QoF9eELAAAABAAAAAwAAAAKAAAABgX14QUAAAALAAAABwX14QgF9eEJAAAABQAAAA0F9eEHAAAABwX14QYF9eEHAAAAAwX14QEAAAAPAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/waf/src/main/resources/codegen-resources/waf/endpoint-rule-set.json b/services/waf/src/main/resources/codegen-resources/waf/endpoint-rule-set.json deleted file mode 100644 index b33167fa755d..000000000000 --- a/services/waf/src/main/resources/codegen-resources/waf/endpoint-rule-set.json +++ /dev/null @@ -1,416 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - false - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://waf.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "waf", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "stringEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "name" - ] - }, - "aws" - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - false - ] - } - ], - "endpoint": { - "url": "https://waf-fips.amazonaws.com", - "properties": { - "authSchemes": [ - { - "name": "sigv4", - "signingName": "waf", - "signingRegion": "us-east-1" - } - ] - }, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://waf.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-bdd-1.json b/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-bdd-1.json new file mode 100644 index 000000000000..cbdfe8d215f7 --- /dev/null +++ b/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-regional-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-regional-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-regional.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://waf-regional.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-rule-set.json b/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-rule-set.json deleted file mode 100644 index 4277245ea475..000000000000 --- a/services/waf/src/main/resources/codegen-resources/wafregional/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf-regional-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf-regional-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://waf-regional.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://waf-regional.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/wafv2/pom.xml b/services/wafv2/pom.xml index bbba60dfd2bf..908a99cec9af 100644 --- a/services/wafv2/pom.xml +++ b/services/wafv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT wafv2 AWS Java SDK :: Services :: WAFV2 diff --git a/services/wafv2/src/main/resources/codegen-resources/customization.config b/services/wafv2/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/wafv2/src/main/resources/codegen-resources/customization.config +++ b/services/wafv2/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/wafv2/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/wafv2/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..b17fec5d5b02 --- /dev/null +++ b/services/wafv2/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wafv2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wafv2-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wafv2.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wafv2.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/wafv2/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/wafv2/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 359579ae5ee3..000000000000 --- a/services/wafv2/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wafv2-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wafv2-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wafv2.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://wafv2.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/wafv2/src/main/resources/codegen-resources/service-2.json b/services/wafv2/src/main/resources/codegen-resources/service-2.json index 011e4eb8ac3c..a3299475f8e2 100644 --- a/services/wafv2/src/main/resources/codegen-resources/service-2.json +++ b/services/wafv2/src/main/resources/codegen-resources/service-2.json @@ -158,7 +158,7 @@ {"shape":"WAFConfigurationWarningException"}, {"shape":"WAFExpiredManagedRuleGroupVersionException"} ], - "documentation":"

    Creates a WebACL per the specifications provided.

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, and Amazon Web Services Verified Access instance.

    " + "documentation":"

    Creates a WebACL per the specifications provided.

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, Amazon Web Services Verified Access instance, and Amazon Bedrock AgentCore Gateway.

    " }, "DeleteAPIKey":{ "name":"DeleteAPIKey", @@ -1037,7 +1037,7 @@ {"shape":"WAFConfigurationWarningException"}, {"shape":"WAFFeatureNotIncludedInPricingPlanException"} ], - "documentation":"

    Updates the specified WebACL. While updating a web ACL, WAF provides continuous coverage to the resources that you have associated with the web ACL.

    This operation completely replaces the mutable specifications that you already have for the web ACL with the ones that you provide to this call.

    To modify a web ACL, do the following:

    1. Retrieve it by calling GetWebACL

    2. Update its settings as needed

    3. Provide the complete web ACL specification to this call

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, and Amazon Web Services Verified Access instance.

    Temporary inconsistencies during updates

    When you create or change a web ACL or other WAF resources, the changes take a small amount of time to propagate to all areas where the resources are stored. The propagation time can be from a few seconds to a number of minutes.

    The following are examples of the temporary inconsistencies that you might notice during change propagation:

    • After you create a web ACL, if you try to associate it with a resource, you might get an exception indicating that the web ACL is unavailable.

    • After you add a rule group to a web ACL, the new rule group rules might be in effect in one area where the web ACL is used and not in another.

    • After you change a rule action setting, you might see the old action in some places and the new action in others.

    • After you add an IP address to an IP set that is in use in a blocking rule, the new address might be blocked in one area while still allowed in another.

    " + "documentation":"

    Updates the specified WebACL. While updating a web ACL, WAF provides continuous coverage to the resources that you have associated with the web ACL.

    This operation completely replaces the mutable specifications that you already have for the web ACL with the ones that you provide to this call.

    To modify a web ACL, do the following:

    1. Retrieve it by calling GetWebACL

    2. Update its settings as needed

    3. Provide the complete web ACL specification to this call

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, Amazon Web Services Verified Access instance, and Amazon Bedrock AgentCore Gateway.

    Temporary inconsistencies during updates

    When you create or change a web ACL or other WAF resources, the changes take a small amount of time to propagate to all areas where the resources are stored. The propagation time can be from a few seconds to a number of minutes.

    The following are examples of the temporary inconsistencies that you might notice during change propagation:

    • After you create a web ACL, if you try to associate it with a resource, you might get an exception indicating that the web ACL is unavailable.

    • After you add a rule group to a web ACL, the new rule group rules might be in effect in one area where the web ACL is used and not in another.

    • After you change a rule action setting, you might see the old action in some places and the new action in others.

    • After you add an IP address to an IP set that is in use in a blocking rule, the new address might be blocked in one area while still allowed in another.

    " } }, "shapes":{ @@ -1437,6 +1437,10 @@ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " + }, "PositionalConstraint":{ "shape":"PositionalConstraint", "documentation":"

    The area within the portion of the web request that you want WAF to search for SearchString. Valid values include the following:

    CONTAINS

    The specified part of the web request must include the value of SearchString, but the location doesn't matter.

    CONTAINS_WORD

    The specified part of the web request must include the value of SearchString, and SearchString must contain only alphanumeric characters or underscore (A-Z, a-z, 0-9, or _). In addition, SearchString must be a word, which means that both of the following are true:

    • SearchString is at the beginning of the specified part of the web request or is preceded by a character other than an alphanumeric character or underscore (_). Examples include the value of a header and ;BadBot.

    • SearchString is at the end of the specified part of the web request or is followed by a character other than an alphanumeric character or underscore (_), for example, BadBot; and -BadBot;.

    EXACTLY

    The value of the specified part of the web request must exactly match the value of SearchString.

    STARTS_WITH

    The value of SearchString must appear at the beginning of the specified part of the web request.

    ENDS_WITH

    The value of SearchString must appear at the end of the specified part of the web request.

    " @@ -2909,7 +2913,7 @@ }, "FieldKeys":{ "shape":"FieldToProtectKeys", - "documentation":"

    Specifies the keys to protect for the specified field type. If you don't specify any key, then all keys for the field type are protected.

    " + "documentation":"

    Specifies the keys to protect for the specified field type.

    Required for SINGLE_HEADER, SINGLE_COOKIE, and SINGLE_QUERY_ARGUMENT: provide a non-empty array naming the specific headers, cookies, or query arguments to protect. There is no option to protect all keys of these field types, so enumerate each key you intend to protect.

    Must be omitted for QUERY_STRING and BODY: the entire component is protected and these field types take no keys. Supplying FieldKeys for them is rejected.

    " } }, "documentation":"

    Specifies a field type and keys to protect in stored web request data. This is part of the data protection configuration for a web ACL.

    " @@ -5282,7 +5286,8 @@ "MONETIZATION_CONFIG", "WALLET_ADDRESS", "PRICE_AMOUNT", - "PAYMENT_NETWORK" + "PAYMENT_NETWORK", + "PRE_PARSE_TEXT_TRANSFORMATION" ] }, "ParameterExceptionParameter":{ @@ -5425,6 +5430,42 @@ "CONTAINS_WORD" ] }, + "PreParseTextTransformation":{ + "type":"structure", + "required":[ + "Priority", + "Type" + ], + "members":{ + "Priority":{ + "shape":"PreParseTextTransformationPriority", + "documentation":"

    Sets the relative processing order for the pre-parse text transformations that you define. WAF processes all transformations, from lowest priority value to highest, before inspecting the transformed content.

    " + }, + "Type":{ + "shape":"PreParseTextTransformationType", + "documentation":"

    The type of pre-parse text transformation to apply to the raw query string.

    " + } + }, + "documentation":"

    A pre-parse text transformation that normalizes the raw query string before WAF parses it into individual query arguments. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments.

    " + }, + "PreParseTextTransformationPriority":{ + "type":"integer", + "min":0 + }, + "PreParseTextTransformationType":{ + "type":"string", + "enum":[ + "NONE", + "URL_DECODE", + "URL_DECODE_UNI", + "COMBINE_DUPLICATE_QUERY_ARGS_BY_COMMA", + "REPLACE_SEMICOLONS_WITH_AMPERSANDS" + ] + }, + "PreParseTextTransformations":{ + "type":"list", + "member":{"shape":"PreParseTextTransformation"} + }, "Price":{ "type":"structure", "required":[ @@ -5858,7 +5899,7 @@ "members":{ "RegexString":{ "shape":"RegexPatternString", - "documentation":"

    The string representing the regular expression.

    " + "documentation":"

    The string representing the regular expression. WAF enforces a quota on the maximum number of characters in a regex pattern. For the current limit, see WAF quotas in the WAF Developer Guide.

    " } }, "documentation":"

    A single regular expression. This is used in a RegexPatternSet and also in the configuration for the Amazon Web Services Managed Rules rule group AWSManagedRulesAntiDDoSRuleSet.

    " @@ -5873,7 +5914,7 @@ "members":{ "RegexString":{ "shape":"RegexPatternString", - "documentation":"

    The string representing the regular expression.

    " + "documentation":"

    The string representing the regular expression. WAF enforces a quota on the maximum number of characters in a regex pattern. For the current limit, see WAF quotas in the WAF Developer Guide.

    " }, "FieldToMatch":{ "shape":"FieldToMatch", @@ -5882,6 +5923,10 @@ "TextTransformations":{ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " + }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " } }, "documentation":"

    A rule statement used to search web request components for a match against a single regular expression.

    " @@ -5931,6 +5976,10 @@ "TextTransformations":{ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " + }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " } }, "documentation":"

    A rule statement used to search web request components for matches with regular expressions. To use this, create a RegexPatternSet that specifies the expressions that you want to detect, then use the ARN of that set in this statement. A web request matches the pattern set rule statement if the request component matches any of the patterns in the set. To create a regex pattern set, see CreateRegexPatternSet.

    Each regex pattern set rule statement references a regex pattern set. You create and maintain the set independent of your rules. This allows you to use the single set in multiple rules. When you update the referenced set, WAF automatically updates all rules that reference it.

    " @@ -6841,6 +6890,10 @@ "TextTransformations":{ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " + }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " } }, "documentation":"

    A rule statement that compares a number of bytes against the size of a request component, using a comparison operator, such as greater than (>) or less than (<). For example, you can use a size constraint statement to look for query strings that are longer than 100 bytes.

    If you configure WAF to inspect the request body, WAF inspects only the number of bytes in the body up to the limit for the web ACL and protected resource type. If you know that the request body for your web requests should never exceed the inspection limit, you can use a size constraint statement to block requests that have a larger request body size. For more information about the inspection limits, see Body and JsonBody settings for the FieldToMatch data type.

    If you choose URI for the value of Part of the request to filter on, the slash (/) in the URI counts as one character. For example, the URI /logo.jpg is nine characters long.

    " @@ -6930,6 +6983,10 @@ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " + }, "SensitivityLevel":{ "shape":"SensitivityLevel", "documentation":"

    The sensitivity that you want WAF to use to inspect for SQL injection attacks.

    HIGH detects more attacks, but might generate more false positives, especially if your web requests frequently contain unusual strings. For information about identifying and mitigating false positives, see Testing and tuning in the WAF Developer Guide.

    LOW is generally a better choice for resources that already have other protections against SQL injection attacks or that have a low tolerance for false positives.

    Default: LOW

    " @@ -7143,7 +7200,17 @@ "REPLACE_NULLS", "BASE64_DECODE_EXT", "URL_DECODE_UNI", - "UTF8_TO_UNICODE" + "UTF8_TO_UNICODE", + "REMOVE_WHITESPACE", + "TRIM", + "TRIM_LEFT", + "TRIM_RIGHT", + "REMOVE_COMMENTS_CHAR", + "UPPERCASE", + "CMD_LINE_WIN", + "CMD_LINE_UNIX", + "JS_DECODE_EXT", + "SHA256" ] }, "TextTransformations":{ @@ -7890,7 +7957,7 @@ "documentation":"

    The monetization configuration for the web ACL. Required when any rule in the web ACL uses the Monetize action. Specifies the cryptocurrency payment networks and currency mode for AI bot monetization.

    " } }, - "documentation":"

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, and Amazon Web Services Verified Access instance.

    " + "documentation":"

    A web ACL defines a collection of rules to use to inspect and control web requests. Each rule has a statement that defines what to look for in web requests and an action that WAF applies to requests that match the statement. In the web ACL, you assign a default action to take (allow, block) for any request that does not match any of the rules. The rules in a web ACL can be a combination of the types Rule, RuleGroup, and managed rule group. You can associate a web ACL with one or more Amazon Web Services resources to protect. The resource types include Amazon CloudFront distribution, Amazon API Gateway REST API, Application Load Balancer, AppSync GraphQL API, Amazon Cognito user pool, App Runner service, Amplify application, Amazon Web Services Verified Access instance, and Amazon Bedrock AgentCore Gateway.

    " }, "WebACLSummaries":{ "type":"list", @@ -7936,6 +8003,10 @@ "TextTransformations":{ "shape":"TextTransformations", "documentation":"

    Text transformations eliminate some of the unusual formatting that attackers use in web requests in an effort to bypass detection. Text transformations are used in rule match statements, to transform the FieldToMatch request component before inspecting it, and they're used in rate-based rule statements, to transform request components before using them as custom aggregation keys. If you specify one or more transformations to apply, WAF performs all transformations on the specified content, starting from the lowest priority setting, and then uses the transformed component contents.

    " + }, + "PreParseTextTransformations":{ + "shape":"PreParseTextTransformations", + "documentation":"

    Pre-parse text transformations normalize the raw query string before WAF parses it into individual query arguments. They are applied before the standard text transformations. Pre-parse text transformations are only supported when FieldToMatch is SingleQueryArgument or AllQueryArguments. You can specify up to 10 pre-parse text transformations per rule statement.

    " } }, "documentation":"

    A rule statement that inspects for cross-site scripting (XSS) attacks. In XSS attacks, the attacker uses vulnerabilities in a benign website as a vehicle to inject malicious client-site scripts into other legitimate web browsers.

    " diff --git a/services/wellarchitected/pom.xml b/services/wellarchitected/pom.xml index b237c7539255..309b4a401358 100644 --- a/services/wellarchitected/pom.xml +++ b/services/wellarchitected/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT wellarchitected AWS Java SDK :: Services :: Well Architected diff --git a/services/wellarchitected/src/main/resources/codegen-resources/customization.config b/services/wellarchitected/src/main/resources/codegen-resources/customization.config index d7ed49e2a984..c07d1f98a7e6 100644 --- a/services/wellarchitected/src/main/resources/codegen-resources/customization.config +++ b/services/wellarchitected/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "customServiceMetadata": { "contentType": "application/json" - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/wellarchitected/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/wellarchitected/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..ff3fb18e197c --- /dev/null +++ b/services/wellarchitected/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wellarchitected-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wellarchitected-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wellarchitected.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wellarchitected.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/wellarchitected/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/wellarchitected/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index c2e7ac501b81..000000000000 --- a/services/wellarchitected/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wellarchitected-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wellarchitected-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wellarchitected.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://wellarchitected.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/wellarchitected/src/main/resources/codegen-resources/paginators-1.json b/services/wellarchitected/src/main/resources/codegen-resources/paginators-1.json index 0238510fd735..7b979c5e61be 100644 --- a/services/wellarchitected/src/main/resources/codegen-resources/paginators-1.json +++ b/services/wellarchitected/src/main/resources/codegen-resources/paginators-1.json @@ -5,6 +5,42 @@ "output_token": "NextToken", "limit_key": "MaxResults" }, + "ListAgentContexts": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAgentGoals": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAgentProfiles": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAgentRecommendationGenerations": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAgentRecommendationItems": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, + "ListAgentRecommendations": { + "input_token": "nextToken", + "output_token": "nextToken", + "limit_key": "maxResults", + "result_key": "items" + }, "ListAnswers": { "input_token": "NextToken", "output_token": "NextToken", diff --git a/services/wellarchitected/src/main/resources/codegen-resources/service-2.json b/services/wellarchitected/src/main/resources/codegen-resources/service-2.json index 07d44a205283..a8124d82edfd 100644 --- a/services/wellarchitected/src/main/resources/codegen-resources/service-2.json +++ b/services/wellarchitected/src/main/resources/codegen-resources/service-2.json @@ -2,8 +2,8 @@ "version":"2.0", "metadata":{ "apiVersion":"2020-03-31", + "auth":["aws.auth#sigv4"], "endpointPrefix":"wellarchitected", - "jsonVersion":"1.1", "protocol":"rest-json", "protocols":["rest-json"], "serviceAbbreviation":"Well-Architected", @@ -11,23 +11,23 @@ "serviceId":"WellArchitected", "signatureVersion":"v4", "signingName":"wellarchitected", - "uid":"wellarchitected-2020-03-31", - "auth":["aws.auth#sigv4"] + "uid":"wellarchitected-2020-03-31" }, "operations":{ "AssociateLenses":{ "name":"AssociateLenses", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/associateLenses" + "requestUri":"/workloads/{WorkloadId}/associateLenses", + "responseCode":200 }, "input":{"shape":"AssociateLensesInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Associate a lens to a workload.

    Up to 10 lenses can be associated with a workload in a single API operation. A maximum of 20 lenses can be associated with a workload.

    Disclaimer

    By accessing and/or applying custom lenses created by another Amazon Web Services user or account, you acknowledge that custom lenses created by other users and shared with you are Third Party Content as defined in the Amazon Web Services Customer Agreement.

    " @@ -36,34 +36,98 @@ "name":"AssociateProfiles", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/associateProfiles" + "requestUri":"/workloads/{WorkloadId}/associateProfiles", + "responseCode":200 }, "input":{"shape":"AssociateProfilesInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Associate a profile with a workload.

    " + }, + "CreateAgentContext":{ + "name":"CreateAgentContext", + "http":{ + "method":"POST", + "requestUri":"/api/v1/agent-profiles/{profileArn}/contexts", + "responseCode":200 + }, + "input":{"shape":"CreateAgentContextRequest"}, + "output":{"shape":"CreateAgentContextResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates a context associated with an optimization profile. Contexts provide application and environment information used during recommendation generation.

    ", + "idempotent":true + }, + "CreateAgentGoal":{ + "name":"CreateAgentGoal", + "http":{ + "method":"POST", + "requestUri":"/api/v1/agent-profiles/{profileArn}/goals", + "responseCode":200 + }, + "input":{"shape":"CreateAgentGoalRequest"}, + "output":{"shape":"CreateAgentGoalResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Creates an optimization goal associated with a profile. Goals define specific targets and objectives for the optimization process.

    ", + "idempotent":true + }, + "CreateAgentProfile":{ + "name":"CreateAgentProfile", + "http":{ + "method":"POST", + "requestUri":"/api/v1/agent-profiles", + "responseCode":200 + }, + "input":{"shape":"CreateAgentProfileRequest"}, + "output":{"shape":"CreateAgentProfileResponse"}, + "errors":[ {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Associate a profile with a workload.

    " + "documentation":"

    Creates an optimization profile that defines the scope and configuration for generating recommendations. A profile specifies the execution role, target pillars, and aggregation settings for analyzing your Amazon Web Services resources.

    ", + "idempotent":true }, "CreateLensShare":{ "name":"CreateLensShare", "http":{ "method":"POST", - "requestUri":"/lenses/{LensAlias}/shares" + "requestUri":"/lenses/{LensAlias}/shares", + "responseCode":200 }, "input":{"shape":"CreateLensShareInput"}, "output":{"shape":"CreateLensShareOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a lens share.

    The owner of a lens can share it with other Amazon Web Services accounts, users, an organization, and organizational units (OUs) in the same Amazon Web Services Region. Lenses provided by Amazon Web Services (Amazon Web Services Official Content) cannot be shared.

    Shared access to a lens is not removed until the lens invitation is deleted.

    If you share a lens with an organization or OU, all accounts in the organization or OU are granted access to the lens.

    For more information, see Sharing a custom lens in the Well-Architected Tool User Guide.

    Disclaimer

    By sharing your custom lenses with other Amazon Web Services accounts, you acknowledge that Amazon Web Services will make your custom lenses available to those other accounts. Those other accounts may continue to access and use your shared custom lenses even if you delete the custom lenses from your own Amazon Web Services account or terminate your Amazon Web Services account.

    " @@ -72,17 +136,18 @@ "name":"CreateLensVersion", "http":{ "method":"POST", - "requestUri":"/lenses/{LensAlias}/versions" + "requestUri":"/lenses/{LensAlias}/versions", + "responseCode":200 }, "input":{"shape":"CreateLensVersionInput"}, "output":{"shape":"CreateLensVersionOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ServiceQuotaExceededException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a new lens version.

    A lens can have up to 100 versions.

    Use this operation to publish a new lens version after you have imported a lens. The LensAlias is used to identify the lens to be published. The owner of a lens can share the lens with other Amazon Web Services accounts and users in the same Amazon Web Services Region. Only the owner of a lens can delete it.

    " @@ -91,17 +156,18 @@ "name":"CreateMilestone", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/milestones" + "requestUri":"/workloads/{WorkloadId}/milestones", + "responseCode":200 }, "input":{"shape":"CreateMilestoneInput"}, "output":{"shape":"CreateMilestoneOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a milestone for an existing workload.

    " @@ -110,16 +176,17 @@ "name":"CreateProfile", "http":{ "method":"POST", - "requestUri":"/profiles" + "requestUri":"/profiles", + "responseCode":200 }, "input":{"shape":"CreateProfileInput"}, "output":{"shape":"CreateProfileOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a profile.

    " @@ -128,17 +195,18 @@ "name":"CreateProfileShare", "http":{ "method":"POST", - "requestUri":"/profiles/{ProfileArn}/shares" + "requestUri":"/profiles/{ProfileArn}/shares", + "responseCode":200 }, "input":{"shape":"CreateProfileShareInput"}, "output":{"shape":"CreateProfileShareOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a profile share.

    " @@ -147,16 +215,17 @@ "name":"CreateReviewTemplate", "http":{ "method":"POST", - "requestUri":"/reviewTemplates" + "requestUri":"/reviewTemplates", + "responseCode":200 }, "input":{"shape":"CreateReviewTemplateInput"}, "output":{"shape":"CreateReviewTemplateOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], @@ -166,17 +235,18 @@ "name":"CreateTemplateShare", "http":{ "method":"POST", - "requestUri":"/templates/shares/{TemplateArn}" + "requestUri":"/templates/shares/{TemplateArn}", + "responseCode":200 }, "input":{"shape":"CreateTemplateShareInput"}, "output":{"shape":"CreateTemplateShareOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, + {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Create a review template share.

    The owner of a review template can share it with other Amazon Web Services accounts, users, an organization, and organizational units (OUs) in the same Amazon Web Services Region.

    Shared access to a review template is not removed until the review template share invitation is deleted.

    If you share a review template with an organization or OU, all accounts in the organization or OU are granted access to the review template.

    Disclaimer

    By sharing your review template with other Amazon Web Services accounts, you acknowledge that Amazon Web Services will make your review template available to those other accounts.

    " @@ -185,16 +255,17 @@ "name":"CreateWorkload", "http":{ "method":"POST", - "requestUri":"/workloads" + "requestUri":"/workloads", + "responseCode":200 }, "input":{"shape":"CreateWorkloadInput"}, "output":{"shape":"CreateWorkloadOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, {"shape":"ServiceQuotaExceededException"}, - {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], @@ -204,34 +275,94 @@ "name":"CreateWorkloadShare", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/shares" + "requestUri":"/workloads/{WorkloadId}/shares", + "responseCode":200 }, "input":{"shape":"CreateWorkloadShareInput"}, "output":{"shape":"CreateWorkloadShareOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Create a workload share.

    The owner of a workload can share it with other Amazon Web Services accounts and users in the same Amazon Web Services Region. Shared access to a workload is not removed until the workload invitation is deleted.

    If you share a workload with an organization or OU, all accounts in the organization or OU are granted access to the workload.

    For more information, see Sharing a workload in the Well-Architected Tool User Guide.

    " + }, + "DeleteAgentContext":{ + "name":"DeleteAgentContext", + "http":{ + "method":"DELETE", + "requestUri":"/api/v1/agent-profiles/{profileArn}/contexts/{id}", + "responseCode":200 + }, + "input":{"shape":"DeleteAgentContextRequest"}, + "output":{"shape":"DeleteAgentContextResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes a context associated with a profile.

    ", + "idempotent":true + }, + "DeleteAgentGoal":{ + "name":"DeleteAgentGoal", + "http":{ + "method":"DELETE", + "requestUri":"/api/v1/agent-profiles/{profileArn}/goals/{id}", + "responseCode":200 + }, + "input":{"shape":"DeleteAgentGoalRequest"}, + "output":{"shape":"DeleteAgentGoalResponse"}, + "errors":[ {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Create a workload share.

    The owner of a workload can share it with other Amazon Web Services accounts and users in the same Amazon Web Services Region. Shared access to a workload is not removed until the workload invitation is deleted.

    If you share a workload with an organization or OU, all accounts in the organization or OU are granted access to the workload.

    For more information, see Sharing a workload in the Well-Architected Tool User Guide.

    " + "documentation":"

    Deletes an optimization goal from a profile.

    ", + "idempotent":true + }, + "DeleteAgentProfile":{ + "name":"DeleteAgentProfile", + "http":{ + "method":"DELETE", + "requestUri":"/api/v1/agent-profiles/{profileArn}", + "responseCode":200 + }, + "input":{"shape":"DeleteAgentProfileRequest"}, + "output":{"shape":"DeleteAgentProfileResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Deletes an optimization profile and its associated configuration. This action cannot be undone.

    ", + "idempotent":true }, "DeleteLens":{ "name":"DeleteLens", "http":{ "method":"DELETE", - "requestUri":"/lenses/{LensAlias}" + "requestUri":"/lenses/{LensAlias}", + "responseCode":200 }, "input":{"shape":"DeleteLensInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete an existing lens.

    Only the owner of a lens can delete it. After the lens is deleted, Amazon Web Services accounts and users that you shared the lens with can continue to use it, but they will no longer be able to apply it to new workloads.

    Disclaimer

    By sharing your custom lenses with other Amazon Web Services accounts, you acknowledge that Amazon Web Services will make your custom lenses available to those other accounts. Those other accounts may continue to access and use your shared custom lenses even if you delete the custom lenses from your own Amazon Web Services account or terminate your Amazon Web Services account.

    " @@ -240,15 +371,16 @@ "name":"DeleteLensShare", "http":{ "method":"DELETE", - "requestUri":"/lenses/{LensAlias}/shares/{ShareId}" + "requestUri":"/lenses/{LensAlias}/shares/{ShareId}", + "responseCode":200 }, "input":{"shape":"DeleteLensShareInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a lens share.

    After the lens share is deleted, Amazon Web Services accounts, users, organizations, and organizational units (OUs) that you shared the lens with can continue to use it, but they will no longer be able to apply it to new workloads.

    Disclaimer

    By sharing your custom lenses with other Amazon Web Services accounts, you acknowledge that Amazon Web Services will make your custom lenses available to those other accounts. Those other accounts may continue to access and use your shared custom lenses even if you delete the custom lenses from your own Amazon Web Services account or terminate your Amazon Web Services account.

    " @@ -257,15 +389,16 @@ "name":"DeleteProfile", "http":{ "method":"DELETE", - "requestUri":"/profiles/{ProfileArn}" + "requestUri":"/profiles/{ProfileArn}", + "responseCode":200 }, "input":{"shape":"DeleteProfileInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a profile.

    Disclaimer

    By sharing your profile with other Amazon Web Services accounts, you acknowledge that Amazon Web Services will make your profile available to those other accounts. Those other accounts may continue to access and use your shared profile even if you delete the profile from your own Amazon Web Services account or terminate your Amazon Web Services account.

    " @@ -274,15 +407,16 @@ "name":"DeleteProfileShare", "http":{ "method":"DELETE", - "requestUri":"/profiles/{ProfileArn}/shares/{ShareId}" + "requestUri":"/profiles/{ProfileArn}/shares/{ShareId}", + "responseCode":200 }, "input":{"shape":"DeleteProfileShareInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a profile share.

    " @@ -291,15 +425,16 @@ "name":"DeleteReviewTemplate", "http":{ "method":"DELETE", - "requestUri":"/reviewTemplates/{TemplateArn}" + "requestUri":"/reviewTemplates/{TemplateArn}", + "responseCode":200 }, "input":{"shape":"DeleteReviewTemplateInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a review template.

    Only the owner of a review template can delete it.

    After the review template is deleted, Amazon Web Services accounts, users, organizations, and organizational units (OUs) that you shared the review template with will no longer be able to apply it to new workloads.

    " @@ -308,15 +443,16 @@ "name":"DeleteTemplateShare", "http":{ "method":"DELETE", - "requestUri":"/templates/shares/{TemplateArn}/{ShareId}" + "requestUri":"/templates/shares/{TemplateArn}/{ShareId}", + "responseCode":200 }, "input":{"shape":"DeleteTemplateShareInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a review template share.

    After the review template share is deleted, Amazon Web Services accounts, users, organizations, and organizational units (OUs) that you shared the review template with will no longer be able to apply it to new workloads.

    " @@ -325,15 +461,16 @@ "name":"DeleteWorkload", "http":{ "method":"DELETE", - "requestUri":"/workloads/{WorkloadId}" + "requestUri":"/workloads/{WorkloadId}", + "responseCode":200 }, "input":{"shape":"DeleteWorkloadInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete an existing workload.

    " @@ -342,15 +479,16 @@ "name":"DeleteWorkloadShare", "http":{ "method":"DELETE", - "requestUri":"/workloads/{WorkloadId}/shares/{ShareId}" + "requestUri":"/workloads/{WorkloadId}/shares/{ShareId}", + "responseCode":200 }, "input":{"shape":"DeleteWorkloadShareInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Delete a workload share.

    " @@ -359,15 +497,16 @@ "name":"DisassociateLenses", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/disassociateLenses" + "requestUri":"/workloads/{WorkloadId}/disassociateLenses", + "responseCode":200 }, "input":{"shape":"DisassociateLensesInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Disassociate a lens from a workload.

    Up to 10 lenses can be disassociated from a workload in a single API operation.

    The Amazon Web Services Well-Architected Framework lens (wellarchitected) cannot be removed from a workload.

    " @@ -376,15 +515,16 @@ "name":"DisassociateProfiles", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/disassociateProfiles" + "requestUri":"/workloads/{WorkloadId}/disassociateProfiles", + "responseCode":200 }, "input":{"shape":"DisassociateProfilesInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Disassociate a profile from a workload.

    " @@ -393,32 +533,129 @@ "name":"ExportLens", "http":{ "method":"GET", - "requestUri":"/lenses/{LensAlias}/export" + "requestUri":"/lenses/{LensAlias}/export", + "responseCode":200 }, "input":{"shape":"ExportLensInput"}, "output":{"shape":"ExportLensOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Export an existing lens.

    Only the owner of a lens can export it. Lenses provided by Amazon Web Services (Amazon Web Services Official Content) cannot be exported.

    Lenses are defined in JSON. For more information, see JSON format specification in the Well-Architected Tool User Guide.

    Disclaimer

    Do not include or gather personal identifiable information (PII) of end users or other identifiable individuals in or via your custom lenses. If your custom lens or those shared with you and used in your account do include or collect PII you are responsible for: ensuring that the included PII is processed in accordance with applicable law, providing adequate privacy notices, and obtaining necessary consents for processing such data.

    " + }, + "GetAgentContext":{ + "name":"GetAgentContext", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/contexts/{id}", + "responseCode":200 + }, + "input":{"shape":"GetAgentContextRequest"}, + "output":{"shape":"GetAgentContextResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific context associated with a profile.

    ", + "readonly":true + }, + "GetAgentGoal":{ + "name":"GetAgentGoal", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/goals/{id}", + "responseCode":200 + }, + "input":{"shape":"GetAgentGoalRequest"}, + "output":{"shape":"GetAgentGoalResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific optimization goal.

    ", + "readonly":true + }, + "GetAgentProfile":{ + "name":"GetAgentProfile", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}", + "responseCode":200 + }, + "input":{"shape":"GetAgentProfileRequest"}, + "output":{"shape":"GetAgentProfileResponse"}, + "errors":[ {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Export an existing lens.

    Only the owner of a lens can export it. Lenses provided by Amazon Web Services (Amazon Web Services Official Content) cannot be exported.

    Lenses are defined in JSON. For more information, see JSON format specification in the Well-Architected Tool User Guide.

    Disclaimer

    Do not include or gather personal identifiable information (PII) of end users or other identifiable individuals in or via your custom lenses. If your custom lens or those shared with you and used in your account do include or collect PII you are responsible for: ensuring that the included PII is processed in accordance with applicable law, providing adequate privacy notices, and obtaining necessary consents for processing such data.

    " + "documentation":"

    Retrieves detailed information about an optimization profile, including its configuration and metadata.

    ", + "readonly":true + }, + "GetAgentRecommendation":{ + "name":"GetAgentRecommendation", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-recommendations/{recommendationArn}", + "responseCode":200 + }, + "input":{"shape":"GetAgentRecommendationRequest"}, + "output":{"shape":"GetAgentRecommendationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves detailed information about a specific optimization recommendation, including its impact analysis, content, and implementation guidance.

    ", + "readonly":true + }, + "GetAgentRecommendationGeneration":{ + "name":"GetAgentRecommendationGeneration", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/generations/{generationId}", + "responseCode":200 + }, + "input":{"shape":"GetAgentRecommendationGenerationRequest"}, + "output":{"shape":"GetAgentRecommendationGenerationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Retrieves information about a recommendation generation process, including its status, progress, and results. Recommendation generation is asynchronous: poll this operation until status reaches a terminal value of COMPLETED (results are ready) or ERROR (see errorDetails). Intermediate values are QUEUED and IN_PROGRESS.

    ", + "readonly":true }, "GetAnswer":{ "name":"GetAnswer", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers/{QuestionId}" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers/{QuestionId}", + "responseCode":200 }, "input":{"shape":"GetAnswerInput"}, "output":{"shape":"GetAnswerOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get the answer to a specific question in a workload review.

    " @@ -427,16 +664,17 @@ "name":"GetConsolidatedReport", "http":{ "method":"GET", - "requestUri":"/consolidatedReport" + "requestUri":"/consolidatedReport", + "responseCode":200 }, "input":{"shape":"GetConsolidatedReportInput"}, "output":{"shape":"GetConsolidatedReportOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, - {"shape":"ThrottlingException"}, - {"shape":"ConflictException"} + {"shape":"ConflictException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Get a consolidated report of your workloads.

    You can optionally choose to include workloads that have been shared with you.

    " }, @@ -444,13 +682,14 @@ "name":"GetGlobalSettings", "http":{ "method":"GET", - "requestUri":"/global-settings" + "requestUri":"/global-settings", + "responseCode":200 }, "output":{"shape":"GetGlobalSettingsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Global settings for all workloads.

    " @@ -459,15 +698,16 @@ "name":"GetLens", "http":{ "method":"GET", - "requestUri":"/lenses/{LensAlias}" + "requestUri":"/lenses/{LensAlias}", + "responseCode":200 }, "input":{"shape":"GetLensInput"}, "output":{"shape":"GetLensOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get an existing lens.

    " @@ -476,15 +716,16 @@ "name":"GetLensReview", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}", + "responseCode":200 }, "input":{"shape":"GetLensReviewInput"}, "output":{"shape":"GetLensReviewOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get lens review.

    " @@ -493,15 +734,16 @@ "name":"GetLensReviewReport", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/report" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/report", + "responseCode":200 }, "input":{"shape":"GetLensReviewReportInput"}, "output":{"shape":"GetLensReviewReportOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get lens review report.

    " @@ -510,15 +752,16 @@ "name":"GetLensVersionDifference", "http":{ "method":"GET", - "requestUri":"/lenses/{LensAlias}/versionDifference" + "requestUri":"/lenses/{LensAlias}/versionDifference", + "responseCode":200 }, "input":{"shape":"GetLensVersionDifferenceInput"}, "output":{"shape":"GetLensVersionDifferenceOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get lens version differences.

    " @@ -527,15 +770,16 @@ "name":"GetMilestone", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/milestones/{MilestoneNumber}" + "requestUri":"/workloads/{WorkloadId}/milestones/{MilestoneNumber}", + "responseCode":200 }, "input":{"shape":"GetMilestoneInput"}, "output":{"shape":"GetMilestoneOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get a milestone for an existing workload.

    " @@ -544,15 +788,16 @@ "name":"GetProfile", "http":{ "method":"GET", - "requestUri":"/profiles/{ProfileArn}" + "requestUri":"/profiles/{ProfileArn}", + "responseCode":200 }, "input":{"shape":"GetProfileInput"}, "output":{"shape":"GetProfileOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get profile information.

    " @@ -561,15 +806,16 @@ "name":"GetProfileTemplate", "http":{ "method":"GET", - "requestUri":"/profileTemplate" + "requestUri":"/profileTemplate", + "responseCode":200 }, "input":{"shape":"GetProfileTemplateInput"}, "output":{"shape":"GetProfileTemplateOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get profile template.

    " @@ -578,15 +824,16 @@ "name":"GetReviewTemplate", "http":{ "method":"GET", - "requestUri":"/reviewTemplates/{TemplateArn}" + "requestUri":"/reviewTemplates/{TemplateArn}", + "responseCode":200 }, "input":{"shape":"GetReviewTemplateInput"}, "output":{"shape":"GetReviewTemplateOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get review template.

    " @@ -595,15 +842,16 @@ "name":"GetReviewTemplateAnswer", "http":{ "method":"GET", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers/{QuestionId}" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers/{QuestionId}", + "responseCode":200 }, "input":{"shape":"GetReviewTemplateAnswerInput"}, "output":{"shape":"GetReviewTemplateAnswerOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get review template answer.

    " @@ -612,15 +860,16 @@ "name":"GetReviewTemplateLensReview", "http":{ "method":"GET", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}", + "responseCode":200 }, "input":{"shape":"GetReviewTemplateLensReviewInput"}, "output":{"shape":"GetReviewTemplateLensReviewOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get a lens review associated with a review template.

    " @@ -629,15 +878,16 @@ "name":"GetWorkload", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}" + "requestUri":"/workloads/{WorkloadId}", + "responseCode":200 }, "input":{"shape":"GetWorkloadInput"}, "output":{"shape":"GetWorkloadOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Get an existing workload.

    " @@ -646,34 +896,147 @@ "name":"ImportLens", "http":{ "method":"PUT", - "requestUri":"/importLens" + "requestUri":"/importLens", + "responseCode":200 }, "input":{"shape":"ImportLensInput"}, "output":{"shape":"ImportLensOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Import a new custom lens or update an existing custom lens.

    To update an existing custom lens, specify its ARN as the LensAlias. If no ARN is specified, a new custom lens is created.

    The new or updated lens will have a status of DRAFT. The lens cannot be applied to workloads or shared with other Amazon Web Services accounts until it's published with CreateLensVersion.

    Lenses are defined in JSON. For more information, see JSON format specification in the Well-Architected Tool User Guide.

    A custom lens cannot exceed 500 KB in size.

    Disclaimer

    Do not include or gather personal identifiable information (PII) of end users or other identifiable individuals in or via your custom lenses. If your custom lens or those shared with you and used in your account do include or collect PII you are responsible for: ensuring that the included PII is processed in accordance with applicable law, providing adequate privacy notices, and obtaining necessary consents for processing such data.

    " + }, + "ListAgentContexts":{ + "name":"ListAgentContexts", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/contexts", + "responseCode":200 + }, + "input":{"shape":"ListAgentContextsRequest"}, + "output":{"shape":"ListAgentContextsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists contexts associated with a profile.

    ", + "readonly":true + }, + "ListAgentGoals":{ + "name":"ListAgentGoals", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/goals", + "responseCode":200 + }, + "input":{"shape":"ListAgentGoalsRequest"}, + "output":{"shape":"ListAgentGoalsResponse"}, + "errors":[ {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], - "documentation":"

    Import a new custom lens or update an existing custom lens.

    To update an existing custom lens, specify its ARN as the LensAlias. If no ARN is specified, a new custom lens is created.

    The new or updated lens will have a status of DRAFT. The lens cannot be applied to workloads or shared with other Amazon Web Services accounts until it's published with CreateLensVersion.

    Lenses are defined in JSON. For more information, see JSON format specification in the Well-Architected Tool User Guide.

    A custom lens cannot exceed 500 KB in size.

    Disclaimer

    Do not include or gather personal identifiable information (PII) of end users or other identifiable individuals in or via your custom lenses. If your custom lens or those shared with you and used in your account do include or collect PII you are responsible for: ensuring that the included PII is processed in accordance with applicable law, providing adequate privacy notices, and obtaining necessary consents for processing such data.

    " + "documentation":"

    Lists optimization goals associated with a specified profile. Goals define specific targets and objectives for the optimization process.

    ", + "readonly":true + }, + "ListAgentProfiles":{ + "name":"ListAgentProfiles", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles", + "responseCode":200 + }, + "input":{"shape":"ListAgentProfilesRequest"}, + "output":{"shape":"ListAgentProfilesResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists optimization profiles in your account. Profiles define the scope and configuration for generating optimization recommendations.

    ", + "readonly":true + }, + "ListAgentRecommendationGenerations":{ + "name":"ListAgentRecommendationGenerations", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/generations", + "responseCode":200 + }, + "input":{"shape":"ListAgentRecommendationGenerationsRequest"}, + "output":{"shape":"ListAgentRecommendationGenerationsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists recommendation generation processes for a specified profile.

    ", + "readonly":true + }, + "ListAgentRecommendationItems":{ + "name":"ListAgentRecommendationItems", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-recommendations/{recommendationArn}/items", + "responseCode":200 + }, + "input":{"shape":"ListAgentRecommendationItemsRequest"}, + "output":{"shape":"ListAgentRecommendationItemsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists recommendation items for a specific recommendation. Recommendation items provide detailed information about individual optimization opportunities.

    ", + "readonly":true + }, + "ListAgentRecommendations":{ + "name":"ListAgentRecommendations", + "http":{ + "method":"GET", + "requestUri":"/api/v1/agent-profiles/{profileArn}/recommendations", + "responseCode":200 + }, + "input":{"shape":"ListAgentRecommendationsRequest"}, + "output":{"shape":"ListAgentRecommendationsResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Lists active optimization recommendations for a specified profile with optional filtering by state.

    ", + "readonly":true }, "ListAnswers":{ "name":"ListAnswers", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers", + "responseCode":200 }, "input":{"shape":"ListAnswersInput"}, "output":{"shape":"ListAnswersOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List of answers for a particular workload and lens.

    " @@ -682,15 +1045,16 @@ "name":"ListCheckDetails", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/checks" + "requestUri":"/workloads/{WorkloadId}/checks", + "responseCode":200 }, "input":{"shape":"ListCheckDetailsInput"}, "output":{"shape":"ListCheckDetailsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List of Trusted Advisor check details by account related to the workload.

    " @@ -699,15 +1063,16 @@ "name":"ListCheckSummaries", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/checkSummaries" + "requestUri":"/workloads/{WorkloadId}/checkSummaries", + "responseCode":200 }, "input":{"shape":"ListCheckSummariesInput"}, "output":{"shape":"ListCheckSummariesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List of Trusted Advisor checks summarized for all accounts related to the workload.

    " @@ -716,15 +1081,16 @@ "name":"ListLensReviewImprovements", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/improvements" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/improvements", + "responseCode":200 }, "input":{"shape":"ListLensReviewImprovementsInput"}, "output":{"shape":"ListLensReviewImprovementsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the improvements of a particular lens review.

    " @@ -733,15 +1099,16 @@ "name":"ListLensReviews", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/lensReviews" + "requestUri":"/workloads/{WorkloadId}/lensReviews", + "responseCode":200 }, "input":{"shape":"ListLensReviewsInput"}, "output":{"shape":"ListLensReviewsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List lens reviews for a particular workload.

    " @@ -750,15 +1117,16 @@ "name":"ListLensShares", "http":{ "method":"GET", - "requestUri":"/lenses/{LensAlias}/shares" + "requestUri":"/lenses/{LensAlias}/shares", + "responseCode":200 }, "input":{"shape":"ListLensSharesInput"}, "output":{"shape":"ListLensSharesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the lens shares associated with the lens.

    " @@ -767,14 +1135,15 @@ "name":"ListLenses", "http":{ "method":"GET", - "requestUri":"/lenses" + "requestUri":"/lenses", + "responseCode":200 }, "input":{"shape":"ListLensesInput"}, "output":{"shape":"ListLensesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the available lenses.

    " @@ -783,15 +1152,16 @@ "name":"ListMilestones", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/milestonesSummaries" + "requestUri":"/workloads/{WorkloadId}/milestonesSummaries", + "responseCode":200 }, "input":{"shape":"ListMilestonesInput"}, "output":{"shape":"ListMilestonesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List all milestones for an existing workload.

    " @@ -800,14 +1170,15 @@ "name":"ListNotifications", "http":{ "method":"POST", - "requestUri":"/notifications" + "requestUri":"/notifications", + "responseCode":200 }, "input":{"shape":"ListNotificationsInput"}, "output":{"shape":"ListNotificationsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List lens notifications.

    " @@ -816,14 +1187,15 @@ "name":"ListProfileNotifications", "http":{ "method":"GET", - "requestUri":"/profileNotifications/" + "requestUri":"/profileNotifications", + "responseCode":200 }, "input":{"shape":"ListProfileNotificationsInput"}, "output":{"shape":"ListProfileNotificationsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List profile notifications.

    " @@ -832,15 +1204,16 @@ "name":"ListProfileShares", "http":{ "method":"GET", - "requestUri":"/profiles/{ProfileArn}/shares" + "requestUri":"/profiles/{ProfileArn}/shares", + "responseCode":200 }, "input":{"shape":"ListProfileSharesInput"}, "output":{"shape":"ListProfileSharesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List profile shares.

    " @@ -849,14 +1222,15 @@ "name":"ListProfiles", "http":{ "method":"GET", - "requestUri":"/profileSummaries" + "requestUri":"/profileSummaries", + "responseCode":200 }, "input":{"shape":"ListProfilesInput"}, "output":{"shape":"ListProfilesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List profiles.

    " @@ -865,15 +1239,16 @@ "name":"ListReviewTemplateAnswers", "http":{ "method":"GET", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers", + "responseCode":200 }, "input":{"shape":"ListReviewTemplateAnswersInput"}, "output":{"shape":"ListReviewTemplateAnswersOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the answers of a review template.

    " @@ -882,14 +1257,15 @@ "name":"ListReviewTemplates", "http":{ "method":"GET", - "requestUri":"/reviewTemplates" + "requestUri":"/reviewTemplates", + "responseCode":200 }, "input":{"shape":"ListReviewTemplatesInput"}, "output":{"shape":"ListReviewTemplatesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List review templates.

    " @@ -898,14 +1274,15 @@ "name":"ListShareInvitations", "http":{ "method":"GET", - "requestUri":"/shareInvitations" + "requestUri":"/shareInvitations", + "responseCode":200 }, "input":{"shape":"ListShareInvitationsInput"}, "output":{"shape":"ListShareInvitationsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the share invitations.

    WorkloadNamePrefix, LensNamePrefix, ProfileNamePrefix, and TemplateNamePrefix are mutually exclusive. Use the parameter that matches your ShareResourceType.

    " @@ -914,7 +1291,8 @@ "name":"ListTagsForResource", "http":{ "method":"GET", - "requestUri":"/tags/{WorkloadArn}" + "requestUri":"/tags/{WorkloadArn}", + "responseCode":200 }, "input":{"shape":"ListTagsForResourceInput"}, "output":{"shape":"ListTagsForResourceOutput"}, @@ -928,15 +1306,16 @@ "name":"ListTemplateShares", "http":{ "method":"GET", - "requestUri":"/templates/shares/{TemplateArn}" + "requestUri":"/templates/shares/{TemplateArn}", + "responseCode":200 }, "input":{"shape":"ListTemplateSharesInput"}, "output":{"shape":"ListTemplateSharesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List review template shares.

    " @@ -945,15 +1324,16 @@ "name":"ListWorkloadShares", "http":{ "method":"GET", - "requestUri":"/workloads/{WorkloadId}/shares" + "requestUri":"/workloads/{WorkloadId}/shares", + "responseCode":200 }, "input":{"shape":"ListWorkloadSharesInput"}, "output":{"shape":"ListWorkloadSharesOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    List the workload shares associated with the workload.

    " @@ -962,23 +1342,64 @@ "name":"ListWorkloads", "http":{ "method":"POST", - "requestUri":"/workloadsSummaries" + "requestUri":"/workloadsSummaries", + "responseCode":200 }, "input":{"shape":"ListWorkloadsInput"}, "output":{"shape":"ListWorkloadsOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Paginated list of workloads.

    " }, + "PutAgentRecommendationFeedback":{ + "name":"PutAgentRecommendationFeedback", + "http":{ + "method":"PUT", + "requestUri":"/api/v1/agent-recommendations/{recommendationArn}/feedback", + "responseCode":200 + }, + "input":{"shape":"PutAgentRecommendationFeedbackRequest"}, + "output":{"shape":"PutAgentRecommendationFeedbackResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Submits user feedback on a recommendation to help improve future optimization suggestions and track implementation outcomes.

    ", + "idempotent":true + }, + "StartAgentRecommendationGeneration":{ + "name":"StartAgentRecommendationGeneration", + "http":{ + "method":"POST", + "requestUri":"/api/v1/agent-profiles/{profileArn}/generations", + "responseCode":200 + }, + "input":{"shape":"StartAgentRecommendationGenerationRequest"}, + "output":{"shape":"StartAgentRecommendationGenerationResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Initiates a new recommendation generation process for the specified optimization profile. This asynchronous operation analyzes your Amazon Web Services resources and generates optimization recommendations based on the configured pillars and scope. Use GetAgentRecommendationGeneration to check status.

    ", + "idempotent":true + }, "TagResource":{ "name":"TagResource", "http":{ "method":"POST", - "requestUri":"/tags/{WorkloadArn}" + "requestUri":"/tags/{WorkloadArn}", + "responseCode":200 }, "input":{"shape":"TagResourceInput"}, "output":{"shape":"TagResourceOutput"}, @@ -992,7 +1413,8 @@ "name":"UntagResource", "http":{ "method":"DELETE", - "requestUri":"/tags/{WorkloadArn}" + "requestUri":"/tags/{WorkloadArn}", + "responseCode":200 }, "input":{"shape":"UntagResourceInput"}, "output":{"shape":"UntagResourceOutput"}, @@ -1002,20 +1424,97 @@ ], "documentation":"

    Deletes specified tags from a resource.

    The WorkloadArn parameter can be a workload ARN, a custom lens ARN, a profile ARN, or review template ARN.

    To specify multiple tags, use separate tagKeys parameters, for example:

    DELETE /tags/WorkloadArn?tagKeys=key1&tagKeys=key2

    " }, + "UpdateAgentContext":{ + "name":"UpdateAgentContext", + "http":{ + "method":"PUT", + "requestUri":"/api/v1/agent-profiles/{profileArn}/contexts/{id}", + "responseCode":200 + }, + "input":{"shape":"UpdateAgentContextRequest"}, + "output":{"shape":"UpdateAgentContextResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates an existing context associated with a profile.

    ", + "idempotent":true + }, + "UpdateAgentGoal":{ + "name":"UpdateAgentGoal", + "http":{ + "method":"PUT", + "requestUri":"/api/v1/agent-profiles/{profileArn}/goals/{id}", + "responseCode":200 + }, + "input":{"shape":"UpdateAgentGoalRequest"}, + "output":{"shape":"UpdateAgentGoalResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the pillars and title of an existing goal associated with a profile.

    ", + "idempotent":true + }, + "UpdateAgentProfile":{ + "name":"UpdateAgentProfile", + "http":{ + "method":"PUT", + "requestUri":"/api/v1/agent-profiles/{profileArn}", + "responseCode":200 + }, + "input":{"shape":"UpdateAgentProfileRequest"}, + "output":{"shape":"UpdateAgentProfileResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates an existing optimization profile's configuration, including its pillars, execution role, and aggregation settings.

    ", + "idempotent":true + }, + "UpdateAgentRecommendationStatus":{ + "name":"UpdateAgentRecommendationStatus", + "http":{ + "method":"PATCH", + "requestUri":"/api/v1/agent-recommendations/{recommendationArn}/status", + "responseCode":200 + }, + "input":{"shape":"UpdateAgentRecommendationStatusRequest"}, + "output":{"shape":"UpdateAgentRecommendationStatusResponse"}, + "errors":[ + {"shape":"AccessDeniedException"}, + {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} + ], + "documentation":"

    Updates the status of a recommendation to track its progress through the implementation lifecycle.

    ", + "idempotent":true + }, "UpdateAnswer":{ "name":"UpdateAnswer", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers/{QuestionId}" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/answers/{QuestionId}", + "responseCode":200 }, "input":{"shape":"UpdateAnswerInput"}, "output":{"shape":"UpdateAnswerOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update the answer to a specific question in a workload review.

    " @@ -1024,14 +1523,15 @@ "name":"UpdateGlobalSettings", "http":{ "method":"PATCH", - "requestUri":"/global-settings" + "requestUri":"/global-settings", + "responseCode":200 }, "input":{"shape":"UpdateGlobalSettingsInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update whether the Amazon Web Services account is opted into organization sharing and discovery integration features.

    " @@ -1040,15 +1540,16 @@ "name":"UpdateIntegration", "http":{ "method":"POST", - "requestUri":"/workloads/{WorkloadId}/updateIntegration" + "requestUri":"/workloads/{WorkloadId}/updateIntegration", + "responseCode":200 }, "input":{"shape":"UpdateIntegrationInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, + {"shape":"InternalServerException"}, {"shape":"ConflictException"}, {"shape":"ResourceNotFoundException"}, - {"shape":"AccessDeniedException"}, - {"shape":"InternalServerException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update integration features.

    " @@ -1057,16 +1558,17 @@ "name":"UpdateLensReview", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}", + "responseCode":200 }, "input":{"shape":"UpdateLensReviewInput"}, "output":{"shape":"UpdateLensReviewOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update lens review for a particular workload.

    " @@ -1075,16 +1577,17 @@ "name":"UpdateProfile", "http":{ "method":"PATCH", - "requestUri":"/profiles/{ProfileArn}" + "requestUri":"/profiles/{ProfileArn}", + "responseCode":200 }, "input":{"shape":"UpdateProfileInput"}, "output":{"shape":"UpdateProfileOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a profile.

    " @@ -1093,16 +1596,17 @@ "name":"UpdateReviewTemplate", "http":{ "method":"PATCH", - "requestUri":"/reviewTemplates/{TemplateArn}" + "requestUri":"/reviewTemplates/{TemplateArn}", + "responseCode":200 }, "input":{"shape":"UpdateReviewTemplateInput"}, "output":{"shape":"UpdateReviewTemplateOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a review template.

    " @@ -1111,16 +1615,17 @@ "name":"UpdateReviewTemplateAnswer", "http":{ "method":"PATCH", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers/{QuestionId}" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/answers/{QuestionId}", + "responseCode":200 }, "input":{"shape":"UpdateReviewTemplateAnswerInput"}, "output":{"shape":"UpdateReviewTemplateAnswerOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a review template answer.

    " @@ -1129,16 +1634,17 @@ "name":"UpdateReviewTemplateLensReview", "http":{ "method":"PATCH", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}", + "responseCode":200 }, "input":{"shape":"UpdateReviewTemplateLensReviewInput"}, "output":{"shape":"UpdateReviewTemplateLensReviewOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a lens review associated with a review template.

    " @@ -1147,16 +1653,17 @@ "name":"UpdateShareInvitation", "http":{ "method":"PATCH", - "requestUri":"/shareInvitations/{ShareInvitationId}" + "requestUri":"/shareInvitations/{ShareInvitationId}", + "responseCode":200 }, "input":{"shape":"UpdateShareInvitationInput"}, "output":{"shape":"UpdateShareInvitationOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a workload or custom lens share invitation.

    This API operation can be called independently of any resource. Previous documentation implied that a workload ARN must be specified.

    " @@ -1165,16 +1672,17 @@ "name":"UpdateWorkload", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}" + "requestUri":"/workloads/{WorkloadId}", + "responseCode":200 }, "input":{"shape":"UpdateWorkloadInput"}, "output":{"shape":"UpdateWorkloadOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update an existing workload.

    " @@ -1183,16 +1691,17 @@ "name":"UpdateWorkloadShare", "http":{ "method":"PATCH", - "requestUri":"/workloads/{WorkloadId}/shares/{ShareId}" + "requestUri":"/workloads/{WorkloadId}/shares/{ShareId}", + "responseCode":200 }, "input":{"shape":"UpdateWorkloadShareInput"}, "output":{"shape":"UpdateWorkloadShareOutput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"InternalServerException"}, - {"shape":"ResourceNotFoundException"}, {"shape":"ConflictException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Update a workload share.

    " @@ -1201,17 +1710,18 @@ "name":"UpgradeLensReview", "http":{ "method":"PUT", - "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/upgrade" + "requestUri":"/workloads/{WorkloadId}/lensReviews/{LensAlias}/upgrade", + "responseCode":200 }, "input":{"shape":"UpgradeLensReviewInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, - {"shape":"ThrottlingException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Upgrade lens review for a particular workload.

    " }, @@ -1219,17 +1729,18 @@ "name":"UpgradeProfileVersion", "http":{ "method":"PUT", - "requestUri":"/workloads/{WorkloadId}/profiles/{ProfileArn}/upgrade" + "requestUri":"/workloads/{WorkloadId}/profiles/{ProfileArn}/upgrade", + "responseCode":200 }, "input":{"shape":"UpgradeProfileVersionInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, - {"shape":"ThrottlingException"}, - {"shape":"ServiceQuotaExceededException"} + {"shape":"ConflictException"}, + {"shape":"ServiceQuotaExceededException"}, + {"shape":"ResourceNotFoundException"}, + {"shape":"ThrottlingException"} ], "documentation":"

    Upgrade a profile.

    " }, @@ -1237,15 +1748,16 @@ "name":"UpgradeReviewTemplateLensReview", "http":{ "method":"PUT", - "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/upgrade" + "requestUri":"/reviewTemplates/{TemplateArn}/lensReviews/{LensAlias}/upgrade", + "responseCode":200 }, "input":{"shape":"UpgradeReviewTemplateLensReviewInput"}, "errors":[ + {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, - {"shape":"ResourceNotFoundException"}, - {"shape":"ConflictException"}, {"shape":"InternalServerException"}, - {"shape":"AccessDeniedException"}, + {"shape":"ConflictException"}, + {"shape":"ResourceNotFoundException"}, {"shape":"ThrottlingException"} ], "documentation":"

    Upgrade the lens review of a review template.

    " @@ -1259,9 +1771,16 @@ "Message":{"shape":"ExceptionMessage"} }, "documentation":"

    User does not have sufficient access to perform this action.

    ", - "error":{"httpStatusCode":403}, + "error":{ + "httpStatusCode":403, + "senderFault":true + }, "exception":true }, + "AccountId":{ + "type":"string", + "pattern":"\\d{12}" + }, "AccountJiraConfigurationInput":{ "type":"structure", "members":{ @@ -1352,6 +1871,491 @@ "type":"list", "member":{"shape":"AdditionalResources"} }, + "AgentProfileArn":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:aws([a-z0-9-]+)?:wellarchitected:[a-z0-9-]{6,64}:\\d{12}:agent-profile/([a-zA-Z0-9_-]+)" + }, + "AgentProfileSummaries":{ + "type":"list", + "member":{"shape":"AgentProfileSummary"} + }, + "AgentProfileSummary":{ + "type":"structure", + "required":[ + "name", + "pillars", + "executionRoleArn", + "aggregationConfiguration", + "arn", + "createdBy", + "createdAt" + ], + "members":{ + "name":{ + "shape":"AgentProfileSummaryNameString", + "documentation":"

    The system name of the profile.

    " + }, + "displayName":{ + "shape":"AgentProfileSummaryDisplayNameString", + "documentation":"

    The display name of the profile shown to users.

    " + }, + "description":{ + "shape":"AgentProfileSummaryDescriptionString", + "documentation":"

    A description of the profile.

    " + }, + "businessOverview":{ + "shape":"AgentProfileSummaryBusinessOverviewString", + "documentation":"

    The business overview for this profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars associated with this profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled for the profile.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM execution role used for recommendation actions.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The aggregation configuration that defines which Amazon Web Services accounts and Regions to analyze.

    " + }, + "arn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile.

    " + }, + "eligibleForScheduledGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for scheduled recommendation generation.

    " + }, + "eligibleForArchitectureGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for manual architecture generation.

    " + }, + "fieldErrors":{ + "shape":"FieldErrors", + "documentation":"

    A map of field paths to error messages for invalid or missing input fields.

    " + }, + "tags":{ + "shape":"Tags", + "documentation":"

    The tags associated with the profile.

    " + }, + "createdBy":{ + "shape":"AgentProfileSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that created this profile.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was created.

    " + }, + "lastModifiedBy":{ + "shape":"AgentProfileSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this profile.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was last modified.

    " + } + }, + "documentation":"

    Summary of an optimization profile, including its configuration, metadata, and audit information.

    " + }, + "AgentProfileSummaryBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "AgentProfileSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentProfileSummaryDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "AgentProfileSummaryDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "AgentProfileSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentProfileSummaryNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"[a-zA-Z0-9_-]+" + }, + "AgentRecommendationArn":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:aws([a-z0-9-]+)?:wellarchitected:[a-z0-9-]{6,64}:\\d{12}:agent-recommendation/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "AgentRecommendationGenerationSummaries":{ + "type":"list", + "member":{"shape":"AgentRecommendationGenerationSummary"} + }, + "AgentRecommendationGenerationSummary":{ + "type":"structure", + "required":[ + "id", + "profileArn", + "status", + "createdBy", + "createdAt" + ], + "members":{ + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the recommendation generation.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile used for this generation.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the recommendation generation.

    " + }, + "status":{ + "shape":"GenerationStatus", + "documentation":"

    The current status of the recommendation generation.

    " + }, + "estimatedCompletionTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The estimated time for the generation to complete.

    " + }, + "createdBy":{ + "shape":"AgentRecommendationGenerationSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that started this generation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was started.

    " + }, + "lastModifiedBy":{ + "shape":"AgentRecommendationGenerationSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this generation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was last modified.

    " + } + }, + "documentation":"

    Summary of a recommendation generation process initiated through the agent API.

    " + }, + "AgentRecommendationGenerationSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationGenerationSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationItemSummaries":{ + "type":"list", + "member":{"shape":"AgentRecommendationItemSummary"} + }, + "AgentRecommendationItemSummary":{ + "type":"structure", + "required":[ + "id", + "recommendationArn", + "type", + "metadata", + "createdBy", + "createdAt" + ], + "members":{ + "id":{ + "shape":"String", + "documentation":"

    The unique identifier of the recommendation item.

    " + }, + "recommendationArn":{ + "shape":"RecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated recommendation.

    " + }, + "type":{ + "shape":"RecommendationItemType", + "documentation":"

    The type of the recommendation item.

    " + }, + "metadata":{ + "shape":"Document", + "documentation":"

    Metadata containing a snapshot of the resource or recommendation at the time of generation.

    " + }, + "createdBy":{ + "shape":"AgentRecommendationItemSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that created this recommendation item.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation item was created.

    " + }, + "lastModifiedBy":{ + "shape":"AgentRecommendationItemSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this recommendation item.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation item was last modified.

    " + } + }, + "documentation":"

    Summary of an agent recommendation item, representing an Amazon Web Services resource or recommendation affected by the optimization recommendation.

    " + }, + "AgentRecommendationItemSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationItemSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationRemediation":{ + "type":"structure", + "required":[ + "recommendationArn", + "type", + "steps", + "createdBy", + "createdAt" + ], + "members":{ + "recommendationArn":{ + "shape":"RecommendationArn", + "documentation":"

    The ARN of the recommendation that this remediation belongs to.

    " + }, + "type":{ + "shape":"RemediationType", + "documentation":"

    The remediation method.

    " + }, + "steps":{ + "shape":"RemediationSteps", + "documentation":"

    The procedural steps to perform the remediation.

    " + }, + "resourceLinks":{ + "shape":"ResourceLinks", + "documentation":"

    External references associated with the steps.

    " + }, + "createdBy":{ + "shape":"AgentRecommendationRemediationCreatedByString", + "documentation":"

    The identifier of the user or system that created this remediation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the remediation was created.

    " + }, + "lastModifiedBy":{ + "shape":"AgentRecommendationRemediationLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this remediation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the remediation was last modified.

    " + } + }, + "documentation":"

    The core fields for a remediation.

    " + }, + "AgentRecommendationRemediationCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationRemediationLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationRemediations":{ + "type":"list", + "member":{"shape":"AgentRecommendationRemediation"} + }, + "AgentRecommendationSummaries":{ + "type":"list", + "member":{"shape":"AgentRecommendationSummary"} + }, + "AgentRecommendationSummary":{ + "type":"structure", + "required":[ + "recommendationArn", + "profileArn", + "title", + "description", + "type", + "pillar", + "priority", + "effort", + "status", + "state", + "impact", + "roi", + "createdBy", + "createdAt" + ], + "members":{ + "recommendationArn":{ + "shape":"RecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated profile.

    " + }, + "title":{ + "shape":"AgentRecommendationSummaryTitleString", + "documentation":"

    The title of the recommendation.

    " + }, + "description":{ + "shape":"AgentRecommendationSummaryDescriptionString", + "documentation":"

    A description of the recommendation.

    " + }, + "type":{ + "shape":"RecommendationType", + "documentation":"

    The type of the recommendation.

    " + }, + "pillar":{ + "shape":"Pillar", + "documentation":"

    The Well-Architected Tool Framework pillar that the recommendation addresses.

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the recommendation.

    " + }, + "effort":{ + "shape":"Effort", + "documentation":"

    The effort required to implement the recommendation.

    " + }, + "status":{ + "shape":"RecommendationStatus", + "documentation":"

    The current status of the recommendation.

    " + }, + "state":{ + "shape":"RecommendationState", + "documentation":"

    The current state of the recommendation.

    " + }, + "updateReason":{ + "shape":"AgentRecommendationSummaryUpdateReasonString", + "documentation":"

    The free-text reason associated with the recommendation's most recent status update.

    " + }, + "impact":{ + "shape":"ImpactCategory", + "documentation":"

    The severity of the recommendation's impact.

    " + }, + "roi":{ + "shape":"Roi", + "documentation":"

    The return on investment estimate for the recommendation.

    " + }, + "numberOfResources":{ + "shape":"Integer", + "documentation":"

    The number of Amazon Web Services resources this recommendation affects.

    " + }, + "awsServices":{ + "shape":"StringList", + "documentation":"

    The Amazon Web Services services that the recommendation applies to.

    " + }, + "businessUnits":{ + "shape":"StringList", + "documentation":"

    The business units that own the affected resources.

    " + }, + "applications":{ + "shape":"StringList", + "documentation":"

    The applications that the recommendation targets.

    " + }, + "createdBy":{ + "shape":"AgentRecommendationSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that created this recommendation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation was created.

    " + }, + "lastModifiedBy":{ + "shape":"AgentRecommendationSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this recommendation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation was last modified.

    " + } + }, + "documentation":"

    Summary of an agent optimization recommendation returned by list operations.

    " + }, + "AgentRecommendationSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationSummaryDescriptionString":{ + "type":"string", + "max":500, + "min":80, + "sensitive":true + }, + "AgentRecommendationSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "AgentRecommendationSummaryTitleString":{ + "type":"string", + "max":120, + "min":3, + "sensitive":true + }, + "AgentRecommendationSummaryUpdateReasonString":{ + "type":"string", + "max":4096, + "min":1, + "sensitive":true + }, + "AggregationConfiguration":{ + "type":"structure", + "required":[ + "accountId", + "regions", + "accessRoleArn" + ], + "members":{ + "accountId":{ + "shape":"AccountId", + "documentation":"

    The Amazon Web Services account ID to analyze.

    " + }, + "regions":{ + "shape":"Regions", + "documentation":"

    A list of Amazon Web Services Regions to include in the analysis.

    " + }, + "accessRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of an IAM role to assume for resource analysis in this account.

    " + } + }, + "documentation":"

    Configuration settings that define the scope of Amazon Web Services resources to analyze for optimization recommendations.

    " + }, + "AggregationConfigurations":{ + "type":"list", + "member":{"shape":"AggregationConfiguration"}, + "max":100, + "min":0 + }, "Answer":{ "type":"structure", "members":{ @@ -1432,8 +2436,17 @@ "ApplicationArn":{ "type":"string", "max":2084, + "min":0, "pattern":"arn:aws[-a-z]*:servicecatalog:[a-z]{2}(-gov)?-[a-z]+-\\d:\\d{12}:/applications/[a-z0-9]+" }, + "ApplicationType":{ + "type":"string", + "enum":[ + "SAS", + "DESKTOP_APPLICATION", + "OTHER" + ] + }, "AssociateLensesInput":{ "type":"structure", "required":[ @@ -1478,7 +2491,8 @@ "AwsRegion":{ "type":"string", "documentation":"

    An Amazon Web Services Region, for example, us-west-2 or ap-northeast-1.

    ", - "max":100 + "max":100, + "min":0 }, "Base64String":{ "type":"string", @@ -1496,6 +2510,10 @@ "type":"list", "member":{"shape":"BestPractice"} }, + "Boolean":{ + "type":"boolean", + "box":true + }, "CheckDescription":{"type":"string"}, "CheckDetail":{ "type":"structure", @@ -1536,7 +2554,10 @@ "shape":"CheckFailureReason", "documentation":"

    Reason associated to the check.

    " }, - "UpdatedAt":{"shape":"Timestamp"} + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the check was last updated.

    " + } }, "documentation":"

    Account details for a Well-Architected best practice in relation to Trusted Advisor checks.

    " }, @@ -1571,6 +2592,7 @@ }, "CheckStatusCount":{ "type":"integer", + "box":true, "max":101, "min":1 }, @@ -1597,7 +2619,10 @@ "shape":"CheckDescription", "documentation":"

    Trusted Advisor check description.

    " }, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the check summary was last updated.

    " + }, "LensArn":{ "shape":"LensArn", "documentation":"

    Well-Architected Lens ARN associated to the check.

    " @@ -1725,7 +2750,7 @@ }, "ImprovementPlanUrl":{"shape":"ImprovementPlanUrl"} }, - "documentation":"

    The choice level improvement plan.

    " + "documentation":"

    The choice level improvement plan.

    This value is only applicable to custom lenses.

    " }, "ChoiceImprovementPlans":{ "type":"list", @@ -1733,7 +2758,8 @@ }, "ChoiceNotes":{ "type":"string", - "max":250 + "max":250, + "min":0 }, "ChoiceReason":{ "type":"string", @@ -1792,7 +2818,8 @@ "type":"string", "documentation":"

    A unique case-sensitive string used to ensure that this request is idempotent (executes only once).

    You should not reuse the same token for other requests. If you retry a request with the same client request token and the same parameters after the original request has completed successfully, the result of the original request is returned.

    This token is listed as required, however, if you do not specify it, the Amazon Web Services SDKs automatically generate one for you. If you are not using the Amazon Web Services SDK or the CLI, you must provide this token or the request will fail.

    ", "max":2048, - "min":1 + "min":1, + "pattern":"[\\x00-\\x7F]*" }, "ConflictException":{ "type":"structure", @@ -1807,7 +2834,10 @@ "ResourceType":{"shape":"ExceptionResourceType"} }, "documentation":"

    The resource has already been processed, was deleted, or is too large.

    ", - "error":{"httpStatusCode":409}, + "error":{ + "httpStatusCode":409, + "senderFault":true + }, "exception":true }, "ConsolidatedReportMetric":{ @@ -1821,7 +2851,10 @@ "WorkloadId":{"shape":"WorkloadId"}, "WorkloadName":{"shape":"WorkloadName"}, "WorkloadArn":{"shape":"WorkloadArn"}, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the consolidated report metric was last updated.

    " + }, "Lenses":{ "shape":"LensMetrics", "documentation":"

    The metrics for the lenses in the workload.

    " @@ -1837,28 +2870,599 @@ "type":"list", "member":{"shape":"ConsolidatedReportMetric"} }, - "Count":{ - "type":"integer", - "documentation":"

    A non-negative integer that denotes how many.

    ", - "min":0 - }, - "CreateLensShareInput":{ + "ContextContent":{ "type":"structure", - "required":[ - "LensAlias", - "SharedWith", - "ClientRequestToken" - ], "members":{ - "LensAlias":{ - "shape":"LensAlias", - "location":"uri", - "locationName":"LensAlias" + "accountIds":{ + "shape":"ContextContentAccountIdsList", + "documentation":"

    The Amazon Web Services account IDs associated with this application context.

    " }, - "SharedWith":{"shape":"SharedWith"}, - "ClientRequestToken":{ - "shape":"ClientRequestToken", - "idempotencyToken":true + "regions":{ + "shape":"ContextContentRegionsList", + "documentation":"

    The Amazon Web Services Regions where this application operates.

    " + }, + "awsServices":{ + "shape":"ContextContentAwsServicesList", + "documentation":"

    The Amazon Web Services services used by this application.

    " + }, + "resourceTypes":{ + "shape":"ContextContentResourceTypesList", + "documentation":"

    The Amazon Web Services resource types relevant to this application.

    " + }, + "resourceTags":{ + "shape":"ContextContentResourceTagsList", + "documentation":"

    Resource tags used to scope this application context.

    " + }, + "applicationOverview":{ + "shape":"ContextContentApplicationOverviewString", + "documentation":"

    A free-form overview of the application.

    " + }, + "industry":{ + "shape":"ContextContentIndustryString", + "documentation":"

    The industry vertical for this application.

    " + }, + "applicationType":{ + "shape":"ApplicationType", + "documentation":"

    The type of the application.

    " + }, + "criticality":{ + "shape":"Criticality", + "documentation":"

    The business criticality of the application.

    " + }, + "architectureOverview":{ + "shape":"ContextContentArchitectureOverviewString", + "documentation":"

    A free-form description of the application architecture.

    " + }, + "additionalContext":{ + "shape":"ContextContentAdditionalContextString", + "documentation":"

    Additional context not captured by other fields.

    " + } + }, + "documentation":"

    Typed content structure for a context. Contains application-specific fields that describe the environment used during recommendation generation.

    " + }, + "ContextContentAccountIdsList":{ + "type":"list", + "member":{"shape":"ContextContentAccountIdsListMemberString"}, + "max":1000, + "min":0 + }, + "ContextContentAccountIdsListMemberString":{ + "type":"string", + "max":12, + "min":12, + "pattern":"\\d{12}" + }, + "ContextContentAdditionalContextString":{ + "type":"string", + "max":10000, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}\\r\\n])*", + "sensitive":true + }, + "ContextContentApplicationOverviewString":{ + "type":"string", + "max":10000, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}\\r\\n])*", + "sensitive":true + }, + "ContextContentArchitectureOverviewString":{ + "type":"string", + "max":10000, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}\\r\\n])*", + "sensitive":true + }, + "ContextContentAwsServicesList":{ + "type":"list", + "member":{"shape":"ContextContentAwsServicesListMemberString"}, + "max":300, + "min":0 + }, + "ContextContentAwsServicesListMemberString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[\\P{C}]+" + }, + "ContextContentIndustryString":{ + "type":"string", + "max":1000, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}\\r\\n])*", + "sensitive":true + }, + "ContextContentRegionsList":{ + "type":"list", + "member":{"shape":"ContextContentRegionsListMemberString"}, + "max":50, + "min":0 + }, + "ContextContentRegionsListMemberString":{ + "type":"string", + "max":64, + "min":1, + "pattern":"[a-z]{2}(-gov)?-[a-z]+-\\d+" + }, + "ContextContentResourceTagsList":{ + "type":"list", + "member":{"shape":"ContextResourceTag"}, + "max":20, + "min":0 + }, + "ContextContentResourceTypesList":{ + "type":"list", + "member":{"shape":"ContextContentResourceTypesListMemberString"}, + "max":1500, + "min":0 + }, + "ContextContentResourceTypesListMemberString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[\\P{C}]+" + }, + "ContextResourceTag":{ + "type":"structure", + "required":[ + "key", + "value" + ], + "members":{ + "key":{ + "shape":"ContextResourceTagKeyString", + "documentation":"

    The tag key.

    " + }, + "value":{ + "shape":"ContextResourceTagValueString", + "documentation":"

    The tag value.

    " + } + }, + "documentation":"

    A key-value pair representing a resource tag used to scope context content.

    " + }, + "ContextResourceTagKeyString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+" + }, + "ContextResourceTagValueString":{ + "type":"string", + "max":256, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*" + }, + "ContextSummaries":{ + "type":"list", + "member":{"shape":"ContextSummary"} + }, + "ContextSummary":{ + "type":"structure", + "required":[ + "id", + "profileArn", + "title", + "contextType", + "content", + "createdBy", + "createdAt" + ], + "members":{ + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the context.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated profile.

    " + }, + "title":{ + "shape":"ContextSummaryTitleString", + "documentation":"

    The title of the context.

    " + }, + "contextType":{ + "shape":"ContextType", + "documentation":"

    The type of the context.

    " + }, + "content":{ + "shape":"ContextContent", + "documentation":"

    The typed content of the context, containing application-specific fields such as account IDs, Regions, services, and resource types.

    " + }, + "applicationType":{ + "shape":"ApplicationType", + "documentation":"

    The type of application described by this context.

    " + }, + "criticality":{ + "shape":"Criticality", + "documentation":"

    The business criticality of the application described by this context.

    " + }, + "createdBy":{ + "shape":"ContextSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that created this context.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the context was created.

    " + }, + "lastModifiedBy":{ + "shape":"ContextSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this context.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the context was last modified.

    " + } + }, + "documentation":"

    Summary of a context associated with a profile, representing application or environment information used during recommendation generation.

    " + }, + "ContextSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "ContextSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "ContextSummaryTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "ContextType":{ + "type":"string", + "enum":["APPLICATION"] + }, + "Count":{ + "type":"integer", + "documentation":"

    A non-negative integer that denotes how many.

    ", + "box":true, + "min":0 + }, + "CreateAgentContextRequest":{ + "type":"structure", + "required":[ + "profileArn", + "title", + "contextType", + "content" + ], + "members":{ + "clientToken":{ + "shape":"CreateAgentContextRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile to associate the context with.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "title":{ + "shape":"CreateAgentContextRequestTitleString", + "documentation":"

    The title of the context.

    " + }, + "contextType":{ + "shape":"ContextType", + "documentation":"

    The type of the context.

    " + }, + "content":{ + "shape":"ContextContent", + "documentation":"

    The typed content of the context. The structure contains application-specific fields such as account IDs, Regions, services, and resource types.

    " + } + } + }, + "CreateAgentContextRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "CreateAgentContextRequestTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "CreateAgentContextResponse":{ + "type":"structure", + "required":["context"], + "members":{ + "context":{ + "shape":"ContextSummary", + "documentation":"

    The created context summary.

    " + } + } + }, + "CreateAgentGoalRequest":{ + "type":"structure", + "required":[ + "profileArn", + "pillars", + "title" + ], + "members":{ + "clientToken":{ + "shape":"CreateAgentGoalRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile to associate the goal with.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars to associate with this goal.

    " + }, + "title":{ + "shape":"CreateAgentGoalRequestTitleString", + "documentation":"

    The title of the goal.

    " + }, + "description":{ + "shape":"CreateAgentGoalRequestDescriptionString", + "documentation":"

    A description of the goal.

    " + } + } + }, + "CreateAgentGoalRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "CreateAgentGoalRequestDescriptionString":{ + "type":"string", + "max":4000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "CreateAgentGoalRequestTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "CreateAgentGoalResponse":{ + "type":"structure", + "required":["goal"], + "members":{ + "goal":{ + "shape":"GoalSummary", + "documentation":"

    The created goal summary.

    " + } + } + }, + "CreateAgentProfileRequest":{ + "type":"structure", + "required":[ + "name", + "pillars", + "executionRoleArn", + "aggregationConfiguration" + ], + "members":{ + "name":{ + "shape":"CreateAgentProfileRequestNameString", + "documentation":"

    The system name of the profile.

    " + }, + "displayName":{ + "shape":"CreateAgentProfileRequestDisplayNameString", + "documentation":"

    The display name of the profile shown to users.

    " + }, + "description":{ + "shape":"CreateAgentProfileRequestDescriptionString", + "documentation":"

    A description of the profile.

    " + }, + "businessOverview":{ + "shape":"CreateAgentProfileRequestBusinessOverviewString", + "documentation":"

    The business overview for this profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars to associate with this profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled for the profile.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM execution role used for recommendation actions.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The aggregation configuration that defines which Amazon Web Services accounts and Regions to analyze.

    " + }, + "clientToken":{ + "shape":"CreateAgentProfileRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "tags":{ + "shape":"Tags", + "documentation":"

    The tags to associate with the profile.

    " + } + } + }, + "CreateAgentProfileRequestBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "CreateAgentProfileRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "CreateAgentProfileRequestDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "CreateAgentProfileRequestDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "CreateAgentProfileRequestNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"[a-zA-Z0-9_-]+" + }, + "CreateAgentProfileResponse":{ + "type":"structure", + "required":[ + "name", + "pillars", + "executionRoleArn", + "aggregationConfiguration", + "arn", + "createdBy", + "createdAt" + ], + "members":{ + "name":{ + "shape":"CreateAgentProfileResponseNameString", + "documentation":"

    The system name of the created profile.

    " + }, + "displayName":{ + "shape":"CreateAgentProfileResponseDisplayNameString", + "documentation":"

    The display name of the created profile.

    " + }, + "description":{ + "shape":"CreateAgentProfileResponseDescriptionString", + "documentation":"

    A description of the created profile.

    " + }, + "businessOverview":{ + "shape":"CreateAgentProfileResponseBusinessOverviewString", + "documentation":"

    The business overview of the created profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars associated with the created profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM execution role.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The aggregation configuration.

    " + }, + "arn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the created profile.

    " + }, + "eligibleForScheduledGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for scheduled recommendation generation.

    " + }, + "eligibleForArchitectureGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for manual architecture generation.

    " + }, + "fieldErrors":{ + "shape":"FieldErrors", + "documentation":"

    A map of field paths to error messages for invalid or missing input fields.

    " + }, + "tags":{ + "shape":"Tags", + "documentation":"

    The tags associated with the created profile.

    " + }, + "createdBy":{ + "shape":"CreateAgentProfileResponseCreatedByString", + "documentation":"

    The identifier of the user or system that created this profile.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was created.

    " + }, + "lastModifiedBy":{ + "shape":"CreateAgentProfileResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this profile.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was last modified.

    " + } + } + }, + "CreateAgentProfileResponseBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "CreateAgentProfileResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "CreateAgentProfileResponseDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "CreateAgentProfileResponseDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "CreateAgentProfileResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "CreateAgentProfileResponseNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"[a-zA-Z0-9_-]+" + }, + "CreateLensShareInput":{ + "type":"structure", + "required":[ + "LensAlias", + "SharedWith", + "ClientRequestToken" + ], + "members":{ + "LensAlias":{ + "shape":"LensAlias", + "location":"uri", + "locationName":"LensAlias" + }, + "SharedWith":{"shape":"SharedWith"}, + "ClientRequestToken":{ + "shape":"ClientRequestToken", + "idempotencyToken":true } } }, @@ -2160,29 +3764,146 @@ "location":"uri", "locationName":"WorkloadId" }, - "SharedWith":{"shape":"SharedWith"}, - "PermissionType":{"shape":"PermissionType"}, - "ClientRequestToken":{ - "shape":"ClientRequestToken", - "idempotencyToken":true + "SharedWith":{"shape":"SharedWith"}, + "PermissionType":{"shape":"PermissionType"}, + "ClientRequestToken":{ + "shape":"ClientRequestToken", + "idempotencyToken":true + } + }, + "documentation":"

    Input for Create Workload Share

    " + }, + "CreateWorkloadShareOutput":{ + "type":"structure", + "members":{ + "WorkloadId":{"shape":"WorkloadId"}, + "ShareId":{"shape":"ShareId"} + }, + "documentation":"

    Input for Create Workload Share

    " + }, + "Criticality":{ + "type":"string", + "enum":[ + "MISSION_CRITICAL", + "BUSINESS_CRITICAL", + "NON_CRITICAL", + "TEST_DEVELOPMENT" + ] + }, + "CrossPillarBenefit":{ + "type":"structure", + "required":[ + "pillar", + "title", + "description", + "impact" + ], + "members":{ + "pillar":{ + "shape":"Pillar", + "documentation":"

    The pillar that would be positively impacted.

    " + }, + "title":{ + "shape":"CrossPillarBenefitTitleString", + "documentation":"

    A short phrase describing the outcome.

    " + }, + "description":{ + "shape":"CrossPillarBenefitDescriptionString", + "documentation":"

    A description of what changes and why it matters.

    " + }, + "impact":{ + "shape":"ImpactCategory", + "documentation":"

    The severity of the benefit.

    " + } + }, + "documentation":"

    A benefit on a different pillar from acting on the recommendation.

    " + }, + "CrossPillarBenefitDescriptionString":{ + "type":"string", + "max":300, + "min":30 + }, + "CrossPillarBenefitTitleString":{ + "type":"string", + "max":80, + "min":3 + }, + "CrossPillarBenefits":{ + "type":"list", + "member":{"shape":"CrossPillarBenefit"} + }, + "DefinitionType":{ + "type":"string", + "enum":[ + "WORKLOAD_METADATA", + "APP_REGISTRY" + ] + }, + "DeleteAgentContextRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the context.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the context to delete.

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "DeleteAgentContextResponse":{ + "type":"structure", + "members":{} + }, + "DeleteAgentGoalRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the goal.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the goal to delete.

    ", + "location":"uri", + "locationName":"id" } - }, - "documentation":"

    Input for Create Workload Share

    " + } }, - "CreateWorkloadShareOutput":{ + "DeleteAgentGoalResponse":{ + "type":"structure", + "members":{} + }, + "DeleteAgentProfileRequest":{ "type":"structure", + "required":["profileArn"], "members":{ - "WorkloadId":{"shape":"WorkloadId"}, - "ShareId":{"shape":"ShareId"} - }, - "documentation":"

    Input for Create Workload Share

    " + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile to delete.

    ", + "location":"uri", + "locationName":"profileArn" + } + } }, - "DefinitionType":{ - "type":"string", - "enum":[ - "WORKLOAD_METADATA", - "APP_REGISTRY" - ] + "DeleteAgentProfileResponse":{ + "type":"structure", + "members":{} }, "DeleteLensInput":{ "type":"structure", @@ -2435,6 +4156,41 @@ "max":64, "min":1 }, + "Document":{ + "type":"structure", + "members":{}, + "document":true + }, + "Double":{ + "type":"double", + "box":true + }, + "Effort":{ + "type":"string", + "enum":[ + "LARGE", + "MEDIUM", + "SMALL" + ] + }, + "ErrorDetails":{ + "type":"structure", + "required":[ + "code", + "message" + ], + "members":{ + "code":{ + "shape":"String", + "documentation":"

    The status code identifying the type of error.

    " + }, + "message":{ + "shape":"String", + "documentation":"

    A human-readable description of the error.

    " + } + }, + "documentation":"

    Details about an error that occurred during recommendation generation.

    " + }, "ExceptionMessage":{ "type":"string", "documentation":"

    Description of the error.

    " @@ -2473,11 +4229,539 @@ } } }, + "FeedbackCategory":{ + "type":"string", + "enum":[ + "OTHER", + "RECOMMENDATION_NOT_RELEVANT", + "RESOURCE_NOT_IMPORTANT", + "RESOURCE_TYPE_NOT_IMPORTANT", + "RECOMMENDATION_INCORRECT" + ] + }, + "FieldErrorMessage":{ + "type":"string", + "max":1024, + "min":1 + }, + "FieldErrorPath":{ + "type":"string", + "max":256, + "min":1 + }, + "FieldErrors":{ + "type":"map", + "key":{"shape":"FieldErrorPath"}, + "value":{"shape":"FieldErrorMessage"}, + "max":100, + "min":0 + }, "FlaggedResources":{ "type":"integer", + "box":true, "max":9999, "min":1 }, + "GenerationStatus":{ + "type":"string", + "enum":[ + "QUEUED", + "IN_PROGRESS", + "COMPLETED", + "ERROR" + ] + }, + "GetAgentContextRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the context.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the context to retrieve.

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "GetAgentContextResponse":{ + "type":"structure", + "required":["context"], + "members":{ + "context":{ + "shape":"ContextSummary", + "documentation":"

    The retrieved context summary.

    " + } + } + }, + "GetAgentGoalRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the goal.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the goal to retrieve.

    ", + "location":"uri", + "locationName":"id" + } + } + }, + "GetAgentGoalResponse":{ + "type":"structure", + "required":["goal"], + "members":{ + "goal":{ + "shape":"GoalSummary", + "documentation":"

    The retrieved goal summary.

    " + } + } + }, + "GetAgentProfileRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile to retrieve.

    ", + "location":"uri", + "locationName":"profileArn" + } + } + }, + "GetAgentProfileResponse":{ + "type":"structure", + "required":[ + "name", + "pillars", + "executionRoleArn", + "aggregationConfiguration", + "arn", + "createdBy", + "createdAt" + ], + "members":{ + "name":{ + "shape":"GetAgentProfileResponseNameString", + "documentation":"

    The system name of the profile.

    " + }, + "displayName":{ + "shape":"GetAgentProfileResponseDisplayNameString", + "documentation":"

    The display name of the profile.

    " + }, + "description":{ + "shape":"GetAgentProfileResponseDescriptionString", + "documentation":"

    A description of the profile.

    " + }, + "businessOverview":{ + "shape":"GetAgentProfileResponseBusinessOverviewString", + "documentation":"

    The business overview of the profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars associated with the profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM execution role.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The aggregation configuration.

    " + }, + "arn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile.

    " + }, + "eligibleForScheduledGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for scheduled recommendation generation.

    " + }, + "eligibleForArchitectureGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for manual architecture generation.

    " + }, + "fieldErrors":{ + "shape":"FieldErrors", + "documentation":"

    A map of field paths to error messages for invalid or missing input fields.

    " + }, + "tags":{ + "shape":"Tags", + "documentation":"

    The tags associated with the profile.

    " + }, + "createdBy":{ + "shape":"GetAgentProfileResponseCreatedByString", + "documentation":"

    The identifier of the user or system that created this profile.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was created.

    " + }, + "lastModifiedBy":{ + "shape":"GetAgentProfileResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this profile.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was last modified.

    " + } + } + }, + "GetAgentProfileResponseBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "GetAgentProfileResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentProfileResponseDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "GetAgentProfileResponseDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "GetAgentProfileResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentProfileResponseNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"[a-zA-Z0-9_-]+" + }, + "GetAgentRecommendationGenerationRequest":{ + "type":"structure", + "required":[ + "profileArn", + "generationId" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The ARN of the optimization profile associated with this generation.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "generationId":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the recommendation generation to retrieve.

    ", + "location":"uri", + "locationName":"generationId" + } + } + }, + "GetAgentRecommendationGenerationResponse":{ + "type":"structure", + "required":[ + "id", + "profileArn", + "status", + "createdBy", + "createdAt" + ], + "members":{ + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the recommendation generation.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile used for this generation.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the recommendation generation.

    " + }, + "status":{ + "shape":"GenerationStatus", + "documentation":"

    The current status of the recommendation generation.

    " + }, + "estimatedCompletionTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The estimated time for the generation to complete.

    " + }, + "createdBy":{ + "shape":"GetAgentRecommendationGenerationResponseCreatedByString", + "documentation":"

    The identifier of the user or system that started this generation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was started.

    " + }, + "lastModifiedBy":{ + "shape":"GetAgentRecommendationGenerationResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this generation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was last modified.

    " + }, + "additionalContext":{ + "shape":"Document", + "documentation":"

    Additional context information provided to guide the recommendation generation process.

    " + }, + "scope":{ + "shape":"Scope", + "documentation":"

    The scope configuration that defines which pillars and goals to focus on during generation.

    " + }, + "startedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation generation process started.

    " + }, + "endedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation generation process completed.

    " + }, + "progress":{ + "shape":"Progress", + "documentation":"

    Current progress information including steps completed and completion percentage.

    " + }, + "errorDetails":{ + "shape":"ErrorDetails", + "documentation":"

    Details about the error if the generation status is ERROR.

    " + } + } + }, + "GetAgentRecommendationGenerationResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentRecommendationGenerationResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentRecommendationRequest":{ + "type":"structure", + "required":["recommendationArn"], + "members":{ + "recommendationArn":{ + "shape":"AgentRecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation to retrieve.

    ", + "location":"uri", + "locationName":"recommendationArn" + }, + "remediationType":{ + "shape":"RemediationType", + "documentation":"

    Optional filter on remediation type.

    ", + "location":"querystring", + "locationName":"remediationType" + } + } + }, + "GetAgentRecommendationResponse":{ + "type":"structure", + "required":[ + "recommendationArn", + "profileArn", + "title", + "description", + "type", + "pillar", + "priority", + "effort", + "status", + "state", + "impact", + "roi", + "impactDetails", + "insights", + "highlights", + "remediationSummary", + "createdBy", + "createdAt" + ], + "members":{ + "recommendationArn":{ + "shape":"RecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated profile.

    " + }, + "title":{ + "shape":"GetAgentRecommendationResponseTitleString", + "documentation":"

    The title of the recommendation.

    " + }, + "description":{ + "shape":"GetAgentRecommendationResponseDescriptionString", + "documentation":"

    A description of the recommendation.

    " + }, + "type":{ + "shape":"RecommendationType", + "documentation":"

    The type of the recommendation.

    " + }, + "pillar":{ + "shape":"Pillar", + "documentation":"

    The Well-Architected Tool Framework pillar that the recommendation addresses.

    " + }, + "priority":{ + "shape":"Priority", + "documentation":"

    The priority of the recommendation.

    " + }, + "effort":{ + "shape":"Effort", + "documentation":"

    The effort required to implement the recommendation.

    " + }, + "status":{ + "shape":"RecommendationStatus", + "documentation":"

    The current status of the recommendation.

    " + }, + "state":{ + "shape":"RecommendationState", + "documentation":"

    The current state of the recommendation.

    " + }, + "updateReason":{ + "shape":"GetAgentRecommendationResponseUpdateReasonString", + "documentation":"

    The free-text reason associated with the recommendation's most recent status update.

    " + }, + "impact":{ + "shape":"ImpactCategory", + "documentation":"

    The severity of the recommendation's impact.

    " + }, + "roi":{ + "shape":"Roi", + "documentation":"

    The return on investment estimate for the recommendation.

    " + }, + "numberOfResources":{ + "shape":"Integer", + "documentation":"

    The number of Amazon Web Services resources this recommendation affects.

    " + }, + "awsServices":{ + "shape":"StringList", + "documentation":"

    The Amazon Web Services services that the recommendation applies to.

    " + }, + "businessUnits":{ + "shape":"StringList", + "documentation":"

    The business units that own the affected resources.

    " + }, + "applications":{ + "shape":"StringList", + "documentation":"

    The applications that the recommendation targets.

    " + }, + "impactDetails":{ + "shape":"ImpactDetails", + "documentation":"

    Detailed impact information for the recommendation.

    " + }, + "insights":{ + "shape":"InsightList", + "documentation":"

    A list of insights about the recommendation.

    " + }, + "highlights":{ + "shape":"Highlights", + "documentation":"

    Highlights describing what was detected.

    " + }, + "remediationSummary":{ + "shape":"RemediationSummary", + "documentation":"

    A high-level summary of the recommended remediation.

    " + }, + "crossPillarBenefits":{ + "shape":"CrossPillarBenefits", + "documentation":"

    Cross-pillar benefits of acting on the recommendation.

    " + }, + "tradeOffs":{ + "shape":"TradeOffs", + "documentation":"

    Trade-offs of acting on the recommendation.

    " + }, + "sources":{ + "shape":"RecommendationSourceList", + "documentation":"

    Sources that generated this recommendation.

    " + }, + "goals":{ + "shape":"RecommendationGoals", + "documentation":"

    Goals that this recommendation targets.

    " + }, + "tags":{ + "shape":"Tags", + "documentation":"

    A set of key-value pairs associated with the recommendation, used for cost allocation and access control.

    " + }, + "createdBy":{ + "shape":"GetAgentRecommendationResponseCreatedByString", + "documentation":"

    The identifier of the user or system that created this recommendation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation was created.

    " + }, + "lastModifiedBy":{ + "shape":"GetAgentRecommendationResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this recommendation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the recommendation was last modified.

    " + }, + "remediations":{ + "shape":"AgentRecommendationRemediations", + "documentation":"

    A list of remediations for the recommendation.

    " + } + } + }, + "GetAgentRecommendationResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentRecommendationResponseDescriptionString":{ + "type":"string", + "max":500, + "min":80, + "sensitive":true + }, + "GetAgentRecommendationResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GetAgentRecommendationResponseTitleString":{ + "type":"string", + "max":120, + "min":3, + "sensitive":true + }, + "GetAgentRecommendationResponseUpdateReasonString":{ + "type":"string", + "max":4096, + "min":1, + "sensitive":true + }, "GetAnswerInput":{ "type":"structure", "required":[ @@ -2545,15 +4829,17 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"GetConsolidatedReportMaxResults", + "shape":"GetConsolidatedReportInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" } } }, - "GetConsolidatedReportMaxResults":{ + "GetConsolidatedReportInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":15, "min":1 }, @@ -2899,12 +5185,96 @@ }, "documentation":"

    Input to get a workload.

    " }, - "GetWorkloadOutput":{ + "GetWorkloadOutput":{ + "type":"structure", + "members":{ + "Workload":{"shape":"Workload"} + }, + "documentation":"

    Output of a get workload call.

    " + }, + "GoalIdList":{ + "type":"list", + "member":{"shape":"UUID"}, + "max":10, + "min":1 + }, + "GoalSummaries":{ + "type":"list", + "member":{"shape":"GoalSummary"} + }, + "GoalSummary":{ "type":"structure", + "required":[ + "id", + "profileArn", + "pillars", + "title", + "createdBy", + "createdAt" + ], "members":{ - "Workload":{"shape":"Workload"} + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the goal.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the associated profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars associated with this goal.

    " + }, + "title":{ + "shape":"GoalSummaryTitleString", + "documentation":"

    The title of the goal.

    " + }, + "description":{ + "shape":"GoalSummaryDescriptionString", + "documentation":"

    A description of the goal.

    " + }, + "createdBy":{ + "shape":"GoalSummaryCreatedByString", + "documentation":"

    The identifier of the user or system that created this goal.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the goal was created.

    " + }, + "lastModifiedBy":{ + "shape":"GoalSummaryLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this goal.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the goal was last modified.

    " + } }, - "documentation":"

    Output of a get workload call.

    " + "documentation":"

    Summary of an optimization goal associated with a profile.

    " + }, + "GoalSummaryCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GoalSummaryDescriptionString":{ + "type":"string", + "max":4000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "GoalSummaryLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "GoalSummaryTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true }, "HelpfulResourceUrl":{ "type":"string", @@ -2912,6 +5282,36 @@ "max":2048, "min":1 }, + "Highlight":{ + "type":"string", + "max":250, + "min":20 + }, + "Highlights":{ + "type":"list", + "member":{"shape":"Highlight"}, + "max":5, + "min":1 + }, + "ImpactCategory":{ + "type":"string", + "enum":[ + "HIGH", + "MEDIUM", + "LOW" + ] + }, + "ImpactDetail":{ + "type":"string", + "max":100, + "min":10 + }, + "ImpactDetails":{ + "type":"list", + "member":{"shape":"ImpactDetail"}, + "max":3, + "min":2 + }, "ImportLensInput":{ "type":"structure", "required":[ @@ -2957,7 +5357,7 @@ }, "ImprovementPlanUrl":{ "type":"string", - "documentation":"

    The improvement plan URL for a question in an Amazon Web Services official lenses.

    This value is only available if the question has been answered.

    This value does not apply to custom lenses.

    ", + "documentation":"

    The improvement plan URL for a question in an Amazon Web Services official lenses.

    This value is only available if the question has been answered.

    ", "max":2048, "min":1 }, @@ -2976,7 +5376,7 @@ "ImprovementPlanUrl":{"shape":"ImprovementPlanUrl"}, "ImprovementPlans":{ "shape":"ChoiceImprovementPlans", - "documentation":"

    The improvement plan details.

    " + "documentation":"

    The improvement plan details.

    This value is only applicable to custom lenses.

    " }, "JiraConfiguration":{ "shape":"JiraConfiguration", @@ -2985,7 +5385,45 @@ }, "documentation":"

    An improvement summary of a lens review in a workload.

    " }, - "IncludeSharedResources":{"type":"boolean"}, + "IncludeSharedResources":{ + "type":"boolean", + "box":true + }, + "Insight":{ + "type":"structure", + "required":["usagePattern"], + "members":{ + "usagePattern":{ + "shape":"InsightUsagePatternString", + "documentation":"

    A description of the usage pattern.

    " + }, + "signalsDetected":{ + "shape":"InsightSignalsDetectedString", + "documentation":"

    A description of the signals detected.

    " + } + }, + "documentation":"

    An insight describing a usage pattern and the signals detected.

    " + }, + "InsightList":{ + "type":"list", + "member":{"shape":"Insight"}, + "max":5, + "min":1 + }, + "InsightSignalsDetectedString":{ + "type":"string", + "max":1500, + "min":30 + }, + "InsightUsagePatternString":{ + "type":"string", + "max":2000, + "min":100 + }, + "Integer":{ + "type":"integer", + "box":true + }, "IntegratingService":{ "type":"string", "enum":["JIRA"] @@ -3014,10 +5452,17 @@ }, "IsApplicable":{ "type":"boolean", - "documentation":"

    Defines whether this question is applicable to a lens review.

    " + "documentation":"

    Defines whether this question is applicable to a lens review.

    ", + "box":true + }, + "IsMajorVersion":{ + "type":"boolean", + "box":true + }, + "IsReviewOwnerUpdateAcknowledged":{ + "type":"boolean", + "box":true }, - "IsMajorVersion":{"type":"boolean"}, - "IsReviewOwnerUpdateAcknowledged":{"type":"boolean"}, "IssueManagementType":{ "type":"string", "enum":[ @@ -3025,6 +5470,16 @@ "MANUAL" ] }, + "ItemId":{ + "type":"string", + "max":2048, + "min":1 + }, + "ItemIds":{ + "type":"list", + "member":{"shape":"ItemId"}, + "min":1 + }, "JiraConfiguration":{ "type":"structure", "members":{ @@ -3032,7 +5487,10 @@ "shape":"JiraIssueUrl", "documentation":"

    The URL of the associated Jira issue.

    " }, - "LastSyncedTime":{"shape":"Timestamp"} + "LastSyncedTime":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the Jira configuration was last synced.

    " + } }, "documentation":"

    Configuration of the Jira integration.

    " }, @@ -3045,7 +5503,7 @@ "type":"string", "max":100, "min":1, - "pattern":"^[A-Z][A-Z0-9_]*$" + "pattern":"[A-Z][A-Z0-9_]*" }, "JiraSelectedQuestionConfiguration":{ "type":"structure", @@ -3136,7 +5594,8 @@ }, "LensNamePrefix":{ "type":"string", - "max":100 + "max":100, + "min":0 }, "LensOwner":{"type":"string"}, "LensReview":{ @@ -3161,7 +5620,10 @@ "shape":"JiraSelectedQuestionConfiguration", "documentation":"

    Jira configuration status of the Lens review.

    " }, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the lens review was last updated.

    " + }, "Notes":{"shape":"Notes"}, "RiskCounts":{"shape":"RiskCounts"}, "NextToken":{"shape":"NextToken"}, @@ -3207,7 +5669,10 @@ "shape":"LensStatus", "documentation":"

    The status of the lens.

    " }, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the lens review was last updated.

    " + }, "RiskCounts":{"shape":"RiskCounts"}, "Profiles":{ "shape":"WorkloadProfiles", @@ -3271,8 +5736,14 @@ "documentation":"

    The type of the lens.

    " }, "Description":{"shape":"LensDescription"}, - "CreatedAt":{"shape":"Timestamp"}, - "UpdatedAt":{"shape":"Timestamp"}, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the lens was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the lens was last updated.

    " + }, "LensVersion":{ "shape":"LensVersion", "documentation":"

    The version of the lens.

    " @@ -3319,14 +5790,369 @@ }, "documentation":"

    Lens upgrade summary return object.

    " }, - "LensVersion":{ + "LensVersion":{ + "type":"string", + "max":32, + "min":1 + }, + "LensesAppliedCount":{ + "type":"integer", + "box":true, + "min":0 + }, + "ListAgentContextsRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile to list contexts for.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "maxResults":{ + "shape":"ListAgentContextsRequestMaxResultsInteger", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListAgentContextsRequestNextTokenString", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAgentContextsRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentContextsRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentContextsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"ContextSummaries", + "documentation":"

    A list of context summaries associated with the profile.

    " + }, + "nextToken":{"shape":"ListAgentContextsResponseNextTokenString"} + } + }, + "ListAgentContextsResponseNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentGoalsRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile to list goals for.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "maxResults":{ + "shape":"ListAgentGoalsRequestMaxResultsInteger", + "documentation":"

    The maximum number of goals to return in a single response.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListAgentGoalsRequestNextTokenString", + "documentation":"

    A pagination token returned from a previous call to continue retrieving results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAgentGoalsRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentGoalsRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentGoalsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"GoalSummaries", + "documentation":"

    A list of goal summaries associated with the profile.

    " + }, + "nextToken":{ + "shape":"ListAgentGoalsResponseNextTokenString", + "documentation":"

    A pagination token to retrieve the next set of results, if available.

    " + } + } + }, + "ListAgentGoalsResponseNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentProfilesRequest":{ + "type":"structure", + "members":{ + "maxResults":{ + "shape":"ListAgentProfilesRequestMaxResultsInteger", + "documentation":"

    The maximum number of profiles to return in a single call. Default is 100.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListAgentProfilesRequestNextTokenString", + "documentation":"

    A pagination token returned from a previous call to continue retrieving results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAgentProfilesRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentProfilesRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentProfilesResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AgentProfileSummaries", + "documentation":"

    A list of profile summaries.

    " + }, + "nextToken":{ + "shape":"ListAgentProfilesResponseNextTokenString", + "documentation":"

    A pagination token to retrieve the next set of results, if available.

    " + } + } + }, + "ListAgentProfilesResponseNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationGenerationsRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile to list generation processes for.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "recommendationType":{ + "shape":"RecommendationType", + "documentation":"

    Optional filter by recommendation type.

    ", + "location":"querystring", + "locationName":"RecommendationType" + }, + "maxResults":{ + "shape":"ListAgentRecommendationGenerationsRequestMaxResultsInteger", + "documentation":"

    The maximum number of generation processes to return in a single response.

    ", + "location":"querystring", + "locationName":"MaxResults" + }, + "nextToken":{ + "shape":"ListAgentRecommendationGenerationsRequestNextTokenString", + "documentation":"

    A pagination token returned from a previous call to continue retrieving results.

    ", + "location":"querystring", + "locationName":"NextToken" + } + } + }, + "ListAgentRecommendationGenerationsRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentRecommendationGenerationsRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationGenerationsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AgentRecommendationGenerationSummaries", + "documentation":"

    A list of recommendation generation summaries.

    " + }, + "nextToken":{ + "shape":"ListAgentRecommendationGenerationsResponseNextTokenString", + "documentation":"

    A pagination token to retrieve the next set of results, if available.

    " + } + } + }, + "ListAgentRecommendationGenerationsResponseNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationItemsRequest":{ + "type":"structure", + "required":["recommendationArn"], + "members":{ + "recommendationArn":{ + "shape":"AgentRecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation to list items for.

    ", + "location":"uri", + "locationName":"recommendationArn" + }, + "type":{ + "shape":"RecommendationItemType", + "documentation":"

    Optional filter to return only recommendation items of the specified type.

    ", + "location":"querystring", + "locationName":"type" + }, + "maxResults":{ + "shape":"ListAgentRecommendationItemsRequestMaxResultsInteger", + "documentation":"

    The maximum number of recommendation items to return in a single response.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListAgentRecommendationItemsRequestNextTokenString", + "documentation":"

    A pagination token returned from a previous call to continue retrieving results.

    ", + "location":"querystring", + "locationName":"nextToken" + } + } + }, + "ListAgentRecommendationItemsRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentRecommendationItemsRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationItemsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AgentRecommendationItemSummaries", + "documentation":"

    A list of recommendation items with their detailed metadata and configuration information.

    " + }, + "nextToken":{ + "shape":"ListAgentRecommendationItemsResponseNextTokenString", + "documentation":"

    A pagination token to retrieve the next set of results, if available.

    " + } + } + }, + "ListAgentRecommendationItemsResponseNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationsRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile to list recommendations for.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "maxResults":{ + "shape":"ListAgentRecommendationsRequestMaxResultsInteger", + "documentation":"

    The maximum number of recommendations to return in a single response.

    ", + "location":"querystring", + "locationName":"maxResults" + }, + "nextToken":{ + "shape":"ListAgentRecommendationsRequestNextTokenString", + "documentation":"

    A pagination token returned from a previous call to continue retrieving results.

    ", + "location":"querystring", + "locationName":"nextToken" + }, + "state":{ + "shape":"RecommendationState", + "documentation":"

    Optional filter to return only recommendations with the specified state (OPEN or CLOSED).

    ", + "location":"querystring", + "locationName":"state" + }, + "pillar":{ + "shape":"Pillar", + "documentation":"

    Optional filter to return only recommendations for the specified pillar.

    ", + "location":"querystring", + "locationName":"pillar" + } + } + }, + "ListAgentRecommendationsRequestMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":1000, + "min":1 + }, + "ListAgentRecommendationsRequestNextTokenString":{ + "type":"string", + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" + }, + "ListAgentRecommendationsResponse":{ + "type":"structure", + "required":["items"], + "members":{ + "items":{ + "shape":"AgentRecommendationSummaries", + "documentation":"

    A list of recommendation summaries.

    " + }, + "nextToken":{ + "shape":"ListAgentRecommendationsResponseNextTokenString", + "documentation":"

    A pagination token to retrieve the next set of results, if available.

    " + } + } + }, + "ListAgentRecommendationsResponseNextTokenString":{ "type":"string", - "max":32, - "min":1 - }, - "LensesAppliedCount":{ - "type":"integer", - "min":0 + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "min":1, + "pattern":"[A-Za-z0-9+\\/=_-]+" }, "ListAnswersInput":{ "type":"structure", @@ -3361,7 +6187,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListAnswersMaxResults", + "shape":"ListAnswersInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -3375,8 +6201,10 @@ }, "documentation":"

    Input to list answers.

    " }, - "ListAnswersMaxResults":{ + "ListAnswersInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -3411,7 +6239,7 @@ "locationName":"WorkloadId" }, "NextToken":{"shape":"NextToken"}, - "MaxResults":{"shape":"MaxResults"}, + "MaxResults":{"shape":"ListCheckDetailsInputMaxResultsInteger"}, "LensArn":{ "shape":"LensArn", "documentation":"

    Well-Architected Lens ARN.

    " @@ -3421,6 +6249,13 @@ "ChoiceId":{"shape":"ChoiceId"} } }, + "ListCheckDetailsInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListCheckDetailsOutput":{ "type":"structure", "members":{ @@ -3447,7 +6282,7 @@ "locationName":"WorkloadId" }, "NextToken":{"shape":"NextToken"}, - "MaxResults":{"shape":"MaxResults"}, + "MaxResults":{"shape":"ListCheckSummariesInputMaxResultsInteger"}, "LensArn":{ "shape":"LensArn", "documentation":"

    Well-Architected Lens ARN.

    " @@ -3457,6 +6292,13 @@ "ChoiceId":{"shape":"ChoiceId"} } }, + "ListCheckSummariesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListCheckSummariesOutput":{ "type":"structure", "members":{ @@ -3500,7 +6342,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListLensReviewImprovementsMaxResults", + "shape":"ListLensReviewImprovementsInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -3514,8 +6356,10 @@ }, "documentation":"

    Input to list lens review improvements.

    " }, - "ListLensReviewImprovementsMaxResults":{ + "ListLensReviewImprovementsInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":100, "min":1 }, @@ -3554,13 +6398,20 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"MaxResults", + "shape":"ListLensReviewsInputMaxResultsInteger", "location":"querystring", "locationName":"MaxResults" } }, "documentation":"

    Input to list lens reviews.

    " }, + "ListLensReviewsInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListLensReviewsOutput":{ "type":"structure", "members":{ @@ -3592,7 +6443,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListWorkloadSharesMaxResults", + "shape":"ListLensSharesInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -3604,6 +6455,13 @@ } } }, + "ListLensSharesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListLensSharesOutput":{ "type":"structure", "members":{ @@ -3623,7 +6481,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"MaxResults", + "shape":"ListLensesInputMaxResultsInteger", "location":"querystring", "locationName":"MaxResults" }, @@ -3647,6 +6505,13 @@ }, "documentation":"

    Input to list lenses.

    " }, + "ListLensesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListLensesOutput":{ "type":"structure", "members":{ @@ -3665,10 +6530,17 @@ "locationName":"WorkloadId" }, "NextToken":{"shape":"NextToken"}, - "MaxResults":{"shape":"MaxResults"} + "MaxResults":{"shape":"ListMilestonesInputMaxResultsInteger"} }, "documentation":"

    Input to list all milestones for a workload.

    " }, + "ListMilestonesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListMilestonesOutput":{ "type":"structure", "members":{ @@ -3684,7 +6556,7 @@ "WorkloadId":{"shape":"WorkloadId"}, "NextToken":{"shape":"NextToken"}, "MaxResults":{ - "shape":"ListNotificationsMaxResults", + "shape":"ListNotificationsInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    " }, "ResourceArn":{ @@ -3693,8 +6565,10 @@ } } }, - "ListNotificationsMaxResults":{ + "ListNotificationsInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -3722,12 +6596,19 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"MaxResults", + "shape":"ListProfileNotificationsInputMaxResultsInteger", "location":"querystring", "locationName":"MaxResults" } } }, + "ListProfileNotificationsInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListProfileNotificationsOutput":{ "type":"structure", "members":{ @@ -3760,7 +6641,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListProfileSharesMaxResults", + "shape":"ListProfileSharesInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -3772,8 +6653,10 @@ } } }, - "ListProfileSharesMaxResults":{ + "ListProfileSharesInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -3808,12 +6691,19 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"MaxResults", + "shape":"ListProfilesInputMaxResultsInteger", "location":"querystring", "locationName":"MaxResults" } } }, + "ListProfilesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListProfilesOutput":{ "type":"structure", "members":{ @@ -3853,15 +6743,17 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListReviewTemplateAnswersMaxResults", + "shape":"ListReviewTemplateAnswersInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" } } }, - "ListReviewTemplateAnswersMaxResults":{ + "ListReviewTemplateAnswersInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -3889,12 +6781,19 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"MaxResults", + "shape":"ListReviewTemplatesInputMaxResultsInteger", "location":"querystring", "locationName":"MaxResults" } } }, + "ListReviewTemplatesInputMaxResultsInteger":{ + "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, + "max":50, + "min":1 + }, "ListReviewTemplatesOutput":{ "type":"structure", "members":{ @@ -3931,7 +6830,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListShareInvitationsMaxResults", + "shape":"ListShareInvitationsInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -3951,8 +6850,10 @@ }, "documentation":"

    Input for List Share Invitations

    " }, - "ListShareInvitationsMaxResults":{ + "ListShareInvitationsInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -4009,7 +6910,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListTemplateSharesMaxResults", + "shape":"ListTemplateSharesInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -4021,8 +6922,10 @@ } } }, - "ListTemplateSharesMaxResults":{ + "ListTemplateSharesInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -4061,7 +6964,7 @@ "locationName":"NextToken" }, "MaxResults":{ - "shape":"ListWorkloadSharesMaxResults", + "shape":"ListWorkloadSharesInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    ", "location":"querystring", "locationName":"MaxResults" @@ -4074,8 +6977,10 @@ }, "documentation":"

    Input for List Workload Share

    " }, - "ListWorkloadSharesMaxResults":{ + "ListWorkloadSharesInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -4094,14 +6999,16 @@ "WorkloadNamePrefix":{"shape":"WorkloadNamePrefix"}, "NextToken":{"shape":"NextToken"}, "MaxResults":{ - "shape":"ListWorkloadsMaxResults", + "shape":"ListWorkloadsInputMaxResultsInteger", "documentation":"

    The maximum number of results to return for this request.

    " } }, "documentation":"

    Input to list all workloads.

    " }, - "ListWorkloadsMaxResults":{ + "ListWorkloadsInputMaxResultsInteger":{ "type":"integer", + "documentation":"

    The maximum number of results to return for this request.

    ", + "box":true, "max":50, "min":1 }, @@ -4113,14 +7020,9 @@ }, "documentation":"

    Output of a list workloads call.

    " }, - "MaxResults":{ - "type":"integer", - "documentation":"

    The maximum number of results to return for this request.

    ", - "max":50, - "min":1 - }, "MaxSelectedProfileChoices":{ "type":"integer", + "box":true, "min":0 }, "MetricType":{ @@ -4132,7 +7034,10 @@ "members":{ "MilestoneNumber":{"shape":"MilestoneNumber"}, "MilestoneName":{"shape":"MilestoneName"}, - "RecordedAt":{"shape":"Timestamp"}, + "RecordedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the milestone was recorded.

    " + }, "Workload":{"shape":"Workload"} }, "documentation":"

    A milestone return object.

    " @@ -4146,6 +7051,7 @@ "MilestoneNumber":{ "type":"integer", "documentation":"

    The milestone number.

    A workload can have a maximum of 100 milestones.

    ", + "box":true, "max":100, "min":1 }, @@ -4159,23 +7065,29 @@ "members":{ "MilestoneNumber":{"shape":"MilestoneNumber"}, "MilestoneName":{"shape":"MilestoneName"}, - "RecordedAt":{"shape":"Timestamp"}, + "RecordedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the milestone was recorded.

    " + }, "WorkloadSummary":{"shape":"WorkloadSummary"} }, "documentation":"

    A milestone summary return object.

    " }, "MinSelectedProfileChoices":{ "type":"integer", + "box":true, "min":0 }, "NextToken":{ "type":"string", - "documentation":"

    The token to use to retrieve the next set of results.

    " + "documentation":"

    The token to use to retrieve the next set of results.

    ", + "pattern":"[A-Za-z0-9+\\/=_-]+" }, "Notes":{ "type":"string", "documentation":"

    The notes associated with the workload.

    For a review template, these are the notes that will be associated with the workload when the template is applied.

    ", - "max":2084 + "max":2084, + "min":0 }, "NotificationSummaries":{ "type":"list", @@ -4217,6 +7129,16 @@ "CONTRIBUTOR" ] }, + "Pillar":{ + "type":"string", + "enum":[ + "COST_OPTIMIZATION", + "SECURITY", + "RESILIENCE", + "PERFORMANCE", + "OPERATIONAL_EXCELLENCE" + ] + }, "PillarDifference":{ "type":"structure", "members":{ @@ -4243,6 +7165,28 @@ "max":64, "min":1 }, + "PillarItem":{ + "type":"structure", + "required":[ + "pillar", + "ids" + ], + "members":{ + "pillar":{ + "shape":"Pillar", + "documentation":"

    The pillar this item configuration applies to.

    " + }, + "ids":{ + "shape":"ItemIds", + "documentation":"

    A list of item IDs to process for this pillar, such as best practice IDs, Amazon Web Services service names, or resource ARNs.

    " + } + }, + "documentation":"

    Item configuration for a specific Well-Architected Tool Framework pillar.

    " + }, + "PillarItems":{ + "type":"list", + "member":{"shape":"PillarItem"} + }, "PillarMetric":{ "type":"structure", "members":{ @@ -4287,6 +7231,20 @@ }, "documentation":"

    A pillar review summary of a lens review.

    " }, + "Pillars":{ + "type":"list", + "member":{"shape":"Pillar"}, + "max":5, + "min":1 + }, + "Priority":{ + "type":"string", + "enum":[ + "HIGH", + "MEDIUM", + "LOW" + ] + }, "Profile":{ "type":"structure", "members":{ @@ -4311,8 +7269,14 @@ "documentation":"

    Profile questions.

    " }, "Owner":{"shape":"AwsAccountId"}, - "CreatedAt":{"shape":"Timestamp"}, - "UpdatedAt":{"shape":"Timestamp"}, + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile was last updated.

    " + }, "ShareInvitationId":{ "shape":"ShareInvitationId", "documentation":"

    The ID assigned to the share invitation.

    " @@ -4327,6 +7291,7 @@ "ProfileArn":{ "type":"string", "max":2084, + "min":0, "pattern":"arn:aws[-a-z]*:wellarchitected:[a-z]{2}(-gov)?-[a-z]+-\\d:\\d{12}:profile/[a-z0-9]+" }, "ProfileArns":{ @@ -4355,7 +7320,8 @@ }, "ProfileNamePrefix":{ "type":"string", - "max":100 + "max":100, + "min":0 }, "ProfileNotificationSummaries":{ "type":"list", @@ -4492,8 +7458,14 @@ "documentation":"

    The profile description.

    " }, "Owner":{"shape":"AwsAccountId"}, - "CreatedAt":{"shape":"Timestamp"}, - "UpdatedAt":{"shape":"Timestamp"} + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile was last updated.

    " + } }, "documentation":"

    Summary of a profile.

    " }, @@ -4508,8 +7480,14 @@ "shape":"TemplateQuestions", "documentation":"

    Profile template questions.

    " }, - "CreatedAt":{"shape":"Timestamp"}, - "UpdatedAt":{"shape":"Timestamp"} + "CreatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile template was created.

    " + }, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the profile template was last updated.

    " + } }, "documentation":"

    The profile template.

    " }, @@ -4551,7 +7529,67 @@ "type":"string", "max":32, "min":1, - "pattern":"^[A-Za-z0-9-]+$" + "pattern":"[A-Za-z0-9-]+" + }, + "Progress":{ + "type":"structure", + "required":[ + "stepsCompleted", + "totalSteps", + "completionPercentage" + ], + "members":{ + "stepsCompleted":{ + "shape":"Integer", + "documentation":"

    The number of generation steps that have been completed.

    " + }, + "totalSteps":{ + "shape":"Integer", + "documentation":"

    The total number of steps in the generation process.

    " + }, + "completionPercentage":{ + "shape":"Double", + "documentation":"

    The completion percentage of the generation process (0-100).

    " + } + }, + "documentation":"

    Progress information for a recommendation generation process.

    " + }, + "PutAgentRecommendationFeedbackRequest":{ + "type":"structure", + "required":[ + "recommendationArn", + "type" + ], + "members":{ + "recommendationArn":{ + "shape":"AgentRecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation to provide feedback for.

    ", + "location":"uri", + "locationName":"recommendationArn" + }, + "type":{ + "shape":"RecommendationFeedbackType", + "documentation":"

    The type of feedback being provided.

    " + }, + "feedbackCategory":{ + "shape":"FeedbackCategory", + "documentation":"

    Optional category classifying the nature of the feedback.

    " + }, + "comments":{ + "shape":"PutAgentRecommendationFeedbackRequestCommentsString", + "documentation":"

    Optional comments providing additional context about the feedback.

    " + } + } + }, + "PutAgentRecommendationFeedbackRequestCommentsString":{ + "type":"string", + "max":4096, + "min":1, + "pattern":"[\\P{C}]+" + }, + "PutAgentRecommendationFeedbackResponse":{ + "type":"structure", + "members":{} }, "Question":{ "type":"string", @@ -4633,6 +7671,175 @@ "type":"string", "documentation":"

    Service Quotas requirement to identify originating quota.

    " }, + "RecommendationArn":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:aws([a-z0-9-]+)?:wellarchitected:[a-z0-9-]{6,64}:\\d{12}:agent-recommendation/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, + "RecommendationFeedbackType":{ + "type":"string", + "enum":[ + "USEFUL", + "NOT_USEFUL" + ] + }, + "RecommendationGoal":{ + "type":"structure", + "required":["title"], + "members":{ + "title":{ + "shape":"String", + "documentation":"

    The title of the goal associated with the recommendation.

    " + } + }, + "documentation":"

    Contains information about a goal associated with a recommendation.

    " + }, + "RecommendationGoals":{ + "type":"list", + "member":{"shape":"RecommendationGoal"} + }, + "RecommendationItemType":{ + "type":"string", + "enum":[ + "AWS_RESOURCE", + "RECOMMENDATION" + ] + }, + "RecommendationSource":{ + "type":"string", + "enum":[ + "TRUSTED_ADVISOR", + "COST_EXPLORER", + "CLOUDWATCH", + "WELL_ARCHITECTED_TOOL", + "WELL_ARCHITECTED_AGENT", + "CUSTOMER_IAC" + ] + }, + "RecommendationSourceList":{ + "type":"list", + "member":{"shape":"RecommendationSource"} + }, + "RecommendationState":{ + "type":"string", + "enum":[ + "OPEN", + "CLOSED" + ] + }, + "RecommendationStatus":{ + "type":"string", + "enum":[ + "ACTIVE", + "SUPPRESSED", + "COMPLETED" + ] + }, + "RecommendationType":{ + "type":"string", + "enum":[ + "RESOURCE", + "ARCHITECTURE", + "APPLICATION" + ] + }, + "RecommendationTypes":{ + "type":"list", + "member":{"shape":"RecommendationType"}, + "max":1, + "min":1 + }, + "RecommendedFixStep":{ + "type":"string", + "max":200, + "min":20 + }, + "RecommendedFixSteps":{ + "type":"list", + "member":{"shape":"RecommendedFixStep"}, + "max":5, + "min":1 + }, + "Region":{ + "type":"string", + "max":64, + "min":0, + "pattern":"[a-z]{2}-[a-z]+-\\d{1}" + }, + "Regions":{ + "type":"list", + "member":{"shape":"Region"}, + "max":25, + "min":0 + }, + "RemediationStep":{ + "type":"structure", + "required":["content"], + "members":{ + "title":{ + "shape":"RemediationStepTitleString", + "documentation":"

    An optional short label for the step.

    " + }, + "content":{ + "shape":"RemediationStepContentString", + "documentation":"

    The content describing the step, which can include code examples and verification checklists.

    " + } + }, + "documentation":"

    One step within a remediation procedure.

    " + }, + "RemediationStepContentString":{ + "type":"string", + "max":8000, + "min":80, + "sensitive":true + }, + "RemediationStepTitleString":{ + "type":"string", + "max":80, + "min":3, + "sensitive":true + }, + "RemediationSteps":{ + "type":"list", + "member":{"shape":"RemediationStep"}, + "max":10, + "min":1 + }, + "RemediationSummary":{ + "type":"structure", + "required":[ + "recommendation", + "steps" + ], + "members":{ + "recommendation":{ + "shape":"RemediationSummaryRecommendationString", + "documentation":"

    A short imperative statement of the recommended action.

    " + }, + "steps":{ + "shape":"RecommendedFixSteps", + "documentation":"

    High-level steps to implement the fix.

    " + } + }, + "documentation":"

    A high-level remediation summary returned in the detail response.

    " + }, + "RemediationSummaryRecommendationString":{ + "type":"string", + "max":240, + "min":80 + }, + "RemediationType":{ + "type":"string", + "enum":[ + "AUTO_REMEDIATION", + "CONSOLE", + "CLI", + "SDK", + "IAC", + "MCP" + ] + }, "ReportFormat":{ "type":"string", "enum":[ @@ -4646,6 +7853,37 @@ "min":50, "pattern":"arn:aws(-us-gov|-iso(-[a-z])?|-cn)?:wellarchitected:[a-z]{2}(-gov|-iso([a-z])?)?-[a-z]+-\\d:\\d{12}:(review-template)/[a-f0-9]{32}" }, + "ResourceLink":{ + "type":"structure", + "required":["url"], + "members":{ + "url":{ + "shape":"ResourceLinkUrlString", + "documentation":"

    The URL of the external reference.

    " + }, + "title":{ + "shape":"ResourceLinkTitleString", + "documentation":"

    An optional human-readable title for the link.

    " + } + }, + "documentation":"

    An external reference associated with remediation steps.

    " + }, + "ResourceLinkTitleString":{ + "type":"string", + "max":100, + "min":3 + }, + "ResourceLinkUrlString":{ + "type":"string", + "max":500, + "min":10 + }, + "ResourceLinks":{ + "type":"list", + "member":{"shape":"ResourceLink"}, + "max":10, + "min":0 + }, "ResourceNotFoundException":{ "type":"structure", "required":[ @@ -4659,7 +7897,10 @@ "ResourceType":{"shape":"ExceptionResourceType"} }, "documentation":"

    The requested resource was not found.

    ", - "error":{"httpStatusCode":404}, + "error":{ + "httpStatusCode":404, + "senderFault":true + }, "exception":true }, "ReviewTemplate":{ @@ -4679,7 +7920,10 @@ "documentation":"

    A count of how many total questions are answered and unanswered in the review template.

    " }, "Owner":{"shape":"AwsAccountId"}, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the review template was last updated.

    " + }, "TemplateArn":{ "shape":"TemplateArn", "documentation":"

    The review template ARN.

    " @@ -4777,7 +8021,8 @@ "ReviewTemplateArns":{ "type":"list", "member":{"shape":"TemplateArn"}, - "max":1 + "max":1, + "min":0 }, "ReviewTemplateLensAliases":{ "type":"list", @@ -4806,7 +8051,10 @@ "shape":"ReviewTemplatePillarReviewSummaries", "documentation":"

    Pillar review summaries of a lens review.

    " }, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the review template lens review was last updated.

    " + }, "Notes":{"shape":"Notes"}, "QuestionCounts":{ "shape":"QuestionCounts", @@ -4849,7 +8097,10 @@ "documentation":"

    Lenses associated with the review template.

    " }, "Owner":{"shape":"AwsAccountId"}, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the review template was last updated.

    " + }, "TemplateArn":{ "shape":"TemplateArn", "documentation":"

    The review template ARN.

    " @@ -4893,6 +8144,64 @@ "value":{"shape":"Count"}, "documentation":"

    A map from risk names to the count of how many questions have that rating.

    " }, + "RiskRating":{ + "type":"string", + "enum":[ + "LOW", + "MEDIUM", + "HIGH" + ] + }, + "Roi":{ + "type":"structure", + "required":["detail"], + "members":{ + "estimate":{ + "shape":"RoiEstimateString", + "documentation":"

    A short statistic or key metric. Optional when there is no quantifiable figure.

    " + }, + "detail":{ + "shape":"RoiDetailString", + "documentation":"

    A sentence providing context for the estimate.

    " + } + }, + "documentation":"

    A return-on-investment estimate with context.

    " + }, + "RoiDetailString":{ + "type":"string", + "max":300, + "min":30 + }, + "RoiEstimateString":{ + "type":"string", + "max":40, + "min":2 + }, + "RoleArn":{ + "type":"string", + "max":2048, + "min":0, + "pattern":"arn:([a-z\\-]+):iam::\\d{12}:role/(service-role/)?[a-zA-Z0-9+=,.@\\-_]+" + }, + "Scope":{ + "type":"structure", + "required":["pillars"], + "members":{ + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars to include in the generation scope.

    " + }, + "goalIds":{ + "shape":"GoalIdList", + "documentation":"

    Specific goal IDs to focus on during recommendation generation.

    " + }, + "items":{ + "shape":"PillarItems", + "documentation":"

    Optional per-pillar item filtering configuration.

    " + } + }, + "documentation":"

    Defines the scope for recommendation generation, specifying which pillars and goals to focus on.

    " + }, "SelectedChoiceIds":{ "type":"list", "member":{"shape":"ChoiceId"} @@ -4945,7 +8254,10 @@ "ServiceCode":{"shape":"ServiceCode"} }, "documentation":"

    The user has reached their resource quota.

    ", - "error":{"httpStatusCode":402}, + "error":{ + "httpStatusCode":402, + "senderFault":true + }, "exception":true }, "ShareId":{ @@ -5068,22 +8380,147 @@ }, "SharedWithPrefix":{ "type":"string", - "max":100 + "max":100, + "min":0 + }, + "StartAgentRecommendationGenerationRequest":{ + "type":"structure", + "required":[ + "profileArn", + "types", + "scope" + ], + "members":{ + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the optimization profile to use for generating recommendations.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "types":{ + "shape":"RecommendationTypes", + "documentation":"

    The types of recommendations to generate.

    " + }, + "name":{ + "shape":"StartAgentRecommendationGenerationRequestNameString", + "documentation":"

    An optional name for this generation process to help identify it in lists and logs.

    " + }, + "additionalContext":{ + "shape":"Document", + "documentation":"

    Optional additional context to guide the recommendation generation, such as specific business requirements or constraints.

    " + }, + "scope":{ + "shape":"Scope", + "documentation":"

    Scope configuration to focus the generation on specific pillars or goals.

    " + } + } + }, + "StartAgentRecommendationGenerationRequestNameString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[A-Za-z0-9_-]+" + }, + "StartAgentRecommendationGenerationResponse":{ + "type":"structure", + "required":[ + "id", + "profileArn", + "status", + "createdBy", + "createdAt" + ], + "members":{ + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the recommendation generation.

    " + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile used for this generation.

    " + }, + "name":{ + "shape":"String", + "documentation":"

    The name of the recommendation generation.

    " + }, + "status":{ + "shape":"GenerationStatus", + "documentation":"

    The current status of the recommendation generation.

    " + }, + "estimatedCompletionTime":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The estimated time for the generation to complete.

    " + }, + "createdBy":{ + "shape":"StartAgentRecommendationGenerationResponseCreatedByString", + "documentation":"

    The identifier of the user or system that started this generation.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was started.

    " + }, + "lastModifiedBy":{ + "shape":"StartAgentRecommendationGenerationResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this generation.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the generation was last modified.

    " + } + } + }, + "StartAgentRecommendationGenerationResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "StartAgentRecommendationGenerationResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 }, "StatusMessage":{ "type":"string", "max":512, "min":1 }, + "String":{"type":"string"}, + "StringList":{ + "type":"list", + "member":{"shape":"String"} + }, "Subdomain":{ "type":"string", "max":100, "min":1 }, + "SyntheticTimestamp_date_time":{ + "type":"timestamp", + "timestampFormat":"iso8601" + }, + "Tag":{ + "type":"structure", + "required":[ + "key", + "value" + ], + "members":{ + "key":{ + "shape":"TagKeyString", + "documentation":"

    The key of the tag.

    " + }, + "value":{ + "shape":"TagValueString", + "documentation":"

    The value of the tag.

    " + } + }, + "documentation":"

    A key-value pair associated with a resource for cost allocation and access control.

    " + }, "TagKey":{ "type":"string", "max":128, - "min":1 + "min":1, + "pattern":"(?!aws:)[\\p{L}\\p{N}\\p{Z}_.:/=+@-]+" }, "TagKeyList":{ "type":"list", @@ -5091,6 +8528,12 @@ "max":50, "min":1 }, + "TagKeyString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+" + }, "TagMap":{ "type":"map", "key":{"shape":"TagKey"}, @@ -5125,6 +8568,16 @@ "max":256, "min":0 }, + "TagValueString":{ + "type":"string", + "max":256, + "min":1, + "pattern":"[\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+" + }, + "Tags":{ + "type":"list", + "member":{"shape":"Tag"} + }, "TemplateArn":{ "type":"string", "max":250, @@ -5135,18 +8588,19 @@ "type":"string", "max":250, "min":3, - "pattern":"^[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+$" + "pattern":"[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+" }, "TemplateName":{ "type":"string", "max":100, "min":3, - "pattern":"^[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+$" + "pattern":"[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+" }, "TemplateNamePrefix":{ "type":"string", "max":100, - "pattern":"^[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+$" + "min":0, + "pattern":"[A-Za-z0-9-_.,:/()@!&?#+'’\\s]+" }, "TemplateQuestions":{ "type":"list", @@ -5178,12 +8632,73 @@ "ServiceCode":{"shape":"ServiceCode"} }, "documentation":"

    Request was denied due to request throttling.

    ", - "error":{"httpStatusCode":429}, + "error":{ + "httpStatusCode":429, + "senderFault":true + }, "exception":true }, - "Timestamp":{ - "type":"timestamp", - "documentation":"

    The date and time recorded.

    " + "Timestamp":{"type":"timestamp"}, + "TradeOff":{ + "type":"structure", + "required":[ + "pillar", + "title", + "description", + "risk", + "mitigation" + ], + "members":{ + "pillar":{ + "shape":"Pillar", + "documentation":"

    The pillar that could be negatively impacted.

    " + }, + "title":{ + "shape":"TradeOffTitleString", + "documentation":"

    A short phrase describing what is lost or degraded.

    " + }, + "description":{ + "shape":"TradeOffDescriptionString", + "documentation":"

    A description of the specific risk and the condition that triggers it.

    " + }, + "risk":{ + "shape":"RiskRating", + "documentation":"

    The risk rating for the trade-off.

    " + }, + "mitigation":{ + "shape":"TradeOffMitigationString", + "documentation":"

    A specific action to mitigate the trade-off and when to take it.

    " + }, + "riskExplanation":{ + "shape":"TradeOffRiskExplanationString", + "documentation":"

    An optional explanation providing additional context for the risk rating.

    " + } + }, + "documentation":"

    A negative trade-off from acting on the recommendation.

    " + }, + "TradeOffDescriptionString":{ + "type":"string", + "max":450, + "min":30 + }, + "TradeOffMitigationString":{ + "type":"string", + "max":450, + "min":30 + }, + "TradeOffRiskExplanationString":{ + "type":"string", + "max":160, + "min":1 + }, + "TradeOffTitleString":{ + "type":"string", + "max":80, + "min":3 + }, + "TradeOffs":{ + "type":"list", + "member":{"shape":"TradeOff"} }, "TrustedAdvisorIntegrationStatus":{ "type":"string", @@ -5192,6 +8707,10 @@ "DISABLED" ] }, + "UUID":{ + "type":"string", + "pattern":"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + }, "UntagResourceInput":{ "type":"structure", "required":[ @@ -5216,6 +8735,355 @@ "type":"structure", "members":{} }, + "UpdateAgentContextRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "clientToken":{ + "shape":"UpdateAgentContextRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the context.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the context to update.

    ", + "location":"uri", + "locationName":"id" + }, + "title":{ + "shape":"UpdateAgentContextRequestTitleString", + "documentation":"

    The updated title of the context.

    " + }, + "content":{ + "shape":"ContextContent", + "documentation":"

    The updated typed content of the context. The structure contains application-specific fields such as account IDs, Regions, services, and resource types.

    " + } + } + }, + "UpdateAgentContextRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "UpdateAgentContextRequestTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "UpdateAgentContextResponse":{ + "type":"structure", + "required":["context"], + "members":{ + "context":{ + "shape":"ContextSummary", + "documentation":"

    The updated context summary.

    " + } + } + }, + "UpdateAgentGoalRequest":{ + "type":"structure", + "required":[ + "profileArn", + "id" + ], + "members":{ + "clientToken":{ + "shape":"UpdateAgentGoalRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile containing the goal to update.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "id":{ + "shape":"UUID", + "documentation":"

    The unique identifier of the goal to update.

    ", + "location":"uri", + "locationName":"id" + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The updated pillars for the goal. Pillars define the optimization focus areas such as cost, performance, resilience, and operational excellence.

    " + }, + "title":{ + "shape":"UpdateAgentGoalRequestTitleString", + "documentation":"

    The updated title for the goal. Maximum length of 1000 characters.

    " + }, + "description":{ + "shape":"UpdateAgentGoalRequestDescriptionString", + "documentation":"

    A description of the goal.

    " + } + } + }, + "UpdateAgentGoalRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "UpdateAgentGoalRequestDescriptionString":{ + "type":"string", + "max":4000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "UpdateAgentGoalRequestTitleString":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "UpdateAgentGoalResponse":{ + "type":"structure", + "required":["goal"], + "members":{ + "goal":{ + "shape":"GoalSummary", + "documentation":"

    The updated goal summary.

    " + } + } + }, + "UpdateAgentProfileRequest":{ + "type":"structure", + "required":["profileArn"], + "members":{ + "clientToken":{ + "shape":"UpdateAgentProfileRequestClientTokenString", + "documentation":"

    A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.

    ", + "idempotencyToken":true + }, + "profileArn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the profile to update.

    ", + "location":"uri", + "locationName":"profileArn" + }, + "displayName":{ + "shape":"UpdateAgentProfileRequestDisplayNameString", + "documentation":"

    The updated display name of the profile.

    " + }, + "description":{ + "shape":"UpdateAgentProfileRequestDescriptionString", + "documentation":"

    The updated description of the profile.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The updated ARN of the IAM execution role.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The updated aggregation configuration.

    " + }, + "businessOverview":{ + "shape":"UpdateAgentProfileRequestBusinessOverviewString", + "documentation":"

    The updated business overview for the profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The updated Well-Architected Tool Framework pillars for the profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled for the profile.

    " + } + } + }, + "UpdateAgentProfileRequestBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "UpdateAgentProfileRequestClientTokenString":{ + "type":"string", + "max":128, + "min":1, + "pattern":"[\\x21-\\x7E]+" + }, + "UpdateAgentProfileRequestDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "UpdateAgentProfileRequestDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "UpdateAgentProfileResponse":{ + "type":"structure", + "required":[ + "name", + "pillars", + "executionRoleArn", + "aggregationConfiguration", + "arn", + "createdBy", + "createdAt" + ], + "members":{ + "name":{ + "shape":"UpdateAgentProfileResponseNameString", + "documentation":"

    The system name of the updated profile.

    " + }, + "displayName":{ + "shape":"UpdateAgentProfileResponseDisplayNameString", + "documentation":"

    The display name of the updated profile.

    " + }, + "description":{ + "shape":"UpdateAgentProfileResponseDescriptionString", + "documentation":"

    A description of the updated profile.

    " + }, + "businessOverview":{ + "shape":"UpdateAgentProfileResponseBusinessOverviewString", + "documentation":"

    The business overview of the updated profile.

    " + }, + "pillars":{ + "shape":"Pillars", + "documentation":"

    The Well-Architected Tool Framework pillars associated with the updated profile.

    " + }, + "deletionProtection":{ + "shape":"Boolean", + "documentation":"

    Indicates whether deletion protection is enabled.

    " + }, + "executionRoleArn":{ + "shape":"RoleArn", + "documentation":"

    The ARN of the IAM execution role.

    " + }, + "aggregationConfiguration":{ + "shape":"AggregationConfigurations", + "documentation":"

    The aggregation configuration.

    " + }, + "arn":{ + "shape":"AgentProfileArn", + "documentation":"

    The Amazon Resource Name (ARN) of the updated profile.

    " + }, + "eligibleForScheduledGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for scheduled recommendation generation.

    " + }, + "eligibleForArchitectureGeneration":{ + "shape":"Boolean", + "documentation":"

    Indicates whether the profile is valid for manual architecture generation.

    " + }, + "fieldErrors":{ + "shape":"FieldErrors", + "documentation":"

    A map of field paths to error messages for invalid or missing input fields.

    " + }, + "tags":{ + "shape":"Tags", + "documentation":"

    The tags associated with the updated profile.

    " + }, + "createdBy":{ + "shape":"UpdateAgentProfileResponseCreatedByString", + "documentation":"

    The identifier of the user or system that created this profile.

    " + }, + "createdAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was created.

    " + }, + "lastModifiedBy":{ + "shape":"UpdateAgentProfileResponseLastModifiedByString", + "documentation":"

    The identifier of the user or system that last modified this profile.

    " + }, + "lastModifiedAt":{ + "shape":"SyntheticTimestamp_date_time", + "documentation":"

    The timestamp when the profile was last modified.

    " + } + } + }, + "UpdateAgentProfileResponseBusinessOverviewString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "UpdateAgentProfileResponseCreatedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "UpdateAgentProfileResponseDescriptionString":{ + "type":"string", + "max":512, + "min":0, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])*", + "sensitive":true + }, + "UpdateAgentProfileResponseDisplayNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"(?:(?!\\$\\{[a-zA-Z]+:)[\\P{C}])+", + "sensitive":true + }, + "UpdateAgentProfileResponseLastModifiedByString":{ + "type":"string", + "max":128, + "min":1 + }, + "UpdateAgentProfileResponseNameString":{ + "type":"string", + "max":128, + "min":3, + "pattern":"[a-zA-Z0-9_-]+" + }, + "UpdateAgentRecommendationStatusRequest":{ + "type":"structure", + "required":[ + "recommendationArn", + "status" + ], + "members":{ + "recommendationArn":{ + "shape":"AgentRecommendationArn", + "documentation":"

    The Amazon Resource Name (ARN) of the recommendation to update.

    ", + "location":"uri", + "locationName":"recommendationArn" + }, + "status":{ + "shape":"RecommendationStatus", + "documentation":"

    The new status to assign to the recommendation.

    " + }, + "updateReason":{ + "shape":"UpdateAgentRecommendationStatusRequestUpdateReasonString", + "documentation":"

    A free-text reason explaining this status update.

    " + } + } + }, + "UpdateAgentRecommendationStatusRequestUpdateReasonString":{ + "type":"string", + "max":4096, + "min":1, + "sensitive":true + }, + "UpdateAgentRecommendationStatusResponse":{ + "type":"structure", + "members":{} + }, "UpdateAnswerInput":{ "type":"structure", "required":[ @@ -5678,7 +9546,10 @@ "Fields":{"shape":"ValidationExceptionFieldList"} }, "documentation":"

    The user input is not valid.

    ", - "error":{"httpStatusCode":400}, + "error":{ + "httpStatusCode":400, + "senderFault":true + }, "exception":true }, "ValidationExceptionField":{ @@ -5730,13 +9601,19 @@ "WorkloadName":{"shape":"WorkloadName"}, "Description":{"shape":"WorkloadDescription"}, "Environment":{"shape":"WorkloadEnvironment"}, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the workload was last updated.

    " + }, "AccountIds":{"shape":"WorkloadAccountIds"}, "AwsRegions":{"shape":"WorkloadAwsRegions"}, "NonAwsRegions":{"shape":"WorkloadNonAwsRegions"}, "ArchitecturalDesign":{"shape":"WorkloadArchitecturalDesign"}, "ReviewOwner":{"shape":"WorkloadReviewOwner"}, - "ReviewRestrictionDate":{"shape":"Timestamp"}, + "ReviewRestrictionDate":{ + "shape":"Timestamp", + "documentation":"

    The review restriction date for the workload.

    " + }, "IsReviewOwnerUpdateAcknowledged":{ "shape":"IsReviewOwnerUpdateAcknowledged", "documentation":"

    Flag indicating whether the workload owner has acknowledged that the Review owner field is required.

    If a Review owner is not added to the workload within 60 days of acknowledgement, access to the workload is restricted until an owner is added.

    " @@ -5781,18 +9658,21 @@ "type":"list", "member":{"shape":"AwsAccountId"}, "documentation":"

    The list of Amazon Web Services account IDs associated with the workload.

    ", - "max":100 + "max":100, + "min":0 }, "WorkloadApplications":{ "type":"list", "member":{"shape":"ApplicationArn"}, - "max":1 + "max":1, + "min":0 }, "WorkloadArchitecturalDesign":{ "type":"string", "documentation":"

    The URL of the architectural design for the workload.

    ", "max":2048, - "pattern":"^(|(https?|ftp):\\/\\/[^\\s/$.?#].[^\\s]*)$" + "min":0, + "pattern":"(|(https?|ftp):\\/\\/[^\\s/$.?#].[^\\s]*)" }, "WorkloadArn":{ "type":"string", @@ -5802,7 +9682,8 @@ "type":"list", "member":{"shape":"AwsRegion"}, "documentation":"

    The list of Amazon Web Services Regions associated with the workload, for example, us-east-2, or ca-central-1.

    ", - "max":50 + "max":50, + "min":0 }, "WorkloadDescription":{ "type":"string", @@ -5853,12 +9734,14 @@ "WorkloadIndustry":{ "type":"string", "documentation":"

    The industry for the workload.

    ", - "max":100 + "max":100, + "min":0 }, "WorkloadIndustryType":{ "type":"string", "documentation":"

    The industry type for the workload.

    If specified, must be one of the following:

    • Agriculture

    • Automobile

    • Defense

    • Design and Engineering

    • Digital Advertising

    • Education

    • Environmental Protection

    • Financial Services

    • Gaming

    • General Public Services

    • Healthcare

    • Hospitality

    • InfoTech

    • Justice and Public Safety

    • Life Sciences

    • Manufacturing

    • Media & Entertainment

    • Mining & Resources

    • Oil & Gas

    • Power & Utilities

    • Professional Services

    • Real Estate & Construction

    • Retail & Wholesale

    • Social Protection

    • Telecommunications

    • Travel, Transportation & Logistics

    • Other

    ", - "max":100 + "max":100, + "min":0 }, "WorkloadIssueManagementStatus":{ "type":"string", @@ -5922,7 +9805,8 @@ "WorkloadNamePrefix":{ "type":"string", "documentation":"

    An optional string added to the beginning of each workload name returned in the results.

    ", - "max":100 + "max":100, + "min":0 }, "WorkloadNonAwsRegion":{ "type":"string", @@ -5933,7 +9817,8 @@ "type":"list", "member":{"shape":"WorkloadNonAwsRegion"}, "documentation":"

    The list of non-Amazon Web Services Regions associated with the workload.

    ", - "max":5 + "max":5, + "min":0 }, "WorkloadPillarPriorities":{ "type":"list", @@ -5957,12 +9842,14 @@ "WorkloadProfileArns":{ "type":"list", "member":{"shape":"ProfileArn"}, - "max":1 + "max":1, + "min":0 }, "WorkloadProfiles":{ "type":"list", "member":{"shape":"WorkloadProfile"}, - "max":1 + "max":1, + "min":0 }, "WorkloadResourceDefinition":{ "type":"list", @@ -6018,7 +9905,10 @@ "WorkloadArn":{"shape":"WorkloadArn"}, "WorkloadName":{"shape":"WorkloadName"}, "Owner":{"shape":"AwsAccountId"}, - "UpdatedAt":{"shape":"Timestamp"}, + "UpdatedAt":{ + "shape":"Timestamp", + "documentation":"

    The date and time when the workload was last updated.

    " + }, "Lenses":{"shape":"WorkloadLenses"}, "RiskCounts":{"shape":"RiskCounts"}, "ImprovementStatus":{"shape":"WorkloadImprovementStatus"}, @@ -6031,5 +9921,5 @@ "documentation":"

    A workload summary return object.

    " } }, - "documentation":"Well-Architected Tool

    This is the Well-Architected Tool API Reference. The WA Tool API provides programmatic access to the Well-Architected Tool in the Amazon Web Services Management Console. For information about the Well-Architected Tool, see the Well-Architected Tool User Guide.

    " + "documentation":"

    Amazon Web Services Well-Architected

    Amazon Web Services Well-Architected helps you evaluate your architectures against Amazon Web Services best practices across operational excellence, security, reliability, performance efficiency, cost optimization, and sustainability. The service includes the Amazon Web Services Well-Architected Agent for AI-powered recommendations tailored to your specific environment, and the Well-Architected Tool for conducting reviews and tracking improvements.

    This is the Amazon Web Services Well-Architected API Reference. Through this API, you can programmatically access personalized recommendations and automation scripts from the Amazon Web Services Well-Architected Agent, and create and manage workloads, conduct lens reviews, track milestones, manage custom lenses, share workloads across accounts, and manage profiles with the Well-Architected Tool.

    For more information about the service, see the Amazon Web Services Well-Architected User Guide.

    " } diff --git a/services/wickr/pom.xml b/services/wickr/pom.xml index 9f3c305348ce..6fe5b586159e 100644 --- a/services/wickr/pom.xml +++ b/services/wickr/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT wickr AWS Java SDK :: Services :: Wickr diff --git a/services/wickr/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/wickr/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..4f050830e02d --- /dev/null +++ b/services/wickr/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://admin.wickr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://admin.wickr-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://admin.wickr.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://admin.wickr.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/wickr/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/wickr/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1f95801d1f4b..000000000000 --- a/services/wickr/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://admin.wickr-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://admin.wickr-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://admin.wickr.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://admin.wickr.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/wisdom/pom.xml b/services/wisdom/pom.xml index fefbb0fec980..32f3acb3433e 100644 --- a/services/wisdom/pom.xml +++ b/services/wisdom/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT wisdom AWS Java SDK :: Services :: Wisdom diff --git a/services/wisdom/src/main/resources/codegen-resources/customization.config b/services/wisdom/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/wisdom/src/main/resources/codegen-resources/customization.config +++ b/services/wisdom/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/wisdom/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/wisdom/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..e6d91088fef7 --- /dev/null +++ b/services/wisdom/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://wisdom.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/wisdom/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/wisdom/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 8a698238589d..000000000000 --- a/services/wisdom/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://wisdom.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://wisdom.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/workdocs/pom.xml b/services/workdocs/pom.xml index 87846f5af728..c7265f5098f5 100644 --- a/services/workdocs/pom.xml +++ b/services/workdocs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workdocs AWS Java SDK :: Services :: Amazon WorkDocs diff --git a/services/workdocs/src/main/resources/codegen-resources/customization.config b/services/workdocs/src/main/resources/codegen-resources/customization.config index c89f8010e088..d259cf264e11 100644 --- a/services/workdocs/src/main/resources/codegen-resources/customization.config +++ b/services/workdocs/src/main/resources/codegen-resources/customization.config @@ -3,6 +3,5 @@ "describeUsers", "describeActivities", "getResources" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/workdocs/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workdocs/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..03e9d25fd6b4 --- /dev/null +++ b/services/workdocs/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workdocs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workdocs-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workdocs.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workdocs.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workdocs/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workdocs/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 2cf94053cb41..000000000000 --- a/services/workdocs/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workdocs-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workdocs-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workdocs.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workdocs.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/workmail/pom.xml b/services/workmail/pom.xml index a56e86c2257f..aa6973733f51 100644 --- a/services/workmail/pom.xml +++ b/services/workmail/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 workmail diff --git a/services/workmail/src/main/resources/codegen-resources/customization.config b/services/workmail/src/main/resources/codegen-resources/customization.config index cade6d8f3851..e1478802b59d 100644 --- a/services/workmail/src/main/resources/codegen-resources/customization.config +++ b/services/workmail/src/main/resources/codegen-resources/customization.config @@ -1,6 +1,5 @@ { "verifiedSimpleMethods": [ "listOrganizations" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/workmail/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workmail/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..c05f95a4188b --- /dev/null +++ b/services/workmail/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmail-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmail.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmail.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workmail/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workmail/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index b2a384f7b05f..000000000000 --- a/services/workmail/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmail-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmail-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmail.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workmail.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/workmailmessageflow/pom.xml b/services/workmailmessageflow/pom.xml index 9647611d837b..04397bfc0783 100644 --- a/services/workmailmessageflow/pom.xml +++ b/services/workmailmessageflow/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workmailmessageflow AWS Java SDK :: Services :: WorkMailMessageFlow diff --git a/services/workmailmessageflow/src/main/resources/codegen-resources/customization.config b/services/workmailmessageflow/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/workmailmessageflow/src/main/resources/codegen-resources/customization.config +++ b/services/workmailmessageflow/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..347714ce9df1 --- /dev/null +++ b/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmailmessageflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmailmessageflow-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmailmessageflow.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workmailmessageflow.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 0a3c7457bdfd..000000000000 --- a/services/workmailmessageflow/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmailmessageflow-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmailmessageflow-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workmailmessageflow.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workmailmessageflow.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/workspaces/pom.xml b/services/workspaces/pom.xml index 85ed68c214aa..1b4a54b7f1ee 100644 --- a/services/workspaces/pom.xml +++ b/services/workspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workspaces AWS Java SDK :: Services :: Amazon WorkSpaces diff --git a/services/workspaces/src/main/resources/codegen-resources/customization.config b/services/workspaces/src/main/resources/codegen-resources/customization.config index fd0fde6fe6ff..4494f73266ff 100644 --- a/services/workspaces/src/main/resources/codegen-resources/customization.config +++ b/services/workspaces/src/main/resources/codegen-resources/customization.config @@ -10,6 +10,5 @@ "excludedSimpleMethods": [ "describeAccountModifications", "describeAccount" - ], - "enableGenerateCompiledEndpointRules": true + ] } diff --git a/services/workspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..79df572f4a97 --- /dev/null +++ b/services/workspaces/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workspaces/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workspaces/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1c7011dbb1d1..000000000000 --- a/services/workspaces/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workspaces.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file 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 3912919e3428..cdf98f90f090 100644 --- a/services/workspaces/src/main/resources/codegen-resources/service-2.json +++ b/services/workspaces/src/main/resources/codegen-resources/service-2.json @@ -311,7 +311,7 @@ {"shape":"OperationNotSupportedException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Creates a pool of WorkSpaces.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Creates a pool of WorkSpaces.

    " }, "DeleteAccountLinkInvitation":{ "name":"DeleteAccountLinkInvitation", @@ -806,7 +806,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Retrieves a list that describes the streaming sessions for a specified pool.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Retrieves a list that describes the streaming sessions for a specified pool.

    " }, "DescribeWorkspacesPools":{ "name":"DescribeWorkspacesPools", @@ -821,7 +821,7 @@ {"shape":"ResourceNotFoundException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Describes the specified WorkSpaces Pools.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Describes the specified WorkSpaces Pools.

    " }, "DisassociateConnectionAlias":{ "name":"DisassociateConnectionAlias", @@ -987,7 +987,7 @@ {"shape":"OperationInProgressException"}, {"shape":"ResourceUnavailableException"} ], - "documentation":"

    Migrates a WorkSpace from one operating system or bundle type to another, while retaining the data on the user volume.

    The migration process recreates the WorkSpace by using a new root volume from the target bundle image and the user volume from the last available snapshot of the original WorkSpace. During migration, the original D:\\Users\\%USERNAME% user profile folder is renamed to D:\\Users\\%USERNAME%MMddyyTHHmmss%.NotMigrated. A new D:\\Users\\%USERNAME%\\ folder is generated by the new OS. Certain files in the old user profile are moved to the new user profile.

    For available migration scenarios, details about what happens during migration, and best practices, see Migrate a WorkSpace.

    " + "documentation":"

    Migrates a WorkSpace from one operating system or bundle type to another, while retaining the data on the user volume.

    The migration process recreates the WorkSpace by using a new root volume from the target bundle image and the user volume from the last available snapshot of the original WorkSpace. During migration, the original D:\\Users\\%USERNAME% user profile folder is renamed to D:\\Users\\%USERNAME%MMddyyTHHmmss%.NotMigrated. A new D:\\Users\\%USERNAME%\\ folder is generated by the new OS. Certain files in the old user profile are moved to the new user profile.

    For available migration scenarios, details about what happens during migration, and best practices, see Migrate a WorkSpace.

    If the source WorkSpace has nested virtualization enabled and the target bundle does not support nested virtualization, the migration fails.

    " }, "ModifyAccount":{ "name":"ModifyAccount", @@ -1292,7 +1292,7 @@ {"shape":"OperationInProgressException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Starts the specified pool.

    You cannot start a pool unless it has a running mode of AutoStop and a state of STOPPED.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Starts the specified pool.

    You cannot start a pool unless it has a running mode of AutoStop and a state of STOPPED.

    " }, "StopWorkspaces":{ "name":"StopWorkspaces", @@ -1319,7 +1319,7 @@ {"shape":"OperationInProgressException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Stops the specified pool.

    You cannot stop a WorkSpace pool unless it has a running mode of AutoStop and a state of AVAILABLE, IMPAIRED, UNHEALTHY, or ERROR.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Stops the specified pool.

    You cannot stop a WorkSpace pool unless it has a running mode of AutoStop and a state of AVAILABLE, IMPAIRED, UNHEALTHY, or ERROR.

    " }, "TerminateWorkspaces":{ "name":"TerminateWorkspaces", @@ -1346,7 +1346,7 @@ {"shape":"OperationInProgressException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Terminates the specified pool.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Terminates the specified pool.

    " }, "TerminateWorkspacesPoolSession":{ "name":"TerminateWorkspacesPoolSession", @@ -1363,7 +1363,7 @@ {"shape":"OperationInProgressException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Terminates the pool session.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Terminates the pool session.

    " }, "UpdateConnectClientAddIn":{ "name":"UpdateConnectClientAddIn", @@ -1467,7 +1467,7 @@ {"shape":"OperationInProgressException"}, {"shape":"AccessDeniedException"} ], - "documentation":"

    Updates the specified pool.

    " + "documentation":"

    End of support notice: On December 31, 2027, Amazon Web Services will end support for Amazon WorkSpaces Pools. After December 31, 2027, you will no longer be able to access the Amazon WorkSpaces Pools console or Amazon WorkSpaces Pools resources. For more information, see Amazon WorkSpaces Pools end of support.

    Updates the specified pool.

    " } }, "shapes":{ @@ -2122,6 +2122,11 @@ "min":6, "pattern":"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$" }, + "ClientExperiencePolicy":{ + "type":"string", + "max":64, + "pattern":"^[A-Z_0-9]+$" + }, "ClientLocale":{ "type":"string", "max":5, @@ -2144,6 +2149,10 @@ "LogUploadEnabled":{ "shape":"LogUploadEnum", "documentation":"

    Specifies whether users can upload diagnostic log files of Amazon WorkSpaces client directly to WorkSpaces to troubleshoot issues when using the WorkSpaces client. When enabled, the log files will be sent to WorkSpaces automatically and will be applied to all users in the specified directory.

    " + }, + "ClientExperiencePolicy":{ + "shape":"ClientExperiencePolicy", + "documentation":"

    The client experience policy that determines which client experience the user sees. Administrators can set this policy to control the client experience for users in a directory. Valid values include FORCE_CLASSIC, FORCE_UI_2026, and USER_CHOICE.

    " } }, "documentation":"

    Describes an Amazon WorkSpaces client.

    " @@ -2201,7 +2210,11 @@ "GRAPHICS_G6F_XLARGE", "GRAPHICS_G6F_2XLARGE", "GRAPHICS_G6F_4XLARGE", - "GRAPHICS_GR6F_4XLARGE" + "GRAPHICS_GR6F_4XLARGE", + "GRAPHICS_G7_2XLARGE", + "GRAPHICS_G7_4XLARGE", + "GRAPHICS_G7_8XLARGE", + "GRAPHICS_G7_12XLARGE" ] }, "ComputeList":{ @@ -4364,7 +4377,8 @@ "enum":[ "BASE", "GRAPHICS_G4DN", - "GRAPHICS_G6" + "GRAPHICS_G6", + "GRAPHICS_G7" ] }, "ImageErrorMessage":{ @@ -4965,7 +4979,8 @@ "ROOT_VOLUME", "USER_VOLUME", "COMPUTE_TYPE", - "PROTOCOL" + "PROTOCOL", + "NESTED_VIRTUALIZATION" ] }, "ModificationState":{ @@ -4973,7 +4988,7 @@ "members":{ "Resource":{ "shape":"ModificationResourceEnum", - "documentation":"

    The resource.

    " + "documentation":"

    The WorkSpace property being modified.

    " }, "State":{ "shape":"ModificationStateEnum", @@ -7191,7 +7206,7 @@ }, "Protocols":{ "shape":"ProtocolList", - "documentation":"

    The protocol. For more information, see Protocols for Amazon WorkSpaces.

    • Only available for WorkSpaces created with PCoIP bundles.

    • The Protocols property is case sensitive. Ensure you use PCOIP or DCV (formerly WSP).

    • Unavailable for Windows 7 WorkSpaces and WorkSpaces using GPU-based bundles (Graphics, GraphicsPro, Graphics.g4dn, GraphicsPro.g4dn, and Graphics.g6).

    " + "documentation":"

    The protocol. For more information, see Protocols for Amazon WorkSpaces.

    • Only available for WorkSpaces created with PCoIP bundles.

    • The Protocols property is case sensitive. Ensure you use PCOIP or DCV (formerly WSP).

    • Unavailable for Windows 7 WorkSpaces and WorkSpaces using GPU-based bundles (Graphics, GraphicsPro, Graphics.g4dn, GraphicsPro.g4dn, Graphics.g6, and Graphics.g7).

    " }, "OperatingSystemName":{ "shape":"OperatingSystemName", @@ -7200,6 +7215,10 @@ "GlobalAccelerator":{ "shape":"GlobalAcceleratorForWorkSpace", "documentation":"

    Indicates the Global Accelerator properties.

    " + }, + "NestedVirtualizationEnabled":{ + "shape":"BooleanObject", + "documentation":"

    Specifies whether nested virtualization is enabled for the WorkSpace.

    For more information, see Nested virtualization for Amazon WorkSpaces.

    " } }, "documentation":"

    Describes a WorkSpace.

    " diff --git a/services/workspacesinstances/pom.xml b/services/workspacesinstances/pom.xml index 6654998e6ac7..9df5d0d4557e 100644 --- a/services/workspacesinstances/pom.xml +++ b/services/workspacesinstances/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workspacesinstances AWS Java SDK :: Services :: Workspaces Instances @@ -56,5 +56,10 @@ http-auth-aws ${awsjavasdk.version}
    + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + diff --git a/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..660d951cd766 --- /dev/null +++ b/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,104 @@ +{ + "version": "1.1", + "parameters": { + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-instances-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-instances.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 6, + "nodes": "/////wAAAAH/////AAAAAAAAAAYAAAADAAAAAQAAAAQF9eEFAAAAAgAAAAUF9eEFAAAAAwX14QMF9eEEAAAAAwX14QEF9eEC" +} \ No newline at end of file diff --git a/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 1e739c88e42f..000000000000 --- a/services/workspacesinstances/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,137 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - }, - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "endpoint": { - "url": "https://workspaces-instances-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-instances.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/workspacesinstances/src/main/resources/codegen-resources/service-2.json b/services/workspacesinstances/src/main/resources/codegen-resources/service-2.json index a17466421318..f08aaf61cf26 100644 --- a/services/workspacesinstances/src/main/resources/codegen-resources/service-2.json +++ b/services/workspacesinstances/src/main/resources/codegen-resources/service-2.json @@ -5,8 +5,11 @@ "auth":["aws.auth#sigv4"], "endpointPrefix":"workspaces-instances", "jsonVersion":"1.0", - "protocol":"json", - "protocols":["json"], + "protocol":"smithy-rpc-v2-cbor", + "protocols":[ + "smithy-rpc-v2-cbor", + "json" + ], "serviceFullName":"Amazon Workspaces Instances", "serviceId":"Workspaces Instances", "signatureVersion":"v4", @@ -264,6 +267,10 @@ } }, "documentation":"

    Indicates insufficient permissions to perform the requested action.

    ", + "error":{ + "httpStatusCode":403, + "senderFault":true + }, "exception":true }, "AmdSevSnpEnum":{ @@ -408,6 +415,7 @@ "type":"string", "max":64, "min":1, + "pattern":"[\\x20-\\x7E]+", "sensitive":true }, "ConflictException":{ @@ -432,6 +440,10 @@ } }, "documentation":"

    Signals a conflict with the current state of the resource.

    ", + "error":{ + "httpStatusCode":409, + "senderFault":true + }, "exception":true }, "ConnectionTrackingSpecificationRequest":{ @@ -473,6 +485,10 @@ "ThreadsPerCore":{ "shape":"NonNegativeInteger", "documentation":"

    Number of threads per CPU core.

    " + }, + "NestedVirtualization":{ + "shape":"NestedVirtualizationEnum", + "documentation":"

    Specifies whether to enable or disable nested virtualization.

    " } }, "documentation":"

    Configures CPU-specific settings for WorkSpace Instance.

    " @@ -1073,6 +1089,8 @@ }, "InstanceType":{ "type":"string", + "max":64, + "min":1, "pattern":"([a-z0-9-]+)\\.([a-z0-9]+)" }, "InstanceTypeInfo":{ @@ -1119,6 +1137,7 @@ } }, "documentation":"

    Indicates an unexpected server-side error occurred.

    ", + "error":{"httpStatusCode":500}, "exception":true, "fault":true, "retryable":{"throttling":false} @@ -1463,6 +1482,13 @@ "max":25, "min":1 }, + "NestedVirtualizationEnum":{ + "type":"string", + "enum":[ + "enabled", + "disabled" + ] + }, "NetworkInterfaceId":{ "type":"string", "pattern":"eni-[0-9a-zA-Z]{1,63}" @@ -1627,6 +1653,10 @@ } }, "documentation":"

    Indicates the requested resource could not be found.

    ", + "error":{ + "httpStatusCode":404, + "senderFault":true + }, "exception":true }, "ResourceTypeEnum":{ @@ -1696,6 +1726,10 @@ } }, "documentation":"

    Indicates that a service quota has been exceeded.

    ", + "error":{ + "httpStatusCode":402, + "senderFault":true + }, "exception":true }, "SnapshotId":{ @@ -1883,6 +1917,10 @@ } }, "documentation":"

    Indicates the request rate has exceeded limits.

    ", + "error":{ + "httpStatusCode":429, + "senderFault":true + }, "exception":true, "retryable":{"throttling":true} }, @@ -1937,6 +1975,10 @@ } }, "documentation":"

    Indicates invalid input parameters in the request.

    ", + "error":{ + "httpStatusCode":400, + "senderFault":true + }, "exception":true }, "ValidationExceptionField":{ diff --git a/services/workspacesthinclient/pom.xml b/services/workspacesthinclient/pom.xml index 773ee5f2c467..02319f5f83dd 100644 --- a/services/workspacesthinclient/pom.xml +++ b/services/workspacesthinclient/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workspacesthinclient AWS Java SDK :: Services :: Work Spaces Thin Client diff --git a/services/workspacesthinclient/src/main/resources/codegen-resources/customization.config b/services/workspacesthinclient/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/workspacesthinclient/src/main/resources/codegen-resources/customization.config +++ b/services/workspacesthinclient/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..15767bd65b9f --- /dev/null +++ b/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://thinclient-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://thinclient-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://thinclient.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://thinclient.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index 66bb2e10d514..000000000000 --- a/services/workspacesthinclient/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://thinclient-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://thinclient-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://thinclient.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://thinclient.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ], - "type": "tree" - } - ] -} \ No newline at end of file diff --git a/services/workspacesweb/pom.xml b/services/workspacesweb/pom.xml index 9418583b054e..ac59cfc3e585 100644 --- a/services/workspacesweb/pom.xml +++ b/services/workspacesweb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT workspacesweb AWS Java SDK :: Services :: Work Spaces Web diff --git a/services/workspacesweb/src/main/resources/codegen-resources/customization.config b/services/workspacesweb/src/main/resources/codegen-resources/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/services/workspacesweb/src/main/resources/codegen-resources/customization.config +++ b/services/workspacesweb/src/main/resources/codegen-resources/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/services/workspacesweb/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/workspacesweb/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..07965e6058ae --- /dev/null +++ b/services/workspacesweb/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-web-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-web-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-web.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://workspaces-web.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/workspacesweb/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/workspacesweb/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index d7e15746395f..000000000000 --- a/services/workspacesweb/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-web-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-web-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-web.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://workspaces-web.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file diff --git a/services/xray/pom.xml b/services/xray/pom.xml index 1cf572be74d0..714bb2c893e6 100644 --- a/services/xray/pom.xml +++ b/services/xray/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT xray AWS Java SDK :: Services :: AWS X-Ray diff --git a/services/xray/src/main/resources/codegen-resources/customization.config b/services/xray/src/main/resources/codegen-resources/customization.config index e30f4faf438f..ecb184d32a62 100644 --- a/services/xray/src/main/resources/codegen-resources/customization.config +++ b/services/xray/src/main/resources/codegen-resources/customization.config @@ -13,6 +13,5 @@ "AnnotationValue": { "union": true } - }, - "enableGenerateCompiledEndpointRules": true + } } diff --git a/services/xray/src/main/resources/codegen-resources/endpoint-bdd-1.json b/services/xray/src/main/resources/codegen-resources/endpoint-bdd-1.json new file mode 100644 index 000000000000..0bbaf1e4a168 --- /dev/null +++ b/services/xray/src/main/resources/codegen-resources/endpoint-bdd-1.json @@ -0,0 +1,188 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://xray-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://xray-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://xray.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://xray.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 2, + "nodeCount": 13, + "nodes": "/////wAAAAH/////AAAAAAAAAAwAAAADAAAAAQAAAAQF9eELAAAAAgAAAAUF9eELAAAAAwAAAAgAAAAGAAAABAAAAAcF9eEKAAAABQX14QgF9eEJAAAABAAAAAoAAAAJAAAABgX14QYF9eEHAAAABQAAAAsF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAANAAAABAX14QIF9eED" +} \ No newline at end of file diff --git a/services/xray/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/xray/src/main/resources/codegen-resources/endpoint-rule-set.json deleted file mode 100644 index ee5f776621d5..000000000000 --- a/services/xray/src/main/resources/codegen-resources/endpoint-rule-set.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "version": "1.0", - "parameters": { - "Region": { - "builtIn": "AWS::Region", - "required": false, - "documentation": "The AWS region used to dispatch the request.", - "type": "string" - }, - "UseDualStack": { - "builtIn": "AWS::UseDualStack", - "required": true, - "default": false, - "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", - "type": "boolean" - }, - "UseFIPS": { - "builtIn": "AWS::UseFIPS", - "required": true, - "default": false, - "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", - "type": "boolean" - }, - "Endpoint": { - "builtIn": "SDK::Endpoint", - "required": false, - "documentation": "Override the endpoint used to send this request", - "type": "string" - } - }, - "rules": [ - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Endpoint" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "error": "Invalid Configuration: FIPS and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", - "type": "error" - }, - { - "conditions": [], - "endpoint": { - "url": { - "ref": "Endpoint" - }, - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "isSet", - "argv": [ - { - "ref": "Region" - } - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "aws.partition", - "argv": [ - { - "ref": "Region" - } - ], - "assign": "PartitionResult" - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - }, - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - } - ] - }, - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://xray-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS and DualStack are enabled, but this partition does not support one or both", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseFIPS" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsFIPS" - ] - }, - true - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://xray-fips.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "FIPS is enabled but this partition does not support FIPS", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - { - "ref": "UseDualStack" - }, - true - ] - } - ], - "rules": [ - { - "conditions": [ - { - "fn": "booleanEquals", - "argv": [ - true, - { - "fn": "getAttr", - "argv": [ - { - "ref": "PartitionResult" - }, - "supportsDualStack" - ] - } - ] - } - ], - "rules": [ - { - "conditions": [], - "endpoint": { - "url": "https://xray.{Region}.{PartitionResult#dualStackDnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "DualStack is enabled but this partition does not support DualStack", - "type": "error" - } - ], - "type": "tree" - }, - { - "conditions": [], - "endpoint": { - "url": "https://xray.{Region}.{PartitionResult#dnsSuffix}", - "properties": {}, - "headers": {} - }, - "type": "endpoint" - } - ], - "type": "tree" - } - ], - "type": "tree" - }, - { - "conditions": [], - "error": "Invalid Configuration: Missing Region", - "type": "error" - } - ] -} \ No newline at end of file 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 054af8e9227b..700f35ed8cb4 100644 --- a/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 +++ b/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 @@ -42,6 +42,8 @@ Class d 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 ) @@ -49,6 +51,7 @@ Class dep 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/pom.xml b/test/architecture-tests/pom.xml index 88d09f671a3d..04791341078e 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml @@ -171,6 +171,11 @@ apache5-client ${awsjavasdk.version} + + software.amazon.awssdk + aws-crt-client + ${awsjavasdk.version} + org.junit.jupiter junit-jupiter diff --git a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/CodingConventionWithSuppressionTest.java b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/CodingConventionWithSuppressionTest.java index feae8cdf8b92..085bb6ecd994 100644 --- a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/CodingConventionWithSuppressionTest.java +++ b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/CodingConventionWithSuppressionTest.java @@ -57,10 +57,19 @@ public class CodingConventionWithSuppressionTest { ArchUtils.classNameToPattern("software.amazon.awssdk.services.s3.internal.crt.S3CrtResponseHandlerAdapter"), ArchUtils.classNameToPattern( "software.amazon.awssdk.services.s3.internal.crt.CrtResponseFileResponseTransformer"), + ArchUtils.classNameToPattern("software.amazon.awssdk.http.crt.AwsCrtHttpClientBase"), + ArchUtils.classNameToPattern("software.amazon.awssdk.http.crt.internal.AwsCrtConfigurationUtils"), + ArchUtils.classNameToPattern("software.amazon.awssdk.crtcore.CrtConfigurationUtils"), + ArchUtils.classNameToPattern( + "software.amazon.awssdk.http.crt.internal.response.CrtResponseAdapter"), ArchUtils.classNameToPattern(RetryableSubAsyncRequestBody.class), ArchUtils.classNameToPattern(KnownContentLengthAsyncRequestBodySubscriber.class), ArchUtils.classNameToPattern(UnknownContentLengthAsyncRequestBodySubscriber.class), + ArchUtils.classNameToPattern( + "software.amazon.awssdk.transfer.s3.internal.model.CrtFileDownload"), ArchUtils.classNameToPattern(CopyObjectHelper.class), + ArchUtils.classNameToPattern("software.amazon.awssdk.core.internal.warmup.WarmUpDiscovery"), + ArchUtils.classNameToPattern("software.amazon.awssdk.core.internal.warmup.TargetedWarmUpInvoker"), ArchUtils.classNameToPattern("software.amazon.awssdk.mapper.dynamodb.ConversionSchemas"), ArchUtils.classNameToPattern( "software.amazon.awssdk.mapper.dynamodb.internal.marshallers.ObjectSetToStringSetMarshaller"), @@ -70,6 +79,7 @@ public class CodingConventionWithSuppressionTest { private static final Set ALLOWED_ERROR_LOG_SUPPRESSION = new HashSet<>( Arrays.asList( ArchUtils.classNameToPattern(EmfMetricLoggingPublisher.class), + ArchUtils.classNameToPattern("software.amazon.awssdk.http.crt.internal.CrtAsyncRequestExecutor"), ArchUtils.classWithInnerClassesToPattern(ResponseTransformer.class))); @Test diff --git a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/NamingConventionWithSuppressionTest.java b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/NamingConventionWithSuppressionTest.java index 75277418c19a..7c9ef5753ade 100644 --- a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/NamingConventionWithSuppressionTest.java +++ b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/NamingConventionWithSuppressionTest.java @@ -23,12 +23,11 @@ import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchRule; import java.util.Arrays; -import java.util.HashSet; +import java.util.Collections; import java.util.Set; import java.util.function.Supplier; import java.util.regex.Pattern; import org.junit.jupiter.api.Test; -import software.amazon.awssdk.services.s3.endpoints.internal.S3EndpointAuthSchemeStrategyFactory; /** * This test class diffs from {@link NamingConventionTest}; it doesn't use archunit annotations such as {@link ArchTest} @@ -44,9 +43,7 @@ public class NamingConventionWithSuppressionTest { *

    * DO NOT ADD NEW EXCEPTIONS */ - private static final Set ALLOWED_SUPPLIER_SUPPRESSION = new HashSet<>( - Arrays.asList(Pattern.compile(".*/DefaultEndpointAuthSchemeStrategyFactory.class"), - ArchUtils.classNameToPattern(S3EndpointAuthSchemeStrategyFactory.class))); + private static final Set ALLOWED_SUPPLIER_SUPPRESSION = Collections.emptySet(); @Test void supplierImpl_shouldHaveSupplierSuffix() { diff --git a/test/auth-tests/pom.xml b/test/auth-tests/pom.xml index 74bad3c2a6a9..e9836fffc1ce 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../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 9cf1c833d663..ce7bde979756 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/bundle-shading-tests/pom.xml b/test/bundle-shading-tests/pom.xml index 75fd8a896d5d..f50110af3155 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/codegen-generated-classes-test/pom.xml b/test/codegen-generated-classes-test/pom.xml index bae0448b8e97..6acf8c6a2d17 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/customization.config new file mode 100644 index 000000000000..2c63c0851048 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/customization.config @@ -0,0 +1,2 @@ +{ +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-bdd-1.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-bdd-1.json new file mode 100644 index 000000000000..66e220ed535f --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-bdd-1.json @@ -0,0 +1,330 @@ +{ + "version": "1.1", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "AccountId": { + "builtIn": "AWS::Auth::AccountId", + "required": false, + "documentation": "The AWS account ID, read off the resolved identity.", + "type": "string" + }, + "AccountIdEndpointMode": { + "builtIn": "AWS::Auth::AccountIdEndpointMode", + "required": false, + "documentation": "Whether the account ID may be used in the endpoint.", + "type": "string" + }, + "clientStringParam": { + "required": false, + "documentation": "A client context parameter, so the cache key compares it early as reference-stable.", + "type": "string" + }, + "staticStringParam": { + "required": false, + "documentation": "Bound to a per-operation static literal.", + "type": "string" + }, + "requestStringParam": { + "required": false, + "documentation": "Bound to a request member, so it can change per request.", + "type": "string" + }, + "resourceArnList": { + "required": false, + "documentation": "Read only as resourceArnList[0], so the cache key compares just the first element. This is the DynamoDB shape.", + "type": "stringArray" + }, + "unusedStringParam": { + "required": false, + "documentation": "Declared but read by no condition and no result, so the cache key must leave it out.", + "type": "string" + }, + "wholeArnList": { + "required": false, + "documentation": "Read as a whole, so the cache key compares every element.", + "type": "stringArray" + } + }, + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + }, + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + }, + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountId" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "AccountIdEndpointMode" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "clientStringParam" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "staticStringParam" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "requestStringParam" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "resourceArnList" + }, + "[0]" + ], + "assign": "FirstArn" + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "wholeArnList" + } + ] + }, + { + "fn": "isSet", + "argv": [ + { + "ref": "resourceArnList" + } + ] + }, + { + "fn": "getAttr", + "argv": [ + { + "ref": "wholeArnList" + }, + "[1]" + ], + "assign": "SecondArn" + } + ], + "results": [ + { + "conditions": [], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ], + "root": 23, + "nodeCount": 23, + "nodes": "/////wAAAAH/////AAAAAAAAAA0AAAADAAAAAQAAAAQF9eEMAAAAAgAAAAUF9eEMAAAAAwAAAAgAAAAGAAAABAAAAAcF9eELAAAABQX14QkF9eEKAAAABAAAAAsAAAAJAAAABgAAAAoF9eEIAAAABwX14QYF9eEHAAAABQAAAAwF9eEFAAAABgX14QQF9eEFAAAAAwX14QEAAAAOAAAABAX14QIF9eEDAAAACAAAABAAAAAQAAAACQAAABEAAAARAAAACgAAABIAAAASAAAACwAAABMAAAATAAAADAAAABQAAAAUAAAADQAAAAIAAAACAAAADgAAAA8AAAAPAAAADwAAABUAAAAVAAAAEAAAABYAAAAW" +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-rule-set.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-rule-set.json new file mode 100644 index 000000000000..74d707c19c06 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-rule-set.json @@ -0,0 +1,381 @@ +{ + "version": "1.0", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": false, + "documentation": "The AWS region used to dispatch the request.", + "type": "string" + }, + "UseDualStack": { + "builtIn": "AWS::UseDualStack", + "required": true, + "default": false, + "documentation": "When true, use the dual-stack endpoint. If the configured endpoint does not support dual-stack, dispatching the request MAY return an error.", + "type": "boolean" + }, + "UseFIPS": { + "builtIn": "AWS::UseFIPS", + "required": true, + "default": false, + "documentation": "When true, send this request to the FIPS-compliant regional endpoint. If the configured endpoint does not have a FIPS compliant endpoint, dispatching the request will return an error.", + "type": "boolean" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint used to send this request", + "type": "string" + }, + "AccountId": { + "builtIn": "AWS::Auth::AccountId", + "required": false, + "documentation": "The AWS account ID, read off the resolved identity.", + "type": "string" + }, + "AccountIdEndpointMode": { + "builtIn": "AWS::Auth::AccountIdEndpointMode", + "required": false, + "documentation": "Whether the account ID may be used in the endpoint.", + "type": "string" + }, + "clientStringParam": { + "required": false, + "documentation": "A client context parameter, so the cache key compares it early as reference-stable.", + "type": "string" + }, + "staticStringParam": { + "required": false, + "documentation": "Bound to a per-operation static literal.", + "type": "string" + }, + "requestStringParam": { + "required": false, + "documentation": "Bound to a request member, so it can change per request.", + "type": "string" + }, + "resourceArnList": { + "required": false, + "documentation": "Read only as resourceArnList[0], so the cache key compares just the first element. This is the DynamoDB shape.", + "type": "stringArray" + }, + "unusedStringParam": { + "required": false, + "documentation": "Declared but read by no condition and no result, so the cache key must leave it out.", + "type": "string" + }, + "wholeArnList": { + "required": false, + "documentation": "Read as a whole, so the cache key compares every element.", + "type": "stringArray" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "error": "Invalid Configuration: FIPS and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported", + "type": "error" + }, + { + "conditions": [], + "endpoint": { + "url": { + "ref": "Endpoint" + }, + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Region" + } + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "aws.partition", + "argv": [ + { + "ref": "Region" + } + ], + "assign": "PartitionResult" + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + }, + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + } + ] + }, + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "FIPS and DualStack are enabled, but this partition does not support one or both", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseFIPS" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsFIPS" + ] + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + }, + "aws-us-gov" + ] + } + ], + "endpoint": { + "url": "https://connect.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect-fips.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "FIPS is enabled but this partition does not support FIPS", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + { + "ref": "UseDualStack" + }, + true + ] + } + ], + "rules": [ + { + "conditions": [ + { + "fn": "booleanEquals", + "argv": [ + true, + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "supportsDualStack" + ] + } + ] + } + ], + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dualStackDnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "DualStack is enabled but this partition does not support DualStack", + "type": "error" + } + ], + "type": "tree" + }, + { + "conditions": [], + "endpoint": { + "url": "https://connect.{Region}.{PartitionResult#dnsSuffix}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ], + "type": "tree" + } + ], + "type": "tree" + }, + { + "conditions": [], + "error": "Invalid Configuration: Missing Region", + "type": "error" + } + ] +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-tests.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-tests.json new file mode 100644 index 000000000000..189614f2396c --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/endpoint-tests.json @@ -0,0 +1,413 @@ +{ + "testCases": [ + { + "documentation": "For region af-south-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.af-south-1.amazonaws.com" + } + }, + "params": { + "Region": "af-south-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region ap-northeast-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.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://connect.ap-northeast-2.amazonaws.com" + } + }, + "params": { + "Region": "ap-northeast-2", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region ap-southeast-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.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://connect.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", + "expect": { + "endpoint": { + "url": "https://connect.ca-central-1.amazonaws.com" + } + }, + "params": { + "Region": "ca-central-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region eu-central-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.eu-central-1.amazonaws.com" + } + }, + "params": { + "Region": "eu-central-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region eu-west-2 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.eu-west-2.amazonaws.com" + } + }, + "params": { + "Region": "eu-west-2", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-west-2 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-west-2.amazonaws.com" + } + }, + "params": { + "Region": "us-west-2", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.us-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect.us-east-1.api.aws" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region cn-north-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region cn-north-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region cn-north-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect.cn-north-1.api.amazonwebservices.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region cn-north-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.cn-north-1.amazonaws.com.cn" + } + }, + "params": { + "Region": "cn-north-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-gov-west-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-west-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-gov-west-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-west-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.us-gov-east-1.api.aws" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": true, + "UseDualStack": true + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack enabled", + "expect": { + "endpoint": { + "url": "https://connect.us-gov-east-1.api.aws" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": false, + "UseDualStack": true + } + }, + { + "documentation": "For region us-gov-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-gov-east-1.amazonaws.com" + } + }, + "params": { + "Region": "us-gov-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-iso-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-iso-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-iso-east-1.c2s.ic.gov" + } + }, + "params": { + "Region": "us-iso-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For region us-isob-east-1 with FIPS enabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect-fips.us-isob-east-1.sc2s.sgov.gov" + } + }, + "params": { + "Region": "us-isob-east-1", + "UseFIPS": true, + "UseDualStack": false + } + }, + { + "documentation": "For region us-isob-east-1 with FIPS disabled and DualStack disabled", + "expect": { + "endpoint": { + "url": "https://connect.us-isob-east-1.sc2s.sgov.gov" + } + }, + "params": { + "Region": "us-isob-east-1", + "UseFIPS": false, + "UseDualStack": false + } + }, + { + "documentation": "For custom endpoint with region set and fips disabled and dualstack disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with region not set and fips disabled and dualstack disabled", + "expect": { + "endpoint": { + "url": "https://example.com" + } + }, + "params": { + "UseFIPS": false, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with fips enabled and dualstack disabled", + "expect": { + "error": "Invalid Configuration: FIPS and custom endpoint are not supported" + }, + "params": { + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": false, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "For custom endpoint with fips disabled and dualstack enabled", + "expect": { + "error": "Invalid Configuration: Dualstack and custom endpoint are not supported" + }, + "params": { + "Region": "us-east-1", + "UseFIPS": false, + "UseDualStack": true, + "Endpoint": "https://example.com" + } + }, + { + "documentation": "Missing region", + "expect": { + "error": "Invalid Configuration: Missing Region" + } + } + ], + "version": "1.0" +} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/service-2.json new file mode 100644 index 000000000000..0b1408801fca --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/bddendpoints/service-2.json @@ -0,0 +1,145 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2024-01-01", + "endpointPrefix": "bddendpoints", + "jsonVersion": "1.1", + "protocol": "rest-json", + "serviceAbbreviation": "BddEndpoints", + "serviceFullName": "BDD Endpoint Resolution Test Service", + "serviceId": "BddEndpoints", + "signatureVersion": "v4", + "signingName": "bddendpoints", + "uid": "bddendpoints-2024-01-01", + "auth": [ + "aws.auth#sigv4" + ] + }, + "clientContextParams": { + "clientStringParam": { + "documentation": "A client-level string context parameter.", + "type": "string" + } + }, + "operations": { + "TestOperation": { + "name": "TestOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "TestOperationRequest" + }, + "output": { + "shape": "TestOperationResponse" + } + }, + "OperationWithStaticParam": { + "name": "OperationWithStaticParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "staticContextParams": { + "staticStringParam": { + "value": "static-value" + } + }, + "input": { + "shape": "TestOperationRequest" + }, + "output": { + "shape": "TestOperationResponse" + } + }, + "OperationWithContextParam": { + "name": "OperationWithContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "ContextParamInput" + }, + "output": { + "shape": "TestOperationResponse" + } + }, + "OperationWithListContextParam": { + "name": "OperationWithListContextParam", + "http": { + "method": "POST", + "requestUri": "/" + }, + "operationContextParams": { + "resourceArnList": { + "path": "Items[*].Arn" + }, + "wholeArnList": { + "path": "Items[*].Arn" + } + }, + "input": { + "shape": "ListContextParamInput" + }, + "output": { + "shape": "TestOperationResponse" + } + } + }, + "shapes": { + "TestOperationRequest": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "TestOperationResponse": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "ContextParamInput": { + "type": "structure", + "members": { + "RequestMember": { + "shape": "String", + "contextParam": { + "name": "requestStringParam" + } + } + } + }, + "ListContextParamInput": { + "type": "structure", + "members": { + "Items": { + "shape": "ItemList" + } + } + }, + "ItemList": { + "type": "list", + "member": { + "shape": "Item" + } + }, + "Item": { + "type": "structure", + "members": { + "Arn": { + "shape": "String" + } + } + }, + "String": { + "type": "string" + } + } +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/compiledrules/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/compiledrules/customization.config index e824e95e8fbd..2c63c0851048 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/compiledrules/customization.config +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/compiledrules/customization.config @@ -1,3 +1,2 @@ { - "enableGenerateCompiledEndpointRules": true } diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/defaultretrymode/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/defaultretrymode/customization.config index f0057184b8e0..365f086ad0f9 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/defaultretrymode/customization.config +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/defaultretrymode/customization.config @@ -1,6 +1,4 @@ { - "defaultRetryMode": "STANDARD", + "defaultRetryMode": "STANDARD" - - "enableGenerateCompiledEndpointRules": true } \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/endpointproviders/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/endpointproviders/customization.config index 341d2bca3aa5..41d9edb67337 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/endpointproviders/customization.config +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/endpointproviders/customization.config @@ -1,7 +1,6 @@ { "skipEndpointTestGeneration": true, - "enableGenerateCompiledEndpointRules": false, "endpointParameters": { "PojoString": { "required": false, diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/json/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/json/service-2.json new file mode 100644 index 000000000000..c0372d42aa46 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/json/service-2.json @@ -0,0 +1,38 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2010-05-08", + "endpointPrefix":"json-service-endpoint", + "globalEndpoint": "json-service.amazonaws.com", + "jsonVersion":"1.0", + "protocol":"json", + "serviceAbbreviation":"Aws Json Service", + "serviceFullName":"Some Service That Uses AWS JSON", + "serviceId":"Aws Json Service", + "signingName": "aws-json-service", + "signatureVersion":"v4", + "uid":"aws-json-service-2010-05-08", + "awsQueryCompatible":{} + }, + "operations":{ + "AllType": { + "name": "APostOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "httpChecksumRequired": true + } + }, + "shapes": { + "OneShape": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "String":{"type":"string"} + } +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-rule-set.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-rule-set.json new file mode 100644 index 000000000000..c7620b774705 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-rule-set.json @@ -0,0 +1,54 @@ +{ + "version": "1.2", + "serviceId": "NoRegionService", + "parameters": { + "Endpoint": { + "type": "string", + "builtIn": "SDK::Endpoint", + "documentation": "Override the endpoint used to send this request" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [ + { + "ref": "Endpoint" + } + ] + } + ], + "endpoint": { + "url": "{Endpoint}", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1", + "signingName": "noregionservice" + } + ] + } + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://noregionservice.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1", + "signingName": "noregionservice" + } + ] + } + }, + "type": "endpoint" + } + ] +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-tests.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-tests.json new file mode 100644 index 000000000000..50828b80c56e --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/endpoint-tests.json @@ -0,0 +1,23 @@ +{ + "testCases": [ + { + "documentation": "Default endpoint", + "params": {}, + "expect": { + "endpoint": { + "url": "https://noregionservice.us-east-1.amazonaws.com", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "us-east-1", + "signingName": "noregionservice" + } + ] + } + } + } + } + ], + "version": "1.0" +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/service-2.json new file mode 100644 index 000000000000..98519f7ee453 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/noregionservice/service-2.json @@ -0,0 +1,50 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2023-01-01", + "endpointPrefix": "noregionservice", + "protocol": "json", + "serviceFullName": "No Region Service", + "serviceId": "NoRegionService", + "signatureVersion": "v4", + "signingName": "noregionservice", + "jsonVersion": "1.1", + "targetPrefix": "NoRegionService" + }, + "operations": { + "SomeOperation": { + "name": "SomeOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "SomeOperationRequest" + }, + "output": { + "shape": "SomeOperationResponse" + } + } + }, + "shapes": { + "SomeOperationRequest": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "SomeOperationResponse": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "String": { + "type": "string" + } + } +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config new file mode 100644 index 000000000000..2c63c0851048 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/customization.config @@ -0,0 +1,2 @@ +{ +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json new file mode 100644 index 000000000000..1e17a2a8641c --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-rule-set.json @@ -0,0 +1,42 @@ +{ + "version": "1.0", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region - declared but never referenced in rules", + "type": "string" + }, + "Endpoint": { + "builtIn": "SDK::Endpoint", + "required": false, + "documentation": "Override the endpoint", + "type": "string" + } + }, + "rules": [ + { + "conditions": [ + { + "fn": "isSet", + "argv": [{"ref": "Endpoint"}] + } + ], + "endpoint": { + "url": "{Endpoint}", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [], + "endpoint": { + "url": "https://regionnotused.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + } + ] +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json new file mode 100644 index 000000000000..3ce5aaf4f010 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/endpoint-tests.json @@ -0,0 +1 @@ +{"testCases": []} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json new file mode 100644 index 000000000000..2457bb476052 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/regionnotused/service-2.json @@ -0,0 +1,37 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2023-01-01", + "endpointPrefix": "regionnotused", + "protocol": "rest-json", + "serviceFullName": "Region Not Used Test Service", + "serviceId": "RegionNotUsed", + "signatureVersion": "v4", + "uid": "regionnotused-2023-01-01" + }, + "operations": { + "DoSomething": { + "name": "DoSomething", + "http": { + "method": "POST", + "requestUri": "/do-something" + }, + "input": { + "shape": "DoSomethingRequest" + }, + "output": { + "shape": "DoSomethingResponse" + } + } + }, + "shapes": { + "DoSomethingRequest": { + "type": "structure", + "members": {} + }, + "DoSomethingResponse": { + "type": "structure", + "members": {} + } + } +} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config index 4a57cda840dd..f137036979c6 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "skipEndpointTestGeneration": true } diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/customization.config index bb763afd276b..ec7c8d355d50 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/customization.config +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/customization.config @@ -1,4 +1,3 @@ { - "skipEndpointTestGeneration": true, - "enableGenerateCompiledEndpointRules": true + "skipEndpointTestGeneration": true } diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/service-2.json index 7f630bcea8d3..9ac538399676 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/service-2.json +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/stringarray/service-2.json @@ -73,6 +73,18 @@ "method": "POST", "requestUri": "/" } + }, + "NestedMapOperation": { + "input": { "shape": "NestedMapOperationRequest" }, + "operationContextParams": { + "stringArrayParam": { + "path": "keys(nestedMap.map)" + } + }, + "http": { + "method": "POST", + "requestUri": "/" + } } }, "shapes": { @@ -125,6 +137,18 @@ "map":{"shape":"Map"} } }, + "NestedMapOperationRequest": { + "type": "structure", + "members": { + "nestedMap":{"shape":"NestedMap"} + } + }, + "NestedMap": { + "type": "structure", + "members": { + "map":{"shape":"Map"} + } + }, "Map":{ "type":"map", "key":{"shape":"String"}, diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestCompressionTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestCompressionTest.java index df5b327a5442..b6d0ec381a7d 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestCompressionTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestCompressionTest.java @@ -83,7 +83,7 @@ public void asyncNonStreamingOperation_compressionEnabledThresholdOverridden_com c -> c.minimumCompressionThresholdInBytes(1))) .build(); - asyncClient.putOperationWithRequestCompression(request); + asyncClient.putOperationWithRequestCompression(request).join(); SdkHttpFullRequest loggedRequest = (SdkHttpFullRequest) mockAsyncHttpClient.getLastRequest(); InputStream loggedStream = loggedRequest.contentStreamProvider().get().newStream(); @@ -104,7 +104,7 @@ public void asyncNonStreamingOperation_payloadSizeLessThanCompressionThreshold_d .body(SdkBytes.fromUtf8String(UNCOMPRESSED_BODY)) .build(); - asyncClient.putOperationWithRequestCompression(request); + asyncClient.putOperationWithRequestCompression(request).join(); SdkHttpFullRequest loggedRequest = (SdkHttpFullRequest) mockAsyncHttpClient.getLastRequest(); InputStream loggedStream = loggedRequest.contentStreamProvider().get().newStream(); @@ -148,7 +148,7 @@ public void asyncNonStreamingOperation_compressionEnabledThresholdOverriddenWith c -> c.minimumCompressionThresholdInBytes(1))) .build(); - asyncClient.putOperationWithRequestCompression(request); + asyncClient.putOperationWithRequestCompression(request).join(); SdkHttpFullRequest loggedRequest = (SdkHttpFullRequest) mockAsyncHttpClient.getLastRequest(); InputStream loggedStream = loggedRequest.contentStreamProvider().get().newStream(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java index ab9394e70ac0..f95312956612 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/BusinessMetricsUserAgentTest.java @@ -246,7 +246,7 @@ void validate_serviceUserAgent_format() { .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) .build(); - client.headOperation(); + assertThatThrownBy(client.headOperation()::join); String userAgent = assertAndGetUserAgentString(); assertThat(userAgent).contains("AmazonProtocolRestJson#" + ServiceVersionInfo.VERSION); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/EndpointSharedConfigTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/EndpointSharedConfigTest.java index 78662bb0dc59..cc969843b877 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/EndpointSharedConfigTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/EndpointSharedConfigTest.java @@ -12,6 +12,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; import software.amazon.awssdk.profiles.ProfileFile; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; @@ -28,6 +29,8 @@ public class EndpointSharedConfigTest { private static final String GLOBAL_SYS_PROP = "aws.endpointUrl"; private static final String SERVICE_ENV_VAR = "AWS_ENDPOINT_URL_AMAZONPROTOCOLRESTJSON"; private static final String SERVICE_SYS_PROP = "aws.endpointUrlProtocolRestJson"; + private static final String IGNORE_ENDPOINT_URLS_SYS_PROP = + SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(); @Parameterized.Parameter public TestCase testCase; @@ -37,6 +40,7 @@ public void resolvesCorrectEndpoint() { Map systemPropertiesBeforeTest = new HashMap<>(); systemPropertiesBeforeTest.put(GLOBAL_SYS_PROP, System.getProperty(GLOBAL_SYS_PROP)); systemPropertiesBeforeTest.put(SERVICE_SYS_PROP, System.getProperty(SERVICE_SYS_PROP)); + systemPropertiesBeforeTest.put(IGNORE_ENDPOINT_URLS_SYS_PROP, System.getProperty(IGNORE_ENDPOINT_URLS_SYS_PROP)); EnvironmentVariableHelper helper = new EnvironmentVariableHelper(); @@ -66,6 +70,10 @@ public void resolvesCorrectEndpoint() { System.setProperty(SERVICE_SYS_PROP, testCase.serviceSystemPropSetting); } + if (testCase.ignoreConfiguredEndpointUrls) { + System.setProperty(IGNORE_ENDPOINT_URLS_SYS_PROP, "true"); + } + StringBuilder profileFileContent = new StringBuilder(); profileFileContent.append("[default]\n"); if (testCase.globalProfileSetting != null) { @@ -128,7 +136,8 @@ public static Iterable testCases() { "Global environment variable", "Services Section profile file", "Service profile file", - "Global profile file"); + "Global profile file", + "Ignore configured endpoint URLs"); boolean[][] settingCombinations = getSettingCombinations(settingNames.size()); @@ -161,6 +170,9 @@ private static TestCase createCase(List settingNames, } } + boolean ignoreConfiguredEndpointUrls = settings[8]; + expectedEndpointIndex = applyIgnoreConfiguredEndpointUrls(expectedEndpointIndex, ignoreConfiguredEndpointUrls); + // Create case name String caseName; if (firstTrueSetting == null) { @@ -176,7 +188,17 @@ private static TestCase createCase(List settingNames, caseName += "."; } - return new TestCase(settings, expectedEndpointIndex, caseName); + return new TestCase(settings, expectedEndpointIndex, ignoreConfiguredEndpointUrls, caseName); + } + + /** + * When ignore_configured_endpoint_urls is true, all endpoint sources are suppressed except client override (index 0). + */ + private static Integer applyIgnoreConfiguredEndpointUrls(Integer expectedEndpointIndex, boolean ignore) { + if (!ignore || Integer.valueOf(0).equals(expectedEndpointIndex)) { + return expectedEndpointIndex; + } + return null; } public static void printArrayOfArrays(boolean[][] arrays) { @@ -229,13 +251,15 @@ public static class TestCase { private final String serviceProfileSetting; private final String globalProfileSetting; private final String serviceSectionProfileSetting; + private final boolean ignoreConfiguredEndpointUrls; private final String caseName; private final String expectedEndpoint; - public TestCase(boolean[] settings, Integer expectedEndpointIndex, String caseName) { + public TestCase(boolean[] settings, Integer expectedEndpointIndex, boolean ignoreConfiguredEndpointUrls, + String caseName) { this(endpoint(settings, 0), endpoint(settings, 1), endpoint(settings, 2), endpoint(settings, 3), endpoint(settings, 4), endpoint(settings, 5), endpoint(settings, 6), endpoint(settings, 7), - endpointForIndex(expectedEndpointIndex), caseName); + ignoreConfiguredEndpointUrls, endpointForIndex(expectedEndpointIndex), caseName); } private static String endpoint(boolean[] settings, int i) { @@ -257,6 +281,7 @@ private TestCase(String clientSetting, String serviceSectionProfileSetting, String serviceProfileSetting, String globalProfileSetting, + boolean ignoreConfiguredEndpointUrls, String expectedEndpoint, String caseName) { this.clientSetting = clientSetting; @@ -267,6 +292,7 @@ private TestCase(String clientSetting, this.serviceProfileSetting = serviceProfileSetting; this.globalProfileSetting = globalProfileSetting; this.serviceSectionProfileSetting = serviceSectionProfileSetting; + this.ignoreConfiguredEndpointUrls = ignoreConfiguredEndpointUrls; this.expectedEndpoint = expectedEndpoint; this.caseName = caseName; } 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 f24f7f35d1c6..1424545509bc 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 @@ -105,9 +105,9 @@ public void sync_json_nonStreaming_unsignedPayload_with_Sha1_in_header() { } @Test - public void aync_json_nonStreaming_unsignedPayload_with_Sha1_in_header() { + public void async_json_nonStreaming_unsignedPayload_with_Sha1_in_header() { jsonAsyncClient.operationWithChecksumNonStreaming( - r -> r.checksumAlgorithm(ChecksumAlgorithm.SHA1).stringMember("Hello world").build()); + r -> r.checksumAlgorithm(ChecksumAlgorithm.SHA1).stringMember("Hello world").build()).join(); assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); //Note that content will be of form "{"stringMember":"Hello world"}" assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("M68rRwFal7o7B3KEMt3m0w39TaA="); @@ -132,7 +132,7 @@ public void sync_xml_nonStreaming_unsignedEmptyPayload_with_Sha1_in_header() { } @Test - public void aync_xml_nonStreaming_unsignedPayload_with_Sha1_in_header() { + public void async_xml_nonStreaming_unsignedPayload_with_Sha1_in_header() { xmlAsyncClient.operationWithChecksumNonStreaming(r -> r.stringMember("Hello world") .checksumAlgorithm(software.amazon.awssdk.services.protocolrestxml.model.ChecksumAlgorithm.SHA1).build()).join(); assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); @@ -141,7 +141,7 @@ public void aync_xml_nonStreaming_unsignedPayload_with_Sha1_in_header() { } @Test - public void aync_xml_nonStreaming_unsignedEmptyPayload_with_Sha1_in_header() { + public void async_xml_nonStreaming_unsignedEmptyPayload_with_Sha1_in_header() { xmlAsyncClient.operationWithChecksumNonStreaming(r -> r.checksumAlgorithm(software.amazon.awssdk.services.protocolrestxml.model.ChecksumAlgorithm.SHA1).build()).join(); assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/IgnoreConfiguredEndpointUrlsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/IgnoreConfiguredEndpointUrlsTest.java new file mode 100644 index 000000000000..1ef0323fcd9b --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/IgnoreConfiguredEndpointUrlsTest.java @@ -0,0 +1,284 @@ +/* + * 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 java.net.URI; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClientBuilder; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Tests that the {@code ignore_configured_endpoint_urls} setting correctly suppresses endpoint URL resolution from + * environment variables, system properties, and the shared configuration file, while preserving programmatic + * endpoint overrides set on the client builder. + */ +class IgnoreConfiguredEndpointUrlsTest { + private static final String SERVICE_ENV_VAR = "AWS_ENDPOINT_URL_AMAZONPROTOCOLRESTJSON"; + private static final String GLOBAL_ENV_VAR = "AWS_ENDPOINT_URL"; + private static final String SERVICE_SYS_PROP = "aws.endpointUrlProtocolRestJson"; + private static final String GLOBAL_SYS_PROP = "aws.endpointUrl"; + private static final String DEFAULT_ENDPOINT = "https://customresponsemetadata.us-west-2.amazonaws.com"; + private static final String ENV_ENDPOINT = "https://env-endpoint.example.com"; + private static final String PROFILE_ENDPOINT = "https://profile-endpoint.example.com"; + private static final String CLIENT_OVERRIDE_ENDPOINT = "https://client-override.example.com"; + + private final EnvironmentVariableHelper helper = new EnvironmentVariableHelper(); + + @BeforeEach + void setup() { + helper.reset(); + System.clearProperty(GLOBAL_SYS_PROP); + System.clearProperty(SERVICE_SYS_PROP); + System.clearProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property()); + } + + @AfterEach + void teardown() { + helper.reset(); + System.clearProperty(GLOBAL_SYS_PROP); + System.clearProperty(SERVICE_SYS_PROP); + System.clearProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property()); + } + + @Test + void defaultBehavior_endpointFromEnvVarIsUsed() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(ENV_ENDPOINT); + } + + @Test + void ignoreViaSystemProperty_endpointFromEnvVarIsIgnored() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreViaEnvVar_endpointFromEnvVarIsIgnored() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + helper.set(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS, "true"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreViaProfile_endpointFromEnvVarIsIgnored() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + + ProfileFile profileFile = profileWithIgnore("true", null); + String resolved = resolveEndpoint(null, profileFile); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreViaProfile_profileEndpointInSameProfileIsAlsoIgnored() { + ProfileFile profileFile = profileWithIgnore("true", PROFILE_ENDPOINT); + String resolved = resolveEndpoint(null, profileFile); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_globalEnvVarIsIgnored() { + helper.set(GLOBAL_ENV_VAR, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_serviceSysPropIsIgnored() { + System.setProperty(SERVICE_SYS_PROP, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_globalSysPropIsIgnored() { + System.setProperty(GLOBAL_SYS_PROP, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_profileEndpointIsIgnored() { + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + ProfileFile profileFile = profileWithEndpoint(PROFILE_ENDPOINT); + String resolved = resolveEndpoint(null, profileFile); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_servicesSectionEndpointIsIgnored() { + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + ProfileFile profileFile = profileWithServicesSection(PROFILE_ENDPOINT); + String resolved = resolveEndpoint(null, profileFile); + + assertThat(resolved).startsWith(DEFAULT_ENDPOINT); + } + + @Test + void ignoreTrue_programmaticEndpointOverrideStillWorks() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + String resolved = resolveEndpoint(URI.create(CLIENT_OVERRIDE_ENDPOINT), null); + + assertThat(resolved).startsWith(CLIENT_OVERRIDE_ENDPOINT); + } + + @Test + void ignoreTrue_programmaticEndpointOverrideWorksEvenWithAllSourcesConfigured() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + helper.set(GLOBAL_ENV_VAR, ENV_ENDPOINT); + System.setProperty(SERVICE_SYS_PROP, ENV_ENDPOINT); + System.setProperty(GLOBAL_SYS_PROP, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + ProfileFile profileFile = profileWithEndpoint(PROFILE_ENDPOINT); + String resolved = resolveEndpoint(URI.create(CLIENT_OVERRIDE_ENDPOINT), profileFile); + + assertThat(resolved).startsWith(CLIENT_OVERRIDE_ENDPOINT); + } + + @Test + void ignoreFalse_endpointFromEnvVarIsUsed() { + helper.set(SERVICE_ENV_VAR, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "false"); + + String resolved = resolveEndpoint(null, null); + + assertThat(resolved).startsWith(ENV_ENDPOINT); + } + + @Test + void ignoreTrue_isEndpointOverriddenReturnsFalseWhenFallingToDefault() { + System.setProperty(SERVICE_SYS_PROP, ENV_ENDPOINT); + System.setProperty(SdkSystemSetting.AWS_IGNORE_CONFIGURED_ENDPOINT_URLS.property(), "true"); + + EndpointCapturingInterceptor interceptor = new EndpointCapturingInterceptor(); + ProtocolRestJsonClient client = baseBuilder(null, null) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) + .build(); + + try { + client.allTypes(); + } catch (EndpointCapturingInterceptor.CaptureCompletedException e) { + // expected + } + + assertThat(interceptor.endpoints()).singleElement().asString().startsWith(DEFAULT_ENDPOINT); + } + + private String resolveEndpoint(URI endpointOverride, ProfileFile profileFile) { + EndpointCapturingInterceptor interceptor = new EndpointCapturingInterceptor(); + + ProtocolRestJsonClientBuilder builder = baseBuilder(endpointOverride, profileFile); + builder.overrideConfiguration(c -> { + if (profileFile != null) { + c.defaultProfileFile(profileFile).defaultProfileName("default"); + } + c.addExecutionInterceptor(interceptor); + }); + + ProtocolRestJsonClient client = builder.build(); + + try { + client.allTypes(); + } catch (EndpointCapturingInterceptor.CaptureCompletedException e) { + // expected + } + + assertThat(interceptor.endpoints()).hasSize(1); + return interceptor.endpoints().get(0); + } + + private ProtocolRestJsonClientBuilder baseBuilder(URI endpointOverride, ProfileFile profileFile) { + ProtocolRestJsonClientBuilder builder = + ProtocolRestJsonClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(AnonymousCredentialsProvider.create()); + + if (endpointOverride != null) { + builder.endpointOverride(endpointOverride); + } + + return builder; + } + + private static ProfileFile profileWithIgnore(String ignoreValue, String endpointUrl) { + StringBuilder content = new StringBuilder(); + content.append("[default]\n"); + content.append("ignore_configured_endpoint_urls = ").append(ignoreValue).append("\n"); + if (endpointUrl != null) { + content.append("endpoint_url = ").append(endpointUrl).append("\n"); + } + return ProfileFile.builder() + .type(ProfileFile.Type.CONFIGURATION) + .content(content.toString()) + .build(); + } + + private static ProfileFile profileWithEndpoint(String endpointUrl) { + String content = "[default]\n" + + "endpoint_url = " + endpointUrl + "\n"; + return ProfileFile.builder() + .type(ProfileFile.Type.CONFIGURATION) + .content(content) + .build(); + } + + private static ProfileFile profileWithServicesSection(String endpointUrl) { + String content = "[default]\n" + + "services = dev\n\n" + + "[services dev]\n" + + "amazonprotocolrestjson =\n" + + " endpoint_url = " + endpointUrl + "\n"; + return ProfileFile.builder() + .type(ProfileFile.Type.CONFIGURATION) + .content(content) + .build(); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/NoneAuthTypeRequestTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/NoneAuthTypeRequestTest.java index 20ceeee91815..d193c7087f11 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/NoneAuthTypeRequestTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/NoneAuthTypeRequestTest.java @@ -113,14 +113,14 @@ public void sync_json_authorization_is_present_for_defaultAuth() { @Test public void async_json_authorization_is_absent_for_noneAuthType() { - jsonAsyncClient.operationWithNoneAuthType(o -> o.booleanMember(true)); + jsonAsyncClient.operationWithNoneAuthType(o -> o.booleanMember(true)).join(); assertThat(getAsyncRequest().firstMatchingHeader("Authorization")).isNotPresent(); verify(credentialsProvider, times(0)).resolveIdentity(any(ResolveIdentityRequest.class)); } @Test public void async_json_authorization_is_present_for_defaultAuth() { - jsonAsyncClient.jsonValuesOperation(); + jsonAsyncClient.jsonValuesOperation().join(); assertThat(getAsyncRequest().firstMatchingHeader("Authorization")).isPresent(); verify(credentialsProvider, times(1)).resolveIdentity(any(ResolveIdentityRequest.class)); } @@ -141,14 +141,14 @@ public void sync_xml_authorization_is_present_for_defaultAuth() { @Test public void async_xml_authorization_is_absent_for_noneAuthType() { - xmlAsyncClient.operationWithNoneAuthType(o -> o.booleanMember(true)); + xmlAsyncClient.operationWithNoneAuthType(o -> o.booleanMember(true)).join(); assertThat(getAsyncRequest().firstMatchingHeader("Authorization")).isNotPresent(); verify(credentialsProvider, times(0)).resolveIdentity(any(ResolveIdentityRequest.class)); } @Test public void async_xml_authorization_is_present_for_defaultAuth() { - xmlAsyncClient.jsonValuesOperation(json -> json.jsonValueMember("one")); + xmlAsyncClient.jsonValuesOperation(json -> json.jsonValueMember("one")).join(); assertThat(getAsyncRequest().firstMatchingHeader("Authorization")).isPresent(); verify(credentialsProvider, times(1)).resolveIdentity(any(ResolveIdentityRequest.class)); } diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/ProfileFileConfigurationTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/ProfileFileConfigurationTest.java index d8a11a0b76b2..21df46df84ff 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/ProfileFileConfigurationTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/ProfileFileConfigurationTest.java @@ -41,6 +41,7 @@ import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner; import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; +import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; import software.amazon.awssdk.http.auth.spi.signer.SignRequest; import software.amazon.awssdk.http.auth.spi.signer.SignedRequest; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; @@ -197,7 +198,7 @@ public void streamingOperation_asyncHttpSigner_profileIsHonoredForCredentialsAnd env.remove(SdkSystemSetting.AWS_ACCESS_KEY_ID); env.remove(SdkSystemSetting.AWS_SECRET_ACCESS_KEY); - Mockito.when(signer.signAsync(any(AsyncSignRequest.class))).thenReturn(CompletableFuture.completedFuture(any(AsyncSignRequest.class))); + Mockito.when(signer.signAsync(any(AsyncSignRequest.class))).thenReturn(CompletableFuture.completedFuture(mock(AsyncSignedRequest.class))); ProtocolRestJsonAsyncClient asyncClient = asyncClientWithHttpSignerOverride(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/auth/AuthSchemeCacheTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/auth/AuthSchemeCacheTest.java new file mode 100644 index 000000000000..6474ad1eb101 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/auth/AuthSchemeCacheTest.java @@ -0,0 +1,270 @@ +/* + * 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.auth; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.awscore.AwsExecutionAttribute; +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.SdkHttpClient; +import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; +import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.multiauth.MultiauthClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.auth.scheme.ProtocolRestJsonAuthSchemeParams; +import software.amazon.awssdk.services.protocolrestjson.auth.scheme.ProtocolRestJsonAuthSchemeProvider; + +class AuthSchemeCacheTest { + + @Mock + private SdkHttpClient mockHttpClient; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + when(mockHttpClient.clientName()).thenReturn("MockHttpClient"); + when(mockHttpClient.prepareRequest(any())) + .thenThrow(new RuntimeException("stop")); + } + + @Test + void customClientProvider_isNotCached() { + AtomicInteger resolveCount = new AtomicInteger(0); + + ProtocolRestJsonAuthSchemeProvider customProvider = params -> { + resolveCount.incrementAndGet(); + return Collections.singletonList( + AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build()); + }; + + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .authSchemeProvider(customProvider) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(resolveCount.get()).isEqualTo(1); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(resolveCount.get()).isEqualTo(2); + + client.close(); + } + + @Test + void perRequestOverride_usesOverrideProvider() { + AtomicInteger requestProviderCount = new AtomicInteger(0); + + ProtocolRestJsonAuthSchemeProvider requestProvider = params -> { + requestProviderCount.incrementAndGet(); + return Collections.singletonList( + AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build()); + }; + + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(requestProviderCount.get()).isEqualTo(0); + + assertThatThrownBy(() -> client.allTypes(r -> r.overrideConfiguration( + c -> c.authSchemeProvider(requestProvider) + ))).hasMessageContaining("stop"); + assertThat(requestProviderCount.get()).isEqualTo(1); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(requestProviderCount.get()).isEqualTo(1); + + client.close(); + } + + @Test + void defaultProvider_multipleOperationsSucceed() { + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThatThrownBy(() -> client.deleteOperation(r -> {})).hasMessageContaining("stop"); + assertThatThrownBy(() -> client.deleteOperation(r -> {})).hasMessageContaining("stop"); + + client.close(); + } + + @Test + void defaultProvider_returnsUnmodifiableList() { + List options = ProtocolRestJsonAuthSchemeProvider.defaultProvider().resolveAuthScheme( + ProtocolRestJsonAuthSchemeParams.builder().operation("AllTypes").region(Region.US_WEST_2).build()); + + assertThat(options).isNotEmpty(); + assertThatThrownBy(() -> options.add(AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build())) + .isInstanceOf(UnsupportedOperationException.class); + } + + @Test + void defaultProvider_cachesUnmodifiableListAndReusesInstance() throws Exception { + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + + Map> cache = authSchemeCache(client); + assertThat(cache).isNotEmpty(); + List cached = cache.values().iterator().next(); + + assertThatThrownBy(() -> cached.add(AuthSchemeOption.builder().schemeId(AwsV4AuthScheme.SCHEME_ID).build())) + .isInstanceOf(UnsupportedOperationException.class); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(cache.values().iterator().next()).isSameAs(cached); + + client.close(); + } + + @Test + void perOpAuthService_differentOperationsSeparateCacheEntries() throws Exception { + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + Map> cache = authSchemeCache(client); + assertThat(cache).hasSize(1); + + assertThatThrownBy(() -> client.deleteOperation(r -> {})).hasMessageContaining("stop"); + assertThat(cache).hasSize(2); + + client.close(); + } + + + @Test + void regionChange_causesCacheMiss() throws Exception { + AtomicInteger callCount = new AtomicInteger(0); + ExecutionInterceptor regionSwitcher = new ExecutionInterceptor() { + @Override + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + if (callCount.incrementAndGet() > 1) { + executionAttributes.putAttribute(AwsExecutionAttribute.AWS_REGION, Region.EU_WEST_1); + } + } + }; + + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .overrideConfiguration(c -> c.addExecutionInterceptor(regionSwitcher)) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + Map> cache = authSchemeCache(client); + assertThat(cache).hasSize(1); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(cache).hasSize(2); + + client.close(); + } + + @Test + void cacheHit_returnsSameInstanceOnRepeatedCalls() throws Exception { + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .build(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + Map> cache = authSchemeCache(client); + assertThat(cache).hasSize(1); + List firstResult = cache.values().iterator().next(); + + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThatThrownBy(() -> client.allTypes(r -> {})).hasMessageContaining("stop"); + assertThat(cache).hasSize(1); + assertThat(cache.values().iterator().next()).isSameAs(firstResult); + + client.close(); + } + + @Test + void regionSetChange_causesCacheMiss() throws Exception { + AtomicInteger callCount = new AtomicInteger(0); + ExecutionInterceptor regionSetSwitcher = new ExecutionInterceptor() { + @Override + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + if (callCount.incrementAndGet() > 1) { + executionAttributes.putAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET, + Collections.singleton("eu-west-1")); + } + } + }; + + MultiauthClient client = MultiauthClient.builder() + .httpClient(mockHttpClient) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_WEST_2) + .overrideConfiguration(c -> c.addExecutionInterceptor(regionSetSwitcher)) + .build(); + + assertThatThrownBy(() -> client.multiAuthWithOnlySigv4a(r -> {})).hasMessageContaining("stop"); + Map> cache = authSchemeCache(client); + assertThat(cache).hasSize(1); + + assertThatThrownBy(() -> client.multiAuthWithOnlySigv4a(r -> {})).hasMessageContaining("stop"); + assertThat(cache).hasSize(2); + + client.close(); + } + + @SuppressWarnings("unchecked") + private static Map> authSchemeCache(Object client) throws Exception { + Field field = client.getClass().getDeclaredField("authSchemeCache"); + field.setAccessible(true); + return (Map>) field.get(client); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/bddendpoints/BddEndpointProviderCacheTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/bddendpoints/BddEndpointProviderCacheTest.java new file mode 100644 index 000000000000..45887d41bc15 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/bddendpoints/BddEndpointProviderCacheTest.java @@ -0,0 +1,508 @@ +/* + * 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.bddendpoints; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.bddendpoints.endpoints.BddEndpointsEndpointParams; +import software.amazon.awssdk.services.bddendpoints.endpoints.BddEndpointsEndpointProvider; + +/** + * Behavioural tests for the single-entry result cache generated into the BDD endpoint provider. + * + *

    The suite is organised around the one invariant that matters: a cache hit must be indistinguishable from a fresh + * resolution. That splits into two obligations. + * + *

      + *
    1. No stale hit. Changing any single parameter must not return the endpoint resolved for the previous value. + * Every parameter the model declares gets its own test, because a parameter accidentally left out of the + * generated key check is the one defect here that produces a wrong endpoint rather than a slow one.
    2. + *
    3. Hits where they are due. Equal params must actually reuse the cached instance, otherwise the change is + * cost without benefit. Asserted with {@code isSameAs}, which is the only externally visible evidence that the + * cache was consulted.
    4. + *
    + * + *

    The model over-declares parameters on purpose, to cover every {@code BddParameterReferences.Usage} value and every + * parameter kind: boolean, string, {@code stringArray}, built-in, client context, static context and request context. + * Several of them cannot change the resolved URL, which makes them the more interesting cases to test: a stale hit is + * detectable only by instance identity, not by comparing hosts. + * + *

    The trailing nodes of {@code bddendpoints/endpoint-bdd-1.json} were appended by hand with {@code high == low}, so + * that each parameter is read by a condition without altering any resolved endpoint. A future peephole pass that + * collapses {@code high == low} nodes would silently make those parameters unreferenced and void the coverage above. + */ +class BddEndpointProviderCacheTest { + private static final Region REGION = Region.US_EAST_1; + private static final Region OTHER_REGION = Region.US_WEST_2; + + /** + * Mirrors {@code BddEndpointProviderSpec.MAX_LIST_COMPARISON_SIZE}. Not importable from here, so the cap-related + * tests below derive their sizes from this one constant. + */ + private static final int LIST_SIZE_CAP = 4; + + /** + * Returns params that resolve successfully, with every optional parameter left unset. + */ + private static BddEndpointsEndpointParams.Builder baseBuilder() { + return BddEndpointsEndpointParams.builder() + .region(REGION) + .useDualStack(false) + .useFips(false); + } + + private static BddEndpointsEndpointParams params(Consumer customizer) { + BddEndpointsEndpointParams.Builder builder = baseBuilder(); + customizer.accept(builder); + return builder.build(); + } + + private static BddEndpointsEndpointProvider provider() { + return BddEndpointsEndpointProvider.defaultProvider(); + } + + private static Endpoint resolve(BddEndpointsEndpointProvider provider, BddEndpointsEndpointParams params) { + return provider.resolveEndpoint(params).join(); + } + + /** + * Resolves {@code first}, then {@code second}, and asserts the second call did not reuse the first result. + * + *

    Instance identity rather than URL comparison, so this works for the parameters that do not influence the + * resolved URL. Those are exactly the parameters where a missing key check would go unnoticed. + * + *

    Identity is a valid miss signal only while every resolution constructs a new {@link Endpoint}. If codegen ever + * hoists constant endpoint results to {@code static final}, this helper and {@link #cacheIsPerProviderInstance()} + * start failing for that reason rather than because the cache regressed. + */ + private static void assertInvalidates(BddEndpointsEndpointParams first, BddEndpointsEndpointParams second) { + BddEndpointsEndpointProvider provider = provider(); + Endpoint firstEndpoint = resolve(provider, first); + Endpoint secondEndpoint = resolve(provider, second); + assertThat(secondEndpoint).isNotSameAs(firstEndpoint); + } + + private static void assertHits(BddEndpointsEndpointParams first, BddEndpointsEndpointParams second) { + BddEndpointsEndpointProvider provider = provider(); + Endpoint firstEndpoint = resolve(provider, first); + Endpoint secondEndpoint = resolve(provider, second); + assertThat(secondEndpoint).isSameAs(firstEndpoint); + } + + // ---- hits ---- + + @Test + void sameParamsInstance_reusesCachedEndpoint() { + BddEndpointsEndpointParams p = params(b -> { + }); + assertHits(p, p); + } + + @Test + void distinctButEqualParams_reusesCachedEndpoint() { + assertHits(params(b -> { + }), params(b -> { + })); + } + + @Test + void cacheIsPerProviderInstance() { + BddEndpointsEndpointParams p = params(b -> { + }); + Endpoint fromFirstProvider = resolve(provider(), p); + Endpoint fromSecondProvider = resolve(provider(), p); + assertThat(fromSecondProvider).isNotSameAs(fromFirstProvider); + assertThat(fromSecondProvider.endpointUrl().host()).isEqualTo(fromFirstProvider.endpointUrl().host()); + } + + /** + * The cached endpoint must be the one the params call for, not merely some previously resolved endpoint. Alternating + * between two parameter sets in a loop would pass even if the cache returned the wrong entry, so each round asserts + * the host as well. + */ + @Test + void alternatingParams_eachResolutionMatchesItsOwnParams() { + BddEndpointsEndpointProvider provider = provider(); + BddEndpointsEndpointParams plain = params(b -> { + }); + BddEndpointsEndpointParams fips = params(b -> b.useFips(true)); + + String plainHost = resolve(provider, plain).endpointUrl().host(); + String fipsHost = resolve(provider, fips).endpointUrl().host(); + assertThat(plainHost).doesNotContain("fips"); + assertThat(fipsHost).contains("fips"); + + for (int i = 0; i < 4; i++) { + assertThat(resolve(provider, plain).endpointUrl().host()).isEqualTo(plainHost); + assertThat(resolve(provider, fips).endpointUrl().host()).isEqualTo(fipsHost); + } + } + + // ---- no stale hit, one test per parameter ---- + + @Test + void useFipsChange_invalidates() { + assertInvalidates(params(b -> { + }), params(b -> b.useFips(true))); + } + + @Test + void useDualStackChange_invalidates() { + assertInvalidates(params(b -> { + }), params(b -> b.useDualStack(true))); + } + + @Test + void regionChange_invalidates() { + assertInvalidates(params(b -> { + }), params(b -> b.region(OTHER_REGION))); + } + + @Test + void clientStringParamChange_invalidates() { + assertInvalidates(params(b -> b.clientStringParam("first")), + params(b -> b.clientStringParam("second"))); + } + + @Test + void staticStringParamChange_invalidates() { + assertInvalidates(params(b -> b.staticStringParam("first")), + params(b -> b.staticStringParam("second"))); + } + + @Test + void endpointOverrideChange_invalidates() { + assertInvalidates(params(b -> b.endpoint("https://first.example.com")), + params(b -> b.endpoint("https://second.example.com"))); + } + + @Test + void accountIdEndpointModeChange_invalidates() { + assertInvalidates(params(b -> b.accountIdEndpointMode("preferred")), + params(b -> b.accountIdEndpointMode("disabled"))); + } + + @Test + void accountIdChange_invalidates() { + assertInvalidates(params(b -> b.accountId("111111111111")), + params(b -> b.accountId("222222222222"))); + } + + @Test + void requestStringParamChange_invalidates() { + assertInvalidates(params(b -> b.requestStringParam("first")), + params(b -> b.requestStringParam("second"))); + } + + // ---- lists read as a whole: wholeArnList, reached via isSet, so every element is part of the key ---- + + @Test + void wholeList_elementChange_invalidates() { + assertInvalidates(params(b -> b.wholeArnList(Arrays.asList("a", "b"))), + params(b -> b.wholeArnList(Arrays.asList("a", "c")))); + } + + @Test + void wholeList_lengthChange_invalidates() { + assertInvalidates(params(b -> b.wholeArnList(Arrays.asList("a", "b"))), + params(b -> b.wholeArnList(Collections.singletonList("a")))); + } + + @Test + void wholeList_orderChange_invalidates() { + assertInvalidates(params(b -> b.wholeArnList(Arrays.asList("a", "b"))), + params(b -> b.wholeArnList(Arrays.asList("b", "a")))); + } + + // ---- lists read only at index 0: resourceArnList, reached via getAttr(list, "[0]") ---- + // + // The BDD's only read of this list is its first element, so nothing past element 0 can reach the endpoint. The key + // therefore compares element 0 alone, which turns changes the endpoint cannot see into hits rather than misses. + // This is the DynamoDB shape, where comparing the whole list costs more than half a regional resolution. + + @Test + void firstElementList_firstElementChange_invalidates() { + assertInvalidates(params(b -> b.resourceArnList(Arrays.asList("a", "b"))), + params(b -> b.resourceArnList(Arrays.asList("z", "b")))); + } + + @Test + void firstElementList_laterElementChange_isAHit() { + assertHits(params(b -> b.resourceArnList(Arrays.asList("a", "b"))), + params(b -> b.resourceArnList(Arrays.asList("a", "c")))); + } + + @Test + void firstElementList_lengthChangeKeepingFirstElement_isAHit() { + assertHits(params(b -> b.resourceArnList(Arrays.asList("a", "b", "c"))), + params(b -> b.resourceArnList(Collections.singletonList("a")))); + } + + @Test + void firstElementList_orderChangeMovingFirstElement_invalidates() { + assertInvalidates(params(b -> b.resourceArnList(Arrays.asList("a", "b"))), + params(b -> b.resourceArnList(Arrays.asList("b", "a")))); + } + + /** + * {@code isSet} can tell an absent list from an empty one, so presence stays part of the key even though + * {@code listAccess} yields null for both. + * + *

    Collapsing the two would be sound only for a BDD whose branches for absent and empty converge. DynamoDB's do - + * both reach the same node - but that is a property of the graph rather than of the parameter, so the generated + * comparison does not assume it. The cost is one extra reference check and a miss in this case. + */ + @Test + void firstElementList_emptyAndUnset_areDistinguished() { + assertInvalidates(params(b -> b.resourceArnList(Collections.emptyList())), params(b -> { + })); + } + + /** + * No size cap applies when only the first element is compared, so a list far past the cap still hits. That is the + * point: the comparison is O(1) rather than bounded-but-linear. + */ + @Test + void firstElementList_farPastTheSizeCap_stillHits() { + List long1 = new ArrayList<>(listOfSize(500)); + List long2 = new ArrayList<>(listOfSize(500)); + long2.set(499, "different-tail"); + assertHits(params(b -> b.resourceArnList(long1)), params(b -> b.resourceArnList(long2))); + } + + // ---- parameters the BDD never reads are not part of the key ---- + + /** + * {@code unusedStringParam} is declared by the model and read by no condition and no result, so it cannot change the + * resolved endpoint and must not evict the cached one. + * + *

    This is the behaviour that makes the cache worth having for S3, whose rule set declares {@code Key}, + * {@code Prefix} and {@code CopySource} and reads none of them. {@code Key} changes on essentially every object + * request, so treating it as part of the key would mean the cache almost never hits. + */ + @Test + void parameterTheBddNeverReads_doesNotInvalidate() { + assertHits(params(b -> b.unusedStringParam("first")), + params(b -> b.unusedStringParam("second"))); + } + + @Test + void parameterTheBddNeverReads_settingItDoesNotInvalidate() { + assertHits(params(b -> { + }), params(b -> b.unusedStringParam("now-set"))); + } + + // ---- transitions to and from unset ---- + + @Test + void settingAPreviouslyUnsetParam_invalidates() { + assertInvalidates(params(b -> { + }), params(b -> b.requestStringParam("now-set"))); + } + + @Test + void clearingAPreviouslySetParam_invalidates() { + assertInvalidates(params(b -> b.requestStringParam("was-set")), params(b -> { + })); + } + + @Test + void settingAPreviouslyUnsetList_invalidates() { + assertInvalidates(params(b -> { + }), params(b -> b.wholeArnList(Collections.singletonList("a")))); + } + + @Test + void clearingAPreviouslySetList_invalidates() { + assertInvalidates(params(b -> b.wholeArnList(Collections.singletonList("a"))), params(b -> { + })); + } + + @Test + void emptyListAndUnsetList_areDistinguished() { + assertInvalidates(params(b -> b.wholeArnList(Collections.emptyList())), params(b -> { + })); + } + + // ---- equals fallback ---- + + /** + * A parameter compared with {@code Objects.equals} must hit on an equal value arriving as a fresh reference. Without + * the {@code equals} fallback, a request-derived string would miss on every call and the cache would never pay off + * for the services that need it most. + */ + @Test + void equalValueDifferentReference_hits() { + String value = "shared-value"; + String copy = new String(value); + assertThat(value).isNotSameAs(copy); + + assertHits(params(b -> b.requestStringParam(value)), params(b -> b.requestStringParam(copy))); + assertHits(params(b -> b.accountId(value)), params(b -> b.accountId(copy))); + + String url = "https://override.example.com"; + assertHits(params(b -> b.endpoint(url)), params(b -> b.endpoint(new String(url)))); + } + + @Test + void requestList_equalContentsDifferentListInstance_hits() { + assertHits(params(b -> b.wholeArnList(new ArrayList<>(Arrays.asList("a", "b")))), + params(b -> b.wholeArnList(new ArrayList<>(Arrays.asList("a", "b"))))); + } + + /** + * Element comparison also falls back to {@code equals}, so equal strings held by different references still hit. + */ + @Test + void requestList_equalElementsDifferentReferences_hits() { + assertHits(params(b -> b.wholeArnList(Collections.singletonList("element"))), + params(b -> b.wholeArnList(Collections.singletonList(new String("element"))))); + } + + // ---- list size cap ---- + + /** + * At the cap the element walk still runs, so equal lists hit. + */ + @Test + void requestList_atSizeCap_stillHits() { + assertHits(params(b -> b.wholeArnList(listOfSize(LIST_SIZE_CAP))), + params(b -> b.wholeArnList(listOfSize(LIST_SIZE_CAP)))); + } + + /** + * Past the cap the check bails out and reports a miss without walking the elements, which keeps the key check + * bounded. Equal lists therefore stop hitting; that is a deliberate cost ceiling, not a defect, and it is pinned + * here so that changing the cap is a conscious decision. + */ + @Test + void requestList_pastSizeCap_alwaysMisses() { + assertInvalidates(params(b -> b.wholeArnList(listOfSize(LIST_SIZE_CAP + 1))), + params(b -> b.wholeArnList(listOfSize(LIST_SIZE_CAP + 1)))); + } + + /** + * Even a miss must still resolve correctly, so an oversized list is not a functional break. + */ + @Test + void requestList_pastSizeCap_stillResolvesCorrectly() { + Endpoint endpoint = resolve(provider(), params(b -> b.wholeArnList(listOfSize(50)))); + assertThat(endpoint.endpointUrl().host()).isEqualTo("connect.us-east-1.amazonaws.com"); + } + + private static List listOfSize(int size) { + return IntStream.range(0, size).mapToObj(i -> "element-" + i).collect(Collectors.toList()); + } + + // ---- failures are never cached ---- + + /** + * A rule error must not be stored, and must not evict a good entry. Replaying a cached failure would turn one bad + * call into a permanently broken client. + */ + @Test + void ruleError_isNotCached_andLeavesEarlierEntryIntact() { + BddEndpointsEndpointProvider provider = provider(); + BddEndpointsEndpointParams good = params(b -> { + }); + Endpoint first = resolve(provider, good); + + // FIPS combined with an endpoint override is an error in this rule set. + BddEndpointsEndpointParams bad = params(b -> b.useFips(true).endpoint("https://override.example.com")); + assertThatThrownBy(() -> resolve(provider, bad)).isInstanceOf(CompletionException.class); + + assertThat(resolve(provider, good)).isSameAs(first); + // Still an error the second time, rather than a replayed success. + assertThatThrownBy(() -> resolve(provider, bad)).isInstanceOf(CompletionException.class); + } + + @Test + void missingRegion_isNotCached() { + BddEndpointsEndpointProvider provider = provider(); + BddEndpointsEndpointParams noRegion = BddEndpointsEndpointParams.builder() + .useDualStack(false) + .useFips(false) + .build(); + assertThatThrownBy(() -> resolve(provider, noRegion)).isInstanceOf(CompletionException.class); + assertThatThrownBy(() -> resolve(provider, noRegion)).isInstanceOf(CompletionException.class); + + assertThat(resolve(provider, params(b -> { + })).endpointUrl().host()).isEqualTo("connect.us-east-1.amazonaws.com"); + } + + // ---- concurrency ---- + + /** + * Concurrent resolution of two distinct parameter sets against one provider. The cache field is written without any + * lock, so threads race to overwrite it; every thread must still receive the endpoint its own params call for. A + * torn or misattributed entry shows up here as a host mismatch. + */ + @Test + void concurrentResolution_neverReturnsAnotherThreadsEndpoint() throws Exception { + BddEndpointsEndpointProvider provider = provider(); + BddEndpointsEndpointParams plain = params(b -> { + }); + BddEndpointsEndpointParams dualStack = params(b -> b.useDualStack(true)); + String plainHost = resolve(provider(), plain).endpointUrl().host(); + String dualStackHost = resolve(provider(), dualStack).endpointUrl().host(); + assertThat(plainHost).isNotEqualTo(dualStackHost); + + int threads = 16; + int iterations = 500; + ExecutorService executor = Executors.newFixedThreadPool(threads); + try { + CountDownLatch start = new CountDownLatch(1); + List> tasks = new ArrayList<>(); + for (int t = 0; t < threads; t++) { + boolean useDualStack = t % 2 == 0; + BddEndpointsEndpointParams params = useDualStack ? dualStack : plain; + String expectedHost = useDualStack ? dualStackHost : plainHost; + tasks.add(() -> { + start.await(); + for (int i = 0; i < iterations; i++) { + assertThat(resolve(provider, params).endpointUrl().host()).isEqualTo(expectedHost); + } + return null; + }); + } + List> futures = tasks.stream().map(executor::submit).collect(Collectors.toList()); + start.countDown(); + for (Future future : futures) { + future.get(60, TimeUnit.SECONDS); + } + } finally { + executor.shutdownNow(); + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/EndpointUrlConformanceTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/EndpointUrlConformanceTest.java new file mode 100644 index 000000000000..2c4212607a29 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/EndpointUrlConformanceTest.java @@ -0,0 +1,136 @@ +/* + * 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.compiledendpointrules.endpoints.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.endpoints.EndpointUrl; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.compiledendpointrules.endpoints.CompiledEndpointRulesEndpointParams; +import software.amazon.awssdk.services.compiledendpointrules.endpoints.CompiledEndpointRulesEndpointProvider; + +/** + * Conformance test verifying that the build-time decomposed EndpointUrl (via {@code EndpointUrl.fromComponents()}) + * produces results equivalent to runtime parsing (via {@code EndpointUrl.fromString()}). + + *

    This guards against drift between the build-time ({@code EndpointUrlCodeEmitter}) and runtime + * ({@code EndpointUrl.fromString()}) URL decomposition logic. + */ +class EndpointUrlConformanceTest { + + private static final CompiledEndpointRulesEndpointProvider PROVIDER = + CompiledEndpointRulesEndpointProvider.defaultProvider(); + + /** + * Test cases covering the standard region-based resolution path (uses fromComponents in generated code) + * and the custom endpoint override path (uses fromString in generated code). + */ + static List testCases() { + return Arrays.asList( + // Standard region resolution — exercises fromComponents code path + TestCase.ofRegion("us-east-1", "https://compiledendpointrules.us-east-1.amazonaws.com"), + TestCase.ofRegion("us-west-2", "https://compiledendpointrules.us-west-2.amazonaws.com"), + TestCase.ofRegion("eu-west-1", "https://compiledendpointrules.eu-west-1.amazonaws.com"), + TestCase.ofRegion("ap-southeast-1", "https://compiledendpointrules.ap-southeast-1.amazonaws.com"), + TestCase.ofRegion("cn-north-1", "https://compiledendpointrules.cn-north-1.amazonaws.com.cn"), + TestCase.ofRegion("us-gov-west-1", "https://compiledendpointrules.us-gov-west-1.amazonaws.com"), + + // Custom endpoint override — exercises fromString code path + TestCase.ofEndpoint("us-east-1", "https://custom.example.com", + "https://custom.example.com"), + TestCase.ofEndpoint("us-east-1", "https://custom.example.com:8443", + "https://custom.example.com:8443"), + TestCase.ofEndpoint("us-east-1", "https://custom.example.com/base/path", + "https://custom.example.com/base/path"), + TestCase.ofEndpoint("us-east-1", "http://localhost:4566", + "http://localhost:4566") + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("testCases") + void resolvedEndpointUrl_componentsAreConsistentWithUri(TestCase testCase) throws Exception { + CompletableFuture future = PROVIDER.resolveEndpoint(testCase.params()); + Endpoint endpoint = future.get(); + EndpointUrl endpointUrl = endpoint.endpointUrl(); + + // 1. Verify the resolved URL matches what we expect + assertThat(endpointUrl.toUri()).isEqualTo(URI.create(testCase.expectedUrl)); + + // 2. Verify component getters are consistent with toUri() + URI uri = endpointUrl.toUri(); + assertThat(endpointUrl.scheme()).isEqualTo(uri.getScheme()); + assertThat(endpointUrl.host()).isEqualTo(uri.getHost()); + assertThat(endpointUrl.port()).isEqualTo(uri.getPort()); + String expectedPath = uri.getRawPath() != null ? uri.getRawPath() : ""; + assertThat(endpointUrl.encodedPath()).isEqualTo(expectedPath); + + // 3. Verify round-trip: reconstruct URL string from components, re-parse, and compare + String reconstructed = endpointUrl.scheme() + "://" + endpointUrl.host() + + (endpointUrl.port() >= 0 ? ":" + endpointUrl.port() : "") + + endpointUrl.encodedPath(); + EndpointUrl reparsed = EndpointUrl.fromString(reconstructed); + + assertThat(reparsed.scheme()).isEqualTo(endpointUrl.scheme()); + assertThat(reparsed.host()).isEqualTo(endpointUrl.host()); + assertThat(reparsed.port()).isEqualTo(endpointUrl.port()); + assertThat(reparsed.encodedPath()).isEqualTo(endpointUrl.encodedPath()); + assertThat(reparsed).isEqualTo(endpointUrl); + } + + static class TestCase { + private final String description; + private final Region region; + private final String customEndpoint; + private final String expectedUrl; + + TestCase(String description, Region region, String customEndpoint, String expectedUrl) { + this.description = description; + this.region = region; + this.customEndpoint = customEndpoint; + this.expectedUrl = expectedUrl; + } + + static TestCase ofRegion(String regionId, String expectedUrl) { + return new TestCase("region=" + regionId, Region.of(regionId), null, expectedUrl); + } + + static TestCase ofEndpoint(String regionId, String endpoint, String expectedUrl) { + return new TestCase("endpoint=" + endpoint, Region.of(regionId), endpoint, expectedUrl); + } + + CompiledEndpointRulesEndpointParams params() { + CompiledEndpointRulesEndpointParams.Builder builder = CompiledEndpointRulesEndpointParams.builder() + .region(region); + if (customEndpoint != null) { + builder.endpoint(customEndpoint); + } + return builder.build(); + } + + @Override + public String toString() { + return description; + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsAwsPartitionTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsAwsPartitionTest.java new file mode 100644 index 000000000000..fa2468671c3f --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsAwsPartitionTest.java @@ -0,0 +1,119 @@ +/* + * 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.compiledendpointrules.endpoints.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.lang.reflect.Field; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; + +/** + * Covers {@code RulesFunctions.awsPartition}'s handling of partition metadata that declares no {@code aws} partition. + * + *

    {@code aws} is the fallback for a region that matches neither a declared region name nor a partition's region + * pattern, so metadata without it is only incomplete for those regions. The regions it does describe must keep + * resolving, and only the unmatched ones may fail. Pinned here because the natural way to precompute the fallback - + * validating it while loading - fails every region instead, and reads as a tidier implementation. + * + *

    Reachable in production through either partitions-file override, not through the shipped default: the default + * metadata is generated into {@code LazyPartitionsContainer} at build time from {@code partitions.json.resource} and + * always declares {@code aws}. + */ +class RulesFunctionsAwsPartitionTest { + private static final String NO_AWS_PARTITIONS_FILE = + RulesFunctionsAwsPartitionTest.class.getResource( + "/software/amazon/awssdk/services/endpointproviders/no-aws-partitions.json").getFile(); + + private final EnvironmentVariableHelper environment = new EnvironmentVariableHelper(); + + /** + * {@code RulesFunctions} caches the loaded metadata in a static, so the cache has to be cleared around any test + * that swaps the metadata out. Without this the result would depend on whether some earlier test in the same JVM + * had already resolved a partition. + */ + @BeforeEach + void clearCacheBefore() throws Exception { + resetPartitionDataCache(); + } + + @AfterEach + void clearCacheAfter() throws Exception { + environment.reset(); + resetPartitionDataCache(); + } + + @Test + void metadataWithoutAws_regionDeclaredByAnotherPartition_stillResolves() { + environment.set(SdkSystemSetting.AWS_PARTITIONS_FILE, NO_AWS_PARTITIONS_FILE); + + assertThat(RulesFunctions.awsPartition("cn-north-1").name()).isEqualTo("aws-cn"); + } + + @Test + void metadataWithoutAws_regionMatchingAnotherPartitionsPattern_stillResolves() { + environment.set(SdkSystemSetting.AWS_PARTITIONS_FILE, NO_AWS_PARTITIONS_FILE); + + // Not declared in the fixture's regions, so this can only resolve through the regionRegex. + assertThat(RulesFunctions.awsPartition("cn-northwest-1").name()).isEqualTo("aws-cn"); + } + + /** + * The one case the missing partition actually breaks. The message has to name the region and the override + * mechanisms, because at this point that is the only information available about why the fallback was needed. + */ + @Test + void metadataWithoutAws_unmatchedRegion_throwsNamingTheRegionAndTheCause() { + environment.set(SdkSystemSetting.AWS_PARTITIONS_FILE, NO_AWS_PARTITIONS_FILE); + + assertThatThrownBy(() -> RulesFunctions.awsPartition("us-east-1")) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("us-east-1") + .hasMessageContaining("'aws' partition") + .hasMessageContaining("aws.partitionsFile"); + } + + @Test + void defaultMetadata_unmatchedRegion_fallsBackToAws() { + assertThat(RulesFunctions.awsPartition("not-a-real-region-1").name()).isEqualTo("aws"); + } + + @Test + void defaultMetadata_knownRegionResolvesToItsOwnPartition() { + assertThat(RulesFunctions.awsPartition("us-west-2").name()).isEqualTo("aws"); + assertThat(RulesFunctions.awsPartition("cn-north-1").name()).isEqualTo("aws-cn"); + assertThat(RulesFunctions.awsPartition("us-gov-west-1").name()).isEqualTo("aws-us-gov"); + } + + private static void resetPartitionDataCache() throws Exception { + Field partitionDataField = RulesFunctions.class.getDeclaredField("PARTITION_DATA"); + partitionDataField.setAccessible(true); + Object lazyValue = partitionDataField.get(null); + + Field valueField = lazyValue.getClass().getDeclaredField("value"); + valueField.setAccessible(true); + valueField.set(lazyValue, null); + + Field initializedField = lazyValue.getClass().getDeclaredField("initialized"); + initializedField.setAccessible(true); + initializedField.setBoolean(lazyValue, false); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSplitTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSplitTest.java new file mode 100644 index 000000000000..37d40593479c --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSplitTest.java @@ -0,0 +1,211 @@ +/* + * 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.compiledendpointrules.endpoints.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import software.amazon.awssdk.core.exception.SdkClientException; + +/** + * Covers {@code RulesFunctions.split}'s handling of arguments the endpoint rules specification forbids. + * + *

    None of {@code value}, {@code delimiter} or {@code limit} is optional, so reaching this function with a bad one + * means the rule set or the generated provider is wrong. Each therefore has to fail as a named + * {@link SdkClientException} that a reader can act on, rather than as whatever the first dereference happens to + * produce. The four cases below previously produced four different outcomes, three of them unhelpful and one of them + * dangerous. + * + *

    The valid cases are pinned alongside them, because the natural way to add the validation - after the + * {@code limit == 1} shortcut, where the arguments are first used - leaves two of the violations undetected. + */ +class RulesFunctionsSplitTest { + + // ---- value: the rules type checker requires it to be set ---- + + /** + * Covers every limit branch. {@code limit == 1} is the one that matters most: it returns before {@code value} is + * dereferenced, so a null used to come back as {@code [null]} with no error at all. Downstream that reads as an + * unset value, which sends the rule down a different branch instead of failing. + */ + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 5}) + void nullValue_throwsSdkClientException(int limit) { + assertThatThrownBy(() -> RulesFunctions.split(null, ",", limit)) + .isInstanceOf(SdkClientException.class) + .isNotInstanceOf(NullPointerException.class) + .hasMessageContaining("null value"); + } + + // ---- delimiter: "must not be null or empty" ---- + + /** + * At {@code limit == 1} the delimiter is never read, so a null one used to be accepted silently. + */ + @ParameterizedTest + @ValueSource(ints = {0, 1, 2, 5}) + void nullDelimiter_throwsSdkClientException(int limit) { + assertThatThrownBy(() -> RulesFunctions.split("a,b", null, limit)) + .isInstanceOf(SdkClientException.class) + .isNotInstanceOf(NullPointerException.class) + .hasMessageContaining("null delimiter"); + } + + /** + * An empty delimiter with a limit produced silent nonsense - {@code split("abc", "", 4)} returned + * {@code ["", "", "", "abc"]}. + */ + @ParameterizedTest + @ValueSource(ints = {2, 4, 5}) + void emptyDelimiterWithLimit_throwsSdkClientException(int limit) { + assertThatThrownBy(() -> RulesFunctions.split("abc", "", limit)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("empty delimiter"); + } + + /** + * The case that made this worth fixing rather than tidying. {@code indexOf("")} matches at the current position + * every time, so with no limit the loop appended empty strings until the heap was exhausted - + * {@link OutOfMemoryError} on a 256 MB heap, which takes more than the request down with it. + * + *

    The timeout is the assertion as much as the exception type is: a regression here hangs rather than fails. + */ + @Test + @Timeout(10) + void emptyDelimiterUnlimited_throwsInsteadOfExhaustingTheHeap() { + assertThatThrownBy(() -> RulesFunctions.split("abc", "", 0)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("empty delimiter"); + } + + /** + * An empty value short-circuits before the delimiter is read, so this pins that validation still happens. + */ + @Test + void emptyValueWithBadDelimiter_stillThrows() { + assertThatThrownBy(() -> RulesFunctions.split("", null, 0)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("null delimiter"); + assertThatThrownBy(() -> RulesFunctions.split("", "", 0)) + .isInstanceOf(SdkClientException.class) + .hasMessageContaining("empty delimiter"); + } + + // ---- limit: "must not be negative" ---- + + /** + * Previously an {@code IllegalArgumentException: Illegal Capacity: -1} from {@code ArrayList}'s constructor, which + * names neither split nor the limit. + */ + @ParameterizedTest + @ValueSource(ints = {-1, -2, -100, Integer.MIN_VALUE}) + void negativeLimit_throwsSdkClientExceptionNamingTheLimit(int limit) { + assertThatThrownBy(() -> RulesFunctions.split("a,b", ",", limit)) + .isInstanceOf(SdkClientException.class) + .isNotInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("negative limit") + .hasMessageContaining(String.valueOf(limit)); + } + + // ---- valid input keeps working ---- + + /** + * Stated by the specification: "For empty input strings, the function returns an array containing a single empty + * string." Not an empty array, which is what a reader tends to assume. + */ + @Test + void emptyValue_returnsSingleEmptyString() { + assertThat(RulesFunctions.split("", ",", 0)).containsExactly(""); + assertThat(RulesFunctions.split("", ",", 1)).containsExactly(""); + assertThat(RulesFunctions.split("", ",", 3)).containsExactly(""); + } + + @Test + void limitOne_returnsWholeValueUnsplit() { + assertThat(RulesFunctions.split("a,b,c", ",", 1)).containsExactly("a,b,c"); + } + + @Test + void limitZero_splitsOnEveryOccurrence() { + assertThat(RulesFunctions.split("a,b,c", ",", 0)).containsExactly("a", "b", "c"); + } + + @Test + void limitBoundsThePartsAndKeepsTheRemainderWhole() { + assertThat(RulesFunctions.split("a,b,c,d", ",", 2)).containsExactly("a", "b,c,d"); + assertThat(RulesFunctions.split("a,b,c,d", ",", 3)).containsExactly("a", "b", "c,d"); + assertThat(RulesFunctions.split("a,b,c,d", ",", 99)).containsExactly("a", "b", "c", "d"); + } + + @Test + void delimiterAbsent_returnsTheWholeValue() { + assertThat(RulesFunctions.split("abc", ",", 0)).containsExactly("abc"); + } + + /** + * The shape the S3 rules use: {@code split(Bucket, "--", 0)} feeding an index read, for S3 Express bucket names. + */ + @Test + void multiCharacterDelimiter_splitsOnTheWholeDelimiter() { + assertThat(RulesFunctions.split("mybucket--usw2-az1--x-s3", "--", 0)) + .containsExactly("mybucket", "usw2-az1", "x-s3"); + assertThat(RulesFunctions.split("a-b", "--", 0)).containsExactly("a-b"); + } + + @Test + void delimitersAtTheEdgesProduceEmptyParts() { + assertThat(RulesFunctions.split(",a,", ",", 0)).containsExactly("", "a", ""); + assertThat(RulesFunctions.split("a,,b", ",", 0)).containsExactly("a", "", "b"); + } + + @Test + void valueEqualToTheDelimiter_producesTwoEmptyParts() { + assertThat(RulesFunctions.split(",", ",", 0)).containsExactly("", ""); + } + + /** + * A long unlimited split, to exercise the growth path of the list now that {@code limit == 0} seeds a capacity + * instead of starting empty. + */ + @Test + void unlimitedSplitOfManyParts() { + int parts = 200; + StringBuilder value = new StringBuilder(); + for (int i = 0; i < parts; i++) { + if (i > 0) { + value.append(','); + } + value.append('p').append(i); + } + + assertThat(RulesFunctions.split(value.toString(), ",", 0)) + .hasSize(parts) + .startsWith("p0", "p1") + .endsWith("p" + (parts - 1)); + } + + @Test + void resultIsTheDocumentedOrderForAKnownCase() { + assertThat(RulesFunctions.split("a.b.c", ".", 0)).isEqualTo(Arrays.asList("a", "b", "c")); + assertThat(RulesFunctions.split("solo", ".", 0)).isEqualTo(Collections.singletonList("solo")); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSubstringEqualsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSubstringEqualsTest.java new file mode 100644 index 000000000000..2dfe2f2a18e2 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/compiledendpointrules/endpoints/internal/RulesFunctionsSubstringEqualsTest.java @@ -0,0 +1,232 @@ +/* + * 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.compiledendpointrules.endpoints.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * {@code RulesFunctions.substringEquals} is emitted by the BDD endpoint codegen peephole in place of + * {@code stringEquals(coalesce(substring(value, start, stop, reverse), ""), literal)}. It must be + * indistinguishable from that composition, otherwise a rule takes a different branch than the + * endpoint spec requires and we resolve a wrong endpoint. + * + *

    The interesting case is non-ASCII input: the spec's {@code substring} returns null when *any* + * character in the whole input is outside the 7-bit ASCII range, which makes the comparison false + * even when the characters at the compared positions match exactly. + * + *

    Why this lives here. {@code RulesFunctions} is a codegen template copied into every + * service module, not a class owned by any one service, so per + * {@code docs/guidelines/testing-guidelines.md} it belongs with "generated SDK common + * functionalities" in this module rather than under a single service. It is exercised through the + * {@code compiledendpointrules} test service, alongside {@code EndpointUrlConformanceTest} and + * {@code RuleUrlTest}, which cover other generated classes from the same template set. The + * substring windows below are the ones the peephole actually emits for the S3 BDD model. + */ +class RulesFunctionsSubstringEqualsTest { + + /** + * The composition that {@code substringEquals} replaces. Written out in full so the test is + * checking against the spec functions rather than against a restatement of the optimization. + */ + private static boolean reference(String value, int startIndex, int stopIndex, boolean reverse, String literal) { + return RulesFunctions.stringEquals( + RulesFunctions.coalesce(RulesFunctions.substring(value, startIndex, stopIndex, reverse), ""), + literal); + } + + @ParameterizedTest(name = "substringEquals({0}, {1}, {2}, {3}, {4})") + @MethodSource("nonEmptyLiteralCases") + void substringEquals_againstSpecComposition_agrees(String value, int startIndex, int stopIndex, boolean reverse, + String literal) { + assertThat(RulesFunctions.substringEquals(value, startIndex, stopIndex, reverse, literal)) + .as("substringEquals must agree with stringEquals(coalesce(substring(..), \"\"), literal)") + .isEqualTo(reference(value, startIndex, stopIndex, reverse, literal)); + } + + /** + * An empty literal is the sole case where the two are allowed to differ, because + * {@code coalesce(null, "")} makes the spec composition true whenever {@code substring} returns + * null. Asserting the direction of every divergence keeps that carve-out honest: if the helper + * ever diverged for a non-empty literal it would show up in + * {@link #substringEquals_againstSpecComposition_agrees}, and if a *new* kind of divergence + * appeared here it would show up as a failure rather than as a silently skipped case. + * + *

    Codegen never emits this shape - see {@code BddPeepholeVisitorTest.emptyLiteralIsNotRewritten}. + */ + @ParameterizedTest(name = "substringEquals({0}, {1}, {2}, {3}, \"\")") + @MethodSource("emptyLiteralCases") + void substringEquals_withEmptyLiteral_divergesOnlyBySpecReturningTrue(String value, int startIndex, int stopIndex, + boolean reverse) { + boolean actual = RulesFunctions.substringEquals(value, startIndex, stopIndex, reverse, ""); + boolean expected = reference(value, startIndex, stopIndex, reverse, ""); + + assertThat(actual).as("substringEquals must never be true for an empty literal").isFalse(); + if (actual != expected) { + assertThat(expected) + .as("the only permitted divergence is the spec composition returning true") + .isTrue(); + } + } + + private static List nonEmptyLiteralCases() { + return cases(false); + } + + private static List emptyLiteralCases() { + List args = new ArrayList<>(); + for (Arguments a : cases(true)) { + Object[] g = a.get(); + // Drop the trailing literal; the test method supplies it. + args.add(Arguments.of(g[0], g[1], g[2], g[3])); + } + return args; + } + + private static List cases(boolean emptyLiteralOnly) { + // (startIndex, stopIndex) windows that codegen actually emits for the S3 BDD, plus a forward + // interior match which the S3 ruleset does not currently use, and a degenerate empty window. + int[][] windows = { + {0, 4}, {0, 6}, {0, 7}, {16, 18}, {14, 16}, {1, 3}, {3, 3} + }; + List values = Arrays.asList( + null, + "", + "a", + "ab", + "arn:", + "arn:aws:s3:::mybucket", + "mybucket--x-s3", + "mybucket--xa-s3", + "my-bucket-name", + "mybucket--abcd-ab1--x-s3", + // Non-ASCII: the compared window is pure ASCII and matches, but the spec still rejects + // the whole input, so every one of these must come out false. + "arn\u00e9:aws:s3:::b", + "arn:aws:s3:::b\u00fc", + "mybucket\u00fc--x-s3", + "\u00fcmybucket--x-s3", + "mybucket--x-s3\u00fc", + // Multi-byte beyond Latin-1, and a surrogate pair. + "mybucket\u4e2d--x-s3", + "mybucket\ud83d\ude00--x-s3" + ); + List literals = emptyLiteralOnly + ? Arrays.asList("") + : Arrays.asList("arn:", "--x-s3", "--xa-s3", "--", "rn", "zz"); + + List args = new ArrayList<>(); + for (int[] window : windows) { + for (String value : values) { + for (String literal : literals) { + for (boolean reverse : new boolean[] {false, true}) { + args.add(Arguments.of(value, window[0], window[1], reverse, literal)); + } + } + } + } + return args; + } + + /** + * Spot checks in the direction that matters, so a regression is legible rather than just a + * differential mismatch somewhere in the matrix above. + */ + @Test + void substringEquals_withNonAsciiInput_isFalseEvenWhenComparedWindowMatches() { + // Pure-ASCII directory bucket: this is an S3 Express bucket. + assertThat(RulesFunctions.substringEquals("mybucket--x-s3", 0, 6, true, "--x-s3")).isTrue(); + + // Same suffix, but a non-ASCII character elsewhere in the name. The spec's substring returns + // null, so this is NOT an S3 Express bucket and must not be routed as one. + assertThat(RulesFunctions.substringEquals("mybuck\u00e9t--x-s3", 0, 6, true, "--x-s3")).isFalse(); + assertThat(reference("mybuck\u00e9t--x-s3", 0, 6, true, "--x-s3")).isFalse(); + + // Likewise for the ARN prefix check. + assertThat(RulesFunctions.substringEquals("arn:aws:s3:::b", 0, 4, false, "arn:")).isTrue(); + assertThat(RulesFunctions.substringEquals("arn:aws:s3:::b\u00fc", 0, 4, false, "arn:")).isFalse(); + assertThat(reference("arn:aws:s3:::b\u00fc", 0, 4, false, "arn:")).isFalse(); + } + + @Test + void substringEquals_withNullOrTooShortInput_isFalse() { + assertThat(RulesFunctions.substringEquals(null, 0, 4, false, "arn:")).isFalse(); + assertThat(RulesFunctions.substringEquals("arn", 0, 4, false, "arn:")).isFalse(); + assertThat(RulesFunctions.substringEquals("", 0, 4, false, "arn:")).isFalse(); + } + + @Test + void substringEquals_withLiteralLengthNotMatchingWindow_isFalse() { + // Guards against a caller passing a literal that is not stopIndex - startIndex long. A + // shorter or longer literal can never equal the substring. + assertThat(RulesFunctions.substringEquals("arn:aws", 0, 4, false, "arn")).isFalse(); + assertThat(RulesFunctions.substringEquals("arn:aws", 0, 4, false, "arn:a")).isFalse(); + } + + /** + * The one case where {@code substringEquals} is deliberately not equivalent, and therefore the + * one case codegen must not rewrite. {@code startIndex == stopIndex} makes the spec's + * {@code substring} return null, the coalesce turns that into {@code ""}, and comparing {@code ""} + * to an empty literal is true - even for a null input. See + * {@code BddPeepholeVisitorTest.emptyLiteralIsNotRewritten}, which pins the codegen guard. + */ + @Test + void substringEquals_withDegenerateEmptyWindow_divergesFromSpecAndIsGuardedInCodegen() { + assertThat(reference(null, 3, 3, false, "")).isTrue(); + assertThat(reference("anything", 3, 3, false, "")).isTrue(); + + assertThat(RulesFunctions.substringEquals(null, 3, 3, false, "")).isFalse(); + assertThat(RulesFunctions.substringEquals("anything", 3, 3, false, "")).isFalse(); + } + + /** + * {@code isValidHostLabel(s, allowDots)} delegates to the two specialized helpers that optimized + * codegen calls directly, so the three must stay in agreement. Covers the delegation introduced + * to remove a duplicated copy of the multi-label loop. + */ + @Test + void isValidHostLabel_agreesWithSpecializedVariants() { + List labels = Arrays.asList( + null, "", ".", "a", "a.b", "a..b", "-a", "a-", "a-b", "a.b.c", "9a", "a_b", + "abc.def.ghi", ".leading", "trailing.", + // 63 chars (max) and 64 chars (over) + new String(new char[63]).replace('\0', 'a'), + new String(new char[64]).replace('\0', 'a'), + // over-length single chunk inside a multi-label name + "ok." + new String(new char[64]).replace('\0', 'a') + ); + + for (String label : labels) { + assertThat(RulesFunctions.isValidHostLabel(label, false)) + .as("isValidHostLabel(%s, false) must equal isValidHostLabelSingle", label) + .isEqualTo(RulesFunctions.isValidHostLabelSingle(label)); + assertThat(RulesFunctions.isValidHostLabel(label, true)) + .as("isValidHostLabel(%s, true) must equal isValidHostLabelMulti", label) + .isEqualTo(RulesFunctions.isValidHostLabelMulti(label)); + } + + // Sanity: the two variants genuinely differ on dots, so the above is not vacuous. + assertThat(RulesFunctions.isValidHostLabelSingle("a.b")).isFalse(); + assertThat(RulesFunctions.isValidHostLabelMulti("a.b")).isTrue(); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ClientEndpointResolutionTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ClientEndpointResolutionTest.java new file mode 100644 index 000000000000..da9e0b3e34d0 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ClientEndpointResolutionTest.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.endpointproviders; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.EndpointCapturingInterceptor; +import software.amazon.awssdk.services.restjsonendpointproviders.RestJsonEndpointProvidersClient; + +/** + * Tests that the generated client builder resolves a default endpoint when no override is configured, + * and correctly uses endpoint overrides from client configuration, system properties, and environment sources. + */ +public class ClientEndpointResolutionTest { + + private static final String SERVICE_SYSTEM_PROPERTY = "aws.endpointUrlRestJsonEndpointProviders"; + + @AfterEach + void cleanup() { + System.clearProperty(SERVICE_SYSTEM_PROPERTY); + } + + @Test + void clientBuild_withRegionOnly_resolvesEndpointViaEndpoints2() { + EndpointCapturingInterceptor interceptor = new EndpointCapturingInterceptor(); + + RestJsonEndpointProvidersClient client = RestJsonEndpointProvidersClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) + .build(); + + try { + client.operationWithNoInputOrOutput(r -> {}); + } catch (EndpointCapturingInterceptor.CaptureCompletedException e) { + // Expected + } + + assertThat(interceptor.endpoints()) + .singleElement() + .asString() + .contains("us-west-2") + .contains("amazonaws.com"); + } + + @Test + void clientBuild_withSystemPropertyOverride_usesOverrideEndpoint() { + System.setProperty(SERVICE_SYSTEM_PROPERTY, "https://custom-override.example.com"); + + EndpointCapturingInterceptor interceptor = new EndpointCapturingInterceptor(); + + RestJsonEndpointProvidersClient client = RestJsonEndpointProvidersClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) + .build(); + + try { + client.operationWithNoInputOrOutput(r -> {}); + } catch (EndpointCapturingInterceptor.CaptureCompletedException e) { + // Expected + } + + assertThat(interceptor.endpoints()) + .singleElement() + .asString() + .startsWith("https://custom-override.example.com"); + } + + @Test + void clientBuild_withEndpointOverride_usesClientOverride() { + EndpointCapturingInterceptor interceptor = new EndpointCapturingInterceptor(); + + RestJsonEndpointProvidersClient client = RestJsonEndpointProvidersClient.builder() + .region(Region.US_WEST_2) + .endpointOverride(URI.create("https://my-override.example.com")) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) + .build(); + + try { + client.operationWithNoInputOrOutput(r -> {}); + } catch (EndpointCapturingInterceptor.CaptureCompletedException e) { + // Expected + } + + assertThat(interceptor.endpoints()) + .singleElement() + .asString() + .startsWith("https://my-override.example.com"); + } + +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java index 38684df7d291..cb7c086e2a25 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/endpointproviders/ParametersTest.java @@ -243,4 +243,19 @@ public void clientContextParams_setOnBuilder_resolvedCorrectly() { assertThat(params.stringClientContextParam()).isEqualTo("foobar"); assertThat(params.booleanClientContextParam()).isTrue(); } + + @Test + public void regionId_whenRegionIsSet_returnsRegionIdString() { + RestJsonEndpointProvidersEndpointParams params = RestJsonEndpointProvidersEndpointParams.builder() + .region(Region.of("us-west-2")) + .build(); + assertThat(params.regionId()).isEqualTo("us-west-2"); + } + + @Test + public void regionId_whenRegionIsNull_returnsNull() { + RestJsonEndpointProvidersEndpointParams params = RestJsonEndpointProvidersEndpointParams.builder() + .build(); + assertThat(params.regionId()).isNull(); + } } diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationAssertions.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationAssertions.java new file mode 100644 index 000000000000..723ff24017fd --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationAssertions.java @@ -0,0 +1,126 @@ +/* + * 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.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.Duration; +import java.util.List; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.SdkMetric; + +/** + * Assertions on the window that {@link CoreMetric#API_CALL_DURATION} is supposed to cover. + */ +public final class ApiCallDurationAssertions { + + private ApiCallDurationAssertions() { + } + + /** + * Assert that {@code ApiCallDuration} individually encloses each duration reported inside its window. + * + *

    Every one of these is a necessary condition on its own, so this is safe to apply to any API call, including + * calls that failed or were retried. + * + *

    {@code MARSHALLING_DURATION} and {@code ENDPOINT_RESOLVE_DURATION} are additionally required to be present. An + * enclosure check over an absent metric passes vacuously, which would let a regression that stopped reporting one of + * them through unnoticed — and those two are exactly the ones this PR's defect hid. + */ + public static void assertEnclosesComponents(MetricCollection apiCall) { + Duration apiCallDuration = single(apiCall, CoreMetric.API_CALL_DURATION); + + // Required: every API call marshals a request and resolves an endpoint before it can be sent, so a regression + // that stops reporting either of these must fail rather than pass vacuously. + assertRequiredAndEnclosed(apiCallDuration, apiCall, CoreMetric.MARSHALLING_DURATION); + assertRequiredAndEnclosed(apiCallDuration, apiCall, CoreMetric.ENDPOINT_RESOLVE_DURATION); + + // Optional: absent when the endpoint is not signed, when an identity is already cached in a form that reports no + // duration, or when the call failed before the phase ran. + assertEnclosedIfPresent(apiCallDuration, apiCall, CoreMetric.CREDENTIALS_FETCH_DURATION); + + for (MetricCollection attempt : apiCall.children()) { + assertEnclosedIfPresent(apiCallDuration, attempt, CoreMetric.SIGNING_DURATION); + assertEnclosedIfPresent(apiCallDuration, attempt, CoreMetric.SERVICE_CALL_DURATION); + assertEnclosedIfPresent(apiCallDuration, attempt, CoreMetric.UNMARSHALLING_DURATION); + } + } + + /** + * Assert the javadoc additivity formula: {@code ApiCallDuration} is at least the sum of the components it is + * documented to be composed of. + * + *

    The relation is an inequality rather than an equality because several steps inside the window have no metric of + * its own. + * + *

    Only apply this where the phases are genuinely disjoint: a single-attempt call on a synchronous client. It does + * not hold on asynchronous clients, where {@code SERVICE_CALL_DURATION} does not stop at time to first byte (see + * {@code CoreMetric.TIME_TO_FIRST_BYTE}) and so overlaps {@code UNMARSHALLING_DURATION} for streaming operations. + * Use {@link #assertEnclosesComponents(MetricCollection)} there, which holds unconditionally. + */ + public static void assertEnclosesComponentSum(MetricCollection apiCall) { + Duration apiCallDuration = single(apiCall, CoreMetric.API_CALL_DURATION); + + Duration componentSum = sum(apiCall, CoreMetric.MARSHALLING_DURATION) + .plus(sum(apiCall, CoreMetric.ENDPOINT_RESOLVE_DURATION)) + .plus(sum(apiCall, CoreMetric.CREDENTIALS_FETCH_DURATION)); + + for (MetricCollection attempt : apiCall.children()) { + componentSum = componentSum.plus(sum(attempt, CoreMetric.BACKOFF_DELAY_DURATION)) + .plus(sum(attempt, CoreMetric.SIGNING_DURATION)) + .plus(sum(attempt, CoreMetric.SERVICE_CALL_DURATION)) + .plus(sum(attempt, CoreMetric.UNMARSHALLING_DURATION)); + } + + assertThat(apiCallDuration) + .as("ApiCallDuration must be at least the sum of the components") + .isGreaterThanOrEqualTo(componentSum); + } + + private static void assertRequiredAndEnclosed(Duration apiCallDuration, + MetricCollection collection, + SdkMetric metric) { + assertThat(collection.metricValues(metric)) + .as("%s must be reported for every API call", metric.name()) + .isNotEmpty(); + assertEnclosedIfPresent(apiCallDuration, collection, metric); + } + + private static void assertEnclosedIfPresent(Duration apiCallDuration, + MetricCollection collection, + SdkMetric metric) { + for (Duration value : collection.metricValues(metric)) { + assertThat(apiCallDuration) + .as("ApiCallDuration must enclose %s", metric.name()) + .isGreaterThanOrEqualTo(value); + } + } + + private static Duration single(MetricCollection collection, SdkMetric metric) { + List values = collection.metricValues(metric); + assertThat(values).as("%s must be reported", metric.name()).hasSize(1); + return values.get(0); + } + + private static Duration sum(MetricCollection collection, SdkMetric metric) { + Duration total = Duration.ZERO; + for (Duration value : collection.metricValues(metric)) { + total = total.plus(value); + } + return total; + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationWindowTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationWindowTest.java new file mode 100644 index 000000000000..36e6c0b67d1e --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/ApiCallDurationWindowTest.java @@ -0,0 +1,312 @@ +/* + * 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.metrics; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.net.URI; +import java.nio.ByteBuffer; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +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.metrics.CoreMetric; +import software.amazon.awssdk.endpoints.Endpoint; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricPublisher; +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.endpoints.ProtocolRestJsonEndpointParams; +import software.amazon.awssdk.services.protocolrestjson.endpoints.ProtocolRestJsonEndpointProvider; +import software.amazon.awssdk.services.protocolrestjson.model.StreamingOutputOperationResponse; +import software.amazon.awssdk.services.testutil.MockIdentityProviderUtil; + +/** + * Verifies which phases of an API call fall inside the {@link CoreMetric#API_CALL_DURATION} window, for both the + * synchronous and asynchronous clients. + * + *

    Each test injects a delay that is large relative to everything else the call does, into exactly one phase, and then + * asserts that the delay is visible in the reported {@code ApiCallDuration}. A phase that is outside the measured window + * contributes nothing to it, so the assertion fails outright rather than by a margin. This is deliberately stronger than + * checking the additivity formula: the phases at issue normally cost microseconds against a call that costs + * milliseconds, so an inequality over real timings passes whether or not they are included. + * + *

    The phases covered are work before marshalling, endpoint resolution, the {@code afterExecution} interceptors, and + * completion of an {@link AsyncResponseTransformer}. The first three are places the window has been wrong, on one or both + * clients. The last is not a past defect but is the documented end of the asynchronous window for streaming operations. + */ +public class ApiCallDurationWindowTest { + + /** + * Large enough to dwarf the rest of the call and to survive scheduling jitter, small enough to keep the test quick. + */ + private static final Duration INJECTED_DELAY = Duration.ofMillis(300); + + @Rule + public WireMockRule wireMock = new WireMockRule(0); + + private MetricPublisher publisher; + private ScheduledExecutorService scheduler; + + @Before + public void setup() { + publisher = mock(MetricPublisher.class); + scheduler = Executors.newSingleThreadScheduledExecutor(); + stubFor(post(anyUrl()).willReturn(aResponse().withStatus(200) + .withHeader("x-amz-request-id", "req-id") + .withBody("{}"))); + } + + @After + public void teardown() { + scheduler.shutdownNow(); + } + + @Test + public void syncClient_apiCallDuration_includesWorkBeforeMarshalling() { + callSync(b -> b.addExecutionInterceptor(new DelayingInterceptor(Phase.BEFORE_MARSHALLING)), null); + assertDelayIsMeasured(); + } + + @Test + public void asyncClient_apiCallDuration_includesWorkBeforeMarshalling() { + callAsync(b -> b.addExecutionInterceptor(new DelayingInterceptor(Phase.BEFORE_MARSHALLING)), null); + assertDelayIsMeasured(); + } + + @Test + public void syncClient_apiCallDuration_includesEndpointResolution() { + callSync(b -> { + }, slowEndpointProvider()); + assertDelayIsMeasured(); + } + + @Test + public void asyncClient_apiCallDuration_includesEndpointResolution() { + callAsync(b -> { + }, slowEndpointProvider()); + assertDelayIsMeasured(); + } + + @Test + public void syncClient_apiCallDuration_includesAfterExecutionInterceptors() { + callSync(b -> b.addExecutionInterceptor(new DelayingInterceptor(Phase.AFTER_EXECUTION)), null); + assertDelayIsMeasured(); + } + + @Test + public void asyncClient_apiCallDuration_includesAfterExecutionInterceptors() { + callAsync(b -> b.addExecutionInterceptor(new DelayingInterceptor(Phase.AFTER_EXECUTION)), null); + assertDelayIsMeasured(); + } + + /** + * The async window closes when the future returned to the caller completes, which for a streaming operation is when + * the {@link AsyncResponseTransformer} completes. This delays only that completion — the transformer schedules it + * rather than blocking, so no pipeline stage and no event loop thread is held up. Anything the delay shows up in must + * therefore be measuring as far as the transformer. + */ + @Test + public void asyncClient_apiCallDuration_includesResponseTransformerCompletion() { + try (ProtocolRestJsonAsyncClient client = asyncClientBuilder(b -> { + }, null).build()) { + client.streamingOutputOperation(r -> { + }, new DelayedCompletionTransformer()).join(); + } + + assertDelayIsMeasured(); + } + + private void assertDelayIsMeasured() { + assertThat(capturedApiCallDuration()) + .as("ApiCallDuration must include the delay injected into the phase under test") + .isGreaterThanOrEqualTo(INJECTED_DELAY); + } + + private Duration capturedApiCallDuration() { + ArgumentCaptor captor = ArgumentCaptor.forClass(MetricCollection.class); + verify(publisher).publish(captor.capture()); + MetricCollection apiCall = captor.getValue(); + ApiCallDurationAssertions.assertEnclosesComponents(apiCall); + return apiCall.metricValues(CoreMetric.API_CALL_DURATION).get(0); + } + + private void callSync(Consumer overrides, + ProtocolRestJsonEndpointProvider endpointProvider) { + ProtocolRestJsonClientBuilder builder = + ProtocolRestJsonClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(MockIdentityProviderUtil.mockIdentityProvider()) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .overrideConfiguration(c -> { + c.addMetricPublisher(publisher).retryStrategy(b -> b.maxAttempts(1)); + overrides.accept(c); + }); + if (endpointProvider != null) { + builder.endpointProvider(endpointProvider); + } + try (ProtocolRestJsonClient client = builder.build()) { + client.allTypes(); + } + } + + private void callAsync(Consumer overrides, + ProtocolRestJsonEndpointProvider endpointProvider) { + try (ProtocolRestJsonAsyncClient client = asyncClientBuilder(overrides, endpointProvider).build()) { + client.allTypes().join(); + } + } + + private ProtocolRestJsonAsyncClientBuilder asyncClientBuilder( + Consumer overrides, + ProtocolRestJsonEndpointProvider endpointProvider) { + + ProtocolRestJsonAsyncClientBuilder builder = + ProtocolRestJsonAsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(MockIdentityProviderUtil.mockIdentityProvider()) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .overrideConfiguration(c -> { + c.addMetricPublisher(publisher).retryStrategy(b -> b.maxAttempts(1)); + overrides.accept(c); + }); + if (endpointProvider != null) { + builder.endpointProvider(endpointProvider); + } + return builder; + } + + private ProtocolRestJsonEndpointProvider slowEndpointProvider() { + ProtocolRestJsonEndpointProvider delegate = ProtocolRestJsonEndpointProvider.defaultProvider(); + return new ProtocolRestJsonEndpointProvider() { + @Override + public CompletableFuture resolveEndpoint(ProtocolRestJsonEndpointParams endpointParams) { + sleep(); + return delegate.resolveEndpoint(endpointParams); + } + }; + } + + private static void sleep() { + try { + Thread.sleep(INJECTED_DELAY.toMillis()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException(e); + } + } + + private enum Phase { + BEFORE_MARSHALLING, + AFTER_EXECUTION + } + + /** + * Drains the response body, then completes its future {@link #INJECTED_DELAY} later via the scheduler rather than by + * sleeping, so the delay is purely in the transformer's completion and not in any thread the SDK owns. + */ + private final class DelayedCompletionTransformer + implements AsyncResponseTransformer { + + private volatile CompletableFuture result; + + @Override + public CompletableFuture prepare() { + result = new CompletableFuture<>(); + return result; + } + + @Override + public void onResponse(StreamingOutputOperationResponse response) { + } + + @Override + public void onStream(SdkPublisher publisher) { + publisher.subscribe(new Subscriber() { + @Override + public void onSubscribe(Subscription subscription) { + subscription.request(Long.MAX_VALUE); + } + + @Override + public void onNext(ByteBuffer byteBuffer) { + } + + @Override + public void onError(Throwable throwable) { + result.completeExceptionally(throwable); + } + + @Override + public void onComplete() { + scheduler.schedule(() -> result.complete(null), INJECTED_DELAY.toMillis(), TimeUnit.MILLISECONDS); + } + }); + } + + @Override + public void exceptionOccurred(Throwable error) { + result.completeExceptionally(error); + } + } + + private static final class DelayingInterceptor implements ExecutionInterceptor { + private final Phase phase; + + private DelayingInterceptor(Phase phase) { + this.phase = phase; + } + + @Override + public void beforeMarshalling(Context.BeforeMarshalling context, ExecutionAttributes executionAttributes) { + if (phase == Phase.BEFORE_MARSHALLING) { + sleep(); + } + } + + @Override + public void afterExecution(Context.AfterExecution context, ExecutionAttributes executionAttributes) { + if (phase == Phase.AFTER_EXECUTION) { + sleep(); + } + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java index c1ec12515ca0..f25d137beab8 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java @@ -212,6 +212,21 @@ public void testApiCall_operationSuccessful_addsMetrics() { .isGreaterThanOrEqualTo(Duration.ZERO); } + @Test + public void testApiCall_operationSuccessful_apiCallDurationEnclosesItsComponents() { + client.allTypes(); + + ArgumentCaptor collectionCaptor = ArgumentCaptor.forClass(MetricCollection.class); + verify(mockPublisher).publish(collectionCaptor.capture()); + + MetricCollection capturedCollection = collectionCaptor.getValue(); + + ApiCallDurationAssertions.assertEnclosesComponents(capturedCollection); + ApiCallDurationAssertions.assertEnclosesComponentSum(capturedCollection); + } + + + @Test public void testApiCall_serviceReturnsError_errorInfoIncludedInMetrics() throws IOException { AbortableInputStream content = contentStream("{}"); @@ -244,6 +259,7 @@ public void testApiCall_serviceReturnsError_errorInfoIncludedInMetrics() throws assertThat(capturedCollection.children()).hasSize(MAX_ATTEMPTS); assertThat(capturedCollection.metricValues(CoreMetric.RETRY_COUNT)).containsExactly(MAX_RETRIES); assertThat(capturedCollection.metricValues(CoreMetric.API_CALL_SUCCESSFUL)).containsExactly(false); + ApiCallDurationAssertions.assertEnclosesComponents(capturedCollection); for (MetricCollection requestMetrics : capturedCollection.children()) { // A service exception is still a successful HTTP execution so diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/async/BaseAsyncCoreMetricsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/async/BaseAsyncCoreMetricsTest.java index 851da2a007dd..628507255e36 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/async/BaseAsyncCoreMetricsTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/async/BaseAsyncCoreMetricsTest.java @@ -44,6 +44,7 @@ import software.amazon.awssdk.http.HttpMetric; import software.amazon.awssdk.metrics.MetricCollection; import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.services.metrics.ApiCallDurationAssertions; import software.amazon.awssdk.services.protocolrestjson.model.EmptyModeledException; @RunWith(MockitoJUnitRunner.class) @@ -268,6 +269,11 @@ private void verifySuccessfulApiCallCollection(MetricCollection capturedCollecti verifyApiCallCollection(capturedCollection); assertThat(capturedCollection.metricValues(CoreMetric.RETRY_COUNT)).containsExactly(0); assertThat(capturedCollection.metricValues(CoreMetric.API_CALL_SUCCESSFUL)).containsExactly(true); + // Note: the javadoc additivity formula is deliberately not asserted as a whole here, only per component in + // verifyApiCallCollection. On async the phases are not disjoint: SERVICE_CALL_DURATION does not stop at time to + // first byte, as noted on CoreMetric.TIME_TO_FIRST_BYTE, so for a streaming operation it overlaps + // UNMARSHALLING_DURATION and their sum can marginally exceed ApiCallDuration. That is a separate defect in + // SERVICE_CALL_DURATION, not in the window measured here. } private void verifyApiCallCollection(MetricCollection capturedCollection) { @@ -284,6 +290,9 @@ private void verifyApiCallCollection(MetricCollection capturedCollection) { .isGreaterThan(FIXED_DELAY); assertThat(capturedCollection.metricValues(CoreMetric.SERVICE_ENDPOINT).get(0)).toString() .startsWith("http://localhost"); + // The async client used to measure ApiCallDuration from the signing stage onwards, which excluded marshalling + // and endpoint resolution. Guard against that regression, and against the two clients diverging again. + ApiCallDurationAssertions.assertEnclosesComponents(capturedCollection); } void stubSuccessfulResponse() { diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/noregion/NoRegionSigningRegionTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/noregion/NoRegionSigningRegionTest.java new file mode 100644 index 000000000000..0f5c6ce6935f --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/noregion/NoRegionSigningRegionTest.java @@ -0,0 +1,74 @@ +/* + * 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.noregion; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute; +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.regions.Region; + +/** + * Verifies that signing region is correctly resolved at request time for a service + * without AWS_REGION in its endpoint params. The endpoint rules define signingRegion: "us-east-1" + * in the auth scheme, which should be applied at request time regardless of the client region. + */ +public class NoRegionSigningRegionTest { + + @Test + void signingRegion_resolvedFromEndpointRulesAtRequestTime() { + SigningRegionCapturingInterceptor interceptor = new SigningRegionCapturingInterceptor(); + + NoRegionClient client = NoRegionClient.builder() + .region(Region.US_WEST_2) // Client configured with us-west-2 + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)) + .endpointOverride(java.net.URI.create("https://noregionservice.us-east-1.amazonaws.com")) + .build(); + + try { + client.someOperation(r -> r.stringMember("test")); + } catch (SigningRegionCapturingInterceptor.CaptureCompletedException e) { + // Expected — we throw after capturing + } + + // The signing region should come from the endpoint rules auth scheme (us-east-1), + // not the client region (us-west-2) + assertThat(interceptor.signingRegion).isNotNull(); + assertThat(interceptor.signingRegion.id()).isEqualTo("us-east-1"); + + client.close(); + } + + private static class SigningRegionCapturingInterceptor implements ExecutionInterceptor { + private Region signingRegion; + + @Override + public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + signingRegion = executionAttributes.getAttribute(AwsSignerExecutionAttribute.SIGNING_REGION); + throw new CaptureCompletedException(); + } + + static class CaptureCompletedException extends RuntimeException { + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/AsyncOperationCancelTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/AsyncOperationCancelTest.java index e243a489ddbb..e99874dae0a6 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/AsyncOperationCancelTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/AsyncOperationCancelTest.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.services.protocolquery; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -35,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** @@ -49,13 +51,18 @@ public class AsyncOperationCancelTest { private CompletableFuture executeFuture; + private ScheduledExecutorService scheduledExec; + @Before public void setUp() { + scheduledExec = mock(ScheduledExecutorService.class); + client = ProtocolQueryAsyncClient.builder() .region(Region.US_EAST_1) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("foo", "bar"))) .httpClient(mockHttpClient) + .overrideConfiguration(o -> o.scheduledExecutorService(scheduledExec)) .build(); executeFuture = new CompletableFuture(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/MoveQueryParamsToBodyTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/MoveQueryParamsToBodyTest.java index 559c36a8019b..9532d4bd83c6 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/MoveQueryParamsToBodyTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolquery/MoveQueryParamsToBodyTest.java @@ -129,7 +129,7 @@ public void customInterceptor_asyncClient_additionalQueryParamsAdded_paramsAlsoM .build(); ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); - asyncClient.membersInQueryParams(r -> r.stringQueryParam("hello")); + assertThatThrownBy(asyncClient.membersInQueryParams(r -> r.stringQueryParam("hello"))::join); verify(asyncMockHttpClient, atLeast(1)).execute(requestCaptor.capture()); verifyParametersMovedToBody_asyncClient(requestCaptor); @@ -164,7 +164,7 @@ public void requestOverrideConfiguration_asyncClient_additionalQueryParamsAdded_ ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); - asyncClient.membersInQueryParams(r -> r.stringQueryParam("hello").overrideConfiguration(createOverrideConfigWithQueryParams())); + assertThatThrownBy(asyncClient.membersInQueryParams(r -> r.stringQueryParam("hello").overrideConfiguration(createOverrideConfigWithQueryParams()))::join); verify(asyncMockHttpClient, atLeast(1)).execute(requestCaptor.capture()); verifyParametersMovedToBody_asyncClient(requestCaptor); } @@ -199,7 +199,7 @@ public void asyncClient_noQueryParamsAdded_onlyContainsOriginalContent() throws .build(); ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); - asyncClient.allTypes(r -> r.stringMember("hello")); + assertThatThrownBy(asyncClient.allTypes(r -> r.stringMember("hello"))::join); verify(asyncMockHttpClient, atLeast(1)).execute(requestCaptor.capture()); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/AsyncOperationCancelTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/AsyncOperationCancelTest.java index 932f4a9032ac..876ea2fda4ff 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/AsyncOperationCancelTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/AsyncOperationCancelTest.java @@ -17,10 +17,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import io.reactivex.Flowable; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -43,7 +45,8 @@ import software.amazon.awssdk.services.protocolrestjson.model.StreamingOutputOperationResponse; /** - * Test to ensure that cancelling the future returned for an async operation will cancel the future returned by the async HTTP client. + * Test to ensure that cancelling the future returned for an async operation will cancel the future returned by the async HTTP + * client. */ @RunWith(MockitoJUnitRunner.class) public class AsyncOperationCancelTest { @@ -54,22 +57,29 @@ public class AsyncOperationCancelTest { private CompletableFuture executeFuture; + private ScheduledExecutorService scheduledExec; + @Before public void setUp() { + scheduledExec = mock(ScheduledExecutorService.class); + client = ProtocolRestJsonAsyncClient.builder() - .region(Region.US_EAST_1) - .credentialsProvider(StaticCredentialsProvider.create( - AwsBasicCredentials.create("foo", "bar"))) - .httpClient(mockHttpClient) - .build(); + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("foo", "bar"))) + .httpClient(mockHttpClient) + .overrideConfiguration(o -> o.scheduledExecutorService(scheduledExec)) + .build(); executeFuture = new CompletableFuture<>(); + when(mockHttpClient.execute(any())).thenReturn(executeFuture); } @Test - public void testNonStreamingOperation() { - CompletableFuture responseFuture = client.allTypes(r -> {}); + public void testNonStreamingOperation() throws InterruptedException { + CompletableFuture responseFuture = client.allTypes(r -> { + }); responseFuture.cancel(true); assertThat(executeFuture.isCompletedExceptionally()).isTrue(); assertThat(executeFuture.isCancelled()).isTrue(); @@ -77,7 +87,8 @@ public void testNonStreamingOperation() { @Test public void testStreamingOperation() { - CompletableFuture responseFuture = client.streamingInputOperation(r -> {}, AsyncRequestBody.empty()); + CompletableFuture responseFuture = client.streamingInputOperation(r -> { + }, AsyncRequestBody.empty()); responseFuture.cancel(true); assertThat(executeFuture.isCompletedExceptionally()).isTrue(); assertThat(executeFuture.isCancelled()).isTrue(); @@ -95,25 +106,26 @@ public void testStreamingOutputOperation() { @Test public void testEventStreamingOperation() throws InterruptedException { CompletableFuture responseFuture = - client.eventStreamOperation(r -> {}, + client.eventStreamOperation(r -> { + }, Flowable.just(InputEventStream.inputEventBuilder().build()), - new EventStreamOperationResponseHandler() { - @Override - public void responseReceived(EventStreamOperationResponse response) { - } - - @Override - public void onEventStream(SdkPublisher publisher) { - } - - @Override - public void exceptionOccurred(Throwable throwable) { - } - - @Override - public void complete() { - } - }); + new EventStreamOperationResponseHandler() { + @Override + public void responseReceived(EventStreamOperationResponse response) { + } + + @Override + public void onEventStream(SdkPublisher publisher) { + } + + @Override + public void exceptionOccurred(Throwable throwable) { + } + + @Override + public void complete() { + } + }); responseFuture.cancel(true); assertThat(executeFuture.isCompletedExceptionally()).isTrue(); assertThat(executeFuture.isCancelled()).isTrue(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestxml/AsyncOperationCancelTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestxml/AsyncOperationCancelTest.java index 51deef21c7e5..2d221a115e8a 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestxml/AsyncOperationCancelTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestxml/AsyncOperationCancelTest.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.services.protocolrestxml; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** @@ -53,13 +55,18 @@ public class AsyncOperationCancelTest { private CompletableFuture executeFuture; + private ScheduledExecutorService scheduledExec; + @Before public void setUp() { + scheduledExec = mock(ScheduledExecutorService.class); + client = ProtocolRestXmlAsyncClient.builder() .region(Region.US_EAST_1) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("foo", "bar"))) .httpClient(mockHttpClient) + .overrideConfiguration(o -> o.scheduledExecutorService(scheduledExec)) .build(); executeFuture = new CompletableFuture(); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/restjsonendpointproviders/endpoints/internal/RestJsonEndpointProvidersEndpointProviderTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/restjsonendpointproviders/endpoints/internal/RestJsonEndpointProvidersEndpointProviderTest.java deleted file mode 100644 index 755828a7871b..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/restjsonendpointproviders/endpoints/internal/RestJsonEndpointProvidersEndpointProviderTest.java +++ /dev/null @@ -1,137 +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.restjsonendpointproviders.endpoints.internal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme; -import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.utils.MapUtils; - -class RestJsonEndpointProvidersEndpointProviderTest { - - private DefaultRestJsonEndpointProvidersEndpointProvider provider; - - @BeforeEach - void init() { - this.provider = new DefaultRestJsonEndpointProvidersEndpointProvider(); - } - - @Test - public void valueAsEndpoint_isNone_throws() { - assertThatThrownBy(() -> provider.valueAsEndpointOrThrow(Value.none())) - .isInstanceOf(SdkClientException.class); - } - - @Test - public void valueAsEndpoint_isString_throwsAsMsg() { - assertThatThrownBy(() -> provider.valueAsEndpointOrThrow(Value.fromStr("oops!"))) - .isInstanceOf(SdkClientException.class) - .hasMessageContaining("oops!"); - } - - @Test - public void valueAsEndpoint_isEndpoint_returnsEndpoint() { - Value.Endpoint endpointVal = Value.Endpoint.builder() - .url("https://myservice.aws") - .build(); - - Endpoint expected = Endpoint.builder() - .url(URI.create("https://myservice.aws")) - .build(); - - assertThat(expected.url()).isEqualTo(provider.valueAsEndpointOrThrow(endpointVal).url()); - } - - @Test - public void valueAsEndpoint_endpointHasAuthSchemes_includesAuthSchemes() { - List authSchemes = Arrays.asList( - Value.fromRecord(MapUtils.of(Identifier.of("name"), Value.fromStr("sigv4"), - Identifier.of("signingRegion"), Value.fromStr("us-west-2"), - Identifier.of("signingName"), Value.fromStr("myservice"), - Identifier.of("disableDoubleEncoding"), Value.fromBool(false))), - - Value.fromRecord(MapUtils.of(Identifier.of("name"), Value.fromStr("sigv4a"), - Identifier.of("signingRegionSet"), - Value.fromArray(Collections.singletonList(Value.fromStr("*"))), - Identifier.of("signingName"), Value.fromStr("myservice"), - Identifier.of("disableDoubleEncoding"), Value.fromBool(false))), - - // Unknown scheme name, should ignore - Value.fromRecord(MapUtils.of(Identifier.of("name"), Value.fromStr("sigv5"))) - ); - - - Value.Endpoint endpointVal = Value.Endpoint.builder() - .url("https://myservice.aws") - .property("authSchemes", Value.fromArray(authSchemes)) - .build(); - - - EndpointAuthScheme sigv4 = SigV4AuthScheme.builder() - .signingName("myservice") - .signingRegion("us-west-2") - .disableDoubleEncoding(false) - .build(); - - EndpointAuthScheme sigv4a = SigV4aAuthScheme.builder() - .signingName("myservice") - .addSigningRegion("*") - .disableDoubleEncoding(false) - .build(); - - assertThat(provider.valueAsEndpointOrThrow(endpointVal).attribute(AwsEndpointAttribute.AUTH_SCHEMES)) - .containsExactly(sigv4, sigv4a); - } - - @Test - public void valueAsEndpoint_endpointHasUnknownProperty_ignores() { - Value.Endpoint endpointVal = Value.Endpoint.builder() - .url("https://myservice.aws") - .property("foo", Value.fromStr("baz")) - .build(); - - assertThat(provider.valueAsEndpointOrThrow(endpointVal).attribute(AwsEndpointAttribute.AUTH_SCHEMES)).isNull(); - } - - @Test - public void valueAsEndpoint_endpointHasHeaders_includesHeaders() { - Value.Endpoint endpointVal = Value.Endpoint.builder() - .url("https://myservice.aws") - .addHeader("foo1", "bar1") - .addHeader("foo1", "bar2") - .addHeader("foo2", "baz") - .build(); - - Map> expectedHeaders = MapUtils.of("foo1", Arrays.asList("bar1", "bar2"), - "foo2", Arrays.asList("baz")); - - assertThat(provider.valueAsEndpointOrThrow(endpointVal).headers()).isEqualTo(expectedHeaders); - } - -} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/AdaptiveRetryRateLimitingTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/AdaptiveRetryRateLimitingTest.java new file mode 100644 index 000000000000..24bc160e9f9f --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/retry/AdaptiveRetryRateLimitingTest.java @@ -0,0 +1,278 @@ +/* + * 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.retry; + +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.core.WireMockConfiguration.options; +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.tomakehurst.wiremock.common.FileSource; +import com.github.tomakehurst.wiremock.extension.Parameters; +import com.github.tomakehurst.wiremock.extension.ResponseDefinitionTransformer; +import com.github.tomakehurst.wiremock.http.Request; +import com.github.tomakehurst.wiremock.http.ResponseDefinition; +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; +import com.github.tomakehurst.wiremock.stubbing.ServeEvent; +import java.net.URI; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.awscore.client.builder.AwsDefaultClientBuilder; +import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.retries.AdaptiveRetryStrategy; +import software.amazon.awssdk.services.json.JsonAsyncClient; +import software.amazon.awssdk.services.json.JsonAsyncClientBuilder; +import software.amazon.awssdk.services.json.JsonClient; +import software.amazon.awssdk.services.json.JsonClientBuilder; + +/** + * End-to-end testing for testing the correctness of the rate limiting implementation of the adaptive retry strategy. + */ +class AdaptiveRetryRateLimitingTest { + private static final AtomicLong eventCount = new AtomicLong(0L); + + private static final int throttleTps = 20; + private static final double tpsLower = throttleTps * 0.5; + private static final double tpsUpper = throttleTps * 1.5; + + private static final Duration testDuration = Duration.ofSeconds(30); + private static final Duration warmupDuration = Duration.ofSeconds(2); + private static final Duration tailTrim = Duration.ofSeconds(1); + private static final int numWorkerThreads = Runtime.getRuntime().availableProcessors(); + + private static final RollingThrottle throttler = new RollingThrottle(throttleTps); + + private static String newRetriesPropertySave; + + @RegisterExtension + static WireMockExtension wm = WireMockExtension.newInstance() + .options(options().dynamicPort() + .extensions(new ThrottlingTransformer())) + .build(); + + @BeforeAll + static void setup() { + newRetriesPropertySave = System.getProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()); + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), "true"); + } + + @AfterAll + static void teardown() { + if (newRetriesPropertySave != null) { + System.setProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property(), newRetriesPropertySave); + } else { + System.clearProperty(SdkSystemSetting.AWS_NEW_RETRIES_2026.property()); + } + } + + @Test + void staticServerThrottling_sync() throws Exception { + JsonClientBuilder builder = JsonClient.builder(); + configure(builder); + JsonClient client = builder.build(); + + Callable c = () -> { + client.allType(r -> {}); + return null; + }; + + try { + testStaticServerThrottling(c); + } finally { + client.close(); + } + } + + @Test + void staticServerThrottling_async() throws Exception { + JsonAsyncClientBuilder builder = JsonAsyncClient.builder(); + configure(builder); + JsonAsyncClient client = builder.build(); + + Callable c = () -> { + client.allType(r -> {}).join(); + return null; + }; + + try { + testStaticServerThrottling(c); + } finally { + client.close(); + } + } + + private void configure(AwsClientBuilder builder) { + AdaptiveRetryStrategy adaptiveRetryStrategy = AwsRetryStrategy.adaptiveRetryStrategy(true); + + builder.endpointOverride(URI.create(wm.baseUrl())) + .region(Region.US_WEST_2) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "secret"))) + .overrideConfiguration(o -> o.retryStrategy(adaptiveRetryStrategy)) + .build(); + } + + /** + * The server has a static max TPS of 20 before responding with throttling exceptions. The client sending rate should match + * this within an acceptable margin. + */ + void testStaticServerThrottling(Callable operationInvoker) throws Exception { + + wm.stubFor(any(anyUrl()).willReturn(aResponse().withTransformers("throttling"))); + + + Instant startT = Instant.now(); + Instant endAt = startT.plus(testDuration); + AtomicBoolean stop = new AtomicBoolean(false); + + ExecutorService pool = Executors.newFixedThreadPool(numWorkerThreads); + try { + List> futures = IntStream.range(0, numWorkerThreads) + .mapToObj(i -> pool.submit(() -> { + while (!stop.get() && Instant.now().isBefore(endAt)) { + try { + operationInvoker.call(); + } catch (Exception e) { + // We measure wire-level TPS, not call success. + // Throttling exceptions surface here once retries are exhausted. + } + } + })) + .collect(Collectors.toList()); + + for (Future f : futures) { + f.get(testDuration.getSeconds() + 30, TimeUnit.SECONDS); + } + } finally { + stop.set(true); + } + Instant endT = Instant.now(); + + double measuredTps = tpsInWindow( + wm.getAllServeEvents(), + startT.plus(warmupDuration), + endT.minus(tailTrim)); + + assertThat(measuredTps) + .as("Expected send rate >= %.1f TPS, but got %.1f TPS. " + + "Is the SDK not converging to the server throttle rate?", + tpsLower, measuredTps) + .isGreaterThanOrEqualTo(tpsLower); + assertThat(measuredTps) + .as("Expected send rate <= %.1f TPS, but got %.1f TPS. " + + "Is the SDK not respecting the server throttle rate limit?", + tpsUpper, measuredTps) + .isLessThanOrEqualTo(tpsUpper); + } + + private static double tpsInWindow(List events, Instant from, Instant to) { + long count = events.stream() + .map(e -> e.getRequest().getLoggedDate().toInstant()) + .filter(t -> !t.isBefore(from) && t.isBefore(to)) + .count(); + double seconds = Duration.between(from, to).toMillis() / 1000.0; + return seconds <= 0 ? 0 : count / seconds; + } + + /** + * Sliding 1-second window admission control. Once {@code TPS} requests have been admitted within the past second, returns + * false until the window slides. + */ + static final class RollingThrottle { + private final int tps; + private final ConcurrentLinkedDeque hits = new ConcurrentLinkedDeque<>(); + + RollingThrottle(int tps) { + this.tps = tps; + } + + synchronized boolean tryAcquire() { + long now = System.nanoTime(); + long cutoff = now - TimeUnit.SECONDS.toNanos(1); + while (!hits.isEmpty() && hits.peekFirst() < cutoff) { + hits.pollFirst(); + } + if (hits.size() >= tps) { + return false; + } + hits.addLast(now); + return true; + } + } + + /** + * WireMock transformer that delegates the 200-vs-throttle decision to {@link #throttler}. + */ + public static final class ThrottlingTransformer extends ResponseDefinitionTransformer { + + private static final String successBody = "{}"; + private static final String throttleBody = + "{\"__type\":\"ThrottlingException\",\"message\":\"Rate exceeded\"}"; + + @Override + public String getName() { + return "throttling"; + } + + @Override + public boolean applyGlobally() { + return false; + } + + @Override + public ResponseDefinition transform(Request request, + ResponseDefinition responseDefinition, + FileSource files, + Parameters parameters) { + eventCount.incrementAndGet(); + + if (throttler.tryAcquire()) { + return aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/x-amz-json-1.0") + .withBody(successBody) + .build(); + } + return aResponse() + .withStatus(400) + .withHeader("Content-Type", "application/x-amz-json-1.0") + .withHeader("x-amzn-ErrorType", "ThrottlingException") + .withBody(throttleBody) + .build(); + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/DefaultVisitor.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/DefaultVisitor.java deleted file mode 100644 index b805994d098c..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/DefaultVisitor.java +++ /dev/null @@ -1,117 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.List; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.BooleanEqualsFn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointResult; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Expr; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.ExprVisitor; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Fn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.FnVisitor; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.GetAttr; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.IsSet; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.IsValidHostLabel; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.IsVirtualHostableS3Bucket; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Literal; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Not; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.ParseArn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.ParseUrl; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.PartitionFn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Ref; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Rule; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.RuleValueVisitor; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.StringEqualsFn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Substring; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.UriEncodeFn; - -public abstract class DefaultVisitor implements RuleValueVisitor, ExprVisitor, FnVisitor { - public abstract R getDefault(); - - @Override - public R visitLiteral(Literal literal) { - return getDefault(); - } - - @Override - public R visitRef(Ref ref) { - return getDefault(); - } - - @Override - public R visitFn(Fn fn) { - return getDefault(); - } - - @Override - public R visitPartition(PartitionFn fn) { - return getDefault(); - } - - @Override - public R visitParseArn(ParseArn fn) { - return getDefault(); - } - - - @Override - public R visitIsValidHostLabel(IsValidHostLabel fn) { - return getDefault(); - } - - @Override - public R visitBoolEquals(BooleanEqualsFn fn) { - return getDefault(); - } - - @Override - public R visitStringEquals(StringEqualsFn fn) { - return getDefault(); - } - - @Override - public R visitIsSet(IsSet fn) { - return getDefault(); - } - - @Override - public R visitNot(Not not) { - return getDefault(); - } - - @Override - public R visitGetAttr(GetAttr getAttr) { - return getDefault(); - } - - @Override - public R visitParseUrl(ParseUrl parseUrl) { - return getDefault(); - } - - @Override - public R visitSubstring(Substring substring) { return getDefault(); } - - @Override - public R visitTreeRule(List rules) { - return getDefault(); - } - - @Override - public R visitErrorRule(Expr error) { - return getDefault(); - } - - @Override - public R visitEndpointRule(EndpointResult endpoint) { - return getDefault(); - } - - @Override - public R visitUriEncode(UriEncodeFn fn) { - return getDefault(); - } - - @Override - public R visitIsVirtualHostLabelsS3Bucket(IsVirtualHostableS3Bucket fn) { - return getDefault(); - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTest.java deleted file mode 100644 index 4636966756a2..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTest.java +++ /dev/null @@ -1,241 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Optional; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Identifier; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Parameter; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.ParameterType; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.RuleEngine; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.RuleError; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Value; -import software.amazon.awssdk.utils.Pair; - -public class EndpointTest { - public static final String EXPECT = "expect"; - public static final String PARAMS = "params"; - public static final String DOCUMENTATION = "documentation"; - - private final String documentation; - - public Expectation getExpectation() { - return expectation; - } - - private final Expectation expectation; - - private final Value.Record params; - - private EndpointTest(Builder builder) { - this.documentation = builder.documentation; - this.expectation = Optional.ofNullable(builder.expectation).orElseThrow(NoSuchElementException::new); - this.params = Optional.ofNullable(builder.params).orElseThrow(NoSuchElementException::new);; - } - - public String getDocumentation() { - return documentation; - } - - public List> getParams() { - ArrayList> out = new ArrayList<>(); - params.forEach((name, value) -> { - out.add(Pair.of(name, value)); - }); - return out; - } - - public List getParameters() { - ArrayList result = new ArrayList(); - params.forEach((name, value) -> { - - Parameter.Builder pb = Parameter.builder().name(name); - - if (value instanceof Value.Str) { - pb.type(ParameterType.STRING); - result.add(pb.build()); - } else if (value instanceof Value.Bool) { - pb.type(ParameterType.BOOLEAN); - result.add(pb.build()); - } - }); - return result; - } - - public void execute(EndpointRuleset ruleset) { - Value actual = RuleEngine.defaultEngine().evaluate(ruleset, this.params.getValue()); - RuleError.ctx( - String.format("while executing test case%s", Optional - .ofNullable(documentation) - .map(d -> " " + d) - .orElse("")), - () -> expectation.check(actual) - ); - } - - public static EndpointTest fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder b = builder(); - - JsonNode documentationNode = objNode.get(DOCUMENTATION); - if (documentationNode != null) { - b.documentation(documentationNode.asString()); - } - - b.params(Value.fromNode(objNode.get(PARAMS)).expectRecord()); - b.expectation(Expectation.fromNode(objNode.get(EXPECT))); - - return b.build(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - EndpointTest that = (EndpointTest) o; - - if (documentation != null ? !documentation.equals(that.documentation) : that.documentation != null) - return false; - if (!expectation.equals(that.expectation)) return false; - return params.equals(that.params); - } - - @Override - public int hashCode() { - int result = documentation != null ? documentation.hashCode() : 0; - result = 31 * result + expectation.hashCode(); - result = 31 * result + params.hashCode(); - return result; - } - - public static Builder builder() { - return new Builder(); - } - - public static abstract class Expectation { - public static final String ERROR = "error"; - - public static Expectation fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Expectation result; - JsonNode errorNode = objNode.get(ERROR); - if (errorNode != null) { - result = new Error(errorNode.asString()); - } else { - result = new Endpoint(Value.endpointFromNode(node)); - } - return result; - } - - abstract void check(Value value); - - public static Error error(String message) { - return new Error(message); - } - - public static class Error extends Expectation { - public String getMessage() { - return message; - } - - private final String message; - - public Error(String message) { - this.message = message; - } - - @Override - void check(Value value) { - RuleError.ctx("While checking endpoint test (expecting an error)", () -> { - if (!value.expectString().equals(this.message)) { - throw new AssertionError(String.format("Expected error %s but got %s", this.message, value)); - } - }); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Error error = (Error) o; - - return message.equals(error.message); - } - - @Override - public int hashCode() { - return message.hashCode(); - } - } - - public static class Endpoint extends Expectation { - public Value.Endpoint getEndpoint() { - return endpoint; - } - - private final Value.Endpoint endpoint; - - public Endpoint(Value.Endpoint endpoint) { - this.endpoint = endpoint; - } - - @Override - void check(Value value) { - Value.Endpoint actual = value.expectEndpoint(); - if (!actual.equals(this.endpoint)) { - throw new AssertionError( - String.format("Expected endpoint:\n%s but got:\n%s", - this.endpoint.toString(), - actual)); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Endpoint endpoint1 = (Endpoint) o; - - return endpoint != null ? endpoint.equals(endpoint1.endpoint) : endpoint1.endpoint == null; - } - - @Override - public int hashCode() { - return endpoint != null ? endpoint.hashCode() : 0; - } - } - } - - public static class Builder { - private String documentation; - private Expectation expectation; - private Value.Record params; - - public Builder documentation(String documentation) { - this.documentation = documentation; - return this; - } - - public Builder expectation(Expectation expectation) { - this.expectation = expectation; - return this; - } - - public Builder params(Value.Record params) { - this.params = params; - return this; - } - - public EndpointTest build() { - return new EndpointTest(this); - } - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTestSuite.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTestSuite.java deleted file mode 100644 index 5ff9365cedec..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/EndpointTestSuite.java +++ /dev/null @@ -1,94 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; - -public class EndpointTestSuite { - public static final String SERVICE = "service"; - public static final String TEST_CASES = "testCases"; - - private final List testCases; - private final String service; - - - public EndpointTestSuite(String service, List testCases) { - this.service = service; - this.testCases = testCases; - } - - private EndpointTestSuite(Builder b) { - this(b.service, b.testCases); - } - - public void execute(EndpointRuleset ruleset) { - for (EndpointTest test : this.getTestCases()) { - test.execute(ruleset); - } - } - - public static EndpointTestSuite fromNode(JsonNode node) { - Map objNode = node.asObject(); - - Builder b = builder(); - - b.service(objNode.get(SERVICE).asString()); - objNode.get(TEST_CASES).asArray() - .stream().map(EndpointTest::fromNode) - .forEach(b::addTestCase); - - return b.build(); - } - - public String getService() { - return service; - } - - public List getTestCases() { - return testCases; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - EndpointTestSuite that = (EndpointTestSuite) o; - - if (!testCases.equals(that.testCases)) return false; - return service.equals(that.service); - } - - @Override - public int hashCode() { - int result = testCases.hashCode(); - result = 31 * result + service.hashCode(); - return result; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String service; - private final List testCases = new ArrayList<>(); - - public Builder service(String service) { - this.service = service; - return this; - } - - public Builder addTestCase(EndpointTest testCase) { - this.testCases.add(testCase); - return this; - } - - public EndpointTestSuite build() { - return new EndpointTestSuite(this); - } - } - -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/IntegrationTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/IntegrationTest.java deleted file mode 100644 index bde0c8728ed1..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/IntegrationTest.java +++ /dev/null @@ -1,101 +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.rules; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.URL; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; -import software.amazon.awssdk.services.rules.testutil.TestDiscovery; - -@TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class IntegrationTest { - private static final TestDiscovery TEST_DISCOVERY = new TestDiscovery(); - - @ParameterizedTest - @MethodSource("validTestcases") - void checkValidRules(ValidationTestCase validationTestCase) { - EndpointRuleset ruleset = EndpointRuleset.fromNode(validationTestCase.contents()); - List errors = new ValidateUriScheme().visitRuleset(ruleset) - .collect(Collectors.toList()); - assertEquals(errors, Collections.emptyList()); - } - - @ParameterizedTest - @MethodSource("checkableTestCases") - void executeTestSuite(TestDiscovery.RulesTestcase testcase) { - testcase.testcase().execute(testcase.ruleset()); - } - - private Stream validTestcases() { - return TEST_DISCOVERY.getValidRules() - .stream() - .map(name -> new ValidationTestCase(name, TEST_DISCOVERY.validRulesetUrl(name), TEST_DISCOVERY.testCaseUrl(name))); - } - - private Stream checkableTestCases() { - return TEST_DISCOVERY.testSuites() - .flatMap( - suite -> suite.testSuites() - .stream() - .flatMap(ts -> ts.getTestCases() - .stream() - .map(tc -> new TestDiscovery.RulesTestcase(suite.ruleset(), tc)))); - } - - public static final class ValidationTestCase { - private final String name; - private final URL ruleSet; - private final URL testCase; - - public ValidationTestCase(String name, URL ruleSet, URL testCase) { - this.name = name; - this.ruleSet = ruleSet; - this.testCase = testCase; - } - - JsonNode contents() { - try { - return JsonNode.parser().parse(ruleSet.openStream()); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - public URL ruleSet() { - return ruleSet; - } - - public URL testCase() { - return testCase; - } - - @Override - public String toString() { - return name; - } - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/RuleEngineTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/RuleEngineTest.java deleted file mode 100644 index b97688fbaf17..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/RuleEngineTest.java +++ /dev/null @@ -1,55 +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.rules; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.InputStream; -import java.util.Collections; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.protocols.jsoncore.JsonNodeParser; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Identifier; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.RuleEngine; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Value; -import software.amazon.awssdk.utils.MapUtils; - -public class RuleEngineTest { - private EndpointRuleset parse(String resource) { - InputStream is = getClass().getClassLoader().getResourceAsStream(resource); - JsonNode node = JsonNodeParser.create().parse(is); - return EndpointRuleset.fromNode(node); - } - - @Test - void testRuleEval() { - EndpointRuleset actual = parse("rules/valid-rules/minimal-ruleset.json"); - Value result = RuleEngine.defaultEngine().evaluate(actual, MapUtils.of(Identifier.of("Region"), Value.fromStr("us-east-1"))); - Value.Endpoint expected = Value.Endpoint.builder() - .url("https://us-east-1.amazonaws.com") - .property("authSchemes", Value.fromArray(Collections.singletonList( - Value.fromRecord(MapUtils.of( - Identifier.of("name"), Value.fromStr("v4"), - Identifier.of("signingScope"), Value.fromStr("us-east-1"), - Identifier.of("signingName"), Value.fromStr("serviceName") - )) - ))) - .build(); - - assertThat(result.expectEndpoint()).isEqualTo(expected); - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/TraversingVisitor.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/TraversingVisitor.java deleted file mode 100644 index d5124a6dbc46..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/TraversingVisitor.java +++ /dev/null @@ -1,63 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.List; -import java.util.stream.Stream; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Condition; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointResult; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Expr; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Fn; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Rule; - -public abstract class TraversingVisitor extends DefaultVisitor> { - public Stream visitRuleset(EndpointRuleset ruleset) { - return ruleset.getRules() - .stream() - .flatMap(this::handleRule); - } - - private Stream handleRule(Rule rule) { - Stream fromConditions = visitConditions(rule.getConditions()); - return Stream.concat(fromConditions, rule.accept(this)); - } - - @Override - public Stream visitFn(Fn fn) { - return fn.acceptFnVisitor(this); - } - - @Override - public Stream getDefault() { - return Stream.empty(); - } - - @Override - public Stream visitEndpointRule(EndpointResult endpoint) { - return visitEndpoint(endpoint); - } - - @Override - public Stream visitErrorRule(Expr error) { - return error.accept(this); - } - - @Override - public Stream visitTreeRule(List rules) { - return rules.stream().flatMap(subrule -> subrule.accept(this)); - } - - public Stream visitEndpoint(EndpointResult endpoint) { - return Stream.concat( - endpoint.getUrl() - .accept(this), - endpoint.getProperties() - .entrySet() - .stream() - .flatMap(map -> map.getValue().accept(this)) - ); - } - - public Stream visitConditions(List conditions) { - return conditions.stream().flatMap(c -> c.getFn().accept(this)); - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidateUriScheme.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidateUriScheme.java deleted file mode 100644 index 75daab21ccfc..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidateUriScheme.java +++ /dev/null @@ -1,71 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointResult; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Identifier; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Literal; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.Template; - -/** - * Validate that URIs start with a scheme - */ -public class ValidateUriScheme extends TraversingVisitor { - boolean checkingEndpoint = false; - - @Override - public Stream visitEndpoint(EndpointResult endpoint) { - checkingEndpoint = true; - Stream errors = endpoint.getUrl().accept(this); - checkingEndpoint = false; - return errors; - } - - @Override - public Stream visitLiteral(Literal literal) { - return literal.accept(new Literal.Visitor>() { - @Override - public Stream visitBool(boolean b) { - return Stream.empty(); - } - - @Override - public Stream visitStr(Template value) { - return validateTemplate(value); - } - - @Override - public Stream visitObject(Map members) { - return Stream.empty(); - } - - @Override - public Stream visitTuple(List members) { - return Stream.empty(); - } - - @Override - public Stream visitInt(int value) { - return Stream.empty(); - } - }); - } - - private Stream validateTemplate(Template template) { - if (checkingEndpoint) { - Template.Part head = template.getParts().get(0); - if (head instanceof Template.Literal) { - String templateStart = ((Template.Literal) head).getValue(); - if (!(templateStart.startsWith("http://") || templateStart.startsWith("https://"))) { - return Stream.of(new ValidationError( - ValidationErrorType.INVALID_URI, - "URI should start with `http://` or `https://` but the URI started with " + templateStart) - ); - } - } - /* Allow dynamic URIs for now—we should lint that at looks like a scheme at some point */ - } - return Stream.empty(); - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationError.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationError.java deleted file mode 100644 index 4e37db505cbb..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationError.java +++ /dev/null @@ -1,41 +0,0 @@ -package software.amazon.awssdk.services.rules; - -import java.util.Objects; - -public final class ValidationError { - private final ValidationErrorType validationErrorType; - private final String error; - - public ValidationError(ValidationErrorType validationErrorType, String error) { - this.validationErrorType = validationErrorType; - this.error = error; - } - - public ValidationErrorType validationErrorType() { - return validationErrorType; - } - - public String error() { - return error; - } - - @Override - public String toString() { - return this.validationErrorType + ", " + this.error; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - ValidationError that = (ValidationError) obj; - return Objects.equals(this.validationErrorType, that.validationErrorType) && - Objects.equals(this.error, that.error); - } - - @Override - public int hashCode() { - return Objects.hash(validationErrorType, error); - } - -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationErrorType.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationErrorType.java deleted file mode 100644 index 36b4d93f6bd5..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/ValidationErrorType.java +++ /dev/null @@ -1,14 +0,0 @@ -package software.amazon.awssdk.services.rules; - -public enum ValidationErrorType { - INCONSISTENT_PARAMETER_TYPE, - UNSUPPORTED_PARAMETER_TYPE, - PARAMETER_MISMATCH, - PARAMETER_TYPE_MISMATCH, - SERVICE_ID_MISMATCH, - REQUIRED_PARAMETER_MISSING, - PARAMETER_IS_NOT_USED, - PARAMETER_IS_NOT_DEFINED, - - INVALID_URI, -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/testutil/TestDiscovery.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/testutil/TestDiscovery.java deleted file mode 100644 index d8099708f535..000000000000 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rules/testutil/TestDiscovery.java +++ /dev/null @@ -1,196 +0,0 @@ -package software.amazon.awssdk.services.rules.testutil; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UncheckedIOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import software.amazon.awssdk.protocols.jsoncore.JsonNode; -import software.amazon.awssdk.services.restjsonendpointproviders.endpoints.internal.EndpointRuleset; -import software.amazon.awssdk.services.rules.EndpointTest; -import software.amazon.awssdk.services.rules.EndpointTestSuite; - -public class TestDiscovery { - private static final String RESOURCE_ROOT = "/rules"; - - public static final class RulesTestcase { - private final EndpointRuleset ruleset; - private final EndpointTest testcase; - - public RulesTestcase(EndpointRuleset ruleset, EndpointTest testcase) { - this.ruleset = ruleset; - this.testcase = testcase; - } - - @Override - public String toString() { - return testcase.getDocumentation(); - } - - public EndpointRuleset ruleset() { - return ruleset; - } - - public EndpointTest testcase() { - return testcase; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - RulesTestcase that = (RulesTestcase) obj; - return Objects.equals(this.ruleset, that.ruleset) && - Objects.equals(this.testcase, that.testcase); - } - - @Override - public int hashCode() { - return Objects.hash(ruleset, testcase); - } - - } - - public static final class RulesTestSuite { - private final EndpointRuleset ruleset; - private final List testSuites; - - public RulesTestSuite(EndpointRuleset ruleset, List testSuites) { - this.ruleset = ruleset; - this.testSuites = testSuites; - } - - @Override - public String toString() { - return ruleset.toString(); - } - - public EndpointRuleset ruleset() { - return ruleset; - } - - public List testSuites() { - return testSuites; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - RulesTestSuite that = (RulesTestSuite) obj; - return Objects.equals(this.ruleset, that.ruleset) && - Objects.equals(this.testSuites, that.testSuites); - } - - @Override - public int hashCode() { - return Objects.hash(ruleset, testSuites); - } - - } - - public Stream testSuites() { - JsonNode.parser(); - List rulesetNodes = getValidRules() - .stream() - .map(e -> JsonNode.parser().parse(getResourceStream("valid-rules/" + e))) - .collect(Collectors.toList()); - - List testSuiteFiles = getManifestEntries("test-cases/manifest.txt") - .stream() - .map(e -> JsonNode.parser().parse(getResourceStream("test-cases/" + e))) - .collect(Collectors.toList()); - - List rulesets = rulesetNodes.stream() - .map(EndpointRuleset::fromNode) - .collect(Collectors.toList()); - List rulesetIds = rulesets.stream() - .map(EndpointRuleset::getServiceId) - .collect(Collectors.toList()); - if (rulesetIds.stream() - .distinct() - .count() != rulesets.size()) { - throw new RuntimeException(String.format("Duplicate service ids discovered: %s", rulesets.stream() - .map(EndpointRuleset::getServiceId) - .sorted() - .collect(Collectors.toList()))); - } - - List testSuites = testSuiteFiles.stream() - .map(EndpointTestSuite::fromNode) - .collect(Collectors.toList()); - testSuites.stream() - .filter(testSuite -> !rulesetIds.contains(testSuite.getService())) - .forEach(bad -> { - throw new RuntimeException("did not find service for " + bad.getService()); - }); - return rulesets.stream() - .map(ruleset -> { - List matchingTestSuites = testSuites.stream() - .filter(test -> test.getService() - .equals(ruleset.getServiceId())) - .collect(Collectors.toList()); - return new RulesTestSuite(ruleset, matchingTestSuites); - }); - } - - private List getManifestEntries(String path) { - String absPath = RESOURCE_ROOT + "/" + path; - try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(absPath)))) { - List entries = new ArrayList<>(); - while (true) { - String e = br.readLine(); - if (e == null) { - break; - } - entries.add(e); - } - return entries; - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private InputStream getResourceStream(String path) { - String absPath = RESOURCE_ROOT + "/" + path; - return getClass().getResourceAsStream(absPath); - } - - private URL getResource(String path) { - String absPath = RESOURCE_ROOT + "/" + path; - return getClass().getResource(absPath); - } - - public RulesTestSuite getTestSuite(String name) { - return new RulesTestSuite(rulesetFromPath(name), Collections.singletonList(testSuiteFromPath(name))); - } - - public List getValidRules() { - return getManifestEntries("valid-rules/manifest.txt"); - } - - public URL validRulesetUrl(String name) { - return getResource("valid-rules/" + name); - } - - public URL testCaseUrl(String name) { - return getResource("test-cases/" + name); - } - - private EndpointRuleset rulesetFromPath(String name) { - return EndpointRuleset.fromNode(JsonNode.parser().parse(Objects.requireNonNull(this.getClass() - .getResourceAsStream(String.format("valid-rules/%s", name))))); - } - - private EndpointTestSuite testSuiteFromPath(String name) { - return EndpointTestSuite.fromNode(JsonNode.parser().parse(Objects.requireNonNull(this.getClass() - .getResourceAsStream(String.format("test-cases/%s", name))))); - } -} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/stringarray/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/stringarray/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java new file mode 100644 index 000000000000..39b9da93cf81 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/stringarray/endpoints/internal/OperationContextParamsBindingEquivalenceTest.java @@ -0,0 +1,258 @@ +/* + * 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.stringarray.endpoints.internal; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.stringarray.endpoints.StringArrayEndpointParams; +import software.amazon.awssdk.services.stringarray.jmespath.internal.JmesPathRuntime.Value; +import software.amazon.awssdk.services.stringarray.model.ListOfObjectsOperationRequest; +import software.amazon.awssdk.services.stringarray.model.ListOfUnionsOperationRequest; +import software.amazon.awssdk.services.stringarray.model.MapOperationRequest; +import software.amazon.awssdk.services.stringarray.model.NestedMapOperationRequest; +import software.amazon.awssdk.services.stringarray.model.ObjectMember; +import software.amazon.awssdk.services.stringarray.model.UnionMember; + +/** + * Verifies that the codegen-lowered {@code operationContextParams} bindings for the synthetic string array service + * produce the same values as the reflective {@code JmesPathRuntime} evaluation, which remains the fallback for + * unsupported expressions and is used here as the equivalence oracle. Covers a projection behind a nullable struct + * ("nested.listOfObjects[*].key"), a multiselect-list + flatten ("listOfUnions[*][string, object.key][]"), + * {@code keys()} over a map ("keys(map)"), and {@code keys()} behind a nullable struct ("keys(nestedMap.map)"). + * + *

    Each lowered binding is invoked directly via its generated, private + * {@code setOperationContextParams(builder, request)} overload, so the check is isolated to the binding itself. + */ +public class OperationContextParamsBindingEquivalenceTest { + + private static List lowered(Object request) { + try { + Method binding = StringArrayEndpointResolverUtils.class.getDeclaredMethod( + "setOperationContextParams", StringArrayEndpointParams.Builder.class, request.getClass()); + binding.setAccessible(true); + StringArrayEndpointParams.Builder builder = StringArrayEndpointParams.builder(); + binding.invoke(null, builder, request); + return builder.build().stringArrayParam(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private static List reflectiveObjects(ListOfObjectsOperationRequest request) { + return new Value(request).field("nested").field("listOfObjects").wildcard().field("key").stringValues(); + } + + private static List reflectiveUnions(ListOfUnionsOperationRequest request) { + Function string = v -> v.field("string"); + Function objectKey = v -> v.field("object").field("key"); + return new Value(request).field("listOfUnions").wildcard() + .multiSelectList(string, objectKey).flatten().stringValues(); + } + + private static List reflectiveMap(MapOperationRequest request) { + return new Value(request).field("map").keys().stringValues(); + } + + private static void assertObjectsEquivalent(ListOfObjectsOperationRequest request, List expected) { + List low = lowered(request); + assertEquals(reflectiveObjects(request), low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + private static void assertUnionsEquivalent(ListOfUnionsOperationRequest request, List expected) { + List low = lowered(request); + assertEquals(reflectiveUnions(request), low, "lowered binding must equal reflective evaluation"); + assertEquals(expected, low, "lowered binding must equal the hand-computed expectation"); + } + + private static ObjectMember object(String key) { + return ObjectMember.builder().key(key).build(); + } + + @Test + public void objectsNestedNull() { + assertObjectsEquivalent(ListOfObjectsOperationRequest.builder().build(), Collections.emptyList()); + } + + /** + * A null projection prefix yields {@code Collections.emptyList()} from {@code stringValues()}, so the lowered + * binding must not substitute a mutable list. + */ + @Test + public void objectsNestedNullYieldsSameMutabilityAsReflective() { + ListOfObjectsOperationRequest request = ListOfObjectsOperationRequest.builder().build(); + assertThrows(UnsupportedOperationException.class, () -> reflectiveObjects(request).add("x"), + "oracle assumption: reflective evaluation returns an immutable list for a null prefix"); + assertThrows(UnsupportedOperationException.class, () -> lowered(request).add("x"), + "lowered binding must match the reflective list's mutability for a null prefix"); + } + + @Test + public void objectsMultipleKeysOrdered() { + ListOfObjectsOperationRequest request = ListOfObjectsOperationRequest.builder() + .nested(n -> n.listOfObjects(object("k1"), object("k2"), object("k3"))) + .build(); + assertObjectsEquivalent(request, Arrays.asList("k1", "k2", "k3")); + } + + @Test + public void objectsNullKeyAndNullElementDropped() { + List objects = new ArrayList<>(); + objects.add(object("k1")); + objects.add(null); + objects.add(object(null)); + objects.add(object("k2")); + ListOfObjectsOperationRequest request = ListOfObjectsOperationRequest.builder() + .nested(n -> n.listOfObjects(objects)) + .build(); + assertObjectsEquivalent(request, Arrays.asList("k1", "k2")); + } + + @Test + public void unionsEmptyRequest() { + assertUnionsEquivalent(ListOfUnionsOperationRequest.builder().build(), Collections.emptyList()); + } + + @Test + public void unionsStringAndObjectBranchesOrdered() { + // Within one union the multiselect order is [string, object.key]. + ListOfUnionsOperationRequest request = ListOfUnionsOperationRequest.builder() + .listOfUnions(UnionMember.builder().string("s1").object(object("o1")).build(), + UnionMember.builder().object(object("o2")).build(), + UnionMember.builder().string("s3").build()) + .build(); + assertUnionsEquivalent(request, Arrays.asList("s1", "o1", "o2", "s3")); + } + + @Test + public void unionsEmptyMemberAndNullLeafDropped() { + List unions = new ArrayList<>(); + unions.add(UnionMember.builder().string("s1").build()); + unions.add(UnionMember.builder().build()); + unions.add(UnionMember.builder().object(object(null)).build()); + unions.add(null); + ListOfUnionsOperationRequest request = ListOfUnionsOperationRequest.builder() + .listOfUnions(unions) + .build(); + assertUnionsEquivalent(request, Collections.singletonList("s1")); + } + + @Test + public void mapEmptyRequest() { + MapOperationRequest request = MapOperationRequest.builder().build(); + List low = lowered(request); + assertEquals(reflectiveMap(request), low, "lowered binding must equal reflective evaluation"); + assertEquals(Collections.emptyList(), low); + } + + @Test + public void mapKeysMatchReflectiveContent() { + String[] keys = {"zebra", "mango", "apple", "delta", "foxtrot", "bravo", "yankee", "tango", "kilo", "echo"}; + Map map = new LinkedHashMap<>(); + for (String key : keys) { + map.put(key, "value"); + } + MapOperationRequest request = MapOperationRequest.builder().map(map).build(); + List reflective = reflectiveMap(request); + List low = lowered(request); + assertEquals(reflective.size(), low.size(), + "lowered result must contain the same number of keys as reflective evaluation"); + assertEquals(new HashSet<>(reflective), new HashSet<>(low), + "lowered key content must equal reflective evaluation"); + assertEquals(new HashSet<>(Arrays.asList(keys)), new HashSet<>(low), "content must match"); + } + + private static List reflectiveNestedMap(NestedMapOperationRequest request) { + return new Value(request).field("nestedMap").field("map").keys().stringValues(); + } + + private static void assertNestedMapEquivalent(NestedMapOperationRequest request, List expectedContent) { + List reflective = reflectiveNestedMap(request); + List low = lowered(request); + assertEquals(reflective.size(), low.size(), + "lowered result must contain the same number of keys as reflective evaluation"); + assertEquals(new HashSet<>(reflective), new HashSet<>(low), + "lowered key content must equal reflective evaluation"); + assertEquals(new HashSet<>(expectedContent), new HashSet<>(low), "content must match"); + } + + @Test + public void nestedMapNullPrefix() { + assertNestedMapEquivalent(NestedMapOperationRequest.builder().build(), Collections.emptyList()); + } + + /** + * {@code keys()} normalizes a null prefix to an empty list value, whose {@code stringValues()} is mutable, so the + * lowered binding must hand the endpoint params a mutable list here, unlike a null projection prefix. + */ + @Test + public void nestedMapNullPrefixYieldsSameMutabilityAsReflective() { + NestedMapOperationRequest request = NestedMapOperationRequest.builder().build(); + assertDoesNotThrow(() -> reflectiveNestedMap(request).add("x"), + "oracle assumption: reflective keys() returns a mutable list for a null prefix"); + assertDoesNotThrow(() -> lowered(request).add("x"), + "lowered binding must match the reflective list's mutability for a null prefix"); + } + + @Test + public void nestedMapKeys() { + NestedMapOperationRequest request = NestedMapOperationRequest.builder() + .nestedMap(n -> n.map(Collections.singletonMap("table", "value"))) + .build(); + assertNestedMapEquivalent(request, Collections.singletonList("table")); + } + + /** + * The equivalence assertions above are only meaningful if the generated methods are actually lowered: a codegen + * regression that sends these operations back to the reflective path would make every comparison + * oracle-against-itself. The resolver's class file must not reference the reflective runtime. + */ + @Test + public void operationContextParamBindingsDoNotUseReflectiveFallback() throws IOException { + byte[] classBytes = readClassBytes(StringArrayEndpointResolverUtils.class); + assertFalse(new String(classBytes, StandardCharsets.ISO_8859_1).contains("JmesPathRuntime"), + "generated resolver references JmesPathRuntime; bindings fell back to the reflective path"); + } + + private static byte[] readClassBytes(Class clazz) throws IOException { + try (InputStream in = clazz.getResourceAsStream(clazz.getSimpleName() + ".class"); + ByteArrayOutputStream out = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int read; + while ((read = in.read(buffer)) > 0) { + out.write(buffer, 0, read); + } + return out.toByteArray(); + } + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/CannedResponseSyntheticCallTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/CannedResponseSyntheticCallTest.java new file mode 100644 index 000000000000..7fe180b424c7 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/CannedResponseSyntheticCallTest.java @@ -0,0 +1,72 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +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.warmup.http.CannedResponseHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.model.AllTypesResponse; +import software.amazon.awssdk.services.protocolrestjson.model.ProtocolRestJsonException; + +/** + * Tests a generated client configured with a {@link CannedResponseHttpClient}. + */ +class CannedResponseSyntheticCallTest { + + private static final byte[] RESPONSE_PAYLOAD = "{\"StringMember\":\"warmup\"}".getBytes(StandardCharsets.UTF_8); + + private static ProtocolRestJsonClient clientWith(CannedResponseHttpClient httpClient) { + return ProtocolRestJsonClient.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .region(Region.US_EAST_1) + .endpointOverride(URI.create("http://localhost")) + .httpClient(httpClient) + .build(); + } + + @Test + void syntheticCall_throughCannedClient_completesAndUnmarshallsBody() { + ProtocolRestJsonClient client = clientWith(CannedResponseHttpClient.builder() + .responseBody(RESPONSE_PAYLOAD) + .build()); + + AllTypesResponse response = client.allTypes(r -> { + }); + + assertThat(response.stringMember()).isEqualTo("warmup"); + } + + @Test + void syntheticCall_whenCannedStatusIsError_throwsServiceExceptionWithThatStatus() { + ProtocolRestJsonClient client = clientWith(CannedResponseHttpClient.builder() + .statusCode(500) + .build()); + + assertThatThrownBy(() -> client.allTypes(r -> { + })) + .isInstanceOf(ProtocolRestJsonException.class) + .satisfies(e -> assertThat(((ProtocolRestJsonException) e).statusCode()).isEqualTo(500)); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/OperationRecordingInterceptor.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/OperationRecordingInterceptor.java new file mode 100644 index 000000000000..bc938f69a0d3 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/OperationRecordingInterceptor.java @@ -0,0 +1,46 @@ +/* + * 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.warmup; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +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; + +/** + * Records invoked operation names. Registered as a global interceptor via + * {@code software/amazon/awssdk/global/handlers/execution.interceptors} so tests can observe calls made by clients + * they cannot configure, such as the client a generated {@code SdkWarmUpProvider} builds internally. + */ +public class OperationRecordingInterceptor implements ExecutionInterceptor { + + private static final List OPERATION_NAMES = new CopyOnWriteArrayList<>(); + + public static List operationNames() { + return OPERATION_NAMES; + } + + public static void reset() { + OPERATION_NAMES.clear(); + } + + @Override + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + OPERATION_NAMES.add(executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME)); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/WarmUpProviderBindingTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/WarmUpProviderBindingTest.java new file mode 100644 index 000000000000..70c068138d35 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/warmup/WarmUpProviderBindingTest.java @@ -0,0 +1,74 @@ +/* + * 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.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.internal.warmup.ProtocolRestJsonWarmUpProvider; + +/** + * Verifies the generated {@code SdkWarmUpProvider} invokes the operation selected by + * {@code WarmUpOperationSelector}. {@link OperationRecordingInterceptor} is registered as a global interceptor to + * observe calls made by the clients the provider builds internally. + */ +class WarmUpProviderBindingTest { + + /** + * The operation WarmUpOperationSelector picks for the ProtocolRestJson test model. + */ + private static final String EXPECTED_OPERATION = "AllTypes"; + + private final ProtocolRestJsonWarmUpProvider provider = new ProtocolRestJsonWarmUpProvider(); + + @BeforeEach + void resetRecorder() { + OperationRecordingInterceptor.reset(); + } + + @Test + void warmUpClient_sync_invokesSelectedOperation() { + assertThatCode(() -> provider.warmUpClient(ClientType.SYNC)).doesNotThrowAnyException(); + + assertThat(OperationRecordingInterceptor.operationNames()).containsExactly(EXPECTED_OPERATION); + } + + @Test + void warmUpClient_async_invokesSelectedOperation() { + assertThatCode(() -> provider.warmUpClient(ClientType.ASYNC)).doesNotThrowAnyException(); + + assertThat(OperationRecordingInterceptor.operationNames()).containsExactly(EXPECTED_OPERATION); + } + + @Test + void warmUp_invokesSelectedOperationOnBothClients() { + assertThatCode(provider::warmUp).doesNotThrowAnyException(); + + assertThat(OperationRecordingInterceptor.operationNames()) + .containsExactly(EXPECTED_OPERATION, EXPECTED_OPERATION); + } + + @Test + void clientClassNames_matchGeneratedClients() { + assertThat(provider.syncClientClassName()).isEqualTo(ProtocolRestJsonClient.class.getName()); + assertThat(provider.asyncClientClassName()).isEqualTo(ProtocolRestJsonAsyncClient.class.getName()); + } +} diff --git a/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000000..abf65ecbc89b --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.awssdk.warmup.OperationRecordingInterceptor diff --git a/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/services/endpointproviders/no-aws-partitions.json b/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/services/endpointproviders/no-aws-partitions.json new file mode 100644 index 000000000000..20f0a977d26c --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/resources/software/amazon/awssdk/services/endpointproviders/no-aws-partitions.json @@ -0,0 +1,19 @@ +{ + "partitions" : [ + { + "id": "aws-cn", + "outputs": { + "dnsSuffix": "amazonaws.com.cn", + "dualStackDnsSuffix": "api.amazonwebservices.com.cn", + "implicitGlobalRegion": "cn-northwest-1", + "name": "aws-cn", + "supportsDualStack": true, + "supportsFIPS": true + }, + "regionRegex": "^cn\\-\\w+\\-\\d+$", + "regions": { + "cn-north-1": {} + } + } + ] +} diff --git a/test/crt-unavailable-tests/pom.xml b/test/crt-unavailable-tests/pom.xml index 068236de8d18..220bcf9f324d 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/http-client-benchmarks/pom.xml b/test/http-client-benchmarks/pom.xml index 0abec411b936..f58aaccc0040 100644 --- a/test/http-client-benchmarks/pom.xml +++ b/test/http-client-benchmarks/pom.xml @@ -19,7 +19,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml diff --git a/test/http-client-tests/pom.xml b/test/http-client-tests/pom.xml index e88b31b283cc..b232e6a963ba 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml http-client-tests @@ -48,6 +48,11 @@ http-client-spi ${awsjavasdk.version} + + software.amazon.awssdk + sdk-core + ${awsjavasdk.version} + software.amazon.awssdk metrics-spi diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/core/http/NoopTestRequest.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/http/NoopTestRequest.java new file mode 100644 index 000000000000..3f2251a2626f --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/http/NoopTestRequest.java @@ -0,0 +1,81 @@ +/* + * 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.http; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.SdkRequestOverrideConfiguration; + +public class NoopTestRequest extends SdkRequest { + + private final SdkRequestOverrideConfiguration requestOverrideConfig; + + private NoopTestRequest(Builder builder) { + this.requestOverrideConfig = builder.overrideConfiguration(); + + } + + @Override + public Optional overrideConfiguration() { + return Optional.ofNullable(requestOverrideConfig); + } + + @Override + public Builder toBuilder() { + return new BuilderImpl(); + } + + public static Builder builder() { + return new BuilderImpl(); + } + + @Override + public List> sdkFields() { + return Collections.emptyList(); + } + + public interface Builder extends SdkRequest.Builder { + @Override + NoopTestRequest build(); + + @Override + SdkRequestOverrideConfiguration overrideConfiguration(); + + Builder overrideConfiguration(SdkRequestOverrideConfiguration requestOverrideConfig); + } + + private static class BuilderImpl implements Builder { + private SdkRequestOverrideConfiguration requestOverrideConfig; + + @Override + public SdkRequestOverrideConfiguration overrideConfiguration() { + return requestOverrideConfig; + } + + public Builder overrideConfiguration(SdkRequestOverrideConfiguration requestOverrideConfig) { + this.requestOverrideConfig = requestOverrideConfig; + return this; + } + + @Override + public NoopTestRequest build() { + return new NoopTestRequest(this); + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/EmptySdkResponseHandler.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/EmptySdkResponseHandler.java new file mode 100644 index 000000000000..9c1c0bdf12db --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/EmptySdkResponseHandler.java @@ -0,0 +1,37 @@ +/* + * 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.response; + +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.protocol.VoidSdkResponse; +import software.amazon.awssdk.http.SdkHttpFullResponse; + +public class EmptySdkResponseHandler implements HttpResponseHandler { + + @Override + public SdkResponse handle(SdkHttpFullResponse response, + ExecutionAttributes executionAttributes) + throws Exception { + return VoidSdkResponse.builder().build(); + } + + @Override + public boolean needsConnectionLeftOpen() { + return true; + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/NullErrorResponseHandler.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/NullErrorResponseHandler.java new file mode 100644 index 000000000000..97916c106ed1 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/http/response/NullErrorResponseHandler.java @@ -0,0 +1,38 @@ +/* + * 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.response; + +import software.amazon.awssdk.core.exception.SdkServiceException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.http.SdkHttpFullResponse; + +public class NullErrorResponseHandler implements HttpResponseHandler { + + @Override + public SdkServiceException handle(SdkHttpFullResponse response, + ExecutionAttributes executionAttributes) throws Exception { + return SdkServiceException.builder() + .statusCode(response.statusCode()) + .build(); + } + + @Override + public boolean needsConnectionLeftOpen() { + return false; + } + +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/AsyncResponseHandlerTestUtils.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/AsyncResponseHandlerTestUtils.java new file mode 100644 index 000000000000..8761bbfb6403 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/AsyncResponseHandlerTestUtils.java @@ -0,0 +1,142 @@ +/* + * 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 java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import org.reactivestreams.Publisher; +import software.amazon.awssdk.core.Response; +import software.amazon.awssdk.core.async.DrainingSubscriber; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler; +import software.amazon.awssdk.core.internal.http.async.CombinedResponseAsyncHttpResponseHandler; +import software.amazon.awssdk.http.SdkHttpResponse; + +public class AsyncResponseHandlerTestUtils { + private AsyncResponseHandlerTestUtils() { + } + + public static TransformingAsyncResponseHandler noOpResponseHandler() { + return noOpResponseHandler(null); + } + + public static TransformingAsyncResponseHandler noOpResponseHandler(T result) { + return new NoOpResponseHandler<>(result); + } + + public static TransformingAsyncResponseHandler superSlowResponseHandler(long sleepInMillis) { + return superSlowResponseHandler(null, sleepInMillis); + } + + public static TransformingAsyncResponseHandler superSlowResponseHandler(T result, long sleepInMillis) { + return new SuperSlowResponseHandler<>(result, sleepInMillis); + } + + + public static TransformingAsyncResponseHandler> combinedAsyncResponseHandler( + TransformingAsyncResponseHandler successResponseHandler, + TransformingAsyncResponseHandler failureResponseHandler) { + + return new CombinedResponseAsyncHttpResponseHandler<>( + successResponseHandler == null ? noOpResponseHandler() : successResponseHandler, + failureResponseHandler == null ? noOpResponseHandler() : failureResponseHandler); + } + + private static class NoOpResponseHandler implements TransformingAsyncResponseHandler { + private final CompletableFuture cf = new CompletableFuture<>(); + private final T result; + + NoOpResponseHandler(T result) { + this.result = result; + } + + @Override + public CompletableFuture prepare() { + return cf; + } + + @Override + public void onHeaders(SdkHttpResponse headers) { + } + + @Override + public void onStream(Publisher stream) { + stream.subscribe(new DrainingSubscriber() { + @Override + public void onError(Throwable t) { + cf.completeExceptionally(t); + } + + @Override + public void onComplete() { + cf.complete(result); + } + }); + } + + @Override + public void onError(Throwable error) { + cf.completeExceptionally(error); + } + } + + private static class SuperSlowResponseHandler implements TransformingAsyncResponseHandler { + private final CompletableFuture cf = new CompletableFuture<>(); + private final T result; + private final long sleepMillis; + + SuperSlowResponseHandler(T result, long sleepMillis) { + this.result = result; + this.sleepMillis = sleepMillis; + } + + @Override + public CompletableFuture prepare() { + return cf.thenApply(r -> { + try { + Thread.sleep(sleepMillis); + } catch (InterruptedException ignored) { + // Ignored. + } + return r; + }); + } + + @Override + public void onHeaders(SdkHttpResponse headers) { + } + + @Override + public void onStream(Publisher stream) { + stream.subscribe(new DrainingSubscriber() { + @Override + public void onError(Throwable t) { + cf.completeExceptionally(t); + } + + @Override + public void onComplete() { + cf.complete(result); + } + }); + } + + @Override + public void onError(Throwable error) { + cf.completeExceptionally(error); + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/ResponseHandlerTestUtils.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/ResponseHandlerTestUtils.java new file mode 100644 index 000000000000..d3e2731cba1e --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/core/internal/util/ResponseHandlerTestUtils.java @@ -0,0 +1,47 @@ +/* + * 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 software.amazon.awssdk.core.Response; +import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.exception.SdkServiceException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.internal.http.CombinedResponseHandler; + +public final class ResponseHandlerTestUtils { + private ResponseHandlerTestUtils() { + } + + public static HttpResponseHandler noOpSyncResponseHandler() { + return (response, executionAttributes) -> null; + } + + public static HttpResponseHandler superSlowResponseHandler(long sleepInMills) { + return (response, executionAttributes) -> { + Thread.sleep(sleepInMills); + return null; + }; + } + + public static HttpResponseHandler> combinedSyncResponseHandler( + HttpResponseHandler successResponseHandler, + HttpResponseHandler failureResponseHandler) { + + return new CombinedResponseHandler<>( + successResponseHandler == null ? noOpSyncResponseHandler() : successResponseHandler, + failureResponseHandler == null ? noOpSyncResponseHandler() : failureResponseHandler); + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite.java new file mode 100644 index 000000000000..c3e3c5287272 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite.java @@ -0,0 +1,81 @@ +/* + * 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.http; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.core.internal.util.AsyncResponseHandlerTestUtils.noOpResponseHandler; +import static utils.HttpTestUtils.executionContext; +import static utils.HttpTestUtils.testAsyncClientBuilder; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.io.ByteArrayInputStream; +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import org.junit.Rule; +import org.junit.Test; +import software.amazon.awssdk.core.exception.ApiCallAttemptTimeoutException; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import utils.ValidSdkObjects; + +/** + * Reusable suite that verifies sdk-core's async API-call-attempt timeout aborts a slow real response, exercised over a real + * {@link SdkAsyncHttpClient}. Each concrete async HTTP client module subclasses this and provides its client via + * {@link #createSdkAsyncHttpClient()}. + */ +public abstract class SdkAsyncHttpClientApiCallAttemptTimeoutTestSuite { + + private static final Duration API_CALL_TIMEOUT = Duration.ofSeconds(1); + + @Rule + public WireMockRule wireMock = new WireMockRule(0); + + private AmazonAsyncHttpClient httpClient; + + protected abstract SdkAsyncHttpClient createSdkAsyncHttpClient(); + + @Test + public void slowApiAttempt_ThrowsApiCallAttemptTimeoutException() { + httpClient = testAsyncClientBuilder() + .asyncHttpClient(createSdkAsyncHttpClient()) + .apiCallTimeout(API_CALL_TIMEOUT) + .apiCallAttemptTimeout(Duration.ofMillis(1)) + .build(); + + stubFor(get(anyUrl()) + .willReturn(aResponse().withStatus(200).withBody("{}").withFixedDelay(1_000))); + CompletableFuture future = requestBuilder().execute(noOpResponseHandler()); + assertThatThrownBy(future::join).hasCauseInstanceOf(ApiCallAttemptTimeoutException.class); + } + + private AmazonAsyncHttpClient.RequestExecutionBuilder requestBuilder() { + return httpClient.requestExecutionBuilder() + .request(generateRequest()) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(null)); + } + + private SdkHttpFullRequest generateRequest() { + return ValidSdkObjects.sdkHttpFullRequest(wireMock.port()) + .host("localhost") + .contentStreamProvider(() -> new ByteArrayInputStream("test".getBytes())).build(); + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientSslHandshakeBehaviorTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientSslHandshakeBehaviorTestSuite.java new file mode 100644 index 000000000000..923ed5152069 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkAsyncHttpClientSslHandshakeBehaviorTestSuite.java @@ -0,0 +1,78 @@ +/* + * 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.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +import com.github.tomakehurst.wiremock.WireMockServer; +import java.util.concurrent.CompletionException; +import javax.net.ssl.SSLHandshakeException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; + +/** + * Validates that a TLS handshake failure against an untrusted (self-signed) certificate surfaces as + * {@link SSLHandshakeException} with a cause chain, so callers can differentiate transient + * interruptions from persistent certificate failures. + */ +public abstract class SdkAsyncHttpClientSslHandshakeBehaviorTestSuite { + private WireMockServer selfSignedServer; + + protected abstract SdkAsyncHttpClient createSdkAsyncHttpClient(); + + @BeforeEach + public void setup() { + selfSignedServer = HttpTestUtils.createSelfSignedServer(); + selfSignedServer.start(); + } + + @AfterEach + public void teardown() { + if (selfSignedServer != null) { + selfSignedServer.stop(); + selfSignedServer = null; + } + } + + @Test + public void sslHandshakeFailure_surfacesAsSslHandshakeException() { + Throwable thrown = executeRequestAgainstUntrustedServer(); + + assertThat(thrown).isInstanceOf(SSLHandshakeException.class); + } + + @Test + public void sslHandshakeFailure_exceptionCarriesDiagnosableCause() { + Throwable thrown = executeRequestAgainstUntrustedServer(); + + assertThat(thrown).isInstanceOf(SSLHandshakeException.class); + assertThat(thrown.getCause()) + .withFailMessage("SSLHandshakeException must chain the underlying failure as its cause " + + "so callers can differentiate transient from persistent TLS failures. Was: %s", thrown) + .isNotNull(); + } + + private Throwable executeRequestAgainstUntrustedServer() { + try (SdkAsyncHttpClient client = createSdkAsyncHttpClient()) { + Throwable thrown = catchThrowable( + () -> HttpTestUtils.sendGetRequest(selfSignedServer.httpsPort(), client, true).join()); + return thrown instanceof CompletionException ? thrown.getCause() : thrown; + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientConnectionPoolTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientConnectionPoolTestSuite.java new file mode 100644 index 000000000000..ad424615ef96 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientConnectionPoolTestSuite.java @@ -0,0 +1,108 @@ +/* + * 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.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; +import static utils.HttpTestUtils.executionContext; + +import java.time.Duration; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; +import software.amazon.awssdk.core.internal.http.response.EmptySdkResponseHandler; +import software.amazon.awssdk.http.server.MockServer; +import software.amazon.awssdk.retries.DefaultRetryStrategy; +import utils.HttpTestUtils; + +/** + * Verifies that a client whose connection pool is limited to a single connection fails to lease a second connection while the + * first one is still in use. + * + *

    This suite applies to sync clients that expose a bounded connection pool through a {@code maxConnections} setting, which + * today means {@code apache-client} and {@code apache5-client}. {@code url-connection-client} and {@code aws-crt-client} do not + * expose that setting, so they do not subclass this suite.

    + * + *

    The exception raised on pool exhaustion is specific to the underlying HTTP library, so subclasses declare it through + * {@link #expectedPoolTimeoutCause()}.

    + */ +public abstract class SdkHttpClientConnectionPoolTestSuite { + + private static MockServer server; + + /** + * Returns a client whose connection pool holds at most {@code maxConnections} connections, and which waits no longer than + * {@code connectionTimeout} for a connection. + */ + protected abstract SdkHttpClient createSdkHttpClient(int maxConnections, Duration connectionTimeout); + + /** + * Returns the exception the underlying HTTP library raises when the pool cannot supply a connection in time. + */ + protected abstract Class expectedPoolTimeoutCause(); + + @BeforeAll + public static void setup() { + server = MockServer.createMockServer(MockServer.ServerBehavior.OVERLOADED); + server.startServer(); + } + + @AfterAll + public static void tearDown() { + if (server != null) { + server.stopServer(); + } + } + + @Test + @Timeout(60) + public void leasing_a_new_connection_fails_with_connection_pool_timeout() { + + AmazonSyncHttpClient httpClient = HttpTestUtils.testClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .httpClient(createSdkHttpClient(1, Duration.ofMillis(100))) + .build(); + + SdkHttpFullRequest request = server.configureHttpEndpoint(SdkHttpFullRequest.builder()) + .method(SdkHttpMethod.GET) + .build(); + + // Block the first connection in the pool with this request. + httpClient.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(new EmptySdkResponseHandler(), null)); + + try { + // A new connection will be leased here which would fail in + // ConnectionPoolTimeoutException. + httpClient.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(null, null)); + Assertions.fail("Connection pool timeout exception is expected!"); + } catch (SdkClientException e) { + assertThat(e.getCause()).isInstanceOf(expectedPoolTimeoutCause()); + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSdkPipelineBehaviorTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSdkPipelineBehaviorTestSuite.java new file mode 100644 index 000000000000..06ef704a0acf --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSdkPipelineBehaviorTestSuite.java @@ -0,0 +1,230 @@ +/* + * 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.http; + +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.findAll; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.matching; +import static com.github.tomakehurst.wiremock.client.WireMock.optionsRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; +import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; +import static utils.HttpTestUtils.executionContext; +import static utils.HttpTestUtils.testClientBuilder; + +import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import org.junit.Test; +import software.amazon.awssdk.core.exception.SdkServiceException; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; +import software.amazon.awssdk.core.internal.http.pipeline.stages.ApplyTransactionIdStage; +import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; +import software.amazon.awssdk.core.io.SdkFilterInputStream; +import utils.http.WireMockTestBase; + +/** + * Reusable suite that exercises sdk-core's {@link AmazonSyncHttpClient} execution pipeline (client-configuration header + * injection, request-header precedence, OPTIONS pass-through, transaction-id consistency across retries, and closing of + * every {@link ContentStreamProvider}-created stream) over a real {@link SdkHttpClient}. Each concrete HTTP client module + * subclasses this and provides its client via {@link #createSdkHttpClient()}. + */ +public abstract class SdkHttpClientSdkPipelineBehaviorTestSuite extends WireMockTestBase { + + private static final String OPERATION = "/some-operation"; + private static final String HEADER = "Some-Header"; + private static final String CONFIG_HEADER_VALUE = "client config header value"; + private static final String REQUEST_HEADER_VALUE = "request header value"; + private static final String RESOURCE_PATH = "/transaction-id/"; + + protected abstract SdkHttpClient createSdkHttpClient(); + + @Test + public void headersSpecifiedInClientConfigurationArePutOnRequest() { + stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse())); + SdkHttpFullRequest request = newGetRequest(OPERATION).build(); + + AmazonSyncHttpClient sut = createClient(HEADER, CONFIG_HEADER_VALUE); + sendRequest(request, sut); + + verify(getRequestedFor(urlPathEqualTo(OPERATION)).withHeader(HEADER, matching(CONFIG_HEADER_VALUE))); + } + + @Test + public void headersOnRequestsWinOverClientConfigurationHeaders() { + stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse())); + SdkHttpFullRequest request = newGetRequest(OPERATION) + .putHeader(HEADER, REQUEST_HEADER_VALUE) + .build(); + + AmazonSyncHttpClient sut = createClient(HEADER, CONFIG_HEADER_VALUE); + sendRequest(request, sut); + + verify(getRequestedFor(urlPathEqualTo(OPERATION)).withHeader(HEADER, matching(REQUEST_HEADER_VALUE))); + } + + @Test + public void canHandleOptionsRequest() { + stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse())); + SdkHttpFullRequest request = newRequest(OPERATION) + .method(SdkHttpMethod.OPTIONS) + .build(); + + AmazonSyncHttpClient sut = amazonSyncHttpClient(); + sendRequest(request, sut); + + verify(optionsRequestedFor(urlPathEqualTo(OPERATION))); + } + + @Test + public void retriedRequest_HasSameTransactionIdForAllRetries() throws Exception { + stubFor(get(urlEqualTo(RESOURCE_PATH)).willReturn(aResponse().withStatus(500))); + executeRequest(); + assertTransactionIdIsUnchangedAcrossRetries(); + } + + @Test + public void closesAllCreatedInputStreamsFromProvider() { + stubFor(any(urlPathEqualTo(OPERATION)).willReturn(aResponse().withStatus(500))); + + TestContentStreamProvider provider = new TestContentStreamProvider(); + SdkHttpFullRequest request = newRequest(OPERATION) + .contentStreamProvider(provider) + .method(SdkHttpMethod.PUT) + .build(); + + AmazonSyncHttpClient testClient = amazonSyncHttpClient(); + try { + sendRequest(request, testClient); + fail("Should have thrown SdkServiceException"); + } catch (SdkServiceException ignored) { + // Ignored or expected. + } + + // The test client uses the default retry policy so there should be 4 + // total attempts and an equal number created streams + assertThat(provider.getCreatedStreams().size()).isEqualTo(4); + for (CloseTrackingInputStream is : provider.getCreatedStreams()) { + assertThat(is.isClosed()).isTrue(); + } + } + + private void executeRequest() throws Exception { + AmazonSyncHttpClient httpClient = amazonSyncHttpClient(); + try { + SdkHttpFullRequest request = newGetRequest(RESOURCE_PATH).build(); + httpClient.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(null, stubErrorHandler())); + fail("Expected exception"); + } catch (SdkServiceException expected) { + // Ignored or expected. + } + } + + private void assertTransactionIdIsUnchangedAcrossRetries() { + String previousTransactionId = null; + for (LoggedRequest request : findAll(getRequestedFor(urlEqualTo(RESOURCE_PATH)))) { + String currentTransactionId = request.getHeader(ApplyTransactionIdStage.HEADER_SDK_TRANSACTION_ID); + // Transaction ID should always be set + assertNotNull(currentTransactionId); + // Transaction ID should be the same across retries + if (previousTransactionId != null) { + assertEquals(previousTransactionId, currentTransactionId); + } + previousTransactionId = currentTransactionId; + } + } + + private void sendRequest(SdkHttpFullRequest request, AmazonSyncHttpClient sut) { + sut.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); + } + + private AmazonSyncHttpClient createClient(String headerName, String headerValue) { + return testClientBuilder().httpClient(createSdkHttpClient()).additionalHeader(headerName, headerValue).build(); + } + + private AmazonSyncHttpClient amazonSyncHttpClient() { + return testClientBuilder().httpClient(createSdkHttpClient()).build(); + } + + private static class TestContentStreamProvider implements ContentStreamProvider { + private static final byte[] CONTENT_BYTES = "Hello".getBytes(StandardCharsets.UTF_8); + private List createdStreams = new ArrayList<>(); + + @Override + public InputStream newStream() { + closeCurrentStream(); + CloseTrackingInputStream s = newContentStream(); + createdStreams.add(s); + return s; + } + + List getCreatedStreams() { + return createdStreams; + } + + private CloseTrackingInputStream newContentStream() { + return new CloseTrackingInputStream(new ByteArrayInputStream(CONTENT_BYTES)); + } + + private void closeCurrentStream() { + if (createdStreams.isEmpty()) { + return; + } + invokeSafely(() -> createdStreams.get(createdStreams.size() - 1).close()); + } + } + + private static class CloseTrackingInputStream extends SdkFilterInputStream { + private boolean isClosed = false; + + CloseTrackingInputStream(InputStream in) { + super(in); + } + + @Override + public void close() throws IOException { + super.close(); + isClosed = true; + } + + boolean isClosed() { + return isClosed; + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeBehaviorTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeBehaviorTestSuite.java new file mode 100644 index 000000000000..23ab7d1c33c7 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeBehaviorTestSuite.java @@ -0,0 +1,98 @@ +/* + * 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.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.catchThrowable; + +import com.github.tomakehurst.wiremock.WireMockServer; +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import javax.net.ssl.SSLHandshakeException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** + * Validates that a TLS handshake failure against an untrusted (self-signed) certificate surfaces as + * {@link SSLHandshakeException} with a cause chain, so callers can differentiate transient + * interruptions from persistent certificate failures. + */ +public abstract class SdkHttpClientSslHandshakeBehaviorTestSuite { + private WireMockServer selfSignedServer; + + /** + * Implemented by a child class to create an HTTP client to validate + */ + protected abstract SdkHttpClient createSdkHttpClient(); + + @BeforeEach + public void setup() { + selfSignedServer = HttpTestUtils.createSelfSignedServer(); + selfSignedServer.start(); + } + + @AfterEach + public void teardown() { + if (selfSignedServer != null) { + selfSignedServer.stop(); + selfSignedServer = null; + } + } + + @Test + public void sslHandshakeFailure_surfacesAsSslHandshakeException() { + Throwable thrown = executeRequestAgainstUntrustedServer(); + + assertThat(thrown).isInstanceOf(SSLHandshakeException.class); + } + + @Test + public void sslHandshakeFailure_exceptionCarriesDiagnosableCause() { + Throwable thrown = executeRequestAgainstUntrustedServer(); + + assertThat(thrown).isInstanceOf(SSLHandshakeException.class); + assertThat(thrown.getCause()) + .withFailMessage("SSLHandshakeException must chain the underlying failure as its cause " + + "so callers can differentiate transient from persistent TLS failures. Was: %s", thrown) + .isNotNull(); + } + + private Throwable executeRequestAgainstUntrustedServer() { + try (SdkHttpClient client = createSdkHttpClient()) { + SdkHttpFullRequest request = httpsRequest(selfSignedServer.httpsPort()); + return catchThrowable(client.prepareRequest(HttpExecuteRequest.builder() + .request(request) + .contentStreamProvider( + request.contentStreamProvider().orElse(null)) + .build()) + ::call); + } + } + + private static SdkHttpFullRequest httpsRequest(int httpsPort) { + URI uri = URI.create("https://localhost:" + httpsPort); + byte[] content = "Body".getBytes(StandardCharsets.UTF_8); + return SdkHttpFullRequest.builder() + .uri(uri) + .method(SdkHttpMethod.POST) + .putHeader("Host", uri.getHost()) + .putHeader("Content-Length", Integer.toString(content.length)) + .contentStreamProvider(() -> new ByteArrayInputStream(content)) + .build(); + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeTimeoutTestSuite.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeTimeoutTestSuite.java new file mode 100644 index 000000000000..fa64b4728b06 --- /dev/null +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/SdkHttpClientSslHandshakeTimeoutTestSuite.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.http; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.fail; +import static software.amazon.awssdk.core.internal.util.ResponseHandlerTestUtils.combinedSyncResponseHandler; +import static utils.HttpTestUtils.executionContext; + +import java.io.IOException; +import java.time.Duration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; +import software.amazon.awssdk.core.exception.SdkClientException; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; +import software.amazon.awssdk.core.internal.http.response.NullErrorResponseHandler; +import software.amazon.awssdk.http.server.MockServer; +import software.amazon.awssdk.retries.DefaultRetryStrategy; +import utils.HttpTestUtils; + +/** + * Verifies that a client honors its configured socket timeout during the SSL handshake. The client is pointed at a server that + * accepts the connection and then sends nothing, so a client that ignores the socket timeout hangs until the test times out. + * + *

    This suite applies to sync clients that expose a socket timeout, which today means {@code apache-client}, + * {@code apache5-client} and {@code url-connection-client}. It started as a regression test for a bug in Apache HttpClient + * 4.3, where the socket timeout was ignored during the SSL handshake.

    + * + * @link https://issues.apache.org/jira/browse/HTTPCLIENT-1478 + */ +public abstract class SdkHttpClientSslHandshakeTimeoutTestSuite { + + private static final Duration CLIENT_SOCKET_TO = Duration.ofSeconds(1); + + private MockServer server; + + /** + * Returns a client that waits no longer than {@code socketTimeout} for data from the server. + */ + protected abstract SdkHttpClient createSdkHttpClient(Duration socketTimeout); + + @BeforeEach + public void setupBaseFixture() { + server = MockServer.createMockServer(MockServer.ServerBehavior.UNRESPONSIVE); + server.startServer(); + } + + @AfterEach + public void tearDownBaseFixture() { + server.stopServer(); + } + + @Test + @Timeout(60) + public void testSslHandshakeTimeout() { + AmazonSyncHttpClient httpClient = HttpTestUtils.testClientBuilder() + .retryStrategy(DefaultRetryStrategy.doNotRetry()) + .httpClient(createSdkHttpClient(CLIENT_SOCKET_TO)) + .build(); + + try { + SdkHttpFullRequest request = server.configureHttpsEndpoint(SdkHttpFullRequest.builder()) + .method(SdkHttpMethod.GET) + .build(); + httpClient.requestExecutionBuilder() + .request(request) + .originalRequest(NoopTestRequest.builder().build()) + .executionContext(executionContext(request)) + .execute(combinedSyncResponseHandler(null, new NullErrorResponseHandler())); + fail("Client-side socket read timeout is expected!"); + + } catch (SdkClientException e) { + e.printStackTrace(); + /** + * Http client catches the SocketTimeoutException and throws a + * ConnectTimeoutException. + * {@link DefaultHttpClientConnectionOperator#connect(ManagedHttpClientConnection, HttpHost, + * InetSocketAddress, int, SocketConfig, HttpContext)} + */ + assertThat(e).hasCauseInstanceOf(IOException.class); + } + } +} diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/proxy/ProxyConfigCommonTestData.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/proxy/ProxyConfigCommonTestData.java index 4dc1d58be2c7..0c86b9676ccd 100644 --- a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/proxy/ProxyConfigCommonTestData.java +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/proxy/ProxyConfigCommonTestData.java @@ -36,6 +36,7 @@ public final class ProxyConfigCommonTestData { public static final String ENVIRONMENT_HOST = "environmentVariable.com".toLowerCase(Locale.US); public static final String ENVIRONMENT_VARIABLE_PORT_NUMBER = "3333"; public static final String ENVIRONMENT_VARIABLE_NON_PROXY = "environmentVariableNonProxy".toLowerCase(Locale.US); + public static final String ENVIRONMENT_VARIABLE_NON_PROXY_SECOND = "secondNonProxy.com".toLowerCase(Locale.US); public static final String USER_HOST_ON_BUILDER = "proxyBuilder.com"; public static final int USER_PORT_NUMBER_ON_BUILDER = 9999; public static final String USER_USERNAME_ON_BUILDER = "proxyBuilderUser"; @@ -245,7 +246,16 @@ null, null, getSystemPropertyProxySettings().host(USER_HOST_ON_BUILDER).port(USE + "resolved", getSystemPropertiesWithNoUserName(), environmentSettingsWithNoPassword(), - new TestProxySetting(), false, true, getEnvironmentVariableProxySettings().password(null)) + new TestProxySetting(), false, true, getEnvironmentVariableProxySettings().password(null)), + + Arguments.of( + "Provided no system property and a comma-space separated no_proxy environment variable when " + + "useEnvironmentVariable is set then each non-proxy host is resolved with surrounding whitespace trimmed", + Collections.singletonList(Pair.of("", "")), + environmentSettingsWithCommaSpaceNonProxy(), + new TestProxySetting(), false, true, + getEnvironmentVariableProxySettings().nonProxyHost(ENVIRONMENT_VARIABLE_NON_PROXY, + ENVIRONMENT_VARIABLE_NON_PROXY_SECOND)) ); } @@ -300,6 +310,15 @@ private static List> environmentSettingsWithNoPassword() { ); } + private static List> environmentSettingsWithCommaSpaceNonProxy() { + return Arrays.asList( + Pair.of("%s_proxy", + "http://" + ENV_VARIABLE_USER + ":" + ENV_VARIABLE_PASSWORD + "@" + ENVIRONMENT_HOST + + ":" + ENVIRONMENT_VARIABLE_PORT_NUMBER + "/"), + Pair.of("no_proxy", ENVIRONMENT_VARIABLE_NON_PROXY + ", " + ENVIRONMENT_VARIABLE_NON_PROXY_SECOND) + ); + } + private static List> systemPropertySettings() { return Arrays.asList( Pair.of("%s.proxyHost", SYSTEM_PROPERTY_HOST), diff --git a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/server/MockServer.java b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/server/MockServer.java index 71e6c0c3909a..f1e1986c232f 100644 --- a/test/http-client-tests/src/main/java/software/amazon/awssdk/http/server/MockServer.java +++ b/test/http-client-tests/src/main/java/software/amazon/awssdk/http/server/MockServer.java @@ -58,6 +58,10 @@ public static MockServer createMockServer(ServerBehavior serverBehavior) { return new MockServer(new FullCloseInBetweenServerBehavior()); case FULL_CLOSE_AT_THE_END: return new MockServer(new FullCloseAtTheEndServerBehavior()); + case UNRESPONSIVE: + return new MockServer(new UnresponsiveServerBehavior()); + case OVERLOADED: + return new MockServer(new OverloadedServerBehavior()); default: throw new IllegalArgumentException("Unsupported implementation for server issue: " + serverBehavior); } @@ -94,6 +98,18 @@ public void startServer(TlsKeyManagersProvider keyManagersProvider) { listenerThread.start(); } + public void startServer() { + try { + serverSocket = new ServerSocket(0); // auto-assign a port at localhost + logger.info(() -> "Listening on port " + serverSocket.getLocalPort()); + } catch (IOException e) { + throw new RuntimeException("Unable to start the server socket.", e); + } + listenerThread = new MockServerListenerThread(serverSocket, serverBehaviorStrategy); + listenerThread.setDaemon(true); + listenerThread.start(); + } + public void stopServer() { listenerThread.interrupt(); try { @@ -127,7 +143,9 @@ public SdkHttpFullRequest.Builder configureHttpEndpoint(SdkHttpFullRequest.Build public enum ServerBehavior { HALF_CLOSE, FULL_CLOSE_IN_BETWEEN, - FULL_CLOSE_AT_THE_END + FULL_CLOSE_AT_THE_END, + UNRESPONSIVE, + OVERLOADED } public interface ServerBehaviorStrategy { @@ -293,6 +311,73 @@ public void runServer(ServerSocket serverSocket) { } } + /** + * A server behavior which accepts a single connection and then holds it open without writing any bytes. The test client + * talking to this server is expected to timeout appropriately, instead of hanging and waiting for the response forever. + */ + public static class UnresponsiveServerBehavior implements ServerBehaviorStrategy { + + @Override + public void runServer(ServerSocket serverSocket) { + Socket socket = null; + try { + socket = serverSocket.accept(); + Socket acceptedSocket = socket; + logger.info(() -> "Socket created on port " + acceptedSocket.getLocalPort()); + while (true) { + logger.debug(() -> "Holding the connection open without responding."); + Thread.sleep(10 * 1000); + } + } catch (InterruptedException e) { + // Stop server will interrupt to stop this thread. + return; + } catch (IOException e) { + throw new RuntimeException("Error when waiting for new socket connection.", e); + } finally { + closeQuietly(socket); + } + } + } + + /** + * A server behavior which accepts a connection, writes a partial HTTP response (with a Content-Length larger than the bytes + * actually sent) and then keeps holding the connection open while periodically writing a few more bytes. The test client + * talking to this server is expected to timeout appropriately, instead of hanging and waiting for the response forever. + */ + public static class OverloadedServerBehavior implements ServerBehaviorStrategy { + + @Override + public void runServer(ServerSocket serverSocket) { + try { + while (true) { + Socket socket = null; + try { + socket = serverSocket.accept(); + try (DataOutputStream out = new DataOutputStream(socket.getOutputStream())) { + out.writeBytes("HTTP/1.1 200 OK\r\n"); + out.writeBytes("Content-Type: text/html\r\n"); + out.writeBytes("Content-Length: 500\r\n\r\n"); + out.writeBytes("

    Hello."); + while (true) { + Thread.sleep(1000); + out.writeBytes("Hi."); + } + } + } catch (SocketException se) { + // Ignored or expected. + } finally { + closeQuietly(socket); + } + } + } catch (IOException e) { + throw new RuntimeException("Error when waiting for new socket connection.", e); + } catch (InterruptedException e) { + // Stop server will interrupt to stop this thread. + return; + } + } + } + // TLS1.3 enbaled by default for 8u341 onwards. // https://www.oracle.com/java/technologies/javase/8u341-relnotes.html diff --git a/test/http-client-tests/src/main/java/utils/HttpTestUtils.java b/test/http-client-tests/src/main/java/utils/HttpTestUtils.java new file mode 100644 index 000000000000..928146962343 --- /dev/null +++ b/test/http-client-tests/src/main/java/utils/HttpTestUtils.java @@ -0,0 +1,221 @@ +/* + * 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 utils; + +import java.net.URI; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import software.amazon.awssdk.core.ClientEndpointProvider; +import software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; +import software.amazon.awssdk.core.client.config.SdkClientOption; +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.ExecutionInterceptorChain; +import software.amazon.awssdk.core.interceptor.InterceptorContext; +import software.amazon.awssdk.core.internal.http.AmazonAsyncHttpClient; +import software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient; +import software.amazon.awssdk.core.internal.retry.SdkDefaultRetryStrategy; +import software.amazon.awssdk.core.signer.NoOpSigner; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.utils.Validate; + +/** + * Test helpers for building {@link AmazonSyncHttpClient} / {@link AmazonAsyncHttpClient} around a caller-supplied + * {@link SdkHttpClient} / {@link SdkAsyncHttpClient}. Unlike the sdk-core copy of this class, the builders here require an + * explicit transport (there is no ServiceLoader-based default), so that per-client test suites can drive the sdk-core + * execution pipeline over each real HTTP client. + */ +public class HttpTestUtils { + + private HttpTestUtils() { + } + + public static TestClientBuilder testClientBuilder() { + return new TestClientBuilder(); + } + + public static TestAsyncClientBuilder testAsyncClientBuilder() { + return new TestAsyncClientBuilder(); + } + + /** + * Builds a minimal {@link ExecutionContext} for driving {@link AmazonSyncHttpClient} / {@link AmazonAsyncHttpClient} + * directly. + */ + public static ExecutionContext executionContext(SdkHttpFullRequest request) { + InterceptorContext interceptorContext = + InterceptorContext.builder() + .request(NoopTestRequest.builder().build()) + .httpRequest(request) + .build(); + return ExecutionContext.builder() + .signer(new NoOpSigner()) + .interceptorChain(new ExecutionInterceptorChain(Collections.emptyList())) + .executionAttributes(new ExecutionAttributes()) + .interceptorContext(interceptorContext) + .metricCollector(MetricCollector.create("ApiCall")) + .build(); + } + + public static SdkClientConfiguration testClientConfiguration() { + return SdkClientConfiguration.builder() + .option(SdkClientOption.EXECUTION_INTERCEPTORS, new ArrayList<>()) + .option(SdkClientOption.CLIENT_ENDPOINT_PROVIDER, + ClientEndpointProvider.forEndpointOverride(URI.create("http://localhost:8080"))) + .option(SdkClientOption.RETRY_STRATEGY, + SdkDefaultRetryStrategy.defaultRetryStrategy()) + .option(SdkClientOption.ADDITIONAL_HTTP_HEADERS, new HashMap<>()) + .option(SdkClientOption.CRC32_FROM_COMPRESSED_DATA_ENABLED, false) + .option(SdkAdvancedClientOption.SIGNER, new NoOpSigner()) + .option(SdkAdvancedClientOption.USER_AGENT_PREFIX, "") + .option(SdkAdvancedClientOption.USER_AGENT_SUFFIX, "") + .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, Executors.newScheduledThreadPool(1)) + .option(SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR, Runnable::run) + .build(); + } + + public static class TestClientBuilder { + private RetryStrategy retryStrategy; + private SdkHttpClient httpClient; + private Map additionalHeaders = new HashMap<>(); + private Duration apiCallTimeout; + private Duration apiCallAttemptTimeout; + + public TestClientBuilder retryStrategy(RetryStrategy retryStrategy) { + this.retryStrategy = retryStrategy; + return this; + } + + public TestClientBuilder httpClient(SdkHttpClient sdkHttpClient) { + this.httpClient = sdkHttpClient; + return this; + } + + public TestClientBuilder additionalHeader(String key, String value) { + this.additionalHeaders.put(key, value); + return this; + } + + public TestClientBuilder apiCallTimeout(Duration duration) { + this.apiCallTimeout = duration; + return this; + } + + public TestClientBuilder apiCallAttemptTimeout(Duration timeout) { + this.apiCallAttemptTimeout = timeout; + return this; + } + + public AmazonSyncHttpClient build() { + SdkHttpClient sdkHttpClient = Validate.paramNotNull(this.httpClient, "httpClient"); + return new AmazonSyncHttpClient(testClientConfiguration().toBuilder() + .option(SdkClientOption.SYNC_HTTP_CLIENT, sdkHttpClient) + .applyMutation(this::configureRetryStrategy) + .applyMutation(this::configureAdditionalHeaders) + .option(SdkClientOption.API_CALL_TIMEOUT, apiCallTimeout) + .option(SdkClientOption.API_CALL_ATTEMPT_TIMEOUT, + apiCallAttemptTimeout) + .build()); + } + + private void configureAdditionalHeaders(SdkClientConfiguration.Builder builder) { + Map> headers = + this.additionalHeaders.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> Arrays.asList(e.getValue()))); + + builder.option(SdkClientOption.ADDITIONAL_HTTP_HEADERS, headers); + } + + private void configureRetryStrategy(SdkClientConfiguration.Builder builder) { + if (retryStrategy != null) { + builder.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } + + public static class TestAsyncClientBuilder { + private RetryStrategy retryStrategy; + private SdkAsyncHttpClient asyncHttpClient; + private Duration apiCallTimeout; + private Duration apiCallAttemptTimeout; + private Map additionalHeaders = new HashMap<>(); + + public TestAsyncClientBuilder retryStrategy(RetryStrategy retryStrategy) { + this.retryStrategy = retryStrategy; + return this; + } + + public TestAsyncClientBuilder asyncHttpClient(SdkAsyncHttpClient asyncHttpClient) { + this.asyncHttpClient = asyncHttpClient; + return this; + } + + public TestAsyncClientBuilder additionalHeader(String key, String value) { + this.additionalHeaders.put(key, value); + return this; + } + + public TestAsyncClientBuilder apiCallTimeout(Duration duration) { + this.apiCallTimeout = duration; + return this; + } + + public TestAsyncClientBuilder apiCallAttemptTimeout(Duration timeout) { + this.apiCallAttemptTimeout = timeout; + return this; + } + + public AmazonAsyncHttpClient build() { + SdkAsyncHttpClient asyncHttpClient = Validate.paramNotNull(this.asyncHttpClient, "asyncHttpClient"); + return new AmazonAsyncHttpClient(testClientConfiguration().toBuilder() + .option(SdkClientOption.ASYNC_HTTP_CLIENT, asyncHttpClient) + .option(SdkClientOption.API_CALL_TIMEOUT, apiCallTimeout) + .option(SdkClientOption.API_CALL_ATTEMPT_TIMEOUT, + apiCallAttemptTimeout) + .applyMutation(this::configureRetryStrategy) + .applyMutation(this::configureAdditionalHeaders) + .build()); + } + + private void configureAdditionalHeaders(SdkClientConfiguration.Builder builder) { + Map> headers = + this.additionalHeaders.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> Arrays.asList(e.getValue()))); + + builder.option(SdkClientOption.ADDITIONAL_HTTP_HEADERS, headers); + } + + private void configureRetryStrategy(SdkClientConfiguration.Builder builder) { + if (retryStrategy != null) { + builder.option(SdkClientOption.RETRY_STRATEGY, retryStrategy); + } + } + } +} diff --git a/test/http-client-tests/src/main/java/utils/ValidSdkObjects.java b/test/http-client-tests/src/main/java/utils/ValidSdkObjects.java new file mode 100644 index 000000000000..221ea778c1a8 --- /dev/null +++ b/test/http-client-tests/src/main/java/utils/ValidSdkObjects.java @@ -0,0 +1,71 @@ +/* + * 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 utils; + +import java.net.URI; +import java.util.List; +import java.util.Optional; +import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpMethod; + +/** + * A collection of objects (or object builder) pre-populated with all required fields. This allows tests to focus on what data + * they care about, not necessarily what data is required. + */ +public final class ValidSdkObjects { + private ValidSdkObjects() { + } + + public static SdkRequest sdkRequest() { + return new SdkRequest() { + @Override + public Optional overrideConfiguration() { + return Optional.empty(); + } + + @Override + public Builder toBuilder() { + return null; + } + + @Override + public List> sdkFields() { + return null; + } + }; + } + + public static SdkHttpFullRequest.Builder sdkHttpFullRequest() { + return sdkHttpFullRequest(80); + } + + public static SdkHttpFullRequest.Builder sdkHttpFullRequest(int port) { + return SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost")) + .port(port) + .putHeader("Host", "localhost") + .method(SdkHttpMethod.GET); + } + + public static SdkHttpFullResponse.Builder sdkHttpFullResponse() { + return SdkHttpFullResponse.builder() + .statusCode(200); + } +} diff --git a/test/http-client-tests/src/main/java/utils/http/WireMockTestBase.java b/test/http-client-tests/src/main/java/utils/http/WireMockTestBase.java new file mode 100644 index 000000000000..1df3d1fea019 --- /dev/null +++ b/test/http-client-tests/src/main/java/utils/http/WireMockTestBase.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 utils.http; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.net.URI; +import org.junit.Rule; +import software.amazon.awssdk.core.exception.SdkServiceException; +import software.amazon.awssdk.core.http.HttpResponseHandler; +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; + +/** + * Base class for tests that use a WireMock server + */ +public abstract class WireMockTestBase { + + @Rule + public WireMockRule mockServer = new WireMockRule(0); + + protected SdkHttpFullRequest.Builder newGetRequest(String resourcePath) { + return newRequest(resourcePath) + .method(SdkHttpMethod.GET); + } + + protected SdkHttpFullRequest.Builder newRequest(String resourcePath) { + return SdkHttpFullRequest.builder() + .uri(URI.create("http://localhost")) + .port(mockServer.port()) + .encodedPath(resourcePath); + } + + protected HttpResponseHandler stubErrorHandler() throws Exception { + HttpResponseHandler errorHandler = mock(HttpResponseHandler.class); + when(errorHandler.handle(any(SdkHttpFullResponse.class), any(ExecutionAttributes.class))).thenReturn(mockException()); + return errorHandler; + } + + private SdkServiceException mockException() { + SdkServiceException exception = SdkServiceException.builder().message("Dummy error response").statusCode(500).build(); + return exception; + } +} diff --git a/test/module-path-tests/pom.xml b/test/module-path-tests/pom.xml index 77ee0023faad..c8c006934d81 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../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 deleted file mode 100644 index 71d96879199a..000000000000 --- a/test/old-client-version-compatibility-test/pom.xml +++ /dev/null @@ -1,172 +0,0 @@ - - - - - 4.0.0 - - aws-sdk-java-pom - software.amazon.awssdk - 2.47.5-SNAPSHOT - ../../pom.xml - - - old-client-version-compatibility-test - AWS Java SDK :: Test :: Old Client Version Compatibility Test - - Tests for old client versions with the latest "core" package versions. - - https://aws.amazon.com/sdkforjava - - - - - software.amazon.awssdk - bom - ${project.version} - pom - import - - - software.amazon.awssdk - bom-internal - ${project.version} - pom - import - - - - - - - - software.amazon.awssdk - sdk-core - ${awsjavasdk.version} - - - software.amazon.awssdk - aws-core - ${awsjavasdk.version} - - - software.amazon.awssdk - auth - ${awsjavasdk.version} - - - software.amazon.awssdk - http-client-spi - ${awsjavasdk.version} - - - software.amazon.awssdk - regions - ${awsjavasdk.version} - - - - - software.amazon.awssdk - aws-xml-protocol - ${awsjavasdk.version} - runtime - - - software.amazon.awssdk - protocol-core - ${awsjavasdk.version} - runtime - - - software.amazon.awssdk - arns - ${awsjavasdk.version} - runtime - - - - - software.amazon.awssdk - s3 - 2.20.136 - - - - - software.amazon.awssdk - service-test-utils - ${project.version} - - - org.junit.jupiter - junit-jupiter - test - - - com.github.tomakehurst - wiremock-jre8-standalone - test - - - org.apache.logging.log4j - log4j-api - test - - - org.apache.logging.log4j - log4j-core - test - - - org.apache.logging.log4j - log4j-slf4j-impl - test - - - org.mockito - mockito-core - test - - - org.slf4j - jcl-over-slf4j - test - ${slf4j.version} - - - org.assertj - assertj-core - test - - - software.amazon.awssdk - test-utils - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - - diff --git a/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/S3PutGetIntegrationTest.java b/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/S3PutGetIntegrationTest.java deleted file mode 100644 index 30f742d7a54d..000000000000 --- a/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/S3PutGetIntegrationTest.java +++ /dev/null @@ -1,181 +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.oldclient; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -import java.util.UUID; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; -import software.amazon.awssdk.auth.signer.AwsS3V4Signer; -import software.amazon.awssdk.core.ResponseBytes; -import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -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.ChecksumMode; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.testutils.service.AwsTestBase; - -public class S3PutGetIntegrationTest extends AwsTestBase { - private static final S3Client S3 = - s3ClientBuilder().build(); - private static final S3Client S3_CUSTOM_SIGNER = - s3ClientBuilder().overrideConfiguration(c -> c.putAdvancedOption(SdkAdvancedClientOption.SIGNER, - AwsS3V4Signer.create())) - .build(); - private static final S3Client S3_NO_CREDS = - s3ClientBuilder().credentialsProvider(AnonymousCredentialsProvider.create()) - .build(); - - private static final S3AsyncClient S3_ASYNC = - getS3AsyncClientBuilder().build(); - private static final S3AsyncClient S3_ASYNC_CUSTOM_SIGNER = - getS3AsyncClientBuilder().overrideConfiguration(c -> c.putAdvancedOption(SdkAdvancedClientOption.SIGNER, - AwsS3V4Signer.create())) - .build(); - private static final S3AsyncClient S3_ASYNC_NO_CREDS = - getS3AsyncClientBuilder().credentialsProvider(AnonymousCredentialsProvider.create()) - .build(); - - private static final String BUCKET = "sra-get-put-integ-" + System.currentTimeMillis(); - private static final String BODY = "foo"; - private static final String BODY_CRC32 = "jHNlIQ=="; - - private String key; - - @BeforeAll - public static void setup() { - S3.createBucket(r -> r.bucket(BUCKET)); - } - - @BeforeEach - public void setupTest() { - key = UUID.randomUUID().toString(); - } - - @AfterAll - public static void teardown() { - TestUtils.deleteBucketAndAllContents(S3, BUCKET); - } - - @Test - public void putGet() { - S3.putObject(r -> r.bucket(BUCKET).key(key), RequestBody.fromString(BODY)); - assertThat(S3.getObjectAsBytes(r -> r.bucket(BUCKET).key(key)).asUtf8String()).isEqualTo(BODY); - } - - @Test - public void putGet_async() { - S3_ASYNC.putObject(r -> r.bucket(BUCKET).key(key), AsyncRequestBody.fromString(BODY)).join(); - assertThat(S3_ASYNC.getObject(r -> r.bucket(BUCKET).key(key), - AsyncResponseTransformer.toBytes()) - .join() - .asUtf8String()).isEqualTo(BODY); - } - - @Test - public void putGet_requestLevelCreds() { - S3_NO_CREDS.putObject(r -> r.bucket(BUCKET) - .key(key) - .overrideConfiguration(c -> c.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)), - RequestBody.fromString(BODY)); - assertThat(S3_NO_CREDS.getObjectAsBytes(r -> r.bucket(BUCKET) - .key(key) - .overrideConfiguration(c -> c.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN))) - .asUtf8String()).isEqualTo(BODY); - } - - @Test - public void putGet_async_requestLevelCreds() { - S3_ASYNC_NO_CREDS.putObject(r -> r.bucket(BUCKET) - .key(key) - .overrideConfiguration(c -> c.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)), - AsyncRequestBody.fromString(BODY)) - .join(); - assertThat(S3_ASYNC_NO_CREDS.getObject(r -> r.bucket(BUCKET) - .key(key) - .overrideConfiguration(c -> c.credentialsProvider(CREDENTIALS_PROVIDER_CHAIN)), - AsyncResponseTransformer.toBytes()) - .join() - .asUtf8String()).isEqualTo(BODY); - } - - @Test - public void putGet_flexibleChecksums() { - S3.putObject(r -> r.bucket(BUCKET).key(key).checksumAlgorithm(ChecksumAlgorithm.CRC32), - RequestBody.fromString(BODY)); - ResponseBytes response = - S3.getObjectAsBytes(r -> r.bucket(BUCKET).key(key).checksumMode(ChecksumMode.ENABLED)); - assertThat(response.asUtf8String()).isEqualTo(BODY); - assertThat(response.response().checksumCRC32()).isEqualTo(BODY_CRC32); - } - - @Test - public void putGet_async_flexibleChecksums() { - S3_ASYNC.putObject(r -> r.bucket(BUCKET).key(key).checksumAlgorithm(ChecksumAlgorithm.CRC32), - AsyncRequestBody.fromString(BODY)).join(); - ResponseBytes response = S3_ASYNC.getObject(r -> r.bucket(BUCKET).key(key).checksumMode(ChecksumMode.ENABLED), - AsyncResponseTransformer.toBytes()) - .join(); - assertThat(response.asUtf8String()).isEqualTo(BODY); - assertThat(response.response().checksumCRC32()).isEqualTo(BODY_CRC32); - } - - @Test - public void putGet_customSigner_flexibleChecksums() { - S3_CUSTOM_SIGNER.putObject(r -> r.bucket(BUCKET).key(key).checksumAlgorithm(ChecksumAlgorithm.CRC32), - RequestBody.fromString(BODY)); - ResponseBytes response = - S3_CUSTOM_SIGNER.getObjectAsBytes(r -> r.bucket(BUCKET).key(key).checksumMode(ChecksumMode.ENABLED)); - assertThat(response.asUtf8String()).isEqualTo(BODY); - assertThat(response.response().checksumCRC32()).isEqualTo(BODY_CRC32); - } - - @Test - public void putGet_async_customSigner_flexibleChecksums() { - S3_ASYNC_CUSTOM_SIGNER.putObject(r -> r.bucket(BUCKET).key(key).checksumAlgorithm(ChecksumAlgorithm.CRC32), - AsyncRequestBody.fromString(BODY)) - .join(); - ResponseBytes response = - S3_ASYNC_CUSTOM_SIGNER.getObject(r -> r.bucket(BUCKET).key(key).checksumMode(ChecksumMode.ENABLED), - AsyncResponseTransformer.toBytes()) - .join(); - assertThat(response.asUtf8String()).isEqualTo(BODY); - assertThat(response.response().checksumCRC32()).isEqualTo(BODY_CRC32); - } - - private static S3ClientBuilder s3ClientBuilder() { - return S3Client.builder() - .region(Region.US_WEST_2) - .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN); - } - - private static S3AsyncClientBuilder getS3AsyncClientBuilder() { - return S3AsyncClient.builder() - .region(Region.US_WEST_2) - .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN); - } -} diff --git a/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/TestUtils.java b/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/TestUtils.java deleted file mode 100644 index 6a1bb1e4cec7..000000000000 --- a/test/old-client-version-compatibility-test/src/it/java/software/amazon/awssdk/services/oldclient/TestUtils.java +++ /dev/null @@ -1,86 +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.oldclient; - -import java.util.Iterator; -import java.util.List; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest; -import software.amazon.awssdk.services.s3.model.ListObjectVersionsResponse; -import software.amazon.awssdk.services.s3.model.ListObjectsRequest; -import software.amazon.awssdk.services.s3.model.ListObjectsResponse; -import software.amazon.awssdk.services.s3.model.NoSuchBucketException; -import software.amazon.awssdk.services.s3.model.S3Object; -import software.amazon.awssdk.testutils.Waiter; - -public class TestUtils { - - public static void deleteBucketAndAllContents(S3Client s3, String bucketName) { - try { - System.out.println("Deleting S3 bucket: " + bucketName); - ListObjectsResponse response = Waiter.run(() -> s3.listObjects(r -> r.bucket(bucketName))) - .ignoringException(NoSuchBucketException.class) - .orFail(); - List objectListing = response.contents(); - - if (objectListing != null) { - while (true) { - for (Iterator iterator = objectListing.iterator(); iterator.hasNext(); ) { - S3Object objectSummary = (S3Object) iterator.next(); - s3.deleteObject(DeleteObjectRequest.builder().bucket(bucketName).key(objectSummary.key()).build()); - } - - if (response.isTruncated()) { - objectListing = s3.listObjects(ListObjectsRequest.builder() - .bucket(bucketName) - .marker(response.marker()) - .build()) - .contents(); - } else { - break; - } - } - } - - - ListObjectVersionsResponse versions = s3 - .listObjectVersions(ListObjectVersionsRequest.builder().bucket(bucketName).build()); - - if (versions.deleteMarkers() != null) { - versions.deleteMarkers().forEach(v -> s3.deleteObject(DeleteObjectRequest.builder() - .versionId(v.versionId()) - .bucket(bucketName) - .key(v.key()) - .build())); - } - - if (versions.versions() != null) { - versions.versions().forEach(v -> s3.deleteObject(DeleteObjectRequest.builder() - .versionId(v.versionId()) - .bucket(bucketName) - .key(v.key()) - .build())); - } - - s3.deleteBucket(DeleteBucketRequest.builder().bucket(bucketName).build()); - } catch (Exception e) { - System.err.println("Failed to delete bucket: " + bucketName); - e.printStackTrace(); - } - } -} 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 deleted file mode 100644 index e5e68dd2faa4..000000000000 --- a/test/old-client-version-compatibility-test/src/it/resources/log4j2.properties +++ /dev/null @@ -1,38 +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. -# - -status = warn - -appender.console.type = Console -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 = info -rootLogger.appenderRef.stdout.ref = ConsoleAppender - -# Uncomment below to enable more specific logging -# -#logger.sdk.name = software.amazon.awssdk -#logger.sdk.level = debug -# -#logger.request.name = software.amazon.awssdk.request -#logger.request.level = debug -# -#logger.apache.name = org.apache.http.wire -#logger.apache.level = debug -# -#logger.netty.name = io.netty.handler.logging -#logger.netty.level = debug diff --git a/test/protocol-tests-core/pom.xml b/test/protocol-tests-core/pom.xml index 9059cf30ee05..2f4000c7e392 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/protocol-tests/pom.xml b/test/protocol-tests/pom.xml index 331081402660..0cd71bb484cd 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/protocol-tests/src/main/resources/codegen-resources/json10/customization.config b/test/protocol-tests/src/main/resources/codegen-resources/json10/customization.config index bb763afd276b..ec7c8d355d50 100644 --- a/test/protocol-tests/src/main/resources/codegen-resources/json10/customization.config +++ b/test/protocol-tests/src/main/resources/codegen-resources/json10/customization.config @@ -1,4 +1,3 @@ { - "skipEndpointTestGeneration": true, - "enableGenerateCompiledEndpointRules": true + "skipEndpointTestGeneration": true } diff --git a/test/protocol-tests/src/main/resources/codegen-resources/sdkrpcv2/customization.config b/test/protocol-tests/src/main/resources/codegen-resources/sdkrpcv2/customization.config index 4a57cda840dd..f137036979c6 100644 --- a/test/protocol-tests/src/main/resources/codegen-resources/sdkrpcv2/customization.config +++ b/test/protocol-tests/src/main/resources/codegen-resources/sdkrpcv2/customization.config @@ -1,4 +1,3 @@ { - "enableGenerateCompiledEndpointRules": true, "skipEndpointTestGeneration": true } diff --git a/test/protocol-tests/src/main/resources/codegen-resources/smithy-query/customization.config b/test/protocol-tests/src/main/resources/codegen-resources/smithy-query/customization.config index bb763afd276b..ec7c8d355d50 100644 --- a/test/protocol-tests/src/main/resources/codegen-resources/smithy-query/customization.config +++ b/test/protocol-tests/src/main/resources/codegen-resources/smithy-query/customization.config @@ -1,4 +1,3 @@ { - "skipEndpointTestGeneration": true, - "enableGenerateCompiledEndpointRules": true + "skipEndpointTestGeneration": true } diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/chunkedencoding/TransferEncodingChunkedFunctionalTests.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/chunkedencoding/TransferEncodingChunkedFunctionalTests.java index fb5b5851db98..11b6bf778df1 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/chunkedencoding/TransferEncodingChunkedFunctionalTests.java +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/chunkedencoding/TransferEncodingChunkedFunctionalTests.java @@ -18,16 +18,16 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.binaryEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.post; import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; import static software.amazon.awssdk.http.Header.CONTENT_LENGTH; import static software.amazon.awssdk.http.Header.TRANSFER_ENCODING; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; -import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.junit5.WireMockExtension; import io.reactivex.Flowable; import java.io.ByteArrayInputStream; import java.io.FilterInputStream; @@ -40,58 +40,152 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.function.Supplier; +import java.util.stream.Stream; import org.apache.commons.lang3.RandomStringUtils; -import org.junit.Rule; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.reactivestreams.Subscriber; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.http.ContentStreamProvider; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpConfigurationOption; import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.crt.AwsCrtAsyncHttpClient; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; import software.amazon.awssdk.services.protocolrestjson.model.StreamingInputOperationChunkedEncodingRequest; +import software.amazon.awssdk.utils.AttributeMap; public final class TransferEncodingChunkedFunctionalTests { - @Rule - public WireMockRule wireMock = new WireMockRule(0); - - @Test - public void apacheClientStreamingOperation_withoutContentLength_addsTransferEncodingDoesNotAddContentLength() { + // A single-chunk body and a body large enough to span multiple HTTP chunks (streamed in STREAM_BUFFER_SIZE pieces). + private static final int SMALL_BODY_SIZE = 1024; + private static final int MULTI_CHUNK_BODY_SIZE = 1024 * 1024; + private static final int STREAM_BUFFER_SIZE = 128 * 1024; + + @RegisterExtension + static WireMockExtension wireMock = WireMockExtension.newInstance() + .options(wireMockConfig().dynamicPort().dynamicHttpsPort()) + .build(); + + @BeforeEach + public void setUp() { stubSuccessfulResponse(); - try (ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() - .httpClient(ApacheHttpClient.builder().build()) - .endpointOverride(URI.create("http://localhost:" + wireMock.port())) - .build()) { - TestContentProvider provider = new TestContentProvider(RandomStringUtils.random(1000).getBytes(StandardCharsets.UTF_8)); - RequestBody requestBody = RequestBody.fromContentProvider(provider, "binary/octet-stream"); - client.streamingInputOperationChunkedEncoding(StreamingInputOperationChunkedEncodingRequest.builder().build(), requestBody); + } - verify(postRequestedFor(anyUrl()).withHeader(TRANSFER_ENCODING, equalTo("chunked"))); - verify(postRequestedFor(anyUrl()).withoutHeader(CONTENT_LENGTH)); - } + // The clients are tested over HTTPS so the request takes the default unsigned-payload path. Over plaintext HTTP the + // SDK forces payload signing, which buffers the body and attaches a Content-Length that conflicts with + // Transfer-Encoding: chunked - a configuration real chunked callers never use. Each client is exercised with a + // single-chunk body and a multi-chunk body; the large case additionally proves the streamed body arrives intact. + private static Stream asyncClients() { + return Stream.of( + Arguments.of("Netty, small body", trustAllAsyncClient(NettyNioAsyncHttpClient::builder), SMALL_BODY_SIZE), + Arguments.of("Netty, large body", trustAllAsyncClient(NettyNioAsyncHttpClient::builder), MULTI_CHUNK_BODY_SIZE), + Arguments.of("CRT, small body", trustAllAsyncClient(AwsCrtAsyncHttpClient::builder), SMALL_BODY_SIZE), + Arguments.of("CRT, large body", trustAllAsyncClient(AwsCrtAsyncHttpClient::builder), MULTI_CHUNK_BODY_SIZE) + ); } - @Test - public void nettyClientStreamingOperation_withoutContentLength_addsTransferEncodingDoesNotAddContentLength() { - stubSuccessfulResponse(); - try (ProtocolRestJsonAsyncClient client = ProtocolRestJsonAsyncClient.builder() - .httpClient(NettyNioAsyncHttpClient.create()) - .endpointOverride(URI.create("http://localhost:" + wireMock.port())) - .build()) { + private static Stream syncClients() { + return Stream.of( + Arguments.of("Apache, small body", trustAllSyncClient(ApacheHttpClient::builder), SMALL_BODY_SIZE), + Arguments.of("Apache, large body", trustAllSyncClient(ApacheHttpClient::builder), MULTI_CHUNK_BODY_SIZE), + Arguments.of("CRT, small body", trustAllSyncClient(AwsCrtHttpClient::builder), SMALL_BODY_SIZE), + Arguments.of("CRT, large body", trustAllSyncClient(AwsCrtHttpClient::builder), MULTI_CHUNK_BODY_SIZE) + ); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("asyncClients") + public void asyncClientStreamingOperation_withoutContentLength_usesChunkedEncodingAndStreamsBody( + String description, Supplier httpClient, int bodySize) { + byte[] body = randomBody(bodySize); + try (ProtocolRestJsonAsyncClient client = asyncClient(httpClient.get())) { client.streamingInputOperationChunkedEncoding(StreamingInputOperationChunkedEncodingRequest.builder().build(), - customAsyncRequestBodyWithoutContentLength()).join(); + streamingBodyWithoutContentLength(body)).join(); + + verifyChunkedRequest(body); + } + } + + @ParameterizedTest(name = "{0}") + @MethodSource("syncClients") + public void syncClientStreamingOperation_withoutContentLength_usesChunkedEncodingAndStreamsBody( + String description, Supplier httpClient, int bodySize) { + byte[] body = randomBody(bodySize); + try (ProtocolRestJsonClient client = syncClient(httpClient.get())) { + RequestBody requestBody = RequestBody.fromContentProvider(new TestContentProvider(body), "binary/octet-stream"); + client.streamingInputOperationChunkedEncoding(StreamingInputOperationChunkedEncodingRequest.builder().build(), requestBody); - verify(postRequestedFor(anyUrl()).withHeader(TRANSFER_ENCODING, equalTo("chunked"))); + verifyChunkedRequest(body); } } + private void verifyChunkedRequest(byte[] body) { + wireMock.verify(postRequestedFor(anyUrl()).withHeader(TRANSFER_ENCODING, equalTo("chunked"))); + wireMock.verify(postRequestedFor(anyUrl()).withoutHeader(CONTENT_LENGTH)); + wireMock.verify(postRequestedFor(anyUrl()).withRequestBody(binaryEqualTo(body))); + } + + private static byte[] randomBody(int size) { + return RandomStringUtils.randomAscii(size).getBytes(StandardCharsets.UTF_8); + } + + private static Supplier trustAllAsyncClient(Supplier> builder) { + return () -> trustAllClient(builder.get()); + } + + private static Supplier trustAllSyncClient(Supplier> builder) { + return () -> trustAllClient(builder.get()); + } + + private ProtocolRestJsonAsyncClient asyncClient(SdkAsyncHttpClient httpClient) { + return ProtocolRestJsonAsyncClient.builder() + .httpClient(httpClient) + .endpointOverride(URI.create("https://localhost:" + wireMock.getHttpsPort())) + .build(); + } + + private ProtocolRestJsonClient syncClient(SdkHttpClient httpClient) { + return ProtocolRestJsonClient.builder() + .httpClient(httpClient) + .endpointOverride(URI.create("https://localhost:" + wireMock.getHttpsPort())) + .build(); + } + private void stubSuccessfulResponse() { - stubFor(post(anyUrl()).willReturn(aResponse().withStatus(200))); + wireMock.stubFor(post(anyUrl()).willReturn(aResponse().withStatus(200))); } - private AsyncRequestBody customAsyncRequestBodyWithoutContentLength() { + private static SdkAsyncHttpClient trustAllClient(SdkAsyncHttpClient.Builder builder) { + return builder.buildWithDefaults(trustAll()); + } + + private static SdkHttpClient trustAllClient(SdkHttpClient.Builder builder) { + return builder.buildWithDefaults(trustAll()); + } + + private static AttributeMap trustAll() { + return AttributeMap.builder() + .put(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES, true) + .build(); + } + + // A streaming body that reports no content length, forcing chunked transfer encoding. The payload is split into + // multiple buffers so a large body is emitted as more than one HTTP chunk. + private AsyncRequestBody streamingBodyWithoutContentLength(byte[] body) { + List buffers = new ArrayList<>(); + for (int offset = 0; offset < body.length; offset += STREAM_BUFFER_SIZE) { + int end = Math.min(offset + STREAM_BUFFER_SIZE, body.length); + buffers.add(ByteBuffer.wrap(body, offset, end - offset)); + } return new AsyncRequestBody() { @Override public Optional contentLength() { @@ -100,8 +194,7 @@ public Optional contentLength() { @Override public void subscribe(Subscriber s) { - Flowable.fromPublisher(AsyncRequestBody.fromBytes("Random text".getBytes())) - .subscribe(s); + Flowable.fromIterable(buffers).subscribe(s); } }; } diff --git a/test/region-testing/pom.xml b/test/region-testing/pom.xml deleted file mode 100644 index 644e898daeea..000000000000 --- a/test/region-testing/pom.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - aws-sdk-java-pom - software.amazon.awssdk - 2.47.5-SNAPSHOT - ../../pom.xml - - 4.0.0 - - region-testing - AWS Java SDK :: Test :: Region Testing - Test package for testing the regions module against a fake endpoints.json file. - - - - software.amazon.awssdk - bom-internal - ${project.version} - pom - import - - - - - - - software.amazon.awssdk - regions - ${awsjavasdk.version} - - - software.amazon.awssdk - utils - ${awsjavasdk.version} - - - software.amazon.awssdk - annotations - ${awsjavasdk.version} - - - org.assertj - assertj-core - test - - - org.junit.jupiter - junit-jupiter - test - - - org.junit.vintage - junit-vintage-engine - test - - - org.apache.logging.log4j - log4j-api - test - - - org.apache.logging.log4j - log4j-core - test - - - org.apache.logging.log4j - log4j-slf4j-impl - test - - - - - - - software.amazon.awssdk - codegen-lite-maven-plugin - ${awsjavasdk.version} - - - generate-sources - - generate-regions - - - ${basedir}/src/test/resources/variants-test-endpoints.json - ${basedir}/src/test/resources/variants-test-partitions.json - - - - - - - - diff --git a/test/region-testing/src/test/java/software/amazon/awssdk/regiontesting/EndpointVariantsTest.java b/test/region-testing/src/test/java/software/amazon/awssdk/regiontesting/EndpointVariantsTest.java deleted file mode 100644 index 477fc8ba26a9..000000000000 --- a/test/region-testing/src/test/java/software/amazon/awssdk/regiontesting/EndpointVariantsTest.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.regiontesting; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static software.amazon.awssdk.regions.EndpointTag.DUALSTACK; -import static software.amazon.awssdk.regions.EndpointTag.FIPS; - -import java.net.URI; -import java.util.Arrays; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import software.amazon.awssdk.regions.EndpointTag; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.regions.ServiceEndpointKey; -import software.amazon.awssdk.regions.ServiceMetadata; -import software.amazon.awssdk.utils.Validate; - -@RunWith(Parameterized.class) -public class EndpointVariantsTest { - @Parameterized.Parameter - public TestCase testCase; - - @Test - public void resolvesCorrectEndpoint() { - if (testCase instanceof SuccessCase) { - URI endpoint = ServiceMetadata.of(testCase.service).endpointFor(testCase.endpointKey); - assertThat(endpoint).isEqualTo(((SuccessCase) testCase).endpoint); - } else { - FailureCase failureCase = Validate.isInstanceOf(FailureCase.class, testCase, "Unknown case type %s.", getClass()); - assertThatThrownBy(() -> ServiceMetadata.of(testCase.service).endpointFor(testCase.endpointKey)) - .hasMessageContaining(failureCase.exceptionMessage); - } - } - - @Parameterized.Parameters(name = "{0}") - public static Iterable testCases() { - return Arrays.asList(new SuccessCase("default-pattern-service", "us-west-2", "default-pattern-service.us-west-2.amazonaws.com"), - new SuccessCase("default-pattern-service", "us-west-2", "default-pattern-service-fips.us-west-2.amazonaws.com", FIPS), - new SuccessCase("default-pattern-service", "af-south-1", "default-pattern-service.af-south-1.amazonaws.com"), - new SuccessCase("default-pattern-service", "af-south-1", "default-pattern-service-fips.af-south-1.amazonaws.com", FIPS), - new SuccessCase("global-service", "aws-global", "global-service.amazonaws.com"), - new SuccessCase("global-service", "aws-global", "global-service-fips.amazonaws.com", FIPS), - new SuccessCase("override-variant-service", "us-west-2", "override-variant-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-service", "us-west-2", "fips.override-variant-service.us-west-2.new.dns.suffix", FIPS), - new SuccessCase("override-variant-service", "af-south-1", "override-variant-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-service", "af-south-1", "fips.override-variant-service.af-south-1.new.dns.suffix", FIPS), - new SuccessCase("override-variant-dns-suffix-service", "us-west-2", "override-variant-dns-suffix-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-dns-suffix-service", "us-west-2", "override-variant-dns-suffix-service-fips.us-west-2.new.dns.suffix", FIPS), - new SuccessCase("override-variant-dns-suffix-service", "af-south-1", "override-variant-dns-suffix-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-dns-suffix-service", "af-south-1", "override-variant-dns-suffix-service-fips.af-south-1.new.dns.suffix", FIPS), - new SuccessCase("override-variant-hostname-service", "us-west-2", "override-variant-hostname-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-hostname-service", "us-west-2", "fips.override-variant-hostname-service.us-west-2.amazonaws.com", FIPS), - new SuccessCase("override-variant-hostname-service", "af-south-1", "override-variant-hostname-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-hostname-service", "af-south-1", "fips.override-variant-hostname-service.af-south-1.amazonaws.com", FIPS), - new SuccessCase("override-endpoint-variant-service", "us-west-2", "override-endpoint-variant-service.us-west-2.amazonaws.com"), - new SuccessCase("override-endpoint-variant-service", "us-west-2", "fips.override-endpoint-variant-service.us-west-2.amazonaws.com", FIPS), - new SuccessCase("override-endpoint-variant-service", "af-south-1", "override-endpoint-variant-service.af-south-1.amazonaws.com"), - new SuccessCase("override-endpoint-variant-service", "af-south-1", "override-endpoint-variant-service-fips.af-south-1.amazonaws.com", FIPS), - new SuccessCase("default-pattern-service", "us-west-2", "default-pattern-service.us-west-2.amazonaws.com"), - new SuccessCase("default-pattern-service", "us-west-2", "default-pattern-service.us-west-2.api.aws", DUALSTACK), - new SuccessCase("default-pattern-service", "af-south-1", "default-pattern-service.af-south-1.amazonaws.com"), - new SuccessCase("default-pattern-service", "af-south-1", "default-pattern-service.af-south-1.api.aws", DUALSTACK), - new SuccessCase("global-service", "aws-global", "global-service.amazonaws.com"), - new SuccessCase("global-service", "aws-global", "global-service.api.aws", DUALSTACK), - new SuccessCase("override-variant-service", "us-west-2", "override-variant-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-service", "us-west-2", "override-variant-service.dualstack.us-west-2.new.dns.suffix", DUALSTACK), - new SuccessCase("override-variant-service", "af-south-1", "override-variant-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-service", "af-south-1", "override-variant-service.dualstack.af-south-1.new.dns.suffix", DUALSTACK), - new SuccessCase("override-variant-dns-suffix-service", "us-west-2", "override-variant-dns-suffix-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-dns-suffix-service", "us-west-2", "override-variant-dns-suffix-service.us-west-2.new.dns.suffix", DUALSTACK), - new SuccessCase("override-variant-dns-suffix-service", "af-south-1", "override-variant-dns-suffix-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-dns-suffix-service", "af-south-1", "override-variant-dns-suffix-service.af-south-1.new.dns.suffix", DUALSTACK), - new SuccessCase("override-variant-hostname-service", "us-west-2", "override-variant-hostname-service.us-west-2.amazonaws.com"), - new SuccessCase("override-variant-hostname-service", "us-west-2", "override-variant-hostname-service.dualstack.us-west-2.api.aws", DUALSTACK), - new SuccessCase("override-variant-hostname-service", "af-south-1", "override-variant-hostname-service.af-south-1.amazonaws.com"), - new SuccessCase("override-variant-hostname-service", "af-south-1", "override-variant-hostname-service.dualstack.af-south-1.api.aws", DUALSTACK), - new SuccessCase("override-endpoint-variant-service", "us-west-2", "override-endpoint-variant-service.us-west-2.amazonaws.com"), - new SuccessCase("override-endpoint-variant-service", "us-west-2", "override-endpoint-variant-service.dualstack.us-west-2.amazonaws.com", DUALSTACK), - new SuccessCase("override-endpoint-variant-service", "af-south-1", "override-endpoint-variant-service.af-south-1.amazonaws.com"), - new SuccessCase("override-endpoint-variant-service", "af-south-1", "override-endpoint-variant-service.af-south-1.api.aws", DUALSTACK), - new SuccessCase("multi-variant-service", "us-west-2", "multi-variant-service.us-west-2.amazonaws.com"), - new SuccessCase("multi-variant-service", "us-west-2", "multi-variant-service.dualstack.us-west-2.api.aws", DUALSTACK), - new SuccessCase("multi-variant-service", "us-west-2", "fips.multi-variant-service.us-west-2.amazonaws.com", FIPS), - new SuccessCase("multi-variant-service", "us-west-2", "fips.multi-variant-service.dualstack.us-west-2.new.dns.suffix", FIPS, DUALSTACK), - new SuccessCase("multi-variant-service", "af-south-1", "multi-variant-service.af-south-1.amazonaws.com"), - new SuccessCase("multi-variant-service", "af-south-1", "multi-variant-service.dualstack.af-south-1.api.aws", DUALSTACK), - new SuccessCase("multi-variant-service", "af-south-1", "fips.multi-variant-service.af-south-1.amazonaws.com", FIPS), - new SuccessCase("multi-variant-service", "af-south-1", "fips.multi-variant-service.dualstack.af-south-1.new.dns.suffix", FIPS, DUALSTACK), - new FailureCase("some-service", "us-iso-east-1", "No endpoint known for [dualstack] in us-iso-east-1", DUALSTACK), - new FailureCase("some-service", "us-iso-east-1", "No endpoint known for [fips] in us-iso-east-1", FIPS), - new FailureCase("some-service", "us-iso-east-1", "No endpoint known for [fips, dualstack] in us-iso-east-1", FIPS, DUALSTACK), - - // These test case outcomes deviate from the other SDKs, because we ignore "global" services when a - // non-global region is specified. We might consider changing this behavior, since the storm of - // global services becoming regionalized is dying down. - new SuccessCase("global-service", "foo", "global-service.foo.amazonaws.com"), - new SuccessCase("global-service", "foo", "global-service-fips.foo.amazonaws.com", FIPS), - new SuccessCase("global-service", "foo", "global-service.foo.amazonaws.com"), - new SuccessCase("global-service", "foo", "global-service.foo.api.aws", DUALSTACK)); - } - - public static class TestCase { - private final String service; - private final ServiceEndpointKey endpointKey; - - public TestCase(String service, String region, EndpointTag... tags) { - this.service = service; - this.endpointKey = ServiceEndpointKey.builder().region(Region.of(region)).tags(tags).build(); - } - } - - public static class SuccessCase extends TestCase { - private final URI endpoint; - - public SuccessCase(String service, String region, String endpoint, EndpointTag... tags) { - super(service, region, tags); - this.endpoint = URI.create(endpoint); - } - - @Override - public String toString() { - return "Positive Case: " + endpoint.toString(); - } - } - - private static class FailureCase extends TestCase { - private final String exceptionMessage; - - public FailureCase(String service, String region, String exceptionMessage, EndpointTag... tags) { - super(service, region, tags); - this.exceptionMessage = exceptionMessage; - } - - @Override - public String toString() { - return "Negative Case: " + exceptionMessage; - } - } -} diff --git a/test/region-testing/src/test/resources/variants-test-endpoints.json b/test/region-testing/src/test/resources/variants-test-endpoints.json deleted file mode 100644 index bf05ed7db3f4..000000000000 --- a/test/region-testing/src/test/resources/variants-test-endpoints.json +++ /dev/null @@ -1,239 +0,0 @@ -{ - "partitions" : [ - { - "defaults" : { - "hostname" : "{service}.{region}.{dnsSuffix}", - "protocols" : [ "https" ], - "signatureVersions" : [ "v4" ], - "variants" : [ - { - "dnsSuffix" : "amazonaws.com", - "hostname" : "{service}-fips.{region}.{dnsSuffix}", - "tags" : [ "fips" ] - }, - { - "dnsSuffix" : "api.aws", - "hostname" : "{service}.{region}.{dnsSuffix}", - "tags" : [ "dualstack" ] - }, - { - "dnsSuffix" : "api.aws", - "hostname" : "{service}-fips.{region}.{dnsSuffix}", - "tags" : [ "dualstack", "fips" ] - } - ] - }, - "dnsSuffix" : "amazonaws.com", - "partition" : "aws", - "regionRegex" : "^(us|eu|ap|sa|ca|me|af)\\-\\w+\\-\\d+$", - "regions" : { - "af-south-1" : { - "description" : "Africa (Cape Town)" - }, - "us-west-2" : { - "description" : "US West (Oregon)" - } - }, - "services" : { - "default-pattern-service" : { - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "default-pattern-service-fips.us-west-2.amazonaws.com", - "tags" : [ "fips" ] - }, - { - "hostname" : "default-pattern-service.us-west-2.api.aws", - "tags" : [ "dualstack" ] - } - ] - } - } - }, - "global-service" : { - "endpoints" : { - "aws-global" : { - "credentialScope" : { - "region" : "us-east-1" - }, - "hostname" : "global-service.amazonaws.com", - "variants" : [ - { - "hostname" : "global-service-fips.amazonaws.com", - "tags" : [ "fips" ] - }, - { - "hostname" : "global-service.api.aws", - "tags" : [ "dualstack" ] - } - ] - } - }, - "isRegionalized" : false, - "partitionEndpoint" : "aws-global" - }, - "override-variant-service" : { - "defaults" : { - "variants" : [ - { - "hostname" : "fips.{service}.{region}.{dnsSuffix}", - "dnsSuffix" : "new.dns.suffix", - "tags" : [ "fips" ] - }, - { - "hostname" : "{service}.dualstack.{region}.{dnsSuffix}", - "dnsSuffix" : "new.dns.suffix", - "tags" : [ "dualstack" ] - } - ] - }, - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "fips.override-variant-service.us-west-2.new.dns.suffix", - "tags" : [ "fips" ] - }, - { - "hostname" : "override-variant-service.dualstack.us-west-2.new.dns.suffix", - "tags" : [ "dualstack" ] - } - ] - } - } - }, - "override-variant-dns-suffix-service" : { - "defaults" : { - "variants" : [ - { - "dnsSuffix" : "new.dns.suffix", - "tags" : [ "fips" ] - }, - { - "dnsSuffix" : "new.dns.suffix", - "tags" : [ "dualstack" ] - } - ] - }, - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "override-variant-dns-suffix-service-fips.us-west-2.new.dns.suffix", - "tags" : [ "fips" ] - }, - { - "hostname" : "override-variant-dns-suffix-service.us-west-2.new.dns.suffix", - "tags" : [ "dualstack" ] - } - ] - } - } - }, - "override-variant-hostname-service" : { - "defaults" : { - "variants" : [ - { - "hostname" : "fips.{service}.{region}.{dnsSuffix}", - "tags" : [ "fips" ] - }, - { - "hostname" : "{service}.dualstack.{region}.{dnsSuffix}", - "tags" : [ "dualstack" ] - } - ] - }, - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "fips.override-variant-hostname-service.us-west-2.amazonaws.com", - "tags" : [ "fips" ] - }, - { - "hostname" : "override-variant-hostname-service.dualstack.us-west-2.api.aws", - "tags" : [ "dualstack" ] - } - ] - } - } - }, - "override-endpoint-variant-service" : { - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "fips.override-endpoint-variant-service.us-west-2.amazonaws.com", - "tags" : [ "fips" ] - }, - { - "hostname" : "override-endpoint-variant-service.dualstack.us-west-2.amazonaws.com", - "tags" : [ "dualstack" ] - } - ] - } - } - }, - "multi-variant-service" : { - "defaults" : { - "variants" : [ - { - "hostname" : "fips.{service}.{region}.{dnsSuffix}", - "tags" : [ "fips" ] - }, - { - "hostname" : "{service}.dualstack.{region}.{dnsSuffix}", - "tags" : [ "dualstack" ] - }, - { - "dnsSuffix" : "new.dns.suffix", - "hostname" : "fips.{service}.dualstack.{region}.{dnsSuffix}", - "tags" : [ "fips", "dualstack" ] - } - ] - }, - "endpoints" : { - "af-south-1" : { }, - "us-west-2" : { - "variants" : [ - { - "hostname" : "fips.multi-variant-service.dualstack.us-west-2.new.dns.suffix", - "tags" : [ "fips", "dualstack" ] - } - ] - } - } - } - } - }, - { - "defaults": { - "hostname": "{service}.{region}.{dnsSuffix}", - "protocols": ["https"], - "signatureVersions": ["v4"] - }, - "dnsSuffix": "c2s.ic.gov", - "partition": "aws-iso", - "regionRegex": "^us\\-iso\\-\\w+\\-\\d+$", - "regions": { - "us-iso-east-1": { - "description": "US ISO East" - } - }, - "services": { - "some-service": { - "endpoints" : { - "us-iso-east-1": {} - } - } - } - } - ], - "version": 3 -} diff --git a/test/region-testing/src/test/resources/variants-test-partitions.json b/test/region-testing/src/test/resources/variants-test-partitions.json deleted file mode 100644 index 398403e43c1a..000000000000 --- a/test/region-testing/src/test/resources/variants-test-partitions.json +++ /dev/null @@ -1,273 +0,0 @@ -{ - "partitions": [ - { - "id": "aws", - "outputs": { - "dnsSuffix": "amazonaws.com", - "dualStackDnsSuffix": "api.aws", - "implicitGlobalRegion": "us-east-1", - "name": "aws", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^(us|eu|ap|sa|ca|me|af|il|mx)\\-\\w+\\-\\d+$", - "regions": { - "af-south-1": { - "description": "Africa (Cape Town)" - }, - "ap-east-1": { - "description": "Asia Pacific (Hong Kong)" - }, - "ap-east-2": { - "description": "Asia Pacific (Taipei)" - }, - "ap-northeast-1": { - "description": "Asia Pacific (Tokyo)" - }, - "ap-northeast-2": { - "description": "Asia Pacific (Seoul)" - }, - "ap-northeast-3": { - "description": "Asia Pacific (Osaka)" - }, - "ap-south-1": { - "description": "Asia Pacific (Mumbai)" - }, - "ap-south-2": { - "description": "Asia Pacific (Hyderabad)" - }, - "ap-southeast-1": { - "description": "Asia Pacific (Singapore)" - }, - "ap-southeast-2": { - "description": "Asia Pacific (Sydney)" - }, - "ap-southeast-3": { - "description": "Asia Pacific (Jakarta)" - }, - "ap-southeast-4": { - "description": "Asia Pacific (Melbourne)" - }, - "ap-southeast-5": { - "description": "Asia Pacific (Malaysia)" - }, - "ap-southeast-6": { - "description": "Asia Pacific (New Zealand)" - }, - "ap-southeast-7": { - "description": "Asia Pacific (Thailand)" - }, - "aws-global": { - "description": "aws global region" - }, - "ca-central-1": { - "description": "Canada (Central)" - }, - "ca-west-1": { - "description": "Canada West (Calgary)" - }, - "eu-central-1": { - "description": "Europe (Frankfurt)" - }, - "eu-central-2": { - "description": "Europe (Zurich)" - }, - "eu-north-1": { - "description": "Europe (Stockholm)" - }, - "eu-south-1": { - "description": "Europe (Milan)" - }, - "eu-south-2": { - "description": "Europe (Spain)" - }, - "eu-west-1": { - "description": "Europe (Ireland)" - }, - "eu-west-2": { - "description": "Europe (London)" - }, - "eu-west-3": { - "description": "Europe (Paris)" - }, - "il-central-1": { - "description": "Israel (Tel Aviv)" - }, - "me-central-1": { - "description": "Middle East (UAE)" - }, - "me-south-1": { - "description": "Middle East (Bahrain)" - }, - "mx-central-1": { - "description": "Mexico (Central)" - }, - "sa-east-1": { - "description": "South America (Sao Paulo)" - }, - "us-east-1": { - "description": "US East (N. Virginia)" - }, - "us-east-2": { - "description": "US East (Ohio)" - }, - "us-west-1": { - "description": "US West (N. California)" - }, - "us-west-2": { - "description": "US West (Oregon)" - } - } - }, - { - "id": "aws-cn", - "outputs": { - "dnsSuffix": "amazonaws.com.cn", - "dualStackDnsSuffix": "api.amazonwebservices.com.cn", - "implicitGlobalRegion": "cn-northwest-1", - "name": "aws-cn", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^cn\\-\\w+\\-\\d+$", - "regions": { - "aws-cn-global": { - "description": "aws-cn global region" - }, - "cn-north-1": { - "description": "China (Beijing)" - }, - "cn-northwest-1": { - "description": "China (Ningxia)" - } - } - }, - { - "id": "aws-eusc", - "outputs": { - "dnsSuffix": "amazonaws.eu", - "dualStackDnsSuffix": "api.amazonwebservices.eu", - "implicitGlobalRegion": "eusc-de-east-1", - "name": "aws-eusc", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^eusc\\-(de)\\-\\w+\\-\\d+$", - "regions": { - "eusc-de-east-1": { - "description": "EU (Germany)" - } - } - }, - { - "id": "aws-iso", - "outputs": { - "dnsSuffix": "c2s.ic.gov", - "implicitGlobalRegion": "us-iso-east-1", - "name": "aws-iso" - }, - "regionRegex": "^us\\-iso\\-\\w+\\-\\d+$", - "regions": { - "aws-iso-global": { - "description": "aws-iso global region" - }, - "us-iso-east-1": { - "description": "US ISO East" - }, - "us-iso-west-1": { - "description": "US ISO WEST" - } - } - }, - { - "id": "aws-iso-b", - "outputs": { - "dnsSuffix": "sc2s.sgov.gov", - "dualStackDnsSuffix": "api.aws.scloud", - "implicitGlobalRegion": "us-isob-east-1", - "name": "aws-iso-b", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^us\\-isob\\-\\w+\\-\\d+$", - "regions": { - "aws-iso-b-global": { - "description": "aws-iso-b global region" - }, - "us-isob-east-1": { - "description": "US ISOB East (Ohio)" - }, - "us-isob-west-1": { - "description": "US ISOB West" - } - } - }, - { - "id": "aws-iso-e", - "outputs": { - "dnsSuffix": "cloud.adc-e.uk", - "dualStackDnsSuffix": "api.cloud-aws.adc-e.uk", - "implicitGlobalRegion": "eu-isoe-west-1", - "name": "aws-iso-e", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^eu\\-isoe\\-\\w+\\-\\d+$", - "regions": { - "aws-iso-e-global": { - "description": "aws-iso-e global region" - }, - "eu-isoe-west-1": { - "description": "EU ISOE West" - } - } - }, - { - "id": "aws-iso-f", - "outputs": { - "dnsSuffix": "csp.hci.ic.gov", - "dualStackDnsSuffix": "api.aws.hci.ic.gov", - "implicitGlobalRegion": "us-isof-south-1", - "name": "aws-iso-f", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^us\\-isof\\-\\w+\\-\\d+$", - "regions": { - "aws-iso-f-global": { - "description": "aws-iso-f global region" - }, - "us-isof-east-1": { - "description": "US ISOF EAST" - }, - "us-isof-south-1": { - "description": "US ISOF SOUTH" - } - } - }, - { - "id": "aws-us-gov", - "outputs": { - "dnsSuffix": "amazonaws.com", - "dualStackDnsSuffix": "api.aws", - "implicitGlobalRegion": "us-gov-west-1", - "name": "aws-us-gov", - "supportsDualStack": true, - "supportsFIPS": true - }, - "regionRegex": "^us\\-gov\\-\\w+\\-\\d+$", - "regions": { - "aws-us-gov-global": { - "description": "aws-us-gov global region" - }, - "us-gov-east-1": { - "description": "AWS GovCloud (US-East)" - }, - "us-gov-west-1": { - "description": "AWS GovCloud (US-West)" - } - } - } - ], - "version": "1.1" -} diff --git a/test/ruleset-testing-core/pom.xml b/test/ruleset-testing-core/pom.xml index cbb248e4e847..c59d1c01db5a 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/EndpointProviderTestCase.java b/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/EndpointProviderTestCase.java index c731aad8fc78..56da1199e4a4 100644 --- a/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/EndpointProviderTestCase.java +++ b/test/ruleset-testing-core/src/main/java/software/amazon/awssdk/core/rules/testing/EndpointProviderTestCase.java @@ -22,12 +22,19 @@ public final class EndpointProviderTestCase { private Supplier testMethod; private Expect expect; + private String name; public EndpointProviderTestCase(Supplier testMethod, Expect expect) { this.testMethod = testMethod; this.expect = expect; } + public EndpointProviderTestCase(String name, Supplier testMethod, Expect expect) { + this.name = name; + this.testMethod = testMethod; + this.expect = expect; + } + public Supplier getTestMethod() { return testMethod; } @@ -43,4 +50,13 @@ public Expect getExpect() { public void setExpect(Expect expect) { this.expect = expect; } + + @Override + public String toString() { + if (name != null) { + return name; + } else { + return super.toString(); + } + } } diff --git a/test/s3-benchmarks/pom.xml b/test/s3-benchmarks/pom.xml index 4c304ae44b0e..8a3f88da0095 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 @@ -129,6 +129,15 @@ cloudwatch-metric-publisher ${awsjavasdk.version} + + com.fasterxml.jackson.core + jackson-databind + + + org.assertj + assertj-core + test + diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BaseJavaS3ClientBenchmark.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BaseJavaS3ClientBenchmark.java index 0aac95206957..56f401c09e11 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BaseJavaS3ClientBenchmark.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BaseJavaS3ClientBenchmark.java @@ -36,11 +36,12 @@ public abstract class BaseJavaS3ClientBenchmark implements Benchmark { protected final List buckets; protected final byte[] contents; private final S3Client adminClient; + private final InMemoryMetricPublisher metricPublisher; - - protected BaseJavaS3ClientBenchmark(BenchmarkConfig config) { + protected BaseJavaS3ClientBenchmark(BenchmarkConfig config, InMemoryMetricPublisher metricPublisher) { this.iteration = Validate.getOrDefault(config.iteration(), () -> DEFAULT_BENCHMARK_ITERATIONS); this.benchmarkConfig = config; + this.metricPublisher = metricPublisher; this.buckets = new ArrayList<>(); this.adminClient = S3BenchmarkTestUtils.s3ClientBuilder(config.region()) .credentialsProvider(config.credentialsProvider()) @@ -54,12 +55,12 @@ public void run() { setup(); LOGGER.info(() -> "Starting warm up"); warmUp(); + metricPublisher.reset(); LOGGER.info(() -> "Run benchmark"); doRunBenchmark(); - } catch (Exception e) { - LOGGER.error(() -> "Exception occurred", e); } finally { LOGGER.info(() -> "Starting clean up"); + cleanup(); } } @@ -70,17 +71,24 @@ protected void setup() { if (useS3Express) { bucketNameSuffix = String.format(S3EXPRESS_BUCKET_PATTERN, benchmarkConfig.az()); } + String sizeTag = benchmarkConfig.contentLengthInKb() + "k"; for (int i = 0; i < numTestBuckets; i++) { - String bucketName = S3BenchmarkTestUtils.getTemporaryBucketName(i, bucketNameSuffix).toLowerCase(Locale.ENGLISH); + String bucketName = S3BenchmarkTestUtils.getTemporaryBucketName(sizeTag + "-" + i, bucketNameSuffix) + .toLowerCase(Locale.ENGLISH); buckets.add(bucketName); - createBucketSafely(adminClient, bucketName, useS3Express); + createBucketSafely(adminClient, bucketName, useS3Express, benchmarkConfig.az()); } } - protected void warmUp() throws Exception { + protected void warmUp() { for (int i = 0; i < 3; i++) { sendOneRequest(); - Thread.sleep(500); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } } } @@ -95,4 +103,11 @@ protected String bucketName(int i) { protected String key(int i) { return keyNameFromPrefix(i, benchmarkConfig.contentLengthInKb().toString()); } + + protected void cleanup() { + for (String bucket : buckets) { + S3BenchmarkTestUtils.deleteBucketAndContentSafely(adminClient, bucket); + } + adminClient.close(); + } } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/Benchmark.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/Benchmark.java index 1e1ab6455302..6b2f8ab8d495 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/Benchmark.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/Benchmark.java @@ -15,42 +15,7 @@ package software.amazon.awssdk.s3benchmarks.s3express; -import java.util.function.Supplier; - -/** - * Factory to create the benchmark - */ @FunctionalInterface public interface Benchmark { - - /** - * The benchmark method to run - */ void run(); - - default TimedResult runWithTime(Supplier toRun) { - long start = System.currentTimeMillis(); - T result = toRun.get(); - long end = System.currentTimeMillis(); - return new TimedResult<>(result, (end - start) / 1000.0); - } - - final class TimedResult { - private final Double latency; - private final T result; - - public TimedResult(T result, Double latency) { - this.result = result; - this.latency = latency; - } - - public Double latency() { - return latency; - } - - public T result() { - return result; - } - - } } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkConfig.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkConfig.java index 9c1d15aaa18c..4f625907ea34 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkConfig.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkConfig.java @@ -15,131 +15,42 @@ package software.amazon.awssdk.s3benchmarks.s3express; -import java.time.Duration; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; -import software.amazon.awssdk.utils.ToString; public final class BenchmarkConfig { - private final String filePath; private final String az; - private final String key; - private final Double targetThroughput; - private final Long partSizeInMb; - private final ChecksumAlgorithm checksumAlgorithm; private final Integer iteration; - private final Long contentLengthInMb; - private final Integer contentLengthInKb; - private final Duration timeout; - private final Long memoryUsageInMb; - private final Long connectionAcquisitionTimeoutInSec; - private final Boolean forceCrtHttpClient; - private final Integer maxConcurrency; - - private final Long readBufferSizeInMb; private final Integer numBuckets; - private final String prefix; - private final Region region; private final AwsCredentialsProvider credentialsProvider; - private final Boolean useS3Express; private BenchmarkConfig(Builder builder) { - this.filePath = builder.filePath; this.az = builder.az; - this.key = builder.key; - this.targetThroughput = builder.targetThroughput; - this.partSizeInMb = builder.partSizeInMb; - this.checksumAlgorithm = builder.checksumAlgorithm; this.iteration = builder.iteration; - this.readBufferSizeInMb = builder.readBufferSizeInMb; - this.prefix = builder.prefix; - this.contentLengthInMb = builder.contentLengthInMb; - this.timeout = builder.timeout; - this.memoryUsageInMb = builder.memoryUsage; - this.connectionAcquisitionTimeoutInSec = builder.connectionAcquisitionTimeoutInSec; - this.forceCrtHttpClient = builder.forceCrtHttpClient; - this.maxConcurrency = builder.maxConcurrency; - this.numBuckets = builder.numBuckets; this.contentLengthInKb = builder.contentLengthInKb; + this.numBuckets = builder.numBuckets; this.region = builder.region; this.credentialsProvider = builder.credentialsProvider; this.useS3Express = builder.useS3Express; } - public String filePath() { - return filePath; - } - public String az() { return az; } - public String key() { - return key; - } - - public Double targetThroughput() { - return targetThroughput; - } - - public Long partSizeInMb() { - return partSizeInMb; - } - - public ChecksumAlgorithm checksumAlgorithm() { - return checksumAlgorithm; - } - public Integer iteration() { return iteration; } - public Long readBufferSizeInMb() { - return readBufferSizeInMb; - } - - public String prefix() { - return prefix; - } - - public Long contentLengthInMb() { - return contentLengthInMb; - } - public Integer contentLengthInKb() { return contentLengthInKb; } - public Duration timeout() { - return this.timeout; - } - - public Long memoryUsageInMb() { - return this.memoryUsageInMb; - } - - public Long connectionAcquisitionTimeoutInSec() { - return this.connectionAcquisitionTimeoutInSec; - } - - public boolean forceCrtHttpClient() { - return this.forceCrtHttpClient; - } - - public Boolean useS3Express() { - return this.useS3Express; - } - - public Integer maxConcurrency() { - return this.maxConcurrency; - } - public Integer numBuckets() { - return this.numBuckets; + return numBuckets; } public Region region() { @@ -150,142 +61,38 @@ public AwsCredentialsProvider credentialsProvider() { return credentialsProvider; } - public static Builder builder() { - return new Builder(); + public Boolean useS3Express() { + return useS3Express; } - @Override - public String toString() { - return ToString.builder("BenchmarkConfig") - .add("filePath", filePath) - .add("bucket", az) - .add("key", key) - .add("targetThroughput", targetThroughput) - .add("partSizeInMb", partSizeInMb) - .add("checksumAlgorithm", checksumAlgorithm) - .add("iteration", iteration) - .add("contentLengthInMb", contentLengthInMb) - .add("timeout", timeout) - .add("memoryUsageInMb", memoryUsageInMb) - .add("connectionAcquisitionTimeoutInSec", connectionAcquisitionTimeoutInSec) - .add("forceCrtHttpClient", forceCrtHttpClient) - .add("maxConcurrency", maxConcurrency) - .add("readBufferSizeInMb", readBufferSizeInMb) - .add("prefix", prefix) - .build(); + public static Builder builder() { + return new Builder(); } static final class Builder { - private Long readBufferSizeInMb; - private ChecksumAlgorithm checksumAlgorithm; - private String filePath; private String az; - private String key; - private Double targetThroughput; - private Long partSizeInMb; - private Long contentLengthInMb; - private Integer contentLengthInKb; - private Long memoryUsage; - private Long connectionAcquisitionTimeoutInSec; - private Boolean forceCrtHttpClient; - private Integer maxConcurrency; private Integer iteration; + private Integer contentLengthInKb; private Integer numBuckets; - private Region region; private AwsCredentialsProvider credentialsProvider; - - private String prefix; - - private Duration timeout; - private Boolean useS3Express; - public Builder filePath(String filePath) { - this.filePath = filePath; - return this; - } - public Builder az(String az) { this.az = az; return this; } - public Builder useS3Express(Boolean useS3Express) { - this.useS3Express = useS3Express; - return this; - } - - public Builder key(String key) { - this.key = key; - return this; - } - - public Builder targetThroughput(Double targetThroughput) { - this.targetThroughput = targetThroughput; - return this; - } - - public Builder partSizeInMb(Long partSizeInMb) { - this.partSizeInMb = partSizeInMb; - return this; - } - - public Builder checksumAlgorithm(ChecksumAlgorithm checksumAlgorithm) { - this.checksumAlgorithm = checksumAlgorithm; - return this; - } - public Builder iteration(Integer iteration) { this.iteration = iteration; return this; } - public Builder readBufferSizeInMb(Long readBufferSizeInMb) { - this.readBufferSizeInMb = readBufferSizeInMb; - return this; - } - - public Builder prefix(String prefix) { - this.prefix = prefix; - return this; - } - - public Builder contentLengthInMb(Long contentLengthInMb) { - this.contentLengthInMb = contentLengthInMb; - return this; - } - public Builder contentLengthInKb(Integer contentLengthInKb) { this.contentLengthInKb = contentLengthInKb; return this; } - public Builder timeout(Duration timeout) { - this.timeout = timeout; - return this; - } - - public Builder memoryUsageInMb(Long memoryUsage) { - this.memoryUsage = memoryUsage; - return this; - } - - public Builder connectionAcquisitionTimeoutInSec(Long connectionAcquisitionTimeoutInSec) { - this.connectionAcquisitionTimeoutInSec = connectionAcquisitionTimeoutInSec; - return this; - } - - public Builder forceCrtHttpClient(Boolean forceCrtHttpClient) { - this.forceCrtHttpClient = forceCrtHttpClient; - return this; - } - - public Builder maxConcurrency(Integer maxConcurrency) { - this.maxConcurrency = maxConcurrency; - return this; - } - public Builder numBuckets(Integer numBuckets) { this.numBuckets = numBuckets; return this; @@ -301,9 +108,13 @@ public Builder credentialsProvider(AwsCredentialsProvider credentialsProvider) { return this; } + public Builder useS3Express(Boolean useS3Express) { + this.useS3Express = useS3Express; + return this; + } + public BenchmarkConfig build() { return new BenchmarkConfig(this); } - } } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkSystemSetting.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkSystemSetting.java deleted file mode 100644 index d822c1cf3551..000000000000 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/BenchmarkSystemSetting.java +++ /dev/null @@ -1,47 +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.s3benchmarks.s3express; - -import software.amazon.awssdk.annotations.SdkPublicApi; -import software.amazon.awssdk.utils.SystemSetting; - -/** - * System settings set by the benchmark runner. - */ -@SdkPublicApi -public enum BenchmarkSystemSetting implements SystemSetting { - BENCHMARK_TEST_ROLE, - - RUN_ID, - - ; - - - @Override - public String property() { - return null; - } - - @Override - public String environmentVariable() { - return name(); - } - - @Override - public String defaultValue() { - return null; - } -} diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisher.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisher.java new file mode 100644 index 000000000000..5781e47b8e2e --- /dev/null +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisher.java @@ -0,0 +1,82 @@ +/* + * 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.s3benchmarks.s3express; + +import java.time.Duration; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricPublisher; + +/** + * Collects SDK per-request metrics in memory for later aggregation. + * Captures API_CALL_DURATION per operation and READ_THROUGHPUT for GetObject. + */ +public class InMemoryMetricPublisher implements MetricPublisher { + private final ConcurrentHashMap> apiCallDurations = new ConcurrentHashMap<>(); + private final ConcurrentHashMap> readThroughputs = new ConcurrentHashMap<>(); + + @Override + public void publish(MetricCollection metricCollection) { + String operationName = metricCollection.metricValues(CoreMetric.OPERATION_NAME) + .stream().findFirst().orElse("Unknown"); + + metricCollection.metricValues(CoreMetric.API_CALL_DURATION) + .forEach(d -> apiCallDurations + .computeIfAbsent(operationName, k -> new CopyOnWriteArrayList<>()) + .add(d)); + + metricCollection.childrenWithName("ApiCallAttempt") + .forEach(attempt -> attempt.metricValues(CoreMetric.READ_THROUGHPUT) + .forEach(t -> readThroughputs + .computeIfAbsent(operationName, k -> new CopyOnWriteArrayList<>()) + .add(t))); + } + + @Override + public void close() { + } + + public double avgDurationMs(String operationName) { + List durations = apiCallDurations.getOrDefault(operationName, Collections.emptyList()); + if (durations.isEmpty()) { + throw new IllegalStateException("No API_CALL_DURATION samples collected for " + operationName); + } + return durations.stream() + .mapToDouble(d -> d.toNanos() / 1_000_000.0) + .average() + .orElse(0.0); + } + + public double avgReadThroughput(String operationName) { + List throughputs = readThroughputs.getOrDefault(operationName, Collections.emptyList()); + if (throughputs.isEmpty()) { + throw new IllegalStateException("No READ_THROUGHPUT samples collected for " + operationName); + } + return throughputs.stream() + .mapToDouble(Double::doubleValue) + .average() + .orElse(0.0); + } + + public void reset() { + apiCallDurations.clear(); + readThroughputs.clear(); + } +} diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunner.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunner.java index 5822de568e1b..91dc0290f3c1 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunner.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunner.java @@ -15,156 +15,187 @@ package software.amazon.awssdk.s3benchmarks.s3express; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.io.IOException; +import java.nio.file.Paths; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; -import java.util.Optional; -import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; -import software.amazon.awssdk.core.metrics.CoreMetric; -import software.amazon.awssdk.http.HttpMetric; +import java.util.Map; +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; -import software.amazon.awssdk.metrics.MetricLevel; -import software.amazon.awssdk.metrics.MetricPublisher; -import software.amazon.awssdk.metrics.publishers.cloudwatch.CloudWatchMetricPublisher; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.sts.StsClient; -import software.amazon.awssdk.services.sts.auth.StsAssumeRoleCredentialsProvider; import software.amazon.awssdk.utils.Logger; /** - * The S3BenchmarkRunner adds basic upload/download tests. - * - * Improvement suggestions - * - Add detailed metrics - * - Add more sophisticated support for test suites - * - Merge with existing benchmarking tests in this module - * - Dimensions: clients - * - Support checksumming - * + * Runs S3 benchmarks against both S3 Express One Zone (directory buckets) and standard S3, + * outputting results as JMH-compatible JSON. */ public class S3BenchmarkRunner { private static final Logger LOGGER = Logger.loggerFor("S3BenchmarkRunner"); - - private static List metricPublishers = new ArrayList<>(); + private static final Region REGION = Region.US_WEST_2; + private static final String AZ = "usw2-az1"; private S3BenchmarkRunner() { } - public static void runBenchmarks(boolean useS3Express) { - Region region = Region.US_EAST_1; + public static void main(String[] args) throws IOException { + String outputFile = parseOutputFile(args); - String namespacePrefix = useS3Express ? "Veyron" : "Standard"; + List> results = new ArrayList<>(); - AwsCredentialsProvider credentialsProvider = credentialsProvider(); + LOGGER.info(() -> "Running benchmarks against S3 Express"); + results.addAll(runBenchmarks(true)); + LOGGER.info(() -> "Running benchmarks against Standard S3"); + results.addAll(runBenchmarks(false)); - CloudWatchAsyncClient cloudwatchClient = CloudWatchAsyncClient.builder() - .region(region) - .httpClient(NettyNioAsyncHttpClient.create()) - .credentialsProvider(credentialsProvider) - .build(); + writeResultsJson(results, outputFile); + LOGGER.info(() -> "Results written to " + outputFile); + } - S3Client s3Client = S3BenchmarkTestUtils.s3ClientBuilder(region) - .credentialsProvider(credentialsProvider) - .overrideConfiguration(o -> o.addMetricPublisher( - metricPublisher(cloudwatchClient, - namespacePrefix + "/SmallObject/Apache"))) - .build(); + private static String parseOutputFile(String[] args) { + for (int i = 0; i < args.length; i++) { + if ("--output".equals(args[i]) && i + 1 < args.length) { + return args[i + 1]; + } + } + return "results.json"; + } + + private static List> runBenchmarks(boolean useS3Express) { + List> results = new ArrayList<>(); + String bucketType = useS3Express ? "s3express" : "standard"; + + InMemoryMetricPublisher metricPublisher = new InMemoryMetricPublisher(); + DefaultCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create(); + + S3Client syncClient = S3BenchmarkTestUtils.s3ClientBuilder(REGION) + .credentialsProvider(credentialsProvider) + .overrideConfiguration(o -> o.addMetricPublisher(metricPublisher)) + .build(); - LOGGER.info(() -> "Running small objects benchmark, 64Kb data, 5 buckets, 200 iterations"); - BenchmarkConfig smallObjectSyncConfig = BenchmarkConfig.builder() - .region(region) - .credentialsProvider(credentialsProvider) - .numBuckets(5) - .iteration(200) - .contentLengthInKb(64) - .useS3Express(useS3Express) - .az("use1-az5") - .build(); - S3PutGetDeleteSyncBenchmark syncBenchmark = new S3PutGetDeleteSyncBenchmark(smallObjectSyncConfig, s3Client); - syncBenchmark.run(); - s3Client.close(); - - s3Client = S3BenchmarkTestUtils.s3ClientBuilder(region) + try { + results.addAll(runSyncBenchmark(syncClient, metricPublisher, credentialsProvider, useS3Express, 64, bucketType)); + results.addAll(runSyncBenchmark(syncClient, metricPublisher, credentialsProvider, useS3Express, 1024, bucketType)); + } finally { + syncClient.close(); + } + + S3AsyncClient asyncClient = S3AsyncClient.builder() + .region(REGION) + .credentialsProvider(credentialsProvider) + .overrideConfiguration(o -> o.addMetricPublisher(metricPublisher)) + .httpClient(NettyNioAsyncHttpClient.create()) + .build(); + try { + results.addAll(runAsyncBenchmark(asyncClient, metricPublisher, credentialsProvider, useS3Express, 64, bucketType)); + } finally { + asyncClient.close(); + } + + metricPublisher.close(); + return results; + } + + private static List> runSyncBenchmark(S3Client s3Client, + InMemoryMetricPublisher metricPublisher, + DefaultCredentialsProvider credentialsProvider, + boolean useS3Express, + int contentLengthInKb, String bucketType) { + String objectSize = contentLengthInKb >= 1024 ? (contentLengthInKb / 1024) + "MB" : contentLengthInKb + "KB"; + LOGGER.info(() -> String.format("Running sync benchmark: %s, %s, %d buckets, 200 iterations", + bucketType, objectSize, 5)); + + BenchmarkConfig config = BenchmarkConfig.builder() + .region(REGION) .credentialsProvider(credentialsProvider) - .overrideConfiguration(o -> o.addMetricPublisher( - metricPublisher(cloudwatchClient, - namespacePrefix + "/MediumObject/Apache"))) + .numBuckets(5) + .iteration(200) + .contentLengthInKb(contentLengthInKb) + .useS3Express(useS3Express) + .az(AZ) .build(); - LOGGER.info(() -> "Running medium objects benchmark, 1024Kb data, 5 buckets, 200 iterations"); - BenchmarkConfig largeObjectSyncConfig = BenchmarkConfig.builder() - .region(region) - .credentialsProvider(credentialsProvider) - .numBuckets(5) - .iteration(200) - .contentLengthInKb(1024) - .useS3Express(useS3Express) - .az("use1-az5") - .build(); - syncBenchmark = new S3PutGetDeleteSyncBenchmark(largeObjectSyncConfig, s3Client); - syncBenchmark.run(); - - s3Client.close(); - - S3AsyncClient s3AsyncClient = S3BenchmarkTestUtils.s3AsyncClientBuilder(region) - .credentialsProvider(credentialsProvider) - .overrideConfiguration(o -> o.addMetricPublisher( - metricPublisher(cloudwatchClient, - namespacePrefix + "/SmallObject/Netty"))) - .httpClient(NettyNioAsyncHttpClient.create()) - .build(); - LOGGER.info(() -> "Running async small objects benchmark, 64Kb data, 5 buckets, 100 iterations"); - BenchmarkConfig smallObjectAsyncConfig = BenchmarkConfig.builder() - .region(region) - .credentialsProvider(credentialsProvider) - .numBuckets(5) - .iteration(100) - .contentLengthInKb(64) - .useS3Express(useS3Express) - .az("use1-az5") - .build(); - S3PutGetDeleteAsyncBenchmark asyncBenchmark = new S3PutGetDeleteAsyncBenchmark(smallObjectAsyncConfig, s3AsyncClient); - asyncBenchmark.run(); - s3AsyncClient.close(); - - metricPublishers.forEach(MetricPublisher::close); + S3PutGetDeleteSyncBenchmark benchmark = new S3PutGetDeleteSyncBenchmark(config, s3Client, metricPublisher); + benchmark.run(); + + List> results = new ArrayList<>(); + results.add(buildResult("s3express.S3Benchmark.putObject", metricPublisher.avgDurationMs("PutObject"), + "ms/op", bucketType, objectSize, "Apache")); + results.add(buildResult("s3express.S3Benchmark.getObject", metricPublisher.avgDurationMs("GetObject"), + "ms/op", bucketType, objectSize, "Apache")); + results.add(buildResult("s3express.S3Benchmark.deleteObject", metricPublisher.avgDurationMs("DeleteObject"), + "ms/op", bucketType, objectSize, "Apache")); + results.add(buildResult("s3express.S3Benchmark.readThroughput", metricPublisher.avgReadThroughput("GetObject"), + "bytes/s", bucketType, objectSize, "Apache")); + return results; } - private static AwsCredentialsProvider credentialsProvider() { - Optional roleArn = BenchmarkSystemSetting.BENCHMARK_TEST_ROLE.getStringValue(); - if (!roleArn.isPresent() || roleArn.get().trim().isEmpty()) { - throw new RuntimeException(String.format("%s environment variable not defined", - BenchmarkSystemSetting.BENCHMARK_TEST_ROLE)); - } - - LOGGER.info(() -> String.format("Running benchmarks using role %s", roleArn)); + private static List> runAsyncBenchmark(S3AsyncClient s3AsyncClient, + InMemoryMetricPublisher metricPublisher, + DefaultCredentialsProvider credentialsProvider, + boolean useS3Express, + int contentLengthInKb, String bucketType) { + String objectSize = contentLengthInKb >= 1024 ? (contentLengthInKb / 1024) + "MB" : contentLengthInKb + "KB"; + LOGGER.info(() -> String.format("Running async benchmark: %s, %s, %d buckets, 100 iterations", + bucketType, objectSize, 5)); + + BenchmarkConfig config = BenchmarkConfig.builder() + .region(REGION) + .credentialsProvider(credentialsProvider) + .numBuckets(5) + .iteration(100) + .contentLengthInKb(contentLengthInKb) + .useS3Express(useS3Express) + .az(AZ) + .build(); - String runId = BenchmarkSystemSetting.RUN_ID.getStringValueOrThrow(); - return StsAssumeRoleCredentialsProvider.builder() - .stsClient(StsClient.create()) - .refreshRequest(r -> r.roleArn(roleArn.get()).roleSessionName(runId + "-s3express-perf-testing")) - .build(); + S3PutGetDeleteAsyncBenchmark benchmark = new S3PutGetDeleteAsyncBenchmark(config, s3AsyncClient, metricPublisher); + benchmark.run(); + + List> results = new ArrayList<>(); + results.add(buildResult("s3express.S3Benchmark.putObject", metricPublisher.avgDurationMs("PutObject"), + "ms/op", bucketType, objectSize, "Netty")); + results.add(buildResult("s3express.S3Benchmark.getObject", metricPublisher.avgDurationMs("GetObject"), + "ms/op", bucketType, objectSize, "Netty")); + results.add(buildResult("s3express.S3Benchmark.deleteObject", metricPublisher.avgDurationMs("DeleteObject"), + "ms/op", bucketType, objectSize, "Netty")); + results.add(buildResult("s3express.S3Benchmark.readThroughput", metricPublisher.avgReadThroughput("GetObject"), + "bytes/s", bucketType, objectSize, "Netty")); + return results; } - private static CloudWatchMetricPublisher metricPublisher(CloudWatchAsyncClient cloudwatchClient, String namespace) { - CloudWatchMetricPublisher publisher = CloudWatchMetricPublisher.builder() - .cloudWatchClient(cloudwatchClient) - .namespace(namespace) - .dimensions(CoreMetric.SERVICE_ID, - CoreMetric.OPERATION_NAME, - HttpMetric.HTTP_CLIENT_NAME) - .metricLevel(MetricLevel.TRACE) - .build(); - metricPublishers.add(publisher); - return publisher; + static Map buildResult(String benchmarkName, double score, String scoreUnit, + String bucketType, String objectSize, String httpClient) { + Map result = new LinkedHashMap<>(); + result.put("benchmark", benchmarkName); + result.put("mode", "avgt"); + + Map params = new LinkedHashMap<>(); + params.put("bucketType", bucketType); + params.put("objectSize", objectSize); + params.put("httpClient", httpClient); + result.put("params", params); + + Map primaryMetric = new LinkedHashMap<>(); + primaryMetric.put("score", score); + primaryMetric.put("scoreUnit", scoreUnit); + + List> rawData = new ArrayList<>(); + List fork = new ArrayList<>(); + fork.add(score); + rawData.add(fork); + primaryMetric.put("rawData", rawData); + + result.put("primaryMetric", primaryMetric); + return result; } - public static void main(String[] args) { - LOGGER.info(() -> "Running benchmarks against S3 Express"); - runBenchmarks(true); - LOGGER.info(() -> "Running benchmarks against Standard S3"); - runBenchmarks(false); + private static void writeResultsJson(List> results, String outputFile) throws IOException { + ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); + mapper.writeValue(Paths.get(outputFile).toFile(), results); } } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkTestUtils.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkTestUtils.java index fa9cc036983e..824cc7ba6639 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkTestUtils.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkTestUtils.java @@ -15,16 +15,9 @@ package software.amazon.awssdk.s3benchmarks.s3express; -import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.concurrent.ThreadLocalRandom; -import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain; -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; 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.BucketInfo; @@ -45,48 +38,29 @@ import software.amazon.awssdk.utils.Logger; public class S3BenchmarkTestUtils { - protected static final String S3EXPRESS_BUCKET = "s3express-integ--use1-az2-d-s3"; - protected static final String TEST_CREDENTIALS_PROFILE_NAME = "aws-test-account"; - protected static final AwsCredentialsProviderChain CREDENTIALS_PROVIDER_CHAIN = - AwsCredentialsProviderChain.of(ProfileCredentialsProvider.builder() - .profileName(TEST_CREDENTIALS_PROFILE_NAME) - .build(), - DefaultCredentialsProvider.create()); - private static final Logger logger = Logger.loggerFor("S3Benchmark"); - + private static final String RUN_ID = Long.toHexString(System.nanoTime()); private S3BenchmarkTestUtils() { - } static S3ClientBuilder s3ClientBuilder(Region region) { - return S3Client.builder() - .region(region) - .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN); - - } - - static S3AsyncClientBuilder s3AsyncClientBuilder(Region region) { - return S3AsyncClient.builder() - .region(region) - .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN); - + return S3Client.builder().region(region); } - public static String getTemporaryBucketName(int i, String suffix) { - return String.format("Java-S3ExpressBenchmark-%s-%s", i, suffix); + public static String getTemporaryBucketName(String tag, String suffix) { + return String.format("s3bench-%s-%s-%s", RUN_ID, tag, suffix); } public static String keyNameFromPrefix(int i, String prefix) { return String.format("%s-%s", prefix, i); } - public static void createBucketSafely(S3Client client, String bucketName, boolean useS3Express) { + public static void createBucketSafely(S3Client client, String bucketName, boolean useS3Express, String az) { CreateBucketRequest.Builder createBucketRequestBuilder = CreateBucketRequest.builder().bucket(bucketName); if (useS3Express) { - LocationInfo location = LocationInfo.builder().name("use1-az5").type(LocationType.AVAILABILITY_ZONE).build(); + LocationInfo location = LocationInfo.builder().name(az).type(LocationType.AVAILABILITY_ZONE).build(); BucketInfo bucketInfo = BucketInfo.builder() .dataRedundancy(DataRedundancy.SINGLE_AVAILABILITY_ZONE) .type(BucketType.DIRECTORY) @@ -110,17 +84,6 @@ public static void createBucketSafely(S3Client client, String bucketName, boolea client.waiter().waitUntilBucketExists(r -> r.bucket(bucketName)); } - public static void deleteBucketSafe(S3Client s3, String bucketName) { - try { - logger.info(() -> "Deleting S3 bucket: " + bucketName); - s3.deleteBucket(DeleteBucketRequest.builder().bucket(bucketName).build()); - - } catch (Exception e) { - logger.error(() -> "Failed to delete bucket: " + bucketName); - e.printStackTrace(); - } - } - public static void deleteBucketAndContentSafely(S3Client s3, String bucketName) { try { ListObjectsV2Response response = Waiter.run(() -> s3.listObjectsV2(r -> r.bucket(bucketName))) @@ -136,11 +99,11 @@ public static void deleteBucketAndContentSafely(S3Client s3, String bucketName) } if (response.isTruncated()) { - objectListing = s3.listObjectsV2(ListObjectsV2Request.builder() - .bucket(bucketName) - .continuationToken(response.continuationToken()) - .build()) - .contents(); + response = s3.listObjectsV2(ListObjectsV2Request.builder() + .bucket(bucketName) + .continuationToken(response.continuationToken()) + .build()); + objectListing = response.contents(); } else { break; } @@ -152,46 +115,4 @@ public static void deleteBucketAndContentSafely(S3Client s3, String bucketName) e.printStackTrace(); } } - - public static byte[] randomBytes(long size) { - byte[] bytes = new byte[Math.toIntExact(size)]; - ThreadLocalRandom.current().nextBytes(bytes); - return bytes; - } - - public static void printOutResult(List metrics, String name, long contentLengthInByte) { - logger.info(() -> String.format("=============== %s Result ================", name)); - logger.info(() -> String.valueOf(metrics)); - double averageLatency = metrics.stream() - .mapToDouble(a -> a) - .average() - .orElse(0.0); - - double lowestLatency = metrics.stream() - .mapToDouble(a -> a) - .min().orElse(0.0); - - double contentLengthInKilobytes = (contentLengthInByte / (double) 1024) * 8.0; - logger.info(() -> "Average latency (s): " + averageLatency); - logger.info(() -> "Latency variance (s): " + variance(metrics, averageLatency)); - logger.info(() -> "Object size (Gigabit): " + contentLengthInKilobytes); - logger.info(() -> "Average throughput (Gbps): " + contentLengthInKilobytes / averageLatency); - logger.info(() -> "Highest average throughput (Gbps): " + contentLengthInKilobytes / lowestLatency); - logger.info(() -> "=========================================================="); - } - - /** - * calculates the variance (std deviation squared) of the sample - * @param sample the values to calculate the variance for - * @param mean the known mean of the sample - * @return the variance value - */ - private static double variance(Collection sample, double mean) { - double numerator = 0; - for (double value : sample) { - double diff = value - mean; - numerator += (diff * diff); - } - return numerator / sample.size(); - } } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteAsyncBenchmark.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteAsyncBenchmark.java index 20f614d619e8..fe1dd35e442f 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteAsyncBenchmark.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteAsyncBenchmark.java @@ -29,8 +29,9 @@ public class S3PutGetDeleteAsyncBenchmark extends BaseJavaS3ClientBenchmark { private static final Logger LOG = Logger.loggerFor(S3PutGetDeleteAsyncBenchmark.class); private final S3AsyncClient s3AsyncClient; - public S3PutGetDeleteAsyncBenchmark(BenchmarkConfig config, S3AsyncClient s3AsyncClient) { - super(config); + public S3PutGetDeleteAsyncBenchmark(BenchmarkConfig config, S3AsyncClient s3AsyncClient, + InMemoryMetricPublisher metricPublisher) { + super(config, metricPublisher); this.s3AsyncClient = s3AsyncClient; } diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteSyncBenchmark.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteSyncBenchmark.java index 8256745a4874..18f66026fe11 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteSyncBenchmark.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/s3express/S3PutGetDeleteSyncBenchmark.java @@ -26,8 +26,9 @@ public class S3PutGetDeleteSyncBenchmark extends BaseJavaS3ClientBenchmark { private static final Logger LOG = Logger.loggerFor(S3PutGetDeleteSyncBenchmark.class); private final S3Client s3Client; - public S3PutGetDeleteSyncBenchmark(BenchmarkConfig config, S3Client s3Client) { - super(config); + public S3PutGetDeleteSyncBenchmark(BenchmarkConfig config, S3Client s3Client, + InMemoryMetricPublisher metricPublisher) { + super(config, metricPublisher); this.s3Client = s3Client; } diff --git a/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisherTest.java b/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisherTest.java new file mode 100644 index 000000000000..cb2d8487a700 --- /dev/null +++ b/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/InMemoryMetricPublisherTest.java @@ -0,0 +1,98 @@ +/* + * 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.s3benchmarks.s3express; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.within; + +import java.time.Duration; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricCollector; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class InMemoryMetricPublisherTest { + + private InMemoryMetricPublisher publisher; + + @BeforeEach + void setUp() { + publisher = new InMemoryMetricPublisher(); + } + + @Test + void avgDurationMs_throwsOnZeroSamples() { + assertThatThrownBy(() -> publisher.avgDurationMs("PutObject")) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("PutObject"); + } + + @Test + void avgReadThroughput_throwsOnZeroSamples() { + assertThatThrownBy(() -> publisher.avgReadThroughput("GetObject")) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("GetObject"); + } + + @Test + void avgDurationMs_computesAverage() { + publisher.publish(metricCollection("PutObject", Duration.ofMillis(10), null)); + publisher.publish(metricCollection("PutObject", Duration.ofMillis(20), null)); + + assertThat(publisher.avgDurationMs("PutObject")).isCloseTo(15.0, within(0.01)); + } + + @Test + void avgReadThroughput_computesAverage() { + publisher.publish(metricCollection("GetObject", Duration.ofMillis(5), 1000.0)); + publisher.publish(metricCollection("GetObject", Duration.ofMillis(5), 2000.0)); + + assertThat(publisher.avgReadThroughput("GetObject")).isCloseTo(1500.0, within(0.01)); + } + + @Test + void reset_clearsSamples() { + publisher.publish(metricCollection("PutObject", Duration.ofMillis(10), null)); + publisher.reset(); + + assertThatThrownBy(() -> publisher.avgDurationMs("PutObject")) + .isInstanceOf(IllegalStateException.class); + } + + @Test + void separatesOperations() { + publisher.publish(metricCollection("PutObject", Duration.ofMillis(10), null)); + publisher.publish(metricCollection("GetObject", Duration.ofMillis(20), null)); + + assertThat(publisher.avgDurationMs("PutObject")).isCloseTo(10.0, within(0.01)); + assertThat(publisher.avgDurationMs("GetObject")).isCloseTo(20.0, within(0.01)); + } + + private static MetricCollection metricCollection(String operationName, Duration duration, Double readThroughput) { + MetricCollector collector = MetricCollector.create("ApiCall"); + collector.reportMetric(CoreMetric.OPERATION_NAME, operationName); + collector.reportMetric(CoreMetric.API_CALL_DURATION, duration); + + if (readThroughput != null) { + MetricCollector attempt = collector.createChild("ApiCallAttempt"); + attempt.reportMetric(CoreMetric.READ_THROUGHPUT, readThroughput); + } + + return collector.collect(); + } +} diff --git a/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunnerTest.java b/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunnerTest.java new file mode 100644 index 000000000000..3904b0330f82 --- /dev/null +++ b/test/s3-benchmarks/src/test/java/software/amazon/awssdk/s3benchmarks/s3express/S3BenchmarkRunnerTest.java @@ -0,0 +1,64 @@ +/* + * 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.s3benchmarks.s3express; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +class S3BenchmarkRunnerTest { + + @TempDir + Path tempDir; + + @Test + void outputJson_hasExpectedStructure() throws IOException { + List> results = new ArrayList<>(); + results.add(S3BenchmarkRunner.buildResult("s3express.S3Benchmark.putObject", 12.5, "ms/op", "s3express", "64KB", "Apache")); + results.add(S3BenchmarkRunner.buildResult("s3express.S3Benchmark.readThroughput", 96000000.0, "bytes/s", "s3express", "64KB", "Apache")); + + Path outputFile = tempDir.resolve("results.json"); + ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT); + mapper.writeValue(outputFile.toFile(), results); + + JsonNode root = new ObjectMapper().readTree(outputFile.toFile()); + assertThat(root.isArray()).isTrue(); + assertThat(root.size()).isEqualTo(2); + + JsonNode first = root.get(0); + assertThat(first.get("benchmark").asText()).isEqualTo("s3express.S3Benchmark.putObject"); + assertThat(first.get("mode").asText()).isEqualTo("avgt"); + assertThat(first.get("params").get("bucketType").asText()).isEqualTo("s3express"); + assertThat(first.get("params").get("objectSize").asText()).isEqualTo("64KB"); + assertThat(first.get("params").get("httpClient").asText()).isEqualTo("Apache"); + assertThat(first.get("primaryMetric").get("score").asDouble()).isEqualTo(12.5); + assertThat(first.get("primaryMetric").get("scoreUnit").asText()).isEqualTo("ms/op"); + assertThat(first.get("primaryMetric").get("rawData").get(0).get(0).asDouble()).isEqualTo(12.5); + + JsonNode second = root.get(1); + assertThat(second.get("benchmark").asText()).isEqualTo("s3express.S3Benchmark.readThroughput"); + assertThat(second.get("primaryMetric").get("scoreUnit").asText()).isEqualTo("bytes/s"); + } +} diff --git a/test/s3-tests/pom.xml b/test/s3-tests/pom.xml index 888cd4e43f38..47eb28660eed 100644 --- a/test/s3-tests/pom.xml +++ b/test/s3-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/sdk-benchmarks/pom.xml b/test/sdk-benchmarks/pom.xml index 74e2d7755572..9b88ac9d2362 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/BenchmarkRunner.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/BenchmarkRunner.java index 0b28b61a0e4e..e87dbac8d50e 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/BenchmarkRunner.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/BenchmarkRunner.java @@ -51,8 +51,13 @@ import software.amazon.awssdk.benchmark.apicall.protocol.QueryProtocolBenchmark; import software.amazon.awssdk.benchmark.apicall.protocol.SmithyRpcV2ProtocolBenchmark; import software.amazon.awssdk.benchmark.apicall.protocol.XmlProtocolBenchmark; +import software.amazon.awssdk.benchmark.coldstart.V1ClientCreationBenchmark; import software.amazon.awssdk.benchmark.coldstart.V2DefaultClientCreationBenchmark; +import software.amazon.awssdk.benchmark.coldstart.V2DefaultFirstRequestBenchmark; import software.amazon.awssdk.benchmark.coldstart.V2OptimizedClientCreationBenchmark; +import software.amazon.awssdk.benchmark.coldstart.V2SdkWarmUpExecutionTimeBenchmark; +import software.amazon.awssdk.benchmark.coldstart.V2WarmedUpClientCreationBenchmark; +import software.amazon.awssdk.benchmark.coldstart.V2WarmedUpFirstRequestBenchmark; import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientDeleteV1MapperComparisonBenchmark; import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientGetOverheadBenchmark; import software.amazon.awssdk.benchmark.enhanced.dynamodb.EnhancedClientGetV1MapperComparisonBenchmark; @@ -86,8 +91,13 @@ public class BenchmarkRunner { CrtHttpClientBenchmark.class.getSimpleName()); private static final List COLD_START_BENCHMARKS = Arrays.asList( + V1ClientCreationBenchmark.class.getSimpleName(), V2OptimizedClientCreationBenchmark.class.getSimpleName(), - V2DefaultClientCreationBenchmark.class.getSimpleName()); + V2DefaultClientCreationBenchmark.class.getSimpleName(), + V2WarmedUpClientCreationBenchmark.class.getSimpleName(), + V2DefaultFirstRequestBenchmark.class.getSimpleName(), + V2WarmedUpFirstRequestBenchmark.class.getSimpleName(), + V2SdkWarmUpExecutionTimeBenchmark.class.getSimpleName()); private static final List MAPPER_BENCHMARKS = Arrays.asList( EnhancedClientGetOverheadBenchmark.class.getSimpleName(), diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java deleted file mode 100644 index 96911c4e9442..000000000000 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServer.java +++ /dev/null @@ -1,70 +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.benchmark.apicall.protocol; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import software.amazon.awssdk.benchmark.utils.BenchmarkUtils; -import software.amazon.awssdk.utils.IoUtils; - -/** - * Lightweight Jetty server for protocol roundtrip benchmarks. - */ -class ProtocolRoundtripServer { - - private final Server server; - private final int port; - - ProtocolRoundtripServer(ProtocolRoundtripServlet servlet) throws IOException { - port = BenchmarkUtils.getUnusedPort(); - server = new Server(); - ServerConnector connector = new ServerConnector(server); - connector.setPort(port); - server.setConnectors(new Connector[] {connector}); - - ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); - context.addServlet(new ServletHolder(servlet), "/*"); - server.setHandler(context); - } - - void start() throws Exception { - server.start(); - } - - void stop() throws Exception { - server.stop(); - } - - URI getHttpUri() { - return URI.create("http://localhost:" + port); - } - - static byte[] loadFixture(String path) throws IOException { - try (InputStream is = ProtocolRoundtripServer.class.getClassLoader() - .getResourceAsStream("fixtures/" + path)) { - if (is == null) { - throw new IOException("Fixture not found: fixtures/" + path); - } - return IoUtils.toByteArray(is); - } - } -} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java deleted file mode 100644 index abcce14534ad..000000000000 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/ProtocolRoundtripServlet.java +++ /dev/null @@ -1,39 +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.benchmark.apicall.protocol; - -import java.io.IOException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -class ProtocolRoundtripServlet extends HttpServlet { - private final byte[] body; - private final String contentType; - - ProtocolRoundtripServlet(byte[] body, String contentType) { - this.body = body; - this.contentType = contentType; - } - - @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setStatus(200); - resp.setContentLength(body.length); - resp.setContentType(contentType); - resp.getOutputStream().write(body); - } -} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java index eb7dfccee20c..e54d004cbb59 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1CborRoundtripBenchmark.java @@ -41,6 +41,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for SmithyRpcV2 CBOR protocol using CloudWatch GetMetricData via HTTP servlet. @@ -53,16 +54,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1CborRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AmazonCloudWatch client; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/cbor"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/cbor"); server.start(); client = AmazonCloudWatchClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java index 6ae6df995a99..e3b0b06b5fb1 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1Ec2RoundtripBenchmark.java @@ -36,6 +36,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for EC2 protocol using EC2 DescribeInstances via HTTP servlet. @@ -48,16 +49,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1Ec2RoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AmazonEC2 client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); + byte[] response = MockHttpServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = AmazonEC2ClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java index 58146050360c..f0b1bde7450c 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1JsonRoundtripBenchmark.java @@ -39,6 +39,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for JSON protocol (aws-json) using DynamoDB PutItem via HTTP servlet. @@ -51,16 +52,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1JsonRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AmazonDynamoDB client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); + byte[] response = MockHttpServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/x-amz-json-1.0"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/x-amz-json-1.0"); server.start(); client = AmazonDynamoDBClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java index 3da508d4ff5c..318a9269c91e 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1QueryRoundtripBenchmark.java @@ -35,6 +35,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for Query protocol using STS AssumeRole via HTTP servlet. @@ -47,16 +48,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1QueryRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AWSSecurityTokenService client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); + byte[] response = MockHttpServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = AWSSecurityTokenServiceClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java index 5bc6d9ca080f..f0f532b430ea 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestJsonRoundtripBenchmark.java @@ -42,6 +42,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for REST-JSON protocol using Lambda CreateFunction via HTTP servlet. @@ -54,16 +55,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1RestJsonRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AWSLambda client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); + byte[] response = MockHttpServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/json"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/json"); server.start(); client = AWSLambdaClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java index ff42e19ada68..91d4376c26ae 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V1RestXmlRoundtripBenchmark.java @@ -45,6 +45,7 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; /** * V1 roundtrip benchmark for REST-XML protocol using CloudFront CreateDistribution via HTTP servlet. @@ -57,16 +58,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V1RestXmlRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private AmazonCloudFront client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); + byte[] response = MockHttpServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = AmazonCloudFrontClientBuilder.standard() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java index f2f3e60a740b..e5d8e08cece0 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2CborRoundtripBenchmark.java @@ -32,6 +32,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.protocols.json.StructuredJsonGenerator; import software.amazon.awssdk.protocols.rpcv2.internal.SdkStructuredRpcV2CborFactory; @@ -53,16 +54,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2CborRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private CloudWatchClient client; @Setup(Level.Trial) public void setup() throws Exception { byte[] response = createCborResponseFixture(); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/cbor"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/cbor"); server.start(); client = CloudWatchClient.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java index 3dfdd9cd74d2..7101fef1b013 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2Ec2RoundtripBenchmark.java @@ -31,6 +31,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ec2.Ec2Client; @@ -48,16 +49,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2Ec2RoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private Ec2Client client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("ec2-protocol/describe-instances-response.xml"); + byte[] response = MockHttpServer.loadFixture("ec2-protocol/describe-instances-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = Ec2Client.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java index 6d23fc581f6e..fe144b330a3e 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2JsonRoundtripBenchmark.java @@ -33,6 +33,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; @@ -51,16 +52,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2JsonRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private DynamoDbClient client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("json-protocol/putitem-response.json"); + byte[] response = MockHttpServer.loadFixture("json-protocol/putitem-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/x-amz-json-1.0"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/x-amz-json-1.0"); server.start(); client = DynamoDbClient.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java index aff4d9c23cd2..0241e2437fad 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2QueryRoundtripBenchmark.java @@ -31,6 +31,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.sts.StsClient; @@ -47,16 +48,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2QueryRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private StsClient client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("query-protocol/assumerole-response.xml"); + byte[] response = MockHttpServer.loadFixture("query-protocol/assumerole-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = StsClient.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java index 563ad7fd1dd3..61c741508174 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestJsonRoundtripBenchmark.java @@ -33,6 +33,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.lambda.LambdaClient; @@ -54,16 +55,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2RestJsonRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private LambdaClient client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("rest-json-protocol/createfunction-response.json"); + byte[] response = MockHttpServer.loadFixture("rest-json-protocol/createfunction-response.json"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "application/json"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "application/json"); server.start(); client = LambdaClient.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java index 04cdea1b56ef..bb73ee955892 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/apicall/protocol/V2RestXmlRoundtripBenchmark.java @@ -31,6 +31,7 @@ import org.openjdk.jmh.infra.Blackhole; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.cloudfront.CloudFrontClient; @@ -57,16 +58,14 @@ @OutputTimeUnit(TimeUnit.SECONDS) public class V2RestXmlRoundtripBenchmark { - private ProtocolRoundtripServer server; + private MockHttpServer server; private CloudFrontClient client; @Setup(Level.Trial) public void setup() throws Exception { - byte[] response = ProtocolRoundtripServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); + byte[] response = MockHttpServer.loadFixture("rest-xml-protocol/create-distribution-response.xml"); - ProtocolRoundtripServlet servlet = new ProtocolRoundtripServlet(response, "text/xml"); - - server = new ProtocolRoundtripServer(servlet); + server = new MockHttpServer(response, "text/xml"); server.start(); client = CloudFrontClient.builder() diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/FirstRequestBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/FirstRequestBenchmark.java new file mode 100644 index 000000000000..970401aea4c5 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/FirstRequestBenchmark.java @@ -0,0 +1,69 @@ +/* + * 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.benchmark.coldstart; + +import java.util.HashMap; +import java.util.Map; +import org.openjdk.jmh.infra.Blackhole; +import software.amazon.awssdk.core.SdkBytes; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; + +/** + * Contract for benchmarks that isolate the cost of a client's first API call that included Marshalling, Signing and + * unmarshalling.Implementations build the client (and any warm-up) in an untimed {@code @Setup}, so {@link #firstRequest} + * times only the first request. + */ +public interface FirstRequestBenchmark { + + void firstRequest(Blackhole blackhole) throws Exception; + + /** + * Shared payload for the V2 implementations, so they all marshall the same item. V1 implementations build their own: + * the V1 models are a different type. + */ + static PutItemRequest v2PutItemRequest() { + return PutItemRequest.builder() + .tableName("benchmark-table") + .item(v2ItemMap()) + .build(); + } + + static Map v2ItemMap() { + Map item = new HashMap<>(); + item.put("pk", AttributeValue.fromS("benchmark-key")); + item.put("sk", AttributeValue.fromN("100")); + item.put("stringField", AttributeValue.fromS("test-value")); + item.put("numberField", AttributeValue.fromN("123.456")); + item.put("binaryField", AttributeValue.fromB(SdkBytes.fromUtf8String("hello world"))); + item.put("stringSetField", AttributeValue.builder().ss("value1", "value2", "value3").build()); + item.put("numberSetField", AttributeValue.builder().ns("1.1", "2.2", "3.3").build()); + item.put("boolField", AttributeValue.fromBool(false)); + item.put("nullField", AttributeValue.builder().nul(true).build()); + Map deep = new HashMap<>(); + deep.put("level2", AttributeValue.fromN("999")); + Map nested = new HashMap<>(); + nested.put("nested", AttributeValue.fromS("nested-value")); + nested.put("deepNested", AttributeValue.fromM(deep)); + item.put("mapField", AttributeValue.fromM(nested)); + item.put("listField", AttributeValue.builder().l( + AttributeValue.fromS("item1"), + AttributeValue.fromN("42"), + AttributeValue.fromBool(true), + AttributeValue.builder().nul(true).build()).build()); + return item; + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V1FirstRequestBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V1FirstRequestBenchmark.java new file mode 100644 index 000000000000..af55dc0a31b7 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V1FirstRequestBenchmark.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.benchmark.coldstart; + +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.model.AttributeValue; +import com.amazonaws.services.dynamodbv2.model.PutItemRequest; +import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.profile.StackProfiler; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.CommandLineOptionException; +import org.openjdk.jmh.runner.options.CommandLineOptions; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; + +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 0) +@Measurement(iterations = 1) +@Fork(20) +public class V1FirstRequestBenchmark implements FirstRequestBenchmark { + + private static final String FIXTURE = "json-protocol/putitem-response.json"; + private static final String CONTENT_TYPE = "application/x-amz-json-1.0"; + + private MockHttpServer server; + private AmazonDynamoDB client; + + @Setup(Level.Trial) + public void setup() throws Exception { + server = new MockHttpServer(MockHttpServer.loadFixture(FIXTURE), CONTENT_TYPE); + server.start(); + + client = AmazonDynamoDBClientBuilder.standard() + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration( + server.getHttpUri().toString(), "us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "test"))) + .build(); + } + + @Override + @Benchmark + public void firstRequest(Blackhole blackhole) throws Exception { + blackhole.consume(client.putItem(putItemRequest())); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + if (client != null) { + client.shutdown(); + } + if (server != null) { + server.stop(); + } + } + + public static void main(String... args) throws RunnerException, CommandLineOptionException { + Options opt = new OptionsBuilder() + .parent(new CommandLineOptions()) + .include(V1FirstRequestBenchmark.class.getSimpleName()) + .addProfiler(StackProfiler.class) + .build(); + Collection run = new Runner(opt).run(); + } + + private static PutItemRequest putItemRequest() { + return new PutItemRequest() + .withTableName("benchmark-table") + .withItem(itemMap()); + } + + private static Map itemMap() { + Map item = new HashMap<>(); + item.put("pk", new AttributeValue().withS("benchmark-key")); + item.put("sk", new AttributeValue().withN("100")); + item.put("stringField", new AttributeValue().withS("test-value")); + item.put("numberField", new AttributeValue().withN("123.456")); + item.put("binaryField", new AttributeValue().withB(ByteBuffer.wrap("hello world".getBytes()))); + item.put("stringSetField", new AttributeValue().withSS("value1", "value2", "value3")); + item.put("numberSetField", new AttributeValue().withNS("1.1", "2.2", "3.3")); + item.put("boolField", new AttributeValue().withBOOL(false)); + item.put("nullField", new AttributeValue().withNULL(true)); + Map deep = new HashMap<>(); + deep.put("level2", new AttributeValue().withN("999")); + Map nested = new HashMap<>(); + nested.put("nested", new AttributeValue().withS("nested-value")); + nested.put("deepNested", new AttributeValue().withM(deep)); + item.put("mapField", new AttributeValue().withM(nested)); + item.put("listField", new AttributeValue().withL( + new AttributeValue().withS("item1"), + new AttributeValue().withN("42"), + new AttributeValue().withBOOL(true), + new AttributeValue().withNULL(true))); + return item; + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultClientCreationBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultClientCreationBenchmark.java index 74c3a5eecda2..87e7685a2f87 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultClientCreationBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultClientCreationBenchmark.java @@ -37,7 +37,7 @@ import org.openjdk.jmh.runner.options.CommandLineOptions; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; -import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; /** @@ -58,7 +58,7 @@ public class V2DefaultClientCreationBenchmark implements SdkClientCreationBenchm public void createClient(Blackhole blackhole) throws Exception { client = DynamoDbClient.builder() .endpointDiscoveryEnabled(false) - .httpClient(ApacheHttpClient.builder().build()).build(); + .httpClient(Apache5HttpClient.builder().build()).build(); blackhole.consume(client); } diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultFirstRequestBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultFirstRequestBenchmark.java new file mode 100644 index 000000000000..da75c5be7095 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2DefaultFirstRequestBenchmark.java @@ -0,0 +1,105 @@ +/* + * 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.benchmark.coldstart; + +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.profile.StackProfiler; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.CommandLineOptionException; +import org.openjdk.jmh.runner.options.CommandLineOptions; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * Times the first {@code putItem} on an already-built {@link DynamoDbClient}, with no warm-up. Compare against + * {@link V2WarmedUpFirstRequestBenchmark}. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 0) +@Measurement(iterations = 1) +@Fork(20) +public class V2DefaultFirstRequestBenchmark implements FirstRequestBenchmark { + + private static final String FIXTURE = "json-protocol/putitem-response.json"; + private static final String CONTENT_TYPE = "application/x-amz-json-1.0"; + + private MockHttpServer server; + private DynamoDbClient client; + + @Setup(Level.Trial) + public void setup() throws Exception { + server = new MockHttpServer(MockHttpServer.loadFixture(FIXTURE), CONTENT_TYPE); + server.start(); + + client = DynamoDbClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .endpointDiscoveryEnabled(false) + .build(); + } + + @Override + @Benchmark + public void firstRequest(Blackhole blackhole) throws Exception { + blackhole.consume(client.putItem(FirstRequestBenchmark.v2PutItemRequest())); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + if (client != null) { + client.close(); + } + if (server != null) { + server.stop(); + } + } + + public static void main(String... args) throws RunnerException, CommandLineOptionException { + Options opt = new OptionsBuilder() + .parent(new CommandLineOptions()) + .include(V2DefaultFirstRequestBenchmark.class.getSimpleName()) + .addProfiler(StackProfiler.class) + .build(); + Collection run = new Runner(opt).run(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2OptimizedClientCreationBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2OptimizedClientCreationBenchmark.java index c7826d64d821..aefb537c37c6 100644 --- a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2OptimizedClientCreationBenchmark.java +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2OptimizedClientCreationBenchmark.java @@ -40,7 +40,7 @@ import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; @@ -64,7 +64,7 @@ public void createClient(Blackhole blackhole) throws Exception { .region(Region.US_WEST_2) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("test", "test"))) - .httpClient(ApacheHttpClient.builder().build()) + .httpClient(Apache5HttpClient.builder().build()) .overrideConfiguration(ClientOverrideConfiguration.builder().build()) .endpointDiscoveryEnabled(false) .build(); diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2SdkWarmUpExecutionTimeBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2SdkWarmUpExecutionTimeBenchmark.java new file mode 100644 index 000000000000..037444f8e588 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2SdkWarmUpExecutionTimeBenchmark.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.benchmark.coldstart; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.ServiceLoader; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.profile.StackProfiler; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.CommandLineOptionException; +import org.openjdk.jmh.runner.options.CommandLineOptions; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.core.warmup.SdkWarmUp; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * Measures how long {@link SdkWarmUp#warmUp} takes. The batched, sequential and no-arg methods cover the same scope + * (every discovered {@link SdkWarmUpProvider}, sync and async), so their scores are directly comparable. + * + *

    Scores include a real STS network call per HTTP client, so they vary by host: do not add them to + * {@code baseline.json}. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 0) +@Measurement(iterations = 1) +@Fork(20) +public class V2SdkWarmUpExecutionTimeBenchmark { + + /** Sync and async client class per discovered provider, for the sequential (one call per service) method. */ + private List[]> clientClassesByService; + + /** The same classes in one array, for the single batched {@code warmUp} call. */ + private Class[] allClientClasses; + + /** + * Resolves the discovered providers' client classes so the timed methods pay only for {@code warmUp}. Fails rather + * than skipping an unresolvable provider, which would silently narrow the batched/sequential scope. + */ + @Setup(Level.Trial) + @SuppressWarnings("unchecked") + public void setup() { + clientClassesByService = new ArrayList<>(); + List> flattened = new ArrayList<>(); + + for (SdkWarmUpProvider provider : ServiceLoader.load(SdkWarmUpProvider.class)) { + Class syncClient = loadClientClass(provider.syncClientClassName()); + Class asyncClient = loadClientClass(provider.asyncClientClassName()); + clientClassesByService.add(new Class[] {syncClient, asyncClient}); + flattened.add(syncClient); + flattened.add(asyncClient); + } + + if (clientClassesByService.isEmpty()) { + throw new IllegalStateException("No SdkWarmUpProvider found on the classpath; nothing to warm up."); + } + allClientClasses = flattened.toArray(new Class[0]); + } + + private Class loadClientClass(String className) { + try { + return Class.forName(className).asSubclass(SdkClient.class); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("A registered SdkWarmUpProvider names client class " + className + + ", which is not on the classpath.", e); + } + } + + @Benchmark + public void warmUpSingleService() throws Exception { + SdkWarmUp.warmUp(DynamoDbClient.class); + } + + /** One {@code warmUp} call naming every discovered client, so the HTTP client warm-up runs once. */ + @Benchmark + public void warmUpAllServicesBatched() throws Exception { + SdkWarmUp.warmUp(allClientClasses); + } + + /** One {@code warmUp} call per discovered service, so the HTTP client warm-up runs once per service. */ + @Benchmark + public void warmUpAllServicesSequentially() throws Exception { + for (Class[] perService : clientClassesByService) { + SdkWarmUp.warmUp(perService); + } + } + + /** The no-arg overload: same scope as the two methods above, reached through discovery inside {@code warmUp}. */ + @Benchmark + public void warmUpAllRegisteredProviders() throws Exception { + SdkWarmUp.warmUp(); + } + + public static void main(String... args) throws RunnerException, CommandLineOptionException { + Options opt = new OptionsBuilder() + .parent(new CommandLineOptions()) + .include(V2SdkWarmUpExecutionTimeBenchmark.class.getSimpleName()) + .addProfiler(StackProfiler.class) + .build(); + Collection run = new Runner(opt).run(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpClientCreationBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpClientCreationBenchmark.java new file mode 100644 index 000000000000..28663d95719d --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpClientCreationBenchmark.java @@ -0,0 +1,89 @@ +/* + * 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.benchmark.coldstart; + +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.profile.StackProfiler; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.CommandLineOptionException; +import org.openjdk.jmh.runner.options.CommandLineOptions; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import software.amazon.awssdk.core.warmup.SdkWarmUp; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * Client-creation counterpart to {@link V2DefaultClientCreationBenchmark}, with {@link SdkWarmUp#warmUp(Class[])} run once + * in {@code @Setup} (untimed). The measured work is the same client build; comparing the two scores shows how much of + * client construction the warm-up front-loads. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SampleTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 3) +@Measurement(iterations = 5) +@Fork(3) +public class V2WarmedUpClientCreationBenchmark implements SdkClientCreationBenchmark { + + private DynamoDbClient client; + + @Setup(Level.Trial) + public void setup() { + SdkWarmUp.warmUp(DynamoDbClient.class); + } + + @Override + @Benchmark + public void createClient(Blackhole blackhole) throws Exception { + client = DynamoDbClient.builder() + .endpointDiscoveryEnabled(false) + .httpClient(Apache5HttpClient.builder().build()).build(); + blackhole.consume(client); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + if (client != null) { + client.close(); + } + } + + public static void main(String... args) throws RunnerException, CommandLineOptionException { + Options opt = new OptionsBuilder() + .parent(new CommandLineOptions()) + .include(V2WarmedUpClientCreationBenchmark.class.getSimpleName()) + .addProfiler(StackProfiler.class) + .build(); + Collection run = new Runner(opt).run(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpFirstRequestBenchmark.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpFirstRequestBenchmark.java new file mode 100644 index 000000000000..eb0f11da2f2d --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/coldstart/V2WarmedUpFirstRequestBenchmark.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.benchmark.coldstart; + +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.profile.StackProfiler; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.CommandLineOptionException; +import org.openjdk.jmh.runner.options.CommandLineOptions; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.benchmark.utils.MockHttpServer; +import software.amazon.awssdk.core.warmup.SdkWarmUp; +import software.amazon.awssdk.http.apache5.Apache5HttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + +/** + * Same measured work as {@link V2DefaultFirstRequestBenchmark} (the first {@code putItem} on an already-built client), + * but {@link SdkWarmUp#warmUp(Class[])} runs in the untimed {@code @Setup}. The score difference between the two is the + * first-call work that warm-up front-loads. See {@link V2SdkWarmUpExecutionTimeBenchmark} for how long warmUp() itself + * takes. Single-shot, zero warmup, high fork count: only the first invocation per JVM is cold. Do not override these + * JMH parameters from the CLI, or the two variants converge. + */ +@State(Scope.Benchmark) +@BenchmarkMode(Mode.SingleShotTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 0) +@Measurement(iterations = 1) +@Fork(20) +public class V2WarmedUpFirstRequestBenchmark implements FirstRequestBenchmark { + + private static final String FIXTURE = "json-protocol/putitem-response.json"; + private static final String CONTENT_TYPE = "application/x-amz-json-1.0"; + + private MockHttpServer server; + private DynamoDbClient client; + + @Setup(Level.Trial) + public void setup() throws Exception { + server = new MockHttpServer(MockHttpServer.loadFixture(FIXTURE), CONTENT_TYPE); + server.start(); + + SdkWarmUp.warmUp(DynamoDbClient.class); + + client = DynamoDbClient.builder() + .endpointOverride(server.getHttpUri()) + .region(Region.US_EAST_1) + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("test", "test"))) + .httpClient(Apache5HttpClient.create()) + .endpointDiscoveryEnabled(false) + .build(); + } + + @Override + @Benchmark + public void firstRequest(Blackhole blackhole) throws Exception { + blackhole.consume(client.putItem(FirstRequestBenchmark.v2PutItemRequest())); + } + + @TearDown(Level.Trial) + public void tearDown() throws Exception { + if (client != null) { + client.close(); + } + if (server != null) { + server.stop(); + } + } + + public static void main(String... args) throws RunnerException, CommandLineOptionException { + Options opt = new OptionsBuilder() + .parent(new CommandLineOptions()) + .include(V2WarmedUpFirstRequestBenchmark.class.getSimpleName()) + .addProfiler(StackProfiler.class) + .build(); + Collection run = new Runner(opt).run(); + } +} diff --git a/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/utils/MockHttpServer.java b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/utils/MockHttpServer.java new file mode 100644 index 000000000000..17ae56221a34 --- /dev/null +++ b/test/sdk-benchmarks/src/main/java/software/amazon/awssdk/benchmark/utils/MockHttpServer.java @@ -0,0 +1,94 @@ +/* + * 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.benchmark.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import software.amazon.awssdk.utils.IoUtils; + +/** + * Lightweight plain-HTTP Jetty server that answers every request with a fixed 200 status, body and content type, so a + * real service client can complete an operation without leaving the machine. Used by the protocol roundtrip and + * cold-start benchmarks. + */ +public final class MockHttpServer { + + private final Server server; + private final int port; + + public MockHttpServer(byte[] responseBody, String contentType) throws IOException { + port = BenchmarkUtils.getUnusedPort(); + server = new Server(); + ServerConnector connector = new ServerConnector(server); + connector.setPort(port); + server.setConnectors(new Connector[] {connector}); + + ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS); + context.addServlet(new ServletHolder(new FixedResponseServlet(responseBody, contentType)), "/*"); + server.setHandler(context); + } + + public void start() throws Exception { + server.start(); + } + + public void stop() throws Exception { + server.stop(); + } + + public URI getHttpUri() { + return URI.create("http://localhost:" + port); + } + + public static byte[] loadFixture(String path) throws IOException { + try (InputStream is = MockHttpServer.class.getClassLoader().getResourceAsStream("fixtures/" + path)) { + if (is == null) { + throw new IOException("Fixture not found: fixtures/" + path); + } + return IoUtils.toByteArray(is); + } + } + + /** + * Stateless: returns the same response for every method, path and body, and does not validate the request. + */ + private static final class FixedResponseServlet extends HttpServlet { + private final byte[] body; + private final String contentType; + + private FixedResponseServlet(byte[] body, String contentType) { + this.body = body; + this.contentType = contentType; + } + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setStatus(200); + resp.setContentLength(body.length); + resp.setContentType(contentType); + resp.getOutputStream().write(body); + } + } +} diff --git a/test/sdk-native-image-test/pom.xml b/test/sdk-native-image-test/pom.xml index 04a74d81236e..59bea76c2450 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 @@ -33,7 +33,7 @@ 3.6.1 1.6.0 1.7.36 - 0.9.6 + 1.1.10 @@ -148,15 +148,6 @@ sdk-native-image-test software.amazon.awssdk.nativeimagetest.App - - - - --verbose - --no-fallback - --initialize-at-build-time=org.slf4j - --initialize-at-run-time=io.netty.handler.ssl.BouncyCastleAlpnSslUtils - - diff --git a/test/sdk-standard-benchmarks/pom.xml b/test/sdk-standard-benchmarks/pom.xml index b9ff3e18e52f..d2950938b861 100644 --- a/test/sdk-standard-benchmarks/pom.xml +++ b/test/sdk-standard-benchmarks/pom.xml @@ -19,7 +19,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml diff --git a/test/service-client-backward-compat-test/pom.xml b/test/service-client-backward-compat-test/pom.xml new file mode 100644 index 000000000000..cb212664fce6 --- /dev/null +++ b/test/service-client-backward-compat-test/pom.xml @@ -0,0 +1,148 @@ + + + + + 4.0.0 + + aws-sdk-java-pom + software.amazon.awssdk + 2.55.5-SNAPSHOT + ../../pom.xml + + + service-client-backward-compat-test + AWS Java SDK :: Test :: Service Client Backward Compatibility Test + + Tests that verify older service client versions (>= 2.28.1) work correctly with the latest core modules. + This ensures backward compatibility for the new core + old service client version skew scenario. + + https://aws.amazon.com/sdkforjava + + + + + software.amazon.awssdk + bom + ${project.version} + pom + import + + + software.amazon.awssdk + bom-internal + ${project.version} + pom + import + + + + + + + + software.amazon.awssdk + sdk-core + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-core + ${awsjavasdk.version} + + + software.amazon.awssdk + auth + ${awsjavasdk.version} + + + software.amazon.awssdk + http-client-spi + ${awsjavasdk.version} + + + software.amazon.awssdk + regions + ${awsjavasdk.version} + + + + + software.amazon.awssdk + aws-xml-protocol + ${awsjavasdk.version} + runtime + + + software.amazon.awssdk + protocol-core + ${awsjavasdk.version} + runtime + + + software.amazon.awssdk + arns + ${awsjavasdk.version} + runtime + + + + + software.amazon.awssdk + s3 + 2.28.1 + + + + + software.amazon.awssdk + test-utils + test + + + software.amazon.awssdk + service-test-utils + ${project.version} + test + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + + + org.mockito + mockito-core + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/test/old-client-version-compatibility-test/src/test/java/InterceptorSignerAttributeTest.java b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/InterceptorSignerAttributeTest.java similarity index 76% rename from test/old-client-version-compatibility-test/src/test/java/InterceptorSignerAttributeTest.java rename to test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/InterceptorSignerAttributeTest.java index 58b525e89528..d014700c9a0b 100644 --- a/test/old-client-version-compatibility-test/src/test/java/InterceptorSignerAttributeTest.java +++ b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/InterceptorSignerAttributeTest.java @@ -13,12 +13,13 @@ * permissions and limitations under the License. */ +package software.amazon.awssdk.services.backwardcompat; + import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; import org.junit.jupiter.api.Test; @@ -40,18 +41,6 @@ import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; -import software.amazon.awssdk.http.auth.aws.scheme.AwsV4AuthScheme; -import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner; -import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner; -import software.amazon.awssdk.http.auth.spi.scheme.AuthScheme; -import software.amazon.awssdk.http.auth.spi.signer.AsyncSignRequest; -import software.amazon.awssdk.http.auth.spi.signer.AsyncSignedRequest; -import software.amazon.awssdk.http.auth.spi.signer.HttpSigner; -import software.amazon.awssdk.http.auth.spi.signer.SignRequest; -import software.amazon.awssdk.http.auth.spi.signer.SignedRequest; -import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; -import software.amazon.awssdk.identity.spi.IdentityProvider; -import software.amazon.awssdk.identity.spi.IdentityProviders; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; @@ -76,10 +65,10 @@ public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes attributeModifications.accept(executionAttributes); } }, - AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, // Endpoint rules override signing name - AwsSignerExecutionAttribute.SIGNING_REGION, // Endpoint rules override signing region - AwsSignerExecutionAttribute.AWS_CREDENTIALS, // Legacy auth strategy overrides credentials - AwsSignerExecutionAttribute.SIGNER_DOUBLE_URL_ENCODE); // Endpoint rules override double-url-encode + AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME, + AwsSignerExecutionAttribute.SIGNING_REGION, + AwsSignerExecutionAttribute.AWS_CREDENTIALS, + AwsSignerExecutionAttribute.SIGNER_DOUBLE_URL_ENCODE); } @Test @@ -91,7 +80,7 @@ public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttribut return context.request(); } }, - AwsSignerExecutionAttribute.AWS_CREDENTIALS); // Legacy auth strategy overrides credentials + AwsSignerExecutionAttribute.AWS_CREDENTIALS); } @Test @@ -145,24 +134,19 @@ private void test(Function, ExecutionInterceptor> MockAsyncHttpClient asyncHttpClient = new MockAsyncHttpClient()) { stub200Responses(httpClient, asyncHttpClient); - S3ClientBuilder s3Builder = createS3Builder(configBuilder, httpClient); - S3AsyncClientBuilder s3AsyncBuilder = createS3AsyncBuilder(configBuilder, asyncHttpClient); - CapturingSigner signer1 = new CapturingSigner(); - try (S3Client s3 = s3Builder.overrideConfiguration(configBuilder.putAdvancedOption(SdkAdvancedClientOption.SIGNER, - signer1) - .build()) - .build()) { + try (S3Client s3 = createS3Builder(configBuilder, httpClient) + .overrideConfiguration(configBuilder.putAdvancedOption(SdkAdvancedClientOption.SIGNER, signer1).build()) + .build()) { callS3(s3); validateLegacySignRequest(attributesToExclude, signer1); } CapturingSigner signer2 = new CapturingSigner(); - try (S3AsyncClient s3 = - s3AsyncBuilder.overrideConfiguration(configBuilder.putAdvancedOption(SdkAdvancedClientOption.SIGNER, signer2) - .build()) - .build()) { - callS3(s3); + try (S3AsyncClient s3 = createS3AsyncBuilder(configBuilder, asyncHttpClient) + .overrideConfiguration(configBuilder.putAdvancedOption(SdkAdvancedClientOption.SIGNER, signer2).build()) + .build()) { + callS3Async(s3); validateLegacySignRequest(attributesToExclude, signer2); } } @@ -171,15 +155,14 @@ private void test(Function, ExecutionInterceptor> private static void stub200Responses(MockSyncHttpClient httpClient, MockAsyncHttpClient asyncHttpClient) { HttpExecuteResponse response = HttpExecuteResponse.builder() - .response(SdkHttpResponse.builder() - .statusCode(200) - .build()) + .response(SdkHttpResponse.builder().statusCode(200).build()) .build(); httpClient.stubResponses(response); asyncHttpClient.stubResponses(response); } - private static S3ClientBuilder createS3Builder(ClientOverrideConfiguration.Builder configBuilder, MockSyncHttpClient httpClient) { + private static S3ClientBuilder createS3Builder(ClientOverrideConfiguration.Builder configBuilder, + MockSyncHttpClient httpClient) { return S3Client.builder() .region(Region.US_WEST_2) .credentialsProvider(AnonymousCredentialsProvider.create()) @@ -187,7 +170,8 @@ private static S3ClientBuilder createS3Builder(ClientOverrideConfiguration.Build .overrideConfiguration(configBuilder.build()); } - private static S3AsyncClientBuilder createS3AsyncBuilder(ClientOverrideConfiguration.Builder configBuilder, MockAsyncHttpClient asyncHttpClient) { + private static S3AsyncClientBuilder createS3AsyncBuilder(ClientOverrideConfiguration.Builder configBuilder, + MockAsyncHttpClient asyncHttpClient) { return S3AsyncClient.builder() .region(Region.US_WEST_2) .credentialsProvider(AnonymousCredentialsProvider.create()) @@ -196,18 +180,13 @@ private static S3AsyncClientBuilder createS3AsyncBuilder(ClientOverrideConfigura } private static void callS3(S3Client s3) { - s3.putObject(r -> r.bucket("foo") - .key("bar") - .checksumAlgorithm(ChecksumAlgorithm.CRC32), + s3.putObject(r -> r.bucket("foo").key("bar").checksumAlgorithm(ChecksumAlgorithm.CRC32), RequestBody.fromString("text")); } - private void callS3(S3AsyncClient s3) { - s3.putObject(r -> r.bucket("foo") - .key("bar") - .checksumAlgorithm(ChecksumAlgorithm.CRC32), - AsyncRequestBody.fromString("text")) - .join(); + private void callS3Async(S3AsyncClient s3) { + s3.putObject(r -> r.bucket("foo").key("bar").checksumAlgorithm(ChecksumAlgorithm.CRC32), + AsyncRequestBody.fromString("text")).join(); } private void validateLegacySignRequest(Set> attributesToExclude, CapturingSigner signer) { diff --git a/test/old-client-version-compatibility-test/src/test/java/S3AnonymousTest.java b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3AnonymousTest.java similarity index 98% rename from test/old-client-version-compatibility-test/src/test/java/S3AnonymousTest.java rename to test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3AnonymousTest.java index 72e6baba808a..bab85cf6f89f 100644 --- a/test/old-client-version-compatibility-test/src/test/java/S3AnonymousTest.java +++ b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3AnonymousTest.java @@ -13,6 +13,8 @@ * permissions and limitations under the License. */ +package software.amazon.awssdk.services.backwardcompat; + import static org.assertj.core.api.Assertions.assertThat; import org.junit.jupiter.api.AfterEach; diff --git a/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3OperationsTest.java b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3OperationsTest.java new file mode 100644 index 000000000000..9b7ba2031197 --- /dev/null +++ b/test/service-client-backward-compat-test/src/test/java/software/amazon/awssdk/services/backwardcompat/S3OperationsTest.java @@ -0,0 +1,194 @@ +/* + * 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.backwardcompat; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +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.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.ChecksumMode; +import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; +import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient; + +/** + * Ensure that S3 put/get operations, flexible checksums, and request-level credential overrides work correctly. + */ +public class S3OperationsTest { + private static final StaticCredentialsProvider REQUEST_CREDENTIALS = + StaticCredentialsProvider.create(AwsBasicCredentials.create("request-akid", "request-skid")); + + private MockSyncHttpClient httpClient; + private MockAsyncHttpClient asyncHttpClient; + private S3Client s3; + private S3AsyncClient s3Async; + + @BeforeEach + public void setup() { + this.httpClient = new MockSyncHttpClient(); + this.httpClient.stubNextResponse200(); + + this.asyncHttpClient = new MockAsyncHttpClient(); + this.asyncHttpClient.stubNextResponse200(); + + this.s3 = S3Client.builder() + .region(Region.US_WEST_2) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .httpClient(httpClient) + .build(); + + this.s3Async = S3AsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .httpClient(asyncHttpClient) + .build(); + } + + @AfterEach + public void teardown() { + httpClient.close(); + asyncHttpClient.close(); + s3.close(); + s3Async.close(); + } + + // Put/Get operations + + @Test + public void putObject_sync_completesSuccessfully() { + s3.putObject(r -> r.bucket("bucket").key("key"), RequestBody.fromString("foo")); + assertThat(httpClient.getLastRequest()).isNotNull(); + assertThat(httpClient.getLastRequest().method().name()).isEqualTo("PUT"); + } + + @Test + public void putObject_async_completesSuccessfully() { + s3Async.putObject(r -> r.bucket("bucket").key("key"), AsyncRequestBody.fromString("foo")).join(); + assertThat(asyncHttpClient.getLastRequest()).isNotNull(); + assertThat(asyncHttpClient.getLastRequest().method().name()).isEqualTo("PUT"); + } + + @Test + public void getObject_sync_completesSuccessfully() { + s3.getObject(r -> r.bucket("bucket").key("key"), ResponseTransformer.toBytes()); + assertThat(httpClient.getLastRequest()).isNotNull(); + assertThat(httpClient.getLastRequest().method().name()).isEqualTo("GET"); + } + + @Test + public void getObject_async_completesSuccessfully() { + s3Async.getObject(r -> r.bucket("bucket").key("key"), AsyncResponseTransformer.toBytes()).join(); + assertThat(asyncHttpClient.getLastRequest()).isNotNull(); + assertThat(asyncHttpClient.getLastRequest().method().name()).isEqualTo("GET"); + } + + // Flexible checksums + + @Test + public void putObject_withChecksumAlgorithm_sync_sendsChecksumHeader() { + s3.putObject(r -> r.bucket("bucket").key("key").checksumAlgorithm(ChecksumAlgorithm.CRC32), + RequestBody.fromString("foo")); + assertThat(httpClient.getLastRequest()).isNotNull(); + // Checksum algorithm is sent as x-amz-sdk-checksum-algorithm, actual value as trailing header + assertThat(httpClient.getLastRequest().firstMatchingHeader("x-amz-sdk-checksum-algorithm")) + .isPresent() + .hasValue("CRC32"); + assertThat(httpClient.getLastRequest().firstMatchingHeader("x-amz-trailer")) + .isPresent() + .hasValue("x-amz-checksum-crc32"); + } + + @Test + public void putObject_withChecksumAlgorithm_async_sendsChecksumHeader() { + s3Async.putObject(r -> r.bucket("bucket").key("key").checksumAlgorithm(ChecksumAlgorithm.CRC32), + AsyncRequestBody.fromString("foo")).join(); + assertThat(asyncHttpClient.getLastRequest()).isNotNull(); + assertThat(asyncHttpClient.getLastRequest().firstMatchingHeader("x-amz-sdk-checksum-algorithm")) + .isPresent() + .hasValue("CRC32"); + assertThat(asyncHttpClient.getLastRequest().firstMatchingHeader("x-amz-trailer")) + .isPresent() + .hasValue("x-amz-checksum-crc32"); + } + + @Test + public void getObject_withChecksumMode_sync_sendsChecksumHeader() { + s3.getObject(r -> r.bucket("bucket").key("key").checksumMode(ChecksumMode.ENABLED), + ResponseTransformer.toBytes()); + assertThat(httpClient.getLastRequest()).isNotNull(); + assertThat(httpClient.getLastRequest().firstMatchingHeader("x-amz-checksum-mode")) + .isPresent() + .hasValue("ENABLED"); + } + + @Test + public void getObject_withChecksumMode_async_sendsChecksumHeader() { + s3Async.getObject(r -> r.bucket("bucket").key("key").checksumMode(ChecksumMode.ENABLED), + AsyncResponseTransformer.toBytes()).join(); + assertThat(asyncHttpClient.getLastRequest()).isNotNull(); + assertThat(asyncHttpClient.getLastRequest().firstMatchingHeader("x-amz-checksum-mode")) + .isPresent() + .hasValue("ENABLED"); + } + + // Request-level credential overrides + + @Test + public void requestLevelCredentials_overrideClientCredentials_sync() { + s3.putObject(r -> r.bucket("bucket") + .key("key") + .overrideConfiguration(c -> c.credentialsProvider(REQUEST_CREDENTIALS)), + RequestBody.fromString("foo")); + // Request should have Authorization header since we overrode anonymous with real credentials + assertThat(httpClient.getLastRequest().firstMatchingHeader("Authorization")).isPresent(); + } + + @Test + public void requestLevelCredentials_overrideClientCredentials_async() { + s3Async.putObject(r -> r.bucket("bucket") + .key("key") + .overrideConfiguration(c -> c.credentialsProvider(REQUEST_CREDENTIALS)), + AsyncRequestBody.fromString("foo")) + .join(); + // Request should have Authorization header since we overrode anonymous with real credentials + assertThat(asyncHttpClient.getLastRequest().firstMatchingHeader("Authorization")).isPresent(); + } + + @Test + public void withoutRequestLevelCredentials_usesClientAnonymous_sync() { + s3.putObject(r -> r.bucket("bucket").key("key"), RequestBody.fromString("foo")); + // No override — should be anonymous (no Authorization header) + assertThat(httpClient.getLastRequest().firstMatchingHeader("Authorization")).isEmpty(); + } + + @Test + public void withoutRequestLevelCredentials_usesClientAnonymous_async() { + s3Async.putObject(r -> r.bucket("bucket").key("key"), AsyncRequestBody.fromString("foo")).join(); + // No override — should be anonymous (no Authorization header) + assertThat(asyncHttpClient.getLastRequest().firstMatchingHeader("Authorization")).isEmpty(); + } +} diff --git a/test/service-test-utils/pom.xml b/test/service-test-utils/pom.xml index 4d4c7e010ce5..afcd20878d81 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml service-test-utils diff --git a/test/stability-tests/pom.xml b/test/stability-tests/pom.xml index 186f1dfe6345..0f4781a13653 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/test/test-utils/pom.xml b/test/test-utils/pom.xml index b99933e32425..5e1ac5d28781 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml test-utils diff --git a/test/tests-coverage-reporting/pom.xml b/test/tests-coverage-reporting/pom.xml index f351f0cc8b9c..f303777679a6 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../../pom.xml 4.0.0 @@ -218,7 +218,7 @@ ${awsjavasdk.version} - old-client-version-compatibility-test + service-client-backward-compat-test software.amazon.awssdk ${awsjavasdk.version} diff --git a/test/v2-migration-tests/pom.xml b/test/v2-migration-tests/pom.xml index ee1cafffb48d..d8bcf0bccd65 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../.. diff --git a/test/warmup-tests/pom.xml b/test/warmup-tests/pom.xml new file mode 100644 index 000000000000..08738a164ff7 --- /dev/null +++ b/test/warmup-tests/pom.xml @@ -0,0 +1,181 @@ + + + + + 4.0.0 + + aws-sdk-java-pom + software.amazon.awssdk + 2.55.5-SNAPSHOT + ../../pom.xml + + warmup-tests + AWS Java SDK :: Test :: Warm-up Tests + Centralized tests for the warm-up feature across all modules. Covers the SdkWarmUp orchestrator, HTTP-client + warm-up (run against every HTTP client), and the generated SdkWarmUpProvider of every service module: the + aws-sdk-java aggregate dependency puts all services on the test classpath, so new services are tested + automatically. This is a leaf test module: nothing depends on it, so depending on the HTTP clients and all + services here does not create a dependency cycle. + https://aws.amazon.com/sdkforjava + + + + + software.amazon.awssdk + bom-internal + ${project.version} + pom + import + + + + + + + true + + + + + software.amazon.awssdk + sdk-core + ${awsjavasdk.version} + + + software.amazon.awssdk + apache-client + ${awsjavasdk.version} + test + + + software.amazon.awssdk + http-auth-aws-crt + ${awsjavasdk.version} + test + + + software.amazon.awssdk + apache5-client + ${awsjavasdk.version} + test + + + software.amazon.awssdk + aws-crt-client + ${awsjavasdk.version} + test + + + software.amazon.awssdk + netty-nio-client + ${awsjavasdk.version} + test + + + software.amazon.awssdk + url-connection-client + ${awsjavasdk.version} + test + + + software.amazon.awssdk + sts + ${awsjavasdk.version} + test + + + software.amazon.awssdk + dynamodb + ${awsjavasdk.version} + test + + + + software.amazon.awssdk + aws-sdk-java + ${awsjavasdk.version} + test + + + software.amazon.awssdk + test-utils + ${awsjavasdk.version} + test + + + org.apache.logging.log4j + log4j-core + test + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + + + com.github.tomakehurst + wiremock-jre8-standalone + test + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + true + + + + org.apache.maven.plugins + maven-dependency-plugin + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 1 + false + + + + + diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceSyncClient.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceSyncClient.java new file mode 100644 index 000000000000..5d8f84a642d5 --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceSyncClient.java @@ -0,0 +1,25 @@ +/* + * 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.http.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client matching {@link IdempotenceWarmUpProvider#syncClientClassName()}, warmed only by + * {@link SdkWarmUpIdempotenceTest}. + */ +public interface IdempotenceSyncClient extends SdkClient { +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceWarmUpProvider.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceWarmUpProvider.java new file mode 100644 index 000000000000..8ce59f31752d --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/IdempotenceWarmUpProvider.java @@ -0,0 +1,54 @@ +/* + * 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.http.warmup; + +import java.util.concurrent.atomic.AtomicInteger; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Test-only {@link SdkWarmUpProvider} for {@link SdkWarmUpIdempotenceTest}. Matches {@link IdempotenceSyncClient} + * only and counts sync warms; performs no I/O. + */ +public final class IdempotenceWarmUpProvider implements SdkWarmUpProvider { + + private static final AtomicInteger SYNC_WARMS = new AtomicInteger(); + + public static int syncWarmCount() { + return SYNC_WARMS.get(); + } + + @Override + public void warmUp() { + } + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.http.warmup.IdempotenceSyncClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.http.warmup.IdempotenceAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SYNC_WARMS.incrementAndGet(); + } + } +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetrySyncClient.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetrySyncClient.java new file mode 100644 index 000000000000..13f8cea0e151 --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetrySyncClient.java @@ -0,0 +1,24 @@ +/* + * 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.http.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client matching {@link RetryWarmUpProvider#syncClientClassName()}. + */ +public interface RetrySyncClient extends SdkClient { +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetryWarmUpProvider.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetryWarmUpProvider.java new file mode 100644 index 000000000000..2e876c3f7489 --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/RetryWarmUpProvider.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.http.warmup; + +import java.util.concurrent.atomic.AtomicInteger; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Test-only provider whose first {@code warmUpClient(SYNC)} call throws; later calls succeed. + */ +public final class RetryWarmUpProvider implements SdkWarmUpProvider { + + private static final AtomicInteger SYNC_ATTEMPTS = new AtomicInteger(); + private static final AtomicInteger SYNC_SUCCESSES = new AtomicInteger(); + + public static int syncAttemptCount() { + return SYNC_ATTEMPTS.get(); + } + + public static int syncSuccessCount() { + return SYNC_SUCCESSES.get(); + } + + @Override + public void warmUp() { + } + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.http.warmup.RetrySyncClient"; + } + + @Override + public String asyncClientClassName() { + return null; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType != ClientType.SYNC) { + return; + } + if (SYNC_ATTEMPTS.incrementAndGet() == 1) { + throw new RuntimeException("Simulated transient warm-up failure (test)"); + } + SYNC_SUCCESSES.incrementAndGet(); + } +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveAsyncClient.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveAsyncClient.java new file mode 100644 index 000000000000..6890353143a5 --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveAsyncClient.java @@ -0,0 +1,25 @@ +/* + * 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.http.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client matching {@link SelectiveWarmUpProvider#asyncClientClassName()}, warmed only by + * {@link SdkWarmUpSelectiveTest}. + */ +public interface SelectiveAsyncClient extends SdkClient { +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveSyncClient.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveSyncClient.java new file mode 100644 index 000000000000..5ae8ec289314 --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveSyncClient.java @@ -0,0 +1,25 @@ +/* + * 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.http.warmup; + +import software.amazon.awssdk.core.SdkClient; + +/** + * Test-only client matching {@link SelectiveWarmUpProvider#syncClientClassName()}, warmed only by + * {@link SdkWarmUpSelectiveTest}. + */ +public interface SelectiveSyncClient extends SdkClient { +} diff --git a/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveWarmUpProvider.java b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveWarmUpProvider.java new file mode 100644 index 000000000000..d8754738255c --- /dev/null +++ b/test/warmup-tests/src/main/java/software/amazon/awssdk/http/warmup/SelectiveWarmUpProvider.java @@ -0,0 +1,61 @@ +/* + * 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.http.warmup; + +import java.util.concurrent.atomic.AtomicInteger; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; + +/** + * Test-only {@link SdkWarmUpProvider} for {@link SdkWarmUpSelectiveTest}. Matches {@link SelectiveSyncClient} and + * {@link SelectiveAsyncClient} and counts warms per client type; performs no I/O. + */ +public final class SelectiveWarmUpProvider implements SdkWarmUpProvider { + + private static final AtomicInteger SYNC_WARMS = new AtomicInteger(); + private static final AtomicInteger ASYNC_WARMS = new AtomicInteger(); + + public static int syncWarmCount() { + return SYNC_WARMS.get(); + } + + public static int asyncWarmCount() { + return ASYNC_WARMS.get(); + } + + @Override + public void warmUp() { + } + + @Override + public String syncClientClassName() { + return "software.amazon.awssdk.http.warmup.SelectiveSyncClient"; + } + + @Override + public String asyncClientClassName() { + return "software.amazon.awssdk.http.warmup.SelectiveAsyncClient"; + } + + @Override + public void warmUpClient(ClientType clientType) { + if (clientType == ClientType.SYNC) { + SYNC_WARMS.incrementAndGet(); + } else if (clientType == ClientType.ASYNC) { + ASYNC_WARMS.incrementAndGet(); + } + } +} diff --git a/test/warmup-tests/src/main/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider b/test/warmup-tests/src/main/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider new file mode 100644 index 000000000000..3e6b812379bc --- /dev/null +++ b/test/warmup-tests/src/main/resources/META-INF/services/software.amazon.awssdk.core.warmup.SdkWarmUpProvider @@ -0,0 +1,3 @@ +software.amazon.awssdk.http.warmup.IdempotenceWarmUpProvider +software.amazon.awssdk.http.warmup.SelectiveWarmUpProvider +software.amazon.awssdk.http.warmup.RetryWarmUpProvider diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/AsyncHttpClientWarmUpTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/AsyncHttpClientWarmUpTest.java new file mode 100644 index 000000000000..b23c00dbfb9a --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/AsyncHttpClientWarmUpTest.java @@ -0,0 +1,110 @@ +/* + * 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.http.warmup; + +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.anyRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.net.URI; +import java.util.ServiceLoader; +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 software.amazon.awssdk.core.internal.http.loader.AsyncHttpClientWarmer; +import software.amazon.awssdk.http.async.SdkAsyncHttpService; +import software.amazon.awssdk.http.crt.AwsCrtSdkHttpService; +import software.amazon.awssdk.http.nio.netty.NettySdkAsyncHttpService; + +/** + * Verifies the CRaC async warm-up sends its GET through each real async HTTP client. Every async client is exercised here, in + * one place, instead of a separate test in each client module. The stub mirrors a real STS {@code GET} (302 redirect, empty + * body); the warm-up must not follow the redirect, so exactly one request is expected. + */ +class AsyncHttpClientWarmUpTest { + + // Minimum async HTTP clients expected on this module's classpath: netty-nio, aws-crt async. Used as a floor so a broken + // ServiceLoader that discovers nothing fails the test instead of passing a trivial verify(0). + private static final int MIN_ASYNC_CLIENT_COUNT = 2; + + private WireMockServer mockServer; + + static SdkAsyncHttpService[] asyncClients() { + return new SdkAsyncHttpService[] { + new NettySdkAsyncHttpService(), + new AwsCrtSdkHttpService() + }; + } + + @BeforeEach + void setUp() { + mockServer = new WireMockServer(WireMockConfiguration.options().dynamicPort()); + mockServer.start(); + } + + @AfterEach + void tearDown() { + mockServer.stop(); + } + + @ParameterizedTest + @MethodSource("asyncClients") + void warmAll_sendsWarmUpGetThroughClient(SdkAsyncHttpService service) { + mockServer.stubFor(any(anyUrl()).willReturn(aResponse() + .withStatus(302) + .withHeader("Location", "https://aws.amazon.com/iam"))); + + URI endpoint = URI.create("http://localhost:" + mockServer.port() + "/"); + AsyncHttpClientWarmer.forService(() -> endpoint, service).warmAll(); + + mockServer.verify(1, getRequestedFor(urlPathEqualTo("/"))); + mockServer.verify(1, anyRequestedFor(anyUrl())); + } + + /** + * Exercises the real classpath-discovery path used by {@code warmUp()}: {@code warmAll()} discovers every async + * {@link SdkAsyncHttpService} on the classpath via {@link ServiceLoader} and warms each. Confirms discovery finds all + * {@value #MIN_ASYNC_CLIENT_COUNT} clients and that each receives exactly one warm-up GET. + */ + @Test + void warmAll_whenDiscoveringFromClasspath_warmsEveryAsyncClient() { + mockServer.stubFor(any(anyUrl()).willReturn(aResponse() + .withStatus(302) + .withHeader("Location", "https://aws.amazon.com/iam"))); + + int discoveredClients = 0; + for (SdkAsyncHttpService ignored : ServiceLoader.load(SdkAsyncHttpService.class)) { + discoveredClients++; + } + // Fail if discovery finds fewer clients than expected (e.g. a broken ServiceLoader finding none). + assertThat(discoveredClients).isGreaterThanOrEqualTo(MIN_ASYNC_CLIENT_COUNT); + + URI endpoint = URI.create("http://localhost:" + mockServer.port() + "/"); + AsyncHttpClientWarmer.create(() -> endpoint).warmAll(); + + // Verify against the actual discovered count, not the constant, so this stays correct as clients are added. + mockServer.verify(discoveredClients, getRequestedFor(urlPathEqualTo("/"))); + mockServer.verify(discoveredClients, anyRequestedFor(anyUrl())); + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpIdempotenceTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpIdempotenceTest.java new file mode 100644 index 000000000000..a9da1682745d --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpIdempotenceTest.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.http.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.warmup.SdkWarmUp; + +/** + * Verifies {@link SdkWarmUp#warmUp(Class...)} warms a client at most once per JVM. Uses a dedicated + * {@link IdempotenceSyncClient} that no other test warms, so the "first warms, repeat no-ops" transition is observable + * regardless of execution order or JVM sharing. + */ +class SdkWarmUpIdempotenceTest { + + private String savedRegionProperty; + + @BeforeEach + void setUp() { + savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "warmup-idempotence-test"); + } + + @AfterEach + void tearDown() { + if (savedRegionProperty != null) { + System.setProperty("aws.region", savedRegionProperty); + } else { + System.clearProperty("aws.region"); + } + } + + @Test + void warmUp_sameClientTwice_warmsProviderExactlyOnce() { + SdkWarmUp.warmUp(IdempotenceSyncClient.class); + assertThat(IdempotenceWarmUpProvider.syncWarmCount()) + .as("first warm-up warms the sync client type once") + .isEqualTo(1); + + // Second call for the same client must be a no-op: it is already recorded as warmed. + SdkWarmUp.warmUp(IdempotenceSyncClient.class); + assertThat(IdempotenceWarmUpProvider.syncWarmCount()) + .as("second warm-up of the same client does not warm again") + .isEqualTo(1); + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpRetryTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpRetryTest.java new file mode 100644 index 000000000000..b76b4250ccf6 --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpRetryTest.java @@ -0,0 +1,64 @@ +/* + * 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.http.warmup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.warmup.SdkWarmUp; + +/** + * Verifies a failed {@link SdkWarmUp#warmUp(Class...)} warm-up is retried on the next call. + */ +class SdkWarmUpRetryTest { + + private String savedRegionProperty; + + @BeforeEach + void setUp() { + savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "warmup-retry-test"); + } + + @AfterEach + void tearDown() { + if (savedRegionProperty != null) { + System.setProperty("aws.region", savedRegionProperty); + } else { + System.clearProperty("aws.region"); + } + } + + @Test + void warmUp_afterWarmUpFailure_retriesOnNextCallThenStops() { + // First call: the provider throws, so the client is not recorded as warmed. + assertThatCode(() -> SdkWarmUp.warmUp(RetrySyncClient.class)).doesNotThrowAnyException(); + assertThat(RetryWarmUpProvider.syncAttemptCount()).as("first call attempts the warm").isEqualTo(1); + assertThat(RetryWarmUpProvider.syncSuccessCount()).as("first call fails").isEqualTo(0); + + // Second call: retried; this time it succeeds. + SdkWarmUp.warmUp(RetrySyncClient.class); + assertThat(RetryWarmUpProvider.syncAttemptCount()).as("failure is retried").isEqualTo(2); + assertThat(RetryWarmUpProvider.syncSuccessCount()).as("retry succeeds").isEqualTo(1); + + // Third call: already warmed, no further attempt. + SdkWarmUp.warmUp(RetrySyncClient.class); + assertThat(RetryWarmUpProvider.syncAttemptCount()).as("successful warm is not repeated").isEqualTo(2); + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpSelectiveTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpSelectiveTest.java new file mode 100644 index 000000000000..85f7ecfc0223 --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpSelectiveTest.java @@ -0,0 +1,65 @@ +/* + * 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.http.warmup; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.warmup.SdkWarmUp; + +/** + * Verifies that when {@link SdkWarmUp#warmUp(Class...)} is called with a batch mixing an already-warmed client and a new + * one, only the new client is warmed. Uses dedicated clients that no other test warms. + */ +class SdkWarmUpSelectiveTest { + + private String savedRegionProperty; + + @BeforeEach + void setUp() { + savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "warmup-selective-test"); + } + + @AfterEach + void tearDown() { + if (savedRegionProperty != null) { + System.setProperty("aws.region", savedRegionProperty); + } else { + System.clearProperty("aws.region"); + } + } + + @Test + void warmUp_previouslyWarmedClientInNewBatch_warmsOnlyTheNewClient() { + // Warm up the sync client first. + SdkWarmUp.warmUp(SelectiveSyncClient.class); + assertThat(SelectiveWarmUpProvider.syncWarmCount()).isEqualTo(1); + assertThat(SelectiveWarmUpProvider.asyncWarmCount()).isEqualTo(0); + + // Now warm up a batch containing the already-warmed sync client plus a new async client. + SdkWarmUp.warmUp(SelectiveSyncClient.class, SelectiveAsyncClient.class); + + assertThat(SelectiveWarmUpProvider.syncWarmCount()) + .as("already-warmed sync client is not warmed again") + .isEqualTo(1); + assertThat(SelectiveWarmUpProvider.asyncWarmCount()) + .as("the new async client is warmed once") + .isEqualTo(1); + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpTargetedTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpTargetedTest.java new file mode 100644 index 000000000000..f5f87dd0fdc9 --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SdkWarmUpTargetedTest.java @@ -0,0 +1,196 @@ +/* + * 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.http.warmup; + +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.anyRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.ServiceLoader; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +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.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.core.warmup.SdkWarmUp; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.sts.StsAsyncClient; +import software.amazon.awssdk.services.sts.StsClient; + +/** + * End-to-end integration test of {@link SdkWarmUp#warmUp(Class...)} with real service clients (STS, DynamoDB) whose + * generated {@link SdkWarmUpProvider} implementations are on the classpath via ServiceLoader. + */ +class SdkWarmUpTargetedTest { + + private WireMockServer mockServer; + private String savedRegionProperty; + + @BeforeEach + void setUp() { + mockServer = new WireMockServer(WireMockConfiguration.options().dynamicPort()); + mockServer.start(); + mockServer.stubFor(any(anyUrl()).willReturn(aResponse() + .withStatus(302) + .withHeader("Location", "https://aws.amazon.com/iam"))); + + savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "warmup-integration-test"); + } + + @AfterEach + void tearDown() { + mockServer.stop(); + if (savedRegionProperty != null) { + System.setProperty("aws.region", savedRegionProperty); + } else { + System.clearProperty("aws.region"); + } + } + + /** + * Sanity check: ServiceLoader must discover at least the STS and DynamoDB providers we depend on. + */ + @Test + void serviceLoader_discoversExpectedProviders() { + int count = 0; + for (SdkWarmUpProvider ignored : ServiceLoader.load(SdkWarmUpProvider.class)) { + count++; + } + // STS has 1 provider, DynamoDB has 2 (DynamoDb + DynamoDbStreams). + assertThat(count).isGreaterThanOrEqualTo(3); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("singleClientCases") + void warmUp_withSingleClient_completesWithoutError(String description, Class client) { + assertThatCode(() -> SdkWarmUp.warmUp(client)).doesNotThrowAnyException(); + } + + private static Stream singleClientCases() { + return Stream.of( + arguments("STS sync", StsClient.class), + arguments("STS async", StsAsyncClient.class), + arguments("DynamoDB sync", DynamoDbClient.class), + arguments("DynamoDB async", DynamoDbAsyncClient.class) + ); + } + + @Test + void warmUp_withMultipleServices_completesWithoutError() { + assertThatCode(() -> SdkWarmUp.warmUp(StsClient.class, DynamoDbClient.class, StsAsyncClient.class)) + .doesNotThrowAnyException(); + } + + @Test + void warmUp_calledTwiceWithSameClient_isIdempotent() { + SdkWarmUp.warmUp(StsClient.class); + + // Second call should be a no-op (client already recorded as warmed). + assertThatCode(() -> SdkWarmUp.warmUp(StsClient.class)).doesNotThrowAnyException(); + } + + @Test + void warmUp_calledWithNewClientAfterPrevious_warmsOnlyNewClient() { + SdkWarmUp.warmUp(StsClient.class); + + // DynamoDB is new; STS should not be re-warmed. + assertThatCode(() -> SdkWarmUp.warmUp(DynamoDbClient.class, StsClient.class)).doesNotThrowAnyException(); + } + + @Test + void warmUp_concurrentCalls_allCompleteSuccessfully() throws InterruptedException { + int threadCount = 8; + CountDownLatch start = new CountDownLatch(1); + CountDownLatch done = new CountDownLatch(threadCount); + List threads = new ArrayList<>(); + List failures = Collections.synchronizedList(new ArrayList<>()); + AtomicInteger completed = new AtomicInteger(); + + Class[] clients = {StsClient.class, StsAsyncClient.class, DynamoDbClient.class, DynamoDbAsyncClient.class}; + for (int i = 0; i < threadCount; i++) { + @SuppressWarnings("unchecked") + Class client = (Class) clients[i % clients.length]; + Thread thread = new Thread(() -> { + try { + start.await(); + SdkWarmUp.warmUp(client); + completed.incrementAndGet(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Throwable t) { + failures.add(t); + } finally { + done.countDown(); + } + }); + threads.add(thread); + thread.start(); + } + + start.countDown(); + done.await(); + for (Thread thread : threads) { + thread.join(); + } + + assertThat(failures).as("no warmUp(Class...) call threw").isEmpty(); + assertThat(completed.get()).as("every warmUp(Class...) call completed").isEqualTo(threadCount); + } + + @Test + void warmUp_withUnmatchedClient_isNoOpAndSendsNoRequest() { + mockServer.stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200))); + + assertThatCode(() -> SdkWarmUp.warmUp(UnregisteredClient.class)).doesNotThrowAnyException(); + + // No provider matches, so no HTTP warmer runs and nothing hits the mock server. + mockServer.verify(0, anyRequestedFor(anyUrl())); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("noOpInputCases") + void warmUp_withNoOpInput_doesNotThrow(String description, Class[] clients) { + assertThatCode(() -> SdkWarmUp.warmUp(clients)).doesNotThrowAnyException(); + } + + private static Stream noOpInputCases() { + return Stream.of( + arguments("null array", (Class[]) null), + arguments("empty array", new Class[0]) + ); + } + + interface UnregisteredClient extends SdkClient { + } +} + diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SyncHttpClientWarmUpTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SyncHttpClientWarmUpTest.java new file mode 100644 index 000000000000..695993240606 --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/http/warmup/SyncHttpClientWarmUpTest.java @@ -0,0 +1,113 @@ +/* + * 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.http.warmup; + +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.anyRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import java.net.URI; +import java.util.ServiceLoader; +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 software.amazon.awssdk.core.internal.http.loader.SyncHttpClientWarmer; +import software.amazon.awssdk.http.SdkHttpService; +import software.amazon.awssdk.http.apache.ApacheSdkHttpService; +import software.amazon.awssdk.http.apache5.Apache5SdkHttpService; +import software.amazon.awssdk.http.crt.AwsCrtSdkHttpService; +import software.amazon.awssdk.http.urlconnection.UrlConnectionSdkHttpService; + +/** + * Verifies the CRaC sync warm-up sends its GET through each real sync HTTP client. Every client is exercised here, in one + * place, instead of a separate test in each client module. The stub mirrors a real STS {@code GET} (302 redirect, empty + * body); the warm-up must not follow the redirect, so exactly one request is expected. + */ +class SyncHttpClientWarmUpTest { + + // The sync HTTP clients on this module's classpath: apache, apache5, aws-crt, url-connection. Hardcoded so a broken + // ServiceLoader that discovers nothing fails the test instead of passing a trivial verify(0). + private static final int SYNC_CLIENT_COUNT = 4; + + private WireMockServer mockServer; + + static SdkHttpService[] syncClients() { + return new SdkHttpService[] { + new Apache5SdkHttpService(), + new ApacheSdkHttpService(), + new AwsCrtSdkHttpService(), + new UrlConnectionSdkHttpService() + }; + } + + @BeforeEach + void setUp() { + mockServer = new WireMockServer(WireMockConfiguration.options().dynamicPort()); + mockServer.start(); + } + + @AfterEach + void tearDown() { + mockServer.stop(); + } + + @ParameterizedTest + @MethodSource("syncClients") + void warmAll_sendsWarmUpGetThroughClient(SdkHttpService service) { + mockServer.stubFor(any(anyUrl()).willReturn(aResponse() + .withStatus(302) + .withHeader("Location", "https://aws.amazon.com/iam"))); + + URI endpoint = URI.create("http://localhost:" + mockServer.port() + "/"); + SyncHttpClientWarmer.forService(() -> endpoint, service).warmAll(); + + mockServer.verify(1, getRequestedFor(urlPathEqualTo("/"))); + mockServer.verify(1, anyRequestedFor(anyUrl())); + } + + /** + * Exercises the real classpath-discovery path used by {@code warmUp()}: {@code warmAll()} discovers every sync + * {@link SdkHttpService} on the classpath via {@link ServiceLoader} and warms each. Confirms discovery finds all + * {@value #SYNC_CLIENT_COUNT} clients and that each receives exactly one warm-up GET. + */ + @Test + void warmAll_whenDiscoveringFromClasspath_warmsEverySyncClient() { + mockServer.stubFor(any(anyUrl()).willReturn(aResponse() + .withStatus(302) + .withHeader("Location", "https://aws.amazon.com/iam"))); + + int discoveredClients = 0; + for (SdkHttpService ignored : ServiceLoader.load(SdkHttpService.class)) { + discoveredClients++; + } + // Guard against a broken ServiceLoader: if discovery silently finds 0, verify(0) below would pass trivially. + assertThat(discoveredClients).isEqualTo(SYNC_CLIENT_COUNT); + + URI endpoint = URI.create("http://localhost:" + mockServer.port() + "/"); + SyncHttpClientWarmer.create(() -> endpoint).warmAll(); + + mockServer.verify(SYNC_CLIENT_COUNT, getRequestedFor(urlPathEqualTo("/"))); + mockServer.verify(SYNC_CLIENT_COUNT, anyRequestedFor(anyUrl())); + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/AllServicesWarmUpTest.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/AllServicesWarmUpTest.java new file mode 100644 index 000000000000..46a629bbadda --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/AllServicesWarmUpTest.java @@ -0,0 +1,206 @@ +/* + * 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.warmup.allservices; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; +import org.apache.logging.log4j.Level; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Named; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.SdkClient; +import software.amazon.awssdk.core.warmup.SdkWarmUp; +import software.amazon.awssdk.core.warmup.SdkWarmUpProvider; +import software.amazon.awssdk.testutils.LogCaptor; +import software.amazon.awssdk.utils.ClassLoaderHelper; + +/** + * Warms every service on the classpath through the public API: {@link SdkWarmUp#warmUp(Class[])} per generated + * client, and {@link SdkWarmUp#warmUp()} for all of them at once. + */ +class AllServicesWarmUpTest { + + private static final String SERVICES_PACKAGE_PREFIX = "software.amazon.awssdk.services."; + + /** + * Services with no selectable warm-up operation (all operations are streaming or deprecated); warm-up only + * builds and closes the client. + */ + private static final Set KNOWN_NO_OP_SERVICES = new HashSet<>(Arrays.asList( + // All APIs are deprecated + "cloudhsm", + "finspacedata", + "iotthingsgraph", + "lexmodelbuilding", + "proton", + + // All streaming operations + "kinesisvideomedia", + "sagemakerruntimehttp2")); + + /** + * Known warm-up failures. Document the reason per entry. + */ + private static final Set KNOWN_WARMUP_FAILURE_SERVICES = new HashSet<>(Collections.singletonList( + // Endpoint rules require a real CloudFront ARN; the generated dummy ARN is rejected. + "cloudfrontkeyvaluestore")); + + @BeforeEach + void setUp() { + OperationRecordingInterceptor.reset(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("generatedProviders") + void warmUp_syncClient_invokesOperationWithoutErrors(SdkWarmUpProvider provider) { + verifyWarmUp(provider, provider.syncClientClassName()); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("generatedProviders") + void warmUp_asyncClient_invokesOperationWithoutErrors(SdkWarmUpProvider provider) { + verifyWarmUp(provider, provider.asyncClientClassName()); + } + + @Test + void warmUp_withAllServicesOnClasspath_noServiceProviderFails() { + String savedRegionProperty = System.getProperty("aws.region"); + System.setProperty("aws.region", "us-east-1"); + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + SdkWarmUp.warmUp(); + + assertThat(serviceWarmUpFailures(logCaptor)) + .as("SdkWarmUp.warmUp() must not log a warm-up failure for any generated service provider") + .isEmpty(); + } finally { + restoreRegionProperty(savedRegionProperty); + } + + // warmUp() runs once per JVM; an empty recording means it already ran and this test verified nothing. + assertThat(OperationRecordingInterceptor.operationNames()) + .as("warmUp() must have invoked warm-up operations") + .isNotEmpty(); + } + + private void verifyWarmUp(SdkWarmUpProvider provider, String clientClassName) { + assumeTrue(clientClassName != null, + () -> provider.getClass().getSimpleName() + " does not generate this client type"); + assumeTrue(!KNOWN_WARMUP_FAILURE_SERVICES.contains(serviceName(provider)), + () -> provider.getClass().getSimpleName() + + " is a known warm-up failure; see KNOWN_WARMUP_FAILURE_SERVICES"); + + List sdkWarnings; + try (LogCaptor logCaptor = LogCaptor.create(Level.WARN)) { + SdkWarmUp.warmUp(clientClass(clientClassName)); + sdkWarnings = sdkWarnings(logCaptor); + } + + // warmUp(Class) logs warm-up failures at WARN instead of throwing. + assertThat(sdkWarnings) + .as("Warm-up of %s must not emit SDK warn/error logs", clientClassName) + .isEmpty(); + assertExpectedOperationRecorded(provider, clientClassName); + } + + private void assertExpectedOperationRecorded(SdkWarmUpProvider provider, String clientClassName) { + if (KNOWN_NO_OP_SERVICES.contains(serviceName(provider))) { + assertThat(OperationRecordingInterceptor.operationNames()) + .as("%s is listed in KNOWN_NO_OP_SERVICES but recorded an operation; remove the stale entry", + provider.getClass().getSimpleName()) + .isEmpty(); + } else { + assertThat(OperationRecordingInterceptor.operationNames()) + .as("Warm-up of %s must invoke its selected warm-up operation", clientClassName) + .isNotEmpty(); + } + } + + /** + * All generated service providers; excludes this module's hand-written test providers. + */ + static Stream> generatedProviders() { + return serviceProviders().map(p -> Named.of(p.getClass().getSimpleName(), p)); + } + + private static Stream serviceProviders() { + return StreamSupport.stream(ServiceLoader.load(SdkWarmUpProvider.class).spliterator(), false) + .filter(p -> p.getClass().getName().startsWith(SERVICES_PACKAGE_PREFIX)); + } + + private static String serviceName(SdkWarmUpProvider provider) { + String remainder = provider.getClass().getName().substring(SERVICES_PACKAGE_PREFIX.length()); + return remainder.substring(0, remainder.indexOf('.')); + } + + private static Class clientClass(String clientClassName) { + try { + return ClassLoaderHelper.loadClass(clientClassName, SdkWarmUp.class).asSubclass(SdkClient.class); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Client class not on classpath: " + clientClassName, e); + } + } + + /** + * Captured warnings from SDK loggers; warnings from the rest of the classpath are ignored. + */ + private static List sdkWarnings(LogCaptor logCaptor) { + return logCaptor.loggedEvents().stream() + .filter(e -> e.getLoggerName().startsWith("software.amazon.awssdk")) + .map(e -> e.getLoggerName() + " - " + e.getMessage().getFormattedMessage()) + .collect(Collectors.toList()); + } + + /** + * Warm-up failures logged by {@code warmUp()}, excluding {@link #KNOWN_WARMUP_FAILURE_SERVICES}. warmUp() reports + * failures by client class name, so known failures are matched by their client names. + */ + private static List serviceWarmUpFailures(LogCaptor logCaptor) { + Set knownFailureClients = knownWarmUpFailureClients(); + return logCaptor.loggedEvents().stream() + .map(e -> e.getMessage().getFormattedMessage()) + .filter(msg -> msg.contains("software.amazon")) + .filter(msg -> knownFailureClients.stream().noneMatch(msg::contains)) + .collect(Collectors.toList()); + } + + private static Set knownWarmUpFailureClients() { + return serviceProviders().filter(p -> KNOWN_WARMUP_FAILURE_SERVICES.contains(serviceName(p))) + .flatMap(p -> Stream.of(p.syncClientClassName(), p.asyncClientClassName())) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + + private static void restoreRegionProperty(String savedValue) { + if (savedValue != null) { + System.setProperty("aws.region", savedValue); + } else { + System.clearProperty("aws.region"); + } + } +} diff --git a/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/OperationRecordingInterceptor.java b/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/OperationRecordingInterceptor.java new file mode 100644 index 000000000000..cafc7d836ca8 --- /dev/null +++ b/test/warmup-tests/src/test/java/software/amazon/awssdk/warmup/allservices/OperationRecordingInterceptor.java @@ -0,0 +1,45 @@ +/* + * 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.warmup.allservices; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +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; + +/** + * Records invoked operation names. Registered as a global interceptor via + * {@code software/amazon/awssdk/global/handlers/execution.interceptors} to observe clients built inside providers. + */ +public class OperationRecordingInterceptor implements ExecutionInterceptor { + + private static final List OPERATION_NAMES = new CopyOnWriteArrayList<>(); + + public static List operationNames() { + return OPERATION_NAMES; + } + + public static void reset() { + OPERATION_NAMES.clear(); + } + + @Override + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + OPERATION_NAMES.add(executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME)); + } +} diff --git a/test/warmup-tests/src/test/resources/log4j2.properties b/test/warmup-tests/src/test/resources/log4j2.properties new file mode 100644 index 000000000000..a9839e95d9e0 --- /dev/null +++ b/test/warmup-tests/src/test/resources/log4j2.properties @@ -0,0 +1,26 @@ +# +# 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. +# + +status = warn + +appender.console.type = Console +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 + +# warn keeps CI output manageable while every generated provider warms up; +# LogCaptor adjusts the root level itself when capturing. +rootLogger.level = warn +rootLogger.appenderRef.stdout.ref = ConsoleAppender diff --git a/test/warmup-tests/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/test/warmup-tests/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000000..8ac3e1bf150e --- /dev/null +++ b/test/warmup-tests/src/test/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.awssdk.warmup.allservices.OperationRecordingInterceptor diff --git a/third-party/pom.xml b/third-party/pom.xml index e5b251e495cf..afdc0f9d5a75 100644 --- a/third-party/pom.xml +++ b/third-party/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT third-party diff --git a/third-party/third-party-jackson-core/pom.xml b/third-party/third-party-jackson-core/pom.xml index 60e146903a66..1a49ca4fdde0 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 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 4aefa280fcaf..bd4133909b68 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/third-party/third-party-slf4j-api/pom.xml b/third-party/third-party-slf4j-api/pom.xml index c8cf8b4c817f..60f08de69584 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.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 diff --git a/utils-lite/pom.xml b/utils-lite/pom.xml index 76360c77629e..9fbdd82993db 100644 --- a/utils-lite/pom.xml +++ b/utils-lite/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT utils-lite AWS Java SDK :: Utils Lite diff --git a/utils/pom.xml b/utils/pom.xml index b084a8c89f76..1ea556b85b65 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT 4.0.0 @@ -94,11 +94,6 @@ commons-io test - - org.reactivestreams - reactive-streams-tck - test - org.apache.logging.log4j log4j-api diff --git a/utils/src/main/java/software/amazon/awssdk/utils/ProxyConfigProvider.java b/utils/src/main/java/software/amazon/awssdk/utils/ProxyConfigProvider.java index 127fbe1fb32f..96087b7fc7a5 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/ProxyConfigProvider.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/ProxyConfigProvider.java @@ -122,4 +122,21 @@ static ProxyConfigProvider fromSystemEnvironmentSettings(Boolean useSystemProper * @return A set containing the non-proxy host names. */ Set nonProxyHosts(); + + /** + * Gets the set of non-proxy hosts as raw tokens, i.e. without the {@code * -> .*?} Java-regex rewrite that + * {@link #nonProxyHosts()} applies for system-property and environment-variable sources. Consumers whose matcher expects + * the raw {@code nonProxyHosts} tokens (such as the CRT client's curl-style native matcher) must use this instead of + * {@link #nonProxyHosts()}. + * + *

    The default throws {@link UnsupportedOperationException} rather than falling back to {@link #nonProxyHosts()}: a + * fallback would silently feed Java-regex tokens into a curl-style matcher and reintroduce incorrect proxy bypass. + * Implementations consumed by CRT-based clients must override it. + * + * @return A set containing the raw non-proxy host tokens. + */ + default Set rawNonProxyHosts() { + throw new UnsupportedOperationException("rawNonProxyHosts() must be implemented to supply un-rewritten nonProxyHosts " + + "tokens for curl-style matchers such as the CRT client."); + } } diff --git a/utils/src/main/java/software/amazon/awssdk/utils/async/SimplePublisher.java b/utils/src/main/java/software/amazon/awssdk/utils/async/SimplePublisher.java index e931af7b1c84..15526e19c55d 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/async/SimplePublisher.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/async/SimplePublisher.java @@ -95,8 +95,23 @@ public final class SimplePublisher implements Publisher { */ private final FailureMessage failureMessage = new FailureMessage(); + /** + * Whether {@link #subscribe(Subscriber)} has already been called, used to reject a second subscription. Tracked + * separately from {@link #subscriber} because that field is cleared on termination and must not re-open subscription. + */ + private final AtomicBoolean subscribed = new AtomicBoolean(false); + + /** + * True while the subscriber's {@code onSubscribe} is executing. Used to prevent {@link #processEventQueue()} from + * delivering {@code onNext} signals before {@code onSubscribe} has returned, as required by Reactive Streams rule 1.03. + */ + private volatile boolean onSubscribeInProgress = false; + /** * The subscriber provided via {@link #subscribe(Subscriber)}. This publisher only supports a single subscriber. + * + *

    Cleared when the stream terminates (complete, error, or cancel) so the publisher does not retain the subscriber + * reference, per Reactive Streams rule 3.13. */ private Subscriber subscriber; @@ -196,14 +211,19 @@ public CompletableFuture error(Throwable error) { */ @Override public void subscribe(Subscriber s) { - if (subscriber != null) { + if (!subscribed.compareAndSet(false, true)) { s.onSubscribe(new NoOpSubscription()); s.onError(new IllegalStateException("Only one subscription may be active at a time.")); return; } this.subscriber = s; - s.onSubscribe(new SubscriptionImpl()); + onSubscribeInProgress = true; + try { + s.onSubscribe(new SubscriptionImpl()); + } finally { + onSubscribeInProgress = false; + } processEventQueue(); } @@ -275,6 +295,7 @@ private void doProcessQueue() { log.trace(() -> "Calling onComplete()"); subscriber.onComplete(); + subscriber = null; break; case ON_ERROR: @@ -283,9 +304,11 @@ private void doProcessQueue() { onErrorEntry.failure)); log.trace(() -> "Calling onError() with " + onErrorEntry.failure, onErrorEntry.failure); subscriber.onError(onErrorEntry.failure); + subscriber = null; break; case CANCEL: failureMessage.trySet(() -> new CancellationException("subscription has been cancelled.")); + subscriber = null; break; default: // Should never happen. Famous last words? @@ -317,6 +340,11 @@ private boolean shouldProcessQueueEntry(QueueEntry entry) { return false; } + if (onSubscribeInProgress) { + // Do not deliver signals until onSubscribe has returned (Reactive Streams rule 1.03). + return false; + } + if (entry.type() != ON_NEXT) { // This event isn't an on-next event, so we don't need subscriber demand in order to process it. return true; @@ -338,7 +366,10 @@ private void panicAndDie(Throwable cause) { // Create exception here instead of in supplier to preserve a more-useful stack trace. RuntimeException failure = new IllegalStateException("Encountered fatal error in publisher", cause); failureMessage.trySet(() -> failure); - subscriber.onError(cause instanceof Error ? cause : failure); + if (subscriber != null) { + subscriber.onError(cause instanceof Error ? cause : failure); + subscriber = null; + } while (true) { QueueEntry entry = standardPriorityQueue.poll(); diff --git a/utils/src/main/java/software/amazon/awssdk/utils/cache/lru/LruCache.java b/utils/src/main/java/software/amazon/awssdk/utils/cache/lru/LruCache.java index df7bc222d261..eff5892b01ab 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/cache/lru/LruCache.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/cache/lru/LruCache.java @@ -15,6 +15,8 @@ package software.amazon.awssdk.utils.cache.lru; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -77,6 +79,20 @@ public V get(K key) { } } + public List evictAll() { + List evicted = new ArrayList<>(cache.size()); + synchronized (listLock) { + while (true) { + CacheEntry evictedEntry = evict(); + if (evictedEntry == null) { + break; + } + evicted.add(evictedEntry.value); + } + return evicted; + } + } + private CacheEntry newEntry(K key) { V value = valueSupplier.apply(key); return new CacheEntry<>(key, value); @@ -147,11 +163,18 @@ private void addToQueue(CacheEntry entry) { /** * Removes the least recently used entry from the cache, marks it as evicted and removes it from the queue. */ - private void evict() { - leastRecentlyUsed.isEvicted(true); - closeEvictedResourcesIfPossible(leastRecentlyUsed.value); - cache.remove(leastRecentlyUsed.key()); - removeFromQueue(leastRecentlyUsed); + private CacheEntry evict() { + if (leastRecentlyUsed == null) { + return null; + } + + CacheEntry entryToEvict = leastRecentlyUsed; + + entryToEvict.isEvicted(true); + closeEvictedResourcesIfPossible(entryToEvict.value); + cache.remove(entryToEvict.key()); + removeFromQueue(entryToEvict); + return entryToEvict; } private void closeEvictedResourcesIfPossible(V value) { diff --git a/utils/src/main/java/software/amazon/awssdk/utils/http/SdkHttpUtils.java b/utils/src/main/java/software/amazon/awssdk/utils/http/SdkHttpUtils.java index 02a402d0db4d..487610762340 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/http/SdkHttpUtils.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/http/SdkHttpUtils.java @@ -438,6 +438,7 @@ public static Set parseNonProxyHostsProperty() { private static Set extractNonProxyHosts(String nonProxyHosts) { if (nonProxyHosts != null && !isEmpty(nonProxyHosts)) { return Arrays.stream(nonProxyHosts.split("\\|")) + .map(String::trim) .map(String::toLowerCase) .map(s -> StringUtils.replace(s, "*", ".*?")) .collect(Collectors.toSet()); diff --git a/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyEnvironmentVariableConfigProvider.java b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyEnvironmentVariableConfigProvider.java index 084b08f1ef02..b7037a102f10 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyEnvironmentVariableConfigProvider.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyEnvironmentVariableConfigProvider.java @@ -96,4 +96,12 @@ public String host() { public Set nonProxyHosts() { return parseNonProxyHostsEnvironmentVariable(); } + + @Override + public Set rawNonProxyHosts() { + String hosts = ProxyEnvironmentSetting.NO_PROXY.getStringValue() + .map(noProxyHost -> noProxyHost.replace(",", "|")) + .orElse(null); + return ProxyUtils.splitToGlobTokens(hosts); + } } diff --git a/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxySystemPropertyConfigProvider.java b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxySystemPropertyConfigProvider.java index 0cdb8ad922df..90ac7fe7b60d 100644 --- a/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxySystemPropertyConfigProvider.java +++ b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxySystemPropertyConfigProvider.java @@ -84,4 +84,9 @@ public String host() { public Set nonProxyHosts() { return parseNonProxyHostsProperty(); } + + @Override + public Set rawNonProxyHosts() { + return ProxyUtils.splitToGlobTokens(ProxySystemSetting.NON_PROXY_HOSTS.getStringValue().orElse(null)); + } } diff --git a/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyUtils.java b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyUtils.java new file mode 100644 index 000000000000..fdd709cd243e --- /dev/null +++ b/utils/src/main/java/software/amazon/awssdk/utils/internal/proxy/ProxyUtils.java @@ -0,0 +1,48 @@ +/* + * 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.utils.internal.proxy; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.utils.StringUtils; + +/** + * Splits a pipe-separated {@code nonProxyHosts} string into its trimmed, lowercased tokens WITHOUT the {@code * -> .*?} + * Java-regex rewrite that {@code SdkHttpUtils#parseNonProxyHostsProperty()} applies. Surrounding whitespace is trimmed so the + * common comma-space {@code no_proxy=a.com, *.foo.com} form (which arrives as {@code " *.foo.com"} after the {@code , -> |} + * normalization) is matched correctly. The returned tokens keep their documented forms (exact host, {@code *.suffix}, bare + * {@code *}, CIDR), which is what a curl-style matcher such as the CRT client's native matcher expects. The regex-rewritten + * form remains available via {@code SdkHttpUtils} for the Netty/Apache/url-connection clients. + */ +@SdkInternalApi +final class ProxyUtils { + + private ProxyUtils() { + } + + static Set splitToGlobTokens(String nonProxyHosts) { + if (nonProxyHosts != null && !StringUtils.isEmpty(nonProxyHosts)) { + return Arrays.stream(nonProxyHosts.split("\\|")) + .map(String::trim) + .map(String::toLowerCase) + .collect(Collectors.toSet()); + } + return Collections.emptySet(); + } +} diff --git a/utils/src/test/java/software/amazon/awssdk/utils/SdkHttpUtilsTest.java b/utils/src/test/java/software/amazon/awssdk/utils/SdkHttpUtilsTest.java index c32aa7094917..a7055d65b25e 100644 --- a/utils/src/test/java/software/amazon/awssdk/utils/SdkHttpUtilsTest.java +++ b/utils/src/test/java/software/amazon/awssdk/utils/SdkHttpUtilsTest.java @@ -318,5 +318,35 @@ void parseListOfNonProxyHostWithPipesAndWildCard(){ .collect(Collectors.toSet())); } + @Test + void parseNonProxyHostsProperty_regexPathStillRewritesWildcard() { + String previous = System.getProperty("http.nonProxyHosts"); + System.setProperty("http.nonProxyHosts", "example.com|*greedy.org"); + try { + assertThat(SdkHttpUtils.parseNonProxyHostsProperty()) + .isEqualTo(Stream.of("example.com", ".*?greedy.org").collect(Collectors.toSet())); + } finally { + if (previous == null) { + System.clearProperty("http.nonProxyHosts"); + } else { + System.setProperty("http.nonProxyHosts", previous); + } + } + } + + @Test + void parseListOfNonProxyHostWithCommaSpace_trimsSurroundingWhitespace(){ + String multipleHostNames = "example.com, *greedy.org, 192.168.1.1"; + ENVIRONMENT_VARIABLE_HELPER.set("no_proxy", multipleHostNames); + Set strings = SdkHttpUtils.parseNonProxyHostsEnvironmentVariable(); + assertThat(strings).isEqualTo(Stream.of("example.com", ".*?greedy.org", "192.168.1.1") + .collect(Collectors.toSet())); + } + @Test + void parseNonProxyHostWithSurroundingWhitespace_isTrimmed(){ + ENVIRONMENT_VARIABLE_HELPER.set("no_proxy", " example.com "); + Set strings = SdkHttpUtils.parseNonProxyHostsEnvironmentVariable(); + assertThat(strings).containsExactly("example.com"); + } } diff --git a/utils/src/test/java/software/amazon/awssdk/utils/cache/lru/LruCacheTest.java b/utils/src/test/java/software/amazon/awssdk/utils/cache/lru/LruCacheTest.java index 2ee389b8849a..12b8dc3ef470 100644 --- a/utils/src/test/java/software/amazon/awssdk/utils/cache/lru/LruCacheTest.java +++ b/utils/src/test/java/software/amazon/awssdk/utils/cache/lru/LruCacheTest.java @@ -16,13 +16,16 @@ package software.amazon.awssdk.utils.cache.lru; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -40,6 +43,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import software.amazon.awssdk.utils.SdkAutoCloseable; @ExtendWith(MockitoExtension.class) public class LruCacheTest { @@ -246,6 +250,39 @@ void when_multipleThreadsAreCallingCache_WorksAsExpected(Integer numThreads, } } + @Test + void evictAll_noEntries_returnsEmptyList() { + LruCache cache = simpleCache.get(); + assertThat(cache.evictAll()).isEmpty(); + } + + @Test + void evictAll_maxEntries_returnsAllEntries() { + LruCache cache = simpleCache.get(); + List expected = new ArrayList<>(); + for (int i = 0; i < MAX_SIMPLE_CACHE_SIZE; ++i) { + expected.add(cache.get(i)); + } + assertThat(cache.evictAll()).containsExactlyInAnyOrder(expected.toArray(new String[0])); + } + + @Test + void evictAll_closesEvictedEntries() { + LruCache cache = LruCache. + builder(k -> mock(SdkAutoCloseable.class)) + .maxSize(MAX_SIMPLE_CACHE_SIZE) + .build(); + + for (int i = 0; i < MAX_SIMPLE_CACHE_SIZE; ++i) { + cache.get(i); + } + + List evicted = cache.evictAll(); + + assertThat(evicted).isNotEmpty(); + assertThat(evicted).allSatisfy(e -> verify(e).close()); + } + private static Stream concurrencyTestValues() { // numThreads, numGetsPerThreads, sleepDurationMillis, cacheSize return Stream.of(Arguments.of(1000, 5000, false, 5), diff --git a/utils/src/test/java/software/amazon/awssdk/utils/proxy/ProxyConfigurationTest.java b/utils/src/test/java/software/amazon/awssdk/utils/proxy/ProxyConfigurationTest.java index a960c194691a..dd9cb346d10b 100644 --- a/utils/src/test/java/software/amazon/awssdk/utils/proxy/ProxyConfigurationTest.java +++ b/utils/src/test/java/software/amazon/awssdk/utils/proxy/ProxyConfigurationTest.java @@ -25,8 +25,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.testutils.EnvironmentVariableHelper; import software.amazon.awssdk.utils.ProxyConfigProvider; @@ -209,6 +211,41 @@ void given_LocalSetting_when_httpsProtocol_then_correctProxyConfiguration(List

    raw \"{1}\" (no regex rewrite)") + @CsvSource({ + "*.greedy.org, *.greedy.org", + "'*', '*'", + "greedy*, greedy*", + "192.168.*, 192.168.*", + "Example.COM, example.com" + }) + void rawNonProxyHosts_systemProperty_notRewrittenToRegex(String token, String expected) { + System.setProperty("http.nonProxyHosts", token); + assertThat(ProxyConfigProvider.fromSystemPropertySettings("http").rawNonProxyHosts()) + .containsExactly(expected); + } + + @ParameterizedTest(name = "no_proxy \"{0}\" -> raw \"{1}\" (no regex rewrite)") + @CsvSource({ + "*.greedy.org, *.greedy.org", + "'*', '*'", + "greedy*, greedy*", + "192.168.*, 192.168.*", + "Example.COM, example.com" + }) + void rawNonProxyHosts_environmentVariable_notRewrittenToRegex(String token, String expected) { + ENVIRONMENT_VARIABLE_HELPER.set("no_proxy", token); + assertThat(ProxyConfigProvider.fromEnvironmentSettings("http").rawNonProxyHosts()) + .containsExactly(expected); + } + + @Test + void nonProxyHosts_systemProperty_stillRewritesWildcardToRegex() { + System.setProperty("http.nonProxyHosts", "example.com|*greedy.org"); + assertThat(ProxyConfigProvider.fromSystemPropertySettings("http").nonProxyHosts()) + .containsExactlyInAnyOrder("example.com", ".*?greedy.org"); + } + private static class ExpectedProxySetting { private int port; private String host; diff --git a/v2-migration/pom.xml b/v2-migration/pom.xml index bcf36d8d0eb0..7b40b245dc59 100644 --- a/v2-migration/pom.xml +++ b/v2-migration/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.47.5-SNAPSHOT + 2.55.5-SNAPSHOT ../pom.xml